2013-11-24 3 views
0

Я написал эту простую основную информацию, которую я скомпилировал с флагом -fno-стеком-протектором.Передача параметра функции, достигнутой через переполнение буфера

#include <stdio.h> 
int pos; 
char c = 0; 

void 
bof(unsigned int i) 
{ 
    fprintf(stderr, "BOF %u\n", i); 
} 

void 
foo() 
{ 
    unsigned char buf[3]; 
    while(c != 'X') { 
    scanf(" %c", &c); 
    buf[pos++] = c; 
    } 
} 

int 
main() { 
    fprintf(stderr, "%p\n", bof); 
    foo(); 
    return 0; 
} 

Я пытаюсь передать 0 на входной переменной BOF функции, и чтобы убедиться, что я окружил адрес BOF функции с нулями. (обратите внимание, что я использую ubuntu 12.04 v. 64 бит):

perl -e 'print "\ x00" x24. "\ xa4 \ x05 \ x40 \ x00 \ x00 \ x00 \ x00 \ x00". "\ x00" x8. «X» '

Проблема заключается в том, что при выполнении программы с этим буфером результат печати не равен нулю (он даже не постоянный), но при попытке отладки программы: perl -e' print "\ x00 "x24. "\ xa4 \ x05 \ x40 \ x00 \ x00 \ x00 \ x00 \ x00". "\ x00" x8. «X»»> Файл

(gdb) b 19 
Breakpoint 4 at 0x40061b: file main.c, line 19. 
(gdb) r < file 
The program being debugged has been started already. 

Start it from the beginning? (y or n) y 
Starting program: /home/badnack/Documents/Code/stuff/bof/bof < file 
0x4005a4 

Breakpoint 4, foo() at main.c:19 
19 } 
(gdb) l 
14 unsigned char buf[3]; 
15 while(c != 'X') { 
16  scanf(" %c", &c); 
17  buf[pos++] = c; 
18 } 
19 } 
20 
21 int 
22 main() { 
23 fprintf(stderr, "%p\n", bof); 
(gdb) l 
24 foo(); 
25 return 0; 
26 } 
(gdb) disass 
Dump of assembler code for function foo: 
    0x00000000004005d0 <+0>: push %rbp 
    0x00000000004005d1 <+1>: mov %rsp,%rbp 
    0x00000000004005d4 <+4>: sub $0x10,%rsp 
    0x00000000004005d8 <+8>: jmp 0x400610 <foo+64> 
    0x00000000004005da <+10>: mov $0x400755,%eax 
    0x00000000004005df <+15>: mov $0x601040,%esi 
    0x00000000004005e4 <+20>: mov %rax,%rdi 
    0x00000000004005e7 <+23>: mov $0x0,%eax 
    0x00000000004005ec <+28>: callq 0x4004b0 <[email protected]> 
    0x00000000004005f1 <+33>: mov 0x200a4d(%rip),%eax  # 0x601044 <pos> 
    0x00000000004005f7 <+39>: movzbl 0x200a42(%rip),%edx  # 0x601040 <c> 
    0x00000000004005fe <+46>: mov %edx,%ecx 
    0x0000000000400600 <+48>: movslq %eax,%rdx 
    0x0000000000400603 <+51>: mov %cl,-0x10(%rbp,%rdx,1) 
    0x0000000000400607 <+55>: add $0x1,%eax 
    0x000000000040060a <+58>: mov %eax,0x200a34(%rip)  # 0x601044 <pos> 
    0x0000000000400610 <+64>: movzbl 0x200a29(%rip),%eax  # 0x601040 <c> 
    0x0000000000400617 <+71>: cmp $0x58,%al 
    0x0000000000400619 <+73>: jne 0x4005da <foo+10> 
=> 0x000000000040061b <+75>: leaveq 
    0x000000000040061c <+76>: retq 
End of assembler dump. 
(gdb) ni 
0x000000000040061c 19 } 
(gdb) x/10xg $rsp 
0x7fffffffe278: 0x00000000004005a4 0x0000000000000000 
0x7fffffffe288: 0x00007ffff7a3b758 0x0000000000000000 
0x7fffffffe298: 0x00007fffffffe368 0x0000000100000000 
0x7fffffffe2a8: 0x000000000040061d 0x0000000000000000 
0x7fffffffe2b8: 0xbc2b8a4223791ede 0x00000000004004c0 
(gdb) n 
bof (i=0) at main.c:7 
7 { 
(gdb) x/10xg $rsp 
0x7fffffffe280: 0x0000000000000000 0x00007ffff7a3b758 
0x7fffffffe290: 0x0000000000000000 0x00007fffffffe368 
0x7fffffffe2a0: 0x0000000100000000 0x000000000040061d 
0x7fffffffe2b0: 0x0000000000000000 0xbc2b8a4223791ede 
0x7fffffffe2c0: 0x00000000004004c0 0x00007fffffffe360 
(gdb) n 
8  fprintf(stderr, "BOF %u\n", i); 
(gdb) n 
BOF 4158473024 
9 } 
(gdb) x/10xg $rsp 
0x7fffffffe268: 0x0000000000000000 0xf7dd434000000000 
0x7fffffffe278: 0x0000000000000000 0x0000000000000000 
0x7fffffffe288: 0x00007ffff7a3b758 0x0000000000000000 
0x7fffffffe298: 0x00007fffffffe368 0x0000000100000000 
0x7fffffffe2a8: 0x000000000040061d 0x0000000000000000 
(gdb) 

переменной я, кажется, получить правильное значение, но другое значение печатается (именно десятичное представление 0xf7dd434000000000. Что происходит? Почему эта ячейка памяти не присутствовать также до?

ответ

0

Чтобы точно знать, что происходит, нам нужно будет посмотреть код ассемблера для функции bof. В любом случае, надзор в вашем подходе состоит в том, что вы не указали значение параметра в стек; -byte обратный адрес "\ xa4 \ x05 \ x40 \ x00 \ x00 \ x00 \ x00 \ x00" сбрасывается со стека по retq в foo - мы видим это от разницы между

0x7fffffffe278: 0x00000000004005a4 0x0000000000000000 
0x7fffffffe288: 0x00007ffff7a3b758 

и после retq

0x7fffffffe280: 0x0000000000000000 0x00007ffff7a3b758 

(ныне в bof). «\ X00» x8 теперь вместо обратного адреса от bof, который был бы вставлен поверх стека, если bof были вызваны регулярно на callq.

Кроме того, соглашение о вызовах используются, кажется System V Application Binary Interface, где первый (и только в этом случае) аргумент функционировать bof передаются в регистре %rdi, а не на стеке.

Смежные вопросы