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

📄 symbolhandler.pas.svn-base

📁 这是一段游戏修改工具的源代码.ring3功能由dephi开发,驱动是C开发.希望对大家有帮助
💻 SVN-BASE
📖 第 1 页 / 共 2 页
字号:
    end;
  modulelistMREW.endread;
end;

function TSymhandler.getmodulebyname(modulename: string; var mi: TModuleInfo):BOOLEAN;
var i: integer;
begin
  result:=false;
  modulelistMREW.beginread;
  for i:=0 to modulelistpos-1 do
    if (uppercase(modulelist[i].modulename)=uppercase(modulename)) then
    begin
      mi:=modulelist[i];
      result:=true;
      break;
    end;
  modulelistMREW.endread;
end;

function TSymHandler.getsearchpath:string;
var sp: pchar;
begin
  getmem(sp,4096);
  if isloaded then
  begin
    if SymGetSearchPath(processhandle,sp,4096) then
    begin
      result:=sp;
    end
    else result:='';
  end;
end;

procedure TSymHandler.setsearchpath(path:string);
begin
  if isloaded then
    symsetsearchpath(processhandle,pchar(path));

  searchpath:=path;
end;


function TSymhandler.getNameFromAddress(address:dword;symbols:boolean; modules: boolean):string;
var symbol :PImagehlpSymbol;
    offset: dword;
    s: string;
    mi: tmoduleinfo;
    processhandle: thandle;
begin
{$ifdef autoassemblerdll}
  processhandle:=symbolhandler.processhandle;
{$else}
  if targetself then
  begin
    processhandle:=getcurrentprocess;
  end
  else
  begin
    processhandle:=cefuncproc.ProcessHandle;
  end;
{$endif}


  if symbols then
  begin
    //first see if it is a symbol
    symbolloadervalid.beginread;
    try
      if (symbolloaderthread<>nil) then
      begin
        if isloaded then
        begin
          getmem(symbol,sizeof(IMAGEHLP_SYMBOL)+255);
          try
            zeromemory(symbol,sizeof(IMAGEHLP_SYMBOL)+255);
            symbol.SizeOfStruct:=sizeof(IMAGEHLP_SYMBOL)+255;
            symbol.MaxNameLength:=254;
            if SymGetSymFromAddr(processhandle,address,@offset,symbol^) then
            begin
              //found it
              s:=pchar(@symbol.Name[0]);
              if offset=0 then
                result:=s
              else
                result:=s+'+'+inttohex(offset,1);
              exit;
            end;

          finally
            freemem(symbol);
          end;
        end;

      end;
    finally
      symbolloadervalid.endread;
    end;

    //check the userdefined symbols
    result:=self.GetUserdefinedSymbolByAddress(address);
    if result<>'' then exit;
  end;


  if modules then
  begin
    //get the dllname+offset
    if getmodulebyaddress(address,mi) then
    begin
      if address-mi.baseaddress=0 then
        result:=mi.modulename
      else
        result:=mi.modulename+'+'+inttohex(address-mi.baseaddress,1);
      exit;
    end;
  end;

  result:=inttohex(address,8);  //default

end;

function TSymhandler.getNameFromAddress(address:dword):string;
begin
  result:=getNameFromAddress(address,self.showsymbols,self.showmodules);
end;



function TSymhandler.getAddressFromName(name:string):dword;
begin
  result:=getAddressFromName(name,true);
end;

function TSymhandler.getAddressFromName(name: string; waitforsymbols: boolean):dword;
var mi: tmoduleinfo;
    newaddress: string;
    symbol :PImagehlpSymbol;
    oldoptions: dword;

    offset: dword;

    sn: string;
    i: integer;

    ws: widestring;
    pws: pwidechar;
    error: boolean;

    processhandle: thandle;
