|
from pwn import * |
|
|
|
context.log_level = 'warning' |
|
def number(x): |
|
return format(x, '01024x').decode('hex')[::-1] |
|
|
|
# WRAPPER |
|
|
|
# mem[k] = key[l].n |
|
def op_getpub(k, l): |
|
return '\x01' + chr(l) + chr(k) |
|
|
|
# mem[k] = v |
|
def op_setmem(k, v): |
|
if type(v) != str: |
|
return '\x07' + chr(k) + number(v) |
|
else: |
|
return '\x07' + chr(k) + v + '\x00' * (512 - len(v)) |
|
|
|
# mem[k3] = mem[k1] + mem[k2] |
|
def op_add(k1, k2, k3): |
|
return '\x08' + chr(k1) + chr(k2) + chr(k3) |
|
|
|
# mem[k3] = mem[k1] - mem[k2] |
|
def op_sub(k1, k2, k3): |
|
return '\x09' + chr(k1) + chr(k2) + chr(k3) |
|
|
|
# mem[k3] = mem[k1] * mem[k2] |
|
def op_mul(k1, k2, k3): |
|
return '\x0a' + chr(k1) + chr(k2) + chr(k3) |
|
|
|
# mem[k3] = mem[k1] * mem[k2] |
|
def op_div(k1, k2, k3): |
|
return '\x0b' + chr(k1) + chr(k2) + chr(k3) |
|
|
|
# mem[k3] = mem[k1] % mem[k2] |
|
def op_mod(k1, k2, k3): |
|
return '\x0c' + chr(k1) + chr(k2) + chr(k3) |
|
|
|
# mem[k4] = mem[k1] ^ mem[k2] % mem[k3] |
|
def op_powmod(k1, k2, k3, k4): |
|
return '\x0d' + chr(k1) + chr(k2) + chr(k3) + chr(k4) |
|
|
|
# print mem[k] |
|
def op_print(k): |
|
return '\x0f' + chr(k) |
|
|
|
def op_exit(): |
|
return 'd' |
|
|
|
LOCAL, CHALL = 0, 1 |
|
r = None |
|
def initiate(env): |
|
global r |
|
if env == LOCAL: |
|
r = process('./a.out') |
|
else: |
|
r = remote('cryptovm.hackable.software', 1337) |
|
r.recvuntil('-mb28 ') |
|
pow_target = r.recvline().strip() |
|
print '-> POW' |
|
r_pow = process(['hashcash', '-mb28', pow_target]) |
|
r_pow.recvuntil('hashcash token: ') |
|
pow_result = r_pow.recvline().strip() |
|
r_pow.close() |
|
|
|
print '-> POW END' |
|
r.sendline(pow_result) |
|
|
|
message = 'Please give me superuser permissions' |
|
|
|
verify_key = 0 |
|
width = 2000 |
|
iteration = 30 |
|
for k in [1, 0, 2]: |
|
for j in range(iteration): |
|
for verify_key in range(1, 8): |
|
payload = '' |
|
|
|
payload += '\x02\x01' |
|
payload += '\x04' + chr(verify_key) |
|
payload += '\x02\x00' |
|
payload += '\x03' + chr(verify_key) |
|
payload += '\x02\x01' # currentKey.n = key[0].n, currentKey.d = key[0].d mod 2**1024 |
|
|
|
payload += op_setmem(15, 65537) # mem[f] = 65537 |
|
payload += op_getpub(14, verify_key) # mem[e] = n |
|
payload += op_setmem(13, 1) # mem[d] = 1 |
|
payload += op_add(13, 14, 12) # mem[c] = n + 1 |
|
payload += op_setmem(11, 2**1024) # mem[b] = 2**1024 |
|
payload += op_setmem(10, message) # mem[a] = message |
|
|
|
payload += '\x05' + message + '\x00' * (256 - len(message)) + '\x09' |
|
# mem[9] = message^d0 mod n |
|
|
|
payload += op_setmem(0, 65537 - j * width) # mem[0] = 65537 - j * width |
|
for i in range(65537 - j * width, 65537 - (j + 1) * width, -1): |
|
payload += op_sub(0, 13, 0) # mem[0] -= 1 |
|
payload += op_mul(0, 12, 1) # mem[1] = k * (n + 1) |
|
payload += op_add(1, 13, 1) # mem[1] = k * (n + 1) + 1 |
|
payload += op_div(1, 15, 1) # mem[1] = [k * (n + 1) + 1] / e = d' |
|
payload += op_mod(1, 11, 2) # mem[2] = d' mod 2**1024 |
|
payload += op_sub(1, 2, 1) # mem[1] = d' - d' mod 2**1024 = d" |
|
payload += op_sub(1, 11, 1) * k |
|
payload += op_powmod(10, 1, 14, 3) # mem[3] = message^d" mod n |
|
payload += op_mul(3, 9, 3) |
|
payload += op_mod(3, 14, 3) # mem[3] = message^d mod n |
|
payload += '\x06' + chr(verify_key) + '\x03' |
|
|
|
payload += '\x00' |
|
payload += op_exit() |
|
|
|
print 'Trial verify_key=%d, k range=%d, delta=%d' % (verify_key, j, k) |
|
initiate(CHALL) |
|
r.send(payload) |
|
r.shutdown('send') |
|
|
|
r.recvline().strip() |
|
r.recvline().strip() |
|
recv = r.recvline().strip() |
|
print recv |
|
assert recv == 'error.' |
|
r.close() |
|
|
|
# verify_key = 7, j = 2, k = 1 |
|
# DrgnS{093e99f356f7f3ba97409e818450606a} |