找文章看了一下, 讲的很好, 但是地址没了…尴尬, 03年的技术, 大致内容就是介绍了两种注入技术, 一个为常规的远程线程注入, 另一个就是内存注入. 只不过文章思路是只插入一段代码, 也就是编写shellcode. 而无模块注入则是将模块整体以内存写入的形式加载实现隐藏 .
杀软依然秒杀…但是我封装起来写后就检测不到, 特征码竟然消失了…
思路是将自己复制一份加载到目标进程中, 即注入进程和寄生程序是一个东西.不过想想也知道, 注入dll也是一个原理, 无非是拉伸之后再贴到目标进程, 最后依然是起远程线程设置入口点.
但重点在于, 寄生程序IAT中的地址与目标进程的地址可能不一致, 或者没有加载相关dll, 这个时候就要根据目标进程的IAT修复寄生进程的IAT.
在写这个的时候遇到了一些问题如下:
实在是过于麻烦了…带着这个问题, 我们找到了如下答案
又因为每个程序都用到了LoadLibrary和GetProcAddress那么就可以放心大胆的用了.
此时进入目标进程, 线程函数首先需要修复IAT表, 绝对要注意, 进入了线程函数之后修复IAT之前, 当然包括修复IAT都不可以使用非系统必要dll的函数.
给出主体与修复重定位和IAT表的代码
//通过GetCurrent得到的句柄是假句柄, 只对当前进程有用, 无需CloseHandle;
//获取自身Buffer, 当然这里完全可以换成从文件读一个dll然后展开注入, 思路一样
Process::GetProcInfo(&curPi);
sizeOfImage = Pe::GetSizeOfImage(::GetModuleHandleA(NULL));
pImageBuffer = malloc(sizeOfImage);
memcpy(pImageBuffer, ::GetModuleHandleA(NULL),sizeOfImage);
//申请空间
hostPi.hProcess = Process::OpenProcessM(hostName);
if (!(allocBaseAddr = Process::VirtualAllocate(
hostPi.hProcess,
NULL,
sizeOfImage,
PAGE_EXECUTE_READWRITE
)))
return NULL;
//可能出现无重定位的exe, 直接返回失败
if (!Pe::RebaseRelocation(pImageBuffer, (DWORD)allocBaseAddr))
{
::VirtualFreeEx(hostPi.hProcess, allocBaseAddr, NULL, MEM_RELEASE);
return NULL;
}
//写入修复重定位的Buffer, 并计算起始地址开远程线程
::WriteProcessMemory(hostPi.hProcess, allocBaseAddr, pImageBuffer, sizeOfImage, NULL);
crtStartUp = (LPTHREAD_START_ROUTINE)((DWORD)allocBaseAddr + (DWORD)injectThread - (DWORD)GetModuleHandle(NULL));
hostPi.hThread = ::CreateRemoteThread(
hostPi.hProcess,
NULL,
NULL,
crtStartUp,
allocBaseAddr,
NULL,
NULL);
//释放句柄, 栈空间
::WaitForSingleObject(hostPi.hThread, INFINITE);
//如果为完全释放, 大小必须为空, 系统会按照分配时的大小释放空间
::VirtualFreeEx(hostPi.hProcess, allocBaseAddr, NULL, MEM_RELEASE);
free(pImageBuffer);
Process::CloseHandles(hostPi);
void InjectFunc()
{
char szTemp[256] = { 0 };
printf("测试程序..如果IAT未修复则无法运行.\n");
//这两行程序可以测试IAT是否修复成功, 字符串初始化操作调用memset
for (int i = 0; i < 3; i++)
MessageBoxA(0, 0, "注入成功", 0);
}
DWORD WINAPI ThreadProc(LPVOID lparams)
{
if (!Pe::RestoreIAT(lparams))
{
MessageBoxA(NULL, NULL, "修复重定位失败!", NULL);
return -1;
}
InjectFunc();
return 1;
}
int main()
{
CHAR hostName[] = "demo.exe";
injector::InjectThrowMemory(hostName, (LPTHREAD_START_ROUTINE)(ThreadProc));
printf("内存注入线程结束, 任意键退出.\n");
system("pause");
return 0;
}
PIMAGE_NT_HEADERS Pe::GetNtHeaders(LPVOID pBuffer)
{
return (PIMAGE_NT_HEADERS)((DWORD)pBuffer + *((DWORD*)((DWORD)(pBuffer)+0x3c)));
}
BOOL Pe::RebaseRelocation(LPVOID pImageBuffer, DWORD newImageBase)
{
DWORD rvaBaseRelocation = 0;
PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
PIMAGE_BASE_RELOCATION pBaseRelocation = NULL;
PIMAGE_NT_HEADERS pNtHeaders = NULL;
pNtHeaders = GetNtHeaders(pImageBuffer);
pDataDirectory = pNtHeaders->OptionalHeader.DataDirectory;
rvaBaseRelocation = (*(pDataDirectory + 5)).VirtualAddress;
if (!rvaBaseRelocation)
{
MessageBoxA(NULL, "软件无重定位!!! 无法更改ImageBase", "Error", NULL);
return FALSE;
}
pBaseRelocation = (PIMAGE_BASE_RELOCATION)((DWORD)pImageBuffer + rvaBaseRelocation);
DWORD foaOfData = 0;
DWORD rvaOfData = 0;
DWORD currentBlockItems = 0;
DWORD foaOfBlock = 0;
DWORD differenceOfImageBase = 0;
DWORD addressOf_rvaOfData = 0;
DWORD* pFarAddress = NULL;
differenceOfImageBase = newImageBase - pNtHeaders->OptionalHeader.ImageBase;
pNtHeaders->OptionalHeader.ImageBase = newImageBase;
while (pBaseRelocation->SizeOfBlock)
{
//要修改的数据大表在文件中的偏移 大表 + word 型偏移
foaOfBlock = (DWORD)pBaseRelocation - (DWORD)pImageBuffer;
currentBlockItems = (pBaseRelocation->SizeOfBlock - 8) / 2; //word 表示
addressOf_rvaOfData = pBaseRelocation->VirtualAddress;
while (--currentBlockItems)
{
rvaOfData = ((*(WORD*)(foaOfBlock + (DWORD)pImageBuffer + 8)) & 0x0fff) + addressOf_rvaOfData;
pFarAddress = (DWORD*)(rvaOfData + (DWORD)pImageBuffer);
*pFarAddress += differenceOfImageBase;
foaOfBlock += 2;
}
pBaseRelocation = (PIMAGE_BASE_RELOCATION)((DWORD)pBaseRelocation + pBaseRelocation->SizeOfBlock);
}
return TRUE;
}
BOOL Pe::RestoreIAT(LPVOID pImageBuffer)
{
PIMAGE_NT_HEADERS pNtHeaders = NULL;
PIMAGE_IMPORT_DESCRIPTOR pImport = NULL;
HMODULE hModule = 0;
DWORD rvaImport = 0;
DWORD rvaName = 0;
DWORD rvaOriginalThunk = 0;
DWORD rvaFirstThunk = 0;
DWORD originalValue = 0;
LPVOID pFirstValue = NULL;
DWORD ordinalOfFunc = 0;
CHAR* pFuncNameAddr = NULL;
DWORD oldProtect = 0;
pNtHeaders = GetNtHeaders(pImageBuffer);
rvaImport = (*(pNtHeaders->OptionalHeader.DataDirectory + 1)).VirtualAddress;
pImport = (PIMAGE_IMPORT_DESCRIPTOR)((DWORD)pImageBuffer + rvaImport);
//以OriginalFirstThunk为基准找到函数名/序号
//将新值补充到FirstThunk对应的ThunkValue中
while (rvaOriginalThunk = *((DWORD*)pImport))
{
rvaFirstThunk = *((DWORD*)pImport + 4);
rvaName = pImport->Name;
if (!(hModule = ::LoadLibraryA((CHAR*)(DWORD)pImageBuffer + rvaName)))
{
//这一句不能加, printf 的dll可能没加载导致程序异常退出.
//printf("加载dll失败 LastError: %d", GetLastError());
return FALSE;
}
//printf("DLL's name: %s\n", (char*)((DWORD)pImageBuffer + rvaName));
while (originalValue = *(DWORD*)((DWORD)pImageBuffer + (DWORD)rvaOriginalThunk))
{
pFirstValue = (LPVOID)((DWORD)pImageBuffer + rvaFirstThunk);
VirtualProtect(pFirstValue, 4, PAGE_READWRITE, &oldProtect);
if ((originalValue & 0x80000000) == 0x80000000)
{
ordinalOfFunc = (originalValue & 0x7FFFFFFF);
*(DWORD*)pFirstValue = (DWORD)GetProcAddress(hModule, MAKEINTRESOURCEA(ordinalOfFunc));
}
else
{
pFuncNameAddr = (CHAR*)((DWORD)pImageBuffer + originalValue + 2);
*(DWORD*)pFirstValue = (DWORD)GetProcAddress(hModule, pFuncNameAddr);
}
rvaOriginalThunk += 4;
}
pImport++;
}
return TRUE;
}