begin
{$ifdef autoassemblerdll}
  processhandle:=symbolhandler.processhandle;
{$else}
  if targetself then
  begin
    processhandle:=getcurrentprocess;
  end
  else
  begin
    processhandle:=cefuncproc.ProcessHandle;
  end;
{$endif}

  result:=0;

  val(ConvertHexStrToRealStr(name),result,i);
  if i=0 then exit; //it's a valid hexadecimal string


  try
    //first cut of the name from the offset
    offset:=0;
    for i:=length(name) downto 1 do
      if name[i] in ['+','-'] then
      begin
        sn:=copy(name,i+1,length(name));
        offset:=strtoint('$'+sn);

        if name[i]='-' then
          offset:=-offset;

        name:=copy(name,1,i-1);
        break;
      end
      else
      if name[i] in ['[',']'] then
        break;


  except
    raise symexception.create(sn+' is not a valid value');
  end;

  if name='' then name:='0';
  val('$'+name,result,i);
  if i=0 then
  begin
    result:=result+offset;
    exit; //it was a simple +/- calculation
  end;

  {
  debugger hell:
  tools->debugger options->Language Exceptions
  click add...
  type in "symexception" without the quotes

  this will cause you to still break on normal exception like memory access violations, but not on these
  }
  if getreg(uppercase(name),false)<>9 then
    raise symexception.create('Register'); //can happen in case of eax+# //speed improvement

   
  //see if it is a module
  if getmodulebyname(name,mi) then
    result:=mi.baseaddress+offset
  else
  begin


    //if not, see if you can find it as a symbol
    //first check the userdefined symbols (small list, so faster than the symbols)
    result:=GetUserdefinedSymbolByName(name);
    if result<>0 then
    begin
      result:=result+offset;
      exit;
    end;

    {$ifndef autoassemblerdll}
    if (darkbytekernel<>0) and (length(name)>6) and (pos('KERNEL_',uppercase(name))>0) then
    begin
      name:=copy(name,8,length(name)-7);
      ws:=name;
      pws:=@ws[1];
      result:=dword(GetKProcAddress(pws));
      if result<>0 then
      begin
        result:=result+offset;
        exit;
      end;
    end;
    {$endif}

    { 5.4: check if it is a pointer notation }
    result:=GetAddressFromPointer(name,error);
    if not error then
    begin
      result:=result+offset;
      exit;
    end;
    { 5.4 ^^^ }


    symbolloadervalid.beginread;
    try
      if (symbolloaderthread<>nil) then
      begin
        if symbolloaderthread.isloading and not waitforsymbols then
          raise symexception.create('This is not a valid address');

        symbolloaderthread.WaitFor; //wait for it to finish if it's still busy
        //it's not a valid address, it's not a calculation, it's not a modulename+offset, so lets see if it's a module

        getmem(symbol,sizeof(IMAGEHLP_SYMBOL)+255);
        try
          zeromemory(symbol,sizeof(IMAGEHLP_SYMBOL)+255);
          symbol.SizeOfStruct:=sizeof(IMAGEHLP_SYMBOL)+255;
          symbol.MaxNameLength:=254;
          if SymGetSymFromName(processhandle,pchar(name),symbol^) then
            result:=symbol.Address+offset
          else
            raise symexception.Create('This is not a valid address');   //no hex string, no module, no symbol, so invalid
        finally
          freemem(symbol);
        end;
      end else
        raise symexception.Create('This is not a valid address');

    finally
      symbolloadervalid.endread;
    end;   
  end;

end;


procedure TSymhandler.loadmodulelist;
var
  ths: thandle;
  me32:MODULEENTRY32;
  x: pchar;

  processid: dword;
begin
{$ifdef autoassemblerdll}
  processid:=symbolhandler.ProcessID;
{$else}
  if targetself then
    processid:=getcurrentprocessid
  else
    processid:=cefuncproc.ProcessID;
{$endif}
  
  modulelistMREW.BeginWrite;
  try
    modulelistpos:=0;
    if processid=0 then exit;

    //refresh the module list
    ths:=CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,processid);
    if ths<>0 then
    begin
      me32.dwSize:=sizeof(MODULEENTRY32);
      if ths<>0 then
      begin
        try
          if module32first(ths,me32) then
          repeat
            if modulelistpos+1>=length(modulelist) then
              setlength(modulelist,length(modulelist)*2);

            x:=me32.szExePath;
            modulelist[modulelistpos].modulename:=extractfilename(x);
            modulelist[modulelistpos].baseaddress:=dword(me32.modBaseAddr);
            modulelist[modulelistpos].basesize:=me32.modBaseSize;
            inc(modulelistpos);

          until not module32next(ths,me32);
        finally
          closehandle(ths);
        end;
      end;
    end;
  finally
    modulelistmrew.EndWrite;
  end;
