ホーム > カテゴリ > HTML5・JavaScript >

EXE/DLLなどのリソースの文字列を編集する[iResEditor.js]

オープンソースの「iResEditor.js」を使用してEXE/DLLファイルなどの実行ファイルのリソースの文字列を編集する方法です。

iResEditor.jsの入手

iResEditor
http://www.petitmonte.com/labo/iResEditor/

サンプルの実行結果

[実行前]

[実行後]

サンプルコード - Sample code

次のコードは「Menu,Dialog,String Table」の全てのリソースに「add」の文字列を追加します。編集が完了したらファイルを出力します。

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="zip.min.js"></script>
<script src="iResEditor.js"></script>
<script>
 
function onDragOver(event){ 
  event.preventDefault(); 
} 
  
function onDrop(event){
  onAddFile(event);
  event.preventDefault(); 
}  
 
function onAddFile(event) {
  var files;
  var reader = new FileReader();
  var filename;
  
  if(event.target.files){
    files = event.target.files;
  }else{ 
    files = event.dataTransfer.files;   
  }    
 
  reader.onload = function (event) {
    var stream = new Uint8Array(reader.result);  
    var addString = ' add'; // 追加する文字列
    
    try{
      
      // PEファイルの読み込み
      var ResEditor = new TResEditor(filename);
      ResEditor.LoadFromStream(stream,true,true);  
      
      console.log(ResEditor);
      
      if(ResEditor.PEAnalyst.IsPacked){
        alert('このファイルは圧縮されています。');
        return;
      }
            
      if(ResEditor.Edit.Menu.length   === 0 &&
         ResEditor.Edit.Dialog.length === 0 &&
         ResEditor.Edit.String.length === 0){
        alert('このファイルには編集可能なリソースはありません。');
        return;
      }
        
      // 全ての「Menu」の文字列を変更する  
      var Menu = ResEditor.Edit.Menu;
      if(Menu.length !==0){    
        for(var i=0;i<Menu.length;i++){    
          for(var j=0;j<Menu[i].resObject.Items.length;j++){
            // セパレータ以外
            if(Menu[i].resObject.Items[j].menuText !== '-'){
              Menu[i].resObject.Items[j].menuText = Menu[i].resObject.Items[j].menuText + addString;
            }
          } 
        }
      }else{
        console.log('Menu None');
      } 
      
      // 全ての「Dialog」の文字列を変更する  
      var Dialog = ResEditor.Edit.Dialog;
      if(Dialog.length !==0){    
        var DS_SETFONT = 64;
         
        for(var i=0;i<Dialog.length;i++){    
          
          // 通常版と拡張版
          var DlgTemplate,DlgItemTemplate;
          if(Dialog[i].resObject.DlgTemplate){
            DlgTemplate = Dialog[i].resObject.DlgTemplate;
            DlgItemTemplate = Dialog[i].resObject.DlgItemTemplate;
          }else{
            DlgTemplate = Dialog[i].resObject.DlgTemplateEx;
            DlgItemTemplate = Dialog[i].resObject.DlgItemTemplateEx;        
          }
          
          // 親ウインドウの文字列の変更
          DlgTemplate.title = DlgTemplate.title + addString;
          
          // フォントがある場合
          if((DlgTemplate.style & DS_SETFONT) === DS_SETFONT){
            // フォント名の変更
            // DlgTemplate.typeface = 'font name';
            // フォントサイズの変更
            // DlgTemplate.pointsize = 8;
          }
          
          // コントロール    
          for(var j=0;j<DlgItemTemplate.length;j++){
            // 文字列型
            if(typeof DlgItemTemplate[j].title === "string"){ 
              DlgItemTemplate[j].title = DlgItemTemplate[j].title + addString;
            } 
          } 
        }
      }else{
        console.log('Dialog None');
      }       
      
      // 全ての「String Table」の文字列を変更する  
      var StringTable = ResEditor.Edit.String;
      if(StringTable.length !==0){   
        for(var i=0;i<StringTable.length;i++){
          for(var j=0;j<StringTable[i].resObject.ID.length;j++){
            // NULL以外
            if(StringTable[i].resObject.Value[j] !== ''){
              StringTable[i].resObject.Value[j] = StringTable[i].resObject.Value[j]  + addString;
            }
          } 
        } 
      }else{
        console.log('String Table None');
      } 
      
      // この1つのメソッドでも保存できます。
      // ただし、IE/Edgeではセキュリティ制限でダウンロードできません。
      // ResEditor.SaveToFile('test.exe');
            
      var zip = new Zlib.Zip();    
      var stream = ResEditor.SaveToStream();
      
      // 拡張子の取得 
      var ext = ResEditor.FileName.split('.');
      ext = '.' + ext[ext.length-1];
        
      // ZIP(無圧縮)
      zip.addFile(stream,{'filename': PE_ConvertArray('test' + ext),
                          'compressionMethod':Zlib.Zip.CompressionMethod.STORE});
      var compressed = zip.compress();
      
      // ダウンロード
      var F = new TFileStream();
      F.WriteStream(compressed);
      F.SaveToFile('test.zip'); 
        
    }catch(e){
      alert('Error : ' + e);
    }
  };
  
  if (files[0]){    
    filename = files[0].name;
    reader.readAsArrayBuffer(files[0]); 
    document.getElementById("inputfile").value = '';
  }
}        
</script>  
</head>
<body ondrop="onDrop(event);" ondragover="onDragOver(event);"> 
<div style="height:500px;width:500px;">
  <input type="file" id="inputfile" onchange="onAddFile(event);" >
</div>
</body>
</html> 

実行ファイルのリソースを書き換えるには複雑な「PEフォーマット」と「各リソースのフォーマット」をマスターしていないと実現できません。でも、このライブラリを使用するとこれだけのコードでリソースを変更できます。

ただ、リソースのある程度の知識がないと、扱うのは難しいかもしれません。

注意事項

ブラウザから入手した実行ファイルを実行すると
 ・WindowsによってPCが保護されました。 (Windows 8/10の場合)
 ・発行元を確認できませんでした。 (Windows 7の場合)
という警告メッセージが表示されます。回避方法はFAQをご覧ください。

iResEdtor関連記事

リソースの文字列を編集する
リソースをRCファイルへ変換する
リソースをRESファイルへ変換する
リソースをバイナリファイルで抽出する
コードセクションを抽出する
データセクションを抽出する
全てのセクションを抽出する
エキスポート情報をCSVに変換する
インポート情報をテキストに変換する
隠しコードを取得する
リソースをTreeViewで表示する





関連記事



公開日:2016年07月21日
記事NO:02077