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

Commit

Permalink
great progress on dynamic linker with faster instrumental tools
Browse files Browse the repository at this point in the history
  • Loading branch information
2xic committed Jul 28, 2019
1 parent 25fe955 commit caf89b7
Show file tree
Hide file tree
Showing 13 changed files with 349 additions and 88 deletions.
9 changes: 6 additions & 3 deletions common/printer.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
def bold_text(text):
return '\033[1m' + text + '\033[0m'

def bold_print(text):
print(bold_text(text))

def bold_print(text, end=None):
if(end == None):
print(bold_text(text))
else:
print(bold_text(text), end=end)

4 changes: 1 addition & 3 deletions dynamic/dynamic_linker.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,8 @@ def parse_relocation(elf_target, target, debug=False):
elif(rela_type == "R_X86_64_IRELATIVE"):
lookup["DIRECT_MAPPING_{}".format(direct_mapping_count)] = [address, addend]
direct_mapping_count += 1
else:
elif(debug):
print("Fix dynamic linker[{}], need to handle type : {}, symbol size : {}, location {}".format(elf_target.file_name, rela_type, len(elf_target.symbol_table[ELF64_R_SYM(info)]), hex(address)))
# lookup["DIRECT_MAPPING_{}".format(direct_mapping_count)] = [address, 0xf00dbeef]
# direct_mapping_count += 1
except Exception as e:
print("erorr in parse_relocation", e)
return lookup
Expand Down
79 changes: 75 additions & 4 deletions dynamic/emulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import os
import random
import threading
import json
PATH = (os.path.dirname(os.path.abspath(__file__)) + "/")


from unicorn import *
Expand Down Expand Up @@ -39,7 +41,9 @@ def __init__(self, target):
self.target = target

self.boot()

# import sys
# print(sys.argv)
# exit(0)
'''
should make a better way to reset each part of the emulator.
'''
Expand All @@ -50,6 +54,7 @@ def boot(self):
self.db = triforce_db.db_init()
self.emulator = Uc(UC_ARCH_X86, UC_MODE_64)
self.future_breakpoints = []
self.file_descriptors = []

stack_handler.__init__(self)
memory_mapper.__init__(self)
Expand All @@ -75,7 +80,7 @@ def boot(self):
("rip", UC_X86_REG_RIP),
("rsp", UC_X86_REG_RSP),
("r9", UC_X86_REG_R9),

("rdx", UC_X86_REG_RDX)
]