end;

function TSymhandler.GetAddressFromPointer(s: string; var error: boolean):dword;
{
Will return the address of a pointer noted as [[[xxx+xx]+xx]+xx]+xx
If it is a invalid pointer, or can not be resolved, the result is NULL 
}
var i: integer;
    list: tstringlist;
    offsets: array of dword;
    baseaddress: dword;
    off: string;
    realaddress, realaddress2: dword;
    check: boolean;
    count: dword;
begin
  result:=0;
  error:=true;

  list:=tstringlist.create;
  try
    if not ParseAsPointer(s,list) then exit;

    try
      baseaddress:=getaddressfromname(list[0]);
    except
      exit;
    end;

    setlength(offsets,list.count-1);
    for i:=1 to list.Count-1 do //start from the first offset
    begin
      off:=copy(list[i],2,length(list[i]));
      try
        offsets[i-1]:=strtoint('$'+off);
      except
        exit;
      end;
      if list[i][1]='-' then
        offsets[i-1]:=-offsets[i-1];
    end;

    //still here so notation was correct and baseaddress+offsets are filled in
    //now read
    realaddress2:=baseaddress;
    for i:=0 to length(offsets)-1 do
    begin
      check:=readprocessmemory(processhandle,pointer(realaddress2),@realaddress,4,count);
      if check and (count=4) then
        realaddress2:=realaddress+offsets[i]
      else
        exit;
    end;

    result:=realaddress2;
    error:=false;
  finally
    list.free;
  end;
end;

function TSymhandler.ParseAsPointer(s: string; list:tstrings): boolean;
var i: integer;
    prolog: boolean;
    currentlevel: integer;
    temps: string;
    ispointer: boolean;
begin
  //parse the string
  result:=false;
  currentlevel:=0;
  prolog:=true;
  temps:='';
  ispointer:=false;
  
  for i:=1 to length(s) do
  begin
    if s[i]='[' then
    begin
      if prolog then
      begin
        inc(currentlevel);
        ispointer:=true;
      end
      else
        exit; //bracket open after the prolog is not allowed
    end
    else
    begin
      if prolog then
      begin
        if not (s[i] in [#8,' ']) then  //no space or tab
          prolog:=false;
      end;

      if not prolog then
      begin
        //definition, currentlevel is set, now parse till last ] (currentlevel=0)
        if s[i]=']' then //end of a level
        begin
          dec(currentlevel);
          if temps='' then temps:='+0';          
          list.Add(temps);

          temps:='';

          if currentlevel<0 then exit;
          continue;
        end
        else
          temps:=temps+s[i];
      end;
    end;
  end;


  if temps='' then temps:='+0';
  if (ispointer) and (temps<>'') then list.Add(temps);
  if currentlevel>0 then exit;

  result:=ispointer;
end;


destructor TSymhandler.destroy;
begin
  if symbolloaderthread<>nil then
  begin
    symbolloaderthread.Terminate;
    symbolloaderthread.WaitFor;
    symbolloaderthread.free;
  end;


  symbolloadervalid.Free;
  modulelistMREW.free;
  userdefinedsymbolsMREW.free;
  setlength(userdefinedsymbols,0);
  setlength(modulelist,0);
end;

constructor TSymhandler.create;
begin
  symbolloadervalid:=TMultiReadExclusiveWriteSynchronizer.create;
  modulelistMREW:=TMultiReadExclusiveWriteSynchronizer.create;
  userdefinedsymbolsMREW:=TMultireadExclusiveWriteSynchronizer.create;

  setlength(userdefinedsymbols,32);
  setlength(modulelist,32);

  showmodules:=false;
  showsymbols:=true;
end;



initialization
  symhandler:=tsymhandler.create;
  selfsymhandler:=Tsymhandler.create;
  selfsymhandler.targetself:=true;

finalization
  selfsymhandler.free;
  symhandler.free;
  
end.





⌨️ 快捷键说明

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