⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pointerscannerfrm.pas.svn-base

📁 这是一段游戏修改工具的源代码.ring3功能由dephi开发,驱动是C开发.希望对大家有帮助
💻 SVN-BASE
📖 第 1 页 / 共 4 页
字号:
  if results.Size>25*1024*1024 then //bigger than 25mb
    flushresults;

end;

procedure TReverseScanWorker.rscan(address:dword; level: integer);
{
scan through tht memory for a address that points in the region of level, if found, recursive call till level maxlevel
}
var p: ^byte;
    pd: ^dword absolute p;
    maxaddress: dword;
    AddressMinusMaxStructSize: dword;
    found: boolean;
    i,j: integer;
    createdworker: boolean;

    mi: tmoduleinfo;
begin
  if (level>=maxlevel) or
     (symhandler.getmodulebyaddress(address,mi)) then //static address
  begin
    //reached max level, store this results entry
    StorePath(level-1);
    exit;
  end;

  if self.staticscanner.Terminated then
    exit;


  
  p:=vm.GetBuffer;
  AddressMinusMaxStructSize:=address-structsize;
  maxaddress:=dword(p)+vm.GetBufferSize;


  while dword(p)<maxaddress do
  begin
    if (pd^<=address) and
       (pd^>AddressMinusMaxStructSize) then
    begin
      //found one
      found:=true;
      tempresults[level]:=vm.PointerToAddress(p);

      //check if I can offload it to another thread
      if staticscanner.isdone and ((level+1)<maxlevel) then //best only do it when staticscanner is done
      begin
        createdworker:=false;
        reverseScanCS.Enter;
        
        //scan the worker thread array for a idle one, if found use it
        for i:=0 to length(staticscanner.reversescanners)-1 do
        begin
          if staticscanner.reversescanners[i].isdone then
          begin
            staticscanner.reversescanners[i].isdone:=false;
            staticscanner.reversescanners[i].maxlevel:=maxlevel;
            staticscanner.reversescanners[i].addresstofind:=addresstofind; //in case it wasn't set yet...

            staticscanner.reversescanners[i].startaddress:=vm.PointerToAddress(p);
            for j:=0 to maxlevel-1 do
              staticscanner.reversescanners[i].tempresults[j]:=tempresults[j]; //copy results

            staticscanner.reversescanners[i].startlevel:=level;
            staticscanner.reversescanners[i].structsize:=structsize;
            staticscanner.reversescanners[i].startworking.SetEvent;
            break;
          end;
        end;

        reverseScanCS.Leave;

        if createdworker then continue;  //stop processing the rest of this routine and continue scanning
      end;


      rscan(tempresults[level],level+1);
      //messagebox(0,pchar(inttohex(address,8)),'',0);
    end;

    if alligned then
      inc(pd) //dword pointer+1
    else
      inc(p); //byte pointer+1
  end;

  if (not found) and (not staticonly) then
  begin
    //nothing was found, let's just say this is the final level and store it...
    StorePath(level-1);
  end;
end;

procedure TStaticScanner.reversescan;
{
Do a reverse pointer scan
The level0 seperately so it's easier to spawn of the child threads.
Of course, if there's only 1 top level entry it only spawns 1 thread... but someday
I may update it to spawn the threads inside a recursive function... (hmm, or not)
}
var p: ^byte;
    pd: ^dword absolute p;
    maxaddress: dword;
    automaticAddressMinusMaxStructSize: dword;

    results: array of dword;
    i,j: integer;
    alldone: boolean;
