频道分类

delphi 进程隐藏的若干方法

作者:admin 来源:未知 日期:2010/5/28 13:55:45 人气: 标签:

 一、最为古老的DLL注入方法。
虽说古老,但也经历了不少变动,最初的win9X的系统没有Psapi,没有进程快照,所以一般是三级跳。跳啊跳……NT下可以直接用 OpenProcess打开进程(打不开的话,提权到Debug权限),利用LoadLibrary,并且申请远程地址空间,然后把DLL注入到目标 EXE进程当中,可谓省时省力,这也是目前应用作为普遍的方法之一。

典型代码:
view plaincopy to clipboardprint?
function AttachToProcess(const HostFile, GuestFile: string; const PID: DWORD = 0): DWORD;
var
hRemoteProcess: THandle;
dwRemoteProcessId: DWORD;
cb: DWORD;
pszLibFileRemote: Pointer;
iReturnCode: Boolean;
TempVar: DWORD;
pfnStartAddr: TFNThreadStartRoutine;
pszLibAFilename: PwideChar;
begin
Result := 0;
EnabledDebugPrivilege(True);
Getmem(pszLibAFilename, Length(GuestFile) * 2 + 1);
StringToWideChar(GuestFile, pszLibAFilename, Length(GuestFile) * 2 + 1);
if PID > 0 then
dwRemoteProcessID := PID
else
FindAProcess(HostFile, False, dwRemoteProcessID);
hRemoteProcess := OpenProcess(PROCESS_CREATE_THREAD + {允许远程创建线程}
PROCESS_VM_OPERATION + {允许远程VM操作}
PROCESS_VM_WRITE, {允许远程VM写}
FALSE, dwRemoteProcessId);
cb := (1 + lstrlenW(pszLibAFilename)) * sizeof(WCHAR);
pszLibFileRemote := PWIDESTRING(VirtualAllocEx(hRemoteProcess, nil, cb, MEM_COMMIT, PAGE_READWRITE));
TempVar := 0;
iReturnCode := WriteProcessMemory(hRemoteProcess, pszLibFileRemote, pszLibAFilename, cb, TempVar);
if iReturnCode then
begin
pfnStartAddr := GetProcAddress(GetModuleHandle('Kernel32'), 'LoadLibraryW');
TempVar := 0;
Result := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, pszLibFileRemote, 0, TempVar);
end;
Freemem(pszLibAFilename);
end;
function AttachToProcess(const HostFile, GuestFile: string; const PID: DWORD = 0): DWORD;
var
hRemoteProcess: THandle;
dwRemoteProcessId: DWORD;
cb: DWORD;
pszLibFileRemote: Pointer;
iReturnCode: Boolean;
TempVar: DWORD;
pfnStartAddr: TFNThreadStartRoutine;
pszLibAFilename: PwideChar;
begin
Result := 0;
EnabledDebugPrivilege(True);
Getmem(pszLibAFilename, Length(GuestFile) * 2 + 1);
StringToWideChar(GuestFile, pszLibAFilename, Length(GuestFile) * 2 + 1);
if PID > 0 then
dwRemoteProcessID := PID
else
FindAProcess(HostFile, False, dwRemoteProcessID);
hRemoteProcess := OpenProcess(PROCESS_CREATE_THREAD + {允许远程创建线程}
PROCESS_VM_OPERATION + {允许远程VM操作}
PROCESS_VM_WRITE, {允许远程VM写}
FALSE, dwRemoteProcessId);
cb := (1 + lstrlenW(pszLibAFilename)) * sizeof(WCHAR);
pszLibFileRemote := PWIDESTRING(VirtualAllocEx(hRemoteProcess, nil, cb, MEM_COMMIT, PAGE_READWRITE));
TempVar := 0;
iReturnCode := WriteProcessMemory(hRemoteProcess, pszLibFileRemote, pszLibAFilename, cb, TempVar);
if iReturnCode then
begin
pfnStartAddr := GetProcAddress(GetModuleHandle('Kernel32'), 'LoadLibraryW');
TempVar := 0;
Result := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, pszLibFileRemote, 0, TempVar);
end;
Freemem(pszLibAFilename);
end;
二、EXE注入。
比起上面的方法,更为暴力,直接将EXE作为一个模块强行附加到其它进程上面,由于注入的是EXE文件,需要考虑更多的东西,比如指针,比如映像基址,比如对应的EXE的内存映像的读写。当然,远程线程这一步是不可少的。
view plaincopy to clipboardprint?
procedure Inject(ProcessHandle: longword; EntryPoint: pointer);
var
Module, NewModule: Pointer;
Size, BytesWritten, TID: longword;
Begin
// 这里得到的值为一个返回指针型变量,指向内容包括进程映像的基址
Module := Pointer(GetModuleHandle(nil));
/ /得到内存映像的长度
Size:=PImageOptionalHeader
(Pointer(integer(Module)+PImageDosHeader(Module)._lfanew+SizeOf(dword)+SizeOf(TImageFileHeader))).SizeOfImage;
// 在Exp进程的内存范围内分配一个足够长度的内存
VirtualFreeEx(ProcessHandle, Module, 0, MEM_RELEASE);
//确定起始基址和内存映像基址的位置
NewModule := VirtualAllocEx(ProcessHandle, Module, Size, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//开始写内存
WriteProcessMemory(ProcessHandle, NewModule, Module, Size, BytesWritten);
//创建远程线程
CreateRemoteThread(ProcessHandle, nil, 0, EntryPoint, Module, 0, TID);
end;
procedure Inject(ProcessHandle: longword; EntryPoint: pointer);
var
Module, NewModule: Pointer;
Size, BytesWritten, TID: longword;
Begin
// 这里得到的值为一个返回指针型变量,指向内容包括进程映像的基址
Module := Pointer(GetModuleHandle(nil));
/ /得到内存映像的长度
Size:=PImageOptionalHeader
(Pointer(integer(Module)+PImageDosHeader(Module)._lfanew+SizeOf(dword)+SizeOf(TImageFileHeader))).SizeOfImage;
// 在Exp进程的内存范围内分配一个足够长度的内存
VirtualFreeEx(ProcessHandle, Module, 0, MEM_RELEASE);
//确定起始基址和内存映像基址的位置
NewModule := VirtualAllocEx(ProcessHandle, Module, Size, MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE);
//开始写内存
WriteProcessMemory(ProcessHandle, NewModule, Module, Size, BytesWritten);
//创建远程线程
CreateRemoteThread(ProcessHandle, nil, 0, EntryPoint, Module, 0, TID);
end;
这种方法和DLL注入本质上没有太大差别,都是占了别人的坑,一旦目标EXE完蛋,他们也跟着88了,所以一些牛人又想出了新的方法。
三、和谐任务管理器。
这个不算什么进程隐藏的方法,不过还是说下,大多情况下,我们在任务管理器里面看进程,如果把任务管理器和谐掉,让它不显示这个进程就行了。简单来说就是过滤。
实现起来比较简单,找到任务管理器的句柄,获得目标Pid,读取进程名称,如果和目标进程相同,然后就使用WriteprocessMemroy把 taskmgr相应的进程的名称改掉,比如把a.exe改成explorer.exe……当然,出现了几个explorer会让人产生怀疑的……而且这也不算隐藏,最多只是一个伪装……
由于这种方法比较鸡肋,所以不给代码了,有兴趣的朋友自己试试吧……
四、HOOK API(EProcess双向链表)
网上有流传很广的hideprocess.pas,就是利用EProcess的结构。双向链表,摘除链上的相应的两个偏移量,$88和$8C,这两个偏移量地址,然后就能隐藏进程了,C代码如下:
http://www.codeproject.com/KB/system/preventclose.aspx
有基础的朋友可以看看,由于EProcess比较复杂,估计Delphi坛子里玩Ring0的也不多,所以也不多说了,如果想自己探索,有两个建议:1、学好汇编。2、善于利用WinDBG调试。
五、驱动……NtQuerySystemInformation
Native API。内核啊内核……Liunx内核BT,Windows更抓狂……这也是方法之一,由于驱动大多是C编写的,用WDK的人很多,所以这方法大多可以搜到相应的资料,只不过Delphi不擅长写驱动,所以知道这种方法的Delphier一般很少,由于相关资料太少,给个地址吧……有部分源码,不过需要注册……
http://www.kmdkit4d.net/dispbbs.do?boardId=8&ID=52