少し実験をクラック
ツール
- DEV C ++(ブックVSを使用して)
- IDA_Pro_v7.0
- Ollydbg
- LordPE
- 010エディタ
IDAを使用してファイルを開きます。
- プログラムの分岐点を探します
- アセンブラインターフェースにスペースジャンプ
- 0x40156d:VAを取得
ODを使用してファイルを開きます。
- 得られVA IDAへのCtrl + Gジャンプ
- キャリッジリターンの後に、ブレークポイントを追加実行し、この時点で任意のパスワードを入力し、プログラムでこの中断。
- 限り、我々は間違ったパスワードを入力JE変更JNEを達成できるよう、正しい結果を返します。
LordPEを使用してファイルを開きます。
- ODは、専用メモリの値を変更する変更しました
- 式を用いて計算:
ファイルオフセット=仮想メモリアドレス(VA) -ベース・アドレスがロードされる-セクション・オフセット
= 0x0040156D - 0x00400000 - (0x1000番地- 0x400)
= 0x96D
ファイルを変更するバイナリエディタを使って
- ファイルを開く010Editor
- 0x96DにはCtrl + Gジャンプ
- 750Eし740eを変更
- 保存操作
- 正しいパスワードパスワードエラーを入力し、エラーコードが正しいヒントを返します。
2.2.2画期的な実験パスワードの検証手順
知識ポイント
- バッファオーバーフロー
- C言語のstrcpyの機能:https://www.runoob.com/cprogramming/c-function-strcpy.html
実験環境とツール
- Win10の64ビット
- Dev-C ++
- IDA Proの
- FROM
実験記録
- コード:
1 #include <stdio.h> 2 #include <string.h> 3 4 #define PASSWORD "1234567" 5 6 int verify_password(char *password) 7 { 8 int authenticated; 9 char buffer[8]; 10 authenticated=strcmp(password,PASSWORD); 11 strcpy(buffer,password); 12 return authenticated; 13 } 14 15 int main() 16 { 17 int valid_flag = 0; 18 char password[1024]; 19 while(1) 20 { 21 printf("Please input password: "); 22 scanf("%s", password); 23 valid_flag = verify_password(password); 24 if(valid_flag) 25 { 26 printf("incorrect password!\n\n"); 27 } 28 else 29 { 30 printf("Congratulation! You have passed the verification!\n"); 31 break; 32 } 33 } 34 return 0; 35 }
实验步骤
- 运行测试:
- 静态反汇编:
- strcpy后一句地址为0x401532
- strcpy后一句地址为0x401532
- 动态调试
- 输入"qqqqqq",authenticated的值为1
- 输入"qqqqqqqq"尝试使用字符串末尾的'\0'把authenticated的低字节覆盖从而变成0
- 成功绕过了验证
- 输入"qqqqqq",authenticated的值为1
实验 2.3.2 更改返回地址
实验工具
- 010 Editor
- Dev C++
- IDA-Pro
- OD
实验知识点
- 缓冲区溢出覆盖栈内函数的返回地址
实验源码
1 #include <stdio.h> 2 #define PASSWORD "1234567" 3 int verify_password(char *password) 4 { 5 int authenticated; 6 char buffer[8]; 7 authenticated = strcmp(password,PASSWORD); 8 strcpy(buffer,password); 9 return authenticated; 10 } 11 12 main() 13 { 14 int valid_flag=0; 15 char password[1024]; 16 FILE *fp; 17 if(!(fp=fopen("password.txt","rw+"))) 18 { 19 exit(0); 20 } 21 fscanf(fp,"%s",password); 22 valid_flag = verify_password(password); 23 if(valid_flag) 24 { 25 printf("incorrect password!\n"); 26 } 27 else 28 { 29 printf("Congratulation!You Have passed the verification!\n"); 30 } 31 fclose(fp); 32 }
实验步骤
- 运行测试
- 静态反编译,strcpy下一句为0x40152e,密码正确的分支是0x4015ca
- 动态调试
- 当前栈帧的EBP是0x61fa78
- 查看栈的内容
- 尝试直接修改返回地址,成功跳转到正确密码的分支
- 使用二进制编辑器构造payload
- 运行,虽然会闪退,但是通过捕捉,可以发现确实跳转到了正确的分支
- 当前栈帧的EBP是0x61fa78
实验 2.4 代码植入
实验工具
- Windows XP SP3
- Visual C++ 6.0
- Depends
- OD
源码
1 #include <stdio.h> 2 #include <string.h> 3 #include <windows.h> 4 #define PASSWORD "1234567" 5 int verify_password(char *password) 6 { 7 int authenticated; 8 char buffer[44]; 9 authenticated = strcmp(password,PASSWORD); 10 strcpy(buffer,password); 11 return authenticated; 12 } 13 14 main() 15 { 16 int valid_flag=0; 17 char password[1024]; 18 FILE *fp; 19 LoadLibrary("user32.dll"); 20 if(!(fp=fopen("password.txt","rw+"))) 21 { 22 exit(0); 23 } 24 fscanf(fp,"%s",password); 25 valid_flag = verify_password(password); 26 if(valid_flag) 27 { 28 printf("incorrect password!\n"); 29 } 30 else 31 { 32 printf("Congratulation!You Have passed the verification!\n"); 33 } 34 fclose(fp); 35 }
实验步骤
- 编译程序并且拖入Depends,发现并没有user32.dll
- 从编辑器里面打开dll文件,发现也可以看到库的基地址,user32.dll的库基地址为0x77D10000,MessageBoxA的偏移地址为0x407EA,地址为0x77D5 07EA
- 先用123422343234423452346234来找到栈中buffer的位置,buffer的起始地址是0x12FAF0
- 构造password.txt
- 代码植入成功
- 运行测试
遇到的问题
- Depends的结果与实验指导上的不一样,没有显示出user32.dll的库基地址
- 从编辑器打开user32.dll:
- 从编辑器打开user32.dll: