How to Understand "Cmpl $0X0, -0X30(%Rbp)"/"Je ..."

How to understand cmpl $0x0, -0x30(%rbp) / je ...

-0x30(%ebp) doesn't mean to use the value %ebp - 0x30. It's a memory address to read from. The instruction (cmpl) has an l suffix, so it's dealing with a 4 byte quantity. So what's actually happening is that it reads a 4 byte number from the address %ebp - 0x30 and checks whether it's zero.

(The $ prefix means it's an immediate value, not an address. This is why 0x0 is taken literally and not dereferenced.)

What cmpl $0x1, -0x18(ebp) does in AT&T?

Let's break it down a bit.

-0x18(ebp) takes the value stored in the ebp register, subtracts 0x18 from it, and uses the result as a memory address to read from.

Therefore, cmpl $0x1, -0x18(ebp) reads the value stored at the memory address calculated from -0x18(ebp) and subtracts $0x1 from it, setting various flags based on that calculation (e.g. setting the zero flag ZF to 1 if the subtraction results in 0). The various jmp instructions then determine whether to jump or not based on the flags that were set.

assembly quiz - phase6

I found it.

This phase has linked-list nodes whose size is 16 bytes. (Note the mov 0x8(%rbx),%rbx pointer-chasing p = p->next qword load from an offset of +8 relative the start of the node.

We can ignore the high dword of the pointers because they're all the same (x86 being little-endian), and just look at the first 3 dwords of each node with a GDB eXamine format of /3x, using the default size of 32-bit elements.

Breakpoint 1, 0x00005555555554fd in phase_6 ()
(gdb) until *0x0000555555555618
0x0000555555555618 in phase_6 ()
(gdb) x/3x $rdx-16
0x555555758230 <node1>: 0x00000189 0x00000001 0x00000000
(gdb) x/3x $rdx
0x555555758240 <node2>: 0x00000113 0x00000002 0x55758230
(gdb) x/3x $rdx+16
0x555555758250 <node3>: 0x0000007f 0x00000003 0x55758240
(gdb) x/3x $rdx+32
0x555555758260 <node4>: 0x000000ff 0x00000004 0x55758250
(gdb) x/3x $rdx+48
0x555555758270 <node5>: 0x000001fd 0x00000005 0x55758260
(gdb) x/3x $rbx
0x555555758110 <node6>: 0x000003b3 0x00000006 0x55758270

and when I gave 1 2 3 4 5 6 as input the program checks the validity in order of 6 5 4 3 2 1.
If the input is 1 5 3 4 2 6, it checks 6 2 4 3 5 1.

input = a, b, c, d, e -> check = 7-a, 7-b, 7-c, 7-d, 7-e

The validity is checked by

   0x0000555555555616 <+281>:   cmp    %eax,(%rbx)
0x0000555555555618 <+283>: jge 0x555555555607 <phase_6+266>

if the value of node 7-a is bigger than node 7-b, the program says OK. if not NO.

And the value of each node is...

0x555555758230 <node1>: 0x00000189
0x555555758240 <node2>: 0x00000113
0x555555758250 <node3>: 0x0000007f
0x555555758260 <node4>: 0x000000ff
0x555555758270 <node5>: 0x000001fd
0x555555758110 <node6>: 0x000003b3

so the answer is 1 2 6 5 3 4 !!

Binary Bomb Phase 5 - Looking for two ints as input

Obviously line 401278 is checking that the first number is less than or equal to 10. Then some calculations are done and the next check that can explode the bomb is at 4012aa. That is comparing the result of the calculation to the second number entered. Since you are using gdb you can simply put a breakpoint on that instruction and let the program run. Enter a valid first number followed by an arbitrary second. When stopped at the breakpoint print the value in edx. That will be the correct match for the first number entered.

Another approach is spotting the condition on line 40128e. This skips the whole calculation and simply compares the second number to zero. You will need to find the correct value to trigger this which fulfills 0x10(%rsp,%rax,8) == 0. Given that line 40121a does movq $0x0,0x10(%rsp) two zeroes trivially solve the problem.

Finally, you could reverse engineer the whole thing. Notice it is summing up elements of a linked list created on the stack in the first part of the code. The summing starts with the item specified by the first number and stops when the node with value zero is reached. The second number entered should match the calculated sum.



Related Topics



Leave a reply



Submit