Pwnable.kr的第5道题目passcode的writeup。
首先通过ssh连接到题目,查看目录:
查看passcode.c,获得题目源代码:
1 |
|
题目逻辑比较简单,先输入name,然后输入两个整数passcode1和passcode2,当输入的值满足以下条件时即可得到flag:
1 | passcode1==338150 && passcode2==13371337 |
但仔细一看,程序中的两个scanf语句有错误,少了&,导致用户在输入passcode时出现Segmentation fault的错误:
1 | scanf("%d", passcode1); |
程序将passcode的值当做passcode的地址,用户当前输入的值被写入地址passcode中,导致非法内存访问。因此在输入passcode1和passcode2的值之前,我们要设法控制这两个变量的值。注意到变量name的长度为100字节,是否可以覆盖到passcode1甚至passcode2呢?
在IDA里可以看到,程序先调用welcome,再调用login,且中间的值ebp没有发生变化,name的地址为[ebp-0x10],passcode1的地址为[ebp-0x70],偏移为0x70-0x10=0x60,因为那么name的长度为100字节,因此输入的name最后4个字节刚好可以覆盖passcode1的地址。
由于name的长度只有100字节,因此不能覆盖passcode2的地址,但由于我们能够对任意地址写4个字节,因此我们覆写某个函数的got表地址为执行system函数的地址,当执行该函数时,即跳转到指定地址执行,即可得到flag。从源代码或IDA里都能看到,程序在输入passcode1之后执行了printf、fflush函数,可以覆盖这两个函数其中一个,因为要越过passcode2的输入,因此不能覆盖scanf函数。
使用gdb查看system(“/bin/cat flag”)的地址,可以看到跳转的地址为0x080485e3:
最后,完整的exp如下:
1 | from pwn import * |
逐行执行python脚本得到flag: