20145233《网络对抗》第一周平台逆向破解
实践目标
-
本次实践的对象是一个名为
pwn1
的linux可执行文件。 -
该程序正常执行流程是:
main
调用foo
函数,foo
函数会简单回显任何用户输入的字符串。
-
该程序同时包含另一个代码片段,
getShell
,会返回一个可用Shell
。正常情况下这个代码是不会被运行的。我们本次实践的两个目标就是想办法运行这个代码片段。
修改方法
- 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
- 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
实践一
-
先反汇编,理解程序的运行过程与功能
-
使用指令
objump -d pwn1 | more
来查看 -
主要看
foo
函数和main
函数的那部分,知道如何修改代码,使得函数的调用发生改变,当然要看的懂会变得指令。
-
代码中还有一个未被调用的getshell函数,直接运行程序是没有办法运行到这个函数上的,所以我们直接修改代码来完成第一次实践。
-
首先直接修改代码要清楚机器语言是怎样计算的:
-
找到call指令机器码与汇编代码的关系如下:0x80484ba + 0xd7ffffff = 0x8048491,其中机器码e8表示call
-
将上述计算式抽象出来可得:call机器码 = 跳转地址 - call指令的下一个eip
-
由此我们计算调用getshell函数的机器码为:e8 c3 ff ff ff
-
接下来我们只需要修改机器码即可:
-
步骤1: vi 20145233,用vim编辑器查看可执行文件20145233;
-
步骤2: 进入vi编辑模式后,发现乱码,使用
:%!xxd
这个指令将其变为16进制。
-
步骤3: 键入/e8 d7,查询需要改动的机器码的位置,锁定后,按r进入文本编辑模式,将其改为e8 c3。
-
步骤4:
:%!xxd -r
,退出16进制模式(注意:此处如果直接以16进制形式保存退出,运行该文件会报错) -
步骤5:
:wq!
,保存并退出。
-
-
退到最初的运行界面,运行20145233文件,可以看到程序的运行结果已经发生改变:
-
再利用上述步骤可以再将程序改回原来的结果,将所修改的地方改回即可:
实践二 通过构造输入参数,造成BOF攻击,改变程序执行流
确认输入字符串哪几个字符会覆盖到返回地址
-
这一步和第一个过程中的反汇编相同。
-
了解了反汇编之后,需要确认输入字符串哪几个字符会覆盖到返回地址。
-
通过观察foo函数的汇编代码,不难发现其存在BOF漏洞,那我们需要输入多少字符才会造成BOF呢?在此,我们采用每个字节的进行输入,观察程序什么时候崩溃。
-
测试选择类似“1111111122222222333333334444444412345678”来测试更容易标识,易于发现是哪位出现变动。
-
使用gdb进行测试:
-
观察得到的eip值,通过查看ASCII码得知,这个结果是1234。
-
因此我们发现是1234覆盖了eip,所以我们只需要将getshell的内存地址来替换掉这四个字符,就可以达到向getshell函数转移的目的。
-
由于getShell的内存地址是0x0804847d,而其对应的ASCII没有字符,所以我们通过一个简单的perl脚本语言来构造输入值。
-
由为我们没法通过键盘输入x7dx84x04x08这样的16进制值,所以先生成包括这样字符串的一个文件。
-
x0a表示回车,如果没有的话,在程序运行时就需要手工按一下回车键。(kali系统采用的是大端法,所以构造内存地址时注意顺序,末尾的 a表示回车换行。)
-
使用
perl -e 'print "11111111222222223333333344444444x7dx84x04x08x0a"' > input
指令将perl生成的字符串存储到文件input中。 -
关于Perl:
- Perl是一门解释型语言,不需要预编译,可以在命令行上直接使用。
- 使用输出重定向“>”将perl生成的字符串存储到文件input中。
-
可以使用16进制查看指令xxd查看input文件的内容是否如预期。
-
(cat input; cat) | ./20145221
,将input文件作为输入,结果如下:
实验总结
- 这次是网络攻防的第一次实验,我觉得很有意思,尤其是第一部分的攻击,直接强行修改代码来使得程序的运行结果发生改变,并且第二部分的溢出实验,之前也只是听说过有这个东西,自己来实践起来,要不是老师上课将结果,还是不太好理解的。
- 第一次实验我觉得很有意思,我觉得我学这门课的兴趣还是很大的。
- 其中我的虚拟机中出现的其他同学的学号文件是因为,我在我的虚拟机给其他同学演示了一下如何完成此次实验。