バイナリ編集ツール

はじめに

前回のエントリでEXE/DLLファイルを編集するツールを作りました。

このツールを一般化すると便利ではなかろうかと思い、こんなものを作ってみました。

編集箇所をcsvファイルで設定できます。

バイナリ編集ツール

ソースコード

本体ソース

#include <stdio.h>

/*
 * binary_edit.c
 *
 * this program modifies input binary file with csv file.
 *
 * required csv file format
 *   from,to,val
 *   from,to,val
 *   from,to,val
 *   .
 *   .
 *
 *   ex1) 1,1,3  # write 3 at address 1
 *   ex2) 4,6,-1 # delete from address 4 to address 6
 *   ex3) 9,0,0  # write 0 from address 9 to the end of file
 */

void usage( char **argv ) {

  printf( "usage : %s <csv file> <input binary file> <output binary file>\n", argv[ 0 ] ) ;
  return ;

}

unsigned int next_param( FILE *fp, int *from, int *to, int *val ) {
  return fscanf( fp, "%d,%d,%d\n", from, to, val ) == EOF ? 1 : 0 ;
}

void put_val( int val, FILE *fp ) {
  if( val >= 0 )
    putc( val, fp ) ;
}

int main( int argc, char **argv ) {

  FILE *fcsv, *fin, *fout ;
  int c, from, to, val ;
  unsigned int i = 0, param_end ;

  if( argc != 4 ) {
    usage( argv ) ;
    return -1 ;
  }

  if( ! ( fcsv = fopen( argv[ 1 ], "r" ) ) ) {
    printf( "failed to open csv file.\n" ) ;
    return -1 ;
  }

  if( ! ( fin = fopen( argv[ 2 ], "rb" ) ) ) {
    printf( "failed to open input file.\n" ) ;
    fclose( fcsv ) ;
    return -1 ;
  }

  if( ! ( fout = fopen( argv[ 3 ], "wb" ) ) ) {
    printf( "failed to open open file.\n" ) ;
    fclose( fcsv ) ;
    fclose( fin ) ;
    return -1 ;
  }

  param_end = next_param( fcsv, &from, &to, &val ) ;
  while( ( c = getc( fin ) ) != EOF ) {
    if( param_end ) {
      putc( c, fout ) ;
    } else if( from == to && i == from ) {
      put_val( val, fout ) ;
      param_end = next_param( fcsv, &from, &to, &val ) ;
    } else if( from < to && i >= from && i <= to ) {
      put_val( val, fout ) ;
      if( i == to ) {
        param_end = next_param( fcsv, &from, &to, &val ) ;
      }
    } else if( from > to && i >= to ) {
      put_val( val, fout ) ;
    } else {
      putc( c, fout ) ;
    }
    i++ ;
  }

  fclose( fout ) ;
  fclose( fin ) ;
  fclose( fcsv ) ;

  return 0 ;

}
実行例

前回のエントリと同じように、PE形式をCOM形式に変換してみます。

com.csv

0,63,-1
68,68,1


1行目は「アドレス0 - 63まで削除」を意味します。2行目は「アドレス68に1を書き込む」を意味します。

% gcc -o binary_edit.exe binary_edit.c
% ./binary_edit.exe ./com.csv ./dump.exe ./dump.com
% debug dump.com
-g
This program cannot be run in DOS mode.
プログラムは正常に終了しました.

拡張したい箇所

  • csvファイルをもっとわかりやすい形式に
    • わかりやすい形式から、今回使っている形式に変換するスクリプトを書けばOK。このプログラムを書き換える必要はなし?
  • 書き換える値は絶対値でしか指定できない。+1や-2などと設定できると便利そう
  • アドレスxxの値をアドレスyyにコピーできるように
  • アドレスxxの値を読み取り(yyとする)、アドレスyyの値を書き換える

終わりに

コマンドラインでバイナリを編集したかったので作ってみました。機能を拡張していったらそれなりに便利そう?