Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


[?] Injecting code into external process (NEW QUESTION)
Goto page 1, 2  Next
 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming
View previous topic :: View next topic  
Author Message
talkerzero
Grandmaster Cheater
Reputation: 1

Joined: 24 Jul 2008
Posts: 560
Location: California

PostPosted: Fri May 22, 2009 12:49 am    Post subject: [?] Injecting code into external process (NEW QUESTION) Reply with quote

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
View user's profile Send private message Visit poster's website
hcavolsdsadgadsg
I'm a spammer
Reputation: 26

Joined: 11 Jun 2007
Posts: 5801

PostPosted: Fri May 22, 2009 1:21 am    Post subject: Reply with quote

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
View user's profile Send private message
talkerzero
Grandmaster Cheater
Reputation: 1

Joined: 24 Jul 2008
Posts: 560
Location: California

PostPosted: Fri May 22, 2009 8:49 am    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
hcavolsdsadgadsg
I'm a spammer
Reputation: 26

Joined: 11 Jun 2007
Posts: 5801

PostPosted: Fri May 22, 2009 4:16 pm    Post subject: Reply with quote

See what GetLastError() has to say about it, I'll read it over in a bit.
Back to top
View user's profile Send private message
talkerzero
Grandmaster Cheater
Reputation: 1

Joined: 24 Jul 2008
Posts: 560
Location: California

PostPosted: Fri May 22, 2009 7:58 pm    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
dnsi0
I post too much
Reputation: 0

Joined: 04 Jan 2007
Posts: 2674

PostPosted: Fri May 22, 2009 8:00 pm    Post subject: Reply with quote

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. Laughing

Right now you have .CODE copied over but no variables. So... what happens when you access inaccessable memory?
Back to top
View user's profile Send private message
talkerzero
Grandmaster Cheater
Reputation: 1

Joined: 24 Jul 2008
Posts: 560
Location: California

PostPosted: Fri May 22, 2009 8:02 pm    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
dnsi0
I post too much
Reputation: 0

Joined: 04 Jan 2007
Posts: 2674

PostPosted: Fri May 22, 2009 8:04 pm    Post subject: Reply with quote

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
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 473

Joined: 09 May 2003
Posts: 25918
Location: The netherlands

PostPosted: Fri May 22, 2009 8:10 pm    Post subject: Reply with quote

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
View user's profile Send private message MSN Messenger
hcavolsdsadgadsg
I'm a spammer
Reputation: 26

Joined: 11 Jun 2007
Posts: 5801

PostPosted: Fri May 22, 2009 8:41 pm    Post subject: Reply with quote

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
View user's profile Send private message
dnsi0
I post too much
Reputation: 0

Joined: 04 Jan 2007
Posts: 2674

PostPosted: Sat May 23, 2009 6:59 am    Post subject: Reply with quote

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
View user's profile Send private message
Dark Byte
Site Admin
Reputation: 473

Joined: 09 May 2003
Posts: 25918
Location: The netherlands

PostPosted: Sat May 23, 2009 7:48 am    Post subject: Reply with quote

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
View user's profile Send private message MSN Messenger
dnsi0
I post too much
Reputation: 0

Joined: 04 Jan 2007
Posts: 2674

PostPosted: Sat May 23, 2009 1:14 pm    Post subject: Reply with quote

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
View user's profile Send private message
talkerzero
Grandmaster Cheater
Reputation: 1

Joined: 24 Jul 2008
Posts: 560
Location: California

PostPosted: Sat May 23, 2009 4:55 pm    Post subject: Reply with quote

I've already thought of DLL injection and don't wish to use it.
Back to top
View user's profile Send private message Visit poster's website
sponge
I'm a spammer
Reputation: 1

Joined: 07 Nov 2006
Posts: 6009

PostPosted: Sat May 23, 2009 10:53 pm    Post subject: Reply with quote

http://www.woodmann.com/collaborative/tools/index.php/ManualMap
_________________
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites