Three Ways to Inject Your the Code into another process article mentions some of the techniques of a subclass window process after a successful injection. The author allocates a heap of memory and then copies the thread parameters and thread functions next to the heap memory, and finally CreateRemoteThread runs the thread function. The author of this way to get thread parameters can only be self-locating through remote threads. I'm so lazy. It is possible to pass the required parameters directly to the remote thread as CreateRemoteThread parameters, although not verified, but it should be possible.
The author's article was reproduced so many times, he mentioned the technique does not try a bit throwaway feeling, so there is this article.
This article still step by step, all of a sudden write the right code feeling less frustration, but also more in line with the law of human progress, and this at the same time recorded their own mistakes.
Note that the incremental connection and/GZ options need to be removed from the project setup
1) first on the intuitive code, of course, the error is running.
Listing 1:
#include <stdafx.h> #include <windows.h> #include <stdio.h> #include <assert.h> #include <
string.h> typedef HANDLE (*open) (Lpctstr,dword,dword,lpsecurity_attributes,dword,dword,handle);
typedef BOOL (*read) (handle,lpvoid,dword,lpdword,lpoverlapped);
typedef BOOL (*write) (handle,lpvoid,dword,lpdword,lpoverlapped);
typedef DWORD (*func) (void*); #define ERRERS 1 #define PATHLEN #define PROLOGUE 0x23 #define FUNCOFFSET 0x44 #define Structlen sizeof (Injcode) #defin E openprocessproity process_create_thread| process_query_information| process_vm_operation| process_vm_write|
Process_vm_read struct Injcode {char filepath[pathlen]; Func func1;
Writefunc};
void Minorfunc () {__asm {int 0x03;
}} void Afterminorfunc () {} DWORD FuncV1 (void* args) {injcode* injcode;
Injcode = (injcode*) minorfunc;
injcode--; (INJCODE->FUNC1)
();
return 0;
} DWORD Aftermajorfunc (void* args) {return 0;}
injcode* Injcode; int main () {printf ("Funcv1:%p\n ", FuncV1);
DWORD Pid,dwthreadid;
DWORD Writtennum,readnum;
injcode* Injcode;
file* fp = fopen ("C:\\pid.txt", "r+");
ASSERT (FP);
FSCANF (FP, "%d", &pid);
Fclose (FP);
HANDLE REMOTEPROGHD = OpenProcess (openprocessproity,false,pid);
DWORD Funclen = ((DWORD) aftermajorfunc-(DWORD) FuncV1) + ((DWORD) afterminorfunc-(DWORD) minorfunc);
Injcode = (injcode*) VirtualAllocEx (remoteproghd,null,sizeof (Injcode) +funclen,mem_commit,page_execute_readwrite);
The intention is to give the result of Injcode->filepath assignment: //Read Injcode variable, causing unusual access way strcpy (Injcode->filepath, "abc"); Also causes exceptions <pre name= "code" class= "CPP" > injcode->func1=funcv1;
return 0;}
Code at the beginning to see no problem, debugging run, the program runs to
strcpy (Injcode->filepath, "abc");
Inevitable error, see WinDbg output, C0000005, while DT Injcode allocated memory also has the wrong hint:
It took a long time to find the root knot:
Injcode = (injcode*) VirtualAllocEx (remoteproghd,null,sizeof (Injcode) +funclen,mem_commit,page_execute_readwrite);
VirtualAllocEx successfully returns, Injcode points to the memory area (0X00000AC0) in the target process, the same address may not be allocated in this process or have no corresponding access, if access causes an error. In this code, the program attempts to read the memory value at the 0ac0 of the process, and from the WinDbg output the memory should not be allocated and therefore an exception occurs.
Remember that Injcode points to the memory area of the remote thread. Therefore, read and write operations on any memory allocated by VirtualAllocEx (Remotehandle) can only be accessed by read/writeprocessmemory to access the individual members of the remote struct variable.
Let's say you create a remote process variable with VirtualAllocEx, it's easy to understand ~
2) on the correct main function version, the correct way to assign values to the INJCODE structure variables:
List 2)
#include <stdafx.h> #include <windows.h> #include <stdio.h> #include <assert.h> #include <
string.h> typedef HANDLE (*open) (Lpctstr,dword,dword,lpsecurity_attributes,dword,dword,handle);
typedef BOOL (*read) (handle,lpvoid,dword,lpdword,lpoverlapped);
typedef BOOL (*write) (handle,lpvoid,dword,lpdword,lpoverlapped);
typedef DWORD (*func) (void*); #define ERRERS 1 #define PATHLEN #define PROLOGUE 0x23 #define FUNCOFFSET 0x44 #define Structlen sizeof (Injcode) #defin E openprocessproity process_create_thread| process_query_information| process_vm_operation| process_vm_write|
Process_vm_read struct Injcode {char filepath[pathlen];//+0x00 func func1;//+0x40 func func2;//+0x44};
void Minorfunc () {__asm {int 0x03;
}} void Afterminorfunc () {} DWORD Majorfunc (void* args) {injcode* injcode;
Injcode = (injcode*) majorfunc;
injcode--; (INJCODE->FUNC2)
(NULL);
return 0;
} #if 0 DWORD FuncV2 (void* args) {injcode* injcode;
__asm {call Cureip; CurEip:pop eax;
The starting sub Eax,prologue pointing to the Writefunc;
The Injcode starting sub eax,funcoffset that points to the heap allocation;
MOV injcode,eax;
} return 0;
} #endif DWORD Aftermajorfunc (void* args) {return 0;}
injcode* Injcode;
int main () {DWORD pid,dwthreadid;
DWORD Writtennum,readnum;
injcode* Injcode;
file* fp = fopen ("C:\\pid.txt", "r+");
ASSERT (FP);
FSCANF (FP, "%d", &pid);
Fclose (FP);
HANDLE REMOTEPROGHD = OpenProcess (openprocessproity,false,pid); The length of the main function and the called function, first storing majorfunc, followed by minorfunc DWORD Funclen = ((DWORD) aftermajorfunc-(DWORD) majorfunc) + ((DWORD)
afterminorfunc-(DWORD) minorfunc);
Injcode = (injcode*) VirtualAllocEx (remoteproghd,null,sizeof (Injcode) +funclen,mem_commit,page_execute_readwrite);
Injcode!+0x40 Func1, which holds the main function pointer DWORD func1addr = ((DWORD) ((char*) injcode) +0x40);
Injcode!+0x44 Func2 is located, storing the function pointer DWORD func2addr = ((DWORD) ((char*) injcode) +0x44);
DWORD majorfuncbase = ((DWORD) ((char*) injcode) +sizeof (Injcode)); DWORD minorfuncbase = ((DWORD) ((char*) injcode) +sizeoF (Injcode) + ((DWORD) aftermajorfunc-(DWORD) majorfunc));
WriteProcessMemory (REMOTEPROGHD, ((char*) injcode) +0x00, "C:\\1.txt", strlen ("C:\\1.txt"), &writtennum); Injcode!func1=majorfunc WriteProcessMemory (REMOTEPROGHD, (char*) func1addr,&majorfuncbase,sizeof (DWORD),
&writtennum); Injcode!func2=minorfunc WriteProcessMemory (REMOTEPROGHD, (char*) func2addr,&minorfuncbase,sizeof (DWORD),
&writtennum); copy function to remote process writeprocessmemory (REMOTEPROGHD, (char*) Majorfuncbase,majorfunc, ((DWORD) aftermajorfunc-(DWORD)
Majorfunc), &writtennum); WriteProcessMemory (REMOTEPROGHD, (char*) Minorfuncbase,minorfunc, ((DWORD) afterminorfunc-(DWORD) minorfunc),&
Writtennum); HANDLE Remotethread = CreateRemoteThread (remoteproghd,null,0, (Lpthread_start_routine) ((char*) MajorFuncBase), NULL,
0,&dwthreadid);
WaitForSingleObject (Remotethread, INFINITE);
return 0; }
Compile run, the values of the individual members in the Injcode variable have been successfully updated to the target process:
You can see that b50000 +40 + 44 is the address value of two functions, and then look at the functions on these two addresses:
However, after running the CreateRemoteThread, the injected process runs to call ECX and then goes wrong.
Go back to the code Majorfunc:
<pre name= "code" class= "CPP" > injcode* injcode;
Injcode = (injcode*) majorfunc;
injcode--;
The corresponding opcode are:
List 3)
mov dword ptr [ebp-4],401030h
mov eax,dword ptr [ebp-4]
Majorfunc is translated to 401030, absolute address, and more importantly, 401030 is in the address space of the injection process, which may not necessarily be in the address space of the target process, thus causing access errors. The code runs in other process space, and the address is not sure, how to get the Injcode address. This uses the thread to self-locate, the remote thread obtains the memory address of the current instruction, subtracts the offset, and finally navigates to the starting address of the Injcode. Because the function that the thread runs is in the memory space allocated by Injcode, and next to the Injcode variable, it is not easy to modify the modification offset to find a starting address.
List 4) End version:
Redirect.cpp:Defines the entry point for the console application. #include <stdafx.h> #include <windows.h> #include <stdio.h> #include <assert.h> #include <
string.h> typedef HANDLE (*open) (Lpctstr,dword,dword,lpsecurity_attributes,dword,dword,handle);
typedef BOOL (*read) (handle,lpvoid,dword,lpdword,lpoverlapped);
typedef BOOL (*write) (handle,lpvoid,dword,lpdword,lpoverlapped);
typedef DWORD (*func) (void*); #define ERRERS 1 #define PATHLEN #define PROLOGUE 0x0e #define FUNCOFFSET 0x48 #define Structlen sizeof (Injcode) #defin E openprocessproity process_create_thread| process_query_information| process_vm_operation| process_vm_write|
Process_vm_read struct Injcode {char filepath[pathlen];//+0x00 func func1;//+0x40 func func2;//+0x44};
void Minorfunc () {__asm {int 0x03;
}} void Afterminorfunc () {} DWORD Majorfunc (void* args) {injcode* injcode;
__asm {call Cureip;
Cureip:pop eax;
The starting sub Eax,prologue pointing to the Writefunc; Point to heap allocationThe Injcode starting sub eax,funcoffset;
MOV injcode,eax;
} (INJCODE->FUNC2) (NULL);
return 0;
} DWORD Aftermajorfunc (void* args) {return 0;}
injcode* Injcode;
int main () {DWORD pid,dwthreadid;
DWORD Writtennum,readnum;
injcode* Injcode;
file* fp = fopen ("C:\\pid.txt", "r+");
ASSERT (FP);
FSCANF (FP, "%d", &pid);
Fclose (FP);
HANDLE REMOTEPROGHD = OpenProcess (openprocessproity,false,pid); The length of the main function and the called function, first storing majorfunc, followed by minorfunc DWORD Funclen = ((DWORD) aftermajorfunc-(DWORD) majorfunc) + ((DWORD)
afterminorfunc-(DWORD) minorfunc);
Injcode = (injcode*) VirtualAllocEx (remoteproghd,null,sizeof (Injcode) +funclen,mem_commit,page_execute_readwrite);
Injcode!+0x40 Func1, which holds the main function pointer DWORD func1addr = ((DWORD) ((char*) injcode) +0x40);
Injcode!+0x44 Func2 is located, storing the function pointer DWORD func2addr = ((DWORD) ((char*) injcode) +0x44);
DWORD majorfuncbase = ((DWORD) ((char*) injcode) +sizeof (Injcode)); DWORD Minorfuncbase = ((DWORD) ((char*) injcode) +sizeof (Injcode) + ((DWORD) aftermajorfunc-(DWORD) MaJorfunc));
WriteProcessMemory (REMOTEPROGHD, ((char*) injcode) +0x00, "C:\\1.txt", strlen ("C:\\1.txt"), &writtennum); Injcode!func1=majorfunc WriteProcessMemory (REMOTEPROGHD, (char*) func1addr,&majorfuncbase,sizeof (DWORD),
&writtennum); Injcode!func2=minorfunc WriteProcessMemory (REMOTEPROGHD, (char*) func2addr,&minorfuncbase,sizeof (DWORD),
&writtennum); copy function to remote process writeprocessmemory (REMOTEPROGHD, (char*) Majorfuncbase,majorfunc, ((DWORD) aftermajorfunc-(DWORD)
Majorfunc), &writtennum); WriteProcessMemory (REMOTEPROGHD, (char*) Minorfuncbase,minorfunc, ((DWORD) afterminorfunc-(DWORD) minorfunc),&
Writtennum); HANDLE Remotethread = CreateRemoteThread (remoteproghd,null,0, (Lpthread_start_routine) ((char*) MajorFuncBase), NULL,
0,&dwthreadid);
WaitForSingleObject (Remotethread, INFINITE);
return 0; }
Run Minorfunc results after injection:
After jumping to 0xb50078:
Run smoothly into the minorfunc.
This is the end of the full text.