Быстрый алгоритм поиска в памяти по хешу с использованием сигнатуры

Выдрано из исходников программы DecomAs от PEKill:
Допускается использовать сигнатуры со знаком ‘?’ если неизвестен какой либо байт в сигнатуре:


////////////////////////////////////////////////////////////////////////////////
// Улучшеный алгоритм поиска в буфере...
////////////////////////////////////////////////////////////////////////////////
function Find(dwScanStart,dwScanSize:dword;s:string):DWORD;
Type
TEl = packed record
B: BYTE; // Что ищем
X: BYTE; // Маска
end;
Var
i,j:integer;
aHash:ARRAY [0..1024] of TEl; // Сигнатура в виде хеша
dwScanEnd:DWORD;
begin
Result:=0;
if S='' then exit;
if Length(S) mod 2 <>0 then S:=S+'?'; // Четность
dwScanEnd:=dwScanStart+dwScanSize;
ZeroMemory(@aHash,1024);
i:=1; j:=0;
// Билдим хеш
repeat
aHash[j].X:=$FF;
if S[i]='?' then
begin
aHash[j].X:=$0F;
S[i]:='0';
end;
if S[i+1]='?' then
begin
aHash[j].X:=aHash[j].X and $F0;
S[i+1]:='0';
end;
aHash[j].B:=StrToInt('$'+S[i]+S[i+1]);
Inc(i,2);
Inc(j);
until i>Length(S);
// Поиск
for i:=dwScanStart to dwScanEnd-Length(s) div 2 do
begin
for j:=0 to (Length(S) div 2)-1 do
if BYTE(Pointer(i+j)^) and aHash[j].X <> aHash[j].B // Учет маски
then break;
if j=(Length(S) div 2) then break;
end;
if i<(dwScanEnd-Length(s) div 2) then Result:=i; end; [/code] Поиск в загруженном файле. Пример использования 1:
[code lang="Delphi"]
program Project1;
uses
Windows,
SysUtils,
Classes;
var mmFile: TMemoryStream;
HelloPos: Cardinal;
begin
// Загружаем текстовый файл
mmFile:=TMemoryStream.Create; mmFile.LoadFromFile('C:\1.txt');
// Ищем слово H?llo (это может быть Hello, Hillo, Hullo и т.д.)
HelloPos:=Find(DWORD(mmFile.Memory),mmFile.Size, '48??6C6C6F');
if HelloPos<>0 then
MessageBox(0, PChar('Слово H?llo находится в позиции ' + IntToStr(HelloPos-DWORD(mmFile.Memory))),'', 0)
else
MessageBox(0, 'Слово H?llo не найдено','', 0);
end.

Поиск сигнатуры в загруженной библиотеке. Пример использования 2:


program Project2;
uses
Windows,
SysUtils;
type
TSections = array [0..2] of TImageSectionHeader;
var HMod: THandle;
ImageNtHeaders: PImageNtHeaders;
PSections: ^TSections;
SAddr: DWORD;
begin
// Загружаем DLL
HMod := LoadLibrary('kernel32.dll');
// Определяем секцию поиска
ImageNtHeaders := pointer(HMod + dword(PImageDosHeader(HMod)._lfanew));
PSections := pointer(pchar(@(ImageNtHeaders.OptionalHeader)) + ImageNtHeaders.FileHeader.SizeOfOptionalHeader);
// Ищем MZ в заголовке
SAddr := Find (Hmod, PSections[0].VirtualAddress, '4D5A');
if SAddr<>0 then
MessageBox(0,PChar('Сигнатура найдена по адресу: ' + IntToHex(SAddr, 8)),'',0);
end.

Добавить комментарий

Ваш e-mail не будет опубликован.