这次的教程是用ida来逆向分析一个易语言exe程序 这个是我简单写的一个易语言登陆校验 [ecode=1=0].版本 2
.程序集 窗口程序集_启动窗口
.子程序 _登陆_被单击
.如果真 (登陆校验 (编辑框1.内容, 编辑框2.内容))
_启动窗口.可视 = 假
载入 (窗口1, , 真)
.如果真结束
.子程序 登陆校验, 逻辑型
.参数 用户名, 文本型
.参数 密码, 文本型
.如果真 (用户名 = “starry” 且 密码 = “starry”)
返回 (真)
.如果真结束
返回 (假)
[/ecode]
默认即可 点击ok 箭头位置表示他正在分析,分析完成后会自动消失
这次的教程是动态调试,我们选择Local windows Debugger
点击绿色的这个运行即可 点击yes即可
提示下面这个,我们直接点yes
下面这些就是寄存器
堆栈区
数据区
代码区,也就是汇编代码的显示 按键盘上的空格可以放大
按tab键或者F5可以把汇编转为c伪代码
生成字符串
稍等片刻 下面箭头位置是进度 完成后,就会自动消失
这些就是字符串,类似od的字符串搜索
我们直接看登陆校验,如果输入的用户名与密码都等于starry就会返回真 [ecode=1=0].版本 2
.子程序 登陆校验, 逻辑型
.参数 用户名, 文本型
.参数 密码, 文本型
.如果真 (用户名 = “starry” 且 密码 = “starry”)
返回 (真)
.如果真结束
返回 (假) [/ecode] 如果返回真,那么执行载入登陆成功的窗口 [ecode=1=0].版本 2
.子程序 _登陆_被单击
.如果真 (登陆校验 (编辑框1.内容, 编辑框2.内容))
_启动窗口.可视 = 假
载入 (窗口1, , 真)
.如果真结束
[/ecode]
我们可以在ida中搜索starry
然后双击搜索到的starry字符串 右键查看是哪个代码引用了这个starry
Push就是引用这个starry的地方 Sub开头的这个就是函数,ida处理分析的
我们双击点击进入 然后我们按tab键,把汇编代码转为c代码,F5也行
转为c代码后为如下
[C++] 纯文本查看 复制代码 BOOL __stdcall sub_40116A(__int16 **a1, __int16 **a2)
{
return !sub_4010CD(*a1, "starry") && !sub_4010CD(*a2, "starry");
} 函数的返回值为BOOL类型,调用规范__stdcall ,函数名sub_40116A, 参数__int16 **a1, __int16 **a2,参数是一个二级指针, 这个函数实际上就是那个登陆校验函数 return !sub_4010CD(*a1, "starry") && !sub_4010CD(*a2, "starry"); 调用sub_4010CD函数,传入的第一个参数为我们输入的账号*a1,*a2为密码 !这个叹号是取反的意思,如果为真那么“!真”就是假,&&这个是判断,如果两边同时为真,那么返回就为真,有一边为假,后面的函数就不执行了 !sub_4010CD(*a1, "starry") 如果这个函数返回值为假, 那么!sub_4010CD(*a2, "starry");就不执行 我们看看是哪个函数调用了这个登陆校验 我们同样右键找引用 可以看到只有一个函数调用了这个登陆校验函数,那么这个函数应该就是登陆按钮点击后调用的函数了
我们同样双击进入
[C++] 纯文本查看 复制代码 lpMem = (LPVOID)sub_401236(1375797249, (LPCSTR)0x16010003, 8, -1);//获取用户名
v2 = (LPVOID)sub_401236(1375797249, (LPCSTR)0x16010004, 8, -1);//获取密码
//然后把用户名和密码分别给lpMem变量,v2变量
result = sub_40116A((__int16 **)&lpMem, (__int16 **)&v2);
//然后调用登陆校验函数,返回值给result
v1 = result;
//然后把result给v1
if ( v1 )
{
sub_40122A((HWND)0x52010001, byte_6010000, 5, -1, 0, 0);
result = sub_401224(3, 1375797266, 100728849, 65537, 0, 0, 0, 1, 0, -2147483646);
}
if ( lpMem ) //如果用户名不为空就调用释放堆内存的函数
result = sub_401230(lpMem);
if ( v2 )// 如果密码不为空就调用释放堆内存的函数
result = sub_401230(v2);
result = sub_401230(lpMem); //这个是释放堆内存
result = sub_401230(v2);//这个是释放堆内存
//是否释放成功给result变量
//判断v1是否为真,如果为真,那么执行载入窗口的函数
(HWND)0x52010001//这个就是窗口句柄
sub_40122A((HWND)0x52010001, byte_6010000, 5, -1, 0, 0);
result = sub_401224(3, 1375797266, 100728849, 65537, 0, 0, 0, 1, 0, -2147483646); 这两句的代码对应 [ecode=1=0].版本 2
_启动窗口.可视 = 假
载入 (窗口1, , 真)
[/ecode]
下面我们断点调试 单击圆点即可下断 然后我们点击登陆
可以看到断下来了,看到颜色变了,红色变为了下面这个颜色,代表断下来了,代码执行到了这个位置 我们看看v1是什么, 可以看到v1他是0所以,就不执行下面的代码
F8为步过 F7为步入 Ctrl+F7为执行到return尾 F4为运行到指定位置,也就是鼠标指定的位置
F8后执行到了return result位置 同时我们下断点的位置变为了红色,代表我们没执行到那个位置
[C++] 纯文本查看 复制代码 result = sub_40116A((__int16 **)&lpMem, (__int16 **)&v2);
v1 = result; 从上面的代码,我们知道v1是result给的 我们就在result位置下断,然后修改result的值试试 点击这个绿色的箭头就让他运行,不继续向下单步执行
在result赋值位置下断,也就是第10行,下面这个代表行数 下断后,我们点击登陆,断在了如下位置
断下后,我们查看一下result的值是在哪个寄存器, 可以看到在eax,我们可以把eax改为1 就可以登陆成功
我们双击eax寄存器后面的值,把他改为1
然后点击ok
可以看到变为了1
我们F8单步 不好意思,我们应该执行完第10行后改eax才行,因为还没执行登陆校验函数 所以你提前改的话,会把原来改的值覆盖
改完后,点击绿色的运行箭头,可以看到登陆成功了
下面我们试试改汇编代码,达到登陆成功的目的 我们双击进入登陆校验函数,然后按tab键,转为汇编 我们修改一下汇编代码为如下代码 [Asm] 纯文本查看 复制代码 Mov eax,1 // 因为函数的返回值在eax,所以我们给eax赋值
retn //返回
这里我用到的补丁插件是keypatch
下载地址:IDA Patch补丁工具 https://www.52hb.com/thread-51596-1-1.html (出处: 吾爱汇编论坛)
改好后,我们点击patch,
动态调试时代码可能显示有问题,可能不会显示为我们改的汇编代码
我们可以先按D把代码变为数据,然后按c把数据变为code即可 D就是Data,C就是Code 下面是按D然后按C后的显示效果 我们再次点击登陆试试 可以看到登陆成功了,
好的,分析到此结束
|