同事有个需求,他的进程会加载一个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. JavaScript原型&原型链

    原型&原型对象 先来一段简单的代码: function Fun(name) { this.name = name } var obj = new Fun('obj') JavaScript中的 ...

  2. docker运行模式图

    docker运行模式图:

  3. 修改Oracle并行度

    什么是并行度: 并行度的优点就是能够最大限度的利用机器的多个cpu资源,是多个cpu同时工作,从而达到提高数据库工作效率的目的.在系统空闲时间,使用并行是个不错的选择,但是好东西总是相对而言,没有绝对 ...

  4. css3 清除浮动

    eg:三个div,父级div下面有两个div分别float:left和float:right <style> .container{width:400px;border:3px soild ...

  5. 通过注释查找mysql的表名

    通过注释查找mysql的表名 select * from INFORMATION_SCHEMA.columns where COLUMN_NAME Like '%placement%';

  6. CentOS7.2安装Oracle12.1.0.2

    Centos7.2环境安装(安装桌面) #安装界面 #查看版本 cat /etc/redhat-release #查看连接 ifconfig eth0 echo "127.0.0.1 tes ...

  7. The main Method

    The main Method You can call static methods without having any objects. For example, you never const ...

  8. Python3解leetcode Factorial Trailing Zeroes

    问题描述: Given an integer n, return the number of trailing zeroes in n!. Example 1: Input: 3 Output: 0 ...

  9. 【LeetCode 85】最大矩形

    题目链接 [题解] 把所有的"1"矩形分成m类. 第j类的矩形.他的右边界跟第j列紧靠. 那么. 我们设f[i][j]表示(i,j)这个点往左最长能延伸多少个数目的"1& ...

  10. centos7下安装storm步骤

      前言 真是后知后觉,最近忙也要学习,把以前丢的都要拾起来.原理懂不懂也把环境搭起来学习.   环境  centos7 jdk 1.8 zookeeper 3.4.13 storm 1.2.2 安装 ...