Доброго времени суток, суть проблемы следующая: Пишу софт по поиску строк по сигнатуре, программа составлена на делфи под 32 бита и код написан под поиск строки в памяти 32-х битных приложений, все работает все гуд, но столкнулся с проблемой что в некоторых приложениях не работает, по итогу долгого дебага выяснилось что проблема возникала только в приложениях которые 64 бита, начал искать решения, но рабочего кода так и не нашлось, код ниже кидал на коленке не судите строго, но суть не поменялась, там же добавлены наработки по поиску строки в памяти 64 битного приложения, но они не рабочие так как я пока не понимаю как организована работа памяти в 64 битных приложениях. И главный вопрос: Возможно ли из 32 битного приложения обработать память 64 битного приложения, эксперты прошу помощи !
Информацию по обработке памяти 64битных приложений брал тут
https://stackoverflow.com/questions/32746356/32-64-bit-readprocessmemory-issues
Сам код на текущий момент имеет вид:
Код:
{$IFDEF WIN64}
PMEMORY_BASIC_INFORMATION64 = ^MEMORY_BASIC_INFORMATION64;
{$ALIGN 16}
MEMORY_BASIC_INFORMATION64 = record
BaseAddress: ULONGLONG;
AllocationBase: ULONGLONG;
AllocationProtect: DWORD;
_alignment1: DWORD;
RegionSize: ULONGLONG;
State: DWORD;
Protect: DWORD;
_Type: DWORD;
_alignment2: DWORD;
end;
{$ENDIF}
type
WinIsWow64 = function( Handle: THandle; var Iret: BOOL ): Windows.BOOL; stdcall;
type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
Memo1: TMemo;
Edit2: TEdit;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{$IFDEF WIN64}
function VirtualQueryEx64(hProcess: THandle; lpAddress: Pointer; var lpBuffer: MEMORY_BASIC_INFORMATION64; dwLength: SIZE_T): SIZE_T; stdcall; external 'kernel32' name 'VirtualQueryEx';
{$ENDIF}
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
READABLE : Cardinal = (PAGE_EXECUTE_READ or PAGE_EXECUTE_READWRITE or PAGE_EXECUTE_WRITECOPY or PAGE_READONLY or PAGE_READWRITE or PAGE_WRITECOPY);
type
TMBIArray = array of MEMORY_BASIC_INFORMATION;
TPointerArray = array of Cardinal;
TCharArray = array of char;
procedure push_to_bmi(var arr : TMBIArray; el : MEMORY_BASIC_INFORMATION);
var
len : integer;
begin
len := Length(arr);
SetLength(arr, len + 1);
arr[len] := el;
end;
procedure push_to_pointer_array(var arr : TPointerArray; el : Cardinal);
var
len : integer;
begin
len := Length(arr);
SetLength(arr, len + 1);
arr[len] := el;
end;
function get_mem_pages(h : Cardinal) : TMBIArray;
var
pages : TMBIArray;
mbi : MEMORY_BASIC_INFORMATION;
addr : Cardinal;
ret : Cardinal;
begin
addr := 0;
SetLength(pages, 0);
while true do
begin
ret := VirtualQueryEx(h, Pointer(addr), mbi, SizeOf(mbi));
if(ret = 0) then break;
if (mbi.State and MEM_COMMIT) <> 0 then
begin
if (mbi.AllocationProtect and READABLE) <> 0 then
begin
push_to_bmi(pages, mbi);
end;
end;
addr := Cardinal(mbi.BaseAddress) + Cardinal(mbi.RegionSize);
end;
result := pages;
end;
{$IFDEF WIN64}
function get_mem_pages64(h : Cardinal) : TMBIArray;
var
pages : TMBIArray;
mbi : MEMORY_BASIC_INFORMATION;
addr : Cardinal;
ret : Cardinal;
begin
addr := 0;
SetLength(pages, 0);
while true do
begin
//ret := VirtualQueryEx(h, Pointer(addr), mbi, SizeOf(mbi));
ret := VirtualQueryEx64(h, Pointer(addr), mbi, SizeOf(mbi));
if(ret = 0) then break;
if (mbi.State and MEM_COMMIT) <> 0 then
begin
if (mbi.AllocationProtect and READABLE) <> 0 then
begin
push_to_bmi(pages, mbi);
end;
end;
addr := Cardinal(mbi.BaseAddress) + Cardinal(mbi.RegionSize);
end;
result := pages;
end;
{$ENDIF}
{$IFDEF WIN64}
procedure TForm1.ScanMemory64(PIDHandle: THandle; const ProcessName: string);
var
MemStart: ULONGLONG;
ReceivedBytes: SIZE_T;
MemInfo: MEMORY_BASIC_INFORMATION64;
begin
MemStart := 0;
while (VirtualQueryEx64(PIDHandle, Pointer(MemStart), MemInfo, SizeOf(MemInfo)) <> 0) do
begin
if ((MemInfo.State = MEM_COMMIT) and (not (MemInfo.Protect = PAGE_GUARD)
or (MemInfo.Protect = PAGE_NOACCESS)) and (MemInfo.Protect = PAGE_READWRITE)) then
begin
SetLength(Buff, MemInfo.RegionSize);
if (ReadProcessMemory(PIDHandle, Pointer(MemInfo.BaseAddress), Buff,
MemInfo.RegionSize, ReceivedBytes)) then
begin
DoSomethingWithBuff(ProcessName);
end;
end;
Inc(MemStart, MemInfo.RegionSize);
end;
end;
{$ENDIF}
function find_strings_in_page(h : Cardinal; page_start : Cardinal; page_size : Cardinal; needed : String): TPointerArray;
var
result_addrs : TPointerArray;
buf_size : integer;
buf : array [0..4096] of char;
addr_in_page : Cardinal;
last_read : boolean;
can_read : integer;
nr : Cardinal;
ret : boolean;
cycle_end : integer;
i : integer;
j : integer;
cmp_buf : TCharArray;
cmp : integer;
begin
SetLength(result_addrs, 0);
buf_size := 4096;
last_read := false;
addr_in_page := 0;
while true do
begin
can_read := 0;
if(addr_in_page + buf_size) >= page_size then
begin
can_read := page_size - addr_in_page;
last_read := true;
end else
begin
can_read := buf_size;
end;
nr := 0;
ret := ReadProcessMemory(h,Pointer(page_start + addr_in_page), @buf, can_read, nr);
if not ret then break;
cycle_end := nr - (Length(needed) - 1);
//for i := 0 to cycle_end - 1 do
i := 0;
while i < cycle_end do
begin
cmp := 0;
//cmp_buf := TCharArray(Cardinal(@buf) + Cardinal(i));
for j := 0 to Length(needed) - 1 do
begin
cmp := Byte(Byte(needed[j+1]) - Byte(buf[j+1 + i]));
if cmp <> 0 then break;
end;
if cmp = 0 then
begin
push_to_pointer_array(result_addrs, Cardinal(page_start + addr_in_page + i + 1));
i := i + Length(needed);
end;
i := i + 1;
end;
addr_in_page := addr_in_page + can_read - Length(needed);
if last_read then break;
end;
result := result_addrs;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
pid : integer;
hProcess : Cardinal;
find_str : String;
pages : TMBIArray;
i,j : integer;
page_start : Cardinal;
addr_in_page : Cardinal;
page_size : Cardinal;
res : TPointerArray;
buf : array [0..4096] of char;
buf_size : integer;
can_read : Cardinal;
nr : Cardinal;
string_list : TStringList;
begin
string_list := TStringList.Create();
buf_size := 4096;
pid := StrToInt(Edit1.Text);
find_str := Edit2.Text;
hProcess := OpenProcess(PROCESS_ALL_ACCESS, false, pid); //PROCESS_ALL_ACCESS
//ShowMessage('1 - '+SysErrorMessage(GetLastError));
pages := get_mem_pages(hProcess);
//ShowMessage('2 - '+SysErrorMessage(GetLastError));
for i := 0 to Length(pages) - 1 do
begin
res := find_strings_in_page(hProcess, Cardinal(pages[i].BaseAddress), pages[i].RegionSize, find_str);
// ShowMessage('3 - '+SysErrorMessage(GetLastError));
for j := 0 to Length(res) - 1 do
begin
page_start := Cardinal(pages[i].BaseAddress);
addr_in_page := Cardinal(res[j] - page_start);
page_size := pages[i].RegionSize;
can_read := 0;
if(addr_in_page + 4096 >= page_size) then
can_read := page_size - addr_in_page
else
can_read := 4096;
ReadProcessMemory(hProcess,Pointer(page_start + addr_in_page), @buf, can_read, nr);
Memo1.Lines.Add(buf);
//string_list.Add(String(buf));
end;
end;
end;