Created
September 6, 2016 01:25
-
-
Save hugsy/edb4bbbb63fde3a2a49ec52845b372c4 to your computer and use it in GitHub Desktop.
TWCTF 2016 - reverse_box
This file contains 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
#!/usr/bin/python | |
# | |
# @_hugsy_ | |
# | |
# $ python /tmp/uni.py | |
# >>> init randint is d6 | |
# The flag is TWCTF{5UBS717U710N_C1PH3R_W17H_R4ND0M123D_5-B0X} | |
# | |
import unicorn | |
def emulate(eax): | |
emu = unicorn.Uc(unicorn.UC_ARCH_X86, unicorn.UC_MODE_32 + unicorn.UC_MODE_LITTLE_ENDIAN) | |
emu.reg_write(unicorn.x86_const.UC_X86_REG_EAX, eax) | |
emu.reg_write(unicorn.x86_const.UC_X86_REG_EBX, 0x0) | |
emu.reg_write(unicorn.x86_const.UC_X86_REG_ECX, 0x14d4e658) | |
emu.reg_write(unicorn.x86_const.UC_X86_REG_EDX, 0xf7fa63e4) | |
emu.reg_write(unicorn.x86_const.UC_X86_REG_ESP, 0xffffd220) | |
emu.reg_write(unicorn.x86_const.UC_X86_REG_EBP, 0xffffd248) | |
emu.reg_write(unicorn.x86_const.UC_X86_REG_ESI, 0xf7fa6000) | |
emu.reg_write(unicorn.x86_const.UC_X86_REG_EDI, 0xf7fa6000) | |
emu.reg_write(unicorn.x86_const.UC_X86_REG_EIP, 0x80485b1) | |
emu.reg_write(unicorn.x86_const.UC_X86_REG_EFLAGS, 0x202) | |
emu.mem_map(0x0, 4096, 3) | |
emu.mem_map(0x1000, 4096, 3) | |
emu.mem_map(0x8048000, 4096, 5) | |
# Importing /home/hugsy/ctf/tokyo_western_ctf_2016/reverse_box: 0x8048000-0x8049000 | |
data=open('/tmp/gef-0x8048000.raw', 'r').read() | |
emu.mem_write(0x8048000, data) | |
emu.mem_map(0x8049000, 4096, 1) | |
# Importing /home/hugsy/ctf/tokyo_western_ctf_2016/reverse_box: 0x8049000-0x804a000 | |
data=open('/tmp/gef-0x8049000.raw', 'r').read() | |
emu.mem_write(0x8049000, data) | |
emu.mem_map(0x804a000, 4096, 3) | |
# Importing /home/hugsy/ctf/tokyo_western_ctf_2016/reverse_box: 0x804a000-0x804b000 | |
data=open('/tmp/gef-0x804a000.raw', 'r').read() | |
emu.mem_write(0x804a000, data) | |
emu.mem_map(0xf7df7000, 1757184, 5) | |
# Importing /lib/i386-linux-gnu/libc-2.23.so: 0xf7df7000-0xf7fa4000 | |
data=open('/tmp/gef-0xf7df7000.raw', 'r').read() | |
emu.mem_write(0xf7df7000, data) | |
emu.mem_map(0xf7fa4000, 8192, 1) | |
# Importing /lib/i386-linux-gnu/libc-2.23.so: 0xf7fa4000-0xf7fa6000 | |
data=open('/tmp/gef-0xf7fa4000.raw', 'r').read() | |
emu.mem_write(0xf7fa4000, data) | |
emu.mem_map(0xf7fa6000, 4096, 3) | |
# Importing /lib/i386-linux-gnu/libc-2.23.so: 0xf7fa6000-0xf7fa7000 | |
data=open('/tmp/gef-0xf7fa6000.raw', 'r').read() | |
emu.mem_write(0xf7fa6000, data) | |
emu.mem_map(0xf7fa7000, 12288, 3) | |
# Importing : 0xf7fa7000-0xf7faa000 | |
data=open('/tmp/gef-0xf7fa7000.raw', 'r').read() | |
emu.mem_write(0xf7fa7000, data) | |
emu.mem_map(0xf7fd2000, 8192, 3) | |
# Importing : 0xf7fd2000-0xf7fd4000 | |
data=open('/tmp/gef-0xf7fd2000.raw', 'r').read() | |
emu.mem_write(0xf7fd2000, data) | |
emu.mem_map(0xf7fd4000, 12288, 1) | |
emu.mem_map(0xf7fd7000, 8192, 5) | |
# Importing [vdso]: 0xf7fd7000-0xf7fd9000 | |
data=open('/tmp/gef-0xf7fd7000.raw', 'r').read() | |
emu.mem_write(0xf7fd7000, data) | |
emu.mem_map(0xf7fd9000, 139264, 5) | |
# Importing /lib/i386-linux-gnu/ld-2.23.so: 0xf7fd9000-0xf7ffb000 | |
data=open('/tmp/gef-0xf7fd9000.raw', 'r').read() | |
emu.mem_write(0xf7fd9000, data) | |
emu.mem_map(0xf7ffb000, 4096, 3) | |
# Importing : 0xf7ffb000-0xf7ffc000 | |
data=open('/tmp/gef-0xf7ffb000.raw', 'r').read() | |
emu.mem_write(0xf7ffb000, data) | |
emu.mem_map(0xf7ffc000, 4096, 1) | |
# Importing /lib/i386-linux-gnu/ld-2.23.so: 0xf7ffc000-0xf7ffd000 | |
data=open('/tmp/gef-0xf7ffc000.raw', 'r').read() | |
emu.mem_write(0xf7ffc000, data) | |
emu.mem_map(0xf7ffd000, 4096, 3) | |
# Importing /lib/i386-linux-gnu/ld-2.23.so: 0xf7ffd000-0xf7ffe000 | |
data=open('/tmp/gef-0xf7ffd000.raw', 'r').read() | |
emu.mem_write(0xf7ffd000, data) | |
emu.mem_map(0xfffdd000, 135168, 3) | |
# Importing [stack]: 0xfffdd000-0xffffe000 | |
data=open('/tmp/gef-0xfffdd000.raw', 'r').read() | |
emu.mem_write(0xfffdd000, data) | |
emu.hook_add(unicorn.UC_HOOK_CODE, hook_code) | |
try: | |
emu.emu_start(0x80485b1, 0x80486e0) | |
except Exception as e: | |
emu.emu_stop() | |
print('Error: {}'.format(e)) | |
return emu | |
def find_init_randint(): | |
for i in range(256): | |
emu = emulate(i) | |
mem = emu.mem_read(0xffffd26c, 0x100) | |
if mem[ord('T')]==0x95 and mem[ord('W')]==0xee: | |
return i | |
return None | |
init = find_init_randint() | |
if init is None: | |
sys.exit(1) | |
print ">>> init randint is %x" % init | |
t = "95eeaf95ef94234999582f722f492f72b19a7aaf72e6e776b57aee722fe77ab5ad9aaeb156729676ae7a236d99b1df4a".decode("hex") | |
emu = emulate(init) | |
c = emu.mem_read(0xffffd26c, 0x100) | |
b = "" | |
for i in range(len(t)): | |
j = c.find(t[i]) | |
b+= chr(j) | |
print "The flag is", b | |
# Unicorn script generated by gef |
Oh yeah you're right, I forgot to mention that in the post.
gef
will export all the registers it knows to the unicorn
script, including the segmentation selectors (CS,DS,SS,etc.) which afaik unicorn
does not support segmentation properly. The problem is that CS, DS, etc. are not GPR registers but selectors, and unicorn
does not define a base or limit for them by default. This only affects x86-32.
A quick (but very bad) hack to have those running would be to assign the values of those registers to a fake mmaped area.
Or better, as you said, simply commenting/removing those does the trick since no address in the function depends on the value of any of the segment selectors (like for example when the stack canary is stored in GS).
Thanks!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks for the post! It is a very useful approach! Tried to use gef/unicorn to reproduce your solution but got segmentation faults when the generated code is writing to CS,SS,DS,ES,FS,GS and UC_X86_REG_GS. eg:
emu.reg_write(unicorn.x86_const.UC_X86_REG_GS, 0x1000)
Commented out these writes since they should not be critical for this procedure and got it working. But wondering why Im getting a segfault when writing to these emulated registers. Any ideas?