0

I am currently a newbie to assembly. I was looking at a disassembled program and I was wondering:

What does this do?

arg_0 dd 5

cmp [ebp+arg_0],1Eh     ; Subtract the two values - flag either 0 or 1
jnz short loc_blahblah  ; if flag is 0 then jump

I know that it is comparing the two values by subtracting them and keeping the flags.

However when I click on the cmp instruction it shows me : [ebp+arg_0]=00000005 . Is this a memory address? Or is it the new value stored within the stack?

I tried making the cmp instruction result in a flag 0, however I can't seem to be able to do it. Could you explain this in simple terms?

Thanks.

P.S: If this is a little vague, I do apologies as I myself am a little confused.

  • If you simply want to make it jump, change the "jnz" instruction to "jmp"; that'll ignore the flags and always jump – rev Jul 29 '15 at 16:27
0

Your arg_0 dd 5 seems a bit confusing to me as well, since, if that was an assembler instruction, it would define a global variable, not a stack position. Stack positions aren't initialized at compile time or program start, they get used when a program calls a subroutine. So i'll assume you copied this somehow when the program was running, not from the disassembly itself.

When a subroutine is called, the caller pushes the arguments on the stack - i'll assume a single argument here, and let's assume the value is 5. At this moment the stack looks like this:

+----------+
| 00000005 |
+----------+     <--- esp

Then, the caller executes the call instruction, which puts the return address onto the stack, and jumps to your subroutine. Now, the stack looks like this:

+----------+
| 00000005 |
+----------+
| ret.addr |
+----------+     <--- esp

(note the stack grows from high addresses to low addresses on x86 processors, newer entries are below older ones)

And the called subroutine normally starts with saving the old value of ebp by pushing it to the stack, moving the stack pointer to ebp, and subtracting a small value from esp to make room for local variables.

+----------+
| 00000005 |
+----------+
| ret.addr |
+----------+
| old_ebp  |
+----------+     <--- ebp
|          |
|  .....   |
+----------+     <--- esp

So within the subroutine, the argument is always 8 bytes "above" the current value of ebp, while the distance to esp varies, depending on how much space local variables need, and how stuff is pushed to the stack within the subroutine. Which is why parameters are accessed by indexing relative to ebp.

Your cmp instruction compares that value from the stack with the number 0x1e, or 30 decimal. The processor fetches the 5 from its location on the stack, subtracts 30 from it, throws away the result (-25), and executes the jump instruction depending on whether or not the result was 0.

To answer the first question: The 5 is not the new value within the stack, it's the value that was on the stack before the instruction, and is still on the stack as the instruction didn't change it.

Now, if you want the cmp instruction to result in a set zero flag, you'll have to make the result of the subtraction 0 - which means you need to make the result of 5-30 zero. To do this, you have two possibilities - either, change the 5 to a 30, or, change the 30 to a 5.

The first approach - changing the 5 to a 30 - is what you use when you're debugging your own program. Assume you noticed your program doesn't work as intended, your start a debugger, run a part of the program, and notice at a certain point in your program that a variable is 5 when you'd expect it to be 30. Obviously, something went wrong up to this point. But if you want to check if the rest of the program works, you'd like to edit the variable in place - which means, change the content of the memory location to 30, then continue running the program.

The second approach - changing the 30 to a 5 - is used when hacking programs that aren't your own. Assume a program that requires a registration number to be entered. You enter a random number - 12345678, debug the program, notice the digits are mangled somehow, and the result of this mangling is 5. The code you disassembled shows you need a 30 instead of the 5, but you don't know which combination of digits yields that 30. So what do you do? You change the cmp [ebp+arg_0],1Eh to cmp [ebp+arg_0],05h, save back that patched program, and suddenly your 12345678 will be a valid serial number.

So to "make the cmp instruction result in a flag 0", you'll either have to modify the stack memory to turn the 5 into a 0x1e, or you'll have to modify the program code to turn the cmp [ebp+arg_0],1Eh into a cmp [ebp+arg_0],05h. Since you don't specify what exactly your use case is, i can't tell you which of them is what you need.

  • Thank-you! This was really helpful (especially the diagrammatic representation of the stack)! – user36278 Jul 30 '15 at 11:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.