安全项目2现在看来时计较简单的,但是事实是我研究了很长时间。还记得前两天的时候,我觉得这个项目难到让我崩溃,这应该就是会者不难,难者不会了吧:)所以我想写下我这两天的总结和学习到的知识。
对应安全项目2的要求我放在附属的文件上面,但可能是英文的需要大家翻译一下。(用ai很快的)
这是安全项目2的源代码
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* Like gets, except that characters are typed as pairs of hex digits.
Nondigit characters are ignored. Stops when encounters newline */
char* getxs(char* dest)
{
int c;
int even = 1; /* Have read even number of digits */
int otherd = 0; /* Other hex digit of pair */
char* sp = dest;
while ((c = getchar()) != EOF && c != '\n') {
if (isxdigit(c)) {
int val;
if ('0' <= c && c <= '9')
val = c - '0';
else if ('A' <= c && c <= 'F')
val = c - 'A' + 10;
else
val = c - 'a' + 10;
if (even) {
otherd = val;
even = 0;
}
else {
*sp++ = otherd * 16 + val;
even = 1;
}
}
}
*sp++ = '\0';
return dest;
}
int getbuf()
{
char buf[16];
getxs(buf);
return 1;
}
void test()
{
int val;
printf("Type Hex string:");
val = getbuf();
printf("getbuf returned 0x%x\n", val);
}
int main()
{
int buf[16];
/* This little hack is an attempt to get the stack to be in a
stable position
*/
int offset = (((int)buf) & 0xFFF);
int* space = (int*)malloc(offset);
*space = 0; /* So that don't get complaint of unused variable */
test();
return 0;
}
好了,对于所有的题目我们都应该先出思路在进行完成。
1.基本思路
对于这个题的思路在看完基本要求后大家应该知道了,就是应用栈溢出的攻击对getbuf的返回值进行改正使其从1变为0xdeadbeef。(当然还有一种思路,是通过改函数的返回地址将test函数中给val赋值的步骤跳过,并通过栈溢出改变val地址处的值来使val变为0xdeadbeef,这是一种十分巧妙的办法,可以得到相应的正确答案,但我认为这并不是题目想让我们做的,所以不详细的说明,只是作为一种plan b吧) 而怎么对其进行栈溢出的攻击呢,这是一个有趣的问题,大家可以思考思考。我认为我们对其进行的攻击应该是想尽办法向其中注入一段机器码从而改变eax中打算返回的1,然后在让程序返回test函数进行表达从而得到我们想要的结果。
2.对栈溢出攻击的小总结
(1)对原函数返回地址的改变,这是一个很重要的应用。我们在了解栈的结构后,应该知道我们寄存器中ebx会对栈底的地址进行存储,而一个栈的返回地址为栈底的后四个字节,这就为我们通过栈溢出来改变栈的返回地址留下了可能,从而我们可以通过改变返回地址来实现一些功能。比如,跳过某一步骤,或直接跳入一个原本不会被执行的函数(我上一个文章《对安全项目1的总结》中key3和key4就可以通过这种办法进行推导,同样可以得到正确的答案,并且更符合题目的要求)。
(2)在上一条的基础上,通过栈溢出向程序中注入机器码即攻击代码,一旦成功我们可以让程序做任何我们想让他做的事,比如对寄存器的值进行相应的改变,改变程序中任意的变量的值,跳转到想去的步骤等等。这是一个很nb的东西。当然,我们要学习一些机器码才可以这样做,当然在现在ai等工具发达的今天,我们可以询问它们,同时互联网上也有很多这样的工具帮助我们实现目标。
对于栈溢出有些明显的标准,因为这些程序都会使用一些危险的函数比如gets、strcpy等等如果看见这些函数就要小心了。
3.对任务的详细解决步骤
光说不练假把式,让我们以这题为模板来进行一定的锻炼。
对于这个题我们要先通过vs调试的功能看到其寄存器和反汇编等内容这是十分重要的,我们要先通过调试让程序进入这个getbuf的函数
我标注的两个寄存器一个是esp一个是ebp,这两个寄存器对应的是getbuf函数的栈顶和栈底,我的两个内存窗口上面的看到的是buf的地址,下面看到的是esp即对应的栈的地址。然后我们可以很明显的发现buf可以通过输入的值进行栈溢出,来完成我们的想法 。这时我们要进入反汇编来完成我们的设想
这是反汇编对应的图我们可以明显的看到return1;下面是将1的值付给了eax寄存器。所以此时我相信大家都有想法了吧,没错,真是好样的,就是要通过栈溢出来向其中加入机器码来改变eax的值,然后在正常的返回到tset函数之中。(xdm,我查了好几天资料呢) 然后我们看内存窗口,来设计栈溢出攻击。
粉色是栈顶,黄色是buf的内存占用,白色是栈底,蓝色是返回地址。此时我们明白应该用栈溢出改变返回地址 ,将返回地址变为buf的地址,然后在buf的主体处输入相应的机器码,来完成目标。
对应机器码,我们应先考虑其作用。它应该可以改变eax的值并且可以返回原本打算返回的地址。
mov eax,0xdeadbeef
rush 0x00411c78
ret
这就是对应的汇编语言,然后转换为机器码就是
b8 ef be ad de 68 78 1c 41 00 c3
所以最后我们输入我们设计好的字符串b8 ef be ad de 68 78 1c 41 00 c3 00 00 00 00 00 00 00 00 00 b4 fd 19 00 c0 fc 19 00就可以得到正确结果了。(要记住输入时要保证栈底的值不能发生相应改变不然vs会检测出栈溢出导致程序无法执行)
就是这样了,讲完了。希望对大家有帮助:)bb