begin
    //scan the buffer
    fcount:=0; //debug counter to 0
    scount:=0;

    maxlevel:=maxlevel-1; //adjustment for this kind of scan

    setlength(results,maxlevel);
    p:=vm.GetBuffer;
    automaticAddressMinusMaxStructSize:=automaticAddress-sz;


    maxaddress:=dword(p)+vm.GetBufferSize;

    lastaddress:=pointer(maxaddress); //variable for progressbar calculation
    currentaddress:=p;
    firstaddress:=p;
    j:=0;
    
    start:=gettickcount;
    while dword(p)<maxaddress do
    begin
      if (pd^<=automaticaddress) and
         (pd^>automaticAddressMinusMaxStructSize) then
      begin
        //found one
        //activate a worker thread to do this path
        reversescansemaphore.Aquire; //aquire here, the thread will release it

        //quick check if we didn't wait to long and the user clicked terminate
        if terminated then
        begin
          reversescansemaphore.release;
          break;
        end;

        //find an inactive thread
        for i:=0 to length(reversescanners)-1 do
        begin
          if reversescanners[i].isdone then
          begin
            reversescanners[i].isdone:=false;
            reversescanners[i].maxlevel:=maxlevel;

            reversescanners[i].startaddress:=vm.PointerToAddress(p);
            reversescanners[i].addresstofind:=self.automaticaddress;
            reversescanners[i].tempresults[0]:=reversescanners[i].startaddress;
            reversescanners[i].startlevel:=0;
            reversescanners[i].structsize:=sz;
            reversescanners[i].startworking.SetEvent;
            break;
          end;
        end;


        //results[0]:=vm.PointerToAddress(p);
        //rscan(results[0],1,results);
        //messagebox(0,pchar(inttohex(address,8)),'',0);
      end;

      if unalligned then
        inc(p) //byte pointer+1
      else
        inc(pd); //dword pointer+1

      currentaddress:=p;
    end;

    isdone:=true;
    alldone:=false;
    //wait till all threads are in isdone state
    while (not alldone) do
    begin
      sleep(500);
      alldone:=true;

      //no need for a CS here since it's only a read, and even when a new thread is being made, the creator also has the isdone boolean to false
      for i:=0 to length(reversescanners)-1 do
      begin
        if not reversescanners[i].isdone then
        begin
          alldone:=false;
          break;
        end;
      end;
    end;


    setlength(filenames,length(reversescanners));

    for i:=0 to length(reversescanners)-1 do
    begin
      reversescanners[i].stop:=true;
      reversescanners[i].startworking.SetEvent;  //run it in case it was waiting
      reversescanners[i].WaitFor; //wait till this thread has terminated because the main thread has terminated
      reversescanners[i].flushresults;  //write results to disk
      filenames[i]:=reversescanners[i].filename;
      reversescanners[i].Free;
    end;

    postmessage(frmpointerscanner.Handle,staticscanner_done,0,0);
    terminate;
    freeandnil(reversescansemaphore);


    stop:=gettickcount;
    messagebox(0,pchar('Delta Tickcount='+inttostr(stop-start)+' found='+inttostr(fcount)),'',mb_ok);

end;

procedure TStaticScanner.execute;
var
    i,j,k: integer;
    x,opcode:string;

    t:dword;
    hexcount,hexstart: integer;
    isstruct: boolean;
    isstatic: boolean;
    found: boolean;

    mbi: _MEMORY_BASIC_INFORMATION;

    tn,tempnode: ttreenode;
    th: TDissectData;
    lastnode: ttreenode;
    oldshowsymbols: boolean;
    oldshowmodules: boolean;


    bitcount: integer;

    scanregions: tmemoryregions;
    currentregion: integer;
    maxpos: dword;
    dw: byte;

begin
  if terminated then exit;

  if (vm<>nil) and (not reuse) then
    freeandnil(vm);  //free so the next piece of code will do a whole new scan

  if vm=nil then
  begin
    phase:=1;
    progressbar.Position:=0;  
    vm:=tvirtualmemory.Create(filterstart,filterstop,progressbar);
  end;


  phase:=2;
  progressbar.Position:=0;
  
  currentpos:=pointer(start);





  i:=0;

  if reverse then
  begin
    reverseScanCS:=tcriticalsection.Create;
    try
      reverseScanSemaphore:=tsemaphore.create(threadcount);
      setlength(reversescanners,threadcount);
      for i:=0 to threadcount-1 do
      begin
        reversescanners[i]:=TReverseScanWorker.Create(true);
        reversescanners[i].Priority:=scannerpriority;
        reversescanners[i].staticscanner:=self;
        setlength(reversescanners[i].tempresults,maxlevel);
        setlength(reversescanners[i].offsetlist,maxlevel);
        reversescanners[i].staticonly:=staticonly;
        reversescanners[i].alligned:=not self.unalligned;


        reversescanners[i].Resume;
      end;
      reversescan;
    finally
      reverseScanCS.Free;
    end;

  end
  else
  begin
    Method2semaphore:=tsemaphore.create(threadcount);
    setlength(method2scanners,threadcount);
    for i:=0 to threadcount-1 do
    begin
      method2scanners[i]:=tmethod2scanner.create(false);
      method2scanners[i].Priority:=scannerpriority;
    end;


    try
      //create some regions it should scan
      setlength(scanregions,0);

      if not unallignedbase then
      begin
        if (start mod 4)>0 then
          start:=start+(4-(start mod 4));
      end;

      symhandler.fillMemoryRegionsWithModuleData(scanregions,start,stop-start);


      if length(scanregions)=0 then
      begin
        //no memory found (e.g failed to open process)
        setlength(scanregions,1);
        scanregions[0].BaseAddress:=start;
        scanregions[0].MemorySize:=stop-start;
        scanregions[0].IsChild:=false;
        scanregions[0].startaddress:=nil;
      end;

      currentregion:=0;
      currentpos:=pointer(scanregions[currentregion].BaseAddress);

      progressbar.Position:=0;
      progressbar.Max:=stop-start;

      maxpos:=scanregions[currentregion].BaseAddress+scanregions[currentregion].MemorySize-4;

      while (not terminated) and (dword(currentpos)<=stop) do
      begin
        isstatic:=false;

        try
          if ((pdword(vm.AddressToPointer(dword(currentpos)))^ mod 4)=0) or (unalligned) then //unaligned check after the first one so it includes a readable check
            isstatic:=true;

          if (writableonly) and ((dword(currentpos) mod 4096)=0) then
          begin
            if vm.isbadwriteptr(currentpos,4) then
            begin
              inc(pbyte(currentpos),4096);

              isstatic:=false;
              if dword(currentpos)>=maxpos then
              begin
                inc(currentregion);
                if currentregion=length(scanregions) then break; //no more regions
                currentpos:=pointer(scanregions[currentregion].BaseAddress);

                maxpos:=scanregions[currentregion].BaseAddress+scanregions[currentregion].MemorySize-4;
              end;

              inc(i);
              i:=i mod 40;
              if i=0 then progressbar.position:=(dword(currentpos)-start);
              continue;

            end;

          end;


          if isstatic and (pdword(vm.AddressToPointer(dword(currentpos)))^>=filterstart) and (pdword(vm.AddressToPointer(dword(currentpos)))^<=filterstop) then
          begin
            method2scan(dword(currentpos));
          end;

          inc(i);
          i:=i mod 40;
          if i=0 then progressbar.position:=(dword(currentpos)-start);

          if unallignedbase then
            inc(pbyte(currentpos))
          else
            inc(pbyte(currentpos),4);

          if dword(currentpos)>=maxpos then
          begin
            inc(currentregion);
            if currentregion=length(scanregions) then break; //no more regions
            currentpos:=pointer(scanregions[currentregion].BaseAddress);

            maxpos:=scanregions[currentregion].BaseAddress+scanregions[currentregion].MemorySize-4;
          end;
        except
          inc(currentregion);
          if currentregion=length(scanregions) then break; //no more regions
          currentpos:=pointer(scanregions[currentregion].BaseAddress);

          maxpos:=scanregions[currentregion].BaseAddress+scanregions[currentregion].MemorySize-4;
        end;

      end;


      //done
    finally
      setlength(filenames,length(method2scanners));

      for i:=0 to length(method2scanners)-1 do
      begin
        method2scanners[i].stop:=true;
        method2scanners[i].startworking.SetEvent;  //run it in case it was waiting
        method2scanners[i].WaitFor; //wait till this thread has terminated because the main thread has terminated
        method2scanners[i].flushresults;
        filenames[i]:=method2scanners[i].filename; //save the filename
        method2scanners[i].Free;
      end;

      postmessage(frmpointerscanner.Handle,staticscanner_done,0,0);
      terminate;
      freeandnil(Method2semaphore);
    end;

  end;


  if (vm<>nil) and (not reuse) then
    freeandnil(vm);
    
end;



destructor TStaticscanner.destroy;
begin
  terminate;
  waitfor;
  inherited destroy;
end;

//---------------------------------main--------------------------

procedure Tfrmpointerscanner.Method3Fastspeedandaveragememoryusage1Click(
  Sender: TObject);
var
    i: integer;
begin

  start:=now;
  if frmpointerscannersettings=nil then
    frmpointerscannersettings:=tfrmpointerscannersettings.create(nil);

  if frmpointerscannersettings.Visible then exit; //already open, so no need to make again

  if vm<>nil then
    frmpointerscannersettings.cbreuse.Caption:='Reuse memory copy from previous scan';

  if frmpointerscannersettings.Showmodal=mrok then
  begin
    treeview2.Visible:=false;

    panel2.Visible:=false;
    open1.Enabled:=false;
    new1.enabled:=false;
    save1.Enabled:=false;
    rescanmemory1.Enabled:=false;


    incorrectresult:=0;
    continued:=0;
    pointersfound:=0;

    label1.Caption:='Matches found:';
    label2.Left:=label1.Left+label1.Width+5;

    timer2.Enabled:=true;

    treenodeswithchildrenpos:=0;
    matchednodespos:=0;


    //free the old critical section's
    for i:=0 to length(dissectedpointersLevelMREWS)-1 do
      dissectedpointersLevelMREWS[i].Free;

    setlength(dissectedpointersLevelpos,frmpointerscannersettings.maxlevel+1);
    setlength(dissectedpointersLevel,frmpointerscannersettings.maxlevel+1);
    setlength(dissectedpointersLevelMREWS,frmpointerscannersettings.maxlevel+1);

    for i:=0 to length(dissectedpointersLevelpos)-1 do
      dissectedpointersLevelpos[i]:=0;

    for i:=0 to length(dissectedpointersLevelMREWS)-1 do
      dissectedpointersLevelMREWS[i]:=TMultiReadExclusiveWriteSynchronizer.create;

    for i:=0 to length(dissectedpointerslevel)-1 do
      setlength(dissectedpointerslevel[i],1024*1024); //1mb default


    //possible paths cleaning and reinitialize
    for i:=0 to length(possiblepathslevelMREWS)-1 do
      possiblepathslevelMREWS[i].Free;

    setlength(possiblepathslevelpos,frmpointerscannersettings.maxlevel+1);
    setlength(possiblepathslevel,frmpointerscannersettings.maxlevel+1);
    setlength(possiblepathslevelMREWS,frmpointerscannersettings.maxlevel+1);

    for i:=0 to length(possiblepathslevelpos)-1 do
      possiblepathslevelpos[i]:=0;

    for i:=0 to length(possiblepathslevelMREWS)-1 do
      possiblepathslevelMREWS[i]:=TMultiReadExclusiveWriteSynchronizer.create;

    for i:=0 to length(possiblepathslevel)-1 do
      setlength(possiblepathslevel[i],1024*1024); //1mb default


    if staticscanner<>nil then
    begin
      staticscanner.free;
      staticscanner:=nil;
    end;

    //default scan
    staticscanner:=TStaticscanner.Create(true);

    try

      staticscanner.reverse:=frmpointerscannersettings.rbreverse.checked;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -