首页
社区
课程
招聘
[原创]易语言编译器逆向
发表于: 2025-7-30 18:32 6053

[原创]易语言编译器逆向

2025-7-30 18:32
6053

易语言编译器逆向

关键词:易语言、E-Debug、编译原理、KCTF

首先,先思考一个问题,这有关于易语言的编译架构设计:为什么C++Python语言都有相应的CLI(命令行接口)进行编译,而易语言却查无资料?

答案是因为易语言仅在运行期间通过主动和怠性的俩种方式进行代码的Parsing,主动Parsing也就是在GetMessagePeekMessage之类的消息循环中不断地解析代码文件,也可以将其理解为定时解析。

怠性解析也就是等待触发某一事件时再执行,比如当用户手动点击编译时或者在保存代码文件时进行一次代码的Parsing

由于仅在GUI运行期间或者说用户编码阶段进行代码的Parsing,这就导致了易语言没有提供CLI以对代码进行命令行的编译操作,同时也没有内置CLI对代码进行编译操作。

如何证明?仅根据是否提供CLI来猜测语言的功能是不太严谨的。接下来,我通过正常的编码操作、内存分析以及分析控制流的方式来尝试验证。并借此机会,对易语言的编译流程进行逆向,尝试编写一个CrackMe供大家娱乐玩耍。

注:易语言版本为 5.8

首先,我们编写如 1所示函数代码。值得注意的是,如果是手动编码,那么应该可以发现代码被自动格式化了。

1

接下来,我们在上述代码的基础上,为函数的调用参数添加一个test,我是非法参数”并按下回车进行测试。如 2所示,易语言发生了编译报错,我们将此类报错忽视掉,按下确定。

 

2

可以看到如 3所示的情况,易语言自动添加了俩个变量,分别为test”和“我是非法参数”。同时,我们可以发现出现了新的报错“语法错误:错误(39),为某支持库命令提供了过多的参数”。

这直接证明了,易语言在GUI运行期间,或者说用户编码期间进行了代码的Parsing。接下来,我们尝试通过内存分析的方式来判断一下易语言程序是否仅在用户编码阶段进行代码的Parsing

3

首先,我们可以发现易语言在代码行末尾按下回车时,触发了格式化,所以我们将其列出三种情况,如 1所示:

 

 

易语言代码的三种情况

代码情况

注释

原始代码

即未格式化的代码

格式化代码

“ ”->   

填充了参数的格式化代码

信息框( , 0 ,  , )

1

接下来尝试寻找在内存中的代码,基于上述的代码,不断修改字符串“我是Parsing验证代码行”并利用Cheat Engine 定位变量地址。定位结果如 4所示,仅有1个搜索结果,到了此番境地,我们不难假设:如果该变量(token)对应着代码行相关代码,且代码行相关内存发生格式化,即被Parsing了。且程序内存上下文当中没有“明文”的代码。便认为“易语言程序”仅在GUI运行期间或用户编码期间进行代码的Parsing,所以没有提供CLI进行命令行的编译操作。(为排除易语言有内置CLI但并未对外公开的可能)

 

4

为了便于验证,对代码进行了修改,添加了一行对照组代码,如 5所示。

 

5

程序内存数据如 6所示,我们不难发现存在着尚未解析的代码,还有用于对照,发生了Parsing的测试行代码。

6

