def _createInjectedStubs_remote_thread(self, dll, mem): """Allocate memory, create an ASM stub, copy strings and code into the target and executed via CreateRemoteThread(). This stub has five goals: - AllocConsole: This gives us a new console in the target process. - LoadLibraryA: This is used to load the pydetour dll into the process. - GetProcAddress: This is used to find our target exported function from within the above DLL. - Launch python code: Call the exported function, passing the path of the bootstrap function. - Return exit status via ExitThread. This function returns a dictionary of allocation points in the remote process. High level description of ASM function:: def InjectedStub(): kernel32.AllocConsole() hModule = kernel32.LoadLibraryA(dll) if not hModule: ExitThread(errors['ll_failed']) rpf = kernel32.GetProcAddress(hModule, "run_python_file") if not rpf: ExitThread(errors['gpc_failed']) ret = rpf(Paths.inside_bootstrap_py) ExitThread(ret) """ errors = TargetLauncher.ERROR_CODES_NAMED alloc = {} alloc['pyPath'] = mem.allocWrite(Paths.inside_bootstrap_py) alloc['dllPath'] = mem.allocWrite(dll) alloc['dllFunc'] = mem.allocWrite("run_python_file") alloc['executionPoint'] = mem.alloc(None, 128) #we need about 123 bytes hM = kernel32.GetModuleHandleA("kernel32.dll") from util.buffer import ASMBuffer buf = ASMBuffer(128) #buf.INT3() #Debugger trap #--------------------------------------------------------------------- buf.movEAX_Addr(kernel32.GetProcAddress(hM, "AllocConsole")) buf.callEAX() #AllocConsole() #--------------------------------------------------------------------- buf.pushAddr(alloc['dllPath']) buf.movEAX_Addr(kernel32.GetProcAddress(hM, "LoadLibraryA")) buf.callEAX() #hModule to dll -> EAX buf.cmpEAX_Byte(0x0) buf.namedJNZ("ll_success") if True: #buf.movEAX_Addr(kernel32.GetProcAddress(hM, "GetLastError")) #buf.callEAX() #GetLastError #buf.pushEAX() buf.pushDword(errors['ll_failed']) #PUSH 0x1 (thread exit code) 1 = LoadLibrary Failed buf.movEAX_Addr(kernel32.GetProcAddress(hM, "ExitThread")) buf.callEAX() #This cleanly exits the thread #--------------------------------------------------------------------- buf.nameTarget("ll_success") buf.pushAddr(alloc['dllFunc']) buf.pushEAX() #PUSH EAX (hModule to dll) buf.movEAX_Addr(kernel32.GetProcAddress(hM, "GetProcAddress")) buf.callEAX() #dllFunc() address -> EAX buf.cmpEAX_Byte(0x0) buf.namedJNZ("gpa_success") if True: buf.pushDword(errors['gpc_failed']) #PUSH thread exit code 'GetProcAddress Failed' buf.movEAX_Addr(kernel32.GetProcAddress(hM, "ExitThread")) buf.callEAX() #This cleanly exits the thread #--------------------------------------------------------------------- buf.nameTarget("gpa_success") buf.pushAddr(1) #turns on pdb debugging buf.pushAddr(alloc['pyPath']) buf.callEAX() #This calls our run_python_code script buf.addESP(8) buf.cmpEAX_Byte(0x0) buf.namedJZ("run_success") if True: #run_python_code failed, return it's error code buf.pushEAX() buf.movEAX_Addr(kernel32.GetProcAddress(hM, "ExitThread")) buf.callEAX() #This cleanly exits the thread #--------------------------------------------------------------------- buf.nameTarget("run_success") #buf.INT3() buf.pushByte(0) #PUSH 0x0 (thread exit code, success) buf.movEAX_Addr(kernel32.GetProcAddress(hM, "ExitThread")) buf.callEAX() #This cleanly exits the thread buf.push([0xCC, 0xCC, 0xCC, 0xCC, 0xCC]) #Debugger trap buf.push([0xCC, 0xCC, 0xCC, 0xCC, 0xCC]) #Debugger trap buf.verifyJumps() log.debug("Stub is %s bytes."%(buf.cursor)) mem.write(alloc['executionPoint'], buf.buf.raw) return alloc
def _createInjectedStubs_doubleapc(self, dll, mem, parent_wait, child_wait): """Allocate memory, create an ASM stub, copy strings and code into the target. This stub has five goals: - AllocConsole: This gives us a new console in the target process. - LoadLibraryA: This is used to load the pydetour dll into the process. - GetProcAddress: This is used to find our target exported function from within the above DLL. - Launch python code: Call the exported function, passing the path of the bootstrap function. - Replace entry point with the bytes we grabbed - Return exit status (?somehow) This function returns a dictionary of allocation points in the remote process. High level description of ASM function:: def InjectedStub(): kernel32.AllocConsole() hModule = kernel32.LoadLibraryA(dll) if not hModule: ExitThread(errors['ll_failed']) rpf = kernel32.GetProcAddress(hModule, "run_python_file") if not rpf: ExitThread(errors['gpc_failed']) ret = rpf(Paths.inside_bootstrap_py) return """ errors = TargetLauncher.ERROR_CODES_NAMED alloc = {} alloc['pyPath'] = mem.allocWrite(Paths.inside_bootstrap_py) alloc['dllPath'] = mem.allocWrite(dll) alloc['dllFunc'] = mem.allocWrite("run_python_file") alloc['parent_wait'] = mem.allocWrite(parent_wait) alloc['child_wait'] = mem.allocWrite(child_wait) alloc['executionPoint'] = mem.alloc(None, 256) alloc['secondAPC'] = mem.alloc(None, 256) hM = kernel32.GetModuleHandleA("kernel32.dll") hM_ntdll = kernel32.GetModuleHandleA("ntdll.dll") from util.buffer import ASMBuffer if True: #This stub is the /second/ apc to run buf = ASMBuffer(256) #--------------------------------------------------------------------- #--------------------------------------------------------------------- #--------------------------------------------------------------------- buf.callEAX(kernel32.GetProcAddress(hM, "AllocConsole")) #--------------------------------------------------------------------- buf.pushAddr(alloc['dllPath']) buf.callEAX(kernel32.GetProcAddress(hM, "LoadLibraryA")) #hModule to dll -> EAX buf.cmpEAX_Byte(0x0) buf.namedJNZ("ll_success") if True: buf.callEAX(kernel32.GetProcAddress(hM, "GetLastError")) buf.INT3() #buf.pushEAX() buf.pushDword(errors['ll_failed']) #PUSH 0x1 (thread exit code) 1 = LoadLibrary Failed #buf.movEAX_Addr(kernel32.GetProcAddress(hM, "ExitThread")) buf.popEAX() buf.namedJMP("exit") #--------------------------------------------------------------------- buf.nameTarget("ll_success") buf.pushAddr(alloc['dllFunc']) buf.pushEAX() #PUSH EAX (hModule to dll) buf.callEAX(kernel32.GetProcAddress(hM, "GetProcAddress")) buf.cmpEAX_Byte(0x0) buf.namedJNZ("gpa_success") if True: buf.INT3() buf.pushDword(errors['gpc_failed']) #PUSH thread exit code 'GetProcAddress Failed' #buf.movEAX_Addr(kernel32.GetProcAddress(hM, "ExitThread")) buf.popEAX() buf.namedJMP("exit") #--------------------------------------------------------------------- buf.nameTarget("gpa_success") buf.pushAddr(1) #turns on pdb debugging buf.pushAddr(alloc['pyPath']) buf.callEAX() #This calls our run_python_code script buf.addESP(8) buf.cmpEAX_Byte(0x0) buf.namedJZ("run_success") if True: buf.INT3() #run_python_code failed, return it's error code buf.pushEAX() #buf.movEAX_Addr(kernel32.GetProcAddress(hM, "ExitThread")) buf.popEAX() buf.namedJMP("exit") #--------------------------------------------------------------------- buf.nameTarget("run_success") buf.nameTarget("exit", allowFlowThrough=True) self._asmbuf_setevent(buf, hM, alloc['parent_wait']) #Tell the parent to go ahead self._asmbuf_waitevent(buf, hM, alloc['child_wait']) #Wait until parent gives us the go ahead buf.ret(3*4) #APC is passed 3 params buf.push([0xCC, 0xCC, 0xCC, 0xCC, 0xCC]) #Debugger trap buf.push([0xCC, 0xCC, 0xCC, 0xCC, 0xCC]) #Debugger trap buf.verifyJumps() log.debug("Second APC stub is %s bytes."%(buf.cursor)) mem.write(alloc['secondAPC'], buf.buf.raw) if True: #This stub is the /first/ apc to run #--------------------------------------------------------------------- #--------------------------------------------------------------------- from util.buffer import ASMBuffer bufapc = ASMBuffer(256) bufapc.INT3() #This is skipped over by scheduling the first apc at +1 self._asmbuf_waitevent(bufapc, hM, alloc['child_wait']) #Wait until the parent gives us the go ahead bufapc.pushDword(0) bufapc.pushDword(0) bufapc.pushDword(0) bufapc.pushAddr(alloc['secondAPC']) bufapc.callEAX(kernel32.GetProcAddress(hM, "GetCurrentThread")) bufapc.pushEAX() bufapc.callEAX(kernel32.GetProcAddress(hM_ntdll, "NtQueueApcThread")) bufapc.ret(3*4) mem.write(alloc['executionPoint'], bufapc.buf.raw) return alloc