How to use iResEditor.js

[Table of contents]

1. Loading files
2. Writing of files
3. Details of each class
    TResEditor
    TPEAnalyst

First

You download iResEditor.js, and install in your environment.

Here we introduce the basic usage.

But when there is no knowledge of a certain degree of "PE format" and "each resource format", it may be difficult to use this class library.

1. Loading files

Load the executable file. Outputs the results to the browser console.

<!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);  
    
    try{
      
      // Reading of PE files
      var ResEditor = new TResEditor(filename);
      ResEditor.LoadFromStream(stream,true,true);  
      
      // Console to output
      console.log(ResEditor);   
      
    }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> 

[Result]

Following figure shows the console in Chrome.
To view the console, press the F12 key in your browser.

Resources in "Edit" property can be edit.

"PEAnalyst" property contains information such as the "header information of the executable file" and "resources" and "import", "export".

2. Writing of files

Following code adds character string of "add" to all resources of "Menu,Dialog,String Table". And, output.

<!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'; // String to add
    
    try{
      
      // Reading of PE files
      var ResEditor = new TResEditor(filename);
      ResEditor.LoadFromStream(stream,true,true);  
      
      console.log(ResEditor);
      
      if(ResEditor.PEAnalyst.IsPacked){
        alert('This file is compressed.');
        return;
      }
            
      if(ResEditor.Edit.Menu.length   === 0 &&
         ResEditor.Edit.Dialog.length === 0 &&
         ResEditor.Edit.String.length === 0){
        alert('There is no editable resources in this file.');
        return;
      }
        
      // Change the string of all of the "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++){
            // Other than the separator
            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');
      } 
      
      // Change the string of all of the "Dialog"
      var Dialog = ResEditor.Edit.Dialog;
      if(Dialog.length !==0){    
        var DS_SETFONT = 64;
         
        for(var i=0;i<Dialog.length;i++){    
          
          // Normal version and Extension version
          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;        
          }
          
          // Change of string of parent window
          DlgTemplate.title = DlgTemplate.title + addString;
          
          // If there is a font
          if((DlgTemplate.style & DS_SETFONT) === DS_SETFONT){
            // Change font name
            // DlgTemplate.typeface = 'font name';
            // Change font size
            // DlgTemplate.pointsize = 8;
          }
          
          // Control    
          for(var j=0;j<DlgItemTemplate.length;j++){
            // String type
            if(typeof DlgItemTemplate[j].title === "string"){ 
              DlgItemTemplate[j].title = DlgItemTemplate[j].title + addString;
            } 
          } 
        }
      }else{
        console.log('Dialog None');
      }       
      
      // Change the string of all of the "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++){
            // Non-NULL
            if(StringTable[i].resObject.Value[j] !== ''){
              StringTable[i].resObject.Value[j] = StringTable[i].resObject.Value[j]  + addString;
            }
          } 
        } 
      }else{
        console.log('String Table None');
      } 
      
      // You can save in this one method.
      // However, IE / Edge can not be downloaded in the security restrictions.
      // ResEditor.SaveToFile('test.exe');
            
      var zip = new Zlib.Zip();    
      var stream = ResEditor.SaveToStream();
      
      // Acquisition of extension
      var ext = ResEditor.FileName.split('.');
      ext = '.' + ext[ext.length-1];
        
      // ZIP (Uncompressed)
      zip.addFile(stream,{'filename': PE_ConvertArray('test' + ext),
                          'compressionMethod':Zlib.Zip.CompressionMethod.STORE});
      var compressed = zip.compress();
      
      // download
      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> 

3. Details of each class

Core class is TPEAnalyst. TResEditor is a wrapper class of TPEAnalst.

[TResEditor]

PropertyUse
(Edit)Editable resources (Menu,Dialog,String Table)
resNameID, resLangID can not be changed.
FileNameRead file name.
OSTarget OS of the executable file. (32bit or 64bit)
PEAnalystTPEAnalyst

() of Property may not exist depending on the setting.

MethodLoadFromStream(AStream, ResourceFlg [,PackedFlg])
UseLoad the executable file.
ArgumentAStream : Uint8Array
ResourceFlg : true Add the Edit Properties
PackedFlg : true Simple Pack tool judgment (Omitted true)
Return value None

MethodSaveToStream()
UseOutputs the execution file at the stream with the contents of the TResEditor.Edit.
ArgumentNone
Return valueUint8Array

MethodSaveToFile(FileName)
UseOutputs an executable file with the contents of the TResEditor.Edit.
ArgumentFileName: file name
Return valueNone

MethodSaveImportTEXT(FileName)
UseOutputs, all of the "import" information in text format.
ArgumentFileName: file name
Return valuetrue : success, false : error

MethodSaveExportCSV(FileName)
UseOutputs, all of the "export" information in csv format.
ArgumentFileName: file name
Return valuetrue : success, false : error

MethodExtractBinFile(ZipFileName)
UseOutputs, all of the resources in a binary file (RAW).
ArgumentZipFileName: ZIP file name
Return valuetrue : success, false : error

[TPEAnalyst]

PropertyUse
ExportExport information
IMAGE_COFF_HEADERIMAGE_COFF_HEADER Structure
IMAGE_DOS_HEADERIMAGE_DOS_HEADER Structure
IMAGE_OPTIONAL_HEADERIMAGE_OPTIONAL_HEADER Structure
IMAGE_SECTION_HEADERIMAGE_SECTION_HEADER Structure
ImportImport information
(IsPacked)Compression flag. (true or false)
Simple Pack tool judgment (only, UPX and AsPack).
This property can be used if "PackedFlg = true" in TResEditor.LoadFromStream.
(Resource)Resource
This resource is read-only.
StreamTReadStream. (see, source code)
Read the contents of the executable file.

() of property may not exist.

Other

The following sample has published in the blog. (only Japanese)

Convert resource into the RC file
Convert resource into the RES file
Extract the code section
Extract the data section
Extract all section
Get the hidden code
View the resources in the ListView

Advertisement