ImageVerifierCode 换一换
格式:DOCX , 页数:23 ,大小:62.57KB ,
资源ID:19546164      下载积分:12 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/19546164.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(代码注入的三种方法Word文件下载.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

代码注入的三种方法Word文件下载.docx

1、图一WinSpy 密码侦测程序为了找到解决问题的方法。首先让我们简单回顾一下问题背景。要“读取”某个控件的内容无论这个控件是否属于当前的应用程序通常都是发送 WM_GETTEXT 消息来实现。这个技术也同样应用到编辑控件,但是如果该编辑控件属于另外一个进程并设置了 ES_PASSWORD 式样,那么上面讲的方法就行不通了。用 WM_GETTEXT 来获取控件的内容只适用于进程“拥有”密码控件的情况。所以我们的问题变成了如何在另外一个进程的地址空间执行::SendMessage( hPwdEdit, WM_GETTEXT, nMaxChars, psBuffer );通常有三种可能性来解决这个问

2、题。1. 将你的代码放入某个 DLL,然后通过 Windows 钩子映射该DLL到远程进程; 2. 将你的代码放入某个 DLL,然后通过 CreateRemoteThread 和 LoadLibrary 技术映射该DLL到远程进程;3. 如果不写单独的 DLL,可以直接将你的代码拷贝到远程进程通过 WriteProcessMemory并用 CreateRemoteThread 启动它的执行。本文将在第三部分详细描述该技术实现细节;第一部分: Windows 钩子范例程序参见HookSpy 和HookInjExWindows 钩子主要作用是监控某些线程的消息流。通常我们将钩子分为本地钩子和远程钩

3、子以及系统级钩子,本地钩子一般监控属于本进程的线程的消息流,远程钩子是线程专用的,用于监控属于另外进程的线程消息流。系统级钩子监控运行在当前系统中的所有线程的消息流。如果钩子作用的线程属于另外的进程,那么你的钩子过程必须驻留在某个动态链接库(DLL)中。然后系统映射包含钩子过程的DLL到钩子作用的线程的地址空间。Windows将映射整个 DLL,而不仅仅是钩子过程。这就是为什么 Windows 钩子能被用于将代码注入到别的进程地址空间的原因。本文我不打算涉及钩子的具体细节(关于钩子的细节请参见 MSDN 库中的 SetWindowHookEx API),但我在此要给出两个很有用心得,在相关文档

4、中你是找不到这些内容的:1. 在成功调用 SetWindowsHookEx 后,系统自动映射 DLL 到钩子作用的线程地址空间,但不必立即发生映射,因为 Windows 钩子都是消息,DLL 在消息事件发生前并没有产生实际的映射。例如:如果你安装一个钩子监控某些线程(WH_CALLWNDPROC)的非队列消息,在消息被实际发送到(某些窗口的)钩子作用的线程之前,该DLL 是不会被映射到远程进程的。换句话说,如果 UnhookWindowsHookEx 在某个消息被发送到钩子作用的线程之前被调用,DLL 根本不会被映射到远程进程(即使 SetWindowsHookEx 本身调用成功)。为了强制进

5、行映射,在调用 SetWindowsHookEx 之后马上发送一个事件到相关的线程。在UnhookWindowsHookEx了之后,对于没有映射的DLL处理方法也一样。只有在足够的事件发生后,DLL才会有真正的映射。2. 当你安装钩子后,它们可能影响整个系统得性能(尤其是系统级钩子),但是你可以很容易解决这个问题,如果你使用线程专用钩子的DLL映射机制,并不截获消息。考虑使用如下代码:3. BOOL APIENTRY DllMain( HANDLE hModule,4. DWORD ul_reason_for_call,5. LPVOID lpReserved )6. 7. if( ul_re

6、ason_for_call = DLL_PROCESS_ATTACH )8. 9. / Increase reference count via LoadLibrary10. char lib_nameMAX_PATH;11. :GetModuleFileName( hModule, lib_name, MAX_PATH );12. :LoadLibrary( lib_name );13. 14. / Safely remove hook15. :UnhookWindowsHookEx( g_hHook );16. 17. return TRUE; 那么会发生什么呢?首先我们通过Windows

7、 钩子将DLL映射到远程进程。然后,在DLL被实际映射之后,我们解开钩子。通常当第一个消息到达钩子作用线程时,DLL此时也不会被映射。这里的处理技巧是调用LoadLibrary通过增加 DLLs的引用计数来防止映射不成功。现在剩下的问题是如何卸载DLL,UnhookWindowsHookEx 是不会做这个事情的,因为钩子已经不作用于线程了。你可以像下面这样做:o 就在你想要解除DLL映射前,安装另一个钩子;o 发送一个“特殊”消息到远程线程;o 在钩子过程中截获这个消息,响应该消息时调用 FreeLibrary 和 UnhookWindowsHookEx;目前只使用了钩子来从处理远程进程中DL

8、L的映射和解除映射。在此“作用于线程的”钩子对性能没有影响。下面我们将讨论另外一种方法,这个方法与 LoadLibrary 技术的不同之处是DLL的映射机制不会干预目标进程。相对LoadLibrary 技术,这部分描述的方法适用于 WinNT和Win9x。但是,什么时候使用这个技巧呢?答案是当DLL必须在远程进程中驻留较长时间(即如果你子类化某个属于另外一个进程的控件时)以及你想尽可能少的干涉目标进程时。我在 HookSpy 中没有使用它,因为注入DLL 的时间并不长注入时间只要足够得到密码即可。我提供了另外一个例子程序HookInjEx来示范。HookInjEx 将DLL映射到资源管理器“e

9、xplorer.exe”,并从中/解除影射,它子类化“开始”按钮,并交换鼠标左右键单击“开始”按钮的功能。HookSpy 和 HookInjEx 的源代码都可以从本文的下载源代码中获得。第二部分:CreateRemoteThread 和 LoadLibrary 技术 范例程序LibSpy 通常,任何进程都可以通过 LoadLibrary API 动态加载DLL。但是,如何强制一个外部进程调用这个函数呢?答案是:CreateRemoteThread。首先,让我们看一下 LoadLibrary 和FreeLibrary API 的声明:HINSTANCE LoadLibrary(LPCTSTR l

10、pLibFileName / 库模块文件名的地址);BOOL FreeLibrary(HMODULE hLibModule / 要加载的库模块的句柄现在将它们与传递到 CreateRemoteThread 的线程例程ThreadProc 的声明进行比较。DWORD WINAPI ThreadProc(LPVOID lpParameter / 线程数据你可以看到,所有函数都使用相同的调用规范并都接受 32位参数,返回值的大小都相同。也就是说,我们可以传递一个指针到LoadLibrary/FreeLibrary 作为到 CreateRemoteThread 的线程例程。但这里有两个问题,请看下面对

11、CreateRemoteThread 的描述:1. CreateRemoteThread 的 lpStartAddress 参数必须表示远程进程中线程例程的开始地址。2. 如果传递到 ThreadFunc 的参数lpParameter被解释为常规的 32位值(FreeLibrary将它解释为一个 HMODULE),一切OK。但是,如果 lpParameter 被解释为一个指针(LoadLibraryA将它解释为一个串指针)。它必须指向远程进程的某些数据。第一个问题实际上是由它自己解决的。LoadLibrary 和 FreeLibray 两个函数都在 kernel32.dll 中。因为必须保证k

12、ernel32存在并且在每个“常规”进程中的加载地址要相同,LoadLibrary/FreeLibray 的地址在每个进程中的地址要相同,这就保证了有效的指针被传递到远程进程。第二个问题也很容易解决。只要通过 WriteProcessMemory 将 DLL 模块名(LoadLibrary需要的DLL模块名)拷贝到远程进程即可。所以,为了使用CreateRemoteThread 和 LoadLibrary 技术,需要按照下列步骤来做:1. 获取远程进程(OpenProcess)的 HANDLE;2. 为远程进程中的 DLL名分配内存(VirtualAllocEx);3. 将 DLL 名,包含全

13、路径名,写入分配的内存(WriteProcessMemory);4. 用 CreateRemoteThread 和 LoadLibrary. 将你的DLL映射到远程进程;5. 等待直到线程终止(WaitForSingleObject),也就是说直到 LoadLibrary 调用返回。另一种方法是,一旦 DllMain(用DLL_PROCESS_ATTACH调用)返回,线程就会终止;6. 获取远程线程的退出代码(GetExitCodeThread)。注意这是一个 LoadLibrary 返回的值,因此是所映射 DLL 的基地址(HMODULE)。在第二步中释放分配的地址(VirtualFreeE

14、x);7. 用 CreateRemoteThread 和 FreeLibrary从远程进程中卸载 DLL。传递在第六步获取的 HMODULE 句柄到 FreeLibrary(通过 CreateRemoteThread 的lpParameter参数);8. 注意:如果你注入的 DLL 产生任何新的线程,一定要在卸载DLL 之前将它们都终止掉;9. 等待直到线程终止(WaitForSingleObject);此外,处理完成后不要忘了关闭所有句柄,包括在第四步和第八步创建的两个线程以及在第一步获取的远程线程句柄。现在让我们看一下 LibSpy 的部分代码,为了简单起见,上述步骤的实现细节中的错误处理

15、以及 UNICODE 支持部分被略掉。HANDLE hThread;char szLibPath_MAX_PATH; / “LibSpy.dll”模块的名称 (包括全路径);void* pLibRemote; / 远程进程中的地址,szLibPath 将被拷贝到此处;DWORD hLibModule; / 要加载的模块的基地址(HMODULE)HMODULE hKernel32 = :GetModuleHandle(Kernel32/ 初始化szLibPath/./ 1. 在远程进程中为szLibPath 分配内存/ 2. 将szLibPath 写入分配的内存pLibRemote = :Vir

16、tualAllocEx( hProcess, NULL, sizeof(szLibPath), MEM_COMMIT, PAGE_READWRITE );WriteProcessMemory( hProcess, pLibRemote, (void*)szLibPath, sizeof(szLibPath), NULL );/ 将LibSpy.dll 加载到远程进程(使用CreateRemoteThread 和 LoadLibrary)hThread = :CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE) :GetP

17、rocAddress( hKernel32, LoadLibraryA ), pLibRemote, 0, NULL );WaitForSingleObject( hThread, INFINITE );/ 获取所加载的模块的句柄GetExitCodeThread( hThread, &hLibModule );/ 清除CloseHandle( hThread );VirtualFreeEx( hProcess, pLibRemote, sizeof(szLibPath), MEM_RELEASE ); 假设我们实际想要注入的代码SendMessage 被放在DllMain (DLL_PROC

18、ESS_ATTACH)中,现在它已经被执行。那么现在应该从目标进程中将DLL 卸载:/ 从目标进程中卸载 (使用 CreateRemoteThread 和 FreeLibrary)FreeLibrary (void*)hLibModule, 0, NULL );进程间通信到目前为止,我们只讨论了关于如何将DLL 注入到远程进程的内容,但是,在大多数情况下,注入的 DLL 都需要与原应用程序进行某种方式的通信(回想一下,我们的DLL是被映射到某个远程进程的地址空间里了,不是在本地应用程序的地址空间中)。比如秘密侦测程序,DLL必须要知道实际包含密码的控件句柄,显然,编译时无法将这个值进行硬编码。

19、同样,一旦DLL获得了秘密,它必须将它发送回原应用程序,以便能正确显示出来。幸运的是,有许多方法处理这个问题,文件映射,WM_COPYDATA,剪贴板以及很简单的 #pragma data_seg 共享数据段等,本文我不打算使用这些技术,因为MSDN(“进程间通信”部分)以及其它渠道可以找到很多文档参考。不过我在 LibSpy例子中还是使用了 #pragma data_seg。细节请参考 LibSpy 源代码。第三部分:CreateRemoteThread 和 WriteProcessMemory 技术范例程序WinSpy 另外一个将代码拷贝到另一个进程地址空间并在该进程上下文中执行的方法是使

20、用远程线程和 WriteProcessMemory API。这种方法不用编写单独的DLL,而是用 WriteProcessMemory 直接将代码拷贝到远程进程然后用 CreateRemoteThread 启动它执行。先来看看 CreateRemoteThread 的声明:HANDLE CreateRemoteThread( HANDLE hProcess, / 传入创建新线程的进程句柄 LPSECURITY_ATTRIBUTES lpThreadAttributes, / 安全属性指针 DWORD dwStackSize, / 字节为单位的初始线程堆栈 LPTHREAD_START_ROUT

21、INE lpStartAddress, / 指向线程函数的指针 LPVOID lpParameter, / 新线程使用的参数 DWORD dwCreationFlags, / 创建标志 LPDWORD lpThreadId / 指向返回的线程ID 如果你比较它与 CreateThread(MSDN)的声明,你会注意到如下的差别: 在 CreateRemoteThread中,hProcess是额外的一个参数,一个进程句柄,新线程就是在这个进程中创建的; 在 CreateRemoteThread中,lpStartAddress 表示的是在远程进程地址空间中的线程起始地址。线程函数必须要存在于远程进

22、程中,所以我们不能简单地传递一个指针到本地的 ThreadFunc。必须得先拷贝代码到远程进程; 同样,lpParameter 指向的数据也必须要存在于远程进程,所以也得将它拷贝到那。综上所述,我们得按照如下的步骤来做:1. 获取一个远程进程的HANDLE (OpenProces) ;2. 在远程进程地址空间中为注入的数据分配内存(VirtualAllocEx);3. 将初始的 INDATA 数据结构的一个拷贝写入分配的内存中(WriteProcessMemory);4. 在远程进程地址空间中为注入的代码分配内存;5. 将 ThreadFunc 的一个拷贝写入分配的内存;6. 用 Create

23、RemoteThread启动远程的 ThreadFunc 拷贝;7. 等待远程线程终止(WaitForSingleObject);8. 获取远程来自远程进程的结果(ReadProcessMemory 或 GetExitCodeThread);9. 释放在第二步和第四步中分配的内存(VirtualFreeEx);10. 关闭在第六步和第一步获取的句柄(CloseHandle);ThreadFunc 必须要遵循的原则:1. 除了kernel32.dll 和user32.dll 中的函数之外,ThreadFunc 不要调用任何其它函数,只有 kernel32.dll 和user32.dll被保证在本

24、地和目标进程中的加载地址相同(注意,user32.dll并不是被映射到每个 Win32 的进程)。如果你需要来自其它库中的函数,将LoadLibrary 和 GetProcAddress 的地址传给注入的代码,然后放手让它自己去做。如果映射到目标进程中的DLL有冲突,你也可以用 GetModuleHandle 来代替 LoadLibrary。同样,如果你想在 ThreadFunc 中调用自己的子例程,要单独把每个例程的代码拷贝到远程进程并用 INJDATA为 ThreadFunc 提供代码的地址。2. 不要使用静态字符串,而要用 INJDATA 来传递所有字符串。之所以要这样,是因为编译器将静

25、态字符串放在可执行程序的“数据段”中,可是引用(指针)是保留在代码中的。那么,远程进程中ThreadFunc 的拷贝指向的内容在远程进程的地址空间中是不存在的。3. 去掉 /GZ 编译器开关,它在调试版本中是默认设置的。4. 将 ThreadFunc 和 AfterThreadFunc 声明为静态类型,或者不启用增量链接。5. ThreadFunc 中的局部变量一定不能超过一页(也就是 4KB)。注意在调试版本中4KB的空间有大约10个字节是用于内部变量的。6. 如果你有一个开关语句块大于3个case 语句,将它们像下面这样拆分开:7. switch( expression ) 8. case

26、 constant1: statement1; goto END;9. case constant2: statement2;10. case constant3:11. 12. switch( expression ) 13. case constant4: statement4;14. case constant5: statement5;15. case constant6: statement6;16. END:或者将它们修改成一个 if-else if 结构语句(参见附录E)。如果你没有按照这些规则来做,目标进程很可能会崩溃。所以务必牢记。在目标进程中不要假设任何事情都会像在本地进程

27、中那样 (参见附录F)。GetWindowTextRemote(A/W) 要想从“远程”编辑框获得密码,你需要做的就是将所有功能都封装在GetWindowTextRemot(A/W):中。int GetWindowTextRemoteA( HANDLE hProcess, HWND hWnd, LPSTR lpString );int GetWindowTextRemoteW( HANDLE hProcess, HWND hWnd, LPWSTR lpString );参数说明:hProcess:编辑框控件所属的进程句柄;hWnd:包含密码的编辑框控件句柄;lpString:接收文本的缓冲指针

28、;返回值:返回值是拷贝的字符数;下面让我们看看它的部分代码尤其是注入数据的代码以便明白 GetWindowTextRemote 的工作原理。此处为简单起见,略掉了 UNICODE 支持部分。INJDATAtypedef LRESULT (WINAPI *SENDMESSAGE)(HWND,UINT,WPARAM,LPARAM);typedef struct HWND hwnd; / 编辑框句柄SENDMESSAGE fnSendMessage; / 指向user32.dll 中 SendMessageA 的指针char psText128; / 接收密码的缓冲 INJDATA;INJDATA 是一个被注入到远程进程的数据结构。但在注入之前,结构中指向 SendMessageA 的指针是在本地应用程序中初始化的。因为对于每个使用user32.dll的进程来说,user32.dll总是被映射到相同的地址,因此,SendMessageA 的地址也肯定是相同的。这就保证了被传递到远程进程的是一个有效的指针。ThreadFunc函数static DWORD WINAPI ThreadFunc (INJDATA *pData) p

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1