DLL的11种注入方法 (2)

淡若清风 分享 2020-06-21 下载文档

乘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;


DLL的11种注入方法 (2).doc 将本文的Word文档下载到电脑

下一篇:以青春梦想为主题的晚会串词

相关推荐
相关阅读
本类排行
× 游客快捷下载通道(下载后可以自由复制和排版)

下载本文档需要支付 7 元

支付方式:

开通VIP包月会员 特价:29元/月

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信:xxxxxx QQ:xxxxxx