/**********************************************************************
Study Smashing The Stack For Fun And Profit example3
This program is run on 64bit CUP that is sizeof(int *) is 8
gcc version 4.4.1
***********************************************************************/
#include <stdio.h>
void function(int a, int b, int c)
{
char buffer[5] = "abcde"; /* 5 byte buffer is really going to take 8 bytes*/
int *ret; /* the char * size is 8 byte */
int i = 0; /*the int size is 4 byte*/
char *pch = NULL; /* the char * size is 8 byte */
printf("%x\n%x\n%x\n\n", &pch, &i, &ret);
/* To find out the return address is how far away from the buffer address.
We should continue print untill the return address is print, so sometimes
we maybe use i < 30 or i < 80 is possible as the while loop conditon.
So we should have a try, i think the try is easy. */
pch = buffer;
while (i < 50)
{
printf("%8x\t %8x\t %d\n", pch, *pch, i);
pch++;
i++;
}
/* From abov print information we can out the length from buffer to return address */
ret = buffer + 40; /* ret now is point to return adddress */
printf("%x %x\n", ret, *ret);
(*ret) += 7; /* rewrite the return address */
}
void main()
{
int x;
printf("%d %d\n\n", sizeof(int), sizeof(int *));
x = 0;
function(1, 2, 3);
x = 1;
printf("%d\n", x);
}
/*
First we must know what's the return address? and how?
we can use gdb as below:
1、compiled the program:
[SmashingStack]$ gcc -o example3 example3.c
2、started gdg:
SmashingStack]$ gdb example3
GNU gdb Fedora (6.8-37.el5)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu"...
(no debugging symbols found)
(gdb) disassemble main
Dump of assembler code for function main:
0x000000000040057f <main+0>: push %rbp
0x0000000000400580 <main+1>: mov %rsp,%rbp
0x0000000000400583 <main+4>: sub $0x10,%rsp
0x0000000000400587 <main+8>: mov $0x4006ee,%eax
0x000000000040058c <main+13>: mov $0x8,%edx
0x0000000000400591 <main+18>: mov $0x4,%esi
0x0000000000400596 <main+23>: mov %rax,%rdi
0x0000000000400599 <main+26>: mov $0x0,%eax
0x000000000040059e <main+31>: callq 0x4003a0 <printf@plt>
0x00000000004005a3 <main+36>: movl $0x0,-0x4(%rbp)
0x00000000004005aa <main+43>: mov $0x3,%edx
0x00000000004005af <main+48>: mov $0x2,%esi
0x00000000004005b4 <main+53>: mov $0x1,%edi
0x00000000004005b9 <main+58>: callq 0x4004a4 <function>
0x00000000004005be <main+63>: movl $0x1,-0x4(%rbp)
0x00000000004005c5 <main+70>: mov $0x4006f7,%eax
0x00000000004005ca <main+75>: mov -0x4(%rbp),%edx
0x00000000004005cd <main+78>: mov %edx,%esi
0x00000000004005cf <main+80>: mov %rax,%rdi
0x00000000004005d2 <main+83>: mov $0x0,%eax
0x00000000004005d7 <main+88>: callq 0x4003a0 <printf@plt>
0x00000000004005dc <main+93>: leaveq
---Type <return> to continue, or q <return> to quit---
now we can know the return address is 0x00000000004005be
Second we run then example3:
[SmashingStack]$ ./example3
4 8
caf2b3e8
caf2b3f4
caf2b3f8
caf2b400 61 0
caf2b401 62 1
caf2b402 63 2
caf2b403 64 3
caf2b404 65 4
caf2b405 0 5
caf2b406 0 6
caf2b407 0 7
caf2b408 ffffffd0 8
caf2b409 22 9
caf2b40a ffffffb5 10
caf2b40b ffffffa1 11
caf2b40c 38 12
caf2b40d 0 13
caf2b40e 0 14
caf2b40f 0 15
caf2b410 20 16
caf2b411 ffffffd6 17
caf2b412 ffffff80 18
caf2b413 ffffffa0 19
caf2b414 38 20
caf2b415 0 21
caf2b416 0 22
caf2b417 0 23
caf2b418 ffffffc0 24
caf2b419 ffffffbb 25
caf2b41a ffffffa1 26
caf2b41b ffffffa0 27
caf2b41c 38 28
caf2b41d 0 29
caf2b41e 0 30
caf2b41f 0 31
caf2b420 40 32
caf2b421 ffffffb4 33
caf2b422 fffffff2 34
caf2b423 ffffffca 35
caf2b424 ffffffff 36
caf2b425 7f 37
caf2b426 0 38
caf2b427 0 39
caf2b428 ffffffbe 40
caf2b429 5 41
caf2b42a 40 42
caf2b42b 0 43
caf2b42c 0 44
caf2b42d 0 45
caf2b42e 0 46
caf2b42f 0 47
caf2b430 20 48
caf2b431 ffffffb5 49
caf2b428 4005be
0
From the output message we can found out from the buffer address to the return
address is 40(Decimal) or 0x28(Hexadecimal) length.
Now maybe we maybe we should see the assemble file of example3.c
[SmashingStack]$ gcc -S -o example3.s example3.c
SmashingStack]$ vi example3.s
.file "example3.c"
.section .rodata
.LC0:
.string "%x\n%x\n%x\n\n"
.LC1:
.string "%8x\t %8x\t %d\n"
.LC2:
.string "%x %x\n"
.text
.globl function
.type function, @function
function:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
pushq %rbx
subq $72, %rsp
movl %edi, -68(%rbp)
movl %esi, -72(%rbp)
movl %edx, -76(%rbp)
movl $1684234849, -32(%rbp)
movb $101, -28(%rbp)
movl $0, -44(%rbp)
movq $0, -56(%rbp)
movl $.LC0, %eax
leaq -40(%rbp), %rcx
leaq -44(%rbp), %rdx
leaq -56(%rbp), %rbx
.cfi_offset 3, -24
movq %rbx, %rsi
movq %rax, %rdi
movl $0, %eax
call printf
leaq -32(%rbp), %rax
movq %rax, -56(%rbp)
jmp .L2
.L3:
movl -44(%rbp), %ecx
movq -56(%rbp), %rax
movzbl (%rax), %eax
movsbl %al,%edx
movq -56(%rbp), %rbx
movl $.LC1, %eax
movq %rbx, %rsi
movq %rax, %rdi
movl $0, %eax
call printf
movq -56(%rbp), %rax
addq $1, %rax
movq %rax, -56(%rbp)
movl -44(%rbp), %eax
addl $1, %eax
movl %eax, -44(%rbp)
.L2:
movl -44(%rbp), %eax
cmpl $49, %eax
jle .L3
leaq -32(%rbp), %rax
addq $40, %rax
movq %rax, -40(%rbp)
movq -40(%rbp), %rax
movl (%rax), %edx
movq -40(%rbp), %rcx
movl $.LC2, %eax
movq %rcx, %rsi
movq %rax, %rdi
movl $0, %eax
call printf
movq -40(%rbp), %rax
movq -40(%rbp), %rdx
movl (%rdx), %edx
addl $7, %edx
movl %edx, (%rax)
addq $72, %rsp
popq %rbx
leave
ret
.cfi_endproc
.LFE0:
.size function, .-function
.section .rodata
.LC3:
.string "%d %d\n\n"
.LC4:
.string "%d\n"
.text
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
subq $16, %rsp
movl $.LC3, %eax
movl $8, %edx
movl $4, %esi
movq %rax, %rdi
movl $0, %eax
call printf
movl $0, -4(%rbp)
movl $3, %edx
movl $2, %esi
movl $1, %edi
call function
movl $1, -4(%rbp)
movl $.LC4, %eax
movl -4(%rbp), %edx
movl %edx, %esi
movq %rax, %rdi
movl $0, %eax
call printf
leave
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (GNU) 4.4.1"
.section .note.GNU-stack,"",@progbits
There have some question:
1,See the instruction: subq $72, %rsp ;why subtract 72?
2, why is 0x28 which the length of buffer address to return address?
*/