Alright, so I apologize if this isn't helpful at all, but I tried to quickly free write through a phase of the bomb lab. It would have been better to have screenshots and such, but I didn't have much time to work on this today. I'm having a daughter soon and it's my job to paint everything/put stuff together (ohhhhhh the humanity).
This is the original code (my annotations are below):
Quote:
Dump of assembler code for function phase_4:
0x08048c8e <phase_4+0>: push %ebp
0x08048c8f <phase_4+1>: mov %esp,%ebp
0x08048c91 <phase_4+3>: sub $0x28,%esp
0x08048c94 <phase_4+6>: lea -0xc(%ebp),%eax
0x08048c97 <phase_4+9>: mov %eax,0x8(%esp)
0x08048c9b <phase_4+13>: movl $0x8049958,0x4(%esp)
0x08048ca3 <phase_4+21>: mov 0x8(%ebp),%eax
0x08048ca6 <phase_4+24>: mov %eax,(%esp)
0x08048ca9 <phase_4+27>: call 0x804886c <sscanf@plt>
0x08048cae <phase_4+32>: mov %eax,-0x4(%ebp)
0x08048cb1 <phase_4+35>: cmpl $0x1,-0x4(%ebp)
0x08048cb5 <phase_4+39>: jne 0x8048cbe <phase_4+48>
0x08048cb7 <phase_4+41>: mov -0xc(%ebp),%eax
0x08048cba <phase_4+44>: test %eax,%eax
0x08048cbc <phase_4+46>: jg 0x8048cc3 <phase_4+53>
0x08048cbe <phase_4+48>: call 0x8049635 <explode_bomb>
0x08048cc3 <phase_4+53>: mov -0xc(%ebp),%eax
0x08048cc6 <phase_4+56>: mov %eax,(%esp)
0x08048cc9 <phase_4+59>: call 0x8048c58 <func4>
0x08048cce <phase_4+64>: mov %eax,-0x8(%ebp)
0x08048cd1 <phase_4+67>: cmpl $0xc90f7,-0x8(%ebp)
0x08048cd8 <phase_4+74>: je 0x8048cdf <phase_4+81>
0x08048cda <phase_4+76>: call 0x8049635 <explode_bomb>
0x08048cdf <phase_4+81>: leave
0x08048ce0 <phase_4+82>: ret
End of assembler dump.
Quote:
Dump of assembler code for function phase_4:
0x08048c8e <phase_4+0>: push %ebp
0x08048c8f <phase_4+1>: mov %esp,%ebp
0x08048c91 <phase_4+3>: sub $0x28,%esp
The first three lines of the code set up the stack.
-EBP saves a position inside a stack. It's almost like a homepage. It says, this is where I am.
-Everything works around the stack base pointer (EBP is base pointer).
-To access things above the Base Pointer we need to add. To access below, we need to subtract.
-Things above the base pointer are the return addresses and the parameters passed to a function.
--This means that to access the first parameter we need to do EBP+8 because the return address takes up the first 4 bytes.
---To access local variables, we need to subtract. In the above code you can see that 0x28 is subtracted which when converted from hex to decimal is equal to 40 (16*2+8). This makes room on the stack for them.
-Commonly used stacked plates analogy: In order to get to plates on the bottom, we need to move the ones off the top to get to the one we want.
--The top of the stack is always the object that we need to take remove first. It is a last in first out system.
Quote:
0x08048c94 <phase_4+6>: lea -0xc(%ebp),%eax
0x08048c97 <phase_4+9>: mov %eax,0x8(%esp)
0x08048c9b <phase_4+13>: movl $0x8049958,0x4(%esp)
0x08048ca3 <phase_4+21>: mov 0x8(%ebp),%eax
0x08048ca6 <phase_4+24>: mov %eax,(%esp)
0x08048ca9 <phase_4+27>: call 0x804886c <sscanf@plt>
As of right now, we still don't know what we need to input to diffuse this bomb; we don't know if the bomb wants a combination of integers, chars, etc. To find out we can look above the scanf call and examine "$0x8049958." When we examine this in gdb we see "%d," so we know we need to input an integer of some sort to diffuse our bomb.
Quote:
0x08048cae <phase_4+32>: mov %eax,-0x4(%ebp)
0x08048cb1 <phase_4+35>: cmpl $0x1,-0x4(%ebp)
0x08048cb5 <phase_4+39>: jne 0x8048cbe <phase_4+48>
The key to these bomb labs are the compare statements. Here we see that EBP-4 is being compared to 1. Then below it is the "jump not equal instruction." So if, EBP-4 is not equal to 1, the program jumps to the address: 0x8048cbe. If it is equal, the program continues on. As you can see, if the numbers are not equal you will jump to the address where the bomb will explode (phase_4+76). The numbers will be equal as long as you identified what parameters the bomb wants, which we did; so we're all set here and we live to see another day.
Quote:
0x08048cb7 <phase_4+41>: mov -0xc(%ebp),%eax
0x08048cba <phase_4+44>: test %eax,%eax
0x08048cbc <phase_4+46>: jg 0x8048cc3 <phase_4+53>
0x08048cbe <phase_4+48>: call 0x8049635 <explode_bomb>
So now we see another compare statement represented as a "test" instruction. The test instruction implements a bitwise AND on the value in eax. Here it will jump to address 0x8048cc3 and bypass the bomb call if that value is greater than 0. So we jump to that address.
Quote:
0x08048cc3 <phase_4+53>: mov -0xc(%ebp),%eax
0x08048cc6 <phase_4+56>: mov %eax,(%esp)
0x08048cc9 <phase_4+59>: call 0x8048c58 <func4>
Now we are calling function 4, so we head there. But first let's take a quick look at the end of the program. We see that
our value is being compared to $0xc90f7. Converting from hex to decimal, that gives us 823,543. So we know that whatever happens in function 4, our number must be equal to 823,543 at the end of it, or the bomb will explode.
Quote:
0x08048cce <phase_4+64>: mov %eax,-0x8(%ebp)
0x08048cd1 <phase_4+67>: cmpl $0xc90f7,-0x8(%ebp)
0x08048cd8 <phase_4+74>: je 0x8048cdf <phase_4+81>
0x08048cda <phase_4+76>: call 0x8049635 <explode_bomb>
0x08048cdf <phase_4+81>: leave
0x08048ce0 <phase_4+82>: ret
Quote:
08048c58 <func4>:
8048c58: 55 push %ebp
8048c59: 89 e5 mov %esp,%ebp
8048c5b: 83 ec 08 sub $0x8,%esp
8048c5e: 83 7d 08 00 cmpl $0x0,0x8(%ebp)
8048c62: 7f 09 jg 8048c6d <func4+0x15>
8048c64: c7 45 fc 01 00 movl $0x1,0xfffffffc(%ebp)
8048c6b: eb 1c jmp 8048c89 <func4+0x31>
8048c6d: 8b 45 08 mov 0x8(%ebp),%eax
8048c70: 83 e8 01 sub $0x1,%eax
8048c73: 89 04 24 mov %eax,(%esp)
8048c76: e8 dd ff ff ff call 8048c58 <func4>
8048c7b: 89 c2 mov %eax,%edx
8048c7d: 89 d0 mov %edx,%eax
8048c7f: c1 e0 03 shl $0x3,%eax
8048c82: 89 c1 mov %eax,%ecx
8048c84: 29 d1 sub %edx,%ecx
8048c86: 89 4d fc mov %ecx,0xfffffffc(%ebp)
8048c89: 8b 45 fc mov 0xfffffffc(%ebp),%eax
8048c8c: c9 leave
8048c8d: c3 ret
FUNCTION 4 cliffnotes: Here we see that we are looping through this function until our value is no longer greater than 0 (notice the compare instruction in the fourth line). Our number gets 1 subtracted and then function 4 is called, and then 1 is subtracted again until eventually our number is 0. Once our number is 0, we finally move on and the key to notice here is the SHL instruction. This means Shift left and we see here: "shl $0x3,%eax," which means our number is left shifted by 3. This is equivalent to multiplying our number by 8. Our number is put into the register EAX and then moved to ECX. Then EDX is subtracted from ECX, and EDX contains the value 1. So this is equivalent to multiplying our number by 8-1 which is 7.
We know that the program will loop through as many times as the number we enter, and so to get to the value 823,543 the program would run as:
7*7*7*7*7*7*7. So our number is 7. 7^7=823,543.
So we input 7 and move onto the next phase.