问题,当调用StartHook后,打开cmd.exe 等不包含界面的程序则能成功ShowMessage;
如果包含界面的则不能打开。现在把代码写出来,请帮忙看一下,问题出在哪?
main.dll代码library main;
uses
sysutils,
Windows,
Classes,
Dialogs,
Forms,
tlhelp32,
unitHook in 'unitHook.pas';{$R *.res}var
hhk:HHOOK;
Hook: array[0..1] of TNtHookClass;
vspas:Bool;
Curfile:String[255];
htd:Cardinal;
DllInstall:Bool;
{--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--}
procedure GetMyProcessID(const AFilename: string; const PathMatch: Boolean; var ProcessID: DWORD);
var
lppe: TProcessEntry32;
SsHandle: Thandle;
FoundAProc, FoundOK: boolean;
begin
ProcessID :=0;
{ 创建系统快照 }
SsHandle := CreateToolHelp32SnapShot(TH32CS_SnapProcess, 0); { 取得快照中的第一个进程 }
{ 一定要设置结构的大小,否则将返回False }
lppe.dwSize := sizeof(TProcessEntry32);
FoundAProc := Process32First(Sshandle, lppe);
while FoundAProc do
begin
{ 进行匹配 }
if PathMatch then
FoundOK := AnsiStricomp(lppe.szExefile, PChar(AFilename)) = 0
else
FoundOK := AnsiStricomp(PChar(ExtractFilename(lppe.szExefile)), PChar(ExtractFilename(AFilename))) = 0;
if FoundOK then
begin
ProcessID := lppe.th32ProcessID;
break;
end;
{ 未找到,继续下一个进程 }
FoundAProc := Process32Next(SsHandle, lppe);
end;
CloseHandle(SsHandle);
end;
{ 设置权限 }
function EnabledDebugPrivilege(const Enabled : Boolean) : Boolean;
var
hTk : THandle; { 打开令牌句柄 }
rtnTemp : Dword; { 调整权限时返回的值 }
TokenPri : TOKEN_PRIVILEGES;
const
SE_DEBUG = 'SeDebugPrivilege'; { 查询值 }
begin
Result := False;
{ 获取进程令牌句柄,设置权限 }
if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,hTk)) then
begin
TokenPri.PrivilegeCount := 1;
{ 获取Luid值 }
LookupPrivilegeValue(nil,SE_DEBUG,TokenPri.Privileges[0].Luid); if Enabled then
TokenPri.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
else
TokenPri.Privileges[0].Attributes := 0; rtnTemp := 0;
{ 设置新的权限 }
AdjustTokenPrivileges(hTk,False,TokenPri,sizeof(TokenPri),nil,rtnTemp); Result := GetLastError = ERROR_SUCCESS;
CloseHandle(hTk); end;
end;{ 注入远程进程 }
function InjectTo(const Host, Guest: string; const PID: DWORD = 0): DWORD;
var
{ 被注入的进程句柄,进程ID}
hRemoteProcess: THandle;
dwRemoteProcessId: DWORD; { 写入远程进程的内容大小 }
memSize: DWORD; { 写入到远程进程后的地址 }
pszLibFileRemote: Pointer; iReturnCode: Boolean;
TempVar: DWORD; { 指向函数LoadLibraryW的地址 }
pfnStartAddr: TFNThreadStartRoutine; { dll全路径,需要写到远程进程的内存中去 }
pszLibAFilename: PwideChar;
begin
Result := 0;
{ 设置权限 }
EnabledDebugPrivilege(True); { 为注入的dll文件路径分配内存大小,由于为WideChar,故要乘2 }
Getmem(pszLibAFilename, Length(Guest) * 2 + 1);
StringToWideChar(Guest, pszLibAFilename, Length(Guest) * 2 + 1); { 获取进程ID }
if PID > 0 then
dwRemoteProcessID := PID
else
GetMyProcessID(Host, False, dwRemoteProcessID); { 取得远程进程句柄,具有写入权限}
hRemoteProcess := OpenProcess(PROCESS_CREATE_THREAD + {允许远程创建线程}
PROCESS_VM_OPERATION + {允许远程VM操作}
PROCESS_VM_WRITE, {允许远程VM写}
FALSE, dwRemoteProcessId); { 用函数VirtualAllocex在远程进程分配空间,并用WriteProcessMemory中写入dll路径 }
memSize := (1 + lstrlenW(pszLibAFilename)) * sizeof(WCHAR);
pszLibFileRemote := PWIDESTRING(VirtualAllocEx(hRemoteProcess, nil, memSize, MEM_COMMIT, PAGE_READWRITE));
TempVar := 0;
iReturnCode := WriteProcessMemory(hRemoteProcess, pszLibFileRemote, pszLibAFilename, memSize, TempVar); if iReturnCode then
begin
pfnStartAddr := GetProcAddress(GetModuleHandle('Kernel32'), 'LoadLibraryW');
TempVar := 0;
{ 在远程进程中启动dll }
Result := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, pszLibFileRemote, 0, TempVar);
end; { 释放内存空间 }
Freemem(pszLibAFilename);
end;
//拦截 CreateProcessW
function NewCreateProcessW(lpApplicationName: PChar; lpCommandLine: PChar;
lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo;
var lpProcessInformation: TProcessInformation): BOOL; stdcall;
type
TNewCreateProcessW=function (lpApplicationName: PChar; lpCommandLine: PChar;
lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo;
var lpProcessInformation: TProcessInformation): BOOL; stdcall;
begin
ShowMessage(Application.ExeName+' open '+AnsiString(lpApplicationName));
Hook[0].UnHook;
Curfile:=AnsiString(lpApplicationName);
vspas:=True;
Result := TNewCreateProcessW(Hook[0].BaseAddr)(lpApplicationName,lpCommandLine,
lpProcessAttributes, lpThreadAttributes, bInheritHandles,dwCreationFlags,lpEnvironment,
lpCurrentDirectory,lpStartupInfo,lpProcessInformation);
Hook[0].Hook;
end;
function NewNtResumeThread(hThread:Cardinal;PreviousSuspendCount:PULONG):Cardinal;stdcall;
type
TNewNtResumeThread=function (hThread:Cardinal;PreviousSuspendCount:PULONG):Cardinal;stdcall;
begin
if vspas then
begin
vspas:=False;
Hook[1].UnHook;
htd:=InjectTo(String(Curfile),'c:\main.dll');
curfile:='';
WaitForSingleObject(htd,INFINITE );
end;
Hook[1].UnHook;
Result:=TNewNtResumeThread(Hook[1].BaseAddr)(hThread,PreviousSuspendCount);
Hook[1].Hook;
end;
{--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--}
//删除API Hook
procedure UninitHook;
var
I: Integer;
begin
for I := 0 to High(Hook) do
begin
FreeAndNil(Hook[I]);
end;
end;
//安装API Hook
procedure InitHook;
begin
dllinstall:=True;
Hook[0] := TNtHookClass.Create('kernel32.dll', 'CreateProcessW', @NewCreateProcessW);
Hook[1] := TNTHookClass.Create('ntdll.dll','NtResumeThread',@NewNtResumeThread);
end;
{--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--}//传递消息
function HookProc(nCode, wParam, lParam: Integer): Integer; stdcall;
begin
Result := CallNextHookEx(hhk, nCode, wParam, lParam);
end;//开始HOOK
procedure StartHook; stdcall;
begin
hhk:= SetWindowsHookEx(WH_CALLWNDPROC, HookProc, hInstance, 0);
end;
//结束HOOK
procedure EndHook; stdcall;
begin
if hhk <> 0 then
UnhookWindowsHookEx(hhk);
end;//环境处理
procedure DllEntry(dwResaon: DWORD);
begin
case dwResaon of
DLL_PROCESS_ATTACH: InitHook; //DLL载入
DLL_PROCESS_DETACH: UninitHook; //DLL删除
end;
end;exports
StartHook,EndHook;begin
if DllInstall then
Exit;
DllProc := @DllEntry;
DllEntry(DLL_PROCESS_ATTACH);
end.unit Hook代码:unit unitHook;interfaceuses
Windows, Messages, Classes, SysUtils;type //NtHook类相关类型
TNtJmpCode=packed record //8字节
MovEax:Byte;
Addr:DWORD;
JmpCode:Word;
dwReserved:Byte;
end; TNtHookClass=class(TObject)
private
hProcess:THandle;
NewAddr:TNtJmpCode;
OldAddr:array[0..7] of Byte;
ReadOK:Boolean;
public
BaseAddr:Pointer;
constructor Create(DllName,FuncName:string;NewFunc:Pointer);
destructor Destroy; override;
procedure Hook;
procedure UnHook;
end;implementation//==================================================
//NtHOOK 类开始
//==================================================
constructor TNtHookClass.Create(DllName: string; FuncName: string;NewFunc:Pointer);
var
DllModule:HMODULE;
dwReserved:DWORD;
begin
//获取模块句柄
DllModule:=GetModuleHandle(PChar(DllName));
//如果得不到说明未被加载
if DllModule=0 then DllModule:=LoadLibrary(PChar(DllName));
//得到模块入口地址(基址)
BaseAddr:=Pointer(GetProcAddress(DllModule,PChar(FuncName)));
//获取当前进程句柄
hProcess:=GetCurrentProcess;
//指向新地址的指针
NewAddr.MovEax:=$B8;
NewAddr.Addr:=DWORD(NewFunc);
NewAddr.JmpCode:=$E0FF;
//保存原始地址
ReadOK:=ReadProcessMemory(hProcess,BaseAddr,@OldAddr,8,dwReserved);
//开始拦截
Hook;
end;//释放对象
destructor TNtHookClass.Destroy;
begin
UnHook;
CloseHandle(hProcess); inherited;
end;//开始拦截
procedure TNtHookClass.Hook;
var
dwReserved:DWORD;
begin
if (ReadOK=False) then Exit;
//写入新的地址
WriteProcessMemory(hProcess,BaseAddr,@NewAddr,8,dwReserved);
end;//恢复拦截
procedure TNtHookClass.UnHook;
var
dwReserved:DWORD;
begin
if (ReadOK=False) then Exit;
//恢复地址
WriteProcessMemory(hProcess,BaseAddr,@OldAddr,8,dwReserved);
end;end.
如果包含界面的则不能打开。现在把代码写出来,请帮忙看一下,问题出在哪?
main.dll代码library main;
uses
sysutils,
Windows,
Classes,
Dialogs,
Forms,
tlhelp32,
unitHook in 'unitHook.pas';{$R *.res}var
hhk:HHOOK;
Hook: array[0..1] of TNtHookClass;
vspas:Bool;
Curfile:String[255];
htd:Cardinal;
DllInstall:Bool;
{--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--}
procedure GetMyProcessID(const AFilename: string; const PathMatch: Boolean; var ProcessID: DWORD);
var
lppe: TProcessEntry32;
SsHandle: Thandle;
FoundAProc, FoundOK: boolean;
begin
ProcessID :=0;
{ 创建系统快照 }
SsHandle := CreateToolHelp32SnapShot(TH32CS_SnapProcess, 0); { 取得快照中的第一个进程 }
{ 一定要设置结构的大小,否则将返回False }
lppe.dwSize := sizeof(TProcessEntry32);
FoundAProc := Process32First(Sshandle, lppe);
while FoundAProc do
begin
{ 进行匹配 }
if PathMatch then
FoundOK := AnsiStricomp(lppe.szExefile, PChar(AFilename)) = 0
else
FoundOK := AnsiStricomp(PChar(ExtractFilename(lppe.szExefile)), PChar(ExtractFilename(AFilename))) = 0;
if FoundOK then
begin
ProcessID := lppe.th32ProcessID;
break;
end;
{ 未找到,继续下一个进程 }
FoundAProc := Process32Next(SsHandle, lppe);
end;
CloseHandle(SsHandle);
end;
{ 设置权限 }
function EnabledDebugPrivilege(const Enabled : Boolean) : Boolean;
var
hTk : THandle; { 打开令牌句柄 }
rtnTemp : Dword; { 调整权限时返回的值 }
TokenPri : TOKEN_PRIVILEGES;
const
SE_DEBUG = 'SeDebugPrivilege'; { 查询值 }
begin
Result := False;
{ 获取进程令牌句柄,设置权限 }
if (OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,hTk)) then
begin
TokenPri.PrivilegeCount := 1;
{ 获取Luid值 }
LookupPrivilegeValue(nil,SE_DEBUG,TokenPri.Privileges[0].Luid); if Enabled then
TokenPri.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
else
TokenPri.Privileges[0].Attributes := 0; rtnTemp := 0;
{ 设置新的权限 }
AdjustTokenPrivileges(hTk,False,TokenPri,sizeof(TokenPri),nil,rtnTemp); Result := GetLastError = ERROR_SUCCESS;
CloseHandle(hTk); end;
end;{ 注入远程进程 }
function InjectTo(const Host, Guest: string; const PID: DWORD = 0): DWORD;
var
{ 被注入的进程句柄,进程ID}
hRemoteProcess: THandle;
dwRemoteProcessId: DWORD; { 写入远程进程的内容大小 }
memSize: DWORD; { 写入到远程进程后的地址 }
pszLibFileRemote: Pointer; iReturnCode: Boolean;
TempVar: DWORD; { 指向函数LoadLibraryW的地址 }
pfnStartAddr: TFNThreadStartRoutine; { dll全路径,需要写到远程进程的内存中去 }
pszLibAFilename: PwideChar;
begin
Result := 0;
{ 设置权限 }
EnabledDebugPrivilege(True); { 为注入的dll文件路径分配内存大小,由于为WideChar,故要乘2 }
Getmem(pszLibAFilename, Length(Guest) * 2 + 1);
StringToWideChar(Guest, pszLibAFilename, Length(Guest) * 2 + 1); { 获取进程ID }
if PID > 0 then
dwRemoteProcessID := PID
else
GetMyProcessID(Host, False, dwRemoteProcessID); { 取得远程进程句柄,具有写入权限}
hRemoteProcess := OpenProcess(PROCESS_CREATE_THREAD + {允许远程创建线程}
PROCESS_VM_OPERATION + {允许远程VM操作}
PROCESS_VM_WRITE, {允许远程VM写}
FALSE, dwRemoteProcessId); { 用函数VirtualAllocex在远程进程分配空间,并用WriteProcessMemory中写入dll路径 }
memSize := (1 + lstrlenW(pszLibAFilename)) * sizeof(WCHAR);
pszLibFileRemote := PWIDESTRING(VirtualAllocEx(hRemoteProcess, nil, memSize, MEM_COMMIT, PAGE_READWRITE));
TempVar := 0;
iReturnCode := WriteProcessMemory(hRemoteProcess, pszLibFileRemote, pszLibAFilename, memSize, TempVar); if iReturnCode then
begin
pfnStartAddr := GetProcAddress(GetModuleHandle('Kernel32'), 'LoadLibraryW');
TempVar := 0;
{ 在远程进程中启动dll }
Result := CreateRemoteThread(hRemoteProcess, nil, 0, pfnStartAddr, pszLibFileRemote, 0, TempVar);
end; { 释放内存空间 }
Freemem(pszLibAFilename);
end;
//拦截 CreateProcessW
function NewCreateProcessW(lpApplicationName: PChar; lpCommandLine: PChar;
lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo;
var lpProcessInformation: TProcessInformation): BOOL; stdcall;
type
TNewCreateProcessW=function (lpApplicationName: PChar; lpCommandLine: PChar;
lpProcessAttributes, lpThreadAttributes: PSecurityAttributes;
bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: Pointer;
lpCurrentDirectory: PChar; const lpStartupInfo: TStartupInfo;
var lpProcessInformation: TProcessInformation): BOOL; stdcall;
begin
ShowMessage(Application.ExeName+' open '+AnsiString(lpApplicationName));
Hook[0].UnHook;
Curfile:=AnsiString(lpApplicationName);
vspas:=True;
Result := TNewCreateProcessW(Hook[0].BaseAddr)(lpApplicationName,lpCommandLine,
lpProcessAttributes, lpThreadAttributes, bInheritHandles,dwCreationFlags,lpEnvironment,
lpCurrentDirectory,lpStartupInfo,lpProcessInformation);
Hook[0].Hook;
end;
function NewNtResumeThread(hThread:Cardinal;PreviousSuspendCount:PULONG):Cardinal;stdcall;
type
TNewNtResumeThread=function (hThread:Cardinal;PreviousSuspendCount:PULONG):Cardinal;stdcall;
begin
if vspas then
begin
vspas:=False;
Hook[1].UnHook;
htd:=InjectTo(String(Curfile),'c:\main.dll');
curfile:='';
WaitForSingleObject(htd,INFINITE );
end;
Hook[1].UnHook;
Result:=TNewNtResumeThread(Hook[1].BaseAddr)(hThread,PreviousSuspendCount);
Hook[1].Hook;
end;
{--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--}
//删除API Hook
procedure UninitHook;
var
I: Integer;
begin
for I := 0 to High(Hook) do
begin
FreeAndNil(Hook[I]);
end;
end;
//安装API Hook
procedure InitHook;
begin
dllinstall:=True;
Hook[0] := TNtHookClass.Create('kernel32.dll', 'CreateProcessW', @NewCreateProcessW);
Hook[1] := TNTHookClass.Create('ntdll.dll','NtResumeThread',@NewNtResumeThread);
end;
{--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--}//传递消息
function HookProc(nCode, wParam, lParam: Integer): Integer; stdcall;
begin
Result := CallNextHookEx(hhk, nCode, wParam, lParam);
end;//开始HOOK
procedure StartHook; stdcall;
begin
hhk:= SetWindowsHookEx(WH_CALLWNDPROC, HookProc, hInstance, 0);
end;
//结束HOOK
procedure EndHook; stdcall;
begin
if hhk <> 0 then
UnhookWindowsHookEx(hhk);
end;//环境处理
procedure DllEntry(dwResaon: DWORD);
begin
case dwResaon of
DLL_PROCESS_ATTACH: InitHook; //DLL载入
DLL_PROCESS_DETACH: UninitHook; //DLL删除
end;
end;exports
StartHook,EndHook;begin
if DllInstall then
Exit;
DllProc := @DllEntry;
DllEntry(DLL_PROCESS_ATTACH);
end.unit Hook代码:unit unitHook;interfaceuses
Windows, Messages, Classes, SysUtils;type //NtHook类相关类型
TNtJmpCode=packed record //8字节
MovEax:Byte;
Addr:DWORD;
JmpCode:Word;
dwReserved:Byte;
end; TNtHookClass=class(TObject)
private
hProcess:THandle;
NewAddr:TNtJmpCode;
OldAddr:array[0..7] of Byte;
ReadOK:Boolean;
public
BaseAddr:Pointer;
constructor Create(DllName,FuncName:string;NewFunc:Pointer);
destructor Destroy; override;
procedure Hook;
procedure UnHook;
end;implementation//==================================================
//NtHOOK 类开始
//==================================================
constructor TNtHookClass.Create(DllName: string; FuncName: string;NewFunc:Pointer);
var
DllModule:HMODULE;
dwReserved:DWORD;
begin
//获取模块句柄
DllModule:=GetModuleHandle(PChar(DllName));
//如果得不到说明未被加载
if DllModule=0 then DllModule:=LoadLibrary(PChar(DllName));
//得到模块入口地址(基址)
BaseAddr:=Pointer(GetProcAddress(DllModule,PChar(FuncName)));
//获取当前进程句柄
hProcess:=GetCurrentProcess;
//指向新地址的指针
NewAddr.MovEax:=$B8;
NewAddr.Addr:=DWORD(NewFunc);
NewAddr.JmpCode:=$E0FF;
//保存原始地址
ReadOK:=ReadProcessMemory(hProcess,BaseAddr,@OldAddr,8,dwReserved);
//开始拦截
Hook;
end;//释放对象
destructor TNtHookClass.Destroy;
begin
UnHook;
CloseHandle(hProcess); inherited;
end;//开始拦截
procedure TNtHookClass.Hook;
var
dwReserved:DWORD;
begin
if (ReadOK=False) then Exit;
//写入新的地址
WriteProcessMemory(hProcess,BaseAddr,@NewAddr,8,dwReserved);
end;//恢复拦截
procedure TNtHookClass.UnHook;
var
dwReserved:DWORD;
begin
if (ReadOK=False) then Exit;
//恢复地址
WriteProcessMemory(hProcess,BaseAddr,@OldAddr,8,dwReserved);
end;end.
procedure DllEntry(dwResaon: DWORD);
begin
ShowMessage('2');
case dwResaon of
DLL_PROCESS_ATTACH: InitHook; //DLL载入
DLL_PROCESS_DETACH: UninitHook; //DLL删除
end;
ShowMessage('v');
end;exports
StartHook,EndHook;begin
ShowMessage('ins');
if DllInstall then
Exit;
DllProc := @DllEntry;
ShowMessage('1');
DllEntry(DLL_PROCESS_ATTACH);
ShowMessage('6');
end.
调试了下,发现打开记事本的时候,会在//环境处理 那块重复3次,然后就会UninitHook;然后就退出了!
真是不解!呀!