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 


C# Code Relocation / VirtualAll CreateRemoteThread confusion
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
FreewareFire
Newbie cheater
Reputation: 0

Joined: 27 Mar 2013
Posts: 14

PostPosted: Fri Dec 02, 2016 12:37 pm    Post subject: C# Code Relocation / VirtualAll CreateRemoteThread confusion Reply with quote

Hey out there,

as my prevoiusly problem can not be solved i tried to find another solution.
My Problem is: The game i try to hack is updated regulary and with every Update my Base Address and my Pointers get broken. That's bad. I can't search 50 Values every 2 Weeks from scratch. My idea yet was to get into the called (asm) code and relocate the called code to my own memory address where i can read out the memory address i where looking for.

The asm code is
mov [rdi+00000188],rdx

The idea... replace the original code with my own to jmp to a new created memory place created with VirtualAlloc. But i'm confused. I can't really find an example what i had to do, btw. i'm unsure what's the best solution to achieve my goal. Another approach would be to inject my own dll and send the value from rdi to my trainer. But i'm not sure if that's possible.

Can someone give me a drive into the right direction? What's the best solution?

The best solution (i think) would be to grab the value from rdi to my trainer where i could use it then.

As mentioned i try to get that working with C#.

Thank you for any help, suggestions or codes Wink

Btw this Forum is Great!
Back to top
View user's profile Send private message
ulysse31
Master Cheater
Reputation: 2

Joined: 19 Mar 2015
Posts: 324
Location: Paris

PostPosted: Fri Dec 02, 2016 1:24 pm    Post subject: Reply with quote

This can be done with DLL injection or with simple readprocmemory/writeprocmemory.
IF you chose DLL injection you can use pattern scanning to find your instruction :
https://www.youtube.com/watch?v=mKUSLJjlajg

inject dll
use pattern sig scan to get code address
allocate memory (from dll)
hook the original code found with pattern scan and redirect it to allocated memory, save edi somewhere, send the code back to its original location.

You could use code cave instead of memory allocation but your code would be less patch proof.
Back to top
View user's profile Send private message
FreewareFire
Newbie cheater
Reputation: 0

Joined: 27 Mar 2013
Posts: 14

PostPosted: Fri Dec 02, 2016 2:03 pm    Post subject: Reply with quote

@ulysse31

hmmm. Ok, that's what i thought, but how do i allocate memory to the game? I thought i can directly use VirtualAlloc from C# Source to allocate new memory (without inject a dll). If i understand correctly, VirtualAlloc allocates new memory in the game itself and i can access that new allocated memory address as it's returned by VirtualAlloc?. That's what i understand if i'm right (but also can crash the game too?). That's why i'm confused. What's with CreateRemoteThread? I don't really understand the different approaches really. If i use the VirtualAlloc version: Allocate new memory in the game, search for the byte pattern, replace the original code with a jmp condition to the new created memory (the returned address from VirtualAlloc) where i can store the original code, the value from edi and then jmp back to the original code... Correctly?

As it's a 64 bit game, i can't use fasm.net as it's 32 bit only... That's what i thought first Smile

Difficult to me as i see only half solutions, no explainations - reading the past 2 days different Websites but had no idea what's the best solution.

Greets
Back to top
View user's profile Send private message
ulysse31
Master Cheater
Reputation: 2

Joined: 19 Mar 2015
Posts: 324
Location: Paris

PostPosted: Fri Dec 02, 2016 3:18 pm    Post subject: Reply with quote

Yes you can use VirtualAllocEx to allcoate memory inside the game from your own process.
VirtualAlloc can only allocate memory inside the calling process so only the injected dll could call that for the mentioned purpose.
If you inject a DLL you'll need to use CreateRemoteThreadEx to make the game start your dll, as mentioned in video.
If you chose not to inject a dll you can have the same result with virtualallocex and u wont need to use createremotethread. However the code will be ugly and the work won't resist patch that well (sort of).
I just think dll injection is better as you'll be able to use c# code from within the process which is fairly strong and cleaner than writing arrays of bytes to get them executed as code later.
Also in the video i linked both dll injection with createthread and pattern scanning are taken care off so thats like 60% of the work. All that's left for you to do is alloc memory, calculate the byte jumps and save edi.

NB : some WINAPIs have another version of themselves with "Ex" extension which means they can be used from a calling process A to operate on a process B, this is the case for virtualAlloc
Back to top
View user's profile Send private message
FreewareFire
Newbie cheater
Reputation: 0

Joined: 27 Mar 2013
Posts: 14

PostPosted: Sat Dec 03, 2016 10:37 am    Post subject: Reply with quote

