Forked from disconnect3d/defconquals2017_sorcerery_solve.py
Created
May 3, 2017 14:03
-
-
Save rofl0r/b566a6f5da28f14c736cd594bd51180e to your computer and use it in GitHub Desktop.
Solution for sorcerery crackme2000 task from DefCon Quals CTF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Solution from Disconnect3d [playing in Just Hit the Core] | |
""" | |
import os | |
import angr | |
import pwn | |
import subprocess | |
def crack_bin(binary): | |
p = angr.Project(binary, load_options={'auto_load_libs': False}) | |
cfg_fast = p.analyses.CFG() | |
exit_func = p.kb.functions.function(name='exit') | |
free_func = p.kb.functions.function(name='free') | |
pthread_mutex_unlock_func = p.kb.functions.function(name='pthread_mutex_unlock') | |
malloc_func = p.kb.functions.function(name='malloc') | |
base_addr = 0x400000 | |
start_addr = 0x4036A3 # condition blocks start here | |
# some bss memory region we will use to read the flag(?) content from | |
bss_addr = 0x21BCE8 | |
cmd = 'objdump -Mintel -d {} | grep "mov rax,QWORD PTR \\[rsp+0x8\\]"'.format(binary) | |
tmp = subprocess.check_output(cmd, shell=True) | |
tmp = tmp.strip() | |
tmp = tmp[:tmp.index(':')] | |
win_addr = base_addr + int('0x' + tmp, 16) | |
""" | |
.text:000000000040369F mov rdi, [rsp+0B8h+var_B8] ; ptr | |
START HERE ---> .text:00000000004036A3 mov cl, [rdi] | |
So that we .text:00000000004036A5 cmp cl, 6Eh | |
can set rdi .text:00000000004036A8 jnz loc_4010E6 | |
to any address | |
and read flag(?) | |
value later on | |
""" | |
# creating state that will be used for path exploration/traversal | |
state = p.factory.blank_state(addr=start_addr, add_options={'BYPASS_UNSUPPORTED_SYSCALL'}) | |
# Setting RDI so we will know the address of string in the future | |
state.regs.rdi = bss_addr | |
# creating path group which will start on the given state and will be used for path exploration | |
pg = p.factory.path_group(state) | |
# explore the possibilities! find the win scenario path & state, avoid some stuff... | |
r = pg.explore(find=win_addr, avoid=[exit_func.addr, pthread_mutex_unlock_func]) | |
# previous exploration - it didn't work well for all of the binaries. | |
#r = pg.explore(find=free_func.addr, avoid=exit_func.addr) | |
# take the path that found winning address | |
found = r.found[0] | |
string = found.state.se.any_str(found.state.memory.load(bss_addr, 64)) | |
print "Binary %s = '%s'" % (binary, string) | |
return string | |
data = {} | |
binaries = os.listdir('.') | |
for bin in binaries: | |
print('Analysing %s' % bin) | |
data[bin] = crack_bin(bin) | |
""" | |
# Code below launches binaries with their inputs to get outputs, not really needed. | |
def out(binary, stdin): | |
p = pwn.process(binary) | |
p.sendline(stdin) | |
r = p.recvall() | |
print r | |
return r | |
# | |
# a = [] | |
# for k, v in data.items(): | |
# a.append(out(k, v)) | |
""" | |
k = pwn.remote('cm2k-sorcery_13de8e6bf26e435fc43efaf46b488eae.quals.shallweplayaga.me', 12002) | |
k.recvuntil('followed by a newline\n') | |
while True: | |
binary = k.recvuntil('\n')[:-1] | |
print('GOT: %s' % binary) | |
d = data[binary] | |
print('SENDING: %s' % d) | |
k.sendline(pwn.b64e(d)) | |
k.interactive() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment