Binary Bomb (Phase 4) %d %d - c

I have binary Phase that is not returning required result i.e 12. Any suggestions?
Phase 4
Dump of assembler code for function phase_4:
0x000000000040100b <+0>: sub $0x18,%rsp
0x000000000040100f <+4>: lea 0x8(%rsp),%rcx
0x0000000000401014 <+9>: lea 0xc(%rsp),%rdx
0x0000000000401019 <+14>: mov $0x40278d,%esi
0x000000000040101e <+19>: mov $0x0,%eax
0x0000000000401023 <+24>: callq 0x400b90 <__isoc99_sscanf#plt>
0x0000000000401028 <+29>: cmp $0x2,%eax
=> 0x000000000040102b <+32>: je 0x401054 <phase_4+73>
0x000000000040102d <+34>: callq 0x401538 <explode_bomb>
0x0000000000401032 <+39>: mov $0xe,%edx
0x0000000000401037 <+44>: mov $0x0,%esi
0x000000000040103c <+49>: mov 0xc(%rsp),%edi
0x0000000000401040 <+53>: callq 0x400fd7 <func4>
0x0000000000401045 <+58>: cmp $0x12,%eax
0x0000000000401048 <+61>: je 0x40105d <phase_4+82>
0x000000000040104a <+63>: callq 0x401538 <explode_bomb>
0x000000000040104f <+68>: add $0x18,%rsp
0x0000000000401053 <+72>: retq
0x0000000000401054 <+73>: cmpl $0xe,0xc(%rsp)
0x0000000000401059 <+78>: jbe 0x401032 <phase_4+39>
0x000000000040105b <+80>: jmp 0x40102d <phase_4+34>
0x000000000040105d <+82>: cmpl $0x12,0x8(%rsp)
0x0000000000401062 <+87>: jne 0x40104a <phase_4+63>
0x0000000000401064 <+89>: jmp 0x40104f <phase_4+68>
End of assembler dump.
func4 is as follows:
Dump of assembler code for function func4:
=> 0x0000000000400fd7 <+0>: push %rbx
0x0000000000400fd8 <+1>: mov %edx,%eax
0x0000000000400fda <+3>: sub %esi,%eax
0x0000000000400fdc <+5>: mov %eax,%ebx
0x0000000000400fde <+7>: shr $0x1f,%ebx
0x0000000000400fe1 <+10>: add %eax,%ebx
0x0000000000400fe3 <+12>: sar %ebx
0x0000000000400fe5 <+14>: add %esi,%ebx
0x0000000000400fe7 <+16>: cmp %edi,%ebx
0x0000000000400fe9 <+18>: jg 0x400ff3 <func4+28>
0x0000000000400feb <+20>: cmp %edi,%ebx
0x0000000000400fed <+22>: jl 0x400fff <func4+40>
0x0000000000400fef <+24>: mov %ebx,%eax
0x0000000000400ff1 <+26>: pop %rbx
0x0000000000400ff2 <+27>: retq
0x0000000000400ff3 <+28>: lea -0x1(%rbx),%edx
0x0000000000400ff6 <+31>: callq 0x400fd7 <func4>
0x0000000000400ffb <+36>: add %eax,%ebx
0x0000000000400ffd <+38>: jmp 0x400fef <func4+24>
0x0000000000400fff <+40>: lea 0x1(%rbx),%esi
0x0000000000401002 <+43>: callq 0x400fd7 <func4>
0x0000000000401007 <+48>: add %eax,%ebx
0x0000000000401009 <+50>: jmp 0x400fef <func4+24>
End of assembler dump.
I have written a test C program that I believe equivalent to above assembly code for func4.
#include <stdio.h>
int main()
{
int i=0;
for(int i=0;i<15;i++)
{
int z=func4(i,0,14);
printf("in main program: For input %d -> %d\n",i,z);
}
return 0;
}
int func4(int x, int low, int high) {
int mid = (low + high) / 2;
if (x == mid) {
return (mid);
} else if (x < mid) {
int w=mid+func4(x, low, mid - 1);
return w;
} else {
int p=mid+func4(x, mid + 1, high);
return p;
}
}
This program returns OUTPUT as follows:
in main program: For input 0 -> 11
in main program: For input 1 -> 11
in main program: For input 2 -> 13
in main program: For input 3 -> 10
in main program: For input 4 -> 19
in main program: For input 5 -> 15
in main program: For input 6 -> 21
in main program: For input 7 -> 7
in main program: For input 8 -> 35
in main program: For input 9 -> 27
in main program: For input 10 -> 37
in main program: For input 11 -> 18
in main program: For input 12 -> 43
in main program: For input 13 -> 31
in main program: For input 14 -> 45
I figured out that function will take two arguments and the second argument should be 12. But I am not to get value 12 returned from func4.
Any suggestions??

