找回密码
 加入我们

QQ登录

只需一步,快速开始

搜索
查看: 5157|回复: 0

[分享] 最简单的 远程线程实现自定义Dll注入

[复制链接]

1214

主题

352

回帖

11

精华

管理员

菜鸟

积分
93755

贡献奖关注奖人气王精英奖乐于助人勋章

发表于 2010-1-27 20:49:40 | 显示全部楼层 |阅读模式

  1. 首先做一个Dll,名字叫DllInsert.dll,我们在DllMain中的DLL_PROCESS_ATTACH分支写一个::MessageBox(NULL, "You are Load dll now!", "Load", NULL); 在DLL_PROCESS_DETACH中写一个::MessageBox(NULL, "You are Free dll now!", "Free", NULL); ok Dll写完了,把这个Dll放到System32目录中
  2. 下面来注入他到Explorer.exe进程,注意:Debug版本会崩溃,Release版本没问题的,原因不白
  3. #include "Tlhelp32.h."
  4. #include "Psapi.h."
  5. //提升权限
  6. BOOL ImproveProcPriv()
  7. {
  8. HANDLE token;
  9. //提升权限
  10. if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&token))
  11. {
  12.    // MessageBox(NULL,"打开进程令牌失败...","错误",MB_ICONSTOP);
  13.    return FALSE;
  14. }
  15. TOKEN_PRIVILEGES tkp;
  16. tkp.PrivilegeCount = 1;
  17. ::LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&tkp.Privileges[0].Luid);
  18. tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
  19. if(!AdjustTokenPrivileges(token,FALSE,&tkp,sizeof(tkp),NULL,NULL))
  20. {
  21.    // MessageBox(NULL,"调整令牌权限失败...","错误",MB_ICONSTOP);
  22.    return FALSE;
  23. }
  24. CloseHandle(token);
  25. return TRUE;
  26. }
  27. //这个函数名字取反了,- -! 尴尬
  28. DWORD GetProcNameByPID(char *strName)
  29. {
  30.     HANDLE          hprocessSnap = NULL;
  31.     PROCESSENTRY32 pe32;
  32. memset(&pe32, 0, sizeof(PROCESSENTRY32));
  33.     hprocessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//创建进程快照
  34. // 如果创建快照失败就返回1;
  35.     if (hprocessSnap == INVALID_HANDLE_VALUE)
  36. {
  37.    printf("\nCreateToolhelp32Snapshot()failed:%d",GetLastError());
  38.    return 0;
  39.     }
  40.     pe32.dwSize = sizeof(PROCESSENTRY32);   //初始化pe32的dwsize值
  41. //遍历快照
  42.     if (Process32First(hprocessSnap,&pe32))
  43. {   
  44.    do
  45.    {   
  46.     //如果name(要查找的进程的名字)等于pe32.szExeFile(本进程的名字),就返pe32.the32ProcessID          (进程ID)
  47.     if (!stricmp(strName, pe32.szExeFile))
  48.     {
  49.      return (DWORD)pe32.th32ProcessID;
  50.     }
  51.    }while (Process32Next(hprocessSnap,&pe32));
  52.     }
  53. //如果没找到就返回0
  54.     CloseHandle (hprocessSnap);
  55.     return 0;
  56. }
  57. // ========== 定义一个代码结构,本例为一个对话框============
  58. //类似的可以调用Dll里面是函数,只是要把函数名字作为参数传进来
  59. struct MyData
  60. {
  61. char sz[64]; // 对话框显示内容
  62. DWORD dwLoadLibrary; // LoadLibrary的地址
  63. DWORD dwFreeLibrary;
  64. };

  65. // ========== 远程线程的函数 ==============================
  66. DWORD __stdcall RMTFunc(MyData *pData)
  67. {
  68. typedef HMODULE(__stdcall *MLoadLibrary)(LPCTSTR);
  69. typedef void (__stdcall *MFreeLibrary)(HMODULE);
  70. MLoadLibrary Mloaddll = (MLoadLibrary )(pData->dwLoadLibrary);
  71. MFreeLibrary Mfreedll = (MFreeLibrary )(pData->dwFreeLibrary);
  72.    HMODULE hDll = Mloaddll(pData->sz);
  73. Mfreedll(hDll);
  74. return 0;
  75. }
  76. void CInsertExplorerDlg::OnOK()
  77. {
  78. ImproveProcPriv();
  79. DWORD dwIDExplorer = GetProcNameByPID("Explorer.exe");
  80. if (dwIDExplorer == 0)
  81. {
  82.    ::MessageBox(m_hWnd, "Get Pro ID Error!", NULL, NULL);
  83. }
  84. HANDLE hProcess = OpenProcess(
  85.    PROCESS_ALL_ACCESS,
  86.    FALSE,
  87.    dwIDExplorer);
  88. if (hProcess == NULL)
  89. {
  90.    ::MessageBox(m_hWnd, "Open Process Error!", NULL, NULL);
  91.    return ;
  92. }
  93. // ========= 代码结构 ================================================
  94. MyData data;
  95. ZeroMemory(&data, sizeof (MyData));
  96. strcpy(data.sz, "DllInsert.dll");
  97. HINSTANCE hUser = LoadLibrary("kernel32.dll");
  98. if (! hUser)
  99. {
  100.    printf("Can not load library.\n");
  101.    return ;
  102. }
  103. data.dwLoadLibrary = (DWORD)GetProcAddress(hUser, "LoadLibraryA");
  104. data.dwFreeLibrary = (DWORD)GetProcAddress(hUser, "FreeLibrary");
  105. FreeLibrary(hUser);
  106. if (! data.dwLoadLibrary)
  107.    return ;

  108. // ======= 分配空间 ===================================================
  109. void *pRemoteThread
  110.    = VirtualAllocEx(hProcess, 0,
  111.    1024*4, MEM_COMMIT|MEM_RESERVE,
  112.    PAGE_EXECUTE_READWRITE);
  113. if (! pRemoteThread)
  114.    return ;
  115. if (! WriteProcessMemory(hProcess, pRemoteThread, &RMTFunc, 1024*4, 0))
  116.    return ;
  117. MyData *pData
  118.    = (MyData*)VirtualAllocEx(hProcess, 0,
  119.    sizeof (MyData), MEM_COMMIT,
  120.    PAGE_READWRITE);
  121. if (!pData)
  122.    return ;

  123. if (! WriteProcessMemory(hProcess, pData, &data, sizeof (MyData), 0))
  124.    return ;

  125. // =========== 创建远程线程 ===========================================
  126. HANDLE hThread
  127.    = CreateRemoteThread(hProcess, 0,
  128.    0, (LPTHREAD_START_ROUTINE)pRemoteThread,
  129.    pData, 0, 0);
  130. if (! hThread)
  131. {
  132.    printf("远程线程创建失败");
  133.    return ;
  134. }
  135. CloseHandle(hThread);//这个CloseHandle是不会关掉远程线程的,TerminateThread能关掉
  136. VirtualFreeEx(hProcess, pRemoteThread, 1024*4, MEM_RELEASE);
  137. VirtualFreeEx(hProcess, pData, sizeof (MyData), MEM_RELEASE);
  138. CloseHandle(hProcess);
  139. return ;
  140. }

  141. 前面说的那个为什么会崩溃,查了一下原因:
  142. 原因是Debug模式下编译器会自动在代码中插入esp的check routine.它可以使Remote Thread崩溃.   
  143. 在DEBUG模式下常有这一句:
  144. 0043E604 call @ILT+4380(__RTC_CheckEsp) (42E121h)

  145. CreateRemoteThread中莫名其妙的崩溃常由它导致.由于没有你所有的代码,所以只是推测,没有办法详细了.
  146. 一般来说这是由于在Debug模式下,编译会在每个函数执行后自动加入
  147. 恢复stockheap地址等相关指令,也就是说,它会调用自动恢复stockheap地址函数。
  148. 而这个函数在远程地址空间中是不存在的,所以执行时会出错,
  149. 如在Release模式下,编译器就不会插入这个指令,所以执行没有问题。

  150. 其实这个问题跟远程执行插入你自己的代码也是一样的,都需要在release下面才能
  151. 执行成功。
复制代码
【VB】QQ群:1422505加的请打上VB好友
【易语言】QQ群:9531809  或 177048
【FOXPRO】QQ群:6580324  或 33659603
【C/C++/VC】QQ群:3777552
【NiceBasic】QQ群:3703755
您需要登录后才可以回帖 登录 | 加入我们

本版积分规则

快速回复 返回顶部 返回列表