原文:如何实现.net程序的进程注入

  如何实现.net程序的进程注入

                                  周银辉

进程注入比较常见,比如用IDE调试程序以及一些Spy程序,如果仅仅为了与调试器通讯,可以使用.net提供的Debugger接口(在EnvDTE.dll的EnvDTE命名空间下).但无论出于什么目的,进程注入都是比较好玩的事情,所以不妨一试 . 进程注入的方法貌似很多(比如像特洛伊一样乔装打扮让目标进程误认为你的程序集合法而加载到目标进程),这里提到的仅是其中的一种或某些方法的结合.

大致原理是这样的:

  • 源进程(也就是你的代码所在的进程)获得目标进程(也就是你的注入目标所在的进程)的ID或进程对象
  • 源进程提供一回调函数methodA(也就是你想要注入到目标进程后所执行的代码)
  • 将目标进程和回调函数methodA的完整路径(其所在的Assembly,Classic以及MethodName)提交给Injector(也就是我们编写的负责注入的类),让Injector来完成注入和让目标进程执行回调函数
  • Injector根据提供的目标进程ID取得目标进程对象,并获得目标进程的一个线程(我们称为目标线程)
  • 在目标线程中分配一块内存,将回调函数methodA的完整路径作为字符串存入该内存中
  • Injector在目标进程中安装一个钩子(Hook)监视某一个Windows消息(messageA),撰写钩子的回调函数methodB(该方法中的内容稍后解释)
  • 像目标进程发消息messageA,并将刚才分配的内存的基地址作为消息参数传递.
  • 由于我们针对messageA安装了钩子,所以目标进程会调用我们钩子函数methodB,并会把分配的内存的基地址包含在函数参数中
  • methodB中, 根据函数参数中的内存基地址在内存中解析出其实际对象,也就是一个表示我们的methodA的完整路径的字符串.根据该字符串中所表示的Assembly,className, methodName利用.net反射,反射出其MethodInfo对象(注意,关键点,methodB被回调时已经是在目标进程的某个线程中了)
  • Invoke反射出的MethodInfo对象, 我们的methodA得到了执行.

下面这个图可能会帮助你理解上面的话:

