通过远程线程向其他进程注入代码

虽然不是什么高深的技术,但最近在搞屏蔽格式化,所以就写出来吧。虽然还有一点没有解决。屏蔽系统的格式化说白的就是钩掉Explorer.exe进程的导入库shell32.dll中的SHFormatDrive函数,但是在winxp sp2中默认对explorer.exe加入了数据执行保护,无奈现在还是没有找到办法。

我的这个向目标进程注入代码的思想就是用了在目标进程启动一个线程,导入自己的DLL执行。但是跟其他的方法还有点不一样的是,在DLL的加载的时候有一个通知事件吧,就在这里执行代码,当然代码在同一个DLL中,也用导出到目标进程了,特点是:小巧,方便,隐蔽。但是有个致命的弱点就是不能跳过winxp的数据执行保护。高手若有什么高招敬请指点。

下面列出主要代码:

主程序

    // 枚举进程

    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);

    if(hProcessSnap == INVALID_HANDLE_VALUE){

     ::MessageBox(NULL,"Found processes failed","notice",MB_OK);

     return 0;

    }

    bRet = Process32First(hProcessSnap,&pe32);

    while(bRet){//szProcessName是目标进程的可执行文件名,不加路径

     if(strncmp(szProcessName,pe32.szExeFile,(sizeof(szProcessName) >= sizeof(pe32.szExeFile))? sizeof(pe32.szExeFile):sizeof(szProcessName) ) ==0 ){

      pid = pe32.th32ProcessID;

      hTargetProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE,pid);// 取得指定目标进程句柄

      break;

     }

     bRet = Process32Next(hProcessSnap,&pe32);

    }

    CloseHandle(hProcessSnap);

    if(hTargetProcess !=NULL){

     //从本进程的导入表中找LoadLibraryA的地址,目标进程若没有什么特别应该也会在同样的位置

     pfnLoadLibraryAddr = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("Kernel32"),"LoadLibraryA");

     // 在目标进程中申请一个空间保存注入DLL名称,btDllName就是要加载的自定义dll名称,加路径

     btPtr = (char *)VirtualAllocEx(hTargetProcess, NULL, (1 + lstrlenA(btDLLName)) * sizeof(char), MEM_COMMIT, PAGE_EXECUTE_READWRITE);

     bRet = WriteProcessMemory(hTargetProcess, btPtr, btDLLName, (1 + lstrlenA(btDLLName)) * sizeof(char), NULL);

     hRemoteThread = CreateRemoteThread(hTargetProcess, NULL, 0, pfnLoadLibraryAddr,(PVOID)btPtr, 0, NULL);

     if(hRemoteThread != NULL){

      MessageBox(NULL,"Inject Dll success","notice",MB_OK);

      hRemoteThread = NULL;

     }

    }



// Inject.cpp : 定义 DLL 应用程序的入口点。 //



#include "stdafx.h"

 typedef DWORD (__stdcall *LPFUN)(HWND hwnd, UINT drive, UINT fmtID, UINT option);

 //typedef DWORD (*LPFUNINJECT)(VOID);



// mov eax,400000h

 // jmp eax

 // btNewBytes数组的第1-4位d的双字为400000h

 // 用于写入目标函数的内容,后面将会修改跳转地址,指向目标函数的地址

 BYTE btNewBytes[8] = {0xB8,0x00,0x00,0x40,0x00,0xFF,0xE0,0x00};

 BYTE btOldBytes[8];    // 保存注入前目标函数的开头内容

 HMODULE hTargetModule = NULL; // 目标模块句柄

 LPFUN lpFun = NULL;    // 指向目标函数地址



DWORD __stdcall lpfnHook(HWND hwnd, UINT drive, UINT fmtID, UINT option) {

  ::MessageBox(NULL,"Format Forbidden!","notice",MB_OK);



 // 取消修改

   DWORD dwOldProtect;

  MEMORY_BASIC_INFORMATION mbi;

  ::VirtualQuery(lpFun, &mbi, sizeof(mbi));

  ::VirtualProtect(lpFun, 8, PAGE_READWRITE, &dwOldProtect);

  ::WriteProcessMemory(GetCurrentProcess(), (void*)lpFun, btOldBytes, sizeof(DWORD)*2, NULL);

  ::VirtualProtect(lpFun, 8, mbi.Protect, 0);



 return lpFun(hwnd, drive, fmtID, option);

 }



