My little newb question about Memory hacking[SOLVED]

Posts 1–15 of 17 · Page 1 of 2
My little newb question about Memory hacking[SOLVED]
Well, I'm not much into Memory hacking, i always felt like, lazy to get into it.
Started a few hours ago to look at WriteProcessMemory, etc... i find it quite simple ( i saw some stuff about people posts, etc.. which of course made me learn pretty basic stuff without actually want to ).

I though: "let me try something basic like editing windows Solitaire game memory" Well, it wasn't that hard to find the address."
I used CE, probably not the best tool, but it did the job. Searched from my current score, scored a bit more, and searched again and got the address. (which was fine).

Coded a simple console app, found window by name, got the id with GetWindowThreadProcessId and did the WriteProcessMemory (was inside a loop with a sleep to keep the score).

Well, the problem is not on the code actually, my actual problem is on the address. So my doubt is: Should the address always change when I open a new Solitaire? because after close/opening, the address changed, had to get the new one... and change it on the code.
Am i getting a wrong address? am i doing the wrong stuff? or am i damt stupid and its normal?

(no i'm not requesting any code.. so you don't need to post one...)

thanks in advance. some tips are welcome too
here i have something for MW2 it works but it isnt a pro thing ofcourse

#include <Windows.h>
#include "stdafx.h"

int main()
{
HWND hWnd = FindWindow(0, "Modern Warfare 2");
if(hWnd == 0)
{
MessageBox(0, "Error cannot find window.", "Error", MB_OK|MB_ICONERROR)
}
else
{
DWORD proccess_ID;
GetWindowThreadProcessId(hWnd, &proccess_ID);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, proccess_ID);
if(!hProcess)
{
MessageBox(0, "Could not open the process!", "Error!", MB_OK|MB_ICONERROR);
}
{
while(1){
int newdata = 5000;
int newdata2 = 300;
int newdata3 = 40;
int newdata4 = 10000000;
DWORD newdatasize = sizeof(newdata);//first and second main ammo //
if(WriteProcessMemory(hProcess, (LPVOID)0x75F5A8, &newdata, newdatasize, NULL))
if(WriteProcessMemory(hProcess, (LPVOID)0x76A24C, &newdata, newdatasize, NULL))
if(WriteProcessMemory(hProcess, (LPVOID)0x774F08, &newdata, newdatasize, NULL))
if(WriteProcessMemory(hProcess, (LPVOID)0x926F34, &newdata, newdatasize, NULL))
if(WriteProcessMemory(hProcess, (LPVOID)0x108DF44, &newdata, newdatasize, NULL))
if(WriteProcessMemory(hProcess, (LPVOID)0x75F5C0, &newdata, newdatasize, NULL))
}



CloseHandle(hProcess);
}
}
return 0;
}
Quote Originally Posted by Zyixc View Post
here i have something for MW2 it works but it isnt a pro thing ofcourse
/read, btw, thats leeched ^^

Quote Originally Posted by Void View Post
Brinuz, you should read up on DMA.

You could find out what writes/edits the address you found, hopefully it's static and you could edit your original address through that instruction.

In C++, this would be an example of DMA.

[php]
int* array;
//===============
int size;
cin >> size;
//================
array = new int[size];
[/php]

The addresses obviously wouldn't be the same because it would have to allocate memory depending on how many integers you need.
thanks david, its always you
Quote Originally Posted by 'Bruno View Post
/read, btw, thats leeched ^^



thanks david, its always you

yeah right
Ok, after the precious info that David gave me, i managed to understand what was the problem, have been following the address.

Atm i do have:

[php]
MOV eax, [esi+2c]
ADD dword ptr [eax+10], fe
[/php]

< ADD dword ptr [eax+10], fe > This is the line that shows me when the scores changes, the other one is the one before it, and the first

well, i quite understand what is being done here, but not totally. thats why I am posting, because i though that ESI would be the static address? Since EAX+10 is the current adress of memory that contais the score. or is it eax? (not very logical to me, but if it is... let me know why )

i have tried using ESI but didnt get results.. ^^ sry but im new to this memory stuff.. (added 0x2c to it, etc..etc.)
Brinuz, you should read up on DMA.

You could find out what writes/edits the address you found, hopefully it's static and you could edit your original address through that instruction.

In C++, this would be an example of DMA.

[php]
int* array;
//===============
int size;
cin >> size;
//================
array = new int[size];
[/php]

The addresses obviously wouldn't be the same because it would have to allocate memory depending on how many integers you need.
Gimme a min or 5 i'll write up how to get it with ollydbg ^^

K here's what you'll need:
ResHacker
OllyDbg

I assume you'll have ollydbg already, reshacker is just the first result on google.

Load up sol.exe in ResHacker, and browse to the string table, under folder '7' click on 1033, and you'll end up with the following:

Code:
STRINGTABLE
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
{
100, 	"Solitaire"
101, 	"Score: "
102, 	"Time: "
103, 	"CardDraw"
104, 	"Deal Again?"
105, 	"sol.chm"
106, 	"Press Esc or a mouse button to stop..."
107, 	"Bonus: "
108, 	"Developed for Microsoft by Wes Cherry"
}
(FFFUUUUUUU)

take note of the following:
Code:
101, 	"Score: "
102, 	"Time: "


We might need the following later as i'm writing this while debugging.
101 is 65 in hex
102 is 66 in hex
1033 is 409 in hex

from what I know if you're going to use resource files, you'll end up calling stuff from USER32.dll, so let's take a look at sol.exe's import table(ctrl+g to 1001000)
Some interesting stuff:
Code:
010010F8 > . 08C9427E       DD USER32.LoadStringA
01001108 > . CB8C417E       DD USER32.PostMessageW
01001174 > . 369E417E       DD USER32.LoadStringW
01001190 > . E2D7427E       DD USER32.DrawTextW
so what I do now is right click -> find all intermodular calls, and start typing DrawTextW, as it's probably important and followed the first one

Code:
01005269  |. 6A 50          PUSH 50
0100526B  |. 6A 66          PUSH 66
0100526D  |. 8D45 B0        LEA EAX,DWORD PTR SS:[EBP-50]
01005270  |. 50             PUSH EAX
01005271  |. E8 82D1FFFF    CALL sol.010023F8
01005276  |. 8D7C45 B0      LEA EDI,DWORD PTR SS:[EBP+EAX*2-50]
0100527A  |. 8B45 78        MOV EAX,DWORD PTR SS:[EBP+78]
0100527D  |. 8B40 34        MOV EAX,DWORD PTR DS:[EAX+34]
01005280  |. C1F8 02        SAR EAX,2
01005283  |. 50             PUSH EAX                                 ; /Arg2
01005284  |. 57             PUSH EDI                                 ; |Arg1
01005285  |. E8 A1D0FFFF    CALL sol.0100232B                        ; \sol.0100232B
0100528A  |. 8D1C47         LEA EBX,DWORD PTR DS:[EDI+EAX*2]
0100528D  |. 8D45 B0        LEA EAX,DWORD PTR SS:[EBP-50]
01005290  |. 3BD8           CMP EBX,EAX
01005292  |. 74 22          JE SHORT sol.010052B6
01005294  |. 68 22010000    PUSH 122                                 ; /Flags = DT_RIGHT|DT_TOP|DT_SINGLELINE|DT_NOCLIP
01005299  |. FF75 7C        PUSH DWORD PTR SS:[EBP+7C]               ; |pRect
0100529C  |. 8D4D B0        LEA ECX,DWORD PTR SS:[EBP-50]            ; |
0100529F  |. 8BC3           MOV EAX,EBX                              ; |
010052A1  |. 2BC1           SUB EAX,ECX                              ; |
010052A3  |. D1F8           SAR EAX,1                                ; |
010052A5  |. 50             PUSH EAX                                 ; |Count
010052A6  |. 8D45 B0        LEA EAX,DWORD PTR SS:[EBP-50]            ; |
010052A9  |. 50             PUSH EAX                                 ; |Text
010052AA  |. FF35 74710001  PUSH DWORD PTR DS:[1007174]              ; |hDC = NULL
010052B0  |. FF15 90110001  CALL DWORD PTR DS:[<&USER32.DrawTextW>]  ; \DrawTextW
I've highlighted push 66, which is 102 in decimal, remember above? 102 was "Time: ".
Follow the call below push 66:
Code:
010023F8  /$ FF7424 0C      PUSH DWORD PTR SS:[ESP+C]                ; /Count
010023FC  |. 0FB74424 0C    MOVZX EAX,WORD PTR SS:[ESP+C]            ; |
01002401  |. FF7424 08      PUSH DWORD PTR SS:[ESP+8]                ; |Buffer
01002405  |. 50             PUSH EAX                                 ; |RsrcID
01002406  |. FF35 6C730001  PUSH DWORD PTR DS:[100736C]              ; |hInst = NULL
0100240C  |. FF15 74110001  CALL DWORD PTR DS:[<&USER32.LoadStringW>>; \LoadStringW
01002412  \. C2 0C00        RETN 0C
it calls LoadString, so we're on the right track
Go back to where we came from(01005271)

Code:
01005276  |. 8D7C45 B0      LEA EDI,DWORD PTR SS:[EBP+EAX*2-50]
0100527A  |. 8B45 78        MOV EAX,DWORD PTR SS:[EBP+78]
0100527D  |. 8B40 34        MOV EAX,DWORD PTR DS:[EAX+34]
01005280  |. C1F8 02        SAR EAX,2
01005283  |. 50             PUSH EAX                                 ; /Arg2
01005284  |. 57             PUSH EDI                                 ; |Arg1
01005285  |. E8 A1D0FFFF    CALL sol.0100232B                        ; \sol.0100232B
Put a breakpoint on the first MOV EAX, since the call in the bottom adds "Time: " and the value(which is stored in EAX) together.
Now run the game and watch it break.
Stack SS:[0007FCE4] = 0x000BA808
Then it adds +0x34 to that and follows it again(0x000BA83C), which points to the value of time.

*(DWORD*)(0x000BA808+0x34) = 0;

Now for score, follow the 2nd call to drawtext, breakpoint on this:
Code:
01005348  |. 8B47 30        MOV EAX,DWORD PTR DS:[EDI+30]
DS:[0x000BA838] = 000000
but, they do EDI+0x30
So that means we can do the same as with Time:
*(DWORD*)(0x000BA808+0x30) = 1337;

Have fun I guess
oO that's big... it is just me thinking ... or i was doing everything wrong ^^

can't try to do it now as im at work.. but i will definitely follow that at home. Thanks HD =D love ya.. ^^ but damt.. you wrote quite a bit there.. oO (well.. half of it is code tags )
You can also do this with Cheat engine. I saw a tutorial on it a few months back, I cant seem to find it though. But im 100% you can find the address in CE. Its a lot easier than all of those steps
Quote Originally Posted by apandhi View Post
You can also do this with Cheat engine. I saw a tutorial on it a few months back, I cant seem to find it though. But im 100% you can find the address in CE. Its a lot easier than all of those steps
Yeah but that way makes you look smarter.
Quote Originally Posted by apandhi View Post
You can also do this with Cheat engine. I saw a tutorial on it a few months back, I cant seem to find it though. But im 100% you can find the address in CE. Its a lot easier than all of those steps
that was what i used on the post i did and then asked. not new news... but thanks anyway
Quote Originally Posted by 'Bruno View Post
that was what i used on the post i did and then asked. not new news... but thanks anyway
I meant there was a way to find the pointer (i think is the official name for name for it?) for the address that never changes through cheat engine. That way whenever you restart the game the hack still works
yeah i believe its called a static address?(bit rusty lol i think it appears green in the address window)
Quote Originally Posted by falzarex View Post
yeah i believe its called a static address?(bit rusty lol i think it appears green in the address window)
that was already said by David (Void) at the start.

EDIT:

Ok after the help i asked i think it is fair to share the final code which is actually working at windows xp 32bits.

[php]
#include <Windows.h>
#include <iostream>

#define staticScoreAdr 0x1007170

using namespace std;

HANDLE getHandle(LPCWSTR appName);

int main()
{
int score;

HANDLE hSolWindow = getHandle(L"Solitário"); //name of the window might need to be changed since this is in portuguese

while(!hSolWindow)
{
cout << "Didnt find the window.. Retrying.." << endl;
hSolWindow = getHandle(L"Solitário"); //name of the window might need to be changed since this is in portuguese
Sleep(1000);
}


cout << "Found Window.." << endl;
cout << "Insert desired score:" << endl;
cin >> score;

int adress;
ReadProcessMemory(hSolWindow, (LPCVOID)(staticScoreAdr), &adress, sizeof(int), 0); adress += 0x30;

while(true)
{
WriteProcessMemory(hSolWindow, (LPVOID)adress, &score, sizeof(score), 0);
Sleep(10);
}

return 0;
}

HANDLE getHandle(LPCWSTR appName)
{
DWORD* idProcess = new DWORD;
GetWindowThreadProcessId(FindWindow(0, appName), idProcess);
return OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, 0, *idProcess);
}
[/php]

Credits mainly to David (Void) and HD who helped me understanding and explained me some stuff and concepts of memory hacking

This was actually my first hack.. (if i can even call it hack) so Tips?
FindWindow is going to become really irritating if you use it a lot, the caption name won't always be that short...

Look up Process32First and Process32Next, pretty much uses the process name instead of the caption name, removes the need for both FindWindow and GetWindowThreadProcessId.

Great job, looks a lot like my first hack as well. /
Posts 1–15 of 17 · Page 1 of 2
This thread is closed for replies.

Similar Threads

Tags for this Thread

None

Need help?