The assembly code is actually expecting a value of 0x12 (18 rather than 12) from func4:
0x0000000000401040 <+53>: callq 0x400fd7 <func4>
0x0000000000401045 <+58>: cmp $0x12,%eax <- Compare result to 0x12
0x0000000000401048 <+61>: je 0x40105d <phase_4+82>
0x000000000040104a <+63>: callq 0x401538 <explode_bomb>
I haven't looked at your C translation of func4 for correctness, but assuming it's correct it looks like func4(11, 0, 14) gives you what you want.

Related

how to defuse this binary bomb phase 4

I am having trouble this piece of code in assembly language.
Essentially I have to input 2 numbers that matches 2 numbers the code is comparing with.
On line 0x08048c47 in phase_4, it compares the first input with 2, so I know the first input has to be 2. It then moves 4 spaces from the first input to next input, which then gets 2 subtracted from it. Now the (input-2) is compared with 2. It will continue the instruction if the inputs are below than or equal to 2. I've tested this with numbers 2,3,4 which pass the comparison. Other numbers greater than 4 and less than 2 do not pass the comparison and will cause the bomb to explode.
I'm stuck on this part because the value being returned from func4 is not the same was the value represented at 0x08048c6e in phase_4, which is 8(%esp). On my computer when I debug it, it shows that it is 8, and the answers to my inputs 2,3,4 are 40, 60, 80 respectively.
disas func4
0x08048bda <+0>: push %edi
0x08048bdb <+1>: push %esi
0x08048bdc <+2>: push %ebx
0x08048bdd <+3>: mov 0x10(%esp),%ebx
0x08048be1 <+7>: mov 0x14(%esp),%edi
0x08048be5 <+11>: test %ebx,%ebx
0x08048be7 <+13>: jle 0x8048c14 <func4+58>
0x08048be9 <+15>: mov %edi,%eax
0x08048beb <+17>: cmp $0x1,%ebx
0x08048bee <+20>: je 0x8048c19 <func4+63>
0x08048bf0 <+22>: sub $0x8,%esp
0x08048bf3 <+25>: push %edi
0x08048bf4 <+26>: lea -0x1(%ebx),%eax
0x08048bf7 <+29>: push %eax
0x08048bf8 <+30>: call 0x8048bda <func4>
0x08048bfd <+35>: add $0x8,%esp
0x08048c00 <+38>: lea (%edi,%eax,1),%esi
0x08048c03 <+41>: push %edi
0x08048c04 <+42>: sub $0x2,%ebx
0x08048c07 <+45>: push %ebx
0x08048c08 <+46>: call 0x8048bda <func4>
0x08048c0d <+51>: add $0x10,%esp
0x08048c10 <+54>: add %esi,%eax
0x08048c12 <+56>: jmp 0x8048c19 <func4+63>
0x08048c14 <+58>: mov $0x0,%eax
0x08048c19 <+63>: pop %ebx
0x08048c1a <+64>: pop %esi
0x08048c1b <+65>: pop %edi
0x08048c1c <+66>: ret
disas phase_4
0x08048c1d <+0>: sub $0x1c,%esp
0x08048c20 <+3>: mov %gs:0x14,%eax
0x08048c26 <+9>: mov %eax,0xc(%esp)
0x08048c2a <+13>: xor %eax,%eax
0x08048c2c <+15>: lea 0x4(%esp),%eax
0x08048c30 <+19>: push %eax
0x08048c31 <+20>: lea 0xc(%esp),%eax
0x08048c35 <+24>: push %eax
0x08048c36 <+25>: push $0x804a25f
0x08048c3b <+30>: pushl 0x2c(%esp)
0x08048c3f <+34>: call 0x8048810 <__isoc99_sscanf#plt>
0x08048c44 <+39>: add $0x10,%esp
0x08048c47 <+42>: cmp $0x2,%eax
0x08048c4a <+45>: jne 0x8048c58 <phase_4+59>
0x08048c4c <+47>: mov 0x4(%esp),%eax
0x08048c50 <+51>: sub $0x2,%eax
0x08048c53 <+54>: cmp $0x2,%eax
0x08048c56 <+57>: jbe 0x8048c5d <phase_4+64>
0x08048c58 <+59>: call 0x8049123 <explode_bomb>
0x08048c5d <+64>: sub $0x8,%esp
0x08048c60 <+67>: pushl 0xc(%esp)
0x08048c64 <+71>: push $0x6
0x08048c66 <+73>: call 0x8048bda <func4>
0x08048c6b <+78>: add $0x10,%esp
0x08048c6e <+81>: cmp 0x8(%esp),%eax
0x08048c72 <+85>: je 0x8048c79 <phase_4+92>
0x08048c74 <+87>: call 0x8049123 <explode_bomb>
0x08048c79 <+92>: mov 0xc(%esp),%eax
0x08048c7d <+96>: xor %gs:0x14,%eax
0x08048c84 <+103>: je 0x8048c8b <phase_4+110>
0x08048c86 <+105>: call 0x8048790 <__stack_chk_fail#plt>
0x08048c8b <+110>: add $0x1c,%esp
0x08048c8e <+113>: ret
8(%esp) is the first number, under the framework of x86.
enter 40 2 or 60 3 or 80 4 should work.
Equivalent to the following logic
#include <stdio.h>
#include <stdlib.h>
void explode_bomb()
{
printf("explode bomb.\n");
exit(1);
}
unsigned func4(int val, unsigned num)
{
int ret;
if (val <= 0)
return 0;
if (num == 1)
return 1;
ret = func4(val - 1, num);
ret += num;
val -= 2;
ret += func4(val, num);
return ret;
}
void phase_4(const char *input)
{
unsigned num1, num2;
if (sscanf(input, "%u %u", &num1, &num2) != 2)
explode_bomb();
if (num2 - 2 > 2)
explode_bomb();
if (func4(6, num2) != num1)
explode_bomb();
}
int main()
{
phase_4("40 2");
phase_4("60 3");
phase_4("80 4");
printf("success.\n");
return 0;
}

