修改带有缓冲区溢出漏洞的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变量。

方法是找到主函数的返回地址在堆栈上的位置,然后将希望得到的命令的偏移量添加到此地址。 为此:

  • 使用反汇编查找原始返回地址与新返回地址之间的差异:

  • 使用局部变量(例如函数参数)在堆栈上查找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);
    }
    
    如上所述,确切数字取决于系统(即操作系统、编译器等)。然而,使用上述技术,您应该能够找到正确的数字设置


    最后,现代编译器(如VS)可能有安全防护装置来保护堆栈损坏。如果您的程序因为它而崩溃,请检查编译器选项如何禁用此选项。

    请阅读:@AndrewMedico查看了您的示例。请看我的编辑。我不确定如何确定要向ret变量添加多少位。只需在缓冲区中写入要执行的代码(“/bin/sh”,“sh”,NULL);并修改返回地址以跳转到缓冲区。您能解释一下在第一步之后您确定的地址ret指向的jpw吗?我试图将地址打印到命令行,但它似乎与程序集转储中的任何内容都不匹配。当我将指针打印到命令行时,它看起来像“0xf201edd6”,但我对主函数的转储看起来都类似于“400600”。在我的答案中添加了一些图像以使其更清晰。