| View previous topic :: View next topic |
| Author |
Message |
talkerzero Grandmaster Cheater
Reputation: 1
Joined: 24 Jul 2008 Posts: 560 Location: California
|
Posted: Fri May 22, 2009 12:49 am Post subject: [?] Injecting code into external process (NEW QUESTION) |
|
|
I'm trying to use WriteProcessMemory() to inject my code into another process at an address allocated by VirtualAllocEx, so I can call it with CreateRemoteThread(). Is this how I should do it?
(edit) Here's my new code. The target process keeps crashing when inject_thread() reaches CreateRemoteThread(), any idea why?
| Code: | #pragma check_stack (off)
int MainThread()
{
return DialogBox(hInst, MAKEINTRESOURCE(IDD_DIALOG1), NULL, (DLGPROC)DlgProc);
}
void after_thread_func(void){}
#pragma check_stack
DWORD get_process_pid(char *psname)
{
DWORD pid = 0;
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hSnap == INVALID_HANDLE_VALUE)
return 0;
PROCESSENTRY32 pe;
pe.dwSize = sizeof(pe);
BOOL bResult = Process32First(hSnap, &pe);
while(Process32Next(hSnap, &pe))
if( ! strcmp(pe.szExeFile, psname))
pid = pe.th32ProcessID;
CloseHandle(hSnap);
return pid;
}
#define MSG(x) MessageBox(NULL, x, "lol", MB_OK)
int inject_thread(DWORD dwPID)
{
int ret = 0;
HANDLE hProcess = NULL;
LPVOID remote_mem = NULL;
try
{
if((hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, dwPID)) == NULL)
throw 1;
MSG("we're at 1!");
remote_mem = VirtualAllocEx(hProcess, NULL,
(SIZE_T)((char *)after_thread_func - (char *)MainThread),
MEM_COMMIT, PAGE_READWRITE);
if(remote_mem == NULL)
throw 2;
MSG("we're at 2!");
BOOL wFlag = WriteProcessMemory(hProcess, remote_mem, (char *)MainThread,
(SIZE_T)((char *)after_thread_func - (char *)MainThread), (SIZE_T *)0);
if(wFlag == FALSE)
throw 3;
MSG("we're at 3!");
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)remote_mem, 0, 0, NULL);
if(hThread == NULL)
throw 4;
MSG("we're at 4!");
if(WaitForSingleObject(hThread, 10 * 1000) == WAIT_TIMEOUT)
throw 5;
MSG("we're at 5!");
CloseHandle(hThread);
} catch(int err) {
if(err > 2)
VirtualFreeEx(hProcess, remote_mem, 0, MEM_RELEASE);
ret = err;
}
CloseHandle(hProcess);
return ret;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
int nRet = inject_thread(get_process_pid("process.exe"));
char szBuffer[5];
MessageBox(NULL, _itoa(nRet, szBuffer, 10), "inject_thread returned: ", MB_OK);
return EXIT_SUCCESS;
} |
Last edited by talkerzero on Fri May 22, 2009 7:58 pm; edited 7 times in total |
|
| Back to top |
|
 |
hcavolsdsadgadsg I'm a spammer
Reputation: 26
Joined: 11 Jun 2007 Posts: 5801
|
Posted: Fri May 22, 2009 1:21 am Post subject: |
|
|
| First off: you never actually get the handle to the process you're trying to write too, you're just returning the process ID. Use OpenProcess to get it.
|
|
| Back to top |
|
 |
talkerzero Grandmaster Cheater
Reputation: 1
Joined: 24 Jul 2008 Posts: 560 Location: California
|
Posted: Fri May 22, 2009 8:49 am Post subject: |
|
|
| slovach wrote: | | First off: you never actually get the handle to the process you're trying to write too, you're just returning the process ID. Use OpenProcess to get it. |
My mistake, it was 12 at night and I was tired. But is this how I would inject my code into the process & create the remote thread?
|
|
| Back to top |
|
 |
hcavolsdsadgadsg I'm a spammer
Reputation: 26
Joined: 11 Jun 2007 Posts: 5801
|
Posted: Fri May 22, 2009 4:16 pm Post subject: |
|
|
| See what GetLastError() has to say about it, I'll read it over in a bit.
|
|
| Back to top |
|
 |
