Skip to content
This repository has been archived by the owner on Mar 6, 2022. It is now read-only.

Commit

Permalink
reverse engineering - working on ld
Browse files Browse the repository at this point in the history
  • Loading branch information
2xic committed Aug 18, 2019
1 parent b1e0107 commit 4705a30
Show file tree
Hide file tree
Showing 14 changed files with 524 additions and 67 deletions.
7 changes: 4 additions & 3 deletions common/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def wrapper(*args, **kwargs):


class model(model_configs):
def __init__(self, static, socket_io):
def __init__(self, static, socket_io, auto_boot=True, disable_args=False):
super().__init__()
self.static = static

Expand All @@ -44,8 +44,9 @@ def __init__(self, static, socket_io):
self.done_decompile = False
self.decompile_binary()

self.dynamic = emulator(self.static)
self.run_emulator()
self.dynamic = emulator(self.static, disable_args=disable_args)
if auto_boot:
self.run_emulator()
self.ran_emulator = False

# self.cfg = self.create_CFG()
Expand Down
158 changes: 158 additions & 0 deletions dynamic/decoding_the_stack.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1166,6 +1166,164 @@ loc_406cd0:
- 0xeb4fd9 - unicorn
- 0x7fffffffee1b - gdb



'''
0x7ffff7ffed68 is written to rdi
at 0x7234 ?

LD writes the correct address at

000000000001b9ef movups xmm0, xmmword [rsi]
000000000001b9f2 movups xmm1, xmmword [rsi+rdx-0x10]
000000000001b9f7 movups xmmword [rdi], xmm0
000000000001b9fa movups xmmword [rdi+rdx-0x10], xmm1


(gdb) x/25x 0x7ffff7ffed68
0x7ffff7ffed68: 0x62696c2f 0x3638782f 0x2d34365f 0x756e696c
0x7ffff7ffed78: 0x6e672d78 0x696c2f75 0x732e6362 0x00362e6f
0x7ffff7ffed88: 0x00000000 0x00000000 0x00000000 0x00000000
0x7ffff7ffed98: 0x00000000 0x00000000 0x00000000 0x00000000
0x7ffff7ffeda8: 0x00000000 0x00000000 0x00000000 0x00000000
0x7ffff7ffedb8: 0x00000000 0x00000000 0x00000000 0x00000000
0x7ffff7ffedc8: 0x00000000


- unicorn does not seem to write that data....


- all data is from x/25x 0x7fffffffe1a0
RSI!

- okay unicorn actually writes
from .bss
- aLibx8664linuxg:

0000000000012fe2 mov r10d, esi
0000000000012fe5 xor eax, eax
0000000000012fe7 mov r9d, esi
0000000000012fea lea r15, qword [_rtld_global] ; _rtld_global
0000000000012ff1 lea rbp, qword [aLibcso6] ; "libc.so.6"
0000000000012ff8 lea r12, qword [aLibdlso2] ; "libdl.so.2"
0000000000012fff lea r13, qword [aLibpthreadso0] ; "libpthread.so.0"
0000000000013006 lea r14, qword [aLdlinuxx8664so] ; "ld-linux-x86-64.so.2"
000000000001300d and r9d, 0x1
0000000000013011 and r10d, 0x2
0000000000013015 mov rbx, rax


- this writes the data???


libc is loaded at

mov qword ptr [rdi + rdx - 8], rcx (stack [0x3ff113][0x802113] ,unknown[0x362e6f732e6362]);
Breakpoint hit(0xcbba24), write a command or press enter to continue
stepi
one instruction step
mov qword ptr [rdi], rsi (stack [0x3ff111][0x802111] ,unknown[0x2e6f732e6362696c]);
Breakpoint hit(0xcbba27), write a command or press enter to continue
stepi
one instruction step
ret ;


ld-binary -> 0x1ba24



(gdb) c
Continuing.

Hardware watchpoint 2: *0x7ffff7ffed68

Old value = 0
New value = 1651076143
memmove () at ../sysdeps/x86_64/multiarch/../multiarch/memmove-vec-unaligned-erms.S:144
144 ../sysdeps/x86_64/multiarch/../multiarch/memmove-vec-unaligned-erms.S: No such file or directory.
1: x/i $pc
=> 0x7ffff7df49fa <memmove+26>: movups %xmm1,-0x10(%rdi,%rdx,1)
(gdb) watch *0x7ffff7ffed68Quit
(gdb) x 0x7ffff7ffed68


writes first path here
000000000001b9ef movups xmm0, xmmword [rsi]
000000000001b9f2 movups xmm1, xmmword [rsi+rdx-0x10]
000000000001b9f7 movups xmmword [rdi], xmm0
000000000001b9fa movups xmmword [rdi+rdx-0x10], xmm1


SECOND PATH (actually same?)
Hardware watchpoint 2: *0x7ffff7ffed78
Old value = 0
New value = 1852255608
memmove () at ../sysdeps/x86_64/multiarch/../multiarch/memmove-vec-unaligned-erms.S:149
149 ../sysdeps/x86_64/multiarch/../multiarch/memmove-vec-unaligned-erms.S: No such file or directory.
1: x/i $pc
=> 0x7ffff7df49ff <memmove+31>: retq
(gdb) x/100x 0x7ffff7ffed68

000000000001b9ef movups xmm0, xmmword [rsi]
000000000001b9f2 movups xmm1, xmmword [rsi+rdx-0x10]
000000000001b9f7 movups xmmword [rdi], xmm0
000000000001b9fa movups xmmword [rdi+rdx-0x10], xmm1


- bug is actually where rdx points!


- libc string is here 0x1f810
- normal string is here 0x1c500

huh, swing is 0x3310 bytes, on gdb it is 0x20


last location for rdx write.

000000000000712a mov rdx, qword [r13+0x20] ; argument #3 for method sub_1b9d0, CODE XREF=sub_7060+959, sub_7060+1422
000000000000712e mov rsi, qword [r13+0x18] ; argument #2 for method sub_1b9d0
0000000000007132 mov rdi, r15 ; argument #1 for method sub_1b9d0




00000000000105df mov rsi, qword [rsp+0xb8+var_88]
00000000000105e4 test rsi, rsi
00000000000105e7 mov qword [r12], rsi
00000000000105eb jne loc_10610

00000000000105df mov rsi, qword [rsp+0xb8+var_88]
written here -> 0x7fffffffe1c8

(gdb) x $rsp+0xb8
0x7fffffffe1c8: 0xf7def6a8


(gdb) c
Continuing.

Hardware watchpoint 2: *0x7fffffffe1c8

Old value = 0
New value = -136382808
_dl_sysdep_read_whole_file (file=file@entry=0x7ffff7df6988 "/etc/ld.so.cache",
sizep=sizep@entry=0x7ffff7ffe0a0 <cachesize>, prot=prot@entry=1) at dl-misc.c:45
45 dl-misc.c: No such file or directory.
1: x/i $pc
=> 0x7ffff7de95a0 <_dl_sysdep_read_whole_file>: push %r13
(gdb) x 0x7fffffffe1c8
0x7fffffffe1c8: 0xf7def6a8



BINARY -> 0x7ffff7de95a0


actually this write comes from fstat!

'''



