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.
Related
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
I just got started with buffer overflows and when I look for tutorials everyone has printf#plt and gets#plt in their assembler code, but I don't see them. Am I doing something wrong?
Source code:
#include <stdio.h>
#include <string.h>
int main()
{
char password[16];
int passcheck = 0;
void secret();
printf("\nWhat's the password?\n");
gets(password);
if (strcmp(password, "password1"))
{
printf("\nYou fail/n");
}
else
{
printf("\nCorrect password\n");
passcheck = 1;
}
if(passcheck)
{
secret();
}
return 0;
}
void secret()
{
printf("\nYou got it!!!\n");
}
assembler code:
0x00001e50 <+0>: push %ebp
0x00001e51 <+1>: mov %esp,%ebp
0x00001e53 <+3>: push %edi
0x00001e54 <+4>: push %esi
0x00001e55 <+5>: sub $0x40,%esp
0x00001e58 <+8>: call 0x1e5d <main+13>
0x00001e5d <+13>: pop %eax
0x00001e5e <+14>: lea 0x101(%eax),%ecx
0x00001e64 <+20>: movl $0x0,-0xc(%ebp)
0x00001e6b <+27>: movl $0x0,-0x20(%ebp)
0x00001e72 <+34>: mov %ecx,(%esp)
0x00001e75 <+37>: mov %eax,-0x24(%ebp)
0x00001e78 <+40>: call 0x1f28
0x00001e7d <+45>: lea -0x1c(%ebp),%ecx
0x00001e80 <+48>: mov %ecx,(%esp)
0x00001e83 <+51>: mov %eax,-0x28(%ebp)
0x00001e86 <+54>: call 0x1f22
0x00001e8b <+59>: lea -0x1c(%ebp),%ecx
0x00001e8e <+62>: mov -0x24(%ebp),%edx
0x00001e91 <+65>: lea 0x118(%edx),%esi
0x00001e97 <+71>: mov %esp,%edi
0x00001e99 <+73>: mov %esi,0x4(%edi)
0x00001e9c <+76>: mov %ecx,(%edi)
0x00001e9e <+78>: mov %eax,-0x2c(%ebp)
0x00001ea1 <+81>: call 0x1f2e
0x00001ea6 <+86>: cmp $0x0,%eax
0x00001ea9 <+89>: je 0x1ec8 <main+120>
0x00001eaf <+95>: mov -0x24(%ebp),%eax
0x00001eb2 <+98>: lea 0x122(%eax),%ecx
0x00001eb8 <+104>: mov %ecx,(%esp)
0x00001ebb <+107>: call 0x1f28
0x00001ec0 <+112>: mov %eax,-0x30(%ebp)
0x00001ec3 <+115>: jmp 0x1ee3 <main+147>
0x00001ec8 <+120>: mov -0x24(%ebp),%eax
0x00001ecb <+123>: lea 0x12e(%eax),%ecx
0x00001ed1 <+129>: mov %ecx,(%esp)
0x00001ed4 <+132>: call 0x1f28
0x00001ed9 <+137>: movl $0x1,-0x20(%ebp)
0x00001ee0 <+144>: mov %eax,-0x34(%ebp)
0x00001ee3 <+147>: cmpl $0x0,-0x20(%ebp)
0x00001ee7 <+151>: je 0x1ef2 <main+162>
0x00001eed <+157>: call 0x1f00 <secret>
0x00001ef2 <+162>: xor %eax,%eax
0x00001ef4 <+164>: add $0x40,%esp
0x00001ef7 <+167>: pop %esi
0x00001ef8 <+168>: pop %edi
0x00001ef9 <+169>: pop %ebp
0x00001efa <+170>: ret
0x00001efb <+171>: nopl 0x0(%eax,%eax,1)
Add debug symbols to your binaries by compiling your C program with appropriate switch for your C compiler. For example if you use gcc, use -g switch as is described here:. After that you will be able to see original C symbols names when executing your binary under gdb
Regarding your comment - maybe your object files weren't recompiled from scratch. Try to make clean if you use makefiles or just delete all the object (.o) files and then recompile your program with -ggdb switch (it is the same as -g switch but generates debug info specifically for gdb). After recompiling look in your binary for debug infor - couple of strings like 'printf#plt' and 'gets#plt'.
I am trying to modify the following C program so that the main function will skip the printf("x is 1") line and only print "x is 0".
void func(char *str) {
char buffer[24];
int *ret;
ret = buffer + 28; // Supposed to set ret to the return address of func
(*ret) += 32; // Add the offset needed so that func will skip over printf("x is 1")
strcpy(buffer, str);
}
int main(int argc, char **argv) {
int x;
x = 0;
func(argv[1]);
x = 1;
printf("x is 1");
printf("x is 0");
getchar();
}
As the comments imply, the ret pointer needs to first be set to the return address of the function. I then need to add on an offset that will push it over the line I want to skip. I am running this code on a Linux system with 2 x Intel(R) Xeon(TM) CPU 3.20GHz. I am using gcc version 4.7.2 (Debian 4.7.2-5) to compile. I'm also trying to use example3.c from this (http://insecure.org/stf/smashstack.html) link for reference. Here is a disassembly of the main function using gdb:
Dump of assembler code for function main:
0x0000000000400641 <+0>: push %rbp
0x0000000000400642 <+1>: mov %rsp,%rbp
0x0000000000400645 <+4>: sub $0x20,%rsp
0x0000000000400649 <+8>: mov %edi,-0x14(%rbp)
0x000000000040064c <+11>: mov %rsi,-0x20(%rbp)
0x0000000000400650 <+15>: movl $0x0,-0x4(%rbp)
0x0000000000400657 <+22>: mov -0x20(%rbp),%rax
0x000000000040065b <+26>: add $0x8,%rax
0x000000000040065f <+30>: mov (%rax),%rax
0x0000000000400662 <+33>: mov %rax,%rdi
0x0000000000400665 <+36>: callq 0x4005ac <func>
0x000000000040066a <+41>: movl $0x1,-0x4(%rbp)
0x0000000000400671 <+48>: mov $0x40075b,%edi
0x0000000000400676 <+53>: mov $0x0,%eax
0x000000000040067b <+58>: callq 0x400470 <printf#plt>
0x0000000000400680 <+63>: mov $0x400762,%edi
0x0000000000400685 <+68>: mov $0x0,%eax
0x000000000040068a <+73>: callq 0x400470 <printf#plt>
0x000000000040068f <+78>: callq 0x400490 <getchar#plt>
0x0000000000400694 <+83>: leaveq
0x0000000000400695 <+84>: retq
End of assembler dump.
Using what I've read from the example, my buffer is 24 bytes long and I should add an extra 4 bytes for the SFP size. This would mean I add 28 bytes to get to the return address of <+41>. It then looks like I want to jump to the last printf call at <+73>. This should be an offset of 32. However, when I execute the code, "x is 1" is still printed. I can't seem to find out why. Is there something wrong with my math or assumptions?
This looks to be an ideal time to get experience with gdb and verify that your expectations regarding the stack and the function return address locations are correct!
I will, however suggest that your modified return address should probably be at <+63>, not <+73>, as you need to run the function setup code (to pass the argument, etc).
So for my class project I am given a binary and what I have to do is bypass the security authentication. Now, once you change the binary to bypass the authentication, you have to create a C program that will replicate the "same" binary. Now, I have been struggling to understand what this area of the assembly code dump that I obtained does.
0x08048a59 <function8+54>: mov 0x8049e50,%eax
0x08048a5e <function8+59>: add $0x4,%eax
0x08048a61 <function8+62>: mov (%eax),%eax
0x08048a63 <function8+64>: movl $0x8048cd4,0x4(%esp)
I'm not very familiar with assembly, but I got most of it figured out. This is the original/entire assembly dump that I got using GDB.
0x08048a23 <function8+0>: push %ebp
0x08048a24 <function8+1>: mov %esp,%ebp
0x08048a26 <function8+3>: sub $0x28,%esp
0x08048a29 <function8+6>: movl $0xd6a1a,-0x18(%ebp)
0x08048a30 <function8+13>: mov 0x8(%ebp),%eax
0x08048a33 <function8+16>: mov %eax,-0x14(%ebp)
0x08048a36 <function8+19>: mov 0xc(%ebp),%eax
0x08048a39 <function8+22>: mov %eax,-0x10(%ebp)
0x08048a3c <function8+25>: movl $0x0,-0xc(%ebp)
0x08048a43 <function8+32>: mov -0xc(%ebp),%eax
0x08048a46 <function8+35>: mov %eax,%edx
0x08048a48 <function8+37>: sar $0x1f,%edx
0x08048a4b <function8+40>: idivl -0x18(%ebp)
0x08048a4e <function8+43>: imul -0x14(%ebp),%eax
0x08048a52 <function8+47>: imul -0x10(%ebp),%eax
0x08048a56 <function8+51>: mov %eax,-0xc(%ebp)
0x08048a59 <function8+54>: mov 0x8049e50,%eax
0x08048a5e <function8+59>: add $0x4,%eax
0x08048a61 <function8+62>: mov (%eax),%eax
0x08048a63 <function8+64>: movl $0x8048cd4,0x4(%esp)
0x08048a6b <function8+72>: mov %eax,(%esp)
0x08048a6e <function8+75>: call 0x8048434 <strcmp#plt>
0x08048a73 <function8+80>: test %eax,%eax
0x08048a75 <function8+82>: jne 0x8048a8d <function8+106>
0x08048a77 <function8+84>: mov $0x8048cdc,%eax
0x08048a7c <function8+89>: mov -0xc(%ebp),%edx
0x08048a7f <function8+92>: mov %edx,0x4(%esp)
0x08048a83 <function8+96>: mov %eax,(%esp)
0x08048a86 <function8+99>: call 0x8048414 <printf#plt>
0x08048a8b <function8+104>: jmp 0x8048a99 <function8+118>
0x08048a8d <function8+106>: movl $0x8048cfa,(%esp)
0x08048a94 <function8+113>: call 0x8048424 <puts#plt>
0x08048a99 <function8+118>: mov -0xc(%ebp),%eax
0x08048a9c <function8+121>: leave
0x08048a9d <function8+122>: ret
And so far I have managed to convert it to this in C:
int function8(one, two){
int a = 879130;
int b = one;
int c = two;
int d = 0;
d = (d / a * b * c);
if(strcmp(b, (d + 4)) == 0){
printf("You may enter using token %d", d);
}
else{
puts("You may not enter.");
}
return d;
}
int main(){
int one, two = 0;
function8(one, two);
}
I am know that
0x08048a59 <function8+54>: mov 0x8049e50,%eax
and
0x08048a63 <function8+64>: movl $0x8048cd4,0x4(%esp)
are pointing to a particular address and value respectively (correct me if I'm wrong), but don't know if I have to call it or not. If so, how do I call that particular address?
Any help would be appreciated!
Just in case you guys need it, this is my current output when I create a binary using GCC and then run GDB to get the dump:
0x08048434 <function8+0>: push %ebp
0x08048435 <function8+1>: mov %esp,%ebp
0x08048437 <function8+3>: sub $0x28,%esp
0x0804843a <function8+6>: movl $0xd6a1a,-0x18(%ebp)
0x08048441 <function8+13>: mov 0x8(%ebp),%eax
0x08048444 <function8+16>: mov %eax,-0x14(%ebp)
0x08048447 <function8+19>: mov 0xc(%ebp),%eax
0x0804844a <function8+22>: mov %eax,-0x10(%ebp)
0x0804844d <function8+25>: movl $0x0,-0xc(%ebp)
0x08048454 <function8+32>: mov -0xc(%ebp),%eax
0x08048457 <function8+35>: mov %eax,%edx
0x08048459 <function8+37>: sar $0x1f,%edx
0x0804845c <function8+40>: idivl -0x18(%ebp)
0x0804845f <function8+43>: imul -0x14(%ebp),%eax
0x08048463 <function8+47>: imul -0x10(%ebp),%eax
0x08048467 <function8+51>: mov %eax,-0xc(%ebp)
0x0804846a <function8+54>: mov -0xc(%ebp),%eax
0x0804846d <function8+57>: add $0x4,%eax
0x08048470 <function8+60>: mov %eax,0x4(%esp)
0x08048474 <function8+64>: mov -0x14(%ebp),%eax
0x08048477 <function8+67>: mov %eax,(%esp)
0x0804847a <function8+70>: call 0x8048364 <strcmp#plt>
0x0804847f <function8+75>: test %eax,%eax
0x08048481 <function8+77>: jne 0x8048499 <function8+101>
0x08048483 <function8+79>: mov $0x80485a0,%eax
0x08048488 <function8+84>: mov -0xc(%ebp),%edx
0x0804848b <function8+87>: mov %edx,0x4(%esp)
0x0804848f <function8+91>: mov %eax,(%esp)
0x08048492 <function8+94>: call 0x8048344 <printf#plt>
0x08048497 <function8+99>: jmp 0x80484a5 <function8+113>
0x08048499 <function8+101>: movl $0x80485bd,(%esp)
0x080484a0 <function8+108>: call 0x8048354 <puts#plt>
0x080484a5 <function8+113>: mov -0xc(%ebp),%eax
0x080484a8 <function8+116>: leave
0x080484a9 <function8+117>: ret
strcmp compares two strings that are passed in as pointers. The code here :
0x08048a59 <function8+54>: mov 0x8049e50,%eax
0x08048a5e <function8+59>: add $0x4,%eax
0x08048a61 <function8+62>: mov (%eax),%eax
0x08048a63 <function8+64>: movl $0x8048cd4,0x4(%esp)
0x08048a6b <function8+72>: mov %eax,(%esp)
0x08048a6e <function8+75>: call 0x8048434 <strcmp#plt>
is passing two pointers to strcmp, both of which are static/global data (not local, like you have in your C code). One is at 0x8048cd4 (that's the address of the string.. it's probably something in quotes : "example"). The other is a pointer load + 4 that's dereferenced. I'd recommend : (1) look at those addresses to see what's stored in them, and (2) if you're confused by the assembly pointer chasing, try writing simple C programs that call strcmp and seeing the resulting assembly.
good luck.
This is the part who is calling the strcmp as drivingon9 pointed.
0x08048a59 <function8+54>: mov 0x8049e50,%eax
0x08048a5e <function8+59>: add $0x4,%eax
0x08048a61 <function8+62>: mov (%eax),%eax
0x08048a63 <function8+64>: movl $0x8048cd4,0x4(%esp)
0x08048a6b <function8+72>: mov %eax,(%esp)
0x08048a6e <function8+75>: call 0x8048434 <strcmp#plt>
The result value of the strcmp will be stored in the register EAX.
Thats why we have a test eax,eax in the code bellow:
0x0804847f <function8+75>: test %eax,%eax
0x08048481 <function8+77>: jne 0x8048499 <function8+101>
0x08048483 <function8+79>: mov $0x80485a0,%eax
0x08048488 <function8+84>: mov -0xc(%ebp),%edx
The test eax, eax tests if eax register is equal to 0.
i'm not sure what part of the code will let you do what you want, but you can try change the line
0x08048481 <function8+77>: jne 0x8048499 <function8+101>
and change the instruction to a je(JUMP IF EQUAL) or a incondicional jump(JMP)
I have been trying to skip an instruction by changing the return address through stack smashing. The following code skips a++ in main and prints an output of "1 3". I have executed this code on a 32-bit intel machine.
#include<stdio.h>
void fun(int a,int b) {
// buffer
char buf[8];
char *p;
p = (char *)buf+24;
*p=*p+5;
return;
}
int main() {
int a=1,b=2;
fun(a,b);
a++;
b++;
printf("%d %d",a,b);
}
I am unable to understand why return address is stored at a displacement of 24 bytes from starting address of buf. I have tried executing the same code on a different 32-bit intel machine and I had to use a displacement of 20 bytes instead of 24 bytes. I have put my understanding in the following figure. I am not sure about what fills the gap represented by "?" in the figure. Does gcc put any canary value there or am I missing something ?
Link to figure: http://www.cse.iitb.ac.in/~shashankr/stack.png
Smashing the stack example3.c confusion asked the same question but could not explain the reason for displacement in general.
The following figure gives a view of the stack obtained by placing a breakpoint in function.
(source: shashankr at www.cse.iitb.ac.in)
The following is the assembly code for main and fun:
Dump of assembler (fun):
0x08048434 <+0>: push %ebp
0x08048435 <+1>: mov %esp,%ebp
0x08048437 <+3>: sub $0x18,%esp
0x0804843a <+6>: mov %gs:0x14,%eax
0x08048440 <+12>: mov %eax,-0xc(%ebp)
0x08048443 <+15>: xor %eax,%eax
0x08048445 <+17>: lea -0x14(%ebp),%eax
0x08048448 <+20>: add $0x18,%eax
0x0804844b <+23>: mov %eax,-0x18(%ebp)
0x0804844e <+26>: mov -0x18(%ebp),%eax
0x08048451 <+29>: movzbl (%eax),%eax
0x08048454 <+32>: add $0x5,%eax
0x08048457 <+35>: mov %eax,%edx
0x08048459 <+37>: mov -0x18(%ebp),%eax
0x0804845c <+40>: mov %dl,(%eax)
0x0804845e <+42>: mov -0xc(%ebp),%eax
0x08048461 <+45>: xor %gs:0x14,%eax
0x08048468 <+52>: je 0x804846f <fun+59>
0x0804846a <+54>: call 0x8048350 <__stack_chk_fail#plt>
0x0804846f <+59>: leave
0x08048470 <+60>: ret
Dump of assembler (main)
0x08048471 <+0>: push %ebp
0x08048472 <+1>: mov %esp,%ebp
0x08048474 <+3>: and $0xfffffff0,%esp
0x08048477 <+6>: sub $0x20,%esp
0x0804847a <+9>: movl $0x1,0x18(%esp)
0x08048482 <+17>: movl $0x2,0x1c(%esp)
0x0804848a <+25>: mov 0x1c(%esp),%eax
0x0804848e <+29>: mov %eax,0x4(%esp)
0x08048492 <+33>: mov 0x18(%esp),%eax
0x08048496 <+37>: mov %eax,(%esp)
0x08048499 <+40>: call 0x8048434 <fun>
0x0804849e <+45>: addl $0x1,0x18(%esp)
0x080484a3 <+50>: addl $0x1,0x1c(%esp)
0x080484a8 <+55>: mov $0x80485a0,%eax
0x080484ad <+60>: mov 0x1c(%esp),%edx
0x080484b1 <+64>: mov %edx,0x8(%esp)
0x080484b5 <+68>: mov 0x18(%esp),%edx
0x080484b9 <+72>: mov %edx,0x4(%esp)
0x080484bd <+76>: mov %eax,(%esp)
0x080484c0 <+79>: call 0x8048340 <printf#plt>
0x080484c5 <+84>: leave
0x080484c6 <+85>: ret
I believe the answer is nothing. Are you having different gcc versions? Anyway a compiler is allowed to allocate a bit more stack than necessary. Perhaps it's the initial "guess" based on the number of variables, but which isn't reduced by optimization stages, which are allowed to move any variable to a register. Or it's some reservoir to save ecx,ebp or other registers in case the subroutine needs to.
There's anyway one fixed address variable to overcome the problem: a.
Return address = &a[-1].