学习笔记之卸载远程目标进程中的DLL模块

(2007-07-23 23:51:02)

转载

学习笔记之卸载远程目标进程中的DLL模块2007/7/23
1.首先得把DLL模块中的线程结束
使用CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD,0);创建系统线程的快照然后用Thread32First()和
Thread32Next()遍历系统中所有线程.将遍历到的线程保存到THREADENTRY32结构,然后判断结构中的th32OwnerProcessID成员是否与目标进程ID是否相等从而判断该线程是否为目标进程的.然后用函数OpenThread()打开该线程.但是OpenThread函数在VC6中未被定义.该函数存在于kernel32.dll中.在使用时需要自己定义:第三个参数指定要打开的线程的ID(从THREADENTRY32结构获取)
typedef HANDLE (WINAPI*OPENTHREAD)(DWORD dwFlag, BOOL bInheritHandle, DWORD dwThreadId);
然后用GetProcAddress函数从kernel32.dll中获取OpenThread函数的地址后就可以使用该函数了
OPENTHREAD OpenThread=(OPENTHREAD)GetProcAddress(GetModuleHandle("Kernel32"), "OpenThread");
用OpenThread函数打开线程获取线程句柄
HANDLE hThread=OpenThread(THREAD_ALL_ACCESS,FALSE,Thread.th32ThreadID);
有了线程的句柄后就可以调用NtQueryInformationThread函数获取线程的入口地址
函数NtQueryInformationThread在VC6中也未被定义需要自己定义然后再使用
NtQueryInformationThread函数的第一个参数即为线程句柄,第二个参数为一个枚举值而该枚举类型在VC6中未被定义,同样需要自己定义
NtQueryInformationThread函数的定义
typedef DWORD (CALLBACK* NTQUERYINFORMATIONTHREAD)(HANDLE,DWORD,PVOID,DWORD,PDWORD);
获取NtQueryInformationThread函数的地址:NtQueryInformationThread函数存在于ntdll.dll中,ntdll.dll与kernel32.dll一样,在每个进程开始时,系统都为他们做了一会拷贝所以可以直接用
GetProcAddress函数获取其地址
NTQUERYINFORMATIONTHREAD NtQueryInformationThread=(NTQUERYINFORMATIONTHREAD)GetProcAddress(GetModuleHandle("ntdll.dll"),"NtQueryInformationThread");
定义NtQueryInformationThread要用到的枚举类型:
typedef enum _THREAD_INFORMATION_CLASS
{
    ThreadBasicInformation,
    ThreadTimes,
    ThreadPriority,
    ThreadBasePriority,
    ThreadAffinityMask,
    ThreadImpersonationToken,
    ThreadDescriptorTableEntry,
    ThreadEnableAlignmentFaultFixup,
    ThreadEventPair,
    ThreadQuerySetWin32StartAddress,
    ThreadZeroTlsCell,
    ThreadPerformanceCount,
    ThreadAmILastThread,
    ThreadIdealProcessor,
    ThreadPriorityBoost,
    ThreadSetTlsArrayAddress,
    ThreadIsIoPending,
    ThreadHideFromDebugger
}THREAD_INFORMATION_CLASS,*PTHREAD_INFORMATION_CLASS;
在此处NtQueryInformationThread函数将用到此枚举类型的第9个值ThreadQuerySetWin32StartAddress
可以不定义此枚举类型,直接将NtQueryInformationThread函数的第二个参数设为数值9也可以
关于NtQueryInformationThread函数的详细信息了解不多
此处的用法为:
NtQueryInformationThread(hThread,ThreadQuerySetWin32StartAddress,&Start,0x4,NULL);
第一个参数为线程句柄,由OpenThread函数获取,第二个参数为枚举值不多说了
第三个参数为一个DWORD变量的指针,此变量就是用来接收线程入口地址的.第四个参数只能为0x4暂时还不知道是什么意思.第五个参数也是一个DWORD变量指针,但在此处可以设为NULL

判断该线程的入口地址是否在某DLL模块中的方法为:
用NtQueryInformationThread函数获取的线程入口地址 - 该DLL模块句柄(需要先转换为DWORD值)
再用得到的差值与该DLL模块文件的大小相比较如果该差值正好小于或等于DLL模块文件的大小
说明该线程入口地址在该DLL模块之中.
这里所需要模块句柄,对于它的获取稍后再讲.

最后就可以调用TerminateThread(hThread,0);函数结束该线程

用上述方法结束该DLL模块中的所有线程后就可以对该DLL模块进行卸载操作了
2.要卸载DLL模块首先需要获取该DLL模块的句柄
可以通过GetModuleHandle函数获取
也可以通过创建快照CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,processID);的然后用
Module32First和Module32Next遍历模块的方法获取
先说说用GetModuleHandle函数获取.此方法需要用CreateRemoteThread函数在远程进程中创建线程,让该线程调用Kernel32.dll中的GetModuleHandle函数.但是只这样还不行.因为GetModuleHandle函数需要以DLL模块文件名做参数.既然是远程线程调用GetModuleHandle函数.还需要先把DLL模块文件名写入目标进程的地址空间中.最后用CreateRemoteThread函数创建线程执行GetModuleHandle函数来获取DLL句柄
由于是用CreateRemoteThread函数远程执行GetModuleHandle函数.所以无法直接从GetModuleHandle函数得到返回值(也就是DLL句柄).在此必在WaitForSingleObject函数之后用GetExitCodeThread函数来获取线程的退出代码.如果线程正确返回.该退出代码就是线程函数(GetModuleHandle)的返回值然后再用同样的方法用CreateRemoteThread远程创建线程调用FreeLibrary函数来卸载该DLL
(注:此方法本人还没试验成功,理论上是可行的)
现在再来看第二种方法,通过CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,processID)创建进程模块的快照,然后用Module32First和Module32Next遍历进程中所有模块.Module32First和Module32Next函数会将遍历结果保存到MODULEENTRY32结构中.通过查询该结构中的szExePath或szModule成员来判断是否为我们要卸载的目标模块.其中szExePath保存了模块文件的包括全路径的文件名而szModule只包括模块文件名不含路径
3.两个关键的问题解决了,剩下的就是如何卸载DLL模块的问题
要卸载DLL模块需要用到FreeLibrary函数.由于是卸载远程进程中的模块必须让远程进程来执行该函数.
所以将再次用到CreateRemoteThread函数来创建远程线程
以下是实现方法:
首先从Kernel32.dll模块中获取FreeLibrary函数的地址
LPVOID pFunc=(LPTHREAD_START_ROUTINE)GetProcAddress(Pkernel32,"FreeLibrary");//其中Pkernel32是Kernel32.dll的句柄
最后再调用
HANDLE hThread = CreateRemoteThread( process, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc,                (LPVOID)Module->hModule, 0, &dwID/*用来接收新线程的ID*/ );
其中第五个参数就是我们上一步骤中获取的模块句柄
说明一下.由于一个进程可以多次调用LoadLibrary函数来装载一个DLL模块(调用一次LoadLibrary函数系统就会对该DLL模块增加一个引用计数并不是说该进程中会有多个相同的DLL模块)为了防止这种情况.最好用一个循环来进行卸载操作.同样通过用GetExitCodeThread的方法获取FreeLibrary函数的执行情况
直到返回结果为False为止.这样才表示完成了对该模块的卸载

4.另外附上一点关于CreateToolhelp32Snapshot函数的资料
CreateToolhelp32Snapshot函数为指定的进程、进程使用的堆[HEAP]、模块[MODULE]、线程[THREAD])建立一个快照[snapshot]。

原型:
HANDLE WINAPI CreateToolhelp32Snapshot(DWORD dwFlags,DWORD th32ProcessID);

参数:
dwFlags
[输入]指定快照中包含的系统内容,这个参数能够使用下列数值(变量)中的一个。

TH32CS_INHERIT - 声明快照句柄是可继承的。
     TH32CS_SNAPALL - 在快照中包含系统中所有的进程和线程。
     TH32CS_SNAPHEAPLIST - 在快照中包含在th32ProcessID中指定的进程的所有的堆。
     TH32CS_SNAPMODULE - 在快照中包含在th32ProcessID中指定的进程的所有的模块。
     TH32CS_SNAPPROCESS - 在快照中包含系统中所有的进程。
     TH32CS_SNAPTHREAD - 在快照中包含系统中所有的线程。

th32ProcessID
[输入]指定将要快照的进程ID。如果该参数为0表示快照当前进程。该参数只有在设置了TH32CS_SNAPHEAPLIST或TH32CS_SNAPMOUDLE后才有效,在其他情况下该参数被忽略,所有的进程都会被快照。

返回值:
调用成功,返回快照的句柄,调用失败,返回INVAID_HANDLE_VALUE。

5.新问题
在该次学习中所发现的新问题.某些程序在开始时总是要载入很多相关的DLL模块
比如QQGame.exe启动时就载入了多达109个模块.有些是常见的如Ntdll.dll kernel32.dll Gdi32.dll ole32.dll等等.也有一些QQGame.exe自己的DLL模块这些模块完成QQGAME.EXE的一些特殊功能.但是QQGAME.EXE启动后并没有马上就调用某些模块中的东西.比如QQGAME.EXE中的一个HelpDll.dll模块.我们就可以例用这样的模块来启动我们的病毒.我们可将该DLL模块文件拷贝到一隐蔽的目录下.然后自己从新写一个新的DLL模块.该模块应具备的功能.1首先要能载入我们拷贝的真正的DLL模块.2载入或者启动我们的病毒程序.3完成这两样工作后马上进行自我卸载. 最后将写好的DLL文件放到先前HelpDll.dll的目录下复盖真正的DLL文件.这样我们的病毒就会随QQGame.exe的启动而启动了
上面的例子本人测试成功.不知道其它的进程或模块会不会支持这样的方式

来源: <http://blog.sina.com.cn/s/blog_56ea069101000b3k.html>