如果还没明白的话,那就看代码吧(这需要一点点C++/CLI知识,但我已经为每句加上了注释,应该蛮好懂的,关于C++/CLI可以点击这里了解更多.)

  1. #include "stdafx.h"
  2. #include "Injector.h"
  3. #include <vcclr.h>
  4. using namespace ManagedInjector;
  5. //defines a new window message that is guaranteed to be unique throughout the system.
  6. //The message value can be used when sending or posting messages.
  7. static unsigned int WM_GOBABYGO = ::RegisterWindowMessage(L"Injector_GOBABYGO!");
  8. static HHOOK _messageHookHandle;
  9. //-----------------------------------------------------------------------------
  10. //Spying Process functions follow
  11. //-----------------------------------------------------------------------------
  12. void Injector::Launch(System::IntPtr windowHandle, System::Reflection::Assembly^ assembly, System::String^ className, System::String^ methodName) {
  13. System::String^ assemblyClassAndMethod = assembly->Location + "$" + className + "$" + methodName;
  14. //convert String to local wchar_t* or char*
  15. pin_ptr<const wchar_t> acmLocal = PtrToStringChars(assemblyClassAndMethod);
  16. //Maps the specified executable module into the address space of the calling process.
  17. HINSTANCE hinstDLL = ::LoadLibrary((LPCTSTR) _T("ManagedInjector.dll"));
  18. if (hinstDLL)
  19. {
  20. DWORD processID = 0;
  21. //get the process id and thread id
  22. DWORD threadID = ::GetWindowThreadProcessId((HWND)windowHandle.ToPointer(), &processID);
  23. if (processID)
  24. {
  25. //get the target process object (handle)
  26. HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
  27. if (hProcess)
  28. {
  29. int buffLen = (assemblyClassAndMethod->Length + 1) * sizeof(wchar_t);
  30. //Allocates physical storage in memory or in the paging file on disk for the specified reserved memory pages.
  31. //The function initializes the memory to zero.
  32. //The return value is the base address of the allocated region of pages.
  33. void* acmRemote = ::VirtualAllocEx(hProcess, NULL, buffLen, MEM_COMMIT, PAGE_READWRITE);
  34. if (acmRemote)
  35. {
  36. //copies the data(the assemblyClassAndMethod string)
  37. //from the specified buffer in the current process
  38. //to the address range of the target process
  39. ::WriteProcessMemory(hProcess, acmRemote, acmLocal, buffLen, NULL);
  40. //Retrieves the address of MessageHookProc method from the hintsDLL
  41. HOOKPROC procAddress = (HOOKPROC)GetProcAddress(hinstDLL, "MessageHookProc");
  42. //install a hook procedure to the target thread(before the system sends the messages to the destination window procedure)
  43. _messageHookHandle = ::SetWindowsHookEx(WH_CALLWNDPROC, procAddress, hinstDLL, threadID);
  44. if (_messageHookHandle)
  45. {
  46. //send our custom message to the target window of the target process
  47. ::SendMessage((HWND)windowHandle.ToPointer(), WM_GOBABYGO, (WPARAM)acmRemote, 0);
  48. //removes the hook procedure installed in a hook chain by the SetWindowsHookEx function.
  49. ::UnhookWindowsHookEx(_messageHookHandle);
  50. }
  51. //removes a hook procedure installed in a hook chain by the SetWindowsHookEx function.
  52. ::VirtualFreeEx(hProcess, acmRemote, buffLen, MEM_RELEASE);
  53. }
  54. ::CloseHandle(hProcess);
  55. }
  56. }
  57. //Decrements the reference count of the loaded DLL
  58. ::FreeLibrary(hinstDLL);
  59. }
  60. }
  61. __declspec( dllexport )
  62. // The procedure for hooking, this will be called back after hooked
  63. int __stdcall MessageHookProc(int nCode, WPARAM wparam, LPARAM lparam) {
  64. //HC_ACTION: indicate that there are argments in wparam and lparam
  65. if (nCode == HC_ACTION)
  66. {
  67. CWPSTRUCT* msg = (CWPSTRUCT*)lparam;
  68. //when the target window received our custom message
  69. if (msg != NULL && msg->message == WM_GOBABYGO)
  70. {
  71. //get the argument passed by the message
  72. //actually, the argument is the base address (a pointer)
  73. //of the assemblyClassAndMethod string in the target process memory
  74. wchar_t* acmRemote = (wchar_t*)msg->wParam;
  75. //gcnew: creates an instance of a managed type (reference or value type) on the garbage collected heap
  76. System::String^ acmLocal = gcnew System::String(acmRemote);
  77. //split the string into substring array with $. Under this context:
  78. //acmSplit[0]:the assembly's location
  79. //acmSplit[1]:className;
  80. //acmSplit[2]:methodName
  81. //we use these infomation to reflect the method in the source assembly, and invoke it in the target process
  82. cli::array<System::String^>^ acmSplit = acmLocal->Split('$');
  83. //refect the method, and invoke it
  84. System::Reflection::Assembly^ assembly = System::Reflection::Assembly::LoadFile(acmSplit[0]);
  85. if (assembly != nullptr)
  86. {
  87. System::Type^ type = assembly->GetType(acmSplit[1]);
  88. if (type != nullptr)
  89. {
  90. System::Reflection::MethodInfo^ methodInfo =
  91. type->GetMethod(acmSplit[2], System::Reflection::BindingFlags::Static | System::Reflection::BindingFlags::Public);
  92. if (methodInfo != nullptr)
  93. {
  94. methodInfo->Invoke(nullptr, nullptr);
  95. }
  96. }
  97. }
  98. }
  99. }
  100. return CallNextHookEx(_messageHookHandle, nCode, wparam, lparam);
  101. }

接下来,做个DEMO尝试一下:

 

解决方案中的InjectorDemo就是我们上述的源进程,它会利用Injector将下面这段代码注入到Target进程中并执行:

public static void DoSomethingEvie()

{

    vartargetWindow = Application.Current.MainWindow;



    if(targetWindow != null)

    {

        varlb = newLabel{Content = "haha, i caught you :)"};

        targetWindow.Content = lb;

    }

}

也就是说InjectorDemo进程会将InjectTargetApp进程的主窗口的内容修改成"haha, i caught you"这样的一个Label.

运行程序:

 

上面的两个窗口分别处于不同的进程中, 点击 "Inject it" 按钮, 其辉调用如下代码:

ManagedInjector.Injector.Launch(targetProcess.MainWindowHandle, typeof(InjectorWindow).Assembly, typeof(InjectorWindow).FullName, "DoSomethingEvie");

然后:

 

点击这里下载Demo

仅供参考(日志内容仅仅记录了一种存在性,并非特定问题的解决方案,讨论其意义性是毫无意义的,谢谢)