Ok, well i made a little step further. Now i'm able to use VirtualAllocEx to add memory. Also it returns me the memory address where VirtualAllocEx added the memory. Fine so far. But in fact it doesn't make any sense Razz

What i was going to get is just the value of rdi.

mov [rdi+00000188],rdx

Do i really need to allocate memory, relocate the original code to it to store the value from rdi there? Isn't there a easier way to get just the value from rdi?

Also i can't get the idea with CreateRemoteThread. I can't find any example that makes sense to me. The value stored at rdi+00000188 is the money value. There's no base pointer i can catch so i thought it would be another try to get rdi. As said i use C#. Nearly everything is just C or C++ and the examples don't do anything - they just inject DLL but how do the game now to call my injected dll - and what should my dll do? I mean how can the injected dll read the value from rdi then... I've looked the video but he's just speaking about it, not showing it. It sounds so OP to me to just get a value Shocked

Do you or someone have some code or snippets to get me on the right track? I'm more and more confused as i read articles and viewing videos.
Back to top
View user's profile Send private message
ulysse31
Master Cheater
Reputation: 2

Joined: 19 Mar 2015
Posts: 324
Location: Paris

PostPosted: Sat Dec 03, 2016 11:12 am    Post subject: Reply with quote

I'll poste you code (c++) that I wrote 2 years ago while hacking MMO, I was doing my first steps therefore it doesn't look good but does the job.
It gets game handle by name (Tera.exe), injects StealLoginKey.dll and retrieves login ticket (you ll get RDI).
get handle :
Code:
void GetHandle() {
   cout << "Waiting for TERA.exe to launch.." << endl;
   while (!hWnd)
   {
         hWnd = FindWindow(0, ("TERA"));
         if (hWnd == 0)
            Sleep(1);
         else
            cout << "window found." << endl;
      Sleep(200);

   }
   GetWindowThreadProcessId(hWnd, &teraID);
   if (teraID == 0)
      cout << "failed to get process ID." << endl;
   else
      cout << "Retrieved process Id." << endl;
   hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, teraID);
   if (hProc == 0)
      cout << "can't retrieve handle" << endl;
   else
      cout << "handle retrieved" << endl;
}


Now allocate memory inside game to write dll name, put dll in the TERA.exe executable folder (ie ur game exe folder) and createthread to make the game load the dll :

