本帖最后由 冥界3大法王 于 2026-2-17 23:12 编辑
[Delphi] 纯文本查看 复制代码 unit Unit4;
interface
uses
Winapi.PsAPI, Winapi.Windows, Winapi.Messages, System.SysUtils,
System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms,
Vcl.Dialogs, Vcl.StdCtrls;
type
TForm4 = class(TForm)
Edit1: TEdit;
Label1: TLabel;
Edit2: TEdit;
Label2: TLabel;
Button2: TButton;
Edit3: TEdit;
Label3: TLabel;
procedure Button2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form4: TForm4;
implementation
{$R *.dfm}
function IsAddressInNamedSection(PID: DWORD; TargetAddr: NativeUInt; const SectionName: string): Boolean;
var
hProc: THandle;
hMod: HMODULE;
cbNeeded: DWORD;
DosHeader: IMAGE_DOS_HEADER;
NtHeaders: IMAGE_NT_HEADERS64; // 针对 64 位进程
SectionHeader: IMAGE_SECTION_HEADER;
i: Integer;
ModInfo: TModuleInfo;
BytesRead: NativeUInt;
SectionStart, SectionEnd: NativeUInt;
CurrentSecName: string;
begin
Result := False;
hProc := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID);
if hProc = 0 then
Exit;
try
// 1. 获取主模块基址 (通常是程序的 .exe)
if EnumProcessModules(hProc, @hMod, SizeOf(hMod), cbNeeded) then
begin
GetModuleInformation(hProc, hMod, @ModInfo, SizeOf(ModInfo));
// 2. 读取 DOS 头
if not ReadProcessMemory(hProc, ModInfo.lpBaseOfDll, @DosHeader, SizeOf(DosHeader), BytesRead) then
Exit;
// 3. 读取 NT 头 (注意偏移)
if not ReadProcessMemory(hProc, Pointer(NativeUInt(ModInfo.lpBaseOfDll) + Cardinal(DosHeader._lfanew)), @NtHeaders, SizeOf(NtHeaders), BytesRead) then
Exit;
// 4. 遍历所有区段 (Section)
for i := 0 to NtHeaders.FileHeader.NumberOfSections - 1 do
begin
// 计算每个 Section Header 的位置
// 位置 = NT头地址 + NT头结构大小 + (索引 * Header大小)
if ReadProcessMemory(hProc, Pointer(NativeUInt(ModInfo.lpBaseOfDll) + Cardinal(DosHeader._lfanew) + SizeOf(NtHeaders) + (i * SizeOf(SectionHeader))), @SectionHeader, SizeOf(SectionHeader), BytesRead) then
begin
// 获取区段名 (最多8个字节)
SetString(CurrentSecName, PAnsiChar(@SectionHeader.Name[0]), 8);
CurrentSecName := Trim(CurrentSecName).ToLower;
// 5. 判断地址范围
SectionStart := NativeUInt(ModInfo.lpBaseOfDll) + SectionHeader.VirtualAddress;
SectionEnd := SectionStart + SectionHeader.Misc.VirtualSize;
if (TargetAddr >= SectionStart) and (TargetAddr < SectionEnd) then
begin
// 如果地址在这个区段内,检查名字是否匹配
if CurrentSecName.Contains(SectionName.ToLower) then
begin
Result := True;
Break;
end;
end;
end;
end;
end;
finally
CloseHandle(hProc);
end;
end;
procedure TForm4.Button2Click(Sender: TObject);
var
vPID: DWORD;
vAddr: NativeUInt;
begin
// 1. 将 PID 字符串转为数字 (Cardinal)
vPID := StrToIntDef(Trim(Edit2.Text), 0);
// 2. 将地址字符串转为 64位数值 (UInt64/NativeUInt)
// 支持直接输入 0000000000849200 或十六进制格式 $849200
vAddr := NativeUInt(StrToInt64Def('$' + StringReplace(Trim(Edit1.Text), '$', '', [rfReplaceAll]), 0));
// 3. 调用函数判断
if IsAddressInNamedSection(vPID, vAddr, Edit3.text) then
ShowMessage('Yes! 该地址在 .text区段')
else
ShowMessage('No! 该地址不在 .text区段');
end;
end.
本程序仅测试了64位Delphi程序。 |