栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

linux格式化字符串漏洞

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

linux格式化字符串漏洞

格式化字符串漏洞 格式化字符串介绍 常见格式化字符串函数
函数基本介绍
printf输出到stdout
fprintf输出到指定FILE流
vprintf根据参数列表格式化输出到stdout
vfprintf根据参数列表格式化输出到FILE流
sprintf输出到字符串
snprintf输出指定字节数到字符串
vsprintf根据参数列表格式化输出到字符串
vsnprintf根据参数列表格式化输出指定字节到字符串
常用格式化字符串形式
%[parameter][flags][field width][.precision][length]type

parameter:n$,获取格式化字符串中的指定参数field width:输出的最小宽度precision:输出的最大长度length,输出的长度

hh,输出一个字节h,输出一个双字节 type

d/i,有符号整数u,无符号整数x/X,16进制o,8进制s,所有字节c,char类型单个字符p,void * 型,输出对应变量的值。printf("%p",a) 用地址的格式打印变量 a 的值,printf("%p", &a) 打印变量 a 所在的地址。n,不输出字符,但是把已经成功输出的字符个数写入对应的整型指针参数所指的变量。 原理验证

示例程序:

#include

int main() {
    char s[100] = "aaaa.%p.%p.%p.%p.%p.%p.%p";
    printf(s);
    return 0;
}
32位

编译命令:

gcc test.c -g -m32 -o test

输出结果:

aaaa.0xf7ffc988.0xffffcf2a.0x56555595.0xffffcf2a.0xf7ffc984.0x61616161.0x2e70252e

栈结构:

00:0000│ esp  0xffffcee0 —▸ 0xffffcef8 ◂— 'aaaa.%p.%p.%p.%p.%p.%p.%p'
01:0004│      0xffffcee4 —▸ 0xf7ffc988 (_rtld_global_ro+136) ◂— 0x8e
02:0008│      0xffffcee8 —▸ 0xffffcf2a ◂— 0x0
03:000c│      0xffffceec —▸ 0x56555595 (main+24) ◂— add    ebx, 0x1a3f
04:0010│      0xffffcef0 —▸ 0xffffcf2a ◂— 0x0
05:0014│      0xffffcef4 —▸ 0xf7ffc984 (_rtld_global_ro+132) ◂— 0x6
06:0018│ eax  0xffffcef8 ◂— 'aaaa.%p.%p.%p.%p.%p.%p.%p'

自上而下依次是参数0~6,参数0为格式化字符串地址,而格式化字符串前4字节又作为参数6(由于栈结构不同,需要视情况而定)。因此如果将格式化字符串合适的位置设置为目标地址就可以对该地址的数据进行操作。

64位

编译命令:

gcc test.c -g -m64 -o test

输出结果:

aaaa.0x7fffffffde78.0x70.0x555555554770.0x7ffff7dced80.0x7ffff7dced80.0x2e70252e61616161.0x70252e70252e7025

寄存器:

 RAX  0x0
 RBX  0x0
 RCX  0x555555554770 (__libc_csu_init) ◂— push   r15
 RDX  0x70
 RDI  0x7fffffffdd20 ◂— 'aaaa.%p.%p.%p.%p.%p.%p.%p'
 RSI  0x7fffffffde78 —▸ 0x7fffffffe21b
 R8   0x7ffff7dced80 (initial) ◂— 0x0
 R9   0x7ffff7dced80 (initial) ◂— 0x0
 R10  0x0
 R11  0x0
 R12  0x5555555545a0 (_start) ◂— xor    ebp, ebp
 R13  0x7fffffffde70 ◂— 0x1
 R14  0x0
 R15  0x0
 RBP  0x7fffffffdd90 —▸ 0x555555554770 (__libc_csu_init) ◂— push   r15
 RSP  0x7fffffffdd20 ◂— 'aaaa.%p.%p.%p.%p.%p.%p.%p'
 RIP  0x555555554747 (main+157) ◂— call   0x555555554580

栈结构:

00:0000│ rdi rsp  0x7fffffffdd20 ◂— 'aaaa.%p.%p.%p.%p.%p.%p.%p'
01:0008│          0x7fffffffdd28 ◂— '%p.%p.%p.%p.%p.%p'
02:0010│          0x7fffffffdd30 ◂— '.%p.%p.%p'
03:0018│          0x7fffffffdd38 ◂— 0x70 
04:0020│          0x7fffffffdd40 ◂— 0x0

由于64位程序先使用rdi、rsi、rdx、rcx、r8、r9寄存器作为函数参数的前六个参数,多余的参数会依次压在栈上,因此前6个输出的为寄存器中的值(aaaa看做是格式化字符串参数),格式化字符串前8个字节作为参数6。

泄露内存 泄露栈变量内存 泄露栈变量的值

获取栈中被视为第 n + 1 n+1 n+1 个参数的值:%n$x

注意:%x其实只是%d的16进制输出,对应的是32位也就是4字节;在64位操作系统下,只会截区后32位;%p和系统位数关联没有问题,因此建议用%p。

泄露栈变量对应对应地址的内容

获取栈中被视为第 n + 1 n+1 n+1 个参数对应地址的内容:%n$s

泄露任意地址内存

获取地址addr对应的值(addr为第k个参数):addr%k$s

覆盖内存

注意:覆盖内存只能覆盖某地址对应的内存,而不是第几个参数,对于开启ASLR的程序覆盖栈上某个值要事先泄露栈地址。

pwntools生成payload

对于格式化字符串payload,pwntools也提供了一个可以直接使用的类Fmtstr,具体文档见http://docs.pwntools.com/en/stable/fmtstr.html,我们较常使用的功能是

fmtstr_payload(offset, {address:data}, numbwritten=0, write_size='byte')

offset表示格式化字符串的偏移numbwritten表示已经输出的字符个数write_size表示写入方式,是按字节(byte)、按双字节(short)还是按四字节(int),对应着hhn、hn和n,默认值是byte,即按hhn写。

注意:部分题目会限制时间,导致pwntools生成的payload失效。一般这一类题目可以通过仅修改低地址等操作减小输出长度,这时需要手动构造payload。

手动构造payload 覆盖小数字

对于小于机器字长的数字,如果把地址放在格式化字符串前面会使得已输出字符个数大于数字大小,因此要将地址放在后面。

以数字2为例:aa%k$n[padding][addr]

覆盖大数字

直接一次性输出大数字个字节来进行覆盖时间过长,因此需要把大数字拆分成若干个部分,分别进行覆盖。比如hhn按字节写或hn按双字写。

以hhn写入32bit数为例,payload形式为:[addr][addr+1][addr+2][addr+3][pad1]%k$hhn[pad2]%(k+1)$hhn[pad3]%(k+2)$hhn[pad4]%(k+3)$hhn

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/729772.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号