同事有个需求,他的进程会加载一个DLL,他需要在那个DLL的DllMain函数执行之前控制DLL,修改DLL的内存。

以上工作要求全部在应用层执行。

这个其实有点悲剧。

因为这个需求其实有点坑,因为需要在应用层来做,而且好多事情都是高难度事情。

最后我给提了几种解决方案。

1:HOOK LoadLibraryA/W,然后发现如果是目标DLL,那么使用LoadLibraryEx不执行DllMain加载,然后等加载成功了之后,先处理DLL,最后创建线程执行DllMain。

优点:简单方便,工作量少。

缺点:DllMain线程环境、调用栈是伪造的,可能会被检测发现。

2:为了规避上面的问题,就不能用其他函数来做了,只能乖乖使用LoadLibrary族正统的函数,刚好,有一个。

当LoadLibraryA/W抓到了目标DLL之后,可以根据文件解析它的入口点,然后再在入口点处写入一个“C3”,即“ret”,是写入文件中,

然后再调用真实的LoadLibraryA/W函数加载,之后再去找这个入口点,修复C3,最后创建线程执行DllMain。

优点:比上面还简单。只是按位置写文件即可。

缺点:工作量比较大,需要修改原模块,可能导致原模块在其他进程中无法启动,DllMain线程环境、调用栈是伪造的,可能会被检测发现。

3:如果不想那么麻烦的话,还有个办法。

当LoadLibraryA/W抓到了目标DLL之后,拷贝一份目标DLL的文件,到其他的地方,比如Temp目录,

硬编码修改DLL文件的入口点内容,到本地内存中的一个函数里面,然后直接放行加载即可,这样,在模块加载之后,立刻就会从DllMain入口跳转到我们的函数中。而且不会有副作用。

但是为了它,我们实际上是模拟了整个一套API的接口,来让它以为自己是运行在正确的环境中的。

优点:对原模块没有修改,DLL启动之后,入口点会直接调用我们的函数。

缺点:工作量很大,路径被替换了,所以要多HOOK几个其他的函数,如GetModuleHandleA/W、GetModuleFileName、GetModuleFileNameEx等,在LoadLibraryA/W中,也需要判断模块是否已经加载,如果已经加载,则直接返回已经加载的模块handle。

