• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1540
  • Last Modified:

How to scan entire process of a memory for byte array?

pHandle := OpenProcess(PROCESS_ALL_ACCESS, false, 2928);
      if pHandle <> 0 then
        begin
          Addr := dword(sysinfo.lpMinimumApplicationAddress);
          while (Addr < sysinfo.lpMaximumApplicationAddress) do
          begin
            if VirtualQueryEx(Handle, Ptr(Addr), Mbi, SizeOf(Mbi)) = 0 then
            begin
              err := GetLastError;
              inc(Addr, sysinfo.dwPageSize);
              continue;
            end;
             SetLength(buff, mbi.RegionSize);
             ReadProcessMemory(pHandle, Mbi.BaseAddress, @Buff[0], Mbi.RegionSize,             BytesRead);

            if Addr + Mbi.RegionSize < Addr then
              break;
            Addr := Addr + Mbi.RegionSize;
          end;
          CloseHandle(Handle)
        end;

Open in new window


I have tried this code to read the memory .. if i use SetString on the buffer I get only garbage as the memory it's not text.So .. i'm wondering .. how to search for a specific byte array? and to avoid memory leaks while reading/searching.
0
drake08
Asked:
drake08
  • 7
  • 4
  • 2
1 Solution
 
mlmccCommented:
Why do you need to search memory?  Much of what you will be searching for is the application code which probably is protected from reading

mlmcc
0
 
drake08Author Commented:
I want to extract some strings from an application. So .. can you show me a way to do this?
0
 
Sinisa VukCommented:
for what reason do you want to read your app in memory strings?
if it is your app - then you could read anything using "standard/object" way.
0
Keep up with what's happening at Experts Exchange!

Sign up to receive Decoded, a new monthly digest with product updates, feature release info, continuing education opportunities, and more.

 
drake08Author Commented:
Not really memory strings.. it is ok byte array too. Why are you keep asking me for what reason I need this? It is matter?
0
 
Sinisa VukCommented:
This info can really helps us to understand what you need and we can give you another (maybe better) solution. So, if you build some protection stuff - maybe there is something else... if you trying to build some malware - there is no help, if you want to crack some third part component runtime - no help.

all in all... you can use function like this:
function FindByteArrayInArray(pSearchFor: PByte; SearchLen: Cardinal; pBuffer: PByte; BufLen: Cardinal): PByte;
var
  i, j: Cardinal;
  bFound: Boolean;
begin
  Result := nil;

  if SearchLen > BufLen then Exit;
  
  if SearchLen = 0 then
  begin
    Result := pBuffer;
    Exit;
  end;

  for i := 0 to BufLen - SearchLen do //skip length of search string
  begin
    if PByte(Cardinal(pBuffer) + i)^ = pSearchFor^ then //find first byte
    begin
      bFound := True; //assume we ok
      for j := 1 to SearchLen - 1 do
      begin
        if PByte(Cardinal(pBuffer) + i + j)^ <> PByte(Cardinal(pSearchFor) + j)^ then
        begin
          bFound := False;
          Break;
        end;
      end;

      if bFound then //after successful loop
      begin
        Result := PByte(Cardinal(pBuffer) + i);
        Exit;
      end;
    end;
  end;
end;

Open in new window


usage (you can pass any kind of buffer not string only):
  s1 := '1234567890';
  s2 := '890';

  if FindByteArrayInArray(PByte(PChar(s2)), 3, PByte(PChar(s1)), 10) <> nil then
 ....

Open in new window

0
 
drake08Author Commented:
That's hard stuff..
No I'm not building malware but kind of protecting software. The function you provided is working but not on my need. I can't get it working with readprocessmemory. If I use this:

