Listing all memory pages allocated by all accesible processes

How to list all memory pages allocated by all accesible processes

Create a form with a button and a treeview, name the treeview tvwProcessList. Name the button btnProcessList.



uses Windows;



procedure TForm1.btnProcessListClick(Sender: TObject);

var i,l:integer;

    pid:THandle;

    meminfo:MEMORY_BASIC_INFORMATION;

    memstart:pointer;

    memsize:Integer;

    s,attr:String;

    totuse:Integer;

    lpMsgBuf : PCHAR;

    pn, pidn, ln:TTreeNode;

begin

  btnProcessList.Enabled := false;

  tvwProcessList.Items.Clear;

  pn:=tvwProcessList.Items.AddFirst (nil, 'This computer');



  for i:=0 to 2000 do //

    begin //PROCESS_QUERY_INFORMATION

      pid:=OpenProcess (PROCESS_ALL_ACCESS{PROCESS_VM_OPERATION or PROCESS_QUERY_INFORMATION or PROCESS_VM_WRITE}, false, i*4);

      if pid<>0 then

        begin

          //add treenode:



          pidn := tvwProcessList.Items.AddChild (pn, IntToStr(i*4{pid}));

          memstart := 0;

          totuse := 0;

          l:=VirtualQueryEx (pid,

                          memstart,

                          MemInfo,

                          SizeOf(MEMORY_BASIC_INFORMATION));

          while (l=SizeOf(MEMORY_BASIC_INFORMATION)) do

            begin

              if Application.Terminated then

                exit;

              if meminfo.State=MEM_COMMIT then

                begin

                  totuse := totuse+meminfo.RegionSize;

                  attr := '';

                  if (0<>meminfo.Protect and PAGE_NOACCESS) then

                    attr := attr+'NO ACCESS ';

                  if (0<>meminfo.Protect and PAGE_READONLY) then

                    attr := attr+'READONLY ';

                  if (0<>meminfo.Protect and PAGE_READWRITE) then

                    attr := attr+'READWRITE ';

                  if (0<>meminfo.Protect and PAGE_WRITECOPY) then

                    attr := attr+'WRITECOPY ';

                  if (0<>meminfo.Protect and PAGE_EXECUTE) then

                    attr := attr+'EXECUTE ';


                  if (0<>meminfo.Protect and PAGE_EXECUTE_READ) then

                    attr := attr+'EXECUTE_READ ';

                  if (0<>meminfo.Protect and PAGE_EXECUTE_READWRITE) then

                    attr := attr+'EXECUTE_READWRITE ';

                  if (0<>meminfo.Protect and PAGE_EXECUTE_WRITECOPY) then

                    attr := attr+'EXECUTE_WRITECOPY ';

                  if (0<>meminfo.Protect and PAGE_GUARD) then

                    attr := attr+'GUARD ';

                  if (0<>meminfo.Protect and PAGE_NOCACHE) then

                    attr := attr+'NOCACHE ';



                  ln := tvwProcessList.Items.AddChild (pidn,

                           Format ('Attr: %d: %s, Base: %d, size: %d',

                                   [meminfo.protect, attr, integer(meminfo.BaseAddress), meminfo.RegionSize]));

                  Application.ProcessMessages;

                end;

              integer(memstart) := integer(meminfo.BaseAddress)+meminfo.regionsize;

              integer(memstart):=integer(memstart)+memsize;

              l:=VirtualQueryEx (pid,

                              memstart,

                              MemInfo,

                              SizeOf(MEMORY_BASIC_INFORMATION));

            end;

           pidn.Text := Format ('pid: %d, allocated: %d', [i*4, totuse]);



         end;

      CloseHandle(pid);

    end;

  btnProcessList.Enabled := true;

end;



Explanetion:

The windows process ID is always a multiply of 4. SO, accessing process nr. 8 will access the same process as handle 9,10 and 11.

We simply loop a list of possible ID's. There are better ways to do this, but that is outside the scope of this article, and this method works just fine.

IF we have openened a process, we list the first page. We add the size of this page to the start address of the next page to retrieve.

Not all pages are allocated, we can verify this with the MEM_COMMIT tag.

If a page is commited, we examine the attributes, and add a tree node.

This can take a while (especially adding all those tree nodes).

After we are finished, we close the processhandle with CloseHandle. Be very sure to do this!!! Not closing the handle will lead to funny results, and if you do this several times you may well end in having to reboot your system sincew everything gets slow.

 

Share this article!

Follow us!

Find more helpful articles: