同事有个需求,他的进程会加载一个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. php之ob_start()缓冲区

    ob_get_contents()函数及与其相关几个函数的用法 ob_start() ob_get_contents(); 获取缓冲区内容,如果是纯 html内容或标签,则都会放于浏览器的缓冲区中. ...

  2. nginx日志切割脚本shell

    nginx-log-rotate.sh: #!/bin/bash#---------------------------------------------# Comment:Used for rot ...

  3. 基于6U VPX的 SRIO 接口, 和PCIe 接口的msata 固态存储卡

    基于6U VPX 的mSATA高性能数据存储板     一.板卡概述 该产品系我司自主研发.基于标准6U VPX架构. 二.产品特性       最大存储容量8TB        读写方式RAID0 ...

  4. Vue-cli3 环境的搭建

    Vue-cli3 环境的搭建 准备 浏览器插件:Vue.js devtools VsCode 和 VsCode 插件 WebStorm Nodejs vue-cli git 起飞 安装vue-cli3 ...

  5. 数据库系统实现 第一章 DBMS实现概述

    DBMS提供的能力 1)持久存储 DBMS在灵活性方面比文件系统要好,同时支持对非常大量数据的存储 2)编程接口 3)事务管理 DBMS支持对数据的并发存取,即多个不同的进程(称作事物)同时存取操作, ...

  6. lik模糊e查询语句,索引使用效果详解

    一.like查询与索引 在oracle里的一个超级大的表中,我们的where条件的列有建索引的话,会走索引唯一扫描INDEX UNIQUE SCAN.如select * from table wher ...

  7. Vue:列表渲染 v-for on a <template>

    类似于 v-if,你也可以利用带有 v-for 的 <template> 渲染多个元素.比如: <html> <head> <title>Vue v-f ...

  8. Uva10491 Cows and Cars 【迁移自洛谷博客】

    题目大意 假设有a头牛,b辆车(门的总数为a+b),你先选一个门,然后你最终选择前主持人会替你打开C扇有牛的门(不会打开你已经选择的门),问你要不要换门,输出"总是换门"的策略下, ...

  9. ubuntu 安装phpunit

    一.下载安装 wget https://phar.phpunit.de/phpunit-7.2.phar chmod +x phpunit-7.2.phar sudo mv phpunit-7.2.p ...

  10. python wxpython

    pip install wxpython import wxapp = wx.App(False)frame = wx.Frame(None, wx.ID_ANY, "Hollo World ...