Expand Down
33 changes: 26 additions & 7 deletions dynamic/emulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from .registers import *
from .configs import *
import triforce_db
from .helper_scripts.delta import do_cross_check

def threaded(function):
def wrapper(*args, **kwargs):
Expand All @@ -35,10 +36,11 @@ def wrapper(*args, **kwargs):


class emulator(stack_handler, memory_mapper, msr_helper, strace, registers, configs):
def __init__(self, target):
def __init__(self, target, disable_args=False):
self.logging = False

self.target = target
self.disable_args = disable_args

self.boot()
# import sys
Expand Down Expand Up @@ -163,6 +165,9 @@ def boot(self):
"edx":0,
"eax":0x7
})

self.unicorn_debugger.jump_op("ret", None, custom_code=self.unicorn_debugger.pop_branch)


self.unicorn_debugger.jump_op("vpbroadcastb ymm0, xmm0", {

Expand All @@ -187,15 +192,21 @@ def boot(self):
self.emulator.mem_write(0xec5170+8, bytes(bytearray(struct.pack("<Q", 0xf00dbeef))))


# self.unicorn_debugger.add_hook_memory(0xec5170, write_only=True)
self.unicorn_debugger.add_hook_memory(0xec5170, write_only=True)
self.unicorn_debugger.add_breakpoint(0xcb7691)
# self.unicorn_debugger.add_hook_memory(0x8020e7+0x8, write_only=True)
# self.unicorn_debugger.add_hook_memory(0x802110, write_only=True)
# self.unicorn_debugger.add_breakpoint(0xcb0953)


#self.unicorn_debugger.add_breakpoint(0xcb0953)

self.parse_argv_breaks()
# exit(0)g
# print(self.emulator.mem_read(0, 0x128))
# exit(0)


def run(self, non_stop=False, program_entry_point=None):
self.unicorn_debugger.non_stop = non_stop
if not self.target.static_binary:
self.boot_ld()

Expand Down Expand Up @@ -229,6 +240,8 @@ def parse(token):
return break_location

def parse_argv_breaks(self):
if self.disable_args:
return None
'''
just to make it easier to debug.
will rewrite this and the token parser in the helper after
Expand Down Expand Up @@ -268,7 +281,7 @@ def stop_now(self):
self.emulator.emu_stop()
self.unicorn_debugger.log_file.close()

def run(self, non_stop=False, program_entry_point=None):
def run_binary(self, non_stop=False, program_entry_point=None):
if(program_entry_point == None):
program_entry_point = self.target.program_entry_point

Expand All @@ -287,8 +300,10 @@ def hook_block(uc, address, size, user_data):
#self.log_bold_text(">>> Tracing call block at 0x%x(%s), block size = 0x%x" % (address, self.unicorn_debugger.determine_location(address) , size))
# print(">>> Tracing call block at 0x%x(%s), block size = 0x%x" % (address, self.unicorn_debugger.determine_location(address) , size))

if(address == 0x9f54cb):
self.stop_now()
self.unicorn_debugger.branch_logs.append(hex(address))

# if(address == 0x9f54cb):
# self.stop_now()
# raise Exception("bugs")
# exit(0)
self.log_text(uc.reg_read(UC_X86_REG_RBP))
Expand Down Expand Up @@ -354,6 +369,9 @@ def hook_mem_access(uc, access, address, size, value, user_data):
except Exception as e:
self.log_bold_text(">>> Memory is being READ at 0x%x " %(address))

#if((address < 0x802110) and (0x802110 < (address + size))):
# self.unicorn_debugger.handle_commands(memory_access=True)


self.unicorn_debugger.memory_hook_check(address, access == UC_MEM_WRITE)
self.unicorn_debugger.check_memory_value(value)
Expand Down Expand Up @@ -393,6 +411,7 @@ def hook_syscall(mu, user_data):
except Exception as e:
print(e)
print("Last instruction location 0x%x, size %i" % (self.unicorn_debugger.current_address, self.unicorn_debugger.current_size))
print("Last instruction location 0x%x, size %i" % (do_cross_check(self, self.unicorn_debugger.current_address)[2], self.unicorn_debugger.current_size))
self.unicorn_debugger.log_file.close()


Expand Down
30 changes: 24 additions & 6 deletions dynamic/helper_scripts/delta.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,14 @@ def linear_loop(gdb_val, unicorn_val):
# state = refrence.address_instruction_lookup[last_address][0]
# bold_print("Latest instruction with consensus : %s" % ("".join(state[0])))

def do_cross_check(unicorn_refrence, address):
global unicorn_mappings_names
global unicorn_mappings
unicorn_mappings_names = list(unicorn_refrence.look_up_library.keys())
unicorn_mappings = list(unicorn_refrence.look_up_library.values())

return resolve_mapping(address, gdb=False)

def run_check(unicorn_refrence=None):
global unicorn_mappings_names
global unicorn_mappings
Expand Down Expand Up @@ -186,14 +194,16 @@ def run_check(unicorn_refrence=None):
trace_register = False

op_count = 0
#mismatch_count = 0
max_mismatch_count = 2

last_register_state = None

hit_count = {

}

while i < len(unicorn) and j < len(gdb) and 0 < len(unicorn[i]):
while i < len(unicorn) and j < len(gdb) and 0 < len(unicorn[i]) and (disagreement_count < max_mismatch_count):
if(unicorn[i].strip() == (split_safe(gdb[j].strip().split(" "), 1)) or (unicorn[i].strip() == gdb[j].strip().split("\t")[0].split(" ")[-1])):
if("=>" in gdb[j]):
last_agrement = unicorn[i].strip()
Expand Down Expand Up @@ -228,11 +238,13 @@ def run_check(unicorn_refrence=None):
bold_print("Error in function %s" % (elf_get_symbol_name(elf_refrence, int(last_agrement, 16))))
bold_print("Last agreement {} (hit {})".format(hex(agreement), hit_count[last_agrement]))
bold_print("Binary location : gdb : {}, unicorn : {}".format(hex(gdb_real_location), hex(unicorn_real_location)))
#mismatch_count += 1
else:
bold_print("Error in function %s" % (elf_get_symbol_name(unicorn_refrence.target, int(int(last_agrement, 16)))))
bold_print("Last agreement {} (hit {})".format(last_agrement, hit_count[last_agrement]))
bold_print("Unicorn : %s, GDB : %s" % (unicorn[i].strip(), gdb[j].strip().split(" ")[1]))

#mismatch_count += 1


target = "unicorn" if(unicorn_val < gdb_val) else "gdb"

Expand Down Expand Up @@ -268,7 +280,8 @@ def run_check(unicorn_refrence=None):
bold_print("Gdb had to take %i steps" % (new_j - j))
i = new_i
j = new_j

#mismatch_count += 1

elif(target == "gdb"):
linear_loop(gdb_val, unicorn_val)
j = simulate_variable
Expand Down Expand Up @@ -309,6 +322,7 @@ def run_check(unicorn_refrence=None):
print("From address : 0x%x" % int(unicorn[i - 3], 16))
print("unicorn %s, gdb %s " % (unicorn_val, gdb_val))
print(gdb[j])
#mismatch_count += 1

unicorn_report(unicorn_refrence, op_count, unicorn[i - 3])

Expand All @@ -332,9 +346,13 @@ def run_check(unicorn_refrence=None):
print("Last instruction {}".format(unicorn[i-2]))
print("Last instruction {}".format(unicorn[i-3]))

bold_print("Disagreement with gdb == %i" % (disagreement_count))
print("This can be error with handling of instruction or the simple fact that unicorn can have placed something more accesible than gdb.")
print("For instance, enviorment variables are stored more clossely with unicorn")
if not (disagreement_count < max_mismatch_count):
bold_print("Disagreement with gdb == %i (could be more, hit max count)" % (disagreement_count))

else:
bold_print("Disagreement with gdb == %i" % (disagreement_count))
print("This can be error with handling of instruction or the simple fact that unicorn can have placed something more accesible than gdb.")
print("For instance, enviorment variables are stored more clossely with unicorn")

if __name__ == "__main__":
run_check()
Expand Down
Loading

0 comments on commit 4705a30

Please sign in to comment.