disassemble code for 2 formats of printfs - c

I am trying to understand reasoning for seg fault with dissemble code.
Case 1.
char *p = NULL;
printf("%s", p);
O/p: No crash. it give me null. Further looking at disassemble code, it shows this one.
Dump of assembler code for function printf#plt:
0x00000000004003b8 <+0>: jmpq *0x2004aa(%rip) # 0x600868 <printf#got.plt>
0x00000000004003be <+6>: pushq $0x0
0x00000000004003c3 <+11>: jmpq 0x4003a8
End of assembler dump.
While i am trying to further go beyond this but do not know how to move to next set of instructions and what exactly it does.
Case 2.
int
main()
{
char *p = NULL;
printf("%s\n", p);
}
It leads to seg fault.
Disassemble code:
Dump of assembler code for function main:
0x00000000004004c4 <+0>: push %rbp
0x00000000004004c5 <+1>: mov %rsp,%rbp
0x00000000004004c8 <+4>: sub $0x10,%rsp
0x00000000004004cc <+8>: movq $0x0,-0x8(%rbp)
0x00000000004004d4 <+16>: mov -0x8(%rbp),%rax
0x00000000004004d8 <+20>: mov %rax,%rdi
0x00000000004004db <+23>: callq 0x4003b8 <puts#plt>
0x00000000004004e0 <+28>: leaveq
0x00000000004004e1 <+29>: retq
End of assembler dump.
(gdb) disassemble puts
Dump of assembler code for function puts#plt:
0x00000000004003b8 <+0>: jmpq *0x2004aa(%rip) # 0x600868 <puts#got.plt>
0x00000000004003be <+6>: pushq $0x0
0x00000000004003c3 <+11>: jmpq 0x4003a8
End of assembler dump.
Can u please help me to identify what assembler instruction is leading to seg fault?

0x00000000004003b8 <+0>: jmpq *0x2004aa(%rip) # 0x600868 <puts#got.plt>
Two important codewords here:
GOT -> Global Offset Table
PLT -> Procedure Linkage Table
This indicates it calls puts from dynamic library. Address of puts is not know at disassembly only time. Program must be run in order to allow dynamic linker bind address of library function to PLT slot.
What you need is:
(gdb) start
Temporary breakpoint 1 at 0x40053e: file c.c, line 9.
Starting program: /home/josef/DEVEL/test/test/a.out
Temporary breakpoint 1, main () at c.c:9
9 char *p = NULL;
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000400536 <+0>: push %rbp
0x0000000000400537 <+1>: mov %rsp,%rbp
0x000000000040053a <+4>: sub $0x10,%rsp
=> 0x000000000040053e <+8>: movq $0x0,-0x8(%rbp)
0x0000000000400546 <+16>: mov -0x8(%rbp),%rax
0x000000000040054a <+20>: mov %rax,%rdi
0x000000000040054d <+23>: callq 0x400410 <puts#plt>
0x0000000000400552 <+28>: leaveq
0x0000000000400553 <+29>: retq
End of assembler dump.
(gdb) disassemble puts
Dump of assembler code for function _IO_puts:
0x00007ffff7a84d60 <+0>: push %r12
0x00007ffff7a84d62 <+2>: mov %rdi,%r12
0x00007ffff7a84d65 <+5>: push %rbp
0x00007ffff7a84d66 <+6>: push %rbx
0x00007ffff7a84d67 <+7>: callq 0x7ffff7a9d9b0 <strlen>
0x00007ffff7a84d6c <+12>: mov 0x34fafd(%rip),%rbx # 0x7ffff7dd4870 <stdout>
0x00007ffff7a84d73 <+19>: mov %rax,%rbp
0x00007ffff7a84d76 <+22>: mov (%rbx),%eax
0x00007ffff7a84d78 <+24>: mov %rbx,%rdi
0x00007ffff7a84d7b <+27>: and $0x8000,%eax
0x00007ffff7a84d80 <+32>: jne 0x7ffff7a84ddf <_IO_puts+127>
0x00007ffff7a84d82 <+34>: mov 0x88(%rbx),%r8
......
Now you see what is inside puts. You can go forward and disassemble strlen
(gdb) disassemble strlen
Dump of assembler code for function strlen:
0x00007ffff7a9d9b0 <+0>: pxor %xmm8,%xmm8
0x00007ffff7a9d9b5 <+5>: pxor %xmm9,%xmm9
0x00007ffff7a9d9ba <+10>: pxor %xmm10,%xmm10
0x00007ffff7a9d9bf <+15>: pxor %xmm11,%xmm11
0x00007ffff7a9d9c4 <+20>: mov %rdi,%rax
0x00007ffff7a9d9c7 <+23>: mov %rdi,%rcx
0x00007ffff7a9d9ca <+26>: and $0xfff,%rcx
0x00007ffff7a9d9d1 <+33>: cmp $0xfcf,%rcx
0x00007ffff7a9d9d8 <+40>: ja 0x7ffff7a9da40 <strlen+144>
0x00007ffff7a9d9da <+42>: movdqu (%rax),%xmm12
0x00007ffff7a9d9df <+47>: pcmpeqb %xmm8,%xmm12
0x00007ffff7a9d9e4 <+52>: pmovmskb %xmm12,%edx
0x00007ffff7a9d9e9 <+57>: test %edx,%edx
0x00007ffff7a9d9eb <+59>: je 0x7ffff7a9d9f1 <strlen+65>
......
Good luck with analyzing all the code :)

Related

Function of ECX stack register in Assembly code dump

#include<stdio.h>
#include<string.h>
int main(int argc, char ** argv)
{
char buffer[500];
strcpy(buffer, argv[1]);
return 0;
}
I can compiling this program using gcc -m32 -fno-stack-protector -z execstack -fno-pie -no-pie -g -o vuln vuln.c
On disassembling the main function using the debugger, I am getting this as the output:
Dump of assembler code for function main:
0x0804840b <+0>: lea 0x4(%esp),%ecx
0x0804840f <+4>: and $0xfffffff0,%esp
0x08048412 <+7>: pushl -0x4(%ecx)
0x08048415 <+10>: push %ebp
0x08048416 <+11>: mov %esp,%ebp
0x08048418 <+13>: push %ecx
0x08048419 <+14>: sub $0x204,%esp
0x0804841f <+20>: mov %ecx,%eax
0x08048421 <+22>: mov 0x4(%eax),%eax
0x08048424 <+25>: add $0x4,%eax
0x08048427 <+28>: mov (%eax),%eax
0x08048429 <+30>: sub $0x8,%esp
0x0804842c <+33>: push %eax
0x0804842d <+34>: lea -0x1fc(%ebp),%eax
0x08048433 <+40>: push %eax
0x08048434 <+41>: call 0x80482e0 <strcpy#plt>
0x08048439 <+46>: add $0x10,%esp
0x0804843c <+49>: mov $0x0,%eax
0x08048441 <+54>: mov -0x4(%ebp),%ecx
0x08048444 <+57>: leave
0x08048445 <+58>: lea -0x4(%ecx),%esp
0x08048448 <+61>: ret
End of assembler dump.
GCC version : 6.5.0
OS : Ubuntu 16.04
GDB version : 7.11.1
The tutorial which I was refering was showed this assembly code :
Dump of assembler code for function main:
0x080483fb <+0>: push %ebp
0x080483fc <+1>: mov %esp,%ebp
0x080483fe <+3>: sub $0x1f4,%esp
0x08048404 <+9>: mov 0xc(%ebp),%eax
0x08048407 <+12>: add $0x4,%eax
0x0804840a <+15>: mov (%eax),%eax
0x0804840c <+17>: push %eax
0x0804840d <+18>: lea -0x1f4(%ebp),%eax
0x08048413 <+24>: push %eax
0x08048414 <+25>: call 0x80482d0 <strcpy#plt>
0x08048419 <+30>: add $0x8,%esp
0x0804841c <+33>: mov $0x0,%eax
0x08048421 <+38>: leave
0x08048422 <+39>: ret
End of assembler dump.
I have the following questions:
How can I get the exact same assembly code dump mentioned in the tutorial?
The difference in the output seems because of ecx register. What does that register do and why is it not part of tutorial's assembly code ?
In main function, I constructed buffer array of size 500 which is 1f4 in hexadecimal, that's why the assembly code of the tutorial is subtracting 1f4 from esp register, but my assembly code is subtracting 204 which is 516 in decimal. I am not able to understand this.
Edit: As noted in the comments, If I add -mpreferred-stack-boundary=2 to the compiler flags, then I get the same assembly code as the tutorial. Why?

printf and gets not showing in assembler code

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'.

Gdb and external functions

