易语言静态编译由于是静态地址,所以已经有工具可以分析了;但是非静态的因为是动态加载库,分析起来还是有点小麻烦的。这个笔记是我之前分析一个易样本时总结的,可能有些地方也不对,凑合看吧。
要点
右键-属性-详细信息
Resource Hacker或其他可查看资源文件的工具
易语言程序依赖于自实现的库(.fnr)执行,针对易语言的编译模式有静态编译
、非静态编译
和独立编译
,如下图:
由于易语言是自写的框架,类似于MFC,因此如果未处理编译后的程序,程序中将存在一些固定的字符串。
静态编译是直接将库文件与程序合并。
该种编译模式会将库文件存放在程序中,在WinMain
入口会获取读取自身的内容,然后释放出库文件。
随后加载库文件,并调用一个固定函数GetNewSock
。
最后调用函数
进入该函数后,会看到call eax,eax为函数入口。
黑月编译器是网友针对易语言程序编写的一款编译器,他直接会优化掉前期的初始化代码,包括clr(c library runtime)
初始化,直接进入到易语言的标准入口。
易语言的函数大致分有三种,分别为窗体控件的消息函数、用户自定义函数、库函数和组件属性函数。
消息函数都是通过固定代码段调用,代码段定位流程如下:
找到如图特征
进入函数后找到最后一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也在附录中列出。
typdef struct 字节集 { int unkown; int length; char* bytes; };
程序入口为两个函数。
进入第二个后可以看到如下代码特征。
或者搜索到如下字符串。
只能用来分析静态编译的程序。
选择易语言反编译器
IDA会自动识别由于的函数,并在工具栏新增易语言
。
新增的项可以自动识别资源常量
、窗体
、消息函数(控件函数)
。
EDebug可以手动生成后缀为sig的易语言特征,打开配套工具。
然后将易语言的支持库拖入即可,最后将生成的sig文件放置到对应分析工具的插件目录下。
易语言可以设置花指令来干扰程序的逆向分析。在工具栏的工具-系统配置
的窗口中选择安全
,可以设置花指令等级,默认为1。
级别不同,花指令形式也不同。
但是每一级别的花指令代码都是固定的,所以可以在IDA中使用脚本进行批处理处理,或者使用OD的插件去除花指令。
输入要去除花指令的起始地址和地址段大小后,点击执行即可去除。
易语言载入窗口的命令为载入(,,)
,窗体的类型为0x10001,因此可以通过搜索push 0x10001来找到该命令,或者有调用窗口函数的代码段来获取窗口ID。再将原始加载的窗口ID进行替换即可实现窗口跳转。
搜索push 0x10001
结果。
断点放开后执行,直接能跳转到第二个窗口。
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:反转整数字节序
0x1C:延迟 0x24:申请内存
0x0:转换可执行文件数据
0x0:压缩数据 0x4:解压数据 0x8:取数据摘要 0xC:加密数据 0x10:解密数据 0x14:数字签名 0x18:签名验证
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目录列表
0x0:创建快捷方式 0x4:查询快捷方式 0x8:浏览文件夹 0xC:删除到回收站 0x10:进度复制文件 0x14:进度移动文件 0x18:执行 0x1C:取特定目录 0x20:关闭系统
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:设置屏幕分辨率
0x16010030:编辑框 0x16010031:图片框 0x16010032:外形框 0x16010033:画板 0x16010034:分组框 0x16010035:标签 0x16010036:按钮 0x1601016B:时钟 0x16010006:时钟
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
最后提供的函数索引有些不一定正确,索引获取方法就是易语言写一个调用库函数,然后自己去调试器里看他穿的值。之前有想法是做一个特征然后把所有库函数的调用给识别出来,但是在库文件加载顺序不确定下又懒得去弄,就干脆不弄了。
恭喜ID[飞翔的猫咪]获看雪安卓应用安全能力认证高级安全工程师!!
最后于 5天前 被PlaneJun编辑 ,原因: