Hi again all,
This is the second part in my 2 part series, this part will focus on tracing code and making patches within OllyDbg. A little forewarning, this will be a *long* post, as i try and explain everything.
- OllyDbg (or another of your choosing)
- Notes from part 1
- Again...Your brain =)
Ok, so if you followed the first part, you should have the address of an instruction inside solitaire, specifically, the one that actually writes to our current score. This will serve as our starting point in debugging solitaire.
So without further ado...fire up Olly, and open up sol.exe.
You can step through and trace some code at the EP (Entry Point) if you like, but it isnt pretty, you can thank MSVCRT for that
But let's get right to the point shall we, Hit Ctrl+G, and enter the address of the instruction we have, hit enter and you should land right in the action, seeing something like this:
Now if you aren't familiar with olly, the $ sign at the top there denotes the beginning of the routine, so we have dropped quite near the end, right after an immediately suspicious call. (suspicious because EAX is frequently used as the return-value from calls, and as you can see, EAX is what is written to our score (remember that ESI+30 is where our score is), so set a breakpoint at the 'PUSH EBP' in the beginning of this routine (to set a bp quickly in olly, double click the op-codes, in this case '55') and hit F9 to run the game, or Shift+F9 if you dont have your options set up to ignore all exceptions.
Bam!, we immediately break in this routine, but we expected that right? So start stepping through (F7) and take a mental note of what is happening, see all those 'cmp' 'je' pairs at the top? Looks like this routine could probably be used for other things aswell as the score, il leave that for you to explore, as we are only interested in our score right now.
The main things to take in here, are the values of ESI and EAX, so we are looking for both where ESI gets set, and where EAX gets its value from, so notice this at $0x010030A7
MOV ESI, DWORD PTR SS:[EBP+8]
Here, SS: is the segment override, (SS = Stack Segment) which were only really interesting in old 16-bit dos applications, you can safely just imagine it isnt even there now, it basically means we are accessing data from the 'STACK', specifically the data located at EBP+8,
so if you look over to your stack pane (bottom right of the cpu window), right click in the pane and select 'Goto EBP', now double click on the top address, this will switch it to 'relative' addressing (ie: EBP+2, EBP+4 etc) and make reading it a lot easier.
You should see something along the lines of:
Hmm, the value at +8 doesnt look overly familiar right now does it? Unless you somehow got the same address as you did in CE, but i doubt it, it seems that the address of our score is passed as a parameter to this routine (parameters are 'PUSH'ed onto the stack before the call is made, and EBP points to the stack at the point where this routine starts). So we know to look out for that later, but there isnt much point in carrying on yet, as our score is obviously going to be zero right now, so F9/Run to continue running solitaire, and get yourself a score, Note that, if you hit F2 or change your deck, you will also break into olly again. As soon as you get a score, you should break right back in olly, same place we did before.
Step through the code again, following the jumps, keep tracing past where the pointer value is 'MOV'ed into ESI, and stop on the MOV EAX, hmm, there's that ESI+30 again, so first it seems to be reading our score into eax, and then adding to it. (Note the ADD EAX)
Now before we start looking at this more, i want to show you something, notice that ESI is already set with our pointer, and ESI+30 accesses our score, so grab a calculator and work out the resulting value there, (which in my case is $0x000BB0B8 + 30 = $0x000BB0E8)
Now remember the location of our pointer from CE, yes? Well lets go have a look at it, Ctrl+G in the dump window and enter the address of our pointer ($0x01007170), see the first 4 bytes stored there?
That is what a pointer looks like in memory, it is allocated at run-time and then the value of the 'real' value is stored at a fixed location like this, also note the endian-ness of the bytes in the dump window, olly shows these bytes in little-endian, so they will all be backwards (ie: our $0x000BB0E8 will show up as E8 B0 0B 00 in the dump window)
Right, back to business, and back to our routine, note the next instruction after MOV EAX reads our current score in,
ADD EAX, DWORD PTR SS:[EBP+10]
We already know that [EBP+10] is referncing this routine's parameters, so it looks like we found the main AddScore() function of solitaire! How do i know that? Well take a look at EBP+10 in the stack window...convert it to Decimal, then run and look at your score if you like proof.
Then the next instruction write the new score to memory, nothing special really, By the way, DS, just like SS, means the Data Segment
Not much else interesting happens now in this routine, but you may want to check out that call i said looked suspicious before, if you step inside the call (F7) you will notice that it doesnt do much else, except check to see if our score is less than (or equal) to 0, and if it is, sets it to 0
(now that may seem like strange behaviour, considering our score starts at zero and works up, but you will see the need for this quite soon). And the next call after that too, but that doesn't do much else except with writing the updated score to the client (for drawing).
Now back to business again, step over the 'RET' at the end of this routine to bring us to the code that called it, and you can see quite clearly the 3 'PUSH'es before the call, hmm, now we know what 2 of them are right? (address of score, and the score modification), but whats that third one i hear you cry...., well you can set a new BP on the call itself and go check it out, but its just a fixed value that tells the routine to update the score, i havn't delved too deep into it as there was no need, but go right ahead and do so if you feel so inclined.
So lets sum up, we now know how+where it applies our score, but we need to know how it DECREASES over time, so have a look around, set a few breakpoints, and lets see what you can come up with, go on, i'll wait for you =)
Right, if you didnt find anything out, (and gratz if you did!) following along and all will become clear, there is more than one way to do this, but i chose this way because of the ideal opportunity to also show of codecaving
So clear all your breakpoints and just set one in the beginning of the same routine we were in before, and let the game run for a few seconds, dont touch anything, and you will find we break right back into that routine!....Take a look at the stack pane, remember which one is score modification that gets 'ADD'ed to our score...yep!
A little explanation for those that don't fully understand, the value that gets passed there, looks like some sort of HUGE number, but in actual fact, its all down to how signed/unsigned numbers work in asm, $0xFFFFFFFE is actually treated as -2, theres plenty of reading material around that deal with that subject, so i wont re-invent the wheel, just google for signed/unsigned numbers in assembly and you'll figure it out
So, it passes a negative number ever few seconds, which when added, lower our score by (in this case) -2. Now obviously we can't just go modifying the code in this routine, as its used for ALL additions/subtractions to our score, but it IS the ideal opportunity to write a little codecave! Follow along, i know its been a long read...
Now for a code cave, we need to find 5 bytes (a jump is 5 bytes) we can overwrite in this routine, to place a jump to new code, how about this place:
Make sure you highlight all the instructions you are modifying (including the first instruction that wont be overwritten) and copy + paste them to notepad or something, trust me, the more references you have later, the better. Now we need somewhere to assemble a codecave, any space will do as long as its big enough, but sadly there isnt many places available in this .exe, so i chose an unused block of bytes right at the end (scroll down the code until you start seeing 'DB 00's), be sure not to go too far into those 00's as olly usually adds a few there for visual purposes (ie: they dont really exist in the file, or memory), and once you have a place picked out, write the address down.
Now for the hard....ok ok its easy...part, select the instruction that will be overwritten, in my case its the 'ADD EAX, DWORD PTR SS:[EBP+10]' and hit the space bar to assemble new, if you dont know asm, or need help, the following is what should be assembled:
where the ???????? is the address you chose to put the codecave, now hit enter to follow the jump and then spacebar again to start assembling our codecave:Code:JMP ????????
Now what to assemble? Well here is what needs to be done for the purposes of our hack][*]Check the value located at [EBP+10], is it below zero? if so goto 3[*]set the value to 0[*]execute the overwritten instructions, as per codecaving rules!!! <- DO NOT FORGET THIS!!![*]jump back to the instruction following the jump to our codecave[/list]
So there you have it, remember to take into account signed/unsigned numbers when checking the value at EBP+10, or you wont get the results you were hoping for. Now i didnt want to spoon feed or anything, but i understand it can be hard to get s grasp on things when starting out. So here is a screenshot of what i came up with.
Now i recommend you try this yourself first, and ONLY even think about copying code if you are *really really* stuck, otherwise you wont learn as much!
After you have a working codecave (ie, run the game -> get a score -> wait -> it doesnt decrease!)
copy and paste it to notepad, to make life easier when coding the hack.
Freezing the Game Timer
Now this ISNT going to be a spoon-fed operation, hehe, il give you the clues, then you go hunting, you know you can do it, just trust in yourself
If you dont know much about Windows API's, then grab yourself a copy of win32.hlp and read the section on Timers. It will save you a lot of headaches.
Now think about this logically for a moment, what would be the best way of implementing a timer?...(forget all that c time() stuff here), and your knowledge of Windows API's will start screaming at you...so right click in the code window and select 'Search For' -> 'All intermodular calls' to open a new window, start typing the name of that API in the window to find it faster, (assuming you chose the right one of course), once you found it, right click it and set breakpoint on every call, then run the game (restart and run, or you wont break).
You will know when you are in the right place, so let me give you a little hint to patching this, you cant simply 'NOP' out the entire call, because we're wanting an on/off solution, so you can choose to enable/disable the timer whenever you like, so we need a more elegant way to do it, take a look at the parameters 'PUSH'ed onto the stack before the API is called, then look again at your win32.hlp, you know what to do right?
SpoilerAssemble a 'RETN 10' over the first instruction to force the routine to return immediately
And there you have it! There's not much else to do except go and code your hacks in your favourite language! And gratz on reading the whole of my long-winded posts lol
I've attached my working source code here, for reference of course, the first is the DLL that, when injected, makes the necessary patches and works in a neat little GUI. The source also shows (again) how to call one of solitaire's own routines to add a custom amount to your score. The second is a quickly-thrown-together loader/injector, just put it in the same directory as the DLL and run it, it should start sol.exe and then inject the DLL. I've commented the DLL source as much as i can, to try and make it more understandable, and it is written in asm. If you dont want to use the loader, get yourself a copy of 'Winject' (Winject official page: http://www.cheat-project.com/cheats-hac ... nJect-1.7/)
Anyways, hope you learnt something from this tutorial, and if you have any questions/comments, or get stuck, drop a post here!
To Compile Sources you will need:
For the DLL: MASM32 (i used RadASM to write+compile)
For The Loader: Visual Studio 2010 (you can also use 2008, but you will need to create a new project, and then add the source.
DLL: (MD5 : e802f583baa5fe46f788e536e7e8e410)
Loader: (MD5 : bea5c86225850b12aac26005557c1306)