同事遇到了一个问题(在DllMain函数之前抢控制权)的更多相关文章

  1. DLL 支持MFC 没有DLLMAIN函数

    如果使用VC编写DLL时,需要MFC功能: 一般在源文件里就不能手动写DLLMAIN函数了 它给MFC集成了,\src\mfc\dllmodule.cpp打开它,里面有有一个DLLMAIN函数,根据源 ...

  2. dllMain函数

    Windows在加载DLL的时候,需要一个入口函数,就如同控制台或DOS程序需要main函数.Win32程序需要WinMain函数一样.一些例子中,DLL并没有提供DllMain函数,应用工程也能成功 ...

  3. 还看不懂同事的代码?Lambda 表达式、函数接口了解一下

    当前时间:2019年 11月 11日,距离 JDK 14 发布时间(2020年3月17日)还有多少天? // 距离JDK 14 发布还有多少天? LocalDate jdk14 = LocalDate ...

  4. 将对象的所有属性名放到一个数组中 || 获得对象的所有属性名 || return;不具有原子性 || 怎样自己制作异常|| 判断对象有没有某个属性 || 当传递的参数比需要的参数少的时候,没有的值会被赋予undefined || 获得函数实际传递的参数 || 怎么用函数处理一个对象 || 用一个名字空间定义一个模块所有的函数 || 给一个对象添加方法

    获得对象的所有属性名 || 将对象o的所有属性名放到数组中 var o = {x:1,y:2,z:3}; var arr = []; var i = 0; for(arr[i++] in o){};/ ...

  5. C语言学习_C如何在一个文件里调用另一个源文件中的函数

    问题 C如何在一个文件里调用另一个源文件中的函数,如题. 解决办法 当程序大了代码多了之后,想模块化开发,不同文件中存一点,是很好的解决办法,那我们如何做才能让各个文件中的代码协同工作呢?我们知道,m ...

  6. 一个简化的printf函数

    <C和指针>第7章第5道编程题: 实现一个简化的printf函数,它能够处理%d.%f.%s 和 %c 格式码,根据ANSI标准的原则,其他格式码的行为是未定义的.你可以假定已经存在函数 ...

  7. 面试题之java 编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。 要求不能出现截半的情况

    题目:10. 编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串. 但是要保证汉字不被截半个,如"我ABC"4,应该截为"我AB",输 ...

  8. 一个非常有用的函数——COALESCE

    原文:一个非常有用的函数--COALESCE 很多人知道ISNULL函数,但是很少人知道Coalesce函数,人们会无意中使用到Coalesce函数,并且发现它比ISNULL更加强大,其实到目前为止, ...

  9. 一个简单的日志函数C++

    有时候程序总是会发生意想不到的情况,为了方便排查错误的情况,还是写日志比较方便.这里自己写了一个简单的函数,能实现基本的功能. BOOL WriteLog(char * DataBuffer) { C ...

随机推荐

  1. 一、WebApi模型验证实践项目使用

    一.启语 前面我们说到,模型验证的原理(包含1.项目创建,2.模型创建,3.走通测试模型验证,4.在过滤器中处理返回json格式(非控制器内))-完全是新手理解使用的,新番理解 通常情况下,对于那些经 ...

  2. CentOS 6.5之SSH 免密码登录

    0.说明 这里为了方便说明问题,假设有A和B两台安装了centos6.5的主机.目标是实现A.B两台主机分别能够通过ssh免密码登录到对方主机.不同主机的配置过程一样,这里介绍A主机的配置过程. 事先 ...

  3. MongoDB 存储引擎选择

    MongoDB存储引擎选择 MongoDB存储引擎构架 插件式存储引擎, MongoDB 3.0引入了插件式存储引擎API,为第三方的存储引擎厂商加入MongoDB提供了方便,这一变化无疑参考了MyS ...

  4. mongodb 索引基础

    一 .索引基础:    MongoDB的索引几乎与传统的关系型数据库一模一样,这其中也包括一些基本的优化技巧.下面是创建索引的命令:    > db.test.ensureIndex({&quo ...

  5. [BZOJ5305] [HAOI2018] 苹果树 数学 组合计数

    Summary 题意很清楚: 小 \(C\) 在自己家的花园里种了一棵苹果树, 树上每个结点都有恰好两个分支. 经过细心的观察, 小 \(C\) 发现每一天这棵树都会生长出一个新的结点. 第一天的时候 ...

  6. CentOS7.5常用命令

    常用命令: 关机shutdown -h now 参数:重启-r定时-r 23:59 分-r 10 查源软件yum list |grep telnet参数:安装install 服务启动systemctl ...

  7. JavaSE---多线程---扩展

    1.线程的类型 1.1 用户线程 1.2 内核线程 2.java线程 java线程的创建依赖于系统内核,通过JVM调用系统库创建内核线程: 内核线程与java-Thread是1:1的映射关系: 3.线 ...

  8. 正确读取resources目录下的文件

    问题描述:本地可以正常读取areacode.json文件,打成jar包在测试环境找不到该文件. 问题代码: static { StringBuffer strbuffer = new StringBu ...

  9. java生成随机数方法

    java生成随机数方法: String random = String.valueOf(new Random().nextInt(9000)); String timestamp = String.v ...

  10. JavaScript之BOM+DOM

    BOM 浏览器对象模型, 用于把浏览器相关的组件封装为对象进行操作. BOM是包含了DOM的. window对象 弹出框相关 确认: 取消: 与打开关闭window有关的方法 定时器相关 暂停选老婆 ...