好友
阅读权限10
听众
最后登录1970-1-1
|
本帖最后由 yoyoRev 于 2022-11-18 23:45 编辑
看了相关视频,是易语言实现的内存注入,用c/c++来实现一下
内存注入的基本步骤:
1.将要注入的dll文件读取到缓冲区然后拉伸
2.对拉伸后的dll文件进行重定位表的修复
3.起远程线程修复iat表
4.抹除pe指纹,跳转到oep
以下是dll文件代码,只有一个MessageBox函数
#include "pch.h"
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MessageBox(0, TEXT("测试dll"), 0, 0);
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
以下是注入器代码
#include <stdio.h>
#include <windows.h>
typedef struct _InjcetPara {
DWORD NewImageBase;
DWORD AddressOfEntryPoint;
LPVOID LoadLibraryAdd;
LPVOID GetProcAdd;
DWORD RvaIdt;
DWORD SizeOfHeaders;
}InjcetPara,*PInjcetPara;
InjcetPara inp;
BYTE ReIat[] = "\x8B\xFF\x55\x8B\xEC\x83\xEC\x40\x8B\x45\x08\x36\x8B\
\x18\x89\x5D\xFC\x36\x8B\x58\x08\x89\x5D\xF8\x36\x8B\x58\x0C\x89\x5D\xF4\
\x8B\x50\x10\x03\x55\xFC\x89\x55\xEC\x8B\x55\xEC\x83\x7A\x0C\x00\x74\x68\x8B\
\x42\x0C\x03\x45\xFC\x50\xFF\x55\xF8\x89\x45\xE8\xC7\x45\xF0\x00\x00\x00\x00\
\x8B\x55\xEC\x8B\x42\x10\x03\x45\xFC\x89\x45\xE4\x8B\x45\xE4\x8B\xD8\x8B\x7D\xF0\
\xC1\xE7\x02\x83\x3C\x1F\x00\x74\x31\x8B\x04\x1F\xA9\x00\x00\x00\x80\x74\x09\x25\
\xFF\xFF\xFF\x7F\x8B\xD0\xEB\x06\x03\x45\xFC\x8D\x50\x02\x52\xFF\x75\xE8\xFF\x55\xF4\
\x8B\x5D\xE4\x8B\x75\xF0\xC1\xE6\x02\x89\x04\x1E\xFF\x45\xF0\xEB\xBE\x83\x45\xEC\x14\
\xEB\x8F\xFC\x8B\x7D\xFC\x33\xC0\x8B\x5D\x08\x36\x8B\x4B\x14\xC1\xE9\x02\xF3\xAB\x6A\x00\
\x6A\x00\x6A\x01\xFF\x75\xFC\x36\x8B\x43\x04\x03\x45\xFC\xFF\xD0\xC9\xC3";
BOOL FileToImage(PDWORD pFile,PDWORD pImage,PDWORD pImageSize) {
DWORD ImageBufferSize = 0;
PIMAGE_DOS_HEADER pNt = (PIMAGE_DOS_HEADER)pFile;
PIMAGE_FILE_HEADER pFileHead = PIMAGE_FILE_HEADER((DWORD)pFile + pNt->e_lfanew + 4);
PIMAGE_OPTIONAL_HEADER pOption = PIMAGE_OPTIONAL_HEADER(pFileHead + 1);
PIMAGE_SECTION_HEADER pSection = PIMAGE_SECTION_HEADER((DWORD)pFileHead +0x14 + pFileHead->SizeOfOptionalHeader);
inp.AddressOfEntryPoint = pOption->AddressOfEntryPoint;
inp.SizeOfHeaders = pOption->SizeOfHeaders;
ImageBufferSize = pOption->SizeOfImage;
*pImageSize = pOption->SizeOfImage;
PBYTE pImageFile = (PBYTE)malloc(ImageBufferSize);
if (!pImageFile) {
return 0;
}
*pImage = (DWORD)pImageFile;
memset(pImageFile,0, ImageBufferSize);
memcpy((PBYTE)pImageFile, (PBYTE)pFile, pOption->SizeOfHeaders);
//printf("%s\n", pSection->Name);
for (int i = 0; i < pFileHead->NumberOfSections; i++) {
memcpy(PBYTE((DWORD)pImageFile+ pSection->VirtualAddress), PBYTE((DWORD)pFile+ pSection->PointerToRawData), pSection->SizeOfRawData);
pSection++;
}
return 0;
}
BOOL Reloc(PDWORD pImage,DWORD NewImageBase) {
PIMAGE_DOS_HEADER pNt = (PIMAGE_DOS_HEADER)pImage;
PIMAGE_FILE_HEADER pFileHead = PIMAGE_FILE_HEADER((DWORD)pImage + pNt->e_lfanew + 4);
PIMAGE_OPTIONAL_HEADER pOption = PIMAGE_OPTIONAL_HEADER(pFileHead + 1);
PIMAGE_DATA_DIRECTORY pDataDire = PIMAGE_DATA_DIRECTORY((DWORD)(pFileHead + 1) + 0x60);
if (!(pDataDire + 5)->VirtualAddress) {
printf("没有重定位表\n");
return 0;
}
inp.RvaIdt = (pDataDire + 1)->VirtualAddress;
PIMAGE_BASE_RELOCATION pbreloc = PIMAGE_BASE_RELOCATION((DWORD)pImage + (pDataDire + 5)->VirtualAddress);
PWORD PReFlag = 0;
while (pbreloc->VirtualAddress) {
PReFlag = PWORD(pbreloc + 1);
for (int i = 0; i < (pbreloc->SizeOfBlock - 8) / 2; i++) {
if ((*PReFlag & 0xf000) == 0x3000) {
PDWORD ptemp = PDWORD(pbreloc->VirtualAddress + (*PReFlag & 0xfff) + (DWORD)pImage);
*ptemp = *ptemp - pOption->ImageBase + NewImageBase;
}
PReFlag++;
}
pbreloc = PIMAGE_BASE_RELOCATION((DWORD)pbreloc + pbreloc->SizeOfBlock);
}
return 1;
}
DWORD CreateMapFile(LPCSTR lpFileName, PDWORD pFileSize) {
HANDLE hFile = INVALID_HANDLE_VALUE;
HANDLE hMapFile = INVALID_HANDLE_VALUE;
DWORD FileSize = NULL;
LPVOID lpMemory = NULL;
//读取文件
hFile = CreateFileA(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (!hFile) {
MessageBox(0, TEXT("读取文件失败"), 0, 0);
return 0;
}
//获取文件大小
FileSize = GetFileSize(hFile, NULL);
if (!FileSize) {
MessageBox(0, TEXT("获取文件大小失败"), 0, 0);
return 0;
}
*pFileSize = FileSize;
//创建文件映像
hMapFile = CreateFileMappingA(hFile, NULL, PAGE_READWRITE, 0, FileSize, NULL);
if (!hMapFile) {
MessageBox(0, TEXT("创建文件映像失败"), 0, 0);
return 0;
}
lpMemory = MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, 0);
if (!lpMemory) {
MessageBox(0, TEXT("调用文件映射失败"), 0, 0);
return 0;
}
CloseHandle(hFile);
CloseHandle(hMapFile);
return (DWORD)lpMemory;
}
HANDLE GetProcessHandle(DWORD dwProcessId) {
HANDLE hProcess = NULL;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);
if (!hProcess) {
printf("打开进程句柄失败,错误码:%d\n",GetLastError());
}
return hProcess;
}
int main(int argc, char* argv[]) {
DWORD ImageAddress = 0;
DWORD ImageSize = 0;
DWORD FileSize = 0;
DWORD ThreadReIat = 0;
if (argc < 3) {
printf("参数不够,注入失败\n");
return 0;
}
DWORD dwProcessId = atoi(argv[1]);
HANDLE hProcess = GetProcessHandle(dwProcessId);
if (!hProcess) {
return 0;
}
DWORD MeMoryAddress = CreateMapFile(argv[2], &FileSize);
if (!MeMoryAddress) {
return 0;
}
FileToImage((PDWORD)MeMoryAddress,&ImageAddress,&ImageSize);
UnmapViewOfFile((LPVOID)MeMoryAddress);
DWORD NewImageBase = (DWORD)VirtualAllocEx(hProcess,NULL, ImageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!NewImageBase) {
printf("申请空间失败\n");
return 0;
}
inp.NewImageBase = NewImageBase;
if (!Reloc((PDWORD)ImageAddress, NewImageBase)) {
printf("模块没有重定位表,注入失败\n");
VirtualFreeEx(hProcess, (LPVOID)NewImageBase, 0, MEM_RELEASE);
return 0;
}
HMODULE hKernel = LoadLibraryA("kernel32.dll");
if (!hKernel) {
printf("获取kernel32句柄失败\n");
VirtualFreeEx(hProcess, (LPVOID)NewImageBase, 0, MEM_RELEASE);
return 0;
}
inp.LoadLibraryAdd = GetProcAddress(hKernel,"LoadLibraryA");
inp.GetProcAdd = GetProcAddress(hKernel, "GetProcAddress");
if (!inp.LoadLibraryAdd || !inp.GetProcAdd) {
printf("获取函数地址失败\n");
VirtualFreeEx(hProcess, (LPVOID)NewImageBase, 0, MEM_RELEASE);
return 0;
}
WriteProcessMemory(hProcess, (LPVOID)NewImageBase, (LPCVOID)ImageAddress,ImageSize, NULL);
ThreadReIat = (DWORD)VirtualAllocEx(hProcess, NULL, 0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (!ThreadReIat) {
printf("申请线程空间失败\n");
return 0;
}
WriteProcessMemory(hProcess, (LPVOID)ThreadReIat,&inp,sizeof(inp),NULL);
WriteProcessMemory(hProcess, (LPVOID)(ThreadReIat +0x30), &ReIat, sizeof(ReIat), NULL);
//远程线程修复iat表
HANDLE hReIat = CreateRemoteThread(hProcess,NULL,NULL, LPTHREAD_START_ROUTINE(ThreadReIat + 0x30),(LPVOID)ThreadReIat,0,NULL);
if (!hReIat) {
printf("创建远程线程失败,修复IAT表失败\n");
return 0;
}
WaitForSingleObject(hReIat,INFINITE);
VirtualFreeEx(hProcess, (LPVOID)NewImageBase, 0, MEM_RELEASE);
VirtualFreeEx(hProcess, (LPVOID)ThreadReIat, 0, MEM_RELEASE);
return 0;
}
构造了一个结构体,用于远程线程修复iat表,BYTE ReIat[]是进行修复IAT表的shellcode
具体汇编代码如下
;参数说明
;ebp-4:dll文件基址
;ebp-8:LoadLibrary函数地址
;ebp-c:GetProcAddress函数地址
;ebp-10:IAT数组标号
;ebp-14:导入表地址
;ebp-18:导入表NAME指向dll的基址
;ebp-1c:iat数组基址
.386
.model flat,stdcall
option casemap:none
.code
start:
mov edi,edi
push ebp
mov ebp,esp
sub esp,40h
mov eax,dword ptr ss:[ebp+8]
mov ebx,dword ptr ss:[eax]
mov dword ptr ss:[ebp-4],ebx
mov ebx,dword ptr ss:[eax+8]
mov dword ptr ss:[ebp-8],ebx
mov ebx,dword ptr ss:[eax+0ch]
mov dword ptr ss:[ebp-0ch],ebx
mov edx,dword ptr ds:[eax+10h]
add edx,dword ptr ss:[ebp-4]
mov dword ptr ss:[ebp-14h],edx
r2:
mov edx,dword ptr ss:[ebp-14h]
cmp dword ptr ds:[edx+0ch],0
jz clPe
mov eax,dword ptr ds:[edx+0ch]
add eax,dword ptr ss:[ebp-4h]
push eax
call dword ptr ss:[ebp-8]
mov dword ptr ss:[ebp-18h],eax
mov dword ptr ss:[ebp-10h],0
mov edx,dword ptr ss:[ebp-14h]
mov eax,dword ptr ds:[edx+10h] ;获取iat数组偏移
add eax,dword ptr ss:[ebp-4] ;指向iat数组
mov dword ptr ss:[ebp-01ch],eax
IsNull:
mov eax,dword ptr ss:[ebp-01ch]
mov ebx,eax
mov edi,dword ptr ss:[ebp-10h]
shl edi,2
cmp dword ptr ds:[ebx+edi],0
jz r1
mov eax,dword ptr ds:[ebx+edi]
test eax,80000000h ;判断最高位是否为1
jz IsRva
and eax,7fffffffh
mov edx,eax
jmp GetProc
IsRva:
add eax,dword ptr ss:[ebp-4]
lea edx,dword ptr ds:[eax+2]
GetProc:
push edx
push dword ptr ss:[ebp-18h]
call dword ptr ss:[ebp-0ch]
mov ebx,dword ptr ss:[ebp-01ch]
mov esi,dword ptr ss:[ebp-10h]
shl esi,2
mov dword ptr ds:[ebx+esi],eax
inc dword ptr ss:[ebp-10h]
jmp IsNull
r1:
add dword ptr ss:[ebp-14h],14h
jmp r2
clPe: ;抹除PE指纹
cld
mov edi,dword ptr ss:[ebp-4]
xor eax,eax
mov ebx,dword ptr ss:[ebp+8]
mov ecx,dword ptr ss:[ebx+14h]
shr ecx,2
rep stosd
push 0
push 1
push dword ptr ss:[ebp-4]
mov eax,dword ptr ss:[ebx+4]
add eax,dword ptr ss:[ebp-4]
call eax
leave
ret
end start
运行效果
|
-
调试器里看不到dll的痕迹
-
用法及效果
免费评分
-
查看全部评分
|