BOOL APIENTRY DllMain( HANDLE hModule,                        DWORD  ul_reason_for_call,                        LPVOID lpReserved       ) {

  DWORD dwOldProtect;  MEMORY_BASIC_INFORMATION mbi;



    switch (ul_reason_for_call)  {

   case DLL_PROCESS_ATTACH:

    *(DWORD*)(btNewBytes + 1) = (DWORD)lpfnHook;//将btNewBytes数组的第1-4位转化为双字,存储lpfnHook函数地址

    hTargetModule = GetModuleHandle("SHELL32");

    while(hTargetModule == NULL){

     // 等着模块有效

     hTargetModule = GetModuleHandle("SHELL32");

     // 还是自己加载

     //hTargetModule = ::LoadLibrary("SHELL32.DLL");

    }

    //if(hTargetModule == NULL){

    // lpFun = NULL;

    // //::MessageBox(NULL, "Cannot find Shell32.dll", "notice", MB_OK);

    // return FALSE;

    //}

    lpFun = (LPFUN)::GetProcAddress(hTargetModule, "SHFormatDrive");

    if(lpFun == NULL){

     ::FreeLibrary(hTargetModule);

     hTargetModule = NULL;

     //::MessageBox(NULL, "Cannot find function SHFormatDrive", "notice", MB_OK);     // 找不到函数不能加载本模块

     return FALSE;

    }

    ::VirtualQuery(lpFun, &mbi, sizeof(mbi));

    ::VirtualProtect(lpFun, 8, PAGE_EXECUTE_READWRITE, &dwOldProtect);

    memcpy(btOldBytes, lpFun, 8);

    ::WriteProcessMemory(GetCurrentProcess(), (void*)lpFun, btNewBytes, sizeof(DWORD)*2, NULL);

    ::VirtualProtect(lpFun, 8, mbi.Protect, 0);



   //将钩子函数区域改成可以执行可读写

    ::VirtualQuery((LPVOID)lpfnHook, &mbi, sizeof(mbi));

    ::VirtualProtect((LPVOID)lpfnHook,(int)((int)DllMain - (int)lpfnHook + 1024), PAGE_EXECUTE_READWRITE, &dwOldProtect);



   break;

   case DLL_THREAD_ATTACH:

    break;

   case DLL_THREAD_DETACH:

    break;

   case DLL_PROCESS_DETACH:

    break;

     }

     return TRUE;

 }



 lpfnHook函数就是我的新的执行函数,只要执行格式化就会跳转到这里,我在SHFormatDrive函数的开头用新的命令覆盖,这个命令是跳转到我的lpfnHook函数,在lpfnHook中显示一个对话框,告诉不能格式化,我在下面有将SHFormatDrive的开头改回去,也可以就此退出,但注意要继续执行SHFormatDrive操作,必须将SHFormatDrive函数改回去,不然有会跳到lpfnHook中死循环.

在目标进程中若执行格式化函数SHFormatDrive,就会在跳转到我的函数lpfnHook中执行,这里要跟lpfnHook函数的声明要跟SHFormatDrive函数一模一样,就是调用格式也要一样,当初这里费了好大的劲才调试出调用格式不对,引起堆栈不平衡,好在我还学过汇编,不然,估计这篇文章就要夭折了.这里我也没有将lpfnHook函数从DLL中导出,所以检查导入表也看不到有什么新的函数导入.

当然,目标进程还是要导入这个DLL的.我怀疑就是没有将lpfnHook函数导出到目标进程中,所以才会被数据执行保护给闭掉.只是调试动态导入DLL的程序还是不太好调试,反正在VS2003中没有断到lpfnHook函数的入口.不清楚是不是因为不能执行lpfnHook的原因.

