我试图找到一种方法来利用以下源代码中的缓冲区溢出漏洞,以便跳过printf("x is 1")
行:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void func(char *str) {
char buffer[24];
int *ret;
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();
}
为了做到这一点,我想修改&#34; func&#34;功能。我知道我需要使用ret变量才能将返回地址修改为刚过我要跳过的行,但我不确定如何实际执行此操作。有没有人有建议?
编辑:
通过使用gdb,我能够在main函数中找到以下调用:
Temporary breakpoint 1, 0x00000000004005ec in main ()
(gdb) x/20i $pc
=> 0x4005ec <main+4>: sub $0x20,%rsp
0x4005f0 <main+8>: mov %edi,-0x14(%rbp)
0x4005f3 <main+11>: mov %rsi,-0x20(%rbp)
0x4005f7 <main+15>: movl $0x0,-0x4(%rbp)
0x4005fe <main+22>: mov -0x20(%rbp),%rax
0x400602 <main+26>: add $0x8,%rax
0x400606 <main+30>: mov (%rax),%rax
0x400609 <main+33>: mov %rax,%rdi
0x40060c <main+36>: callq 0x4005ac <func>
0x400611 <main+41>: movl $0x1,-0x4(%rbp)
0x400618 <main+48>: mov $0x4006ec,%edi
0x40061d <main+53>: mov $0x0,%eax
0x400622 <main+58>: callq 0x400470 <printf@plt>
0x400627 <main+63>: mov $0x4006f3,%edi
0x40062c <main+68>: mov $0x0,%eax
0x400631 <main+73>: callq 0x400470 <printf@plt>
0x400636 <main+78>: callq 0x400490 <getchar@plt>
0x40063b <main+83>: leaveq
0x40063c <main+84>: retq
0x40063d: nop
虽然,我很困惑从哪里开始。我知道该函数将返回到0x400611的行,并且我需要使它跳转到0x400631,但我不确定如何确定要跳转的位数或我应该如何修改ret变量。
答案 0 :(得分:1)
想法是找到主函数的返回地址在堆栈上的位置,然后将该偏移添加到您想要得到的命令的偏移量。 要做到这一点:
使用反汇编查找原始退货地址与新退货地址之间的差异:
使用局部变量(例如函数参数)在堆栈上查找func帧地址:
最后找到堆栈上返回地址的相对位置,比较局部变量的地址:
使用上面的代码看起来像:
void func(char *str) {
// 1. Get the address of an object on the stack
long *ret = (long*)(&str);
// 2. Move ret to point to the location of the return address from this function.
// Per the example above on my system (Windows 64bit + VS) it was just -1
ret -= NUMBER_OF_ITEMS_IN_THE_STACK_BEFORE_RETURN_ADDR;
// 3. Modify the return address by adding it the offset to command to go to (in my
// (case 33).
*ret = *ret + OFFSET_TO_COMMAND;
// The rest of your code
char buffer[24];
strcpy(buffer, str);
}
如上所述,确切的数字取决于系统(即OS,编译器等)。但是,使用上述技术,您应该能够找到要设置的正确数字。
作为最后一点,现代编译器(例如VS)可能具有保护堆栈损坏的安全保护。如果您的程序因此而崩溃,请检查编译器选项如何禁用此选项。