IDA、X32dbg逆向分析易语言程序窗口标题、宽度、高度

分析背景

源于对某软件的广告删除分析,发现其为易语言程序,特此写一篇关于易语言程序的分析思路,而此篇所讲述的为修改易语言编译后程序的标题、宽度和高度。(大佬勿喷,自己分析的思路记录)

环境准备

我们首先安装易语言较新的版本,并安装破解补丁以至于能够进行编译程序,推荐下载地址:https://www.bilibili.com/video/av205300986/

安装完成后我们新建一个.e程序并打开,我们对_启动窗口设置一些初始值(宽度、高度、标题),如下图所示:

image-20221026154829878

设置好后我们点击上方的 编译静态编译 ,编译到桌面,命名为test.exe,双击打开查看是否能正常运行,能正常运行的话我们关闭程序,使用X32dbg载入程序,因为编译的程序是32位的。

开始分析

我们首先需要明确一点我们的高度和宽度分别为:300、600,转换成对应的十六进制分别为:12C、258,这里我们先实现对程序的宽度和高度进行修改,载入后,我们先按一下F9来到程序的入口,如下图所示:

image-20221026160509441

这里我们讲两个思路定位到关键代码处:

  1. 通过对CreateWindowExA下断
  2. 通过易语言特征
一、CreateWindowExA下断分析

我们先讲第一个方法,也是逆向分析最通用的方法,我们再下方输入:

bp CreateWindowExA

然后按下回车,发现提示下断点成功,我们F9直接来到CreateWindowExA处,这里经过反复调试,发现第一断下来的不是我们想要分析的地方,而第二次为我们想要分析的函数,于是我们再次按下F9得到如图所示:

image-20221026161141317

此时我们不能直接修改该内存的值,原因是我们现在的CreateWindowExA函数为系统API,是最后调用的时候加载的原程序的参数,因此我们需要找到是谁调用了该系统API,我们看一下调用堆栈的数据,找到如下图所示位置,双击返回至上一层:

image-20221026162932045

这里讲一下上一层也就是调用刚刚的API函数的函数层,我们往上划一下,因为返回来第一个选中的汇编指令为执行完函数后指向的下一条指令,因此上方的CALL函数为我们的上一层函数,此时的push压栈参数完全与我们上方查看的API参数一一对应了。

判定依据为第二次断下地方加载了我们的窗口名称,通过查询CreateWindowExA的调用方法如下:

HWND CreateWindowExW(
[in] DWORD dwExStyle,
[in, optional] LPCWSTR lpClassName,
[in, optional] LPCWSTR lpWindowName,
[in] DWORD dwStyle,
[in] int X,
[in] int Y,
[in] int nWidth,
[in] int nHeight,
[in, optional] HWND hWndParent,
[in, optional] HMENU hMenu,
[in, optional] HINSTANCE hInstance,
[in, optional] LPVOID lpParam
);

image-20221026163753593

我们可以看到与宽度对应的寄存器为:dword ptr ss:[ebp-0x20],与高度对应的寄存器为:dword ptr ss:[ebp-0x1C],因此我们查看一下是谁修改了这两个寄存器的值:

image-20221026164313143

此时我们发现直接修改此处的值再修补文件是没法运行的,因此,再往上层进行分析,我们在此处下断(此处地址为0x41147c),Ctrl+F2重新运行,F9来到此处,查看调用堆栈的第二个test模块的调用堆栈,来到更上一层,我们往上看一下有没有大跳跳过此函数的地方,发现没有大跳,那么我们来到上方的第一个ret下面下断,重新运行F9过来:

image-20221026170413727

此时我们F8单步步过往下注意观察寄存器和堆栈值得变化,我们可以发现好几处都进行了宽高的赋值,但到底哪一处才是准确的参数赋值呢?我们将对应的汇编前后三行都复制下来观察一下:

#第一处

