📄 reentry.pas
字号:
unit ReEntry;
interface
uses Windows;
// 修改模块引入表
type
TReEntry = class(TObject)
public
constructor Create(CallerModName, CalleeModName, FuncName: PChar; HookProc: FarProc);
destructor Destroy(); override;
function OriginProc(): FarProc; // 返回原始地址
private
m_CallerModName: PChar; // 调用者模块名
m_hCallerModule: HModule; // 调用者模块句柄
m_CalleeModName: PChar; // 被调者模块名
m_HookProc, // 新老函数地址
m_OrigProc: FarProc;
m_funcName: PChar;
procedure ReplaceIATEntry(CurProc, NewProc: FarProc);
end;
implementation
uses Messages, ImageHlp;
type
// DLL数组结构
TImageImportDescriptor = record
OriginalFirstThunk: DWord; // 保存函数信息的TImageThunkData数组的RVA
TimeDateStamp, ForwarderChain: DWord;
Name: DWord; // DLL名称字符串的RVA
FirstThunk: DWord; // 另一份TImageThunkData数组的拷贝的RVA,装载后,
end; // 该TImageThunkData数组被修改为各函数入口地址
PImageImportDescriptor = ^TImageImportDescriptor;
// 函数名称信息
TImageImportByName = packed record
Hint: Word; // 如果非0, 表示函数的参考序号
Name: array [0..0] of Char; // 函数名字符串
end;
PImageImportByName = ^TImageImportByName;
// 函数数组结构
TImageThunkData = record
case Integer of // 最高位不是1, 则为TImageImportByName的RVA,
0: (ForwarderString: PByte);// 否则, 低31位代表引入的函数的序号, 另外,
1: (Function_: PDWORD); // 装载后, 此数组的一份拷贝变为各函数入口地址
2: (Ordinal: ULONG);
3: (AddressOfData: PImageImportByName);
end;
PImageThunkData = ^TImageThunkData;
constructor TReEntry.Create(
CallerModName, // 调用者模块名
CalleeModName, // 被调者模块名
FuncName: PChar; // 被调用函数名
HookProc: FarProc); // 替换地址
begin
m_CallerModName := CallerModName;
m_hCallerModule := GetModuleHandle(CallerModName);
if (m_hCallerModule = 0) then Exit;
m_CalleeModName := CalleeModName;
m_HookProc := HookProc;
m_funcName := FuncName;
m_OrigProc := GetProcAddress(GetModuleHandle(CalleeModName), FuncName);
if (m_OrigProc = nil) then Exit;
ReplaceIATEntry(m_OrigProc, m_HookProc);
end;
destructor TReEntry.Destroy();
begin
if (m_hCallerModule <> 0) and (m_OrigProc <> nil) and
(GetModuleHandle(m_CallerModName) = m_hCallerModule)
then
ReplaceIATEntry(m_HookProc, m_OrigProc);
end;
function TReEntry.OriginProc(): FarProc;
begin
Result := m_OrigProc;
end;
procedure TReEntry.ReplaceIATEntry(CurProc, NewProc: FarProc);
var
pImportDesc: PImageImportDescriptor;
pThunk: PImageThunkData;
CurModName: PChar;
dwSize, dwProtect, dwTemp: DWord;
begin
if (m_hCallerModule >= $80000000) then Exit;
// 定位至函数引入表
pImportDesc := ImageDirectoryEntryToData(Pointer(m_hCallerModule), True, IMAGE_DIRECTORY_ENTRY_IMPORT, dwSize);
if (pImportDesc = nil) then Exit;
// 遍历TImageImportDescriptor数组, 寻找名称匹配的DLL
while (pImportDesc.Name <> 0) do
begin
CurModName := PChar(m_hCallerModule + pImportDesc.Name);
if (lStrCmpI(CurModName, m_CalleeModName) = 0) then // DLL名字匹配
begin
// 定位至函数地址表
pThunk := PImageThunkData(m_hCallerModule + pImportDesc.FirstThunk);
// 遍历TImageThunkData数组 (寻找地址匹配的函数)
while (pThunk.Function_ <> nil) do
begin
// 找到则改写Function_
if (pThunk.Function_ = CurProc) then
begin
//MessageBox(0,m_funcName,CurModName,MB_OK);
VirtualProtect(@pThunk.Function_, SizeOf(FarProc), PAGE_EXECUTE_WRITECOPY, @dwProtect);
WriteProcessMemory(GetCurrentProcess(), @pThunk.Function_, @NewProc, SizeOf(FarProc), dwTemp);
VirtualProtect(@pThunk.Function_, SizeOf(FarProc), dwProtect, @dwTemp);
Break;
end;
// 下一个TImageThunkData
Inc(pThunk);
end; // while (pThunk.Function_ <> nil) do ..
end;
// 下一个TImageImportDescriptor
Inc(pImportDesc);
end; // while (pImportDesc.Name <> 0) do ..
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -