首页
论坛
课程
招聘
[原创]易语言程序分析笔记
2022-9-22 17:52 4984

[原创]易语言程序分析笔记

2022-9-22 17:52
4984

        易语言静态编译由于是静态地址,所以已经有工具可以分析了;但是非静态的因为是动态加载库,分析起来还是有点小麻烦的。这个笔记是我之前分析一个易样本时总结的,可能有些地方也不对,凑合看吧。

要点

  • 易语言的入口函数特征
  • 各种函数的调用特征以及识别
  • 针对易语言程序的分析插件

1、如何识别易语言程序

一、查看文件信息右键-属性-详细信息

二、查看资源文件Resource Hacker或其他可查看资源文件的工具

三、库文件

易语言程序依赖于自实现的库(.fnr)执行,针对易语言的编译模式有静态编译非静态编译独立编译,如下图:

  • 编译:编译程序时,会将所有需要用到的库文件生成到同程序的目录下。

  • 非静态编译:编译程序时,将所有用到的库文件写入到程序中,与程序合并,编译出来的文件只有程序本身。

  • 独立编译:与静态编译相同之处是编译出来后只有程序本身,但运行程序时,会将所有用到的库文件写入到临时目录中,然后加载库文件。

四、字符串特征

由于易语言是自写的框架,类似于MFC,因此如果未处理编译后的程序,程序中将存在一些固定的字符串。

五、易语言标准入口

①静态编译

静态编译是直接将库文件与程序合并。

②非静态编译

该种编译模式会将库文件存放在程序中,在WinMain入口会获取读取自身的内容,然后释放出库文件。

随后加载库文件,并调用一个固定函数GetNewSock

最后调用函数

进入该函数后,会看到call eax,eax为函数入口。

③黑月编译

黑月编译器是网友针对易语言程序编写的一款编译器,他直接会优化掉前期的初始化代码,包括clr(c library runtime)初始化,直接进入到易语言的标准入口。

2、易语言的函数类型及特征

易语言的函数大致分有三种,分别为窗体控件的消息函数、用户自定义函数、库函数和组件属性函数。

一、消息函数

消息函数都是通过固定代码段调用,代码段定位流程如下:

找到如图特征

进入函数后找到最后一call 局部变量,该位置调用的就是消息函数

将函数对应到IDA中可直接定位到流程。

找到 case 2008:


二、用户自定义函数

用户自定义的函数调用与通常的函数调用方式一致。

三、库函数

库函数为易语言自写支持库里的函数,类似Windows的DLL文件。函数原型如下。

E_FuncCallBack(2,参数一的值,参数一是否可忽略,参数一的类型,参数二的值,参数二是否可忽略,参数二的类型)

该函数是一个变参函数,参数一为欲调用欲调用函数的参数个数,然后其余的以三个参数为一组表示参数的信息。忽略参数的值为布尔值,0表示不可以忽略,1表示可忽略;其参数类型可参考的值如下(可能不完整):

类型

0x80000004

文本型

0x80000101

文本型

0x80000000

通用型

0x80000002

逻辑型

0x80000005

字节集

0x80000006

子程序指针

0x80000301

数值型

0x80000601

数值型

0x10001

窗体

由于易语言的编译模式不同,库函数调用代码也会产生差异。接下来分别解释静态编译非静态编译下,函数代码的差异。

  • 静态编译

  • 非静态编译


非静态编译的程序,在调用库函数时不再通过静态地址的方式调用,而是通过传入库文件序号欲调用对应函数的偏移到寄存器中,然后调用。

库文件序号指的是库文件是程序中加载的第几个文件。序号从0开始,易语言程序在运行初期最先加载的库文件为该库文件,记加载序号为0;如果再加载一个库文件的话则加载新加载的库文件序号为1。对于调用krnln.fnr库文件的函数,易语言程序以隐式形式传递序号,因此在信息框函数调用的反汇编代码中并未看到传入0序号。常用库文件的函数偏移在附录中贴出。

四、组件属性函数

函数分为两种,一种是对组件的属性修改,另一种是组件的自带函数。

  • 属性修改

参数一:父窗口

参数二:子窗口

参数三:属性下标

参数四:未知,一般都为-0x1

参数五:

  • 自带函数调用

与消息函数类型。参一:参数个数、参二:值,也就是父窗口ID、参三:ID、参四:参数类型

因为控件存在于krnln.fnr库中,因此在非静态编译中,库函数序号也是隐式传递。部分组件ID也在附录中列出。

3、易语言的基本数据类型

一、字节集

