同事遇到了一个问题(在DllMain函数之前抢控制权)
同事有个需求,他的进程会加载一个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函数之前抢控制权)的更多相关文章
- DLL 支持MFC 没有DLLMAIN函数
如果使用VC编写DLL时,需要MFC功能: 一般在源文件里就不能手动写DLLMAIN函数了 它给MFC集成了,\src\mfc\dllmodule.cpp打开它,里面有有一个DLLMAIN函数,根据源 ...
- dllMain函数
Windows在加载DLL的时候,需要一个入口函数,就如同控制台或DOS程序需要main函数.Win32程序需要WinMain函数一样.一些例子中,DLL并没有提供DllMain函数,应用工程也能成功 ...
- 还看不懂同事的代码?Lambda 表达式、函数接口了解一下
当前时间:2019年 11月 11日,距离 JDK 14 发布时间(2020年3月17日)还有多少天? // 距离JDK 14 发布还有多少天? LocalDate jdk14 = LocalDate ...
- 将对象的所有属性名放到一个数组中 || 获得对象的所有属性名 || return;不具有原子性 || 怎样自己制作异常|| 判断对象有没有某个属性 || 当传递的参数比需要的参数少的时候,没有的值会被赋予undefined || 获得函数实际传递的参数 || 怎么用函数处理一个对象 || 用一个名字空间定义一个模块所有的函数 || 给一个对象添加方法
获得对象的所有属性名 || 将对象o的所有属性名放到数组中 var o = {x:1,y:2,z:3}; var arr = []; var i = 0; for(arr[i++] in o){};/ ...
- C语言学习_C如何在一个文件里调用另一个源文件中的函数
问题 C如何在一个文件里调用另一个源文件中的函数,如题. 解决办法 当程序大了代码多了之后,想模块化开发,不同文件中存一点,是很好的解决办法,那我们如何做才能让各个文件中的代码协同工作呢?我们知道,m ...
- 一个简化的printf函数
<C和指针>第7章第5道编程题: 实现一个简化的printf函数,它能够处理%d.%f.%s 和 %c 格式码,根据ANSI标准的原则,其他格式码的行为是未定义的.你可以假定已经存在函数 ...
- 面试题之java 编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串。 要求不能出现截半的情况
题目:10. 编写一个截取字符串的函数,输入为一个字符串和字节数,输出为按字节截取的字符串. 但是要保证汉字不被截半个,如"我ABC"4,应该截为"我AB",输 ...
- 一个非常有用的函数——COALESCE
原文:一个非常有用的函数--COALESCE 很多人知道ISNULL函数,但是很少人知道Coalesce函数,人们会无意中使用到Coalesce函数,并且发现它比ISNULL更加强大,其实到目前为止, ...
- 一个简单的日志函数C++
有时候程序总是会发生意想不到的情况,为了方便排查错误的情况,还是写日志比较方便.这里自己写了一个简单的函数,能实现基本的功能. BOOL WriteLog(char * DataBuffer) { C ...
随机推荐
- 20180209-sys模块
sys模块常用操作如下: 1.命令行参数 sys.argv 第一个元素是程序本身路径 # 1.命令行参数 第一个元素是程序本身路径 ret = sys.argv print('命令行参数:',ret ...
- shell函数的结束与返回值
- how to pass variable from shell script to sqlplus
script sqlplus ${ORA_USR}/${ORA_PASS}@${ORA_DB} @${PARM}/TEST $new_usr $model_usr $new_pwd parm of s ...
- Go's Declaration Syntax
Introduction Newcomers to Go wonder why the declaration syntax is different from the tradition estab ...
- 用Matlab的.m脚本文件处理实验室数据
找到相应的文件 findfile %1 打开文件夹 %2 拷贝第一个文件 %3 关闭当前文件,再次拷贝新的文件,直到文件末尾结束 clc clear DST_PATH_t = 'C:\Users\Ma ...
- 获取当前的方法名字,运用线程类Thread
得到当前方法的名字String methodName = Thread.currentThread().getStackTrace()[1].getMethodName(); getStackTrac ...
- Unit Testing of Classes in Java
Every class can have a main method. That is a handy trick for unit testing of classes. For example, ...
- yield关键字详解与三种用法
本篇文章比较硬核, 适合有一定Python基础的读者阅读, 如果您对Python还不甚了解可以先关注我哦, 我会持续更新Python技术文章 yield详解 yield与return相同每次调用都会返 ...
- 转:C++ 11 Lambda表达式
转:https://www.cnblogs.com/DswCnblog/p/5629165.html C++11的一大亮点就是引入了Lambda表达式.利用Lambda表达式,可以方便的定义和创建匿名 ...
- .NET Core 构建跨平台的桌面应用
1.运行环境 开发工具:Visual Studio 2017 JDK版本:.NET Core 2.0 项目管理工具:nuget 2.GITHUB地址 https://github.com/nbfujx ...