diff options
| -rw-r--r-- | miasm2/analysis/sandbox.py | 4 | ||||
| -rw-r--r-- | miasm2/jitter/vm_mngr_py.c | 2 | ||||
| -rw-r--r-- | miasm2/os_dep/win_api_x86_32_seh.py | 589 |
3 files changed, 192 insertions, 403 deletions
diff --git a/miasm2/analysis/sandbox.py b/miasm2/analysis/sandbox.py index 688c7592..9dc800fc 100644 --- a/miasm2/analysis/sandbox.py +++ b/miasm2/analysis/sandbox.py @@ -265,8 +265,8 @@ class OS_Linux_str(OS): class Arch_x86(Arch): _ARCH_ = None # Arch name - STACK_SIZE = 0x100000 - STACK_BASE = 0x123000 + STACK_SIZE = 0x10000 + STACK_BASE = 0x130000 def __init__(self): super(Arch_x86, self).__init__() diff --git a/miasm2/jitter/vm_mngr_py.c b/miasm2/jitter/vm_mngr_py.c index 9894fd02..54511c20 100644 --- a/miasm2/jitter/vm_mngr_py.c +++ b/miasm2/jitter/vm_mngr_py.c @@ -217,7 +217,7 @@ PyObject* vm_set_mem(VmMngr* self, PyObject* args) ret = vm_write_mem(&self->vm_mngr, addr, buffer, size); if (ret < 0) - RAISE(PyExc_TypeError,"arg must be str"); + RAISE(PyExc_TypeError, "Error in set_mem"); check_write_code_bloc(&self->vm_mngr, size*8, addr); diff --git a/miasm2/os_dep/win_api_x86_32_seh.py b/miasm2/os_dep/win_api_x86_32_seh.py index c86c179d..f33a853f 100644 --- a/miasm2/os_dep/win_api_x86_32_seh.py +++ b/miasm2/os_dep/win_api_x86_32_seh.py @@ -28,6 +28,7 @@ from miasm2.jitter.csts import PAGE_READ, PAGE_WRITE from miasm2.core.utils import pck32, upck32 import miasm2.arch.x86.regs as x86_regs + # Constants Windows EXCEPTION_BREAKPOINT = 0x80000003 EXCEPTION_ACCESS_VIOLATION = 0xc0000005 @@ -40,7 +41,7 @@ log = logging.getLogger("seh_helper") console_handler = logging.StreamHandler() console_handler.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s")) log.addHandler(console_handler) -log.setLevel(logging.WARN) +log.setLevel(logging.INFO) FS_0_AD = 0x7ff70000 PEB_AD = 0x7ffdf000 @@ -52,22 +53,20 @@ MAX_MODULES = 0x40 tib_address = FS_0_AD peb_address = PEB_AD peb_ldr_data_offset = 0x1ea0 -peb_ldr_data_address = LDR_AD + peb_ldr_data_offset # PEB_AD + 0x1000 +peb_ldr_data_address = LDR_AD + peb_ldr_data_offset modules_list_offset = 0x1f00 -InInitializationOrderModuleList_offset = 0x1ee0 # 0x1f48 +InInitializationOrderModuleList_offset = 0x1ee0 InInitializationOrderModuleList_address = LDR_AD + \ - InInitializationOrderModuleList_offset # PEB_AD + 0x2000 + InInitializationOrderModuleList_offset InLoadOrderModuleList_offset = 0x1ee0 + \ - MAX_MODULES * 0x1000 # 0x1f48 + MAX_MODULES*0x1000 + MAX_MODULES * 0x1000 InLoadOrderModuleList_address = LDR_AD + \ - InLoadOrderModuleList_offset # PEB_AD + 0x2000 + InLoadOrderModuleList_offset -# in_load_order_module_1 = LDR_AD + -# in_load_order_module_list_offset#PEB_AD + 0x3000 default_seh = PEB_AD + 0x20000 process_environment_address = 0x10000 @@ -85,8 +84,10 @@ loaded_modules = ["ntdll.dll", "kernel32.dll"] main_pe = None main_pe_name = "c:\\xxx\\toto.exe" +MAX_SEH = 5 + -def build_fake_teb(): +def build_teb(myjit, teb_address): """ +0x000 NtTib : _NT_TIB +0x01c EnvironmentPointer : Ptr32 Void @@ -106,10 +107,10 @@ def build_fake_teb(): o += pck32(peb_address) o += pck32(0x11223344) - return o + myjit.vm.add_memory_page(teb_address, PAGE_READ | PAGE_WRITE, o) -def build_fake_peb(): +def build_peb(myjit, peb_address): """ +0x000 InheritedAddressSpace : UChar +0x001 ReadImageFileExecOptions : UChar @@ -121,36 +122,18 @@ def build_fake_peb(): +0x010 processparameter """ - offset_serverdata = 0x100 - offset_data1 = 0x108 - offset_data2 = 0x110 + offset = peb_address + 8 o = "" - o += "\x00" * 0x8 if main_pe: o += pck32(main_pe.NThdr.ImageBase) else: - o += "AAAA" + offset += 4 o += pck32(peb_ldr_data_address) o += pck32(process_parameters_address) + myjit.vm.add_memory_page(offset, PAGE_READ | PAGE_WRITE, o) - o += (0x54 - len(o)) * "A" - o += pck32(peb_address + offset_serverdata) - o += (0x64 - len(o)) * "E" - o += pck32(1) # number of cpu - - o += (offset_serverdata - len(o)) * "B" - o += pck32(0x33333333) - o += pck32(peb_address + offset_data1) - o += (offset_data1 - len(o)) * "C" - o += pck32(0x44444444) - o += pck32(peb_address + offset_data2) - o += (offset_data2 - len(o)) * "D" - o += pck32(0x55555555) - o += pck32(0x0077007C) - return o - -def build_fake_ldr_data(modules_info): +def build_ldr_data(myjit, modules_info): """ +0x000 Length : Uint4B +0x004 Initialized : UChar @@ -161,9 +144,7 @@ def build_fake_ldr_data(modules_info): """ o = "" # ldr offset pad - o += "\x00" * peb_ldr_data_offset - o += "\x00" * 0xc - # text XXX + offset = LDR_AD + peb_ldr_data_offset + 0xC # get main pe info m_e = None @@ -172,10 +153,11 @@ def build_fake_ldr_data(modules_info): m_e = (e, bname, addr) break if not m_e: - log.warn('no main pe, ldr data will be unconsistant') + log.warn('No main pe, ldr data will be unconsistant') + offset, data = offset + 8, "" else: - print 'inloadorder first', hex(m_e[2]) - o += pck32(m_e[2]) + pck32(0) + log.info('Ldr %x', m_e[2]) + data = pck32(m_e[2]) + pck32(0) # get ntdll ntdll_e = None @@ -184,89 +166,15 @@ def build_fake_ldr_data(modules_info): ntdll_e = (e, bname, addr) continue if not ntdll_e: - log.warn('no ntdll, ldr data will be unconsistant') + log.warn('No ntdll, ldr data will be unconsistant') else: - print 'ntdll', hex(ntdll_e[2]) - o += pck32(ntdll_e[2] + 0x8) + pck32(0) # XXX TODO - o += pck32(ntdll_e[2] + 0x10) + pck32(0) - - return o - -# def build_fake_InInitializationOrderModuleList(modules_name): -# """ -# +0x000 Flink : Ptr32 -+ This distance -# +0x004 Blink : Ptr32 | is eight bytes -# +0x018 DllBase : Ptr32 Void -+ DllBase -# +0x01c EntryPoint : Ptr32 Void -# +0x020 SizeOfImage : Uint4B -# +0x024 FullDllName : _UNICODE_STRING -# +0x02c BaseDllName : _UNICODE_STRING -# +0x034 Flags : Uint4B -# +0x038 LoadCount : Uint2B -# +0x03a TlsIndex : Uint2B -# +0x03c HashLinks : _LIST_ENTRY -# +0x03c SectionPointer : Ptr32 Void -# +0x040 CheckSum : Uint4B -# +0x044 TimeDateStamp : Uint4B -# +0x044 LoadedImports : Ptr32 Void -# +0x048 EntryPointActivationContext : Ptr32 Void -# +0x04c PatchInformation : Ptr32 Void -# """ -# -# o = "" -# offset_name = 0x700 -# for i, m in enumerate(modules_name): -# fname = os.path.join('win_dll', m) -# if isinstance(m, tuple): -# fname, e = m -# else: -# fname, e = m, None -# bname = os.path.split(fname)[1].lower() -# bname = "\x00".join(bname)+"\x00" -# print "add module", repr(bname) -# print hex(InInitializationOrderModuleList_address+i*0x1000) -# if e == None: -# e = pe_init.PE(open(fname, 'rb').read()) -# -# next_ad = InInitializationOrderModuleList_address + (i+1)*0x1000 -# if i == len(modules_name) -1: -# next_ad = InInitializationOrderModuleList_address -# m_o = "" -# m_o += pck32(next_ad ) -# m_o += pck32(InInitializationOrderModuleList_address + (i-1)*0x1000) -# m_o += pck32(next_ad + 8 ) -# m_o += pck32(InInitializationOrderModuleList_address -# + (i-1)*0x1000 + 8) -# m_o += pck32(next_ad + 0x10 ) -# m_o += pck32(InInitializationOrderModuleList_address -# + (i-1)*0x1000 + 0x10) -# m_o += pck32(e.NThdr.ImageBase) -# m_o += pck32(e.rva2virt(e.Opthdr.AddressOfEntryPoint)) -# m_o += pck32(e.NThdr.sizeofimage) -# -# m_o += (0x24 - len(m_o))*"A" -# print hex(len(bname)), repr(bname) -# m_o += struct.pack('HH', len(bname), len(bname)+2) -# m_o += pck32(InInitializationOrderModuleList_address -# + i*0x1000+offset_name) -# -# m_o += (0x2C - len(m_o))*"A" -# m_o += struct.pack('HH', len(bname), len(bname)+2) -# m_o += pck32(InInitializationOrderModuleList_address -# + i*0x1000+offset_name) -# -# m_o += (offset_name - len(m_o))*"B" -# m_o += bname -# m_o += "\x00"*3 -# -# -# m_o += (0x1000 - len(m_o))*"J" -# -# print "module", "%.8X"%e.NThdr.ImageBase, fname -# -# o += m_o -# return o -# + data += pck32(ntdll_e[2] + 0x8) + pck32(0) # XXX TODO + data += pck32(ntdll_e[2] + 0x10) + pck32(0) + + if data: + myjit.vm.add_memory_page(offset, PAGE_READ | PAGE_WRITE, data) + + dummy_e = pe_init.PE() dummy_e.NThdr.ImageBase = 0 dummy_e.Opthdr.AddressOfEntryPoint = 0 @@ -274,6 +182,28 @@ dummy_e.NThdr.sizeofimage = 0 def create_modules_chain(myjit, modules_name): + """ + kd> dt nt!_LDR_DATA_TABLE_ENTRY + +0x000 InLoadOrderLinks : _LIST_ENTRY + +0x008 InMemoryOrderLinks : _LIST_ENTRY + +0x010 InInitializationOrderLinks : _LIST_ENTRY + +0x018 DllBase : Ptr32 Void + +0x01c EntryPoint : Ptr32 Void + +0x020 SizeOfImage : Uint4B + +0x024 FullDllName : _UNICODE_STRING + +0x02c BaseDllName : _UNICODE_STRING + +0x034 Flags : Uint4B + +0x038 LoadCount : Uint2B + +0x03a TlsIndex : Uint2B + +0x03c HashLinks : _LIST_ENTRY + +0x03c SectionPointer : Ptr32 Void + +0x040 CheckSum : Uint4B + +0x044 TimeDateStamp : Uint4B + +0x044 LoadedImports : Ptr32 Void + +0x048 EntryPointActivationContext : Ptr32 Void + +0x04c PatchInformation : Ptr32 Void + """ + modules_info = {} base_addr = LDR_AD + modules_list_offset # XXXX offset_name = 0x500 @@ -281,18 +211,15 @@ def create_modules_chain(myjit, modules_name): out = "" for i, m in enumerate([(main_pe_name, main_pe), - ("", dummy_e)] + modules_name): + ("", dummy_e)] + modules_name): addr = base_addr + i * 0x1000 - # fname = os.path.join('win_dll', m) if isinstance(m, tuple): fname, e = m else: fname, e = m, None bpath = fname.replace('/', '\\') - bname = os.path.split(fname)[1].lower() - bname = "\x00".join(bname) + "\x00" - # print "add module", repr(bname), repr(bpath) - # print hex(InInitializationOrderModuleList_address+i*0x1000) + bname_str = os.path.split(fname)[1].lower() + bname = "\x00".join(bname_str) + "\x00" if e is None: if i == 0: full_name = fname @@ -301,11 +228,11 @@ def create_modules_chain(myjit, modules_name): try: e = pe_init.PE(open(full_name, 'rb').read()) except IOError: - log.error('no main pe, ldr data will be unconsistant!!') + log.error('No main pe, ldr data will be unconsistant!') e = None if e is None: continue - print "add module", hex(e.NThdr.ImageBase), repr(bname) + log.info("Add module %x %r", e.NThdr.ImageBase, bname_str) modules_info[bname] = addr, e @@ -319,30 +246,29 @@ def create_modules_chain(myjit, modules_name): m_o += pck32(e.NThdr.ImageBase) m_o += pck32(e.rva2virt(e.Opthdr.AddressOfEntryPoint)) m_o += pck32(e.NThdr.sizeofimage) - - m_o += (0x24 - len(m_o)) * "A" - print hex(len(bname)), repr(bname) m_o += struct.pack('HH', len(bname), len(bname) + 2) m_o += pck32(addr + offset_path) - - m_o += (0x2C - len(m_o)) * "A" m_o += struct.pack('HH', len(bname), len(bname) + 2) m_o += pck32(addr + offset_name) + myjit.vm.add_memory_page(addr, PAGE_READ | PAGE_WRITE, m_o) - m_o += (offset_name - len(m_o)) * "B" + m_o = "" m_o += bname m_o += "\x00" * 3 + myjit.vm.add_memory_page( + addr + offset_name, PAGE_READ | PAGE_WRITE, m_o) - m_o += (offset_path - len(m_o)) * "B" + m_o = "" m_o += "\x00".join(bpath) + "\x00" m_o += "\x00" * 3 - # out += m_o - myjit.vm.set_mem(addr, m_o) + myjit.vm.add_memory_page( + addr + offset_path, PAGE_READ | PAGE_WRITE, m_o) + return modules_info def fix_InLoadOrderModuleList(myjit, module_info): - print "fix inloadorder" + log.debug("Fix InLoadOrderModuleList") # first binary is PE # last is dumm_e olist = [] @@ -357,14 +283,14 @@ def fix_InLoadOrderModuleList(myjit, module_info): if "/" in fname: fname = fname[fname.rfind("/") + 1:] - bname = '\x00'.join(fname) + '\x00' + bname_str = fname + bname = '\x00'.join(bname_str) + '\x00' if not bname.lower() in module_info: - log.warn('module not found, ldr data will be unconsistant') + log.warn('Module not found, ldr data will be unconsistant') continue addr, e = module_info[bname.lower()] - # for bname, (addr, e) in module_info.items(): - print bname + log.debug(bname_str) if e == main_pe: m_e = (e, bname, addr) continue @@ -373,7 +299,7 @@ def fix_InLoadOrderModuleList(myjit, module_info): continue olist.append((e, bname, addr)) if not m_e or not d_e: - log.warn('no main pe, ldr data will be unconsistant') + log.warn('No main pe, ldr data will be unconsistant') else: olist[0:0] = [m_e] olist.append(d_e) @@ -387,6 +313,7 @@ def fix_InLoadOrderModuleList(myjit, module_info): def fix_InMemoryOrderModuleList(myjit, module_info): + log.debug("Fix InMemoryOrderModuleList") # first binary is PE # last is dumm_e olist = [] @@ -401,13 +328,13 @@ def fix_InMemoryOrderModuleList(myjit, module_info): if "/" in fname: fname = fname[fname.rfind("/") + 1:] - bname = '\x00'.join(fname) + '\x00' + bname_str = fname + bname = '\x00'.join(bname_str) + '\x00' if not bname.lower() in module_info: - log.warn('module not found, ldr data will be unconsistant') + log.warn('Module not found, ldr data will be unconsistant') continue addr, e = module_info[bname.lower()] - # for bname, (addr, e) in module_info.items(): - print bname + log.debug(bname_str) if e == main_pe: m_e = (e, bname, addr) continue @@ -416,7 +343,7 @@ def fix_InMemoryOrderModuleList(myjit, module_info): continue olist.append((e, bname, addr)) if not m_e or not d_e: - log.warn('no main pe, ldr data will be unconsistant') + log.warn('No main pe, ldr data will be unconsistant') else: olist[0:0] = [m_e] olist.append(d_e) @@ -451,7 +378,7 @@ def fix_InInitializationOrderModuleList(myjit, module_info): continue olist.append((e, bname, addr)) if not ntdll_e or not kernel_e or not d_e: - log.warn('no kernel ntdll, ldr data will be unconsistant') + log.warn('No kernel ntdll, ldr data will be unconsistant') else: olist[0:0] = [ntdll_e] olist[1:1] = [kernel_e] @@ -472,8 +399,8 @@ def add_process_env(myjit): env_str = '\x00'.join(env_str) env_str += "\x00" * 0x10 myjit.vm.add_memory_page(process_environment_address, - PAGE_READ | PAGE_WRITE, - env_str) + PAGE_READ | PAGE_WRITE, + env_str) myjit.vm.set_mem(process_environment_address, env_str) @@ -487,151 +414,27 @@ def add_process_parameters(myjit): o) -def build_fake_InLoadOrderModuleList(modules_name): - """ - +0x000 Flink : Ptr32 -+ This distance - +0x004 Blink : Ptr32 | is eight bytes - +0x018 DllBase : Ptr32 Void -+ DllBase -> _IMAGE_DOS_HEADER - +0x01c EntryPoint : Ptr32 Void - +0x020 SizeOfImage : Uint4B - +0x024 FullDllName : _UNICODE_STRING - +0x02c BaseDllName : _UNICODE_STRING - +0x034 Flags : Uint4B - +0x038 LoadCount : Uint2B - +0x03a TlsIndex : Uint2B - +0x03c HashLinks : _LIST_ENTRY - +0x03c SectionPointer : Ptr32 Void - +0x040 CheckSum : Uint4B - +0x044 TimeDateStamp : Uint4B - +0x044 LoadedImports : Ptr32 Void - +0x048 EntryPointActivationContext : Ptr32 Void - +0x04c PatchInformation : Ptr32 Void - """ - - o = "" - offset_name = 0x700 - first_name = "\x00".join(main_pe_name + "\x00\x00") - - o = "" - o += pck32(InLoadOrderModuleList_address) - o += pck32(InLoadOrderModuleList_address + - (len(modules_name) - 1) * 0x1000) - o += pck32(InLoadOrderModuleList_address + 8) - o += pck32(InLoadOrderModuleList_address + - (len(modules_name) - 1) * 0x1000 + 8) - o += pck32(InLoadOrderModuleList_address + 0x10) - o += pck32(InLoadOrderModuleList_address + - (len(modules_name) - 1) * 0x1000 + 0x10) - - if main_pe: - o += pck32(main_pe.NThdr.ImageBase) - o += pck32(main_pe.rva2virt(main_pe.Opthdr.AddressOfEntryPoint)) - else: - # no fixed values - pass - - o += (0x24 - len(o)) * "A" - o += struct.pack('HH', len(first_name), len(first_name)) - o += pck32(InLoadOrderModuleList_address + offset_name) - - o += (0x2C - len(o)) * "A" - o += struct.pack('HH', len(first_name), len(first_name)) - o += pck32(InLoadOrderModuleList_address + offset_name) - - o += (offset_name - len(o)) * "B" - o += first_name - o += (0x1000 - len(o)) * "C" - for i, m in enumerate(modules_name): - # fname = os.path.join('win_dll', m) - if isinstance(m, tuple): - fname, e = m - else: - fname, e = m, None - bname = os.path.split(fname)[1].lower() - bname = "\x00".join(bname) + "\x00" - print hex(InLoadOrderModuleList_address + i * 0x1000) - if e is None: - e = pe_init.PE(open(fname, 'rb').read()) - - print "add module", hex(e.NThdr.ImageBase), repr(bname) - - next_ad = InLoadOrderModuleList_address + (i + 1) * 0x1000 - if i == len(modules_name) - 1: - next_ad = InLoadOrderModuleList_address - m_o = "" - m_o += pck32(next_ad) - m_o += pck32(InLoadOrderModuleList_address + (i - 1) * 0x1000) - m_o += pck32(next_ad + 8) - m_o += pck32(InLoadOrderModuleList_address + (i - 1) * 0x1000 + 8) - m_o += pck32(next_ad + 0x10) - m_o += pck32(InLoadOrderModuleList_address + (i - 1) * 0x1000 + 0x10) - m_o += pck32(e.NThdr.ImageBase) - m_o += pck32(e.rva2virt(e.Opthdr.AddressOfEntryPoint)) - m_o += pck32(e.NThdr.sizeofimage) - - m_o += (0x24 - len(m_o)) * "A" - print hex(len(bname)), repr(bname) - m_o += struct.pack('HH', len(bname), len(bname) + 2) - m_o += pck32(InLoadOrderModuleList_address + i * 0x1000 + offset_name) - - m_o += (0x2C - len(m_o)) * "A" - m_o += struct.pack('HH', len(bname), len(bname) + 2) - m_o += pck32(InLoadOrderModuleList_address + i * 0x1000 + offset_name) - - m_o += (offset_name - len(m_o)) * "B" - m_o += bname - m_o += "\x00" * 3 - - m_o += (0x1000 - len(m_o)) * "J" - - print "module", "%.8X" % e.NThdr.ImageBase, fname - - o += m_o - return o - - all_seh_ad = dict([(x, None) for x in xrange(FAKE_SEH_B_AD, FAKE_SEH_B_AD + 0x1000, 0x20)]) # http://blog.fireeye.com/research/2010/08/download_exec_notes.html seh_count = 0 + def init_seh(myjit): global seh_count seh_count = 0 - # myjit.vm.add_memory_page(tib_address, PAGE_READ | PAGE_WRITE, - # p(default_seh) + p(0) * 11 + p(peb_address)) - myjit.vm.add_memory_page( - FS_0_AD, PAGE_READ | PAGE_WRITE, build_fake_teb()) - # myjit.vm.add_memory_page(peb_address, PAGE_READ | PAGE_WRITE, p(0) * - # 3 + p(peb_ldr_data_address)) - myjit.vm.add_memory_page( - peb_address, PAGE_READ | PAGE_WRITE, build_fake_peb()) - # myjit.vm.add_memory_page(peb_ldr_data_address, PAGE_READ | - # PAGE_WRITE, p(0) * 3 + p(in_load_order_module_list_address) + p(0) * - # 0x20) + build_teb(myjit, FS_0_AD) + build_peb(myjit, peb_address) - """ - ldr_data += "\x00"*(InInitializationOrderModuleList_offset - len(ldr_data)) - ldr_data += build_fake_InInitializationOrderModuleList(loaded_modules) - ldr_data += "\x00"*(InLoadOrderModuleList_offset - len(ldr_data)) - ldr_data += build_fake_InLoadOrderModuleList(loaded_modules) - """ - myjit.vm.add_memory_page( - LDR_AD, PAGE_READ | PAGE_WRITE, "\x00" * MAX_MODULES * 0x1000) module_info = create_modules_chain(myjit, loaded_modules) fix_InLoadOrderModuleList(myjit, module_info) fix_InMemoryOrderModuleList(myjit, module_info) fix_InInitializationOrderModuleList(myjit, module_info) - ldr_data = build_fake_ldr_data(module_info) - myjit.vm.set_mem(LDR_AD, ldr_data) + build_ldr_data(myjit, module_info) add_process_env(myjit) add_process_parameters(myjit) - # myjit.vm.add_memory_page(in_load_order_module_list_address, - # PAGE_READ | PAGE_WRITE, p(0) * 40) - # myjit.vm.add_memory_page(in_load_order_module_list_address, - # PAGE_READ | PAGE_WRITE, build_fake_inordermodule(loaded_modules)) myjit.vm.add_memory_page(default_seh, PAGE_READ | PAGE_WRITE, pck32( 0xffffffff) + pck32(0x41414141) + pck32(0x42424242)) @@ -646,113 +449,105 @@ def init_seh(myjit): # http://www.codeproject.com/KB/system/inject2exe.aspx#RestorethefirstRegistersContext5_1 -def regs2ctxt(regs): - ctxt = "" - ctxt += '\x00\x00\x00\x00' # ContextFlags - ctxt += '\x00\x00\x00\x00' * 6 # drX - ctxt += '\x00' * 112 # float context - ctxt += '\x00\x00\x00\x00' + '\x3b\x00\x00\x00' + \ - '\x23\x00\x00\x00' + '\x23\x00\x00\x00' # segment selectors - ctxt += pck32(regs['EDI']) + pck32(regs['ESI']) + pck32(regs['EBX']) + \ - pck32(regs['EDX']) + pck32(regs['ECX']) + pck32(regs['EAX']) + \ - pck32(regs['EBP']) + pck32(regs['EIP']) # gpregs - ctxt += '\x23\x00\x00\x00' # cs - ctxt += '\x00\x00\x00\x00' # eflags - ctxt += pck32(regs['ESP']) # esp - ctxt += '\x23\x00\x00\x00' # ss segment selector - return ctxt - - -def ctxt2regs(ctxt): - ctxt = ctxt[:] - regs = {} - # regs['ctxtsflags'] = upck32(ctxt[:4]) - ctxt = ctxt[4:] - for i in xrange(8): - if i in [4, 5]: - continue - # regs['dr%d'%i] = upck32(ctxt[:4]) - ctxt = ctxt[4:] +def regs2ctxt(myjit): + """ + Build x86_32 cpu context for exception handling + @myjit: jitload instance + """ - ctxt = ctxt[112:] # skip float + ctxt = [] + # ContextFlags + ctxt += [pck32(0x0)] + # DRX + ctxt += [pck32(0x0)] * 6 + # Float context + ctxt += ['\x00' * 112] + # Segment selectors + ctxt += [pck32(reg) for reg in (myjit.cpu.GS, myjit.cpu.FS, + myjit.cpu.ES, myjit.cpu.DS)] + # Gpregs + ctxt += [pck32(reg) for reg in (myjit.cpu.EDI, myjit.cpu.ESI, + myjit.cpu.EBX, myjit.cpu.EDX, + myjit.cpu.ECX, myjit.cpu.EAX, + myjit.cpu.EBP, myjit.cpu.EIP)] + # CS + ctxt += [pck32(myjit.cpu.CS)] + # Eflags + # XXX TODO real eflag + ctxt += [pck32(0x0)] + # ESP + ctxt += [pck32(myjit.cpu.ESP)] + # SS + ctxt += [pck32(myjit.cpu.SS)] + return "".join(ctxt) + + +def ctxt2regs(ctxt, myjit): + """ + Restore x86_32 registers from an exception context + @ctxt: the serialized context + @myjit: jitload instance + """ - # regs['seg_gs'] = upck32(ctxt[:4]) + ctxt = ctxt[:] + # ContextFlags ctxt = ctxt[4:] - # regs['seg_fs'] = upck32(ctxt[:4]) + # DRX XXX TODO + ctxt = ctxt[4 * 6:] + # Float context XXX TODO + ctxt = ctxt[112:] + # gs + myjit.cpu.GS = upck32(ctxt[:4]) ctxt = ctxt[4:] - # regs['seg_es'] = upck32(ctxt[:4]) + # fs + myjit.cpu.FS = upck32(ctxt[:4]) ctxt = ctxt[4:] - # regs['seg_ds'] = upck32(ctxt[:4]) + # es + myjit.cpu.ES = upck32(ctxt[:4]) ctxt = ctxt[4:] - - regs['EDI'], regs['ESI'], regs['EBX'], regs['EDX'], regs['ECX'], regs[ - 'EAX'], regs['EBP'], regs['EIP'] = struct.unpack('I' * 8, ctxt[:4 * 8]) - ctxt = ctxt[4 * 8:] - - # regs['seg_cs'] = upck32(ctxt[:4]) + # ds + myjit.cpu.DS = upck32(ctxt[:4]) ctxt = ctxt[4:] - # regs['eflag'] = upck32(ctxt[:4]) + # Gpregs + myjit.cpu.EDI = upck32(ctxt[:4]) ctxt = ctxt[4:] - - regs['ESP'] = upck32(ctxt[:4]) + myjit.cpu.ESI = upck32(ctxt[:4]) + ctxt = ctxt[4:] + myjit.cpu.EBX = upck32(ctxt[:4]) + ctxt = ctxt[4:] + myjit.cpu.EDX = upck32(ctxt[:4]) + ctxt = ctxt[4:] + myjit.cpu.ECX = upck32(ctxt[:4]) + ctxt = ctxt[4:] + myjit.cpu.EAX = upck32(ctxt[:4]) + ctxt = ctxt[4:] + myjit.cpu.EBP = upck32(ctxt[:4]) + ctxt = ctxt[4:] + myjit.cpu.EIP = upck32(ctxt[:4]) ctxt = ctxt[4:] - for a, b in regs.items(): - print a, hex(b) - # skip extended - return regs - - -def get_free_seh_place(): - global all_seh_ad - ads = all_seh_ad.keys() - ads.sort() - for ad in ads: - v = all_seh_ad[ad] - if v is None: - print 'TAKING SEH', hex(ad) - all_seh_ad[ad] = True - return ad - raise ValueError('too many stacked seh ') - - -def free_seh_place(ad): - print 'RELEASING SEH', hex(ad) - - if not ad in all_seh_ad: - raise ValueError('zarb seh ad!', hex(ad)) - if all_seh_ad[ad] is not True: - # @wisk typolol - raise ValueError('seh alreaedy remouvede?!!', hex(ad)) - all_seh_ad[ad] = None + # CS + myjit.cpu.CS = upck32(ctxt[:4]) + ctxt = ctxt[4:] + # Eflag XXX TODO + ctxt = ctxt[4:] + # ESP + myjit.cpu.ESP = upck32(ctxt[:4]) + ctxt = ctxt[4:] def fake_seh_handler(myjit, except_code): - global seh_count + global seh_count, context_address regs = myjit.cpu.get_gpreg() - print '-> exception at', hex(myjit.cpu.EIP), seh_count + log.warning('Exception at %x %r', myjit.cpu.EIP, seh_count) seh_count += 1 # Help lambda p = lambda s: struct.pack('I', s) - # dump_gpregs_py() - # jitarch.dump_gpregs() # Forge a CONTEXT - ctxt = '\x00\x00\x00\x00' + '\x00\x00\x00\x00' * 6 + '\x00' * 112 - ctxt += '\x00\x00\x00\x00' + '\x3b\x00\x00\x00' + '\x23\x00\x00\x00' - ctxt += '\x23\x00\x00\x00' - ctxt += pck32(myjit.cpu.EDI) + pck32(myjit.cpu.ESI) + \ - pck32(myjit.cpu.EBX) + pck32(myjit.cpu.EDX) + \ - pck32(myjit.cpu.ECX) + pck32(myjit.cpu.EAX) + \ - pck32(myjit.cpu.EBP) + pck32(myjit.cpu.EIP) - ctxt += '\x23\x00\x00\x00' + '\x00\x00\x00\x00' + pck32(myjit.cpu.ESP) - ctxt += '\x23\x00\x00\x00' - # ctxt = regs2ctxt(regs) - - # Find a room for seh - # seh = (get_memory_page_max_address_py()+0x1000)&0xfffff000 + ctxt = regs2ctxt(myjit) # Get current seh (fs:[0]) seh_ptr = upck32(myjit.vm.get_mem(tib_address, 4)) @@ -761,13 +556,15 @@ def fake_seh_handler(myjit, except_code): old_seh, eh, safe_place = struct.unpack( 'III', myjit.vm.get_mem(seh_ptr, 0xc)) - print '-> seh_ptr', hex(seh_ptr), '-> { old_seh', - print hex(old_seh), 'eh', hex(eh), 'safe_place', hex(safe_place), '}' - # print '-> write SEH at', hex(seh&0xffffffff) + # Get space on stack for exception handling + myjit.cpu.ESP -= 0x3c8 + exception_base_address = myjit.cpu.ESP + exception_record_address = exception_base_address + 0xe8 + context_address = exception_base_address + 0xfc + fake_seh_address = exception_base_address + 0x14 - # Write current seh - # myjit.vm.add_memory_page(seh, PAGE_READ | PAGE_WRITE, p(old_seh) + - # p(eh) + p(safe_place) + p(0x99999999)) + log.info('seh_ptr %x { old_seh %x eh %x safe_place %x} ctx_addr %x', + seh_ptr, old_seh, eh, safe_place, context_address) # Write context myjit.vm.set_mem(context_address, ctxt) @@ -787,9 +584,9 @@ def fake_seh_handler(myjit, except_code): } EXCEPTION_RECORD, *PEXCEPTION_RECORD; """ - myjit.vm.set_mem(exception_record_address, pck32(except_code) + - pck32(0) + pck32(0) + pck32(myjit.cpu.EIP) + - pck32(0) + pck32(0)) + myjit.vm.set_mem(exception_record_address, + pck32(except_code) + pck32(0) + pck32(0) + + pck32(myjit.cpu.EIP) + pck32(0)) # Prepare the stack myjit.push_uint32_t(context_address) # Context @@ -798,15 +595,14 @@ def fake_seh_handler(myjit, except_code): myjit.push_uint32_t(return_from_exception) # Ret address # Set fake new current seh for exception - fake_seh_ad = get_free_seh_place() - print hex(fake_seh_ad) - myjit.vm.set_mem(fake_seh_ad, pck32(seh_ptr) + pck32( + log.info("Fake seh ad %x", fake_seh_address) + myjit.vm.set_mem(fake_seh_address, pck32(seh_ptr) + pck32( 0xaaaaaaaa) + pck32(0xaaaaaabb) + pck32(0xaaaaaacc)) - myjit.vm.set_mem(tib_address, pck32(fake_seh_ad)) + myjit.vm.set_mem(tib_address, pck32(fake_seh_address)) dump_seh(myjit) - print '-> jumping at', hex(eh) + log.info('Jumping at %x', eh) myjit.vm.set_exception(0) myjit.cpu.set_exception(0) @@ -819,18 +615,17 @@ fake_seh_handler.base = FAKE_SEH_B_AD def dump_seh(myjit): - print 'dump_seh:' - print '-> tib_address:', hex(tib_address) + log.info('Dump_seh. Tib_address: %x', tib_address) cur_seh_ptr = upck32(myjit.vm.get_mem(tib_address, 4)) indent = 1 loop = 0 while True: - if loop > 5: - print "too many seh, quit" + if loop > MAX_SEH: + log.warn("Too many seh, quit") return prev_seh, eh = struct.unpack('II', myjit.vm.get_mem(cur_seh_ptr, 8)) - print '\t' * indent + 'seh_ptr:', hex(cur_seh_ptr), - print ' -> { prev_seh:', hex(prev_seh), 'eh:', hex(eh), '}' + log.info('\t' * indent + 'seh_ptr: %x { prev_seh: %x eh %x }', + cur_seh_ptr, prev_seh, eh) if prev_seh in [0xFFFFFFFF, 0]: break cur_seh_ptr = prev_seh @@ -860,35 +655,29 @@ def return_from_seh(myjit): "Handle return after a call to fake seh handler" # Get current context + context_address = upck32(myjit.vm.get_mem(myjit.cpu.ESP + 0x8, 4)) + log.info('Context address: %x', context_address) myjit.cpu.ESP = upck32(myjit.vm.get_mem(context_address + 0xc4, 4)) - logging.info('-> new esp: %x', myjit.cpu.ESP) + log.info('New esp: %x', myjit.cpu.ESP) # Rebuild SEH old_seh = upck32(myjit.vm.get_mem(tib_address, 4)) new_seh = upck32(myjit.vm.get_mem(old_seh, 4)) - logging.info('-> old seh: %x', old_seh) - logging.info('-> new seh: %x', new_seh) + log.info('Old seh: %x New seh: %x', old_seh, new_seh) myjit.vm.set_mem(tib_address, pck32(new_seh)) dump_seh(myjit) - # Release SEH - free_seh_place(old_seh) - if myjit.cpu.EAX == 0x0: # ExceptionContinueExecution - print '-> seh continues' ctxt_ptr = context_address - print '-> context:', hex(ctxt_ptr) + log.info('Seh continues Context: %x', ctxt_ptr) # Get registers changes ctxt_str = myjit.vm.get_mem(ctxt_ptr, 0x2cc) - regs = ctxt2regs(ctxt_str) - myjit.pc = regs["EIP"] - for reg_name, reg_value in regs.items(): - setattr(myjit.cpu, reg_name, reg_value) - - logging.info('-> context::Eip: %x', myjit.pc) + ctxt2regs(ctxt_str, myjit) + myjit.pc = myjit.cpu.EIP + log.info('Context::Eip: %x', myjit.pc) elif myjit.cpu.EAX == -1: raise NotImplementedError("-> seh try to go to the next handler") |