我目前正在尝试将带有线程注入的代码洞穴注入到在我的 win7 (x64) 系统上运行的远程 win32 EXE。为此,我使用 Microsoft VB6,通过它我执行以下操作:
- OpenProcess,获取远程进程的句柄 [OK]
- VirtualAllocEx,在进程内部分配一些空间(以 PAGE_EXECUTE 保护和 MEM_COMMIT 作为参数。lpAddress 设置为 NULL 以便函数确定分配区域的位置)[OK,返回一个有效的偏移量]
- WriteProcessMemory,编写我的 shellcode [好的,实际上正确写入了字节,我已经检查过 CheatEngine/MemoryView]
- CreateRemoteThread,线程注入执行我的代码洞穴
- 我的目标 EXE(刚刚创建的远程线程的主机)此时崩溃(“exename”停止工作)
- WaitForSingleObject / CloseHandle / VirtualFreeEx
为了测试成功的代码注入,我试图注入一个什么都不做的shellcode。我对shellcoding和asm了解不多,但我才刚刚开始学习。
我尝试注入不同的代码,例如: - 只有 NOP(崩溃,但我假设它是正常的):\x90\x90\x90.. - 只有 NULL(与上面相同):\x00\x00\x00.. 但是我不明白的是,RETN 之后的 NOP 也会使我的目标 EXE 崩溃 \x90\x90\x90\xCB。我尝试注入的每个字节序列后跟一个 NULL 字节。
为什么我的目标进程崩溃?我必须注入什么字节序列才能执行不会使我的目标 EXE 崩溃的成功注入(但它什么也没做,只是为了测试注入方案)?
我最终想要做的是向游戏注入一个 PUSH x, CALL 目标函数。但是,如果我的虚拟 shellcode 使我的目标进程崩溃,我假设后一个字节序列也会崩溃。谢谢你的时间。
编辑:我得到的异常是 0xC0000005 [写入时访问冲突]
VB6 代码:只需使用目标 Exe 的 pid 作为参数调用 sub
Private Const PAGE_READWRITE As Long = &H4
Private Const PAGE_EXECUTE As Long = &H10
Private Const MEM_RELEASE As Long = &H8000
Private Const MEM_COMMIT As Long = &H1000
Private Const INFINITE As Long = &HFFFFFF
Public Const PROCESS_ALL_ACCESS As Long = &H1F0FFF
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Public Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Private Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Long, lpAddress As Any, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CreateRemoteThread Lib "kernel32" (ByVal hProcess As Long, lpThreadAttributes As Long, ByVal dwStackSize As Long, lpStartAddress As Long, lpParameter As Any, ByVal dwCreationFlags As Long, lpThreadId As Long) As Long
'Function that performs the shellcode injection to a remote process. Takes the target's PID as argument
Public Sub injectCode(ByVal lngPid As Long)
Dim RemThread As Long, LngModule As Long, LngProcess As Long
Dim i As Long
'The byte sequence we'll inject in the remote process (
Dim shellcode(4) As Byte
shellcode(0) = &H90 'NOP : just to pretend that it's actual code
shellcode(1) = &H90 'NOP : same
shellcode(2) = &HC2 'Near return to calling procedure and pop 4 bytes from stack.
shellcode(3) = &H4
shellcode(4) = 0 'NULL terminator
'OpenProcess, to get a handle to the remote process
LngProcess = OpenProcess(PROCESS_ALL_ACCESS, False, lngPid)
'to allocate some space inside of process (with PAGE_EXECUTE protection and MEM_COMMIT as parameter.
'lpAddress set to NULL so that the function determines where to allocate the region)
LngModule = VirtualAllocEx(LngProcess, 0, UBound(shellcode), MEM_COMMIT, PAGE_EXECUTE)
Debug.Print "VirtualAllocEx: " & Hex(LngModule) 'debug info
'writing our shellcode to the target's memory
For i = 0 To UBound(shellcode)
Call WriteProcessMemory(LngProcess, LngModule + i, shellcode(i), 1, 0&)
Next i
'thread injection to execute my code cave
RemThread = CreateRemoteThread(LngProcess, 0&, 0&, ByVal LngModule, 0&, 0&, ByVal 0&)
Debug.Print "CreateRemoteThread: " & Hex(RemThread) 'debug info
'wait for the thread to run
Call WaitForSingleObject(RemThread, INFINITE)
CloseHandle (RemThread)
Call VirtualFreeEx(LngProcess, LngModule, UBound(shellcode), MEM_RELEASE)
Debug.Print "DONE" 'debug info
End Sub
不过有些奇怪的事情发生了。当我在调用 CreateRemoteThread 之前出于调试目的放置 MsgBox(暂停执行)时,该函数返回一个非 NULL 句柄(但目标 EXE 崩溃)。如果我在调用 CreateRemoteThread 之前没有放置 Msgbox,则会返回一个 NULL 句柄。