来自为知笔记(Wiz)

转载于:https://www.cnblogs.com/hungryvampire/p/4469918.html

学习笔记之卸载远程目标进程中的DLL模块(转)相关推荐

  1. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 获取 远程 目标进程 中的 /system/lib/libc.so 动态库中的 mmap 函数地址 )

    文章目录 一.获取 远程 目标进程 中的 /system/lib/libc.so 动态库中的 mmap 函数地址 二.从 /proc/pid/maps 文件中获取 指定 进程 中的 /system/l ...

  2. 再谈隐藏进程中的DLL模块/黑月教主

    http://hi.baidu.com/_achillis/blog/item/59bf732623fbe509918f9d87.html 相当老的话题,大约一年前就写过这个东西了,不过那时候知识比较 ...

  3. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 二 | 准备参数 | 远程调用 mmap 函数 )

    文章目录 一.准备 mmap 函数的参数 二.mmap 函数远程调用 一.准备 mmap 函数的参数 上一篇博客 [Android 逆向]Android 进程注入工具开发 ( 注入代码分析 | 远程调 ...

  4. 【Android 逆向】Android 进程注入工具开发 ( 注入代码分析 | 远程调用 目标进程中 libc.so 动态库中的 mmap 函数 三 | 等待远程函数执行完毕 | 寄存器获取返回值 )

    文章目录 前言 一.等待远程进程 mmap 函数执行完毕 二.从寄存器中获取进程返回值 三.博客资源 前言 前置博客 : [Android 逆向]Android 进程注入工具开发 ( 注入代码分析 | ...

  5. C++学习笔记目录链接(持续更新中)

    学习目标: C++学习笔记目录链接(持续更新中,未完待续) 学习内容: 序号 链接 0 C++ 常见bug记录(持续记录中) 1 C++学习笔记1[数据类型] 2 C++学习笔记2[表达式与语句] 3 ...

  6. 深度学习笔记(32) 目标定位

    深度学习笔记(32) 目标定位 1. 定位分类 2. 定位边框 3. 分类标签 4. 损失函数 1. 定位分类 图片分类任务已经熟悉了,就是算法遍历图片,判断其中的对象是不是汽车 定位分类问题,这意味 ...

  7. Unity Cinemachine插件学习笔记,实现单目标和多目标之间切换

    Unity Cinemachine插件学习笔记,实现单目标和多目标之间切换 *版本要求Unity2017.1及以上. 参考资料: [官方] Unity 2017.1正式版发布 Cinemachine插 ...

  8. OpenCV学习笔记(六):非线性滤波-中值、双边:medianBlur(),bilateralFilter()

    OpenCV学习笔记(六):非线性滤波-中值.双边:medianBlur(),bilateralFilter() 1.中值滤波(Median filter) 是一种典型的非线性滤波技术,基本思想是用像 ...

  9. WPF学习笔记(7):DataGrid中数字自定义格式显示

    WPF学习笔记(7):DataGrid中数字自定义格式显示 原文:WPF学习笔记(7):DataGrid中数字自定义格式显示 DataGrid中数据显示如下图,数据格式比较杂乱.希望达到以下要求:(1 ...

最新文章

  1. 如何解决win8系统下卸载软件出现错误代码为2502和2503的问题
  2. android 动态矩形条,android – 从相机中动态检测不同形状(圆形,方形和矩形)?
  3. aws lambda_如何通过在本地模拟AWS Lambda来加速无服务器开发
  4. 前端学习(1904)vue之电商管理系统电商系统之修改用户的操作
  5. (09)Verilog HDL异步复位
  6. mybatis 多参数处理
  7. JMeter察看结果树的显示模式详解
  8. vue3中setup()函数的使用二
  9. Win64下通过JNI(C++)创建jvm
  10. 豆瓣电影、纪录片、书籍......下载神器
  11. 支付宝支付提示 4006 ISV权限不足
  12. iOS 日记app的制作过程(Objective-C)
  13. Java中的23种设计模式
  14. SQLI DUMB SERIES-10
  15. Fiddler配置自动响应
  16. MIPI介绍(CSI DSI接口)
  17. group 与 groups的区别
  18. 树莓派 4G无线上网卡托+电信/移动4G SIM卡
  19. CII-关键信息基础设施风险评估必要性
  20. opencv支持H264视频编码

热门文章

  1. 获取后端接口请求中的参数(@PathVariable,@RequestParam,@RequestBody区别,使用postman请求
  2. 硬件:台式机老式键盘知识科普
  3. 面试:TCP协议面试10连问,总会用得到,值得收藏!
  4. 硬件编程:77条STM32知识汇总
  5. 进程与线程的区别:最浅显易懂的解释
  6. Redis为何这么快?
  7. DoNet 高效开发必备开发工具
  8. 相对不容易用计算机语言编程实现的是,在描述算法的方法中,相对不容易用计算机语言编程实现的是(    )....
  9. MYSQL读书笔记---运算符、字符串操作
  10. Java线程之多线程与多进程(3)——Java中的多线程