PDA

View Full Version : Changing one line changes many?


sBoff
February 27th, 2007, 04:01
Hi people.

Ive been programming for many years now and recently been bitten by the want to get a better understanding of more low level detail. Ive been using OllyDbg to modify my Win32 C programe, it automatically checks my email.

The thing i cant quite understand is when i modify one line of the code in OllyDbg is automatically changes a couple of lines below the line as well.. I was just wondering if its supposed to do that and why?

Here is the example. Note: im changing the PUSH EAX line (00403954) by doubble clicking on it and typing "PUSH 0000000A" and pressing "Assemble".

Code:

0040393C . 74 2E JE SHORT CheckIt.0040396C
0040393E . 83F8 FF CMP EAX,-1
00403941 . 74 22 JE SHORT CheckIt.00403965
00403943 . 3BC3 CMP EAX,EBX
00403945 . 76 0D JBE SHORT CheckIt.00403954
00403947 . 0105 58714000 ADD DWORD PTR DS:[407158],EAX
0040394D . C605 55714000 01 MOV BYTE PTR DS:[407155],1
00403954 > 50 PUSH EAX
00403955 . 8D45 20 LEA EAX,DWORD PTR SS:[EBP+20]
00403958 . 68 C0554000 PUSH CheckIt.004055C0 ; ASCII "%d New Message(s)"
0040395D . 50 PUSH EAX
0040395E . FFD6 CALL ESI
00403960 . 83C4 0C ADD ESP,0C
00403963 . EB 1E JMP SHORT CheckIt.00403983


The code above gets changed to

Code:

0040393C . 74 2E JE SHORT CheckIt.0040396C
0040393E . 83F8 FF CMP EAX,-1
00403941 . 74 22 JE SHORT CheckIt.00403965
00403943 . 3BC3 CMP EAX,EBX
00403945 . 76 0D JBE SHORT CheckIt.00403954
00403947 . 0105 58714000 ADD DWORD PTR DS:[407158],EAX
0040394D . C605 55714000 01 MOV BYTE PTR DS:[407155],1
00403954 6A 0A PUSH 0A
00403956 45 INC EBP
00403957 2068 C0 AND BYTE PTR DS:[EAX-40],CH
0040395A ? 55 PUSH EBP
0040395B ? 40 INC EAX
0040395C ? 0050 FF ADD BYTE PTR DS:[EAX-1],DL
0040395F ? D6 SALC
00403960 . 83C4 0C ADD ESP,0C
00403963 . EB 1E JMP SHORT CheckIt.00403983


P.S. what does the "Fill with NOP's" do? Full what with NOPs??

Thanks for the help

ZaiRoN
February 27th, 2007, 04:22
You are changing a sequence of bytes into a new one and the debugger simply decodes the new bytes. You are having a weird situation because the length (in bytes) of the new instruction it's not equal to the one of the old instruction. You are trying to change a 1 byte instruction with a 2 bytes instruction, you don't have the physical space to perform the patch. You need to add the new instructions into another place inside the code, adding a jump to the new code.

Aimless
February 27th, 2007, 05:40
Did you get that?

Have PHun

naides
February 27th, 2007, 06:55
When you change an instruction in the code at high level language, there is no problem, the compiler/assembler adjusts the code after your change, and the subsequent instructions remain unaltered/recognizable.

You cannot do the same stunt in compiled code:
It is like a castle of cards: you add or take out stuff, you will send the whole building out of balance: The jumps don't get to their destination (The jump addresses are relative) the call addresses also, the pointers, you name it.

So Olly and other debuggers never INSERTS, in the way a word processor would, extra bytes when you assemble an instruction. At best, it will overwrite the next few bytes of the following instruction(s), which changes the meaning of several instructions down the road. Think that x86 instructions have no fixed length, so determining the first byte (and the lexical meaning) of the next instruction depends on the length of the previous one, another castle of cards.

So the first tenet of RCE is: you can change one byte for another byte in order to change an app behavior.
If you switch a 5 byte length instruction for something 4 or less byte long, you need to pad the extra bytes with NOP instructions (x90) That is where the "fill with NOPs" option comes into use. That way the next and subsequent instructions remain unaltered.

if you want to change a 1 byte instruction for something longer, As you attempted to do, weeeell, you have to resort to the trickery that ZaiRon described

sBoff
February 27th, 2007, 18:31
Ahh ok, yes that makes sence. Thankyou all for the replys

This stuff is getting exciting!

blabberer
February 28th, 2007, 04:17
Quote:

P.S. what does the "Fill with NOP's" do? Full what with NOPs??



like it says it fills with nops

so you changed 50 to 68 0a

there is no space
so it stole the first byte of next operation sequence which was a 3 byte instruction 8d 45 20

so there are two bytes left that doesnt make sense and might/or might not lead to crash so if you have selected fill with nops
ollydbg will fille the 45 and 20 (remaining two bytes ) with 0x90 (nop aka alternate instruction for mov eax,eax aka does nothing sequence of instruction

so that if execution continues the probability of crash reduces a little bit

assume you have a 5 byte far push

68 123456789

you change it to a near push

6a 05

the result after having selected fill with nops would be

6a 05 90 90 90

and with out would be

6a 05 34 56 78

executing the first one with nops has a quiet good chance of succeding while
without has a higher probabilty to crash with invalid opcodes

i hope you understand my vague answer slightly better (especially the implications that i point with might, maybe, maynotbe, could, and probabilty)