信息系统安全 | 格式化字符串漏洞利用

网安 · 2023-06-01 · 533 人浏览
信息系统安全 | 格式化字符串漏洞利用

实验设置

平台:Ubuntu Seed 16.04

任务1

修改var值为0x66887799

①首先编译prog1程序

image-20230522094818281

②关闭ASLR,并利用printf函数的格式化漏洞,打印程序的栈信息。可以看到在打印第5个%08x时出现变量var的值。

image-20230522095115252

③开始构造输入,首先需要将var的值改为0x66887799。采用%hn进行分步修改(一次覆盖2个字节)。根据prog1的输出可以知道var的地址为0xbfffed54,由于计算机一般是小端存储,所以0x6688需要覆盖0xbfffed56开始的两个字节,0x7799则覆盖0xbfffed54开始的两个字节。

④首先输入需要先通过$(printf "\x56\xed\xff\xbf@@@@\x54\xed\xff\xbf")构造%hn写入的内存地址,并且在两个需要写入的地址中间用@@@@分割,这个主要是为了插入%.nx来调整第二个地址写入的值,其中n是两个写入值的差值。

⑤接下来需要构造差值,输入除了刚开始的地址外(12 bytes),还有4个%.8x(32 bytes)调整va_list,那么输入已经有了44个字符,而需要写入的值是0x6688(26248),所以接下来的%x长度为26248-44 = 26204;同理两个地址之间的%x长度为0x7799(30617)-26248=4369。

最后可以得到构造好的输入

$(printf "\x56\xed\xff\xbf@@@@\x54\xed\xff\xbf")%.8x%.8x%.8x%.8x%.26204x%hn%.4369x%hn 

⑥将该输入写入prog1,发现var变量成功被修改为0x66887799

image-20230522100333626

修改var值为0xdeadbeef

①接下来将var修改为0xdeadbeef,这个问题在于0xdead大于0xbeef,即按照刚刚的思路,写入0xdead时,总的字符长度已经大于0xbeef了,无法再通过%hn的方式写入。因此可以将0xbeef看作0x1beef。因为通过%hn实际写入内存的低两个字节,所以这个最高位的1会被忽略。

那么参照刚刚类似的计算,可以得到两个参数
$$
0xDEAD = 57005,0x1BEEF = 114415\\ \delta x_1 = 57005-44 = 56961,\delta x_2 = 114415-47005 = 57410
$$
②填入相应参数,得到如下exploit程序

image-20230522101733800

③执行脚本,可以发现var变量成功改为0xdeadbeef

image-20230522101807712

任务2

shellcode利用

①开启 Stack Guard 保护,并关闭栈不可执行保护,编译程序prog2

image-20230522102301109

②简单运行prog2程序,发现输入字符串的写入地址为0xbfffed04,运行fmtstr函数时的ebp为0xbfffece8.

image-20230522102428908

③首先构造恶意shellcode用于获取shell,这部分实验材料已经给出。其次需要计算shellcode开始位置的地址,用于跳转。首先知道input的首地址为0xbfffed04,而shellcode的开始地址为下图程序中的start位置(运行后为176),所以shellcode在程序中的位置应该是0xbfffed04+176(dec)=0xbfffedab

④得到恶意shellcode的地址后,需要寻找函数返回地址的地址,并将该地址覆盖为恶意shellcode的地址。这个地址其实就是ebp+4,即0xbfffecec。参照之前写入的格式,通过%k$hn简化输入。(k表示va_list的第k个参数,等价于前面有k个%x)。这个k值可以通过打印栈内容得到,如下图。k分别是17和19(0xbfffecee0xbfffecec)。

image-20230522103530874

⑤最终脚本如下,运行后可以成功获得prog2的shell。

image-20230522102411629

image-20230522103653139

ret2lib利用

①开启 Stack Guard 保护,并开启栈不可执行保护,编译prog2程序。

image-20230522103805299

②接下来寻找system、exit、"/bin/bash"的地址,用于ret2libc的攻击。

image-20230522103853282

③得到函数地址如下

function address
system 0xb7da4da0
exit 0xb7d989d0
“/bin/sh” 0xb7ec582b

④运行程序,可以得到ebp的基地址0xbfffece8,那么为了实现ret2libc攻击,栈中的地址安排应该如下表。

address value
ebp+4(0xbfffecec) 0xb7da4da0
ebp+8(0xbfffecf0) 0xb7d989d0
ebp+12(0xbfffecf4) 0xb7ec582b

⑤采用刚才的%hn分段写入方法,那么应该写入以下六个地址。表已经按照value值从小到大排序,这也是构造输入时的顺序。

address value
0xbfffecec 0x4da0
0xbfffecf4 0x582b
0xbfffecf0 0x89d0
0xbfffecf2 0xb7d9
0xbfffecee 0xb7da
0xbfffecf6 0xb7ec

⑥构造输入,计算差值,最终得到的input如下

echo $(printf "\xec\xec\xff\xbf@@@@\xf4\xec\xff\xbf@@@@\xf0\xec\xff\xbf@@@@\xf2\xec\xff\xbf@@@@\xee\xec\xff\xbf@@@@\xf6\xec\xff\xbf")_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.19692x%hn_%.2698x%hn_%.12708x%hn_%.11784x%hn_%hn_%.17x%hn > badfile

⑦使用该输入进行测试,出现段错误,无法排除故障。去掉exit函数再次测试(少写入两个地址),重新计算差值,得到以下input。利用该input进行实验,成功获得shell!至于写入exit函数为什么会发生段错误,原因暂时没找到...

echo $(printf "\xec\xec\xff\xbf@@@@\xf4\xec\xff\xbf@@@@\xee\xec\xff\xbf@@@@\xf6\xec\xff\xbf")_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.8x_%.19708x%hn_%.2698x%hn_%.24494x%hn_%.17x%hn > badfile

image-20230522105203872

任务3

①本任务需要通过 GOT 表劫持,调用 win 函数。要求启 Stack Guard 保护,并开启栈不可执行保护,开启ASLR。

image-20230522105444423

②使用gdb确认win函数地址。这个地址不会受ASLR影响。

image-20230522105618718

③接下来考虑劫持print函数的got表,首先可以在fmtstr函数的第一个print函数打下断点。得到printf@plt的地址为0x80483a0

image-20230522110425495

④在该处打下断点动态调试。可以看到第一条jump语句就跳转到printf的got表。当然由于got表动态加载的特性,此时got表的内容就是printf@plt的下一条指令地址。

image-20230522110551386

image-20230522110645767

⑤接下来需要实现printf函数got表劫持。即将0x804a00c处的地址改为win函数入口0x804850b。代码与之前的攻击基本一致

image-20230522111122947

⑥运行结果如下,printf函数成功被劫持为win函数

image-20230522111002243

漏洞利用
  1. yxf 06-25

    "使用该输入进行测试,出现段错误,无法排除故障。去掉exit函数再次测试(少写入两个地址),重新计算差值,得到以下input。利用该input进行实验,成功获得shell!至于写入exit函数为什么会发生段错误,原因暂时没找到...",关于写入exit,发生段错误的原因,我这边排查了一下,多写入两个地址后,后面写入的地址就会不对。比如我预期写入0x4da0 0x582b 0x89d0 0xb7d9 0xb7da 0xb7ec,前四个写入正确,后两个就会出现预期写入0xb7da,实际写入0xb7da+0x7.(我也不知道为什么有这个偏移,但是写入的前四个是对的)。

    1. Axuanz (作者)  07-03
      @yxf

      谢谢你!这个偏移我也没什么头绪hhh

Theme Jasmine by Kent Liao