var
Ptr_NtTerminateThread, Ptr_NtTerminateProcess: Cardinal;
//Patch的AV.
//在我测试的机器上2个的AV是一样的,分别是$48584331和$485843BE.
hSmss: Cardinal;
OldProtect: Cardinal;
NopBuf: Array [0..20] of Byte; //Nop * 20
NtTerminateThreadBuf: Array [0..Len_NtTerminateThread - 1] of Byte;
//保存patch前的内容
NtTerminateProcessBuf: Array [0..Len_NtTerminateProcess - 1] of Byte;
//保存patch前的内容
i: Cardinal;
function EnabledDebugPrivilege(const bEnabled: Boolean):Boolean; //提升权限
var
hToken: THandle;
tp: TOKEN_PRIVILEGES;
a: DWORD;
const
SE_DEBUG_NAME = 'SeDebugPrivilege';
begin
Result:=False;
if (OpenProcessToken(GetCurrentProcess, TOKEN_ADJUST_PRIVILEGES, hToken)) then
begin
tp.PrivilegeCount :=1;
LookupPrivilegeValue(nil, SE_DEBUG_NAME, tp.Privileges[0].Luid);
if bEnabled then
tp.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED
else
tp.Privileges[0].Attributes := 0;
a:=0;
AdjustTokenPrivileges(hToken, False, @tp, SizeOf(tp), nil, @a);
Result:= GetLastError = ERROR_SUCCESS;
CloseHandle(hToken);
end;
end;
function DoFix: Bool; //Patch
function Fix(Ptr: Pointer; var DesBuf: Array of Byte; Len: integer): Bool;
var
Buf: Array [0..20] of Byte;
begin
result := true;
result := result and ReadProcessMemory(hSmss, Ptr, @Buf[0], Len, @i);
if Ord(Buf[0]) <> $90 then
begin
CopyMemory(@DesBuf[0], @Buf[0], Len);
result := result and WriteProcessMemory(hSmss, Ptr, @NopBuf[0], Len, @i);
end
else
result := false;
end;
begin
result := true;
result := result and VirtualProtectEx(hSmss, Pointer(Ptr_NtTerminateThread), 128,
PAGE_EXECUTE_READWRITE, @OldProtect);
result := result and Fix(Pointer(Ptr_NtTerminateThread), NtTerminateThreadBuf,
Len_NtTerminateThread);
result := result and Fix(Pointer(Ptr_NtTerminateProcess), NtTerminateProcessBuf,
Len_NtTerminateProcess);
result := result and VirtualProtectEx(hSmss, Pointer(Ptr_NtTerminateThread), 128,
OldProtect, @OldProtect);
end;
function UndoFix: Bool;
function Fix(Ptr: Pointer; SrcBuf: Array of Byte; Len: integer): Bool;
var
Buf: Array [0..20] of Byte;
begin
result := true;
result := result and ReadProcessMemory(hSmss, Ptr, @Buf[0], Len, @i);
if Ord(Buf[0]) = $90 then
begin
result := result and WriteProcessMemory(hSmss, Ptr, @SrcBuf[0], Len, @i);
end
else
result := false;
end;
begin
if (Ord(NtTerminateThreadBuf[0]) = 0) or (Ord(NtTerminateProcessBuf[0]) = 0) then
begin
result := false;
exit;
end;
result := true;
result := result and VirtualProtectEx(hSmss, Pointer(Ptr_NtTerminateThread), 256,
PAGE_EXECUTE_READWRITE, @OldProtect);
result := result and Fix(Pointer(Ptr_NtTerminateThread), NtTerminateThreadBuf,
Len_NtTerminateThread);
result := result and Fix(Pointer(Ptr_NtTerminateProcess), NtTerminateProcessBuf,
Len_NtTerminateProcess);
result := result and VirtualProtectEx(hSmss, Pointer(Ptr_NtTerminateThread), 256,
OldProtect, @OldProtect);
end;
function Search4Hardcode: Bool; //取得Patch位置的AV.
var
TmpSmss: TMemoryStream;
PFileHeader: PImageFileHeader;
POptionalHeader32: PImageOptionalHeader32;
PSectionHeader: PImageSectionHeader;
l: integer;
SysDir: PChar;
Ptr: PByte;
f1, f2: Bool;
begin
result := false;
l := GetSystemDirectory(nil, 0);
GetMem(SysDir, l);
GetSystemDirectory(SysDir, l);
TmpSmss := TMemoryStream.Create;
try
TmpSmss.LoadFromFile(SysDir + '\SMSS.EXE');
PFileHeader := PImageFileHeader(Longint(TmpSmss.Memory) +
PImageDosHeader(TmpSmss.Memory)^.e_lfanew + 4);
POptionalHeader32 := PImageOptionalHeader32(DWORD(PFileHeader) +
IMAGE_SIZEOF_FILE_HEADER);
PSectionHeader := PImageSectionHeader(DWORD(POptionalHeader32) +
PFileHeader^.SizeOfOptionalHeader);
f1 := false;
f2 := false;
for i := 0 to PFileHeader^.NumberOfSections - 1 do //遍历各个Section
begin
Ptr := PByte(Cardinal(TmpSmss.Memory) + PSectionHeader^.PointerToRawData);
for i := 0 to PSectionHeader^.SizeOfRawData - 1 do
//在Section中查找需Patch的Hardcode
begin
if Ptr^ = LoByte(LoWord(HC_NtTerminateThread)) then //第一Byte相同?
begin
if PDWORD(Ptr)^ = HC_NtTerminateThread then //整个DWORD相同?
begin
Ptr_NtTerminateThread := POptionalHeader32^.ImageBase +
PSectionHeader^.VirtualAddress + i;
//计算得到Patch位置的AV.
//Smss.exe的基址一般就是其PE中指定的ImageBase.
//所以内存中Smss.exe需要Patch的位置就其在PE文件中的AV.
f1 := true;
end;
end
else if Ptr^ = LoByte(LoWord(HC_NtTerminateProcess)) then
if PDWORD(Ptr)^ = HC_NtTerminateProcess then
begin
Ptr_NtTerminateProcess := POptionalHeader32^.ImageBase +
PSectionHeader^.VirtualAddress + i;
f2 := true;
end;
if f1 and f2 then Break; //2处Patch都已找到.
inc(Ptr);
end;
if f1 and f2 then
begin
result := true;
Break;
end;
inc(PSectionHeader);
end;
finally
TmpSmss.Free;
FreeMem(SysDir);
end;
end;
function FindSmss(var Handle: Cardinal): Bool;
//获取Smss.exe的ProcessId,并打开得到Process Handle.
const
SmssPath = '\SYSTEMROOT\SYSTEM32\SMSS.EXE';
var
lppe: TProcessEntry32;
sHandle:cardinal;
Found: bool;
hp: cardinal;
ExePath: PChar;
begin
result := false;
GetMem(ExePath, MAX_PATH);
sHandle := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
Found := Process32First(sHandle, lppe);
while found do
begin
hp := OpenProcess(PROCESS_ALL_ACCESS, false, lppe.th32ProcessID);
GetModuleFileNameExA(hp, 0, ExePath, MAX_PATH); //取完全路径
if UpperCase(ExePath) = SmssPath then
begin
Handle := hp;
result := true;
Break;
end;
Found := Process32Next(sHandle, lppe);
CloseHandle(hp);
end;
CloseHandle(sHandle);
FreeMem(ExePath);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
if GetVersion and 255 <> 5 then
begin
Showmessage('Works on Win2k Only!!');
Halt;
end;
Search4Hardcode; //取得Patch位置的AV.
EnabledDebugPrivilege(true); //提升权限
FillMemory(@NopBuf[0], 20, $90);
ZeroMemory(@NtTerminateThreadBuf[0], Len_NtTerminateThread);
ZeroMemory(@NtTerminateProcessBuf[0], Len_NtTerminateProcess);
if not FindSmss(hSmss) then
//获取Smss.exe的ProcessId,并打开得到Process Handle.
showmessage('Smss.exe not found?!');
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
UndoFix;
CloseHandle(hSmss);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if not DoFix then //Patch
showmessage('Do fix failed!')
else
Label1.Caption := 'Patched!';
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
if not UndoFix then //恢复
showmessage('Do UndoFix failed!')
else
Label1.Caption := 'Not Patched!';
end;