talkerzero Grandmaster Cheater
Reputation: 1
Joined: 24 Jul 2008 Posts: 560 Location: California
|
Posted: Fri May 22, 2009 7:58 pm Post subject: |
|
|
| slovach wrote: | | See what GetLastError() has to say about it, I'll read it over in a bit. |
The function is executing successfully but the target process is crashing. (when I call CreateRemoteThread)
|
|
| Back to top |
|
 |
dnsi0 I post too much
Reputation: 0
Joined: 04 Jan 2007 Posts: 2674
|
Posted: Fri May 22, 2009 8:00 pm Post subject: |
|
|
| talker0 wrote: | | slovach wrote: | | See what GetLastError() has to say about it, I'll read it over in a bit. |
The function is executing successfully but the target process is crashing. (when I call CreateRemoteThread) |
I believe you have to copy the ENTIRE code over including the variables. You need to set the image base high up so that code that have stataic values don't get messed up or unless you want to correct all the variables.
Right now you have .CODE copied over but no variables. So... what happens when you access inaccessable memory?
|
|
| Back to top |
|
 |
talkerzero Grandmaster Cheater
Reputation: 1
Joined: 24 Jul 2008 Posts: 560 Location: California
|
Posted: Fri May 22, 2009 8:02 pm Post subject: |
|
|
| dnsi0 wrote: | | talker0 wrote: | | slovach wrote: | | See what GetLastError() has to say about it, I'll read it over in a bit. |
The function is executing successfully but the target process is crashing. (when I call CreateRemoteThread) |
I believe you have to copy the ENTIRE code over ... |
Are you fucking serious?
|
|
| Back to top |
|
 |
dnsi0 I post too much
Reputation: 0
Joined: 04 Jan 2007 Posts: 2674
|
Posted: Fri May 22, 2009 8:04 pm Post subject: |
|
|
| talker0 wrote: | | dnsi0 wrote: | | talker0 wrote: | | slovach wrote: | | See what GetLastError() has to say about it, I'll read it over in a bit. |
The function is executing successfully but the target process is crashing. (when I call CreateRemoteThread) |
I believe you have to copy the ENTIRE code over ... |
Are you fucking serious? |
Is there a problem? I have tried injecting code before.
|
|
| Back to top |
|
 |
Dark Byte Site Admin
Reputation: 473
Joined: 09 May 2003 Posts: 25918 Location: The netherlands
|
Posted: Fri May 22, 2009 8:10 pm Post subject: |
|
|
perhaps the call to DialogBox happens from a defered call using a IAT table, which you havn't copied to the exact same location as your injector program.
Perhaps the target process doesn't have a resource named IDD_DIALOG1 , or at least not the same resourceID
Perhaps the address of DlgProc isn't the same as in the target process
In short, the approach you're taking to inject a piece of code into the target its wrong. The method you're using does not allow function calling of any kind. (Sure you can do it by reading the relocation table of your injector to find out what addresses are relative and then change them after injection, and filling in the IAT table, but I think there are easier methods
edit: this is what dnsi says)
I recommend the following:
Write your MainThread in a seperate dll
Then inject that dll by calling CreateRemoteThread on the address of LoadLibrary with as parameter the address of a string with the full path to that dll. (written to the target process with WriteProcessMemory)
Then in the dll entrypoint do what you want
_________________
Tools give you results. Knowledge gives you control.
Like my help? Join me on Patreon so i can keep helping |
|
| Back to top |
|
 |
hcavolsdsadgadsg I'm a spammer
Reputation: 26
Joined: 11 Jun 2007 Posts: 5801
|
Posted: Fri May 22, 2009 8:41 pm Post subject: |
|
|
Yep, you never use LoadLibrary(), which you will need for the method you're using. You want to allocate memory for your path string with VirtualAllocEx(), then write it with WriteProcessMemory().
Use GetProcAddress() to get the address of LoadLibrary() and finally call CreateRemoteThread().
|
|
| Back to top |
|
 |
dnsi0 I post too much
Reputation: 0
Joined: 04 Jan 2007 Posts: 2674
|
Posted: Sat May 23, 2009 6:59 am Post subject: |
|
|
| Dark Byte wrote: | perhaps the call to DialogBox happens from a defered call using a IAT table, which you havn't copied to the exact same location as your injector program.
Perhaps the target process doesn't have a resource named IDD_DIALOG1 , or at least not the same resourceID
Perhaps the address of DlgProc isn't the same as in the target process
In short, the approach you're taking to inject a piece of code into the target its wrong. The method you're using does not allow function calling of any kind. (Sure you can do it by reading the relocation table of your injector to find out what addresses are relative and then change them after injection, and filling in the IAT table, but I think there are easier methods
edit: this is what dnsi says)
I recommend the following:
Write your MainThread in a seperate dll
Then inject that dll by calling CreateRemoteThread on the address of LoadLibrary with as parameter the address of a string with the full path to that dll. (written to the target process with WriteProcessMemory)
Then in the dll entrypoint do what you want |
Hey darkbyte, a while ago I tried "EXE Injection" which was copying the entire code of the app you are currently on and executing a function in injected exe. (The image base is set really high so it doesn't overlap with any existing code). However, If you try to create a dialog it crashes which some people told me it was because delphi sucks at creating dialogs and its hInst is still what it was on the old app. So Is there a way to fix this? (Like if you try to do messagebox() it will work perfectly).
|
|
| Back to top |
|
 |
Dark Byte Site Admin
Reputation: 473
Joined: 09 May 2003 Posts: 25918 Location: The netherlands
|
Posted: Sat May 23, 2009 7:48 am Post subject: |
|
|
Why not just change the .dpr from program to library, and then compile.
That way it'll inject a lot better and works easier as well. (dialogs and forms work fine, e.g look at the injected pointer scan of ce, or the packet editor plugin example)
Anyhow, if you insist on .exe injection:
don't just copy the memory of the currently running executable to the target process. You don't want to copy the initialized data sections that then contain initialized pointers to structures. (e.g the code "if windowpointer=nil then createwindow else usewindow;" will mess up)
You will have to read from the binary .exe (and hope the compiler didn't strip out the relocation table, which is usually not used for .exe's so can be removed to save a few kb of space)
Then read the PE header to find out which sections there are, and allocate the memory regions accordingly with proper protection.
Then copy the physical memory of the exe to the virtual memory regions (note that they don't map 1 on 1)
And then try running the entry point. I don't know if it'll work, as resources and a hinstance might be problematic, but with some luck it'll launch
But again, just compiling the program as a .DLL fixes a lot of problems.
And in case you never noticed, with one simple define in the ce sourcecode (ceasinjectabledll) you can make Cheat Engine itself compile as a dll
_________________
Tools give you results. Knowledge gives you control.
Like my help? Join me on Patreon so i can keep helping |
|
| Back to top |
|
 |
dnsi0 I post too much
Reputation: 0
Joined: 04 Jan 2007 Posts: 2674
|
Posted: Sat May 23, 2009 1:14 pm Post subject: |
|
|
| Dark Byte wrote: | Why not just change the .dpr from program to library, and then compile.
That way it'll inject a lot better and works easier as well. (dialogs and forms work fine, e.g look at the injected pointer scan of ce, or the packet editor plugin example)
Anyhow, if you insist on .exe injection:
don't just copy the memory of the currently running executable to the target process. You don't want to copy the initialized data sections that then contain initialized pointers to structures. (e.g the code "if windowpointer=nil then createwindow else usewindow;" will mess up)
You will have to read from the binary .exe (and hope the compiler didn't strip out the relocation table, which is usually not used for .exe's so can be removed to save a few kb of space)
Then read the PE header to find out which sections there are, and allocate the memory regions accordingly with proper protection.
Then copy the physical memory of the exe to the virtual memory regions (note that they don't map 1 on 1)
And then try running the entry point. I don't know if it'll work, as resources and a hinstance might be problematic, but with some luck it'll launch
But again, just compiling the program as a .DLL fixes a lot of problems.
And in case you never noticed, with one simple define in the ce sourcecode (ceasinjectabledll) you can make Cheat Engine itself compile as a dll |
I know that dll injection works like 10000000000% better than exe injection but I just wanted to try it out because it didn't have any dll files for it.
|
|
| Back to top |
|
 |
talkerzero Grandmaster Cheater
Reputation: 1
Joined: 24 Jul 2008 Posts: 560 Location: California
|
Posted: Sat May 23, 2009 4:55 pm Post subject: |
|
|
| I've already thought of DLL injection and don't wish to use it.
|
|
| Back to top |
|
 |
sponge I'm a spammer
Reputation: 1
Joined: 07 Nov 2006 Posts: 6009
|
|
| Back to top |
|
 |
|