冥界3大法王 发表于 2026-2-17 22:54

判断用户输入的PID、VA地址是否是在.text区段?

本帖最后由 冥界3大法王 于 2026-2-17 23:12 编辑







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), 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), '$', '', ), 0));

// 3. 调用函数判断
if IsAddressInNamedSection(vPID, vAddr, Edit3.text) then
    ShowMessage('Yes! 该地址在 .text区段')
else
    ShowMessage('No! 该地址不在 .text区段');
end;

end.

本程序仅测试了64位Delphi程序。

yanjin2018 发表于 2026-2-18 08:51

学到了谢谢你

fair2025 发表于 2026-3-13 23:58

哇,好久没有看到delphi的代码了。
页: [1]
查看完整版本: 判断用户输入的PID、VA地址是否是在.text区段?