buf: array of byte;
s1 := '100';
 if FindByteArrayInArray(PByte(PChar(s1), 3, PByte(PChar(buf[0]), sizeOf(buf)) <> nil then
  //do something

Open in new window


 along with ReadProcessMemory function nothing is found. So i'm wondering why.. but  your example works great.
0
 
Sinisa VukCommented:
Try to define:
var
  buff: PByte ;
...
  GetMem(buff, mbi.RegionSize);
  ReadProcessMemory(pHandle, Mbi.BaseAddress, buff, Mbi.RegionSize,             BytesRead);

  if BytesRead>0 then
  begin
     s1:='100'; //which is in bytes:  #$31 + #$30 + #$30
     if FindByteArrayInArray(PByte(PChar(s1), 3, buff, BytesRead) <> nil then
 .....

  end;

  FreeMem(buff);

Open in new window

0
 
drake08Author Commented:
var s, s1: String;
s3: Integer;

begin
  s := '19';
  s1:= '519';
  s3:= 0;

  if FindByteArrayInArray(PByte(PChar(s)), 3, PByte(PChar(s1)), 10) <> nil then
    s3 := 1;
end;

Open in new window


s3 will get 1 which is not good for me.
@Sinisa, your function is checking only for occurrences in memory not for exact value.
I need to get s3 := 1 only if the value := '19'.( for example)

@mlmcc, I just want to check wether or not a program have some value in memory.Seems like you missunderstood the question.
0
 
mlmccCommented:
I understand the question just need to understand the reason for writing the program.

Are you trying to read the memory of the application that is running or another application (exe) file.
0
 
drake08Author Commented:
Another application.
0
 
drake08Author Commented:
Only a line of code missed from my code to work like I wanted and nobody was able to write(or to say how should I do) that except Sinisa who wrote something even if wasn't helpfull.. but at least he tried.I tought this community is much helpfull than others which are free of charge.I think I was wrong.No problem ..
0
 
Sinisa VukCommented:
EE is full of similar topics (not in Delphi, but...). One can help too:
http://www.experts-exchange.com/Programming/Editors_IDEs/Q_24029781.html

This is my example, because your is full of errors. I found window handle and get process id for it. Made adjustments to read buffer properly.
function FindByteArrayInArray(pSearchFor: PByte; SearchLen: Cardinal; pBuffer: PByte; BufLen: Cardinal): PByte;
var
  i, j: Cardinal;
  bFound: Boolean;
begin
  Result := nil;

  if SearchLen > BufLen then Exit;
  
  if SearchLen = 0 then
  begin
    Result := pBuffer;
    Exit;
  end;

  for i := 0 to BufLen - SearchLen do //skip length of search string
  begin
    if PByte(Cardinal(pBuffer) + i)^ = pSearchFor^ then //find first byte
    begin
      bFound := True; //assume we ok
      for j := 1 to SearchLen - 1 do
      begin
        if PByte(Cardinal(pBuffer) + i + j)^ <> PByte(Cardinal(pSearchFor) + j)^ then
        begin
          bFound := False;
          Break;
        end;
      end;

      if bFound then //after successful loop
      begin
        Result := PByte(Cardinal(pBuffer) + i);
        Exit;
      end;
    end;
  end;
end;

procedure TForm1.Button7Click(Sender: TObject);
var
  err: DWORD;
  sysinfo: TSystemInfo;
  Handle: THandle;
  Mbi: TMemoryBasicInformation;
  Addr: DWORD_PTR;
  BytesRead: DWORD;
  buff: Array of Byte;
  f: TFileStream;
  hWin, ProcId, BuffSize: Cardinal;
  Process: TPROCESSENTRY32;
  sSearchStr: String;
begin
  ProcId := 0;
  BuffSize := 0;
  sSearchStr := Edit1.Text;

  GetSystemInfo(sysinfo);

  hWin := FindWindow(nil, 'Caption of window put here'); // class can be added too
  if hWin > 0 then
    GetWindowThreadProcessID(hWin, @ProcId);  //get process id - not fixed one as you do
  if ProcId > 0 then
  begin
    Handle := OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, false, ProcId); //avoid PROCESS_ALL_ACCESS
    if Handle <> 0 then
    begin
      Addr := dword(sysinfo.lpMinimumApplicationAddress);
      while (Addr < DWORD_PTR(sysinfo.lpMaximumApplicationAddress)) do
      begin
        if VirtualQueryEx(Handle, Ptr(Addr), Mbi, SizeOf(Mbi)) = 0 then
        begin
          err := GetLastError;
          inc(Addr, sysinfo.dwPageSize);
          continue;
        end;

        if (Mbi.RegionSize > BuffSize) then //optimization
        begin
          BuffSize := Min(Mbi.RegionSize, 64*1024); //limit buff size
          SetLength(buff, BuffSize);
        end;

        if ReadProcessMemory(Handle, Mbi.BaseAddress, @Buff[0], Min(BuffSize, Mbi.RegionSize), BytesRead) then
        begin
          //go search
          if BytesRead > 0 then
          begin
            if FindByteArrayInArray(PByte(PChar(sSearchStr)), Length(sSearchStr), @Buff[0], BytesRead) <> nil then
              ShowMessage('Found: ');
          end;
        end;

        if Addr + BuffSize < Addr then
          break;
        Addr := Addr + BuffSize;
      end;
      SetLength(buff, 0);
      CloseHandle(Handle);
    end;
  end;
end;

Open in new window

0
 
drake08Author Commented:
Sinisa, my code isn't just that I posted on the first post and I'm not getting any errors. I am getting process handle (code on first post is only for some test only) and after I'm going with VirtualQueryEx.All was good except I haven't know how to search in memory block.I have used 'Pos' on buffer and was alright.  Thanks anyway.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Cloud Class® Course: Microsoft Azure 2017

Azure has a changed a lot since it was originally introduce by adding new services and features. Do you know everything you need to about Azure? This course will teach you about the Azure App Service, monitoring and application insights, DevOps, and Team Services.

  • 7
  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now