VC提前注入.net软件的方法
2012-04-18 22:46
232 查看
在之前几节介绍了各种注入方法,但是这些方法存在一些缺陷——对.net程序注入无效。(转载请指明出处)
这个可以理解,.net程序的代码不是汇编,而是微软自定义的IL中间语言。.net CLR如同虚拟机,解析并执行这些中间语言。
于是我们之前所说的修改文件入口点的方法在此是一点都不奏效的,谁知道E8(Call)在IL中是啥!
远线程方法也存在问题。因为我们要提前注入,所以创建进程时使用了CREATE_SUSPENDED以挂起方式启动进程,但是当我们CreateRemoteThread后,会惊人的发现远线程没有执行,更惊人的是傀儡进程(.net程序进程)的主线程复活了。我汇编级调试CreateRemoteThread发现,对于win32程序,远线程创建时挂起,执行了一些操作后,ResumeThread然远线程执行。而对于.net程序,ResumeThread后主线程复活。
那么怎么解决呢?我们可以注入.net CLR。如果全局注入.nt CLR可行,那么结果也不是我们预期的,因为我们只要监控我们关心的进程,其他的进程我们不想关心。因为我是VC程序员,对C#等一窍不通,所以搞这个问题等于是跨界。还好感谢Code Project和Daniel Pistelli,找到.NET
Internals and Code Injection 这篇文章。该文中介绍了一种办法,该方法的大致思路是模拟一个.net CLR,该CLR可以运行.net程序。于是我们可以确定我们要注入的.net程序的“边界”。这点非常重要,其实如果.net程序已经运行起来后,我们使用远线程注入还是成功的。只是我们要做的是提前注入,什么是“前”?多少是“前”?这个“边界”就在此起到非常重要的角色。因为我们模拟.net CLR的程序在准备模拟傀儡.net程序前,.net环境肯定是准备好了的。于是我们只要在模拟之前,让我们的模拟程序自己加载我们准备注入的DLL——变相注入。这是个令人激动的方案。
其实这个方案也是存在缺陷的,因为它是模拟。我用模拟这个词,是因为真正的执行体是它自己而不是傀儡进程。傀儡进程文件只是模拟进程的输入信息。最直接的表现是:我们模拟进程叫A.exe,傀儡进程是B.exe,我们用A.exe运行B.exe,会发现进程列表中只存在A.exe而不存在B.exe。于是可以想到很多问题,比如我们在B.exe中获取当前进程的路径或者当前文件名,当A.exe运行B.exe后,相关逻辑获得是A.exe的路径和文件名。
虽然这是个很棒的东东,可惜其存在的缺陷也是很明显的。所以想提前注入所有进程(win32,.net,java),只在ring3层去做还是很困难的。有些问题还是要切入驱动去做。
工程代码。
(转载请指明出处)
这个可以理解,.net程序的代码不是汇编,而是微软自定义的IL中间语言。.net CLR如同虚拟机,解析并执行这些中间语言。
于是我们之前所说的修改文件入口点的方法在此是一点都不奏效的,谁知道E8(Call)在IL中是啥!
远线程方法也存在问题。因为我们要提前注入,所以创建进程时使用了CREATE_SUSPENDED以挂起方式启动进程,但是当我们CreateRemoteThread后,会惊人的发现远线程没有执行,更惊人的是傀儡进程(.net程序进程)的主线程复活了。我汇编级调试CreateRemoteThread发现,对于win32程序,远线程创建时挂起,执行了一些操作后,ResumeThread然远线程执行。而对于.net程序,ResumeThread后主线程复活。
那么怎么解决呢?我们可以注入.net CLR。如果全局注入.nt CLR可行,那么结果也不是我们预期的,因为我们只要监控我们关心的进程,其他的进程我们不想关心。因为我是VC程序员,对C#等一窍不通,所以搞这个问题等于是跨界。还好感谢Code Project和Daniel Pistelli,找到.NET
Internals and Code Injection 这篇文章。该文中介绍了一种办法,该方法的大致思路是模拟一个.net CLR,该CLR可以运行.net程序。于是我们可以确定我们要注入的.net程序的“边界”。这点非常重要,其实如果.net程序已经运行起来后,我们使用远线程注入还是成功的。只是我们要做的是提前注入,什么是“前”?多少是“前”?这个“边界”就在此起到非常重要的角色。因为我们模拟.net CLR的程序在准备模拟傀儡.net程序前,.net环境肯定是准备好了的。于是我们只要在模拟之前,让我们的模拟程序自己加载我们准备注入的DLL——变相注入。这是个令人激动的方案。
using System; using System.Collections.Generic; using System.Windows.Forms; using System.Runtime.InteropServices; namespace rbloader { static class Program { [DllImport("HookDll.dll")] static extern void ExportFun(); [STAThread] static void Main(string[] args) { ExportFun(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); OpenFileDialog openFileDialog = new OpenFileDialog(); openFileDialog.Filter = "Exe Files (*.exe)|*.exe|Dll Files (*.dll)| *.dll|All Files (*.*)|*.*"; if (openFileDialog.ShowDialog() == DialogResult.OK) { AppDomain ad = AppDomain.CreateDomain("subAppDomain"); ad.ExecuteAssembly(openFileDialog.FileName); } } } }其中HookDll.dll是我前几篇文章中用到注入DLL文件,前篇文章的最后面提供了该文件工程下载地址。ExportFun是HookDll.dll中的导出函数,其拦截了CreateProcessW等函数。
其实这个方案也是存在缺陷的,因为它是模拟。我用模拟这个词,是因为真正的执行体是它自己而不是傀儡进程。傀儡进程文件只是模拟进程的输入信息。最直接的表现是:我们模拟进程叫A.exe,傀儡进程是B.exe,我们用A.exe运行B.exe,会发现进程列表中只存在A.exe而不存在B.exe。于是可以想到很多问题,比如我们在B.exe中获取当前进程的路径或者当前文件名,当A.exe运行B.exe后,相关逻辑获得是A.exe的路径和文件名。
虽然这是个很棒的东东,可惜其存在的缺陷也是很明显的。所以想提前注入所有进程(win32,.net,java),只在ring3层去做还是很困难的。有些问题还是要切入驱动去做。
工程代码。
(转载请指明出处)
相关文章推荐
- VC下提前注入进程的一些方法1——远线程不带参数
- 让你提前认识软件开发(51):VC++集成开发环境中Linux下Pclint工程的配置方法及常见错误修改
- VC下提前注入进程的一些方法2——远线程带参数
- VC下提前注入进程的一些方法1——远线程不带参数
- VC下提前注入进程的一些方法2——远线程带参数
- VC下提前注入进程的一些方法3——修改程序入口点
- VC下提前注入进程的一些方法3——修改程序入口点
- <@乌龟:>VC++2005以上使用.Net的方法
- [VC] - 绕过主动防御的代码注入方法思考
- 深入理解.NET程序的原理 谈一谈破解.NET软件的工具和方法
- 让你提前认识软件开发(18):C语言中常用的文件操作函数总结及使用方法演示代码
- .net读取上传apk文件的包名、软件名称、logo解决方法
- vs2005 vc++ 生成非托管的 不需要.net运行环境的exe程序方法
- VC++软件创业合作方法介绍
- 软件开发方法--.NET基于接口的编程 Interface first programming
- VC巨资注入开源软件产业 商业模式仍需摸索
- 安装软件出现缺少vcruntime140dll的解决方法
- .NET软件防破解方法源码混淆
- 深入理解.NET程序的原理 谈一谈破解.NET软件的工具和方法
- .NET软件防破解方法源码混淆