0041135A | 8B7C24 | mov edi,dword ptr ss:[esp+4C] |
0041135E | 8B5C24 | mov ebx,dword ptr ss:[esp+50] |
00411362 | 3BCD | cmp ecx,ebp |
00411364 | 8B6C24 | mov ebp,dword ptr ss:[esp+54] | 单步执行到这发现EBP的值变成了258
00411368 | 75 54 | jne test.4113BE |
0041136A | 8B46 7 | mov eax,dword ptr ds:[esi+70] |
0041136D | 48 | dec eax |

#第二处

004113A7 | 8BF8 | mov edi,eax |
004113A9 | D1FF | sar edi,1 |
004113AB | FFD3 | call ebx |
004113AD | 8B5424 | mov edx,dword ptr ss:[esp+58] | 单步执行到这,发现edx的值变成了12C
004113B1 | 8B4C24 | mov ecx,dword ptr ss:[esp+68] |
004113B5 | 2BC2 | sub eax,edx |
004113B7 | 99 | cdq |

#第三处

004113B8 | 2BC2 | sub eax,edx |
004113BA | 8BD8 | mov ebx,eax |
004113BC | D1FB | sar ebx,1 |
004113BE | 8B5424 | mov edx,dword ptr ss:[esp+58] | 单步执行到这,发现edx的值变成了12C
004113C2 | 03EF | add ebp,edi |
004113C4 | 85C9 | test ecx,ecx |
004113C6 | 8D0413 | lea eax,dword ptr ds:[ebx+edx] |

#第四处

0041144A | 8B4E 4 | mov ecx,dword ptr ds:[esi+40] |
0041144D | 52 | push edx |
0041144E | 8B5424 | mov edx,dword ptr ss:[esp+70] |
00411452 | 2BC3 | sub eax,ebx | 单步到这里的时候,发现eax变成了12C,与我们的高度对应
00411454 | 2BEF | sub ebp,edi | 单步执行到这,发现ebp的值变成了258
00411456 | 52 | push edx |
00411457 | 50 | push eax |

我们可以发现前面三处距离我们的断点处0x41147c较远,而第四处距离较近,并且我们发现第四处都是对宽和高的赋值,因此我们大胆猜测一下第四处和第五处就是我们需要修改的宽和高的值,第四处截图如下:

image-20221027093228268

这里需要明白一个知识点:调用函数时,若需要对函数进行传参,那么传参的值将会以入栈的形式体现,类似push eax之类的,而函数执行结束的返回值将会存储在eax里,对上图仔细分析我们可以更加有把握的猜测就是我们要找的宽度和高度的汇编指令处了,这里我们贴一下分析的过程:

0041144E | 8B5424 | mov edx,dword ptr ss:[esp+70] |
00411452 | 2BC3 | sub eax,ebx | 单步到这里的时候,发现eax变成了12C,与我们的高度对应
00411454 | 2BEF | sub ebp,edi | 单步执行到这,发现ebp的值变成了258
00411456 | 52 | push edx |
00411457 | 50 | push eax |我们发现这里将eax压栈,也就是压入了高度
00411458 | 894424 | mov dword ptr ss:[esp+68],eax |
0041145C | 8B4424 | mov eax,dword ptr ss:[esp+4C] |
00411460 | 55 | push ebp | 我们发现这里将ebp进行压栈,也就是压入了宽度
00411461 | 53 | push ebx |
00411462 | 57 | push edi |
00411463 | 50 | push eax |
00411464 | 8B86 C | mov eax,dword ptr ds:[esi+CC] |
0041146A | 51 | push ecx | ecx:“helloworld”
0041146B | 50 | push eax |
0041146C | E8 4F0 | call test.4115C0 |
00411471 | 8B4C24 | mov ecx,dword ptr ss:[esp+60] |
00411475 | 83C4 0 | add esp,4 |
00411478 | 50 | push eax | 我们发现这里将eax进行了压栈,也就是压入了0x41146c的函数返回值
00411479 | 51 | push ecx | 将该返回值作为参数传入我们的CreateWindowExA的调用函数
0041147A | 8BCE | mov ecx,esi | ecx:“helloworld”, esi:“打G"world”
0041147C | E8 91C | call test.46D612 | 这里为我们的CreateWindowExA的调用函数