So I have the following code
(gdb) list
#include<stdio.h>
#include<string.h>
int main()
{
char str_a[20];
strcpy(str_a,"Hello World!\n");
printf(str_a);
}
But when I disassemble it with gdb, strcpy isn't referenced. Instead the inside of the function strcpy is shown.
(gdb) disassemble main
Dump of assembler code for function main:
0x00000000004004fd <+0>: push rbp
0x00000000004004fe <+1>: mov rbp,rsp
0x0000000000400501 <+4>: sub rsp,0x20
0x0000000000400505 <+8>: lea rax,[rbp-0x20]
0x0000000000400509 <+12>: movabs rdx,0x6f57206f6c6c6548
0x0000000000400513 <+22>: mov QWORD PTR [rax],rdx
0x0000000000400516 <+25>: mov DWORD PTR [rax+0x8],0x21646c72
0x000000000040051d <+32>: mov WORD PTR [rax+0xc],0xa
0x0000000000400523 <+38>: lea rax,[rbp-0x20]
0x0000000000400527 <+42>: mov rdi,rax
0x000000000040052a <+45>: mov eax,0x0
0x000000000040052f <+50>: call 0x4003e0 <printf#plt>
0x0000000000400534 <+55>: leave
0x0000000000400535 <+56>: ret
End of assembler dump.
How can I get GDB to reference strcpy the way it references printf?
I'm compiling with "gcc -g"
Try compiling your program with -fno-builtin.
In your gcc, strcpy is a builtin function. See also 6.56 Other Built-in Functions Provided by GCC.

Skipping an instruction using stack smashing

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].

Experimental buffer overflow in Ubuntu 10 (assembly)

I am trying to overflow buffer in Ubuntu 10.04 using a C program and diverting the return address to function "junk". But I am not able to overwrite the return address with the address of unused function "junk". It just dumps some unknown address on 12 bytes of stack. Please help me troubleshoot it. Here is the C code:-
(gdb) list
1 #include<stdio.h>
2 void display()
3 {
4 char buff[8];
5 gets(buff);
6 puts(buff);
7 }
8 main()
9 {
10 display();
(gdb)
11 return(0);
12 }
13 junk()
14 {
15 printf("cracked");
16 }
The disasambled code for main is:-
Dump of assembler code for function main:
0x08048462 <+0>: push %ebp
0x08048463 <+1>: mov %esp,%ebp
0x08048465 <+3>: call 0x8048444 <display>
0x0804846a <+8>: mov $0x0,%eax
0x0804846f <+13>: pop %ebp
0x08048470 <+14>: ret
End of assembler dump.
Dump of assembler code for function display:
0x08048444 <+0>: push %ebp
0x08048445 <+1>: mov %esp,%ebp
0x08048447 <+3>: sub $0xc,%esp
0x0804844a <+6>: lea -0x8(%ebp),%eax
0x0804844d <+9>: mov %eax,(%esp)
0x08048450 <+12>: call 0x8048350 <gets#plt>
0x08048455 <+17>: lea -0x8(%ebp),%eax
0x08048458 <+20>: mov %eax,(%esp)
0x0804845b <+23>: call 0x8048380 <puts#plt>
0x08048460 <+28>: leave
0x08048461 <+29>: ret
End of assembler dump.
Dump of assembler code for function junk:
0x08048471 <+0>: push %ebp
0x08048472 <+1>: mov %esp,%ebp
0x08048474 <+3>: sub $0x4,%esp
0x08048477 <+6>: mov $0x8048550,%eax
0x0804847c <+11>: mov %eax,(%esp)
0x0804847f <+14>: call 0x8048370 <printf#plt>
0x08048484 <+19>: leave
0x08048485 <+20>: ret
End of assembler dump.
Now i assemble it without stack protection:-
gcc -ggdb -fno-stack-protector -mpreferred-stack-boundary=2 -o buffer buffer.c
If i give input of:- printf "wwwwwwwwwwww\x72\x84\x04\x08" | ./buffer
The value:- "x72\x84\x04\x08" as the diverted address of 1st instruction of unused function "junk".
It stores some strange memory values on the 12 bytes alongwith return address also, but not my address. And again gives "Segmentation Fault". Is there some other way to exploit buffer in newer Linux flavors?
leave is equivalent to the following:
movl %ebp, %esp
popl %ebp
Thus, in your case, if you supply 'wwww' for %ebp, the program is going to try and do something like this:
movl $0x77777777, %esp ; 0x77777777 = 'wwww'
popl %ebp ; read from address 0x77777777!
You need to supply a reasonable value for %esp!

Resources