Abyx Asked:2020-11-29 06:02:25 +0000 UTC2020-11-29 06:02:25 +0000 UTC 2020-11-29 06:02:25 +0000 UTC 将代码注入新进程 772 例如,如何启动一个进程(x32)并在其中执行一些代码MessageBoxA(0, "Hi", 0, 0)? windows 2 个回答 Voted Best Answer Abyx 2020-11-29T06:02:25Z2020-11-29T06:02:25Z C++ (MSVC) 中的示例,使用RtlRemoteCall: #include <windows.h> #include <iostream> typedef DWORD __stdcall RtlRemoteCall_t( HANDLE Process, HANDLE Thread, PVOID CallSite, ULONG ArgumentCount, PULONG Arguments, BOOL PassContext, BOOL AlreadySuspended); HMODULE ntdll = ::GetModuleHandleA("ntdll"); auto pRtlRemoteCall = (RtlRemoteCall_t*)::GetProcAddress(ntdll, "RtlRemoteCall"); void inject(HANDLE hProcess, HANDLE hThread) { char* shellcode_start; char* shellcode_end; __asm { mov shellcode_start, offset shellcode_start_label mov shellcode_end, offset shellcode_end_label jmp shellcode_end shellcode_start_label: mov ebx, esp // compiler would warn if we'd use EBP // [ebx + 0] context address (added by RtlRemoteCall) // [ebx + 4] arg0: NtContinue address // [ebx + 8] arg1: MessageBoxA address // MessageBoxA(0, "Hi", 0, 0) push 0 push 0 call hi_end_label _emit 'H' _emit 'i' _emit 0 hi_end_label: push 0 call dword ptr[ebx + 8] // NtContinue(ctx, 0) push 0 push dword ptr[ebx + 0] call dword ptr[ebx + 4] shellcode_end_label: } auto shellcode_size = shellcode_end - shellcode_start; void* remote_ptr = ::VirtualAllocEx(hProcess, nullptr, shellcode_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); std::cout << "remote_ptr = " << remote_ptr << '\n'; ::WriteProcessMemory(hProcess, remote_ptr, shellcode_start, shellcode_size, nullptr); ULONG args[] = { (ULONG)::GetProcAddress(ntdll, "NtContinue"), (ULONG)::GetProcAddress(::LoadLibraryA("user32"), "MessageBoxA"), }; pRtlRemoteCall(hProcess, hThread, remote_ptr, _countof(args), args, true, true); ::ResumeThread(hThread); } int main() { wchar_t cmd[] = LR"(c:\Windows\SysWOW64\notepad.exe)"; PROCESS_INFORMATION process_info; STARTUPINFOW startup_info; ::GetStartupInfoW(&startup_info); ::CreateProcessW(cmd, cmd, nullptr, nullptr, FALSE, CREATE_SUSPENDED, nullptr, nullptr, &startup_info, &process_info); inject(process_info.hProcess, process_info.hThread); } 为简化代码,删除了错误处理和关闭句柄。 Abyx 2020-05-30T22:23:31Z2020-05-30T22:23:31Z 与 C++ 中的想法相同,但现在Python3用于 x32 import binascii, ctypes, struct def run_and_inject(target_path, code): si = (ctypes.c_byte * 68)(0) ctypes.windll.kernel32.GetStartupInfoW(si) cmd = ctypes.c_wchar_p(target_path) CREATE_SUSPENDED = 4 pi = (ctypes.c_void_p * 4)(0) ctypes.windll.kernel32.CreateProcessW(cmd, cmd, 0, 0, False, CREATE_SUSPENDED, 0, 0, si, pi) MEM_COMMIT = 0x1000 PAGE_EXECUTE_READWRITE = 0x40 addr = ctypes.windll.kernel32.VirtualAllocEx(pi[0], 0, len(code), MEM_COMMIT, PAGE_EXECUTE_READWRITE) ctypes.windll.kernel32.WriteProcessMemory(pi[0], addr, code, len(code), 0) ctypes.windll.ntdll.RtlRemoteCall(pi[0], pi[1], addr, 0, 0, True, True) ctypes.windll.kernel32.ResumeThread(pi[1]) def hex2code(code_hex): return binascii.a2b_hex(code_hex.replace(' ', '').encode()) def push_string(str_bytes): return struct.pack('<BI', 0xE8, len(str_bytes) + 1) + str_bytes + b'\0' def call(func): addr = ctypes.cast(func, ctypes.c_void_p).value return struct.pack('<BIBB', 0xB8, addr, 0xFF, 0xD0) code = hex2code( # [esp + 0] is the context address (added by RtlRemoteCall) '89 E5' # mov ebp, esp # MessageBoxA(0, "Injected message", 0, 0) '6A 00' # push 0 '6A 00' # push 0 ) + push_string(b'Injected message') + hex2code( '6A 00' # push 0 ) + call(ctypes.windll.user32.MessageBoxA) + hex2code( # NtContinue(ctx, 0) '6A 00' # push 0 'FF 75 00' # push dword[ebp+0] ) + call(ctypes.windll.ntdll.NtContinue) run_and_inject(r'c:\Windows\SysWOW64\notepad.exe', code)
C++ (MSVC) 中的示例,使用
RtlRemoteCall:为简化代码,删除了错误处理和关闭句柄。
与 C++ 中的想法相同,但现在Python3用于 x32