def hook_StartServiceA(ql: Qiling, address: int, params): try: hService = params["hService"] service_handle = ql.os.handle_manager.get(hService) if service_handle.name == "amsint32": if service_handle.name in ql.os.services: service_path = ql.os.services[service_handle.name] service_path = ql.os.path.transform_to_real_path(service_path) ql.amsint32_driver = Qiling([service_path], ql.rootfs, verbose=QL_VERBOSE.DEBUG) init_unseen_symbols( ql.amsint32_driver, ql.amsint32_driver.loader.dlls["ntoskrnl.exe"] + 0xb7695, b"NtTerminateProcess", 0, "ntoskrnl.exe") #ql.amsint32_driver.debugger= ":9999" try: ql.amsint32_driver.load() return 1 except UcError as e: print("Load driver error: ", e) return 0 else: return 0 else: return 1 except Exception as e: ql.log.exception("") print(e)
def hook_StartServiceA(ql: Qiling, address: int, params): hService = params["hService"] service_handle = ql.os.handle_manager.get(hService) ql.test_set_api = True if service_handle.name == "amsint32": if service_handle.name in ql.os.services: service_path = ql.os.services[service_handle.name] service_path = ql.os.path.transform_to_real_path( service_path) ql.amsint32_driver = Qiling([service_path], ql.rootfs, verbose=QL_VERBOSE.DISASM) init_unseen_symbols( ql.amsint32_driver, ql.amsint32_driver.loader.dlls["ntoskrnl.exe"] + 0xb7695, b"NtTerminateProcess", 0, "ntoskrnl.exe") print("load amsint32_driver") try: ql.amsint32_driver.run() return 1 except UcError as e: print("Load driver error: ", e) return 0 else: return 0 else: return 1
except Exception as e: ql.log.exception("") print (e) def hook_stop_address(ql): print(" >>>> Stop address: 0x%08x" % ql.reg.arch_pc) ql.emu_stop() if __name__ == "__main__": ql = Qiling(["../examples/rootfs/x86_windows/bin/sality.dll"], "../examples/rootfs/x86_windows", output="debug") ql.libcache = True # for this module ql.amsint32_driver = None # emulate some Windows API ql.set_api("CreateThread", hook_CreateThread) ql.set_api("CreateFileA", hook_CreateFileA) ql.set_api("WriteFile", hook_WriteFile) ql.set_api("StartServiceA", hook_StartServiceA) #init sality ql.hook_address(hook_stop_address, 0x40EFFB) ql.run() # run driver thread ql.os.set_function_args([0]) ql.hook_address(hook_stop_address, 0x4055FA) ql.run(0x4053B2) ql.log.info("test kill thread") if ql.amsint32_driver: ql.amsint32_driver.os.io_Write(ql.pack32(0xdeadbeef))
def test_pe_win_x86_sality(self): def init_unseen_symbols(ql, address, name, ordinal, dll_name): ql.loader.import_symbols[address] = {"name": name, "ordinal": ordinal, "dll": dll_name.split('.')[0] } ql.loader.import_address_table[dll_name][name] = address if ordinal != 0: ql.loader.import_address_table[dll_name][ordinal] = address # HANDLE CreateThread( # LPSECURITY_ATTRIBUTES lpThreadAttributes, # SIZE_T dwStackSize, # LPTHREAD_START_ROUTINE lpStartAddress, # __drv_aliasesMem LPVOID lpParameter, # DWORD dwCreationFlags, # LPDWORD lpThreadId # ); @winsdkapi(cc=STDCALL, dllname='kernel32_dll') def hook_CreateThread(ql, address, params): # set thread handle return 1 # HANDLE CreateFileA( # LPCSTR lpFileName, # DWORD dwDesiredAccess, # DWORD dwShareMode, # LPSECURITY_ATTRIBUTES lpSecurityAttributes, # DWORD dwCreationDisposition, # DWORD dwFlagsAndAttributes, # HANDLE hTemplateFile # ); @winsdkapi(cc=STDCALL, dllname='kernel32_dll', replace_params={ "lpFileName": STRING, "dwDesiredAccess": DWORD, "dwShareMode": DWORD, "lpSecurityAttributes": POINTER, "dwCreationDisposition": DWORD, "dwFlagsAndAttributes": DWORD, "hTemplateFile": HANDLE }) def hook_CreateFileA(ql, address, params): lpFileName = params["lpFileName"] if lpFileName.startswith("\\\\.\\"): if ql.amsint32_driver: return 0x13371337 else: return (-1) else: ret = _CreateFile(ql, address, params, "CreateFileA") return ret def _WriteFile(ql, address, params): ret = 1 hFile = params["hFile"] lpBuffer = params["lpBuffer"] nNumberOfBytesToWrite = params["nNumberOfBytesToWrite"] lpNumberOfBytesWritten = params["lpNumberOfBytesWritten"] #lpOverlapped = params["lpOverlapped"] if hFile == 0xfffffff5: s = ql.mem.read(lpBuffer, nNumberOfBytesToWrite) ql.os.stdout.write(s) ql.os.utils.string_appearance(s.decode()) ql.mem.write(lpNumberOfBytesWritten, ql.pack(nNumberOfBytesToWrite)) else: f = ql.os.handle_manager.get(hFile) if f is None: # Invalid handle ql.os.last_error = 0xffffffff return 0 else: f = f.obj buffer = ql.mem.read(lpBuffer, nNumberOfBytesToWrite) f.write(bytes(buffer)) ql.mem.write(lpNumberOfBytesWritten, ql.pack32(nNumberOfBytesToWrite)) return ret @winsdkapi(cc=STDCALL, dllname='kernel32_dll', replace_params={ "hFile": HANDLE, "lpBuffer": POINTER, "nNumberOfBytesToWrite": DWORD, "lpNumberOfBytesWritten": POINTER, "lpOverlapped": POINTER }) def hook_WriteFile(ql, address, params): hFile = params["hFile"] lpBuffer = params["lpBuffer"] nNumberOfBytesToWrite = params["nNumberOfBytesToWrite"] lpNumberOfBytesWritten = params["lpNumberOfBytesWritten"] if hFile == 0x13371337: buffer = ql.mem.read(lpBuffer, nNumberOfBytesToWrite) try: r, nNumberOfBytesToWrite = ql.amsint32_driver.os.io_Write(buffer) ql.mem.write(lpNumberOfBytesWritten, ql.pack32(nNumberOfBytesToWrite)) except Exception: print("Error") r = 1 if r: return 1 else: return 0 else: return _WriteFile(ql, address, params) # BOOL StartServiceA( # SC_HANDLE hService, # DWORD dwNumServiceArgs, # LPCSTR *lpServiceArgVectors # ); @winsdkapi(cc=STDCALL, dllname='advapi32_dll') def hook_StartServiceA(ql, address, params): hService = params["hService"] service_handle = ql.os.handle_manager.get(hService) ql.test_set_api = True if service_handle.name == "amsint32": if service_handle.name in ql.os.services: service_path = ql.os.services[service_handle.name] service_path = ql.os.path.transform_to_real_path(service_path) ql.amsint32_driver = Qiling([service_path], ql.rootfs, verbose=QL_VERBOSE.DISASM) init_unseen_symbols(ql.amsint32_driver, ql.amsint32_driver.loader.dlls["ntoskrnl.exe"]+0xb7695, b"NtTerminateProcess", 0, "ntoskrnl.exe") print("load amsint32_driver") try: ql.amsint32_driver.run() return 1 except UcError as e: print("Load driver error: ", e) return 0 else: return 0 else: return 1 def hook_first_stop_address(ql): print(" >>>> First Stop address: 0x%08x" % ql.reg.arch_pc) ql.first_stop = True ql.emu_stop() def hook_second_stop_address(ql): print(" >>>> Second Stop address: 0x%08x" % ql.reg.arch_pc) ql.second_stop = True ql.emu_stop() ql = Qiling(["../examples/rootfs/x86_windows/bin/sality.dll"], "../examples/rootfs/x86_windows", verbose=QL_VERBOSE.DEBUG) ql.libcache = False ql.first_stop = False ql.second_stop = False self.third_stop = False # for this module ql.amsint32_driver = None # emulate some Windows API ql.set_api("CreateThread", hook_CreateThread) ql.set_api("CreateFileA", hook_CreateFileA) ql.set_api("WriteFile", hook_WriteFile) ql.set_api("StartServiceA", hook_StartServiceA) #init sality ql.hook_address(hook_first_stop_address, 0x40EFFB) ql.run() # run driver thread # execution is about to resume from 0x4053B2, which essentially jumps to ExitThread (kernel32.dll). # Set ExitThread exit code to 0 ql.os.fcall = ql.os.fcall_select(STDCALL) ql.os.fcall.writeParams(((DWORD, 0),)) ql.hook_address(hook_second_stop_address, 0x4055FA) ql.run(begin=0x4053B2) print("test kill thread") if ql.amsint32_driver: ql.amsint32_driver.os.utils.io_Write(ql.pack32(0xdeadbeef)) # TODO: Should stop at 0x10423, but for now just stop at 0x0001066a stop_addr = 0x0001066a ql.amsint32_driver.hook_address(self.hook_third_stop_address, stop_addr) # TODO: not sure whether this one is really STDCALL ql.amsint32_driver.os.fcall = ql.amsint32_driver.os.fcall_select(STDCALL) ql.amsint32_driver.os.fcall.writeParams(((DWORD, 0),)) ql.amsint32_driver.run(begin=0x102D0) self.assertEqual(True, ql.first_stop) self.assertEqual(True, ql.second_stop) self.assertEqual(True, self.third_stop) self.assertEqual(True, ql.test_set_api)