1 #include2 #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);//over flowed here! 9 return authenticated;10 }11 void main(void)12 {13 int valid_flag=0;14 char password[1024];15 FILE * fp;16 if(!(fp=fopen("password.txt","rw+")))17 {18 exit(0);19 }20 fscanf(fp,"%s",password);21 valid_flag = verify_password(password);22 if(valid_flag)23 {24 printf("incorrect password!\n");25 }26 else27 {28 printf("You have passed the verification!\n");29 }30 fclose(fp);31 }
编译成debug版本后,用ollydbg打开,
由图可知通过验证的程序分支的指令地址是0x00401122 如果把返回地址覆盖成这个地址。则程序将直接跳转到验证通过分支。
buffer[0~3]
buffer[4~7]
authenticated
前栈帧EBP
返回地址
在password.txt中,将4321作为一个输入单元,buffer[8]需要2个单元,第三个单元将authenticated覆盖,第四个将EBP覆盖,第五个单元将返回地址覆盖。
用十六进制编辑器UltraEdit将第五个修改为0x00401122即可实现跳转。
代码植入:
将以上程序稍加修改:
1 #include2 #include 3 #define PASSWORD "1234567" 4 int verify_password(char *password) 5 { 6 int authenticated; 7 char buffer[44]; 8 authenticated = strcmp(password, PASSWORD); // = ,return 0 9 strcpy(buffer, password);10 return authenticated;11 }12 void main(void)13 {14 int valid_flag = 0;15 char password[1024];16 FILE *fp;17 LoadLibrary("user32.dll"); //for messagebox18 if(!(fp = fopen("password.txt","rw+")))19 {20 exit(0);21 }22 fscanf(fp,"%s",password);23 valid_flag = verify_password(password);24 if(valid_flag)25 printf("incorrect password !\n");26 else27 printf("You have passed the verification !\n");28 fclose(fp);29 getchar();30 31 }
将在password.txt植入用来调用Win API函数MessageBoxA的二进制机器码。
buffer[44]需要11个4321单元....第14个将返回地址覆盖。
先在password.txt写入44个字符,则第45个隐藏的截断符null将冲掉authenticated低字节中的1,从而通过验证,此时运行程序可通过。