typdef struct 字节集
{
   int unkown;
   int length;
   char* bytes;
};

4、编译器:黑月

程序入口为两个函数。

进入第二个后可以看到如下代码特征。

或者搜索到如下字符串。

5、易语言分析插件

一、E-Debug(https://github.com/fjqisba/E-debug-plus

只能用来分析静态编译的程序。

  • OD

  • IDA

选择易语言反编译器

IDA会自动识别由于的函数,并在工具栏新增易语言

新增的项可以自动识别资源常量窗体消息函数(控件函数)

  • 特征生成

EDebug可以手动生成后缀为sig的易语言特征,打开配套工具。

然后将易语言的支持库拖入即可,最后将生成的sig文件放置到对应分析工具的插件目录下。

6、花指令

易语言可以设置花指令来干扰程序的逆向分析。在工具栏的工具-系统配置的窗口中选择安全,可以设置花指令等级,默认为1。

级别不同,花指令形式也不同。

但是每一级别的花指令代码都是固定的,所以可以在IDA中使用脚本进行批处理处理,或者使用OD的插件去除花指令。

输入要去除花指令的起始地址和地址段大小后,点击执行即可去除。

7、针对一些窗口跳转的破解

易语言载入窗口的命令为载入(,,),窗体的类型为0x10001,因此可以通过搜索push 0x10001来找到该命令,或者有调用窗口函数的代码段来获取窗口ID。再将原始加载的窗口ID进行替换即可实现窗口跳转。

搜索push 0x10001结果。

断点放开后执行,直接能跳转到第二个窗口。

8、附录

一、支持库函数偏移

系统核心支持库——krnln

0x0:寻找文件
0x2:相加
0x9:新建索引
0x58:取符号
0x5C:取绝对值
0x60:取整
0x64:绝对取整
0x68:四舍五入
0x6C:求次方
0x70:求平方根
0x74:求正弦
0x78:求余弦
0x7C:求正切
0x80:求反正切
0x84:求自然对数
0x88:求反对数
0x8C:是否运算正确
0x90:置随机数种子
0x94:取随机数
0xC0:位取反
0xC4:位与
0xC8:位或
0xCC:位异或
0x100:取命令行
0x104:取运行目录
0x108:取执行文件名
0x10C:读环境变量
0x110:写环境变量
0x114:取所有发音
0x118:取发音数目
0x11C:取拼音
0x124:取韵母
0x128:发音比较
0x12C:输入字比较
0x130:取文本长度
0x134:取文本左边
0x138:取文本右边
0x13C:取文本中间
0x140:字符
0x144:取代码
0x148:寻找文本
0x14C:倒找文本
0x150:到大写
0x154:到小写
0x158:到全角
0x15C:到半角
0x160:到时间
0x164:到数值
0x168:到文本
0x16C:删首空
0x170:删尾空
0x174:删首位空
0x178:删全部空
0x17C:文本替换
0x180:子文本替换
0x184:取空白文本
0x188:取重复文本
0x18C:文本比较
0x190:分割文本
0x194:取字节集长度
0x198:到字节集
0x19C:取字节集数据
0x1A0:取字节集左边
0x1A4:取字节集右边
0x1A8:取字节集中间
0x1AC:寻找字节集
0x1B0:倒找字节集
0x1B4:字节集替换
0x1B8:子字节集替换
0x1BC:取空白字节集
0x1C0:去重复字节集
0x1C4:分割字节集
0x1C8:数值到大写
0x1CC:数值到金额
0x1D0:数值到格式文本
0x1D4:取十六进制文本
0x1D8:取八进制文本
0x1DC:增减时间
0x1E0:取时间间隔
0x1E4:取某月天数
0x1E8:时间到文本
0x1EC:取时间部分
0x1F0:取年份
0x1F4:取月份
0x1F8:取日
0x1FC:取星期几
0x200:取小时
0x204:取分钟
0x208:取秒
0x20C:指定时间
0x210:取现行时间
0x214:置现行时间
0x218:取磁盘总空间
0x21C:取磁盘剩余空间
0x220:取磁盘卷标
0x224:置磁盘卷标
0x228:改变驱动器
0x22C:改变目录
0x230:取当前目录
0x234:创建目录
0x238:删除目录
0x23C:复制文件
0x240:移动文件
0x244:删除文件
0x248:文件更名
0x24C:文件是否存在
0x254:取文件时间
0x258:取文件尺寸
0x25C:取文件属性
0x260:置文件属性
0x264:取临时文件名
0x268:读入文件
0x26C:写到文件
0x270:打开文件
0x274:打开内存文件
0x278:关闭文件
0x27C:关闭所有文件
0x280:锁住文件
0x284:解锁文件
0x288:移动读写位置
0x28C:移到文件首
0x290:移到文件尾
0x294:读入字节集
0x298:写出字节集
0x268:读入文件
0x2A0:写出文本
0x2A4:读入一行
0x2A8:写文本行
0x2AC:读入数据
0x2B0:写出数据
0x2B4:是否在文件尾
0x2B8:取读写位置
0x2BC:取文件长度
0x2C0:运行
0x2C4:取剪辑板文本
0x2C8:置剪辑板文本
0x2CC:剪辑板中可有文本
0x2D0:清除剪辑板
0x2D4:取屏幕宽度
0x2D8:取屏幕高度
0x2DC:取鼠标水平位置
0x2E0:取鼠标垂直位置
0x300:信息框
0x304:鸣叫
0x308:取启动时间
0x320:载入
0x330:是否已创建
0x334:取数据类型尺寸
0x35C:取窗口句柄
0x540:是否支持多用户
0x544:取错误码
0x548:取错误信息
0x54C:创建
0x550:打开
0x554:替换打开
0x558:置当前库
0x55C:取当前库
0x560:关闭
0x564:全部关闭
0x568:取库文件名
0x56C:是否已打开
0x570:取记录数
0x574:取创建时间
0x578:取字段数
0x57C:取字段名
0x580:改字段名
0x584:取字段类型
0x588:取字段尺寸
0x58C:新建索引
0x590:置当前索引
0x594:取当前索引
0x598:更新索引
0x59C:取索引数
0x5A0:取索引名
0x5A4:取索引字段
0x5A8:置加锁重试时间
0x5AC:锁住数据库
0x5B0:解锁数据库
0x5B4:锁住增删
0x5B8:解增删锁
0x5BC:锁住记录
0x5C4:解锁记录
0x5C8:全部解锁
0x5CC:取平均值
0x5D0:求和
0x5D4:取最大值
0x5D8:取最小值
0x5DC:取最大时间
0x5E0:计算数目
0x5E4:复制结构
0x5E8:复制记录
0x5EC:计算排序
0x5F0:排序
0x5F4:分类计算
0x5F8:添加
0x5FC:加记录
0x600:加空记录
0x604:替换
0x608:修改
0x60C:删除
0x610:是否已删除
0x614:恢复删除
0x618:彻底删除
0x61C:清空
0x620:读
0x624:写
0x628:读字段
0x62C:写字段
0x630:附加字节集
0x634:附加备注
0x638:索引查找
0x63C:查找
0x640:到首记录
0x644:到尾记录
0x648:跳过
0x64C:取记录号
0x650:跳到
0x654:取标签
0x658:记录是否存在
0x65c:标签跳转
0x660:首记录前
0x664:尾记录后
0x668:写出缓存
0x66c:写出所有缓存
0x670:编辑
0x674:置等待鼠标
0x678:恢复鼠标
0x67C:延时
0x688:插入字节集
0x68C:插入文本
0x690:插入文本行
0x694:删除数据
0x698:取文本注册项
0x69C:取数值注册项
0x6A0:取字节集注册项
0x6A4:写注册项
0x6A8:删除注册项
0x6AC:注册项是否存在
0x6C4:取硬盘特征字
0x6F4:转换为主机名
0x6F8:转换为IP地址
0x714:取默认底色
0x71C:快照
0x8BC:取日期
0x8C0:取时间
0x8C8:读配置项
0x8CC:写配置项
0x8D0:取配置节名
0x8D8:打开加密文件
0x8D4:取操作系统类别
0x8DC:是否已加密
0x8E0:置数据库密码
0x8E4:密码输入框
0x8E8:复制密码
0x914:写到内存
0x904:标准输出
0x90C:指针到文本
0x9D4:到字节
0x9D8:到短整数
0x9DC:到整数
0x9E0:到长整数
0x9E4:到小数
0x9F8:左移
0x9FC:右移
0xA7C:取程序名称
0xA8C:取最后错误
0xAA0:文本到UTF8
0xAA4:UTF8到文本
0xAB0:反转整数字节序

特殊功能支持库——spec

0x1C:延迟
0x24:申请内存

可执行文件数据转换支持库——cnvpe

0x0:转换可执行文件数据

数据操作支持库——dp1

0x0:压缩数据
0x4:解压数据
0x8:取数据摘要
0xC:加密数据
0x10:解密数据
0x14:数字签名
0x18:签名验证

互联网支持库——internet

0x0:连接发信服务器
0x4:断开发信服务器
0x8:添加附件文件
0xC:添加附件数据
0x10:清除所有附件
0x14:发送邮件
0x18:置代理服务器
0x1C:HTTP读文件
0x20:连接FTP服务器
0x24:断开FTP服务器
0x28:FTP文件下载
0x2C:FTP文件上传
0x30:FTP删除文件
0x34:FTP文件改名
0x38:FTP创建目录
0x3C:FTP删除目录
0x40:FTP置现行目录
0x44:FTP取现行目录
0x48:FTP目录列表

操作系统界面功能支持库——shell

0x0:创建快捷方式
0x4:查询快捷方式
0x8:浏览文件夹
0xC:删除到回收站
0x10:进度复制文件
0x14:进度移动文件
0x18:执行
0x1C:取特定目录
0x20:关闭系统

应用接口支持库——eAPI

0x0:取键盘指示灯状态
0x4:模拟按键
0x8:模拟鼠标点击
0xC:取硬盘信息
0x10:取驱动器数量
0x14:取驱动器列表
0x18:弹出光驱
0x1C:关闭光驱
0x20:取光驱盘符
0x24:光驱中是否有盘
0x28:取系统进程列表
0x2C:终止进程
0x30:取正在使用DLL列表
0x38:取系统信息
0x3C:取BIOS信息
0x40:取文件版本信息
0x44:取CPU信息
0x48:取CPU占用率
0x4C:取内存容量信息
0x50:取声卡名称
0x54:打开监视器
0x58:关闭监视器
0x5C:添加右键菜单
0x60:删除右键菜单
0x64:设置自动运行
0x68:删除临时文件
0x6C:清除历史记录
0x94:创建程序组
0x98:删除程序组
0x9C:创建程序项
0xA0:删除程序项
0xA4:取快捷方式目标
0xA8:取网卡信息列表
0xAC:取本机网卡名
0xB0:取本机网卡物理地址
0xB4:取远程网卡物理地址
0xBC:取IP地址
0xC0:撰写邮件
0xC4:取网络类型列表
0xC8:取网络工作组列表
0xCC:取网络计算机列表
0xD0:是否与互联网连接
0xDC:打开特殊系统窗口
0xE0:打开指定网址
0xE4:隐藏桌面图标
0xE8:显示桌面图标
0xEC:隐藏任务栏
0xF0:显示任务栏
0xF4:隐藏系统时钟
0xF8:显示系统时钟
0xFC:隐藏开始按钮
0x100:显示开始按钮
0x104:设置桌面壁纸
0x108:设置窗口透明度
0x10C:取显示模式列表
0x110:取当前显示模式
0x114:设置屏幕分辨率

二、组件ID

0x16010030:编辑框
0x16010031:图片框
0x16010032:外形框
0x16010033:画板
0x16010034:分组框
0x16010035:标签
0x16010036:按钮
0x1601016B:时钟
0x16010006:时钟


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

最后提供的函数索引有些不一定正确,索引获取方法就是易语言写一个调用库函数,然后自己去调试器里看他穿的值。之前有想法是做一个特征然后把所有库函数的调用给识别出来,但是在库文件加载顺序不确定下又懒得去弄,就干脆不弄了。


看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~

最后于 2022-9-22 17:54 被PlaneJun编辑 ,原因:
收藏
点赞5
打赏
分享
最新回复 (4)
雪    币: 1894
活跃值: 活跃值 (2490)
能力值: ( LV6,RANK:97 )
在线值:
发帖
回帖
粉丝
fjqisba 活跃值 2022-9-22 18:00
2
1
根据我的总结,研究易语言目前最有效的方法还是去编写IDA插件,想办法让代码可阅读化,Go语言、VB语言等同理。
雪    币: 6279
活跃值: 活跃值 (5352)
能力值: ( LV9,RANK:320 )
在线值:
发帖
回帖
粉丝
PlaneJun 活跃值 6 2022-9-22 18:02
3
0
fjqisba 根据我的总结,研究易语言目前最有效的方法还是去编写IDA插件,想办法让代码可阅读化,Go语言、VB语言等同理。
易语言按照非静态编译的这个思路是可以去做的,但是没时间。只能等别人造轮子
雪    币: 5315
活跃值: 活跃值 (939)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
如斯咩咩咩 活跃值 2022-9-22 19:58
4
0
E-Decompiler
雪    币: 708
活跃值: 活跃值 (1555)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
kakasasa 活跃值 2022-9-23 11:06
5
0
E反编译1楼很6.
游客
登录 | 注册 方可回帖
返回