本例来自于《0day安全,软件漏洞分析技术》,但是由于ollydbg使用功底太差,而且这东西的调试远没有vs等工具智能,因而最初使用上出现了一些问题,记录一下,为后面的学习打点基础。
第一步,先用vc 6.0写一个验证密码的小程序,代码如下:
// crack.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#define PASSWORD "1234567"
int verify_password(char *password)
{
int authenticated;
char buffer[8];
authenticated=strcmp(password,PASSWORD);
strcpy(buffer,password); //纯粹为了缔造越界
return authenticated;
}
int main()
{
int vaild_flag=0;
char password[1024];
while(1)
{
printf("input password: ");
scanf("%s",password);
vaild_flag=verify_password(password);
if(vaild_flag)
{
printf("incorrect!\n");
}
else
{
printf("right!\n");
break;
}
}
return 0;
}
中间有注释的一行,纯粹为了制造一个数组越界,没有任何实际意义,只是为了通过strcpy的越界,抹杀比这个数组先入栈的的整型变量authenticated的值,而这个值,又在主函数调用里面起到了输入判定的作用,当它为1时,提示password输入验证不通过,为0时通过。
调试后,debug里面生成crack.exe,能正常实现密码验证功能.
第二步,把这个crack.exe在ollydbg里面打开,开始调试,先按F9,再按F8,到达输入的起始点停住,程序运行界面如下:

此时为了让程序在后面调试中停住继而观察内存的值,需要设置断点,按ctrl+F,输入CALL crack.strcpy来寻找这行指令,(此处crack是程序名字)


找到之后,点击F2设置断点,然后在程序运行界面输入qqqqqqq并点击回车

程序没有继续向下执行,没有给出incorrect或者是right的提示,证明停在了断点处,此时回到ollydbg界面,点击F8单步执行一条指令,然后看右下角的堆栈窗口,会发现如下情景:

可以看到,刚才输入的qqqqqqq已经读入,而且此时程序已经执行过authenticated=strcmp(password,PASSWORD)这句话,就说明变量authenticated的值肯定为1,而且依据变量的入栈顺序,authenticated的位置正是上图中下面的00000001的位置,为了验证这个事情,可以重新执行上面的步骤,只不过输入值改为1111111,这时,authenticated应该为-1,果不其然,得到了下面的状态,authenticated成了FFFFFFFF:

因此,下面需要做的就是通过输入,和数组的赋值,通过溢出抹杀掉authenticated的值,让他成为0,就能够实现绕过密码。
由于从上图和上上图中发现,当authenticated判定为1而非-1的时候,只需要使得1的那2位变为0x00,那么就可以让下面成为00000000,于是可以想到输入qqqqqqqq,它如果赋值给buffer[8],可以造就一个刚好处于authenticated位置的\0,也就是0x00,试验一下,刚好是如下图所示状况:

这样,就轻松搞定了authenticated的值,继而绕过密码,点击F9继续执行,如图:

此时,1234567的密码已经没什么意义。 |