经过测试分析,发现6A C0”为“信息框”函数的调用号,“(36 1A0F”为字符串参数的长度,为进一步验证易语言有无内置CLI但并未对外公开的可能。我们通过修改字符串的长度,让易语言的Parsing发生异常,通过堆栈的上下文来判断是否有内置CLI的可能。

将字符串长度0F”修改为“00”,并在易语言展开函数参数解析,如 7所示:

7

此时程序发生异常,如 8所示,转到相应代码,同时检查堆栈:

 

8

通过检查堆栈,发现疑似代码提示的相关函数,如 9所示。接下来,我们仅需验证该函数的调用参数是否尚未格式化的原始代码,即可推断其是否是内置的CLI

 

9

在函数头下断点,做些简单的测试。发现函数的调用似乎仅受PeekMessage影响,同时函数的数据流当中也并未出现明文的原始代码。 9所示的EDI寄存器为Parsing后的变量指针,可通过其特征定位所有函数。

至此,我们基本可以认为易语言程序仅在用户编码阶段进行了程序的Parsing,没有提供CLI进行命令行编译。

通过Cheat Engine 搜索相应的变量字符串,搜索访问的指针即可进行局部变量的分析。

定位到 10所示函数,对其进行分析,其数据流如注释所示。

 

10

对图 11所框选的内存范围进行测试并将测试结果可视化如表 1所示,相关测试代码内容如 2所示。

11

样本

0-4

5-8

9

A

B

C-F

CM_ID

(注释)

LENGTH

TYPE

STATIC

PUBLIC

ARRAY_FLAG

LIST_SIZE

001

00 00 00 0D 00 00 00

01 03 00

80

00

00

00

00

CM_001

002

00 00 00 0D 00 00 00

01 03

00

80

01

00

00

00

CM_002

003

00 00 00 10 00 00 00

01 03

00

80

00

00

00

00

CM_003

004

00 00 00 0D 00 00 00

01 03

00

80

00

00

01

EA

CM_004

005

00 00 00 1D 00 00 00

3E 00 01 41

00

00

00

00

CM_005

006

00 00 00 0D 00 00 00

01 03 00

80

00

01

00

00

CM_006

2

CM_ID

注解

CM_001

无注释,整数类型,非静态,非数组

CM_002

无注释,整数类型,静态,非数组

CM_003

有注释,整数类型,非静态,非数组

CM_004

无注释,整数类型,非静态,数组

CM_005

无注释,文本类型,非静态,非数组

CM_006

全局,无注释,整数类型,非静态,非数组

3

同时,如 12所示的框选数据,也就是变量类型地址的上方,这串数据表示变量的ID。在后续编译与变量操作相关的地方会用到。同时,变量ID4byte存储,意味着最多存在4,294,967,295个变量。

 

12

定位全局变量数据结构的方式很简单,通过搜索“当前全局变量数量”即可定位到“全局变量上下文”的基地址+4的位置。

在本案例中,存储全局变量的基地址在e.exe+1CB2D8,其内存如 13所示。

13

其结构与局部变量是一样的,区别在于前者存储在.data”区段,而后者存储在“Heap”(堆)当中。

经过分析,发现存在变量Cache,其内存结构没有发生变化。触发条件为赋值粘贴同一代码,其代码地址位于004E5000,如 14所示,内存数据如 15所示。(Cache变量影响指令的生成)

14

 

15

为了便于理解,给出C样式的变量数据结构。变量上下文的结构如 16所示。动态变量结构如 17所示。

 

16

17

在上文中,我们提到易语言通过主动和怠性的俩种方式进行代码的Parsing,怠性Parsing又可分为如下几种情况:回车格式化代码、单击编译、Ctrl+S保存代码等。

因此,我们通过定位在内存中的代码,并尝试通过Ctrl+S保存代码进行内存数据分析。定位到 18所示位置。其中edi指向的是当前的函数名,[edi+bc]+8指向的是Parsing后的AST树。

18

编写脚本和设计代码,进行数据分析,如 19所示:

 

19

经过测试,字节Offset:0-4表示指令类型,如6A 34 00 00 00表示“赋值”。其中第一个字节具有特殊意义,一般表示是第一个expr,如果有expr嵌套,后续字节不会出现。同时,字节01代表一段指令的结束。(01的存在,可减少指令类型的描述,使得同操作指令可优化内存占用。)

接下来给出部分的指令类型表,如 4所示,包含流程控制、算数运算、逻辑比较、位运算、变量操作、数组操作、文本操作、系统操作等内容。

6A 34 00 00 00

6A 6E 02 00 00

6B 00 00 00 00

6C 01 00 00 00

赋值

判断

如果

如果真

70 03 00 00 00

70 05 00 00 00

70 07 00 00 00

70 09 00 00 00

判断循环首

循环判断首

计次循环首

变量循环首

 6A 0C 00 00 00

6A 0D 00 00 00

6A 0E 00 00 00

6A 0F 00 00 00

跳出循环

返回

结束

相乘

6A 10 00 00 00

6A 11 00 00 00

6A 12 00 00 00

6A 13 00 00 00


传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2025-7-30 21:21 被zZhouQing编辑 ,原因: 我去,参考资料打错了
上传的附件:
收藏
免费 15
支持
分享
最新回复 (16)
雪    币: 1568
活跃值: (2026)
能力值: ( LV12,RANK:229 )
在线值:
发帖
回帖
粉丝
2

许久未上论坛,变化好大。比如论坛似乎默认关注自己了,同时我也点了个VIP的标志,顺便换了一个和 Nisy 叔差不多的头像,哈哈。
----
 我去,忘记传代码和说明版本了。还有,图片好像被压缩了,看看咋改。

----

好像能八卦的好多,比如小弟我捡到一份VMP还原工具的源码、某资金盘的账号密码及MFA密码。(听说卷了30亿,一方面说明法律和知识科普的重要性、一方面说明传销的暴利、一方面说明我大概率错过该产业的上升期了)

这年头,易语言都能玩WEB3了。

最后于 2025-7-30 19:07 被zZhouQing编辑 ,原因: 八卦
2025-7-30 18:36
0
雪    币: 3249
活跃值: (7683)
能力值: ( LV9,RANK:235 )
在线值:
发帖
回帖
粉丝
3
大佬写的很好啊,结构清晰易读。牛的
2025-7-30 21:56
1
雪    币: 5195
活跃值: (6058)
能力值: ( LV10,RANK:160 )
在线值:
发帖
回帖
粉丝
4
如果给整个编译器逆完重写,支持x64,还能再创一次辉煌,哈哈哈哈~

没想到现在还有人对易语言做这么细致的分析,满满都是回忆~
2025-7-30 22:40
2
雪    币: 491
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
牛的牛的牛的牛的
2025-7-31 01:29
0
雪    币: 2815
活跃值: (12067)
能力值: (RANK:385 )
在线值:
发帖
回帖
粉丝
6
佩服
2025-7-31 09:54
0
雪    币: 2976
活跃值: (3846)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
感谢分享,,受教了。
2025-7-31 11:09
0
雪    币: 230
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
8
学习啦,感谢打了分享
2025-7-31 12:56
0
雪    币: 144
活跃值: (1953)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
写的很好,标记一下
2025-7-31 13:48
0
雪    币: 155
活跃值: (3921)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
感谢分享,,受教了。 
2025-7-31 16:03
0
雪    币: 613
活跃值: (2967)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
zZhouQing 许久未上论坛,变化好大。比如论坛似乎默认关注自己了,同时我也点了个VIP的标志,顺便换了一个和 Nisy 叔差不多的头像,哈哈。---- 我去,忘记传代码和说明版本了。还有,图片好像 ...
细说易语言web3资金盘事件?或者粗讲一下
2025-8-2 02:16
0
雪    币: 1568
活跃值: (2026)
能力值: ( LV12,RANK:229 )
在线值:
发帖
回帖
粉丝
12
轻装前行 细说易语言web3资金盘事件?或者粗讲一下[em_004]
web3有个生态叫 web3链游,例如冒险岛(MapleStory),原则上,玩家有对游戏和资产的完全所有权。现实上,参与游戏的玩家有机会得到游戏收入的分红。基于此,大老板会雇佣工作室进行脚本开发,也就是搬砖。而脚本开发的常客是易语言,所以我个人认为,易语言也进入到 web3 的领域了。

我捡到的资金盘账号是 web2.0 的产物,简单来说,web2.0 时代的资金盘类似于股票骗局,仅在增量不断上升的情况下才有机会套到现金。当增量停止,就是抛售存量的时候,优先进入到股票骗局的人一般会优先套现跑路,至此股票骗局的泡沫难以掩盖,导致崩盘。
2025-8-2 04:50
0
雪    币: 42
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
13
能私聊吗
2025-8-3 04:40
0
雪    币: 8
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
易语言太老了,有Cocos  C#  erlang  unity 语言逆向的可以交流一下
2025-9-3 02:21
0
雪    币: 136
活跃值: (533)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
易语言大手子
2025-9-30 14:31
0
雪    币: 5
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
16
可以逆向易写的exe么?大佬
2025-10-30 09:02
0
雪    币: 5
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
mb_alkmadjr 可以逆向易写的exe么?大佬
写法和数据逆出来
2025-10-30 09:03
0
游客
登录 | 注册 方可回帖
返回