看代碼
#include <stdio.h>
#include "windows.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 valid_flag=0;
char password[1024];
while (1)
{
printf("請輸入密碼:");
scanf("%s",password);
valid_flag=verify_password(password);
if (valid_flag)
{
printf("錯誤!\n");
}
else
{
printf("正確!\n");
break;
}
}
return 0;
}
會點C語言就能看懂吧,有個驗證密碼是否正確的函數
要注意的一點是要關閉編譯時的GZ選項,VC6以上版本關閉GS編譯選項
具體方式:vc6工程-設置-c/c++-工程選項裏面去掉GZ
vs C/C++ 代碼生成 緩衝區安全檢查 否
生成程序輸入密碼,當輸入的爲8位但是數值比1234567大時均會通過驗證,這是爲什麼呢?
拿到OD中看下
當輸入12345678時,堆棧中如下所示
0012FB18 34333231 ;4321
0012FB1C 38373635 ;8765
0012FB20 00000000; ;authenticated
0012FB24 /0012FF80; ;ebp
當我們輸入01234567時,因爲比1234567小,所以strcmp會返回-1.補碼爲0xFFFFFFFF,OD中看下
0012FB18 33323130 ;3210
0012FB1C 37363534 ;7654
0012FB20 FFFFFF00 ;authenticated
0012FB24 /0012FF80 ;ebp
authenticated爲FFFFFF,所以還是不會通過驗證的
另外問下爲什麼我OD中那些像strcpy什麼的函數都識別不出來,CALL的都是一個模塊內的地址
是不是符號的問題?
下面我們再換種方式
#include <stdio.h>
#include "windows.h"
#define PASSWORD "1234567"
char *p={
"\x12\x12\x12\x12\x12\x12\x12\x12"//buffer
"\x34\x34\x34\x34"//authenticated
"\xaa\xaa\xaa\xaa"//ebp
"\xbb\xbb\xbb\xbb"//eip
};
int verify_password(char *password)
{
int authenticated;
char buffer[8];
authenticated=strcmp(password,PASSWORD);
strcpy(buffer,password);
return authenticated;
}
int main()
{
int valid_flag=0;
char password[1024];
while (1)
{
printf("請輸入密碼:");
scanf("%s",password);
valid_flag=verify_password(p);
if (valid_flag)
{
printf("錯誤!\n");
}
else
{
printf("正確!\n");
break;
}
}
return 0;
}
爲了方便測試直接在程序內定義一個字符串,這樣編譯運行後會彈出一個引用的0xbbbbbbbb內存不能 爲read錯誤,原因就不多說了。
我們把這個0xxbbbbbbbb改爲輸出正確的分支就可以,拖到OD中找到輸出正確的地址,是0x00401106,替換掉就OK 。
運行下就會輸出正確了,不過程序之後會崩潰掉,因爲棧內EBP被覆蓋爲無效值,使得程序在退出時堆棧無法平衡。