标签:
(原创内容,禁止转载)
之前大致了解过PE格式、ELF格式、COFF格式以及内存布局和栈的布局,这次直接实战反编译。
参考书籍:1.0day安全:软件漏洞分析技术
2.IDA PRO 权威指南
首先搭建开发环境:虚拟机安装系统Windows XP SP2 ,安装VC++6.0,安装ollydbg和IDA PRO
主机:Linux,安装dumpbin、objdump、nidisasm和ditorm(后三个暂时用不上)
一:开发一个简单的C语言程序,主要逻辑是简单验证(本次的目的就是突破这种验证限制)
#include <string.h> #include <stdio.h> #define PASSWORD "123456" int verify_password(char *password){ int authenticated; authenticated = strcmp(password,PASSWORD); return authenticated; } int main(int argc, char* argv[]){ int valid_flag =0; char password[1024]; while(1){ printf("please input password: "); scanf("%s",password); valid_flag = verify_password(password); if(valid_flag){ printf("incorrect password!\n\n"); }else{ printf("Congratulation! you have passed the verification "); break; } } return 0; }
二:先使用一些其他的深度探测工具来检查
(由于内容太多,所以加了grep)可以看到,里面的字符串很多都被找到。但是要注意的是:
可以通过F12来查看图形化的流程说明,如下图:
同时,也可以在IDA中打开包含strings的视图,可以查看原来的字符串,如下图所示:
(.rdata段表示只读的数据,比如字符串文字量、常量和调试目录信息。)
继续,来看一个函数
.text:00401020 _verify_password proc near ; CODE XREF: j__verify_passwordj .text:00401020 .text:00401020 var_44 = byte ptr -44h ;编译器自动生成的记号 .text:00401020 var_4 = dword ptr -4 .text:00401020 Str1 = dword ptr 8 .text:00401020 .text:00401020 push ebp ;从这里开始压入原来的ebp(函数栈帧) .text:00401021 mov ebp, esp ;新的ebp=esp(栈顶) .text:00401023 sub esp, 44h ;开辟44个空间 .text:00401026 push ebx .text:00401027 push esi .text:00401028 push edi ;保留调用的函数的一些数据 .text:00401029 lea edi, [ebp+var_44] .text:0040102C mov ecx, 11h .text:00401031 mov eax, 0CCCCCCCCh .text:00401036 rep stosd .text:00401038 push offset Str2 ; "123456" .text:0040103D mov eax, [ebp+Str1] .text:00401040 push eax ; Str1 .text:00401041 call _strcmp .text:00401046 add esp, 8 .text:00401049 mov [ebp+var_4], eax .text:0040104C mov eax, [ebp+var_4] .text:0040104F pop edi .text:00401050 pop esi .text:00401051 pop ebx .text:00401052 add esp, 44h .text:00401055 cmp ebp, esp .text:00401057 call __chkesp .text:0040105C mov esp, ebp ;恢复ebp .text:0040105E pop ebp .text:0040105F retn
这个结合前一篇关于栈的分析,可以很清楚的看出来程序的执行流程。push offset Str2 这句就是要比较的内容,因此可以选择去读取.rdata段中的数据来get密码。
继续看主函数,call之后的结果保存在了eax中,通过和0比较来判断是否是正确的密码。为了改变流程,可以将jz变成jnz。(jz->0x74,jnz->0x75)
.text:004010C6 call j__verify_password .text:004010CB add esp, 4 .text:004010CE mov [ebp+var_4], eax .text:004010D1 cmp [ebp+var_4], 0 .text:004010D5 jz short loc_4010E6
接下来,还涉及到虚拟内存地址(VA)和文件偏移地址的转换
文件偏移地址=虚拟内存地址(VA)-转载基址(Image Base)-节偏移=0x004010D5-0x00400000-(0x00001000-0x00001000)=0x10D5
利用Winhex来修改74为75,就可以达到目的。结果如图所示:输入之前正确的密码,反而不行,其他字符一律通过
标签:
原文地址:http://www.cnblogs.com/kakaxisir/p/4928022.html