乘2
GetMem(pszLibAFilename, Length(DllFullPath) * 2 + 1);
// 之所以要转换成 WideChar, 是因为当DLL位于有中文字符 的路径下时不会出错
StringToWideChar(DllFullPath, pszLibAFilename, Length (DllFullPath) * 2 + 1);
// 计算 pszLibAFilename 的长度,注意,是以字节为单元的 长度
memSize := (1 + lstrlenW(pszLibAFilename)) * sizeof (WCHAR);
//使用VirtualAllocEx函数在远程进程的内存地址空间分配 DLL文件名空间
pszLibFileRemote := VirtualAllocEx( hRemoteProcess, nil, memSize, MEM_COMMIT, PAGE_READWRITE);
if Assigned(pszLibFileRemote) then begin
//使用WriteProcessMemory函数将DLL的路径名写入到远程 进程的内存空间
if WriteProcessMemory(hRemoteProcess,
pszLibFileRemote, pszLibAFilename, memSize, WriteSize) and (WriteSize = memSize) then begin
// 计算GetModuleHandleW的入口地址 pfnStartAddr := GetProcAddress(LoadLibrary ('Kernel32.dll'), 'GetModuleHandleW');
//使目标进程调用GetModuleHandleW,获得DLL在目标进 程中的句柄
hRemoteThread := CreateRemoteThread (hRemoteProcess, nil, 0,
pfnStartAddr, pszLibFileRemote, 0, lpThreadId); // 等待GetModuleHandle运行完毕
WaitForSingleObject(hRemoteThread,INFINITE);
// 获得GetModuleHandle的返回值,存在dwHandle变量中 GetExitCodeThread(hRemoteThread, dwHandle);
// 计算FreeLibrary的入口地址
pfnStartAddr := GetProcAddress(LoadLibrary ('Kernel32.dll'), 'FreeLibrary');
// 使目标进程调用FreeLibrary,卸载DLL hRemoteThread := CreateRemoteThread
(hRemoteProcess, nil, 0,
pfnStartAddr, Pointer(dwHandle), 0, lpThreadId); // 等待FreeLibrary卸载完毕
WaitForSingleObject( hRemoteThread, INFINITE );
// 如果执行成功返回 True; if hRemoteProcess<>0 then result := TRUE;
// 释放目标进程中申请的空间
VirtualFreeEx(hRemoteProcess, pszLibFileRemote, Length(DllFullPath)+1, MEM_DECOMMIT); // 释放句柄
CloseHandle(hRemoteThread); end; end; finally
// 释放句柄
CloseHandle(hRemoteProcess); end; end; end;
第二种方法:
采用CreateProcess的方法,实现起来比较复杂,但没有上面几种方法的局限性。且可以用其他工
具(VC等)调试注入的DLL。下面进行介绍。
原理如下:
1. 用CreateProcess(CREATE_SUSPENDED)启动目标进程。
2. 找到目标进程的入口,用ImageHlp中的函数可以实现。
3. 将目标进程入口的代码保存起来。
4. 在目标进程的入口写入LoadLibrary(MyDll)实现Dll的注入。
5. 用ResumeThread运行目标进程。
6. 目标进程就运行了LoadLibrary(MyDll),实现DLL的注入。
7. 目标进程运行完LoadLibrary(MyDll)后,将原来的代码写回目标进程的入口。
8. 目标进程Jmp至原来的入口,继续运行程序。
从原理上可以看出,DLL的注入在目标进程的开始就运行了,而且不是用Debug的方案,这样,就
没有上面方案的局限性了。该方案的关键在6,7,8三步,实现方法需要监视进程和DLL合作。下
面,结合代码进行分析。
在监视进程中,创建FileMapping,用来保存目标进程的入口代码,同时保证DLL中可以访问。在
第7步实现将原目标代码写回目标进程的入口。
// 监视程序和DLL共用的结构体
#pragma pack (push ,1) // 保证下面的结构体采用BYTE对齐(必须)
typedef struct {
BYTE int_PUSHAD; // pushad 0x60
BYTE int_PUSH; // push &szDLL 0x68
DWORD push_Value; // &szDLL = \的path
BYTE int_MOVEAX; // move eax &LoadLibrary 0xB8
DWORD eax_Value; // &LoadLibrary
WORD call_eax; // call eax 0xD0FF(FF D0) (LoadLibrary
(\
BYTE jmp_MOVEAX; // move eax &ReplaceOldCode 0xB8
DWORD jmp_Value; // JMP的参数
WORD jmp_eax; // jmp eax 0xE0FF(FF E0) jmp ReplaceOldCode;
char szDLL[MAX_PATH]; // \的FullPath
}INJECT_LOADLIBRARY_CODE, *LPINJECT_CODE;
#pragma pack (pop , 1)
上面结构体的代码为汇编代码,对应的汇编为:
pushad
push szDll
mov eax, &LoadLibraryA
call eax // 实现调用LoadLibrary(szDll)的代码
mov eax, oldentry
jmp eax // 实现在LoadLibrary运行完后, 跳至目标进程的入口继续运行
// FileMaping的结构体
typedef struct {
LPBYTE lpEntryPoint; // 目标进程的入口地址
BYTE oldcode[sizeof(INJECT_CODE)]; // 目标进程的代码保存
}SPY_MEM_SHARE, * LPSPY_MEM_SHARE;
准备工作:
第一步:用CreateProcess(CREATE_SUSPENDED)启动目标进程。
CreateProcessA(0, szRunFile, 0, 0, FALSE, CREATE_SUSPENDED
0, NULL, &stInfo,
&m_proInfo) ;
// 用CreateProcess启动一个暂停的目标进程
// 找到目标进程的入口点,函数如下
第二步:找到目标进程的入口,用ImageHlp中的函数可以实现。
pEntryPoint = GetExeEntryPoint(szRunFile);
LPBYTE GetExeEntryPoint(char *filename) {
PIMAGE_NT_HEADERS pNTHeader;
DWORD pEntryPoint;
PLOADED_IMAGE pImage;
pImage = ImageLoad(filename, NULL);
if(pImage == NULL)
return NULL;
pNTHeader = pImage->FileHeader;
搜索“diyifanwen.net”或“第一范文网”即可找到本站免费阅读全部范文。收藏本站方便下次阅读,第一范文网,提供最新小学教育DLL的11种注入方法 (2)全文阅读和word下载服务。
相关推荐: