代码之家  ›  专栏  ›  技术社区  ›  curious slab

修改exe资源中的字符串

  •  2
  • curious slab  · 技术社区  · 16 年前

    如何修改 buffer 在下面的代码中,然后保存对可执行文件资源的更改?我在找类似的东西 SetString(handle,index,buffer,size) .

    var
      hExe : Cardinal;
      buffer : array [0..4097] of ansichar;
    begin
      hExe:=LoadLibraryEx(PAnsiChar(Edit2.Text),0,LOAD_LIBRARY_AS_DATAFILE);
      LoadString(hExe,65300,buffer,SizeOf(buffer));
      ShowMessage(buffer);
      //need to modify buffer here then I'll unload the resources..
    end;
    

    更新: 这是我对updateResource的尝试

    var
      hEXE: DWORD;
      pData: PAnsiChar;
    begin
      pData := PAnsiChar(Edit1.Text);
      hEXE := BeginUpdateResource(pchar(edit2.text), FALSE);
      if hEXE <> 0 then
      begin
        UpdateResource(hEXE, RT_string, MAKEINTRESOURCE(4082), LANG_NEUTRAL,
          @pData, Length(pData)); //if i change 4082 to 65300 it creates another key like 4082
        EndUpdateResource(hEXE, FALSE);
      end;
    

    这段代码把整个4082内容搞得一团糟。问题是rt_string中名为4082的项是字符串组。当我在资源编辑器中打开exe时,单击字符串表,然后单击4082,结果是:

    STRINGTABLE
    LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
    {
    65296,  "Unicode"
    65297,  "Big Endian Unicode"
    65298,  "UTF-8"
    65299,  "UTF-7"
    65300,  "ABCDE12345"
    }
    

    因此,我要么需要解析字符串组,要么需要一个API来设置组中索引为65300的修改字符串。有什么想法吗?

    4 回复  |  直到 13 年前
        1
  •  6
  •   Rob Kennedy    16 年前

    我找到了 the answer 使用谷歌。( English translation from Chinese )无论如何,谢谢大家!

    procedure UpdateResString(AFileName, ANewString: string; AStringIdent: Integer);
      procedure WriteToArray(AArray: TByteDynArray; AData: Word; var APos: Integer);
      begin
        AArray[APos] := Lo(AData);
        AArray[APos + 1] := Hi(AData);
        Inc(APos, 2);
      end;
    
      function ReadFromArray(AArray: TByteDynArray; APos: Integer): Word;
      begin
        Result := AArray[APos] + AArray[APos + 1] * 16;
      end;
    
    var
      hModule, hResInfo, hUpdate: THandle;
      ResData, TempData: TByteDynArray;
      wsNewString: WideString;
      iSection, iIndexInSection: Integer;
      i, iLen, iSkip, iPos: Integer;
    begin
      hModule := LoadLibrary(PChar(AFileName));
      if hModule = 0 then
        raise Exception.CreateFmt('file %s failed to load.', [AFileName]);
    
      // Calculate the resource string area and the string index in that area
      iSection := AStringIdent div 16 + 1;
      iIndexInSection := AStringIdent mod 16;
    
      // If the resource already exists, then read it out of the original data
      hResInfo := FindResource(hModule, MakeIntResource(iSection), RT_STRING);
      if hResInfo <> 0 then
      begin
        iLen := SizeOfResource(hModule, hResInfo);
        SetLength(ResData, iLen);
        CopyMemory(ResData, LockResource(LoadResource(hModule, hResInfo)), iLen);
      end;
      // Should first close the file, and then update
      FreeLibrary(hModule);
      // Calculate the new data is written to location
      wsNewString := WideString(ANewString);
      iLen := Length(wsNewString);
      iPos := 0;
      for i := 0 to iIndexInSection do
      begin
        if iPos > High(ResData) then
          SetLength(ResData, iPos + 2);
        if i <> iIndexInSection then
        begin
          iSkip := (ReadFromArray(ResData, iPos) + 1) * 2;
          Inc(iPos, iSkip);
        end;
      end;
    
      // Delete the original data and the data behind the temporary
      // storage of data to be added
      iSkip := (ReadFromArray(ResData, iPos) + 1) * 2;
      TempData := Copy(ResData, iPos + iSkip, Length(ResData) - iSkip);
      SetLength(ResData, iPos);
      SetLength(ResData, iPos + (iLen + 1) * 2 + Length(TempData));
    
      // Write new data
      WriteToArray(ResData, iLen, iPos);
      for i := 1 to iLen do
        WriteToArray(ResData, Ord(wsNewString[i]), iPos);
      // Write back to the original data
      for i := 0 to High(TempData) do
        ResData[iPos + i] := TempData[i];
    
      // Write the data back to file
      hUpdate := BeginUpdateResource(PChar(AFileName), False);
      if hUpdate = 0 then
        raise Exception.CreateFmt(
          'cannot write file %s. Please check whether it is open or set read-only.',
          [AFileName]);
    
      UpdateResource(hUpdate, RT_STRING, MakeIntResource(iSection), LANG_NEUTRAL,
        ResData, Length(ResData));
      EndUpdateResource(hUpdate, False);
    end;
    
        2
  •  3
  •   RRUZ    16 年前

    你可以看到 source code (Delphi 2006) XN Resource Editor (是一款适用于Windows 98、Windows 2000和Windows XP的免费、功能强大、功能齐全的资源编辑器和PE模块资源管理器)。

    此外,还应检查以下功能

    再见。

        3
  •  1
  •   Mohammed Nasman    16 年前

    有篇关于这个的文章 Delphi3000 :

    Resources inside .exe files

        4
  •  1
  •   skamradt    16 年前

    我相信你需要用包含你的修改的版本来替换整个组。这并不难解析,您可以走几条捷径。将所有内容加载到tstringlist中,然后循环列表,直到字符串以“65300”开头。执行替换并将字符串列表的文本部分保存为替换资源。