修改带有缓冲区溢出漏洞的C代码以跳过代码
我正试图找到一种方法来利用以下源代码中的缓冲区溢出漏洞,因此,修改带有缓冲区溢出漏洞的C代码以跳过代码,c,buffer-overflow,C,Buffer Overflow,我正试图找到一种方法来利用以下源代码中的缓冲区溢出漏洞,因此,printf(“x是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) {
printf(“x是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();
}
#包括
#包括
#包括
void func(字符*str){
字符缓冲区[24];
int*ret;
strcpy(缓冲区,str);
}
int main(int argc,字符**argv){
int x;
x=0;
func(argv[1]);
x=1;
printf(“x是1”);
printf(“x为0”);
getchar();
}
为此,我想修改“func”函数。我知道我需要使用ret变量来修改返回地址,使其刚好超过我想跳过的行,但我不确定如何实际做到这一点。有人有什么建议吗
编辑:
通过使用gdb,我能够在主函数中找到以下调用:
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
main()中的临时断点1,0x00000000004005ec
(gdb)x/20i$pc
=>0x4005ec:低于$0x20,%rsp
0x4005f0:mov%edi,-0x14(%rbp)
0x4005f3:mov%rsi,-0x20(%rbp)
0x4005f7:movl$0x0,-0x4(%rbp)
0x4005fe:mov-0x20(%rbp),%rax
0x400602:添加$0x8,%rax
0x400606:mov(%rax),%rax
0x400609:mov%rax,%rdi
0x40060c:callq 0x4005ac
0x400611:movl$0x1,-0x4(%rbp)
0x400618:mov$0x4006ec,%edi
0x40061d:mov$0x0,%eax
0x400622:callq 0x400470
0x400627:mov$0x4006f3,%edi
0x40062c:mov$0x0,%eax
0x400631:callq 0x400470
0x400636:callq 0x400490
0x40063b:LEVEQ
0x40063c:retq
0x40063d:nop
尽管如此,我还是不知道该怎么办。我知道函数将返回0x400611行,我需要使它跳转到0x400631,但我不确定如何确定要跳转多少位或如何修改ret变量。方法是找到主函数的返回地址在堆栈上的位置,然后将希望得到的命令的偏移量添加到此地址。 为此:
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);
}
如上所述,确切数字取决于系统(即操作系统、编译器等)。然而,使用上述技术,您应该能够找到正确的数字设置
最后,现代编译器(如VS)可能有安全防护装置来保护堆栈损坏。如果您的程序因为它而崩溃,请检查编译器选项如何禁用此选项。请阅读:@AndrewMedico查看了您的示例。请看我的编辑。我不确定如何确定要向ret变量添加多少位。只需在缓冲区中写入要执行的代码(“/bin/sh”,“sh”,NULL);并修改返回地址以跳转到缓冲区。您能解释一下在第一步之后您确定的地址ret指向的jpw吗?我试图将地址打印到命令行,但它似乎与程序集转储中的任何内容都不匹配。当我将指针打印到命令行时,它看起来像“0xf201edd6”,但我对主函数的转储看起来都类似于“400600”。在我的答案中添加了一些图像以使其更清晰。