function InjectDll(const DllFullPath : string;
const dwRemoteProcessId : Cardinal): boolean;
var
hRemoteProcess, hRemoteThread: THANDLE;
pszLibFileRemote : Pointer;
pszLibAFilename: PwideChar;
pfnStartAddr : TFNThreadStartRoutine;
memSize, WriteSize, lpThreadId : Cardinal;
begin
result := FALSE;
// 调整权限,使程序可以访问其他进程的内存空间
if EnableDebugPrivilegeNT<>0 then
begin
//打开远程线程 PROCESS_ALL_ACCESS 参数表示打开所有的权限
hRemoteProcess := OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwRemoteProcessId );
try
// 为注入的dll文件路径分配内存大小,由于为WideChar,故要乘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
lpThreadId := 0;
// 计算LoadLibraryW的入口地址
pfnStartAddr := GetProcAddress(LoadLibrary('Kernel32.dll'), 'LoadLibraryW');
// 启动远程线程LoadLbraryW,通过远程线程调用创建新的线程
hRemoteThread := CreateRemoteThread(hRemoteProcess, nil, 0,
pfnStartAddr, pszLibFileRemote, 0, lpThreadId);
// 如果执行成功返回 True;
if (hRemoteThread <> 0) then
result := TRUE;
// 释放句柄
CloseHandle(hRemoteThread);
end;
end;
finally
// 释放句柄
CloseHandle(hRemoteProcess);
end;
end;
end;
function UnInjectDll(const DllFullPath : string;
const dwRemoteProcessId : Cardinal) : Boolean;
// 进程注入和取消注入其实都差不多,只是运行的函数不同而已
var
hRemoteProcess, hRemoteThread : THANDLE;
pszLibFileRemote : pchar;
pszLibAFilename: PwideChar;
pfnStartAddr : TFNThreadStartRoutine;
memSize, WriteSize, lpThreadId, dwHandle : Cardinal;
begin
result := FALSE;
// 调整权限,使程序可以访问其他进程的内存空间
if EnableDebugPrivilegeNT<>0 then
begin
//打开远程线程 PROCESS_ALL_ACCESS 参数表示打开所有的权限
hRemoteProcess := OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwRemoteProcessId );
try
// 为注入的dll文件路径分配内存大小,由于为WideChar,故要乘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;
//其实也不需要的... 反正是全局钩子,放进去玩也不错
//可以照QQ之类的东西搞个密码探测器+发送的做试验
评论0