A few doubts on my C program to check prime [duplicate]

This question already has answers here:
Reaching end of function without return statement
(2 answers)
Closed 4 years ago.
This is a simple function to check whether the given number is prime or not and works for the most part except for 2 and 3 (as it doesn't enter the for loop) but they are already prime so no checking is required and the flag should remain untouched.But notice how I put the return statement inside the for loop(This was by mistake) so for integers 2 and 3 as they do not enter the loop the function should return 0(or so I assumed) but they always return 1.why? Is it because the program terminated incorrectly? then why always 1? it can be any non-zero integer right?and are there cases where the main() itself returns a 1?.Please clarify my doubts.Dev-C++ is the IDE used and it uses tdm-gcc 4.9.2 compiler.
int checkPrime(int n)
{
int i, isPrime = 0;
for(i = 2; i <= n/2; ++i) {
if(n % i == 0) {
isPrime = 1;
break;
}
return isPrime;
}
}
Your return statement is in wrong place. You should put it out of for loop. And also in programming 1 stands for true and 0 for false, so you are asking if n is prime and for 17 your function returns 0 (false), but it is prime:
int checkPrime(int n)
{
int i, isPrime = 1;
for(i = 2; i <= n/2; ++i) {
if(n % i == 0) {
isPrime = 0;
break;
}
}
return isPrime;
}
On x86 architecture, the return value of function is in %eax register.
Value present there would be regarded as the return value of the function checkPrime.
And in the %eax register, the value present would be '1', so '1' was treated as the return value.
Proof (Passing '2' to checkPrime() and at the end eax holds 1):-
Dump of assembler code for function checkPrime:
0x0000000000400526 <+0>: push %rbp
0x0000000000400527 <+1>: mov %rsp,%rbp
0x000000000040052a <+4>: mov %edi,-0x14(%rbp)
0x000000000040052d <+7>: movl $0x0,-0x8(%rbp)
0x0000000000400534 <+14>: movl $0x2,-0x4(%rbp)
0x000000000040053b <+21>: nop
0x000000000040053c <+22>: mov -0x14(%rbp),%eax
0x000000000040053f <+25>: mov %eax,%edx
0x0000000000400541 <+27>: shr $0x1f,%edx
0x0000000000400544 <+30>: add %edx,%eax
0x0000000000400546 <+32>: sar %eax
0x0000000000400548 <+34>: cmp -0x4(%rbp),%eax
0x000000000040054b <+37>: jl 0x400568 <checkPrime+66>
0x000000000040054d <+39>: mov -0x14(%rbp),%eax
0x0000000000400550 <+42>: cltd
0x0000000000400551 <+43>: idivl -0x4(%rbp)
0x0000000000400554 <+46>: mov %edx,%eax
0x0000000000400556 <+48>: test %eax,%eax
0x0000000000400558 <+50>: jne 0x400563 <checkPrime+61>
0x000000000040055a <+52>: movl $0x1,-0x8(%rbp)
0x0000000000400561 <+59>: jmp 0x400568 <checkPrime+66>
0x0000000000400563 <+61>: mov -0x8(%rbp),%eax
0x0000000000400566 <+64>: jmp 0x400568 <checkPrime+66>
0x0000000000400568 <+66>: pop %rbp
0x0000000000400569 <+67>: retq
(gdb) break *0x0000000000400569
Breakpoint 1 at 0x400569: file ./test.c, line 19.
(gdb) r
Starting program: /home/syed/Desktop/a.out
Breakpoint 1, 0x0000000000400569 in checkPrime (n=2) at ./test.c:19
19 }
(gdb) info registers eax
eax 0x1 1

instructions related to parameter passing of variable argument function "printf"

In the program binary, how to determine the instructions related to parameter passing of variable argument function "printf"? For example:
#include <stdio.h>
#include <string.h>
int fun(int a, int b){
return a+b;
}
void main (int argc, char* argv[]){
int a = 0;
int b = 1;
int c = 2;
int d = 3;
printf("a:fun(b,c):d: %d:%d:%d\n", a, fun(b,c), d);
}
is assembled as follows:
(gdb) disas main
Dump of assembler code for function main:
0x080483f1 <+0>: push %ebp
0x080483f2 <+1>: mov %esp,%ebp
0x080483f4 <+3>: and $0xfffffff0,%esp
0x080483f7 <+6>: sub $0x20,%esp
0x080483fa <+9>: movl $0x0,0x10(%esp)
0x08048402 <+17>: movl $0x1,0x14(%esp)
0x0804840a <+25>: movl $0x2,0x18(%esp)
0x08048412 <+33>: movl $0x3,0x1c(%esp)
0x0804841a <+41>: mov 0x18(%esp),%eax
0x0804841e <+45>: mov %eax,0x4(%esp)
0x08048422 <+49>: mov 0x14(%esp),%eax
0x08048426 <+53>: mov %eax,(%esp)
0x08048429 <+56>: call 0x80483e4 <fun>
=> 0x0804842e <+61>: mov $0x8048530,%edx
0x08048433 <+66>: mov 0x1c(%esp),%ecx
0x08048437 <+70>: mov %ecx,0xc(%esp)
0x0804843b <+74>: mov %eax,0x8(%esp)
0x0804843f <+78>: mov 0x10(%esp),%eax
0x08048443 <+82>: mov %eax,0x4(%esp)
=> 0x08048447 <+86>: mov %edx,(%esp)
0x0804844a <+89>: call 0x8048300 <printf#plt>
0x0804844f <+94>: leave
0x08048450 <+95>: ret
Whether the instructions related to parameter passing of variable argument function "print" are instructions between two instructions "0x0804842e <+61>: mov $0x8048530,%edx" and " 0x08048447 <+86>: mov %edx,(%esp)".
I have tested many cases of function "printf". In all my tested cases, the instructions related to parameter passing are between these two instructions.
You can find this out by knowing the C calling convention. That is arguments are pushed onto the stack in reverse order.
`0x0804842e <+61>: mov $0x8048530,%edx //Probably the string literal
0x08048433 <+66>: mov 0x1c(%esp),%ecx //Moving 3 literal into %ecx
0x08048437 <+70>: mov %ecx,0xc(%esp) // moving 3 onto top of the arguments on the stack (%esp is the stack pointer)
0x0804843b <+74>: mov %eax,0x8(%esp) //Moving return value from fun onto next slot in the stack, %eax store the return value from a function.
0x0804843f <+78>: mov 0x10(%esp),%eax //Moving 0 literal into %eax
0x08048443 <+82>: mov %eax,0x4(%esp) //Moving %eax into next slot in the stack
0x08048447 <+86>: mov %edx,(%esp) //moving string literal onto the stack
0x0804844a <+89>: call 0x8048300 `//calling printf

C asm jmp going back to jmp after performing the jmp

I'm performing a relative jump in some asm code in C. I've got the jump working as intended, but it goes back to right after the jump happens and finished running the code.
#include <stdio.h>
void function() {
asm("jmp .+0x31"); //this happens to be where I want to jump to from the function call
}
void main(int argc, char* argv[]) {
int x;
x = 0;
function();
x = 1;
x = x + 1;
printf("%d\n", x);
}
0x000000000040053f <+0>: push %rbp
0x0000000000400540 <+1>: mov %rsp,%rbp
0x0000000000400543 <+4>: sub $0x20,%rsp
0x0000000000400547 <+8>: mov %edi,-0x14(%rbp)
0x000000000040054a <+11>: mov %rsi,-0x20(%rbp)
0x000000000040054e <+15>: movl $0x0,-0x4(%rbp)
0x0000000000400555 <+22>: mov $0x0,%eax
0x000000000040055a <+27>: callq 0x400536 <function>
0x000000000040055f <+32>: movl $0x1,-0x4(%rbp)
0x0000000000400566 <+39>: addl $0x1,-0x4(%rbp)
0x000000000040056a <+43>: mov -0x4(%rbp),%eax
0x000000000040056d <+46>: mov %eax,%esi
0x000000000040056f <+48>: mov $0x400620,%edi
0x0000000000400574 <+53>: mov $0x0,%eax
0x0000000000400579 <+58>: callq 0x400410 <printf#plt>
0x000000000040057e <+63>: nop
0x000000000040057f <+64>: leaveq
0x0000000000400580 <+65>: retq
Following the call of function(), it prints a 0 as intended, but it then goes back through the code after function() is called and prints 2 as well. Am I missing how jmp works? Is there a way to exit via asm code?
The goal of this is to skip
x = 1;
x = x + 1;
and just print 0, then exit the file.
Since function doesn't execute a ret instruction, its return address is still there on the stack. That is, when main executes its ret, the return address it uses is in fact an address left by function, and lands back at x = 1; line.
To achieve your goal, function before doing a jump must adjust the stack pointer as if it has never been called.
That said, don't try this at home.

Bomb lab phase 4 func4