我们可以发现使用sub指令得到的宽和高,因此我们需要对宽或高的被减数进行更改值,即可得到新的宽或高,但是这个方法太麻烦,还得往上翻,还得考虑栈平衡,因此我们直接修改对应的eax和ebp寄存器的值即可(这里将高和宽的值置换),F9运行起来得到如图所示:

image-20221027101117107

接下来我们修改窗口标题,同样的思路就能找到窗口标题的修改处,由于都是启动窗口的基本属性,故标题的赋值地址也在附近,这里经调试直接给出:

image-20221027101534474

然后我们F9直接运行起来看看效果:

image-20221027101602441

二、特征分析

我们清除所有断点,Ctrl+F2重启按下F9加载到入口处,右键搜索特征命令:

image-20221027101949097

这里讲一下,易语言的启动窗口特征为(前提是没有特殊情况),或者我们通过易语言的载入函数进行分析,也可以得到窗口的ID:

push 0x52010001

这里贴两篇大佬分析易语言的思路以及特征:

https://fjqisba.github.io/categories/%E6%98%93%E8%AF%AD%E8%A8%80%E9%80%86%E5%90%91/

https://www.52pojie.cn/forum.php?mod=viewthread&tid=483527&highlight=%D2%D7%D3%EF%D1%D4

如何找到载入函数呢,我们这里可以使用IDA静态加载,这里需要用到一个易语言分析模块,贴上一个大佬的模块地址:

https://www.52pojie.cn/thread-1684608-1-1.html

之后怎么通过IDA找载入函数就不用我多说了吧,上面第二篇文章的大佬已经讲得很清楚了

看到这,我们的分析过程就结束了,有人可能想问了,那么我们如何进行将修改过后的值保存到程序里,这样每次打开都是我们修改好的内容呢?

1、 改汇编代码,然后打补丁patch,这个方法及其不推荐,如果改了之后不影响程序的正常运行,那么我们可以这么干,但是通常修改后会影响栈平衡或寄存器赋值不对,导致函数错误,甚至程序崩溃,因此及其不推荐该方法。

2、 HOOK(推荐)

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
原创易语言 版_EXE分析器[PE解析]_可分析DLL函数_导入函数_分析软件三大头_移动表 a.可分进程shuj: 1.进程列表 2.进程模块 模块名 模块句柄 模块基址 模块大小 模块路径 3.通过特征码扫描易语言程序 b.移动EXE文件到分析器即可对这个软件进行分析         1.可以快速分析PE的一些信息 比如         当前选中程序路径:D:\Program Files (x86)\Tencent\WeChat\WeChat.exe         模块句柄:0x00400000         主模块地址:0x00400000         主模块大小:0x00005000         模块数量:74         内存镜像基址:0x00400000         内存镜像大小:0x00079000         节数量:6         所有头大小:1024 c.分析DOS头:         PE标志 标志PE头的地址 d.分析NT头 e.可以分析标准PE头         1.机器码         2.节的数量         3.PE文件的特征值         4.可选PE头的大小         5.符号的数量         ... f.分析可选PE头         1.机器型号         2.链接器版本         3.代码节的RVa         4.shuj节rva         5.内存中节对其和文件对其值         6.ImaeBase 镜像基址         7.SizeOfImage 整个程序在内存中占用的空间         8.所有头大小         9.程序入口点         ..... g.可以分析shuj目录地址         1.导入表         2.导出表         3.zy表         4.IAT表         5.绑定导入表         ...... j.可以分析节表         Name:  .text          [节名称]         VirtualSize[内存中大小(对齐前的长度)]         VirtualAddress[节区在内存中的偏移地址(RVA)]         SizeOfRawData[文件中大小(对齐后的长度)]         PointerToRawData [文件中偏移(OffSet)]         Characteristics[标志(块属性)] l.可以分析DLL软件到哪些函数,可以分析DLL导出了哪些函数 p.可以分析软件的重定位表 以及移动导出表操作,移动导入表操作,偏移转换器。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值