开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 2653|回复: 11
收起左侧

[技术专题] 易语言核心库依赖项精简化分析

[复制链接]

结帖率:65% (36/55)
发表于 2023-11-23 17:27:35 | 显示全部楼层 |阅读模式   河北省石家庄市
本帖最后由 糖心疼 于 2023-11-23 18:14 编辑

  • 分析目的

编译和独立编译所依赖的核心库文件krnln.fnr 实在是大,很多时候开发用不到这么多命令和组件。支持库本质也是动态链接库DLL,就想着看能否用C++重构并升级,精简掉不必要的,只保留必须的依赖。减小空程序的体积。



  • 分析过程

首先用DLL函数查看器分析krnln.fnr,得到若干DLL导出的函数。和支持库所必须的函数GetNewInf。经过反汇编调试跟踪,发现在编译后的exe中并未调用GetNewInf函数。反而是使用的GetNewSock函数。IDA调试跟踪后,代码运行流程如下:LoadLibraryA 加载krnln.fnr,加载失败:读注册表Software\\FlySky\\E\\Install 尝试从易语言安装目录里读取krnln.fne。加载成功:获取GetNewSock函数地址。进行函数强制转换 设置返回值int 调用方式__cdecl  传递参数1000。v5 = (void (__cdecl *)(int))((int (__stdcall *)(int))GetNewSock)(1000);得到返回值后,执行v5(4206592);   所有关键的代码都在GetNewSock里面。其他的应该都是易语言编译出来的软件的格式自带的代码。无需干预。

