assembly - 为什么使用线程注入注入代码洞穴会使我的目标 win32 EXE 崩溃?
问题描述
我目前正在尝试将带有线程注入的代码洞穴注入到在我的 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 句柄。
解决方案
ThreadProc
传递给的回调CreateRemoteThread
接受一个LPVOID
参数并且ThreadProc
是__stdcall
.
LPVOID
参数 for是从'sThreadProc
转发的。CreateRemoteThread
LPVOID lpParameter
在 x86 上,这意味着您需要放置RET
指令以便从堆栈中释放四个字节。
(也ThreadProc
返回 DWORD,这意味着你应该EAX
在返回之前返回值,但如果你不关心返回值,你可以跳过它)
另外,CB 是远回报,你需要使用近回报。
寻找RETN imm opcode,看起来你需要C2 04 00
推荐阅读
- reporting - Aerospike 报告要求 | 需要每小时频繁扫描
- javascript - 根据源对象是否具有具有特定值的深层嵌套属性,有条件地渲染 JSX 元素
- laravel - 在2个表中插入数据,最后插入父表的ID也必须插入到子表中
- python - PIP、请求和其他的 Python SSL 问题
- python - 使用 Python 将语言转换为国家代码
- python - 我有一个长字符串“AAAAA ...”。如何找到最短的图案“A”?
- java - Hibernate - 按 OneToMany-Relationship 排序
- javascript - Getinfo 仅返回插入的第一个封面
- java - Servlet 仅针对默认的 switch case 调用
- c - 使用 libcurl 将文件流式传输到 HTTP 服务器