I'm having trouble with the password for phase_4 of my binary bomb.
So far, I understand...
the inputs must be 2 integers (line 29)
and the second integer should <= than or equal to 2 when 2 is subtracted from it (lines 38-44). Which means it should be a number 2-4
Then, it calls func4, and compares the output of func4 to rsp (which I've done some testing and rsp is always 0) so i need to find a number that returns 0 when inputed into func4.
Whats confusing me is: if the result of func4 needs to be 0, that means it's input should be 0. Taking into account line 38 in phase_4 where it subtracts 2 from my input, that should mean my second # should be 2...? However I have tried that and it makes it explode in line 46 as it doesn't satisfy the first comparison.
I have tried numbers like (0 2) (2 0) (0 1) (0 3) and they all failed. Any suggestions to point me in the right direction? Thanks!
phase_4:
0x000000000040101e <+0>: sub $0x18,%rsp
0x0000000000401022 <+4>: lea 0xc(%rsp),%rcx
0x0000000000401027 <+9>: lea 0x8(%rsp),%rdx
0x000000000040102c <+14>: mov $0x4027cd,%esi
0x0000000000401031 <+19>: mov $0x0,%eax
0x0000000000401036 <+24>: callq 0x400c30 <__isoc99_sscanf#plt>
0x000000000040103b <+29>: cmp $0x2,%eax //check if 2 inputs
0x000000000040103e <+32>: jne 0x40104c <phase_4+46>
0x0000000000401040 <+34>: mov 0xc(%rsp),%eax
=> 0x0000000000401044 <+38>: sub $0x2,%eax
0x0000000000401047 <+41>: cmp $0x2,%eax
0x000000000040104a <+44>: jbe 0x401051 <phase_4+51>//if unsigned eax <= 2
0x000000000040104c <+46>: callq 0x401554 <explode_bomb>
0x0000000000401051 <+51>: mov 0xc(%rsp),%esi
0x0000000000401055 <+55>: mov $0x7,%edi
0x000000000040105a <+60>: callq 0x400fe6 <func4>
0x000000000040105f <+65>: cmp 0x8(%rsp),%eax //comparing eax to 0
0x0000000000401063 <+69>: je 0x40106a <phase_4+76>
0x0000000000401065 <+71>: callq 0x401554 <explode_bomb> //explode if output != 0
0x000000000040106a <+76>: add $0x18,%rsp
0x000000000040106e <+80>: retq
Func4
0x0000000000400fe6 <+0>: push %r12
0x0000000000400fe8 <+2>: push %rbp
0x0000000000400fe9 <+3>: push %rbx
0x0000000000400fea <+4>: mov %edi,%ebx
0x0000000000400fec <+6>: test %edi,%edi
0x0000000000400fee <+8>: jle 0x401014 <func4+46> //if input <= 0
0x0000000000400ff0 <+10>: mov %esi,%ebp
0x0000000000400ff2 <+12>: mov %esi,%eax
0x0000000000400ff4 <+14>: cmp $0x1,%edi
0x0000000000400ff7 <+17>: je 0x401019 <func4+51>
0x0000000000400ff9 <+19>: lea -0x1(%rdi),%edi
0x0000000000400ffc <+22>: callq 0x400fe6 <func4>
0x0000000000401001 <+27>: lea (%rax,%rbp,1),%r12d
0x0000000000401005 <+31>: lea -0x2(%rbx),%edi
0x0000000000401008 <+34>: mov %ebp,%esi
0x000000000040100a <+36>: callq 0x400fe6 <func4>
0x000000000040100f <+41>: add %r12d,%eax
0x0000000000401012 <+44>: jmp 0x401019 <func4+51>
0x0000000000401014 <+46>: mov $0x0,%eax //make return val 0
0x0000000000401019 <+51>: pop %rbx
0x000000000040101a <+52>: pop %rbp
0x000000000040101b <+53>: pop %r12
0x000000000040101d <+55>: retq
Then, it calls func4, and compares the output of func4 to rsp (which
I've done some testing and rsp is always 0) so i need to find a number
that returns 0 when inputed into func4.
This is incorrect. The output of func4 is compared with [rsp + 8], in which the first number was stored.
If we write the desired input as (a, b), then we have a = func4 (7, b) and 2 <= b <= 4.
To understand what func4 (x, y) does I recommend that you convert it to C. See my answer to this question for an illustration.

Resources