Code:
void InjectDll(char *chDllName) {
   AddressOfAllocatedMem = VirtualAllocEx(hProc, 0, 4000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
   if (AddressOfAllocatedMem == 0)
      cout << "could not allocate memory" << endl;
   else
      cout << "Memory allocated" << endl;
   WriteProcessMemory(hProc, AddressOfAllocatedMem, chDllName, strlen(chDllName), NULL);
   HMODULE hKernel32 = GetModuleHandle("Kernel32");
   HANDLE localHandle = CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryA"), AddressOfAllocatedMem, 0, 0);
   if (localHandle == 0)
      cout << "couldn't create thread" << endl;
   else
      cout << "thread created" << " adress of string is : " << AddressOfAllocatedMem << endl;

}


call it all :
Code:
      GetHandle();
      char chDllName[] = "StealLogInKeyDll.dll";
      InjectDll(chDllName);


Now what your dll will do: scan pattern, hook, get rdi, i ll just poste my code (my dll hooked the encryption function which held a login key given by launcher to my mmo client, my dll gave this key to my program and shut the client down) which is a big longer as the dll did more work.

Code:

#include "stdafx.h"
#include <Windows.h>
#include <string>
#include <fstream>
#include <iostream>
#include "Pattern.h"
#include <vector>
HWND hWnd(0);
using namespace std;
HANDLE hProc;
DWORD teraID;
char chDllName[] = "StealLogInKeyDll.dll";
char TeraModule[] = "TERA.exe";
char sigpattern[] = "\x8b\xf1\x8b\x06\x8b\x40\x18\xff\xd0\x84\xc0\x75\x05\x5e\x5d\xc2\x08\x00\xff\x75\x0c\x8d\x8e\x0c\x01\x00\x00\xFF\x75\x08\xe8\x6d\xd9\x2b\xf4";
char mask[] = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx????";
LPVOID AddressOfAllocatedMem;
DWORD dwAllocatedAddress;
DWORD foundAddress;
DWORD foundAddress2;
DWORD encryptionAddr = 0x0183E980;
void GetHandle() {
   cout << "Waiting for TERA.exe to launch.." << endl;
   while (!hWnd)
   {
         hWnd = FindWindow(0, ("TERA"));
         if (hWnd == 0)
            Sleep(1);
         else
            cout << "window found." << endl;
      Sleep(200);

   }
   GetWindowThreadProcessId(hWnd, &teraID);
   hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, teraID);
   if (hProc == 0)
      cout << "can't retrieve handle" << endl;
   else
      cout << "handle retrieved" << endl;
}
void InjectDll() {
   AddressOfAllocatedMem = VirtualAllocEx(hProc, NULL, 0, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
   WriteProcessMemory(hProc, AddressOfAllocatedMem, chDllName, sizeof(chDllName), NULL);
   HMODULE hKernel32 = GetModuleHandle("Kernel32");
   CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryA"), AddressOfAllocatedMem, 0, 0);
}

__declspec (naked) void HookEncryption() {
   _asm {
         push eax
         push ebx
         mov eax, [ebp + 0x08]
         mov ebx,0x00434256
         mov [ebx], eax
         push ecx
         mov ecx,520
         mov dword ptr [ebx + 0x08],0x10
      loop1:
         dec ecx
         push ecx
         push 200
         call Sleep
         pop ecx
         cmp[ebx + 04], 04
         je skip2
         cmp ecx, 00
         jne loop1
      skip1:
         pop ecx
         pop ebx
         pop eax
         call encryptionAddr
         jmp foundAddress2
      skip2:
         push 1
            call exit
   }
}

void MsgBoxAddy(DWORD addy)
{
   char szBuffer[1024];
   sprintf(szBuffer, "Addy: %02x", addy);
   MessageBox(NULL, szBuffer, "Title", MB_OK);

}

BOOL WINAPI DllMain(
   _In_ HINSTANCE hinstDLL,
   _In_ DWORD     Reason,
   _In_ LPVOID    lpvReserved
   ) {
   switch (Reason)
   {
   case DLL_PROCESS_ATTACH:
      //MsgBoxAddy(foundAddress);
      foundAddress = FindPattern(TeraModule, mask, sigpattern, 2);
      foundAddress += 30;
      //MsgBoxAddy(foundAddress);
      foundAddress2 = foundAddress + 5; // because cpu reads 5 byte opcode before processing hook and is further down code line.
      void (*Address)() = HookEncryption;
      char szbuffer[1024];
      unsigned int difference;
      if (foundAddress2 > (int)Address)
         difference = foundAddress2 - (int)Address;
      else
         difference = (int)Address - foundAddress2;
      sprintf(szbuffer, "Allocated Mem is at : %02x", (int)Address);
      //MessageBox(NULL, szbuffer, "Title", MB_OK);
      sprintf(szbuffer, "Distance is : %02x", difference);
      //MessageBox(NULL, szbuffer, "Title", MB_OK);
      char chHookEncryption[5];
      chHookEncryption[0] = '\xE9';
      chHookEncryption[1] = (difference >> 0) & (0xFF);
      chHookEncryption[2] = (difference >> 8) & (0xFF);
      chHookEncryption[3] = (difference >> 16) & (0xFF);
      chHookEncryption[4] = (difference >> 24) & (0xFF);
      HANDLE procHandle = GetCurrentProcess();
      WriteProcessMemory(procHandle, (LPVOID)foundAddress, &chHookEncryption, sizeof(chHookEncryption), NULL);
      break;
   }
   return true;
}


the header of the dll :
Code:
#include "stdafx.h"
#include <Windows.h>
#include <string>
#include <fstream>
#include <iostream>
#include <Psapi.h>
DWORD FindPattern(char * moduleName, char * mask, char * patternLookedFor, int nNumberMatch) {
   HANDLE procHandle = GetCurrentProcess();
   HMODULE proHandle = GetModuleHandle("TERA.exe");
   MODULEINFO modinfo;
   bool bAbool = GetModuleInformation(procHandle, proHandle, &modinfo, sizeof(modinfo));
   int size = modinfo.SizeOfImage;
   int BaseAddress = (int)modinfo.lpBaseOfDll;
   DWORD BaseAddress2 = (DWORD)modinfo.lpBaseOfDll;
   //the aim of this is to find the second address which maches the conditions, for this reason we use a for loop istead of a while loop
   
   for (int i = 0; i < size - strlen(patternLookedFor); i++)
   {
      bool ConditionsMet = 1;
      for (int j = 0; (j < strlen(patternLookedFor)) && (ConditionsMet ==1); ++j)
      {
         ConditionsMet &= ((*(char*)(i + BaseAddress + j) == patternLookedFor[j]) | (mask[j] == '?'));
      }
      if (ConditionsMet)
      {
         if (nNumberMatch == 1)
            return BaseAddress + i;
         else
            nNumberMatch -= 1;
      }
   }
   return 0;
   
}


Is this too much work for what you want to do ?
1/No, this is very little work, learn it once, make it 100 times in a matter of minutes.
2/ Can you do it quicker ? why allocate memory and hook ?
Well, if you can afford to simply overwrite gameinstructions (which you really souldn't do because the game will then have unexpected behaviour), you could overwrite those instructions by something like
mov rax,02040302
mov [rax],rdi
considering 02040302 is a code cave address
then you nop the bytes from the original game instruction that were left as it was (because likely what you overwrite doesn't have the exact same byte size as what you newly wrote).
Then with your .exe program you read the byte at address 02040302 inside the game (readprocessmemory)


Last edited by ulysse31 on Sat Dec 03, 2016 11:21 am; edited 1 time in total
Back to top
View user's profile Send private message
FreewareFire
Newbie cheater
Reputation: 0

Joined: 27 Mar 2013
Posts: 14

PostPosted: Sat Dec 03, 2016 11:20 am    Post subject: Reply with quote

Thank you so much! I'm gonna read it carefully to copy over to C#. The dll Part is the one i gonna research intensively Smile Very Happy

Very nice!!
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 198

Joined: 25 Jan 2006
Posts: 8517
Location: 127.0.0.1

PostPosted: Sat Dec 03, 2016 1:15 pm    Post subject: Reply with quote

If you are injected into the target process, you do not need to use things like WriteProcessMemory/ReadProcessMemory/VirtualAllocEx and so on.

You can read and write memory simply via direct casting to addresses. Which removes a handful of overhead from the two API. (Plus additional calls to get other info that those APIs need.)

You can use VirtualAlloc instead of VirtualAllocEx as you are not targeting a remote process.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
FreewareFire
Newbie cheater
Reputation: 0

Joined: 27 Mar 2013
Posts: 14

PostPosted: Sat Dec 03, 2016 5:05 pm    Post subject: Reply with quote

Ok, what i got so far is: Alloc new memory and inject my DLL - as it's injected it shows a message box that it was successfull. Ok, that's really good Smile

And now comes the part i don't get. How the hell can i now get the value from rdi? Let's say the code rdi+188 is at mem: 012345

What will i do now to tell my dll to get rdi from the loc 012345? If i'd understand right, i replace the original code at 012345 to store the value somewhere i can read it from. What i would try now:

create a dword, let's say myrdi, then goto 012345 and assemble the code to copy rdi value to myrdi. Would that work? Or i'm completly wrong here? I think i miss something fundamental but damn, i wanna understand that Confused
Even my brain crashes Crying or Very sad

I believe i think to complicated Smile
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 198

Joined: 25 Jan 2006
Posts: 8517
Location: 127.0.0.1

PostPosted: Sun Dec 04, 2016 12:55 am    Post subject: Reply with quote

In order to get a registers value you are going to have to create a code-cave and store the value as it passes through your own code, or you are going to have to use breakpoints to cause a breakpoint, read the thread information at the given instruction, then continue. (You can use exceptions and such to do this as well.)
_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
FreewareFire
Newbie cheater
Reputation: 0

Joined: 27 Mar 2013
Posts: 14

PostPosted: Wed Dec 07, 2016 10:57 am    Post subject: Reply with quote

Hi, sorry for late response, was busy last days. I tried nearly everything i can imagine. But it seems i'm stucked. I can create a code cave using VirtualAllocEx from my process and can write to it. The problem i have is the correct jmp to the cave and back (can't figure it out). Problem is that it's a 64 bit game and the cave is created somewhere in the process. I don't get the correct code to jmp from the original code to the cave. As said i using C# - as i'm on 64 bit i'm not able to create the right jump to the cave and get back. Has someone a class or some code to help me out? I found some classes for 32 bit but not for 64 bit. Writing to memory itself isn't my problem as i created few easy trainers before, but not for 64 bit. I don't want to use dll injection as it makes no sense to me - or i'm just to stupid that i'm missing the advantages.

The easy one would as atom0s says: create code cave, jmp to it, store the value, jmp back to the original code and then just read the value i stored at the code cave... And again i thank everyone for his/her help !!
Back to top
View user's profile Send private message
atom0s
Moderator
Reputation: 198

Joined: 25 Jan 2006
Posts: 8517
Location: 127.0.0.1

PostPosted: Wed Dec 07, 2016 3:07 pm    Post subject: Reply with quote

Jumps and calls are calculated offsets, so you need to calculate the jump based on the position of the cave and the original code.

The jump from the original code to your cave will be calculated as:
CaveAddress - (Original Code Address + 5)
Adjust 5 as needed for the size of the jump.

The cave jump that has to return back to the original code would be done as:
ReturnAddress = (OriginalCodeAddress + 5) + NumberOfNopsNeeded
ReturnJump = ReturnAddress - (CaveAddress + (CaveSize + 5))
Adjust 5 as needed for the size of the jump.

When you create a jump, in some cases you will need to use nops to null out additional invalid code if your jump cuts into part of an instruction. So take into account how many are used when creating your jumps.

_________________
- Retired.
Back to top
View user's profile Send private message Visit poster's website
ulysse31
Master Cheater
Reputation: 2

Joined: 19 Mar 2015
Posts: 324
Location: Paris

PostPosted: Wed Dec 07, 2016 4:59 pm    Post subject: Reply with quote

It is this part of the code :
Code:
    foundAddress2 = foundAddress + 5; // because cpu reads 5 byte opcode before processing hook and is further down code line.
      void (*Address)() = HookEncryption;
      char szbuffer[1024];
      unsigned int difference;
      if (foundAddress2 > (int)Address)
         difference = foundAddress2 - (int)Address;
      else
         difference = (int)Address - foundAddress2;
      sprintf(szbuffer, "Allocated Mem is at : %02x", (int)Address);
      //MessageBox(NULL, szbuffer, "Title", MB_OK);
      sprintf(szbuffer, "Distance is : %02x", difference);
      //MessageBox(NULL, szbuffer, "Title", MB_OK);
      char chHookEncryption[5];
      chHookEncryption[0] = '\xE9';
      chHookEncryption[1] = (difference >> 0) & (0xFF);
      chHookEncryption[2] = (difference >> 8) & (0xFF);
      chHookEncryption[3] = (difference >> 16) & (0xFF);
      chHookEncryption[4] = (difference >> 24) & (0xFF);
      HANDLE procHandle = GetCurrentProcess();
      WriteProcessMemory(procHandle, (LPVOID)foundAddress, &chHookEncryption, sizeof(chHookEncryption), NULL);

I am aware this is 32 bit code however the logic remains the exact same.
You just need to use your logic here : Open a 64 bit process with cheat engine and look how long jumps are constructed ;
When you assemble a long jump instruction with CE you will get 14 bytes of opcodes.
The first 6 bytes mean jump qwordptr[], the next 8 bytes are the qwordptr content holding the wanted address (codecave address).
The jmp instruction would be FF2500000000 as long as the ptr value is right after the jmp instruction.
Then you need to reasign the original code you just overwritten with the jump qword ptr inside the code cave, and insert your own code with it.
Then you just jmp back from the cave to after the full jmp qword ptr instruction.

Play around with CE, understand how bytes form jmp opcodes and write the corresponding arrays into your target program :
In 32 bit target the jump will be E9 and then i insert the calculated distance in little endian through byte shifting :

Code:
      chHookEncryption[0] = '\xE9';
      chHookEncryption[1] = (difference >> 0) & (0xFF);
      chHookEncryption[2] = (difference >> 8) & (0xFF);
      chHookEncryption[3] = (difference >> 16) & (0xFF);
      chHookEncryption[4] = (difference >> 24) & (0xFF);
Back to top
View user's profile Send private message
FreewareFire
Newbie cheater
Reputation: 0

Joined: 27 Mar 2013
Posts: 14

PostPosted: Thu Dec 08, 2016 5:51 am    Post subject: Reply with quote

Let me show an example what i get when i do it in notepad:

Original code is at: 7FF656473CB0 (example what's outputted az my tests)
Code Cave is created at: 24C2DEC0000 via VirtualAllocEx

So when i calc the Jump it would be: FFFF8255D7A4C35E

Calculated like: (Cave - Originalcode) - 14

Code:
Int64 offset = caveAddress.ToInt64() - (address.ToInt64() - 14);


and i think this jump is false or i'm wrong?
Back to top
View user's profile Send private message
ulysse31
Master Cheater
Reputation: 2

Joined: 19 Mar 2015
Posts: 324
Location: Paris

PostPosted: Thu Dec 08, 2016 5:24 pm    Post subject: Reply with quote

If you chose to use jmp qword ptr the first 6 bytes always are
"FF2500000000"
Followed by the virtual address so that means in this case no difference, just the address that will be interpreted as data (little endian) so shift bytes.
If you wanna jump to address 0x0123456789123456
then the full code is 14 bytes :
"FF25000000005634128967452301"
If you haven't understood it all, play with cheat engine and understand how jmps are made
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