(本文实现 windows核心编程 里面没有实现的 Dll注入)
1. 让进程生成一个被挂起的子进程
2. 从.exe模块的文件头中取得主线程起始内存地址
3. 将位于该内存地址处的机器指令保存起来
4. 强制将一些手工编写的机器指令写入到该内存地址.这些指令调用LoadLibrary装载一个Dll
5. 恢复子进程运行,让这些指令得到执行
6. 把保存起来的指令恢复到起始处
7. 让进程从起始地址继续执行,就好像什么都没有发生过一样
汗!打了这么多子累死了
(注意了,这里用的方法要比书上说的好一些. 书上说只能是子进程才行! 本文的办法不是子进程照样能注入)
// 代码大致说明
1. 修理shellcode
2. 创建进程(打开其它进程,暂停其运行也行)
3. 写入shellcode到进程, 挂住线程将要执行的位置(不管是什么指令都可以挂钩,因为后shelcodel恢复钩子),
保存挂钩处代码(为5个字节)到shellcode
(下面的代码只是勾住入口点)
4. 释放线程
//
//
//shellcode 执行 流程
//
//加载 你要注入的Dll
IAT->_LoadLibraryA((LPCSTR)_relocal(inject_dllname));
// 把堆栈中的返回点减5 (通过 堆栈参数 &argc -1 就是 ret 指令返回点的EIP)
unsigned long *entry_esp = (unsigned long *)&argc;
entry_esp --;
// EIP 减 5 (就能返回到原来才行执行的位置了)
*entry_esp -= 5;
// 恢复挂钩处得代码
void *pentry = (void *)(*entry_esp);
void *entry_c = (void *)_relocal(original_entry);
IAT->_WriteProcessMemory(
IAT->_GetCurrentProcess(), pentry, entry_c, 5, NULL);
//==========================================================================
// shellcode 部分代码
// 具体编写参考 yuange 2001年的c语言直接直接生成 shellcode, 你用汇编也行
//===============================================================================
// manal jmp to main()
char jmp_main[] = "\xE9\0\0\0\0";
char original_entry[] = "original_entry";
char inject_dllname[0x100] = "inject_dllname";
char loadlibrary_str[] = "LoadLibraryA";
int main(int argc, char* argv[])
{
_IMPORT_AT *IAT = (_IMPORT_AT *)_relocal(&g_IAT);
// Initialize import address table by loadlibraryA
InitializeIAT(_GetLoadLibraryA());
IAT->_LoadLibraryA((LPCSTR)_relocal(inject_dllname));
// sub return point, 5
unsigned long *entry_esp = (unsigned long *)&argc;
entry_esp --;
*entry_esp -= 5;
// revert hooked entry point code
void *pentry = (void *)(*entry_esp);
void *entry_c = (void *)_relocal(original_entry);
IAT->_WriteProcessMemory(
IAT->_GetCurrentProcess(), pentry, entry_c, 5, NULL);
return 0;
}
//==========================================================================
//
// 注入完整代码
//
//=======================================================================
CWinApp theApp;
using namespace std;
UCHAR *_FixShellcode(LPCSTR lpszInjectFileName, ULONG *pEntry, LPCSTR lpszShellFileName, ULONG *pSize)
{
//
// lpszInjectFileName
//
HMODULE hModule = LoadLibraryEx(
lpszInjectFileName, NULL, DONT_RESOLVE_DLL_REFERENCES);
ASSERT(hModule);
unsigned char *Image = (unsigned char *)hModule;
PIMAGE_DOS_HEADER pimg_dos_h = (PIMAGE_DOS_HEADER)Image;
PIMAGE_NT_HEADERS pimg_nt_h = (PIMAGE_NT_HEADERS)
(Image+pimg_dos_h->e_lfanew);
ULONG AddressOfEntryPoint = pimg_nt_h->OptionalHeader.ImageBase +
pimg_nt_h->OptionalHeader.AddressOfEntryPoint;
char entrycode[5];
memcpy(entrycode, (Image+pimg_nt_h->OptionalHeader.AddressOfEntryPoint), 5);
/// 汗! 调试的 时候居然会崩溃 在 ntdll
FreeLibrary(hModule);
//
// lpszShellFileName 读取编译好的 Shellcode
//
HMODULE hModule2 = LoadLibraryEx(
lpszShellFileName, NULL, DONT_RESOLVE_DLL_REFERENCES);
ASSERT(hModule2);
UCHAR *Image2 = (UCHAR *)hModule2;
PIMAGE_DOS_HEADER pImageDosHeader = (PIMAGE_DOS_HEADER)Image2;
PIMAGE_NT_HEADERS pImageNtHeader = (PIMAGE_NT_HEADERS)
(Image2 + pImageDosHeader->e_lfanew);
PIMAGE_SECTION_HEADER pImageSecHeader = (PIMAGE_SECTION_HEADER)
(Image2 + pImageDosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS));
ULONG sizeOfShell = pImageSecHeader->SizeOfRawData;
UCHAR *c = new UCHAR[sizeOfShell];
UCHAR *sectionAddress = (UCHAR *)
(Image2 + pImageSecHeader->VirtualAddress);
ULONG EntryOff = pImageNtHeader->OptionalHeader.AddressOfEntryPoint -
pImageSecHeader->VirtualAddress;
memcpy(c, sectionAddress, sizeOfShell);
FreeLibrary(hModule2);
//
// Fix shell code
//
char *c2 = (char *)c;
ASSERT(c2[0] == '\xE9');
*(ULONG *)(&c2[1]) = EntryOff - 5;
// For debug
//c2[0] = '\xCC';
while(1)
{
if (stricmp(c2, "original_entry") == 0)
{
//保存挂钩处代码到 shellcode
memcpy(c2, entrycode, 5);
}
if (stricmp(c2, "inject_dllname") == 0)
{
//复制 dll 完整路径 !..............................................
memset(c2, 0x0,0x100);
strcpy(c2, "dll.dll");
break;
}
c2 ++;
}
//
*pEntry = AddressOfEntryPoint;
*pSize = sizeOfShell;
return c;
}
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
const char szApplicationName[MAX_PATH] = "C:\\Program Files\\汗!.exe";
char lpszModuleFileName[MAX_PATH] = {0};
GetModuleFileNameA(NULL, lpszModuleFileName, MAX_PATH);
CString szModuleFileName(lpszModuleFileName);
szModuleFileName = szModuleFileName.Left(szModuleFileName.ReverseFind('\\'));
// Shellcode PE 文件
szModuleFileName += "\\c.bin";
UCHAR *c = NULL;
ULONG AddressOfEntryPoint;
ULONG len ;
c = _FixShellcode(szApplicationName, &AddressOfEntryPoint, szModuleFileName, &len);
//
//
//
char szCommandLine[0x400] = {0};
strcpy(szCommandLine, szApplicationName);
STARTUPINFO StartupInfo = {0};
StartupInfo.cb = sizeof(STARTUPINFO);
PROCESS_INFORMATION ProcessInformation;
//
// 前面说了 你打开进程 暂停 获取 .Eip 也行 挂钩处发生变化!
//
if (!CreateProcess(szApplicationName, szCommandLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &StartupInfo, &ProcessInformation))
{
//没释放资源 懒
return FALSE;
}
LPVOID dst = VirtualAllocEx(ProcessInformation.hProcess, NULL, len, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
// call
char call_c[5] = "\xE8";
*((ULONG *)&call_c[1]) = (ULONG)dst - AddressOfEntryPoint - 5;
WriteProcessMemory(ProcessInformation.hProcess, (LPVOID)AddressOfEntryPoint, call_c, 5, NULL);
WriteProcessMemory(ProcessInformation.hProcess, (LPVOID)dst, c, len, NULL);
BOOL bRetCode = ResumeThread(ProcessInformation.hThread);
CloseHandle(ProcessInformation.hProcess);
CloseHandle(ProcessInformation.hThread);
delete[] c;
return nRetCode;
}
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课