人生第一道PWN,Overthewire之Narnia0
十分简单的PWN
第一次做pwn题目,缘由在《THE HACKER PLAYBOOK2》中第一章有提及,并且作者带着做了一遍,觉得很有意思,于是记下了自己做的时候的一些理解
说这道题简单是因为,这道题甚至不需要使用调试器,能看懂c语言,对堆栈有基本理解,熟悉Linux基本指令就能做出来。。。
*题目网站
首先登录题目服务器
1 | ssh narnia0@narnia.labs.overthewire.org |
ls
看到题目文件:narnia0.c
看一下源码
cat narnia0.c
1 |
|
读一遍代码,是一个十分简单的C语言程序:
1 | 首先对变量val进行赋值,然后申请了一个20字节的字符数组buf |
首先,题目要求是把val的值从0x41414141
改变成0xdeadbeef
但是程序并没有提供修改val
变量的可写入函数
浏览代码,发现第五行变量val
被赋值为:0x41414141
查看Ascii码表,算出对应字符串为:AAAA
在第6行char buf[20]
说明程序接受输入的缓冲区长度为20字节
而在第10行scanf()
函数允许最多输入长度为24字节,于是造成了缓冲区溢出,溢出的这4个字节就是达成目的的关键
测试一下输入24个字节后溢出的四个字节会造成什么样的后果
运行程序:
1 | narnia0@narnia:/narnia$ ./narnia0 |
在这里程序在等待用户输入,也就是执行到了 scanf("%24s",&buf)
函数
输入20个A 加上BCDE
来测试
1 | Here is your chance: AAAAAAAAAAAAAAAAAAAABCDE |
输出了val: 0x45444342
而对应的ascii即是EDCB
,这说明可以修改内存中val
的值!溢出的四个字节覆盖到了val
上
注意这里的顺序,输入的最后是BCDE
,但显示的顺序是EDCB
因为栈机制是先进后出/后进先出,及如果依次入栈为1234,依次出栈的顺序就是4321,这点十分重要
现在要做的就算把val
的值变成0xdeadbeef
注意0xdeadbeef
并不是一串字符串,而是一个16进制数,8位的16进制数占4个字节
所以在输入的时候顺序要为:\xef\xbe\xad\xde
及A*20+\xef\xbe\xad\xde
如何获得这串16进制数\xef\xbe\xad\xde
对应的字符串呢?
在Python中,可以使用\x
对字符串进行转义,把输入的字符串当成16进制输出对应的字符
如:
1 | >>> print "\x41" |
及输出了16进制数41
对应的Ascii字符A
那么输出\xef\xbe\xad\xde
对应的字符即:
1 | >>>print "\xef\xbe\xad\xde" |
但是由于各种奇怪的编码问题这个不存在的字符串你是不可能读懂的,即使能也会是乱码,因为根本没有字符去对应那串16进制码,但是计算机能懂就够了
于是需要用到Linux中的“管道”功能,即把一个程序的输出作为另一个程序的输入
例如:netstat -an | grep 445
netstat -an
会列出所有端口,而grep 445
则会进行筛选,只保留有445这个字符串的结果
同理,如果要把Python程序的输出结果当做题目程序的输入,同样需要这个技巧
1 | narnia0@narnia:/narnia$ python -c 'print "A"*20 + "\xef\xbe\xad\xde"' | ./narnia0 |
这句话: python -c 'print "A"*20 + "\xef\xbe\xad\xde"' | ./narnia0
因为在这里不需要进入交互模式,python -c 'xxx'
命令会直接执行单引号中的代码,而不是在交互中进行
如果不加-c
参数,直接执行python xxxxx
,系统则会去匹配当前目录下的xxxxx
文件试图去用Python解释器执行
|
即为管道,把|
左边的输出结果当做输入传递给|
右边的程序
这时看变量val
的值,已经变成了0xdeadbeef
,多出的四个字节成功覆盖在了内存中变量val
储存的位置
再次查看C语言代码
1 | 1. `if(val==0xdeadbeef)` |
如果val
的值变成了0xdeadbeef
,程序将会调用/bin/sh
第二题的密码在etc/narnia_pass/narnia1
如果直接查看会提示权限不够
因此运行Python代码同时读取位于etc/narnia_pass/narnia1
中的密钥:
1 | narnia0@narnia:/narnia$ (python -c 'print "A"*20 + "\xef\xbe\xad\xde"';echo 'cat /etc/narnia_pass/narnia1') | ./narnia0 |
成功显示出了密钥,即下一道题的ssh密码