为什么通过线程注入来注入代码洞穴会使我的目标win32 EXE崩溃?

时间:2019-03-03 09:41:09

标签: assembly vb6 shellcode createremotethread codecave

我当前正在尝试将带有线程注入的代码漏洞注入到在我的win7(x64)系统上运行的远程win32 EXE。 为此,我正在使用Microsoft VB6,通过它我可以执行以下操作:

  • OpenProcess,以获取远程进程的句柄[确定]
  • VirtualAllocEx,在进程内部分配一些空间(使用PAGE_EXECUTE保护和MEM_COMMIT作为参数。lpAddress设置为NULL,以便函数确定将区域分配到的位置)[确定,返回一个 有效偏移量]
  • WriteProcessMemory,写我的shellcode [好,实际上写正确的字节,我已经用CheatEngine / MemoryView检查过了]
  • CreateRemoteThread,执行我的代码洞穴的线程注入[确定,返回一个不为NULL的句柄,我的远程线程据说成功 已创建]
  • 我的目标EXE(刚创建的远程线程的主机)在此时崩溃('exename'停止运行)
  • WaitForSingleObject / CloseHandle / VirtualFreeEx

为了测试成功的代码注入,我尝试注入不执行任何操作的shellcode。我对shellcoding和asm不太了解,但是我才刚刚开始学习。

我尝试注入不同的代码,例如: -仅NOP(崩溃,但我认为这是正常的):\ x90 \ x90 \ x90。 -仅NULL(与上面相同):\ x00 \ x00 \ x00 .. 但是我不明白的是,NOP后面跟着RETN会使我的目标EXE以及\ x90 \ x90 \ x90 \ xCB崩溃。 我尝试注入的每个字节序列后面都有一个NULL字节。

为什么我的目标进程崩溃?为了执行不使目标EXE崩溃的成功注入(我只是为了测试注入方案而没有做任何事情),我必须注入什么字节序列?

我最终想要做的是向游戏注入PUSH x,CALL目标功能。但是,如果我的虚拟shellcode崩溃了我的目标进程,我就假设后者的字节序列也将崩溃。 感谢您的宝贵时间。

编辑:我得到的异常是0xC0000005 [写入时发生访问冲突]

VB6代码:只需使用目标Exe的pid作为参数调用子

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句柄。

1 个答案:

答案 0 :(得分:2)

传递给ThreadProc

CreateRemoteThread回调采用一个LPVOID参数,而ThreadProc__stdcall

LPVOID的{​​{1}}转发ThreadProc

CreateRemoteThread参数。

在x86上,这意味着您需要放入LPVOID lpParameter指令,以便从堆栈中释放四个字节。

(也RET返回DWORD,这意味着您应该在返回之前将值返回到ThreadProc,但是如果您不关心返回值,则可以跳过它)

此外,CB属于远收益,您需要使用近收益。

寻找RETN imm 操作码,看起来您需要EAX