for register, unicorn_refrence in self.db_registers:
Expand Down Expand Up @@ -174,12 +179,65 @@ def boot(self):
'''
start, end, delta = self.init_stack()
self.emulator.reg_write(UC_X86_REG_RSP, end)
self.emulator.mem_write(0xec5170, bytes(bytearray(struct.pack("<Q", 0xf00dbeef))))
self.emulator.mem_write(0xec5170+8, bytes(bytearray(struct.pack("<Q", 0xf00dbeef))))


# self.unicorn_debugger.add_hook_memory(0xec5170, write_only=True)


self.parse_argv_breaks()
# exit(0)
if not self.target.static_binary:
self.boot_ld()
# input("more?")
# exit(0)

def parse_location(self, tokens):
token = ""
break_location = 0
sign = 1
def parse(token):
if(token == "ld"):
return self.look_up_library["ld-linux-x86-64.so.2"][0]
elif(token == "libc"):
return self.look_up_library["libc.so.6"][0]
elif(token.isdigit()):
return int(token)
elif(token.replace("0x", "").isdigit()):
return int(token, 16)
return 0

sign = 1
for y in tokens:
if(y == "+" or y == "-"):
break_location += parse(token) * sign
sign = (1) if(y == "+") else (-1)
token = ""
continue
token += y
break_location += parse(token) * sign
return break_location

def parse_argv_breaks(self):
'''
just to make it easier to debug.
will rewrite this and the token parser in the helper after
I have finished the dynamic linker.
'''
i = 1
breaks = []
while i < len(sys.argv):
if(sys.argv[i] == "--break"):
i += 1

token = sys.argv[i]
breaks.append(token)

break_location = self.parse_location(token)

print("Set breakpoint {}".format(break_location))
self.unicorn_debugger.add_breakpoint(break_location)
i += 1
open(PATH + "/breaks.json", "w").write(json.dumps(breaks))

def log_text(self, text, style=None, level=0):
if(self.logging):
Expand All @@ -195,6 +253,10 @@ def log_bold_text(self, text, level=0):
def run_thread(self, non_stop=False):
self.run(non_stop)

def stop_now(self):
self.emulator.emu_stop()
self.unicorn_debugger.log_file.close()

def run(self, non_stop=False, program_entry_point=None):
if(program_entry_point == None):
program_entry_point = self.target.program_entry_point
Expand All @@ -213,6 +275,11 @@ def run(self, non_stop=False, program_entry_point=None):
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()
# raise Exception("bugs")
# exit(0)
self.log_text(uc.reg_read(UC_X86_REG_RBP))

def hook_mem_invalid(uc, access, address, size, value, user_data):
Expand Down Expand Up @@ -258,6 +325,10 @@ def hook_code(mu, address, size, user_data):

def hook_mem_access(uc, access, address, size, value, user_data):

# if(address == 0xec5170):
# print("huh bug?")
# input("adress read")

if access == UC_MEM_WRITE:
self.log_bold_text(">>> Memory is being WRITE at 0x%x(%s), data size = %u, data value = 0x%x" % (address, self.unicorn_debugger.determine_location(address) , size, value))

Expand Down
19 changes: 10 additions & 9 deletions dynamic/helper_scripts/delta.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,15 @@ def mapping_range(address, start, end):
return start <= address <= end
#((address - start) <= (end - start))

def resolve_mapping(address, gdb=True):
def resolve_mapping(address, gdb=True, get_elf=False):
if gdb:
for index, item in enumerate(gdb_mappings):
if(mapping_range(address, item[0], item[1])):
return gdb_mappings_name[index], ((address - gdb_resolve_mappings[index]) + gdb_add_offset[index]), address - gdb_resolve_mappings[index]
return gdb_mappings_name[index], ((address - gdb_resolve_mappings[index]) + gdb_add_offset[index]), address - gdb_resolve_mappings[index], None
elif not gdb:
for index, item in enumerate(unicorn_mappings):
# print(item)
if(mapping_range(address, item[0], item[0] + item[1])):
return unicorn_mappings_names[index], item[0], (address - item[0])
return unicorn_mappings_names[index], item[0], (address - item[0]), item[2]

print("did not find ??? 0x%x" % (address))
assert(False)
Expand All @@ -75,7 +74,7 @@ def valid_dynamic(unicorn_item, gdb_item):

new_unicorn_val = int(unicorn_item.strip(), 16)
new_gdb_val = int(gdb_item, 16)
_, new_gdb_val, _ = resolve_mapping(new_gdb_val)
_, new_gdb_val, _, _ = resolve_mapping(new_gdb_val)
if(new_gdb_val == new_unicorn_val):
return True
return False
Expand Down Expand Up @@ -120,7 +119,7 @@ def check_for_new_consensus(gdb, unicorn, i, j, static=True):
gdb_look_up_hash[n.strip().split(" ")[1]] = index_gdb
if not static and ("=>" in n):
gdb_val = int(n.strip().split(" ")[1], 16)
_, gdb_val, _ = resolve_mapping(gdb_val)
_, gdb_val, _, _ = resolve_mapping(gdb_val)
gdb_look_up_hash[hex(gdb_val)] = index_gdb

minimum_change_i = None
Expand Down Expand Up @@ -210,7 +209,7 @@ def run_check(unicorn_refrence=None):
old_i, old_j = i, j

if not unicorn_refrence.target.static_binary:
gdb_location, gdb_val, gdb_real_location = resolve_mapping(gdb_val)
gdb_location, gdb_val, gdb_real_location, _ = resolve_mapping(gdb_val)
if(gdb_val == unicorn_val):
last_agrement = unicorn[i].strip()
hit_count[last_agrement] = hit_count.get(last_agrement, 0) + 1
Expand All @@ -219,12 +218,14 @@ def run_check(unicorn_refrence=None):
j += 1
op_count += 1
continue
_, _, agreement = resolve_mapping(int(last_agrement, 16), gdb=False)
_, _, agreement, elf_refrence = resolve_mapping(int(last_agrement, 16), gdb=False)

unicorn_location, _, unicorn_real_location = resolve_mapping(unicorn_val, gdb=False)
unicorn_location, _, unicorn_real_location, _ = resolve_mapping(unicorn_val, gdb=False)
bold_print("Disagreement gdb : {}, {}".format(gdb_location, hex(gdb_val)))
bold_print("Disagreement unicorn : {}, {}".format(unicorn_location, hex(unicorn_val)))

bold_print("Error in Elf %s" % (elf_refrence.file_name))
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)))
else:
Expand Down
47 changes: 39 additions & 8 deletions dynamic/helper_scripts/gdb_leak_dynamic.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import gdb
import sys
import os
import json

PATH = (os.path.dirname(os.path.abspath(__file__)) + "/")
sys.path.insert(0, PATH + "../")
Expand All @@ -9,21 +10,51 @@
from dynamic_linker import *
from elf.utils import get_symbol_name as elf_get_symbol_name
from elf.elf_parser import *
import sys

libc_offset = 0x7ffff7a3a000
ld_offset = 0x7ffff7dd9000

libc = elf("/lib/x86_64-linux-gnu/libc.so.6")
program = elf("/root/test/test_binaries/getgid")
print(program.program_header_start)

'''
'''

exit(0)
#offset = 0x2cd2 if len(sys.argv) < 2 else int(sys.argv[1], 16)
#os.environ["DEBUSSY"] = "1"
#print(sys.argv)

gdb.execute("display/i $pc")

for breaks in json.loads(open(PATH + "../breaks.json").read()):
def parse(token):
if(token == "ld"):
return ld_offset
elif(token == "libc"):
return libc_offset
elif(token.isdigit()):
return int(token)
elif("0x" in token):
return int(token, 16)
return 0

sign = 1
break_location = 0
token =""
for y in breaks:
if(y == "+" or y == "-"):
break_location += parse(token) * sign
sign = (1) if(y == "+") else (-1)
token = ""
continue
token += y

break_location += parse(token) * sign

print("Set breakpoint {}".format(break_location))
# print("{}".format(hex(break_location)))
gdb.execute("break *{}".format(break_location))


#output = gdb.execute('break _start', to_string=True)
#output = gdb.execute('run', to_string=True)
'''
Expand All @@ -50,11 +81,11 @@
#gdb.execute("break *{}".format(libc_offset + 0x20400))

#ENTRY_OFFSET = gdb.execute("break *{}".format(ld_offset + 0xc20))
gdb.execute("break *{}".format(ld_offset + 0x2490))

#gdb.execute("r")
#gdb.execute("break *{}".format(ld_offset + 0xc64))
gdb.execute("r")

#gdb.execute("r")


'''
for i in range(5000):
Expand Down
Loading

0 comments on commit caf89b7

Please sign in to comment.