
要点
- 易语言的入口函数特征
- 各种函数的调用特征以及识别
- 针对易语言程序的分析插件
1、如何识别易语言程序
一、查看文件信息右键-属性-详细信息

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


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

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

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

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


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


五、易语言标准入口

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



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


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

最后调用函数

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


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



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

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

找到如图特征

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

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



找到 case 2008:


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

三、库函数
库函数为易语言自写支持库里的函数,类似Windows的DLL文件。函数原型如下。
1
| 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、易语言分析插件
只能用来分析静态编译的程序。

选择易语言反编译器

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

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

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

然后将易语言的支持库拖入即可,最后将生成的sig文件放置到对应分析工具的插件目录下。
6、花指令
易语言可以设置花指令来干扰程序的逆向分析。在工具栏的工具-系统配置的窗口中选择安全,可以设置花指令等级,默认为1。

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

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

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

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



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

8、附录
一、支持库函数偏移
系统核心支持库——krnln
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
| 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:标准输出 0x908:标准输入 0x90C:指针到文本 0x9D4:到字节 0x9D8:到短整数 0x9DC:到整数 0x9E0:到长整数 0x9E4:到小数 0x9F8:左移 0x9FC:右移 0xA7C:取程序名称 0xA8C:取最后错误 0xAA0:文本到UTF8 0xAA4:UTF8到文本 0xAB0:反转整数字节序
|
特殊功能支持库——spec
可执行文件数据转换支持库——cnvpe
数据操作支持库——dp1
1 2 3 4 5 6 7
| 0x0:压缩数据 0x4:解压数据 0x8:取数据摘要 0xC:加密数据 0x10:解密数据 0x14:数字签名 0x18:签名验证
|
互联网支持库——internet
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| 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
1 2 3 4 5 6 7 8 9
| 0x0:创建快捷方式 0x4:查询快捷方式 0x8:浏览文件夹 0xC:删除到回收站 0x10:进度复制文件 0x14:进度移动文件 0x18:执行 0x1C:取特定目录 0x20:关闭系统
|
应用接口支持库——eAPI
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| 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
1 2 3 4 5 6 7 8 9
| 0x16010030:编辑框 0x16010031:图片框 0x16010032:外形框 0x16010033:画板 0x16010034:分组框 0x16010035:标签 0x16010036:按钮 0x1601016B:时钟 0x16010006:时钟
|