如何实现.net程序的进程注入的更多相关文章

  1. Sql-Server应用程序的高级注入

    本文作者:Chris Anley 翻译: luoluo [luoluonet@hotmail.com] [目 录] [概要] [介绍] [通过错误信息获取信息] [更深入的访问] [xp_cmdshe ...

  2. 使用VC++通过远程进程注入来实现HOOK指定进程的某个API

    前阵子读到一篇关于<HOOK API入门之Hook自己程序的MessageBoxW>的博客,博客地址:http://blog.csdn.net/friendan/article/detai ...

  3. Android中通过进程注入技术改动广播接收器的优先级

    前言 这个周末又没有吊事,在家研究了怎样通过进程的注入技术改动广播接收器的优先级.关于这个应用场景是非常多的.并且也非常重要.所以就非常急的去fixed了. Android中的四大组件中有一个广播:B ...

  4. “聊天剽窃手”--ptrace进程注入型病毒

    近日,百度安全实验室发现了一款"聊天剽窃手"病毒.该病毒可以通过ptrace方式注入恶意代码至QQ.微信程序进程.恶意代码可以实时监控手机QQ.微信的聊天内容及联系人信息. 该病毒 ...

  5. 通过修改EIP寄存器实现32位程序的DLL注入

    功能:通过修改EIP寄存器实现32位程序的DLL注入 <如果是64位 记得自己对应修改汇编代码部分> 原理:挂起目标进程,停止目标进程EIP的变换,在目标进程开启空间,然后把相关的指令机器 ...

  6. Android进程注入

    全部代码在这里下载:http://download.csdn.net/detail/a345017062/8133239 里面有两个exe.inj是一个C层进程注入的样例.inj_dalvik是我写的 ...

  7. 利用“进程注入”实现无文件复活 WebShell

    引子 上周末,一个好兄弟找我说一个很重要的目标shell丢了,这个shell之前是通过一个S2代码执行的漏洞拿到的,现在漏洞还在,不过web目录全部不可写,问我有没有办法搞个webshell继续做内网 ...

  8. Android中通过进程注入技术修改广播接收器的优先级

    前言 这个周末又没有吊事,在家研究了如何通过进程的注入技术修改广播接收器的优先级,关于这个应用场景是很多的,而且也很重要,所以就很急的去fixed了. Android中的四大组件中有一个广播:Broa ...

  9. Android中通过进程注入技术修改系统返回的Mac地址

    致谢 感谢看雪论坛中的这位大神,分享了这个技术:http://bbs.pediy.com/showthread.php?t=186054,从这篇文章中学习到了很多内容,如果没有这篇好文章,我在研究的过 ...

随机推荐

  1. JSP内置对象——Exception对象

    举个实例说明下: 新建一个“exception_test.jsp”: 对应的exception.jsp页面: 运行“exception_test.jsp”后: 虽然执行的是“exception_tes ...

  2. 12、多线程:Threading、守护线程

    线程与进程: 线程对于进程来说,就好似工厂里的工人,分配资源是分配到工厂,工人再去处理. 线程是被系统独立调度和分派的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属 ...

  3. 关于excel中的查找

    弹出查找界面后,点击“选项”按钮 在范围下拉框中选择: 1.工作表:表示在当前表sheet中进行查找 2.工作簿:表示在此excel整个文件中进行查找

  4. check

    private int AddNewstoDB(NewsModels newsModels, string dateTimeStr, string jsonStr, string cid, strin ...

  5. Sender IP字段为"0.0.0.0"的ARP请求报文

    今天在研究免费ARP的过程中,抓到了一种Sender IP字段为“0.0.0.0”的ARP请求报文(广播),抓包截图如下: 这让我很疑惑.一个正常的ARP请求不应该只是Target MAC字段为全0吗 ...

  6. 【PAT】B1075 链表元素分类(25 分)

    这道题算有点难,心目中理想的难度. 不能前怕狼后怕虎,一会担心超时,一会又担心内存过大,直接撸 将三部分分别保存到vector 有意思的在于输出 分别输出第一个的add和num 中间输出nextadd ...

  7. javascript获取DOM对象三种方法

    1. getElementByID() getElementByID()方法可返回对拥有指定ID的第一个对象的引用 2. getElementByTagName() getElementByTagNa ...

  8. NSObject

    一.前言 该博客里面的方法均是看着苹果官方的API来解释的,一般都是常用的方法如有问题,请指出. 二.简介: 该类集成的是其本身,大家可以从任何一个类去向上追溯,都会发现最终的父类都是NSObject ...

  9. DFS普及组常用模板简单整理

    一些普及组会用到的DFS模板,其他的DFS我感觉普及组不会用到所以暂且搁着,等之后有时间了再细写w (至于我为什么最近不写TG相关只写最基础的PJ的内容,请戳这里了解) dfs各种模板big集合 1. ...

  10. (转)postgresql+postgis空间数据库使用总结

    转载地址:https://blog.csdn.net/qq_36588972/article/details/78902195 参考资料: pgrouting路径导航 https://www.cnbl ...