向其他进程注入代码的三种方法
- 格式:doc
- 大小:244.50 KB
- 文档页数:32
创建远程线程注入代码1. 什么是远程线程注入远程线程注入是一种利用现有进程的执行空间来注入自定义代码的技术。
通过创建一个远程线程,将自定义代码加载到目标进程的地址空间中,并在目标进程中执行,实现对目标进程的控制。
2. 远程线程注入的原理远程线程注入的原理基于Windows操作系统的特性。
在Windows中,每个进程拥有自己独立的地址空间,包括可执行代码、数据和堆栈等。
远程线程注入的关键在于利用目标进程的执行空间,将自定义的代码加载到目标进程中,并通过创建远程线程来执行。
远程线程注入的主要步骤如下:1.打开目标进程:通过调用Windows API函数OpenProcess,以目标进程的进程ID(PID)作为参数,打开目标进程,获取进程句柄。
2.分配内存空间:通过调用Windows API函数VirtualAllocEx,在目标进程的地址空间中分配一块内存空间,用于存储将要注入的代码。
3.将代码写入目标进程:通过调用Windows API函数WriteProcessMemory,将自定义的代码写入到目标进程的内存空间中。
4.创建远程线程:通过调用Windows API函数CreateRemoteThread,在目标进程中创建一个远程线程,将注入的代码作为线程的入口点,从而启动目标进程执行注入的代码。
5.等待远程线程结束:通过调用Windows API函数WaitForSingleObject,等待远程线程执行结束。
6.清理资源:关闭进程句柄,并释放分配的内存空间。
3. 远程线程注入的应用场景远程线程注入在实际应用中有着广泛的应用场景,主要用于以下几个方面:3.1 应用程序扩展通过远程线程注入,可以向目标进程中注入自定义的代码,从而扩展目标进程的功能。
例如,可以向某个游戏进程中注入自定义的代码,实现一些游戏外挂的功能,如自动打怪、自动拾取等。
3.2 动态调试和逆向工程远程线程注入可以用于动态调试和逆向工程。
windows代码注入方法(实用版3篇)《windows代码注入方法》篇1Windows 代码注入是指将一段代码注入到另一个程序的运行过程中,从而实现对该程序的控制和修改。
这种方法通常被用于病毒、木马和恶意软件中,但也可以用于一些合法的用途,例如代码调试和自动化测试。
下面是一些Windows 代码注入的方法:1. 代码注入到进程的内存空间中:这种方法可以将代码注入到正在运行的进程的内存空间中,从而使代码能够执行。
可以使用一些工具,例如DebugBreak、OllyDbg 和IDA Pro 等来实现代码注入。
2. 代码注入到进程的代码段中:这种方法可以将代码注入到进程的代码段中,从而使代码能够执行。
可以使用一些工具,例如Metasploit 和Msfvenom 等来实现代码注入。
3. 代码注入到系统的驱动程序中:这种方法可以将代码注入到系统的驱动程序中,从而使代码能够执行。
可以使用一些工具,例如Driver Studio 和Windows Driver Kit 等来实现代码注入。
4. 代码注入到Windows 注册表中:这种方法可以将代码注入到Windows 注册表中,从而使代码能够执行。
可以使用一些工具,例如Regedit 和PowerShell 等来实现代码注入。
代码注入是一种危险的技术,如果不小心使用,可能会导致系统崩溃或被攻击。
《windows代码注入方法》篇2Windows 代码注入是指将一段代码注入到另一个进程的内存空间中,从而实现对该进程的控制和操作。
这种方法通常被用于木马、病毒等恶意软件中,但也可以用于合法的软件开发和系统工具中。
以下是一些Windows 代码注入的方法:1. 创建远程线程:通过CreateRemoteThread 函数创建一个远程线程,将代码注入到另一个进程的内存空间中,并启动线程执行。
这种方法可以使用CreateProcess 函数启动一个新进程,然后使用CreateRemoteThread 函数将代码注入到该进程中。
winfrom 注入的方法Winform注入是一种将代码注入到Windows Forms应用程序中的技术。
主要有以下几种方法:1. 通过事件注入:通过订阅应用程序的事件,例如应用程序启动事件或按钮点击事件,来向应用程序添加自定义代码。
可以使用以下代码示例来实现:```csharpApplication.Run(new MainForm()); //主窗体```2. 通过控件继承:创建一个自定义控件,继承自现有的Windows Forms控件,并在自定义控件中添加自定义代码。
使用自定义控件替换现有的控件来注入代码。
例如:```csharppublic class CustomButton : Button{protected override void OnClick(EventArgs e){// 添加自定义代码base.OnClick(e);}}```3. 通过Hook技术注入:使用Hook技术截获应用程序的消息,例如键盘消息或鼠标消息,并在回调函数中执行自定义代码。
可以使用第三方库或API来实现。
例如使用WinAPI的SetWindowsHookEx函数来设置钩子。
```csharp[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]public static extern IntPtr SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hMod, uint dwThreadId);private delegate IntPtr HookProc(int nCode, IntPtr wParam, IntPtr lParam);```以上是几种常见的Winform注入方法,具体的方法选择取决于需求和应用程序的结构。
闲着没事整理了一下DLL的N种注入方法,对学习外挂的朋友,应该有用!第一种方法:利用CreateRemoteThread 远程建立线程的方式注入DLL.首先,我们要提升自己的权限,因为远程注入必不可免的要访问到目标进程的内存空间,如果没有足够的系统权限,将无法作任何事.下面是这个函数是用来提升我们想要的权限用的.function EnableDebugPriv : Boolean;varhToken : THANDLE;tp : TTokenPrivileges;rl : Cardinal;beginresult := false;//打开进程令牌环OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, hToken);//获得进程本地唯一IDif LookupPrivilegeValue(nil, 'SeDebugPrivilege',tp.Privileges[0].Luid) thenbegintp.PrivilegeCount := 1;tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;//调整权限result := AdjustTokenPrivileges(hToken, False, tp,sizeof(tp), nil, rl);end;end;关于OpenProcessToken() 和AdjustTokenPrivileges() 两个API的简单介绍:OpenProcessToken():获得进程访问令牌的句柄.function OpenProcessToken(ProcessHandle: THandle; //要修改访问权限的进程句柄DesiredAccess: DWORD; //指定你要进行的操作类型var TokenHandle: THandle): BOOL; //返回的访问令牌指针AdjustTokenPrivileges() :调整进程的权限.function AdjustTokenPrivileges(TokenHandle: THandle; // 访问令牌的句柄DisableAllPrivileges: BOOL; // 决定是进行权限修改还是除能(Disable)所有权限const NewState: TTokenPrivileges; // 指明要修改的权限,是一个指向TOKEN_PRIVILEGES结构的指针,该结构包含一个数组,数据组的每个项指明了权限的类型和要进行的操作;BufferLength: DWORD; //结构PreviousState的长度,如果PreviousState为空,该参数应为0var PreviousState: TTokenPrivileges; // 指向TOKEN_PRIVILEGES结构的指针,存放修改前的访问权限的信息var ReturnLength: DWORD //实际PreviousState结构返回的大小) : BOOL;远程注入DLL其实是通过CreateRemoteThread 建立一个远程线程调用LoadLibrary 函数来加载我们指定的DLL,可是如何能让远程线程知道我要加载DLL呢,要知道在Win32系统下,每个进程都拥有自己的4G虚拟地址空间,各个进程之间都是相互独立的。
linux 进程注入原理进程注入是指将代码注入到另一个进程中,使其在目标进程中执行。
在Linux系统中,进程注入是一种常见的技术,它可以在不影响目标进程的情况下,向其添加新的功能或修改其行为。
本文将介绍Linux进程注入的原理、分类、实现方式以及安全风险,帮助读者更好地理解和应用该技术。
一、进程注入的原理Linux系统中的进程是由内核管理的,每个进程都有自己的地址空间和资源使用情况。
进程注入技术利用了Linux系统的这种特性,通过将代码注入到目标进程的地址空间中,使其在目标进程中执行。
具体来说,进程注入的过程可以分为以下几个步骤:1. 找到目标进程的地址空间首先需要找到目标进程的地址空间,通常可以通过读取系统信息、使用工具探测或者调试器辅助等方法来实现。
2. 将代码加载到目标进程的地址空间中将需要注入的代码加载到目标进程的地址空间中,可以使用系统调用、内存映射或者直接写入等方法来实现。
3. 修改目标进程的执行流程在目标进程中加载代码后,需要修改其执行流程,使其能够执行注入的代码。
这通常需要修改目标进程的代码或数据段,使其能够跳转到注入的代码处执行。
二、进程注入的分类根据注入方式的不同,可以将进程注入分为动态注入和静态注入两种类型。
动态注入是指在目标进程运行时,将代码注入到其地址空间中,使其执行。
而静态注入则是将需要注入的代码与目标进程的二进制文件一起编译或链接,使其成为目标进程的一部分。
三、实现方式1. 使用系统调用系统调用是Linux系统提供的一种接口,用于与内核进行交互。
通过系统调用可以将代码注入到目标进程中,使其执行。
常用的系统调用包括ptrace、mmap、exec等。
其中,ptrace可以用来监视目标进程的运行情况,mmap可以用来将代码加载到目标进程的地址空间中,exec可以用来替换目标进程的执行映像。
2. 使用内存映射内存映射是Linux系统提供的一种将物理内存区域映射到进程地址空间的技术。
进程注入原理
嘿,朋友们!今天咱来聊聊进程注入原理。
这玩意儿啊,就像是一场奇妙的魔术表演!
你想啊,一个程序就像一个小世界,它自己在那运行得好好的。
可突然,就有别的东西神不知鬼不觉地溜进去了,还能在里面捣鼓一番。
这是不是很神奇?
进程注入呢,简单来说,就是让一些代码偷偷摸摸地钻进正在运行的进程里面。
这就好比你正在家里安静地看电视呢,突然有人没打招呼就从窗户爬进来了,还在你家走来走去。
这怎么能行呢?
它的方法有很多呢。
比如说,有直接把代码塞进去的,就像硬塞给别人一个东西一样。
还有通过一些巧妙的手段,让进程自己稀里糊涂地就把外来代码给接纳了。
这就好像用花言巧语哄得别人心甘情愿地让你进去。
那为啥要搞这个进程注入呢?哎呀,这用处可大了去了!有时候是为了给程序加点新功能,就像给汽车加装个新零件似的,让它跑得更快更稳。
但要是被坏人利用了,那可就糟糕啦!他们能偷偷摸摸地搞破坏,窃取信息啥的,这可真是让人头疼啊!
咱就说,这进程注入要是用好了,那是如虎添翼;要是用坏了,那可就是大祸临头啊!就像一把锋利的刀,在厨师手里能做出美味佳肴,在坏人手里那可就是凶器了。
你说这进程注入是不是很有意思?它就像个隐藏在程序世界里的小精灵,一会儿好一会儿坏的。
咱可得把它给搞清楚,不能让它随便捣乱呀!不然咱的电脑、手机啥的不就遭殃了吗?
所以啊,大家一定要多了解了解进程注入原理,知道怎么防范那些坏家伙利用它来搞坏事。
别等到自己的宝贝设备出了问题才后悔莫及呀!这可不是开玩笑的,这关系到咱的信息安全、财产安全呢!大家可都得上点心啊!别不当回事儿!
原创不易,请尊重原创,谢谢!。
32位程序注⼊64位DLL到64位进程向其它进程注⼊DLL通常的做法是通过调⽤CreateRemoteThread这个API在⽬标进程内创建⼀个远程线程。
⽤这个线程来调⽤LoadLibraryA或LoadLibraryW(下⽂统称LoadLibrary)以实现让⽬标进程载⼊指定的DLL⽂件。
使⽤CreateRemoteThread创建⼀个远程线程须要传⼊⼀个线程过程函数的地址,⽽且这个函数地址是须要在⽬标进程中有效的。
因为LoadLibrary是kernel32.dll的导出函数。
所以对于执⾏在同⼀个系统上的同为32位的进程或同为64位的进程能够假定彼此进程内的LoadLibrary函数的地址是同样的。
⽽且CreateRemoteThread的线程过程函数和LoadLibrary的參数个数同样,且參数都是指针。
因此通常都是直接将LoadLibrary作为CreateRemoteThread的过程函数。
然后使⽤VirtualAllocEx在⽬标进程中分配内存,使⽤WriteProcessMemory往这块内存中写⼊DLL⽂件路径。
将这块内存的地址作为线程过程函数(LoadLibrary)的參数。
在64位的Windows操作系统上32位进程中的LoadLibrary函数地址与64位进程的函数地址不同。
因此假设想对64位进程注⼊DLL。
简单的做法就是使⽤64位进程来运⾏注⼊⼯作。
可是假设能让32位进程注⼊64位DLL到64位进程显然更好。
在⼀番Google之后找到了。
这篇⽂章的作者研究出来⼀种在Wow64进程中运⾏x64代码的⽅法,⽽且将其封装成了。
本⽂就是介绍怎样使⽤这个库实现Wow64环境下32位进程向64位进程注⼊DLL。
Wow64环境下32位程序注⼊64位DLL到64位进程32位进程难以注⼊DLL进64位进程是因为两个进程内LoadLibrary的地址不同。
32位进程⽆法知道64位进程的LoadLibrary函数地址。
注入bean的方式和种类在Spring框架中,你可以使用多种方式来注入(注入)Bean,以便在应用程序中使用它们。
以下是一些常见的注入方式和种类:1.构造函数注入:通过构造函数将依赖项(Bean)注入到目标Bean中。
这是一种常用的注入方式,通常用于注入必需的依赖项。
你可以使用`<constructor-arg>`元素进行XML配置,或者使用`@Autowired`或`@Inject`注解进行注解配置。
2.Setter方法注入:通过Setter方法将依赖项注入到目标Bean中。
这种方式灵活,通常用于注入可选的依赖项。
你可以使用`<property>`元素进行XML配置,或者使用`@Autowired`或`@Inject`注解进行注解配置。
3.接口注入:通过接口实现将依赖项注入到目标Bean中。
这是一种高度抽象的注入方式,通常用于实现多态和松散耦合。
4.字段注入:通过字段直接注入依赖项,通常使用`@Autowired`或`@Inject`注解进行注解配置。
这种方式相对于构造函数和Setter方法来说更简洁,但也会降低可测试性。
5.工厂方法注入:通过工厂方法将依赖项注入到Bean中,通常使用`@Bean`注解进行配置。
6.自动装配:Spring提供了自动装配功能,可以根据依赖项的类型和名称自动注入Bean。
有三种自动装配模式:根据类型(byType)、根据名称(byName)、自动装配构造函数参数(constructor)。
7.SpEL(Spring表达式语言)注入:使用SpEL表达式来定义Bean之间的关系和依赖。
这使得注入可以更加灵活和动态化。
8.Java配置类注入:通过Java配置类来定义Bean之间的关系,使用`@Configuration`和`@Bean`注解进行配置。
这些注入方式和种类可以根据项目需求和设计选择使用。
通常,构造函数注入和Setter 方法注入是最常见的方式,而自动装配可以简化配置。
常见的⼗种代码注⼊技术Process injection is a widespread defense evasion technique employed often within malware and fileless adversary tradecraft, and entails running custom code within the address space of another process. Process injection improves stealth, and some techniques also achieve persistence. Although there are numerous process injection techniques, in this blog I present ten techniques seen in the wild that run malware code on behalf of another process. I additionally provide screenshots for many of these techniques to facilitate reverse engineering and malware analysis, assisting detection and defense against these common techniques.进程注⼊是⼀种⼴泛使⽤的躲避检测的技术,通常⽤于恶意软件或者⽆⽂件技术。
其需要在另⼀个进程的地址空间内运⾏特制代码,进程注⼊改善了不可见性,同时⼀些技术也实现了持久性。
尽管⽬前有许多进程注⼊技术,但在这篇⽂章中,我将会介绍⼗种在野发现的,在另⼀个程序的地址空间执⾏恶意代码的进程注⼊技术,并提供这些技术应⽤的截图,以便于逆向⼯程和恶意软件分析,然后协助检测并防御这些进程注⼊技术。
向其他进程注入代码的三种方法向其他进程注入代码的三种方法本文章翻译自Robet Kuster的Three Ways to Inject Your Code into Another Process 一文,原版地址见下面。
本文章版权归原作者所有。
原版地址:/threa ... 152&msg=1025152下载整个压缩包下载WinSpy作者:Robert Kuster翻译:袁晓辉( hyzs@)摘要:如何向其他线程的地址空间中注入代码并在这个线程的上下文中执行之。
目录:●导言●Windows 钩子(Hooks)●CreateRemoteThread 和LoadLibrary 技术○进程间通讯●CreateRemoteThread 和WriteProcessmemory 技术○如何使用该技术子类(SubClass)其他进程中的控件○什么情况下适合使用该技术●写在最后的话●附录●参考●文章历史导言:我们在Code project()上可以找到许多密码间谍程序(译者注:那些可以看到别的程序中密码框内容的软件),他们都依赖于Windows钩子技术。
要实现这个还有其他的方法吗?有!但是,首先,让我们简单回顾一下我们要实现的目标,以便你能弄清楚我在说什么。
要读取一个控件的内容,不管它是否属于你自己的程序,一般来说需要发送WM_GETTEXT 消息到那个控件。
这对edit控件也有效,但是有一种情况例外。
如果这个edit控件属于其他进程并且具有ES_PASSWORD 风格的话,这种方法就不会成功。
只有“拥有(OWNS)”这个密码控件的进程才可以用WM_GETTEXT 取得它的内容。
所以,我们的问题就是:如何让下面这句代码在其他进程的地址空间中运行起来:::SendMessage( hPwdEdit, WM_GETTEXT, nMaxChars, psBuffer );一般来说,这个问题有三种可能的解决方案:1. 把你的代码放到一个DLL中;然后用windows 钩子把它映射到远程进程。
2. 把你的代码放到一个DLL中;然后用CreateRemoteThread 和LoadLibrary 把它映射到远程进程。
3. 不用DLL,直接复制你的代码到远程进程(使用WriteProcessMemory)并且用CreateRemoteThread执行之。
在这里有详细的说明:Ⅰ. Windows 钩子示例程序:HookSpy 和HookInjExWindows钩子的主要作用就是监视某个线程的消息流动。
一般可分为:1.局部钩子,只监视你自己进程中某个线程的消息流动。
2.远程钩子,又可以分为:a.特定线程的,监视别的进程中某个线程的消息;b.系统级的,监视整个系统中正在运行的所有线程的消息。
如果被挂钩(监视)的线程属于别的进程(情况2a和2b),你的钩子过程(hook procedure)必须放在一个动态连接库(DLL)中。
系统把这包含了钩子过程的DLL映射到被挂钩的线程的地址空间。
Windows会映射整个DLL而不仅仅是你的钩子过程。
这就是为什么windows钩子可以用来向其他线程的地址空间注入代码的原因了。
在这里我不想深入讨论钩子的问题(请看MSDN中对SetWindowsHookEx的说明),让我再告诉你两个文档中找不到的诀窍,可能会有用:1.当SetWindowHookEx调用成功后,系统会自动映射这个DLL到被挂钩的线程,但并不是立即映射。
因为所有的Windows钩子都是基于消息的,直到一个适当的事件发生后这个DLL才被映射。
比如:如果你安装了一个监视所有未排队的(nonqueued)的消息的钩子(WH_CALLWNDPROC),只有一个消息发送到被挂钩线程(的某个窗口)后这个DLL才被映射。
也就是说,如果在消息发送到被挂钩线程之前调用了UnhookWindowsHookEx那么这个DLL就永远不会被映射到该线程(虽然SetWindowsHookEx调用成功了)。
为了强制映射,可以在调用SetWindowsHookEx后立即发送一个适当的消息到那个线程。
同理,调用UnhookWindowsHookEx之后,只有特定的事件发生后DLL才真正地从被挂钩线程卸载。
2.当你安装了钩子后,系统的性能会受到影响(特别是系统级的钩子)。
然而如果你只是使用的特定线程的钩子来映射DLL而且不截获如何消息的话,这个缺陷也可以轻易地避免。
看一下下面的代码片段:BOOL APIENTRY DllMain( HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved ){if( ul_reason_for_call == DLL_PROCESS_ATTACH ){//用LoadLibrary增加引用次数char lib_name[MAX_PATH];::GetModuleFileName( hModule, lib_name, MAX_PATH );::LoadLibrary( lib_name );// 安全卸载钩子::UnhookWindowsHookEx( g_hHook );}return TRUE;}我们来看一下。
首先,我们用钩子映射这个DLL到远程线程,然后,在DLL被真正映射进去后,我们立即卸载挂钩(unhook)。
一般来说当第一个消息到达被挂钩线程后,这DLL会被卸载,然而我们通过LoadLibrary来增加这个DLL的引用次数,避免了DLL被卸载。
剩下的问题是:使用完毕后如何卸载这个DLL?UnhookWindowsHookEx不行了,因为我们已经对那个线程取消挂钩(unhook)了。
你可以这么做:○在你想要卸载这个DLL之前再安装一个钩子;○发送一个“特殊”的消息到远程线程;○在你的新钩子的钩子过程(hook procedure)中截获该消息,调用FreeLibrary 和(译者注:对新钩子调用)UnhookwindowsHookEx。
现在,钩子只在映射DLL到远程进程和从远程进程卸载DLL时使用,对被挂钩线程的性能没有影响。
也就是说,我们找到了一种(相比第二部分讨论的LoadLibrary技术)WinNT 和Win9x下都可以使用的,不影响目的进程性能的DLL映射机制。
但是,我们应该在何种情况下使用该技巧呢?通常是在DLL需要在远程进程中驻留较长时间(比如你要子类[subclass]另一个进程中的控件)并且你不想过于干涉目的进程时比较适合使用这种技巧。
我在HookSpy中并没有使用它,因为那个DLL只是短暂地注入一段时间――只要能取得密码就足够了。
我在另一个例子HookInjEx中演示了这种方法。
HookInjEx把一个DLL映射进“explorer.exe”(当然,最后又从其中卸载),子类了其中的开始按钮,更确切地说我是把开始按钮的鼠标左右键点击事件颠倒了一下。
你可以在本文章的开头部分找到HookSpy和HookInjEx及其源代码的下载包链接。
Ⅱ. CreateRemoteThread 和LoadLibrary 技术示例程序:LibSpy通常,任何进程都可以通过LoadLibrary动态地加载DLL,但是我们如何强制一个外部进程调用该函数呢?答案是CreateRemoteThread。
让我们先来看看LoadLibrary和FreeLibrary的函数声明:HINSTANCE LoadLibrary(LPCTSTR lpLibFileName // address of filename of library module);BOOL FreeLibrary(HMODULE hLibModule // handle to loaded library module);再和CreateRemoteThread的线程过程(thread procedure)ThreadProc比较一下:DWORD WINAPI ThreadProc(LPVOID lpParameter // thread data);你会发现所有的函数都有同样的调用约定(calling convention)、都接受一个32位的参数并且返回值类型的大小也一样。
也就是说,我们可以把LoadLibrary/FreeLibrary的指针作为参数传递给CrateRemoteThread。
然而,还有两个问题(参考下面对CreateRemoteThread的说明)1.传递给ThreadProc的lpStartAddress 参数必须为远程进程中的线程过程的起始地址。
2.如果把ThreadProc的lpParameter参数当做一个普通的32位整数(FreeLibrary 把它当做HMODULE)那么没有如何问题,但是如果把它当做一个指针(LoadLibrary把它当做一个char*),它就必须指向远程进程中的内存数据。
第一个问题其实已经迎刃而解了,因为LoadLibrary和FreeLibrary都是存在于kernel32.dll中的函数,而kernel32可以保证任何“正常”进程中都存在,且其加载地址都是一样的。
(参看附录A)于是LoadLibrary/FreeLibrary在任何进程中的地址都是一样的,这就保证了传递给远程进程的指针是个有效的指针。
第二个问题也很简单:把DLL的文件名(LodLibrary的参数)用WriteProcessMemory复制到远程进程。
所以,使用CreateRemoteThread和LoadLibrary技术的步骤如下:1.得到远程进程的HANDLE(使用OpenProcess)。
2.在远程进程中为DLL文件名分配内存(VirtualAllocEx)。
3.把DLL的文件名(全路径)写到分配的内存中(WriteProcessMemory)4.使用CreateRemoteThread和LoadLibrary把你的DLL映射近远程进程。
5.等待远程线程结束(WaitForSingleObject),即等待LoadLibrary返回。
也就是说当我们的DllMain(是以DLL_PROCESS_ATTACH为参数调用的)返回时远程线程也就立即结束了。
6.取回远程线程的结束码(GetExitCodeThtread),即LoadLibrary的返回值――我们DLL加载后的基地址(HMODULE)。
7.释放第2步分配的内存(VirtualFreeEx)。
8.用CreateRemoteThread和FreeLibrary把DLL从远程进程中卸载。
调用时传递第6步取得的HMODULE给FreeLibrary(通过CreateRemoteThread的lpParameter 参数)。