[C++] 纯文本查看 复制代码
int sub_40108E()
{
  const CHAR *v0; // eax
  HMODULE LibraryA; // eax
  char *v2; // ebx
  const CHAR *v3; // eax
  FARPROC GetNewSock; // eax
  void (__cdecl *v5)(int); // eax
  LSTATUS v7; // [esp+4h] [ebp-114h]
  DWORD cbData; // [esp+8h] [ebp-110h] BYREF
  HKEY phkResult; // [esp+Ch] [ebp-10Ch] BYREF
  HMODULE hLibModule; // [esp+10h] [ebp-108h]
  char String1[260]; // [esp+14h] [ebp-104h] BYREF

  sub_4011E4(String1);
  v0 = lstrcatA(String1, "krnln.fnr");
  LibraryA = LoadLibraryA(v0);
  if ( LibraryA )
    goto LABEL_7;
  if ( !RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\FlySky\\E\\Install", 0, 0x20019u, &phkResult) )
  {
    cbData = 259;
    v7 = RegQueryValueExA(phkResult, "Path", 0, 0, (LPBYTE)String1, &cbData);
    RegCloseKey(phkResult);
    if ( !v7 )
    {
      v2 = &String1[lstrlenA(String1) - 1];
      if ( *v2 != 92 )
        *(_WORD *)v2 = 92;
      v3 = lstrcatA(String1, "krnln.fne");
      LibraryA = LoadLibraryA(v3);
      if ( LibraryA )
      {
LABEL_7:
        hLibModule = LibraryA;
        GetNewSock = GetProcAddress(LibraryA, "GetNewSock");
        if ( GetNewSock )
        {
          v5 = (void (__cdecl *)(int))((int (__stdcall *)(int))GetNewSock)(1000);
          if ( v5 )
          {
            v5(4206592);
            ExitProcess(0);
          }
        }
        FreeLibrary(hLibModule);
      }
    }
  }
  MessageBoxA(0, "Not found the kernel library or the kernel library is invalid!", "Error", 0x10u);
  return -1;
}


继续跟踪
GetNewSock
[C++] 纯文本查看 复制代码
int (__stdcall *__userpurge GetNewSock@<eax>(int a1@<ebx>, int a2))(int)
{
  int (__stdcall *result)(int); // eax

  switch ( a2 )
  {
    case 1000:
      goto LABEL_4;
    case 1001:
      result = sub_1002E172;
      break;
    case 1002:
      result = sub_1005D6F0;
      break;
    case 1003:
      sub_1002FBF0(dword_1011A834 + 1);
      sub_1002FBF0(a1);
LABEL_4:
      result = sub_1002E172;
      break;
    default:
      result = 0;
      break;
  }
  return result;
}


switch中的1000直接返回了result = sub_1002E172,进入sub_1002E172
[C++] 纯文本查看 复制代码
int __stdcall sub_1002E172(int a1)
{
  return sub_1002D62F(a1, 0, 0);
}

既然返回了这个函数。根据上面的代码。得处这个int a1其实是4206592
[C++] 纯文本查看 复制代码
int __thiscall sub_1002D62F(_DWORD *this, int a2, SIZE_T dwSize, LPCSTR lpString)
{
  int (*v4)(void); // eax
  int result; // eax

  this[298] = GetProcessHeap();
  ++this[49];
  v4 = (int (*)(void))sub_1005F880(a2, dwSize, lpString);
  result = v4();
  --this[49];
  return result;
}

来到这一步发现他获取了默认堆栈句柄。a2就是之前的a1也就是4206592、SIZE_T dwSize =0、 LPCSTR lpString=0、this[49]进行了偏移,v4 = (int (*)(void))sub_1005F880(a2, dwSize, lpString);  又是一个里面的代码返回的函数指针。
[C++] 纯文本查看 复制代码
const CHAR *__thiscall sub_1005F880(int this, const CHAR *a2, SIZE_T dwSize, LPCSTR lpString){
}

最后这个代码就不上了。没啥意义了。761行。代码量很大。里面也有调用其他函数。大概操作就是初始化库的一些操作。不是说重构不了。只能说工作量和工期都很大,不值得投入了。
易语言这个核心库,和平时其他的支持库还是不一样的。他文档中说的是GetNewInf就够了。但实际上核心库完全就没用这个函数。反而是自己造了个函数。还搞了自己的格式。完全和易语言支持库的标准不同。

  • 最终结果
最后因代码量的问题,放弃了重构核心库的想法。但也并非没有实质性的收获,目前是可以把易语言编译的程序精简化。相当于套壳,原始文件当系统文件写入电脑。
具体的操作如下:

1、将krnln.fnr拷贝一份,或者放在服务器上,让他可以通过http请求进行下载,或者其他的方式提供下载。
2、编写DLL,声明API GetNewSock_ 库文件名为krnln.fnr 库中对应名称为 GetNewSock 参数为整数型 参数名随便写。推荐用C++写。C++写的不依赖krnln.fnr 或者静态编译写。
  
DLL命令名返回值类型公开备 注
GetNewSock_整数型 
DLL库文件名:
krnln.dll
在DLL库中对应命令名:
GetNewSock
参数名类 型传址数组备 注
arg1整数型


3、自己设定一个路径,一般为电脑的临时目录,dll加载的时候或者启动子程序的时候,检测临时目录是否存在krnln.fnr,如果存在就不管他。如果不存在就http请求下载并写到临时目录。
4、dll中写一个函数,名称为GetNewSock 记得公开。并且注意检查声明的API 和 远程下载保存的krnln.fnr的路径问题。可以用置DLL装载目录切换到临时目录
  
子程序名返回值类型公开备 注
GetNewSock整数型 
参数名类 型参考可空数组备 注
arg1整数型
返回 (GetNewSock_ (arg1))

都做完以后,编译DLL。将后缀改为fnr,放到易语言的lib目录中,记得备份krnln.fnr。
至此。易语言再编译出来的依赖就会是你自己编译的krnln.fnr,而不再是原本那个大体积的了。
以后这台电脑只要运行过一次软件。其他软件再运行再也不会下载。体积依然保持的是精简后的体积。‘
也是不得以的方法了。如果以后谁有功夫去重构GetNewSock,记得艾特一下。   感谢汇编提供帮助的 NULL!

评分

参与人数 1好评 +1 精币 +3 收起 理由
Suky + 1 + 3 感谢分享,很给力!~

查看全部评分


结帖率:0% (0/1)

签到天数: 6 天

发表于 2024-3-5 00:11:49 | 显示全部楼层   重庆市重庆市
支持!!!
回复 支持 反对

使用道具 举报

结帖率:100% (4/4)

签到天数: 27 天

发表于 2024-2-2 08:42:49 | 显示全部楼层   山东省淄博市
感谢分享,学习一下
回复 支持 反对

使用道具 举报

签到天数: 22 天

发表于 2024-1-8 14:30:40 高大上手机用户 | 显示全部楼层   四川省广元市
gftluo 发表于 2023-12-31 00:03
涛哥软件的各种库 确实 挺无语

不开源的东西有扩展就不错了,以后还能自己写支持库
回复 支持 反对

使用道具 举报

结帖率:25% (1/4)

签到天数: 1 天

发表于 2023-12-31 00:03:40 | 显示全部楼层   广东省茂名市

涛哥软件的各种库 确实 挺无语
回复 支持 反对

使用道具 举报

签到天数: 3 天

发表于 2023-12-30 11:01:00 | 显示全部楼层   辽宁省大连市
分享给自己写的监控指定软件是否运行的软件
回复 支持 反对

使用道具 举报

结帖率:100% (3/3)

签到天数: 3 天

发表于 2023-12-29 02:06:08 | 显示全部楼层   湖南省娄底市
强强强!!!
回复 支持 反对

使用道具 举报

结帖率:0% (0/3)

签到天数: 7 天

发表于 2023-12-15 11:18:42 | 显示全部楼层   四川省乐山市
a524666979 发表于 2023-11-23 18:00
涛哥软件的各种库 确实 挺无语

所以才有众筹重新写核心库!
回复 支持 反对

使用道具 举报

签到天数: 1 天

发表于 2023-11-25 10:05:09 | 显示全部楼层   广东省珠海市
强大网友,都是牛人。
回复 支持 反对

使用道具 举报

签到天数: 9 天

发表于 2023-11-24 11:48:51 | 显示全部楼层   四川省德阳市
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 诚聘英才| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 800073686,邮箱:800073686@b.qq.com
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表