Reputation: 11
I am currently trying to inject a code cave with thread injection to a remote win32 EXE running on my win7 (x64) system. To achieve this, I am using Microsoft VB6, through which I do the following:
For the sake of testing a successful code injection, I am trying to inject a shellcode that does nothing. I don't know much about shellcoding and asm, but I just started learning.
I've tried injecting different codes, like: - only NOPs (crashes but I'm assuming it's normal): \x90\x90\x90.. - only NULLs (same as above): \x00\x00\x00.. However what I don't understand is that NOPs followed by RETN crashes my target EXE aswell \x90\x90\x90\xCB. Every byte sequence I have tried injecting was followed by a NULL byte.
Why does my target process crash ? What byte sequence do I have to inject in order to perform a succesful injection that doesn't crash my target EXE (yet that doesn't do anything, just for the sake of testing the injection scheme) ?
What I want to end up doing is injecting a PUSH x, CALL targetfunction to a game. But if my dummy shellcode crashes my target process I'm assuming the latter byte sequence would too. Thanks for your time.
EDIT: The exception I get is 0xC0000005 [Access violation when writing]
VB6 Code: Just call the sub with the target Exe's pid as argument
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
Something weird happens though. When I put a MsgBox (that pauses the execution) for debug purposes BEFORE calling CreateRemoteThread, the function returns a non-NULL handle (but the target EXE crashes). And if I don't put a Msgbox before calling CreateRemoteThread, a NULL handle is returned.
Upvotes: 1
Views: 1004
Reputation: 13719
ThreadProc
callback passed to CreateRemoteThread
takes one LPVOID
parameter and ThreadProc
is __stdcall
.
LPVOID
parameter for ThreadProc
is forwarded from CreateRemoteThread
's LPVOID lpParameter
.
On x86 it means that you need to put RET
instruction such that frees four bytes from stack.
(Also ThreadProc
returns DWORD, this means you should but return value to EAX
before returning, but if you don't care about return value, you may skip it)
Additionally, CB is far return, you need to use near return.
Look for RETN imm opcode, looks like you need C2 04 00
Upvotes: 3