2012/06/29

Windowsでファジング用のファイルを一気に作成するプログラムとバッチスクリプト

Bugハンター日記」という、プログラムの脆弱性の発見方法について書いた本を買いました。

その中にiPhoneをハックする章があります。

そこでは、

  • 特定のフォーマットの正常なファイルを一つ用意
  • ファイルの中の1バイトだけが異なるファイルを何パターンも作成
  • それを自動でアプリに開かせる

このように網羅的なアタックでアクセス違反が起こるかどうかを見るという方法が使われていました。

こういうテスト手法はファジングと言うらしいです。

さて、このファジングのためにファイルを1バイトだけ書き換えるプログラムが、ソースは載っているのですが、Windowsでは動かない関数が使われていました。

なので Windows環境でコンパイルできるCプログラムを書きました。

gcc -o fuzz fuzz.c

もしgccがない場合はMinGWなどをインストールしてください。

fuzz.c

#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
 int hdl;
 char *name = NULL;
 unsigned int file_offset = 0;
 unsigned int file_value = 0;

 if(argc<2){
  printf("Error: not enough arguments\n");
  return 1;
 }else{
  file_offset = atol(argv[1]);
  file_value = atol(argv[2]);
  name = argv[3];
 }

 hdl = open(name, O_RDWR | O_BINARY);
 if(hdl==-1){
  perror("open");
  exit(1);
 }

 if(lseek(hdl, file_offset, 0)==-1){
  perror("lseek");
  exit(1);
 }

 printf("file offset: 0x%08x (value: 0x%08x)\n", file_offset, file_value);

 if(write(hdl, &file_value, 1)==-1){
  perror("write");
  exit(1);
 }
 
 close(hdl);

 return 0;
}

ちなみにあまり引数の正しさをチェックしてません。オフセットに変な値を渡したりしないほうがいいです。

引数は以下のように渡します。

fuzz.exe funny.doc 10 255

この場合、funny.docの10バイト目を255にして上書き保存します。

また、これを使って次々にファイルを生成させるバッチファイルも作成しました。

go.bat "C:\music\test.ogg" 10 -1

のように使います。

この例では、test.oggを、10バイト目から終端まで(-1を指定すると終端までになります)、1バイトずつ変えては保存します。test10.ogg test11.ogg ... といったファイルが出力されます。

go.bat

@echo off
REM 書式: go.bat "元ファイルへのパス" オフセット 終了するオフセット
REM 例 : go.bat "c:\hoge.doc" 0 100

REM forの中で変数をカウントしながら使えるようにする
REM (遅延環境変数という。%x%のかわりに!x!のように使う)
setlocal ENABLEDELAYEDEXPANSION

REM 環境変数を汚さないように一時的なモードにする
setlocal

REM ファジングをはじめる位置。10進数
set /A off=%2
set /A max=%3
REM ファジングで上書きするときの値。0?255。10進数
set val=255

REM 元にするファイルが存在しない場合エラーを出して終了
if not exist "%~f1" (
 echo "loading...%~f1"
 echo "Error: source file is not found"
 goto destructor
)

REM 位置(オフセット)と終了位置が範囲内にあるか
if "%max%" EQU "-1" (set /A max=%~z1)
if %~z1 LSS %off% (goto invalidoffset)
if %off% LSS 0 (goto invalidoffset)
if %off% GTR %max% (goto invalidoffset)

for /l %%i in (%off%,1,%max%) do (
 cp "%~p1%~n1%~x1" "%~n1%%i%~x1"
 set /A off=off+1
 fuzz !off! %val% "%~n1%%i%~x1"
)

goto destructor

:invalidoffset
echo "Error: invalid offset(%off%) or max(%max%)"
echo "filesize: (%~z1)"
goto destructor

:destructor
REM 使い終わったので元に戻しておく
endlocal

コメントを投稿