关了数据执行保护就可以向explorer.exe中注入代码来屏蔽掉格式化操作对没有被保护的进程可以直接使用.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 示例代码:#include <windows.h> #include <stdio.h> #include <tlhelp32.h> // 远程线程注入dll BOOL InjectDLL(DWORD dwPID, char *szDLLName); int main(int argc, char *argv[]) { printf("远程线程注入dll演示程序\n"); if (argc == 3) { DWORD dwPID = atoi(argv[1]); char *szDLLName = argv[2]; InjectDLL(dwPID, szDLLName); } else { printf("用法:InjectDLL.exe <PID> <DLLName>\n"); } return 0; } // 远程线程注入dll BOOL InjectDLL(DWORD dwPID, char *szDLLName) { HANDLE hProcess, hThread; LPVOID lpBaseAddress; LPTHREAD_START_ROUTINE lpStartAddress; DWORD dwSize, dwThreadId; char szPath[256]; char szBuffer[1024]; // 打开进程 hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID); if (hProcess == NULL) { printf("OpenProcess() Error: %d\n", GetLastError()); return FALSE; } // 获取DLL的完整路径 GetFullPathName(szDLLName, 256, szPath, NULL); // 在进程中申请虚拟内存 dwSize = strlen(szPath) + 1; lpBaseAddress = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE); if (lpBaseAddress == NULL) { printf("VirtualAllocEx() Error: %d\n", GetLastError()); return FALSE; } // 将DLL路径写入到虚拟内存 int nBytesWritten; WriteProcessMemory(hProcess, lpBaseAddress, szPath, dwSize, &nBytesWritten); if (nBytesWritten != dwSize) { printf("WriteProcessMemory() Error: %d\n", GetLastError()); return FALSE; } // 加载Kernel32.dll HMODULE hKernel32 = GetModuleHandle("Kernel32"); if (hKernel32 == NULL) { printf("GetModuleHandle() Error: %d\n", GetLastError()); return FALSE; } // 获取LoadLibraryA函数地址 lpStartAddress = GetProcAddress(hKernel32, "LoadLibraryA"); if (lpStartAddress == NULL) { printf("GetProcAddress() Error: %d\n", GetLastError()); return FALSE; } // 创建远程线程 hThread = CreateRemoteThread(hProcess, NULL, 0, lpStartAddress, lpBaseAddress, 0, &dwThreadId); if (hThread == NULL) { printf("CreateRemoteThread() Error: %d\n", GetLastError()); return FALSE; } // 等待远程线程结束 WaitForSingleObject(hThread, INFINITE); // 读取线程退出码 DWORD dwExitCode; GetExitCodeThread(hThread, &dwExitCode); if (dwExitCode == 0) { printf("LoadLibrary() Error: %d\n", GetLastError()); return FALSE; } // 关闭句柄 CloseHandle(hProcess); CloseHandle(hThread); return TRUE; }我不能帮助你编写代码,但是我可以提供一些参考资料,帮助你编写远程线程注入dll代码。 ### 回答2: 远程线程注入DLL是一种技术,用于在目标进程注入自定义的动态链接库(DLL)并执行其中的代码。以下是一个使用C语言编写的远程线程注入DLL代码示例: ```c #include <stdio.h> #include <stdlib.h> #include <windows.h> int main() { // 目标进程进程ID DWORD pid = 1234; // 加载要注入DLL路径 char dllPath[] = "C:\\path_to_dll\\mydll.dll"; // 获取目标进程句柄 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); if (hProcess == NULL) { printf("无法打开目标进程"); return -1; } // 在目标进程中为DLL路径分配内存 LPVOID dllPathAddr = VirtualAllocEx(hProcess, NULL, sizeof(dllPath), MEM_COMMIT, PAGE_READWRITE); if (dllPathAddr == NULL) { printf("无法在目标进程中分配内存"); CloseHandle(hProcess); return -1; } // 在目标进程中写入DLL路径 if (!WriteProcessMemory(hProcess, dllPathAddr, dllPath, sizeof(dllPath), NULL)) { printf("无法写入DLL路径到目标进程"); VirtualFreeEx(hProcess, dllPathAddr, 0, MEM_RELEASE); CloseHandle(hProcess); return -1; } // 获取Kernel32.dll中LoadLibrary函数的地址 HMODULE kernel32 = GetModuleHandle("kernel32.dll"); FARPROC loadLibrary = GetProcAddress(kernel32, "LoadLibraryA"); // 创建远程线程在目标进程中执行LoadLibrary函数,将DLL路径作为参数 HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibrary, dllPathAddr, 0, NULL); if (hThread == NULL) { printf("无法在目标进程中创建远程线程"); VirtualFreeEx(hProcess, dllPathAddr, 0, MEM_RELEASE); CloseHandle(hProcess); return -1; } // 等待远程线程执行结束 WaitForSingleObject(hThread, INFINITE); // 清理资源 VirtualFreeEx(hProcess, dllPathAddr, 0, MEM_RELEASE); CloseHandle(hThread); CloseHandle(hProcess); printf("远程线程注入DLL成功"); return 0; } ``` 这段代码首先通过`OpenProcess`函数打开目标进程,然后使用`VirtualAllocEx`在目标进程中为DLL路径分配内存,并使用`WriteProcessMemory`将DLL路径写入目标进程内存。接着,使用`GetModuleHandle`和`GetProcAddress`获取`LoadLibrary`函数的地址,然后使用`CreateRemoteThread`在目标进程中创建一个远程线程,让其执行`LoadLibrary`函数,将DLL路径作为参数传递给它。最后,使用`WaitForSingleObject`等待远程线程执行完毕,并释放之前分配的资源。 ### 回答3: 使用C语言编写远程线程注入DLL代码可以通过以下步骤实现: 1. 首先,需要创建一个目标进程的句柄。可以使用`OpenProcess`函数来打开目标进程,并获得进程的句柄。 2. 接下来,需要在目标进程中分配一块内存空间,用于存储DLL的路径和名称。可以使用`VirtualAllocEx`函数在目标进程内部分配内存。 3. 在分配的内存空间中写入DLL的路径和名称。可以使用`WriteProcessMemory`函数将DLL的路径和名称写入到目标进程的内存中。 4. 使用`GetProcAddress`函数获取`LoadLibraryA`函数的地址,该函数用于加载DLL。可以使用`GetModuleHandle`函数获取kernel32.dll的句柄,然后再调用`GetProcAddress`函数来获取`LoadLibraryA`函数的地址。 5. 使用`CreateRemoteThread`函数在目标进程中创建一个远程线程,将`LoadLibraryA`函数地址作为线程的入口点,将DLL的路径和名称作为线程的参数传递。这样,在目标进程中就会自动加载并执行DLL。 完整的代码示例如下: ```c #include <windows.h> int main() { // Step 1: 打开目标进程句柄 HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PROCESS_ID); // Step 2: 分配内存空间 LPVOID lpRemoteBuffer = VirtualAllocEx(hProcess, NULL, MAX_PATH, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); // Step 3: 写入DLL路径和名称 char dllPath[] = "C:\\path\\to\\dll.dll"; WriteProcessMemory(hProcess, lpRemoteBuffer, (LPVOID)dllPath, sizeof(dllPath), NULL); // Step 4: 获取LoadLibraryA函数地址 HMODULE hKernel32 = GetModuleHandleA("kernel32.dll"); FARPROC lpLoadLibraryA = GetProcAddress(hKernel32, "LoadLibraryA"); // Step 5: 创建远程线程注入DLL HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)lpLoadLibraryA, lpRemoteBuffer, 0, NULL); // 关闭句柄 CloseHandle(hThread); CloseHandle(hProcess); return 0; } ``` 以上就是使用C语言编写远程线程注入DLL代码。请注意,使用远程线程注入DLL可能存在一些安全风险,请谨慎使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值