故意脆弱的测试程序不符合预期
我一直在玩使用strcpy,sprint,gets等的故意易受攻击的c程序.这些在
linux上运行时都表现得如预期,但在我的OS X机器上发生了一些奇怪的事情.这是我写的程序:
#include <stdio.h> int main(int argc,char **argv) { char buffer[64]; strcpy(buffer,argv[1]); printf("buffer: %sn",buffer); return 0; } 我像这样跑: (gdb) run test Starting program: /Users/****/test2 test buffer: test [Inferior 1 (process 5290) exited normally] (gdb) run `python -c 'print "A"*64'` Starting program: /Users/****/test2 `python -c 'print "A"*64'` buffer: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA [Inferior 1 (process 5291) exited normally] (gdb) run `python -c 'print "A"*70'` Starting program: /Users/****/test2 `python -c 'print "A"*70'` buffer: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA [Inferior 1 (process 5294) exited normally] (gdb) run `python -c 'print "A"*80'` Starting program: /Users/****/test2 `python -c 'print "A"*80'` buffer: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA [Inferior 1 (process 5297) exited normally] (gdb) run `python -c 'print "A"*100'` Starting program: /Users/****/test2 `python -c 'print "A"*100'` buffer: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Program received signal SIGABRT,Aborted. 0x00007fff8eef3866 in ?? () (gdb) 首先,我原本预计80个字节足以让它崩溃.第二,我期望看到0x4141414141414141而不是0x00007fff8eef3866,因为我只是试图用一堆A来覆盖一些内存.其他数据来自哪里?另外,为什么该计划获得SIGABRT?为什么没有seg故障? 这是集会: .section __TEXT,__text,regular,pure_instructions .globl _main .align 4,0x90 _main: ## @main .cfi_startproc ## BB#0: pushq %rbp Ltmp2: .cfi_def_cfa_offset 16 Ltmp3: .cfi_offset %rbp,-16 movq %rsp,%rbp Ltmp4: .cfi_def_cfa_register %rbp subq $112,%rsp movq ___stack_chk_guard@GOTPCREL(%rip),%rax movq (%rax),%rax movq %rax,-8(%rbp) leaq -96(%rbp),%rax movl $0,-12(%rbp) movl %edi,-16(%rbp) movq %rsi,-24(%rbp) movq -24(%rbp),%rsi movq 8(%rsi),%rsi movq %rax,%rdi callq _strcpy leaq L_.str(%rip),%rdi leaq -96(%rbp),-104(%rbp) ## 8-byte Spill movb $0,%al callq _printf movq ___stack_chk_guard@GOTPCREL(%rip),%rsi movq (%rsi),%rsi movq -8(%rbp),%rdi cmpq %rdi,%rsi movl %eax,-108(%rbp) ## 4-byte Spill jne LBB0_2 ## BB#1: ## %SP_return movl $0,%eax addq $112,%rsp popq %rbp ret LBB0_2: ## %CallStackCheckFailBlk callq ___stack_chk_fail .cfi_endproc .section __TEXT,__cstring,cstring_literals L_.str: ## @.str .asciz "buffer: %sn" .subsections_via_symbols [UPDATE] 实际上,没有一个寄存器似乎被覆盖,但看起来它们应该是: 启动程序:/ Users / henrypitcairn / test2 python -c’print“A”* 128′ Breakpoint 1,0x0000000100000ed4 in main () (gdb) c Continuing. buffer: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA Program received signal SIGABRT,Aborted. 0x00007fff8eef3866 in ?? () (gdb) info registers rax 0x0 0 rbx 0x7fff77921310 140735199449872 rcx 0x7fff5fbff9f8 140734799804920 rdx 0x0 0 rsi 0x6 6 rdi 0xc07 3079 rbp 0x7fff5fbffa20 0x7fff5fbffa20 rsp 0x7fff5fbff9f8 0x7fff5fbff9f8 r8 0x0 0 r9 0x0 0 r10 0x8000000 134217728 r11 0x206 518 r12 0x0 0 r13 0x0 0 r14 0x6 6 r15 0x0 0 rip 0x7fff8eef3866 0x7fff8eef3866 eflags 0x206 [ PF IF ] cs 0x7 7 ss *value not available* ds *value not available* es *value not available* fs 0x0 0 gs 0x30000 196608 (gdb) disas main Dump of assembler code for function main: 0x0000000100000ed0 <+0>: push %rbp 0x0000000100000ed1 <+1>: mov %rsp,%rbp 0x0000000100000ed4 <+4>: sub $0x70,%rsp 0x0000000100000ed8 <+8>: mov 0x131(%rip),%rax # 0x100001010 0x0000000100000edf <+15>: mov (%rax),%rax 0x0000000100000ee2 <+18>: mov %rax,-0x8(%rbp) 0x0000000100000ee6 <+22>: lea -0x60(%rbp),%rax 0x0000000100000eea <+26>: movl $0x0,-0xc(%rbp) 0x0000000100000ef1 <+33>: mov %edi,-0x10(%rbp) 0x0000000100000ef4 <+36>: mov %rsi,-0x18(%rbp) 0x0000000100000ef8 <+40>: mov -0x18(%rbp),%rsi 0x0000000100000efc <+44>: mov 0x8(%rsi),%rsi 0x0000000100000f00 <+48>: mov %rax,%rdi 0x0000000100000f03 <+51>: callq 0x100000f54 0x0000000100000f08 <+56>: lea 0x7b(%rip),%rdi # 0x100000f8a 0x0000000100000f0f <+63>: lea -0x60(%rbp),%rsi 0x0000000100000f13 <+67>: mov %rax,-0x68(%rbp) 0x0000000100000f17 <+71>: mov $0x0,%al 0x0000000100000f19 <+73>: callq 0x100000f4e 0x0000000100000f1e <+78>: mov 0xeb(%rip),%rsi # 0x100001010 0x0000000100000f25 <+85>: mov (%rsi),%rsi 0x0000000100000f28 <+88>: mov -0x8(%rbp),%rdi 0x0000000100000f2c <+92>: cmp %rdi,%rsi 0x0000000100000f2f <+95>: mov %eax,-0x6c(%rbp) 0x0000000100000f32 <+98>: jne 0x100000f43 <main+115> 0x0000000100000f38 <+104>: mov $0x0,%eax 0x0000000100000f3d <+109>: add $0x70,%rsp 0x0000000100000f41 <+113>: pop %rbp 0x0000000100000f42 <+114>: retq 0x0000000100000f43 <+115>: callq 0x100000f48 End of assembler dump. (gdb) 解决方法
从汇编代码中可以看到编译器添加了一个stack_chk_guard,以获得更多“易于操作”的程序,尝试使用-fno-stack-protector进行编译(假设它是gcc).更多选项(也在llvm中)是
here.
它还表明编译器在堆栈上为局部变量保存了112个字节,其中包括4个字节和8个字节的寄存器溢出 – 所以剩下的100个字节可能是缓冲区的一些填充用于保护,这可以解释为什么你看到它失败超过100. 你实际上没有在那里完成整个框架,你可能会超越溢出的寄存器,这解释了为什么它们在你之前的运行中似乎已经“改变”了,也可能是为什么你得到一个SIGABORT而不是seg fault以及为什么返回地址是正常的 – 你没有覆盖返回地址,你覆盖了一些寄存器(导致上帝知道什么) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |