View Single Post
  #1  
Old 07-01-2019, 01:24
phroyt phroyt is offline
Friend
 
Join Date: May 2018
Posts: 70
Rept. Given: 0
Rept. Rcvd 7 Times in 3 Posts
Thanks Given: 28
Thanks Rcvd at 95 Times in 38 Posts
phroyt Reputation: 7
Lightbulb [Delphi] Search Memory

Hi,

Some time ago I found a piece of code to SearchBytes.
After a little I come out with this.

Code:
//XE10 Compatible

uses
  System.SysUtils,
  System.Classes,
  Winapi.PsApi,
  Winapi.Windows;

Function SearchMemory(Module: hModule; wildcard: Byte; searchCode: Array of Byte; size: Integer; Offset: Cardinal = 0) : Pointer;

Implementation

//Search Memory
Function SearchMemory(Module: hModule; wildcard: Byte; searchCode: Array of Byte; size: Integer; Offset: Cardinal = 0) : Pointer;
Const
  UCHAR_MAX = 255;
Var
  scan,lastByte,defaultSkip, searchEnd,searchSuccess : NativeUInt;
  skipLength : ARRAY of Integer;
  dllInfo : TModuleInfo;
  p : pointer;
  OldProtect: DWORD;
begin

  searchSuccess := 0;
  lastByte := size - 1;
  result := nil;

  while searchCode[lastByte] = wildcard do
    Dec(lastByte);

  defaultSkip := lastByte;

  for scan:= 0 to lastByte - 1 do
  begin
    if searchCode[scan] = wildcard then
      defaultSkip := lastByte - scan;
  end;

  if defaultSkip > 1 then
    defaultSkip := defaultSkip - 1;

  //Is just setting the default skip length
  SetLength(skipLength, UCHAR_MAX);
  for scan:=0 to UCHAR_MAX do
    skipLength[scan] := defaultSkip;

  for scan := 0 to lastByte-1 do
    if searchCode[scan] <> wildcard then
      begin
        skipLength[searchCode[scan]] := lastByte - scan;
      end;

  if GetModuleInformation(GetCurrentProcess, Module, @dllInfo, sizeof(dllInfo)) then
    begin

      p := dllInfo.lpBaseOfDll;


      try

        searchEnd := Cardinal(dllInfo.lpBaseOfDll) + dllInfo.SizeOfImage;
        searchEnd := searchEnd - (lastByte + 1);

        if ((Cardinal(p)+offset) <= searchEnd) then
          p := Pointer(Cardinal(p)+offset);


        //FM: remove the write protect on Code Segment
        VirtualProtect(p, searchEnd, PAGE_EXECUTE_READWRITE, OldProtect);

        while Cardinal(p) <= searchEnd do
          begin
            scan := lastByte;

            while ((searchCode[scan] = wildcard) or (PByte(Cardinal(p)+scan)^ = searchCode[scan])) do
            begin
              if scan = 0 then
              begin
                Result := P;
                Inc(searchSuccess);
                Break;
              end;
              scan := scan-1;
            end;

            if ( searchSuccess <> 0 ) then
              break;

            p := Pointer(NativeInt(p)+skipLength[PByte(NativeUInt(p)+lastByte)^]);
          end;

        if ( searchSuccess = 0 ) then
          result := nil;

        if ( searchSuccess > 1 ) then
          result := nil;
      finally
        VirtualProtect(P, searchEnd, OldProtect, @OldProtect);
      end;
    end;
end;
Even without writing anything to Module memory, sometimes I got a wrong Byte value. Changing the protection solved this.


Any thoughts to improve?


Sample use:


Code:
const
//SFNTQueryFeature
Const SFNTQueryFeature_SIG :   Array [0..15] of Byte = ($55, $8B, $EC, $83, $EC,
                          $24, $C7, $45, $DC, $02, $00, $00, $00, $51, $31, $C9);

var
  base: hModule;
  proc1,
  proc2: Pointer;
  offset: Cardinal;

begin

  base := GetModuleHandle(nil);

  proc1 := SearchMemory(base, $00, SFNTGetLicense_SIG, length(SFNTGetLicense_SIG));

  if (proc1 <> nil) then
    offset := Cardinal(proc1)+1 - base;
  
  proc2 := SearchMemory(base, $00, SFNTGetLicense_SIG, length(SFNTGetLicense_SIG), offset);
Reply With Quote
The Following 7 Users Say Thank You to phroyt For This Useful Post:
chessgod101 (01-04-2020), Gladiyator (07-04-2019), Indigo (07-19-2019), Mahmoudnia (07-01-2019), niculaita (07-01-2019), ontryit (10-13-2019), Rasmus (04-11-2020)