vier

Let's be more curious.

【簡単】ファイルの改ざんをWindowsで調べる方法

ファイルの改ざんをWindowsで調べる

はじめに

皆さんはダウンロードしたファイルを実行してウイルスに感染したり、ダウンロードが不完全に終わりファイルが破損・欠落していた、という経験はありますか?

ファイルの破損・欠落は、プログラムがエラーで実行できなかったり、写真や動画だと画像が乱れ異常を確認できます。

しかし、悪意を持った第三者が本物にウイルスを仕込んで配布した場合、改ざんに気づかず実行すると、意味不明のメッセージが表示され情報が抜き取られたり、知らない間にPCが乗っ取られてしまう恐れがあります。


ファイルの改ざんは見破れる?

2つサンプルの画像ファイルを用意したので、どちらのファイルが本物かチェックして見ましょう。

1枚目を写真A、2枚目を写真Bとします。


写真A

改ざんされた画像


写真B
改ざんされてない画像


管理人がどちらかの写真を改ざんしたのですが、どっちがオリジナルか判別できますか。


30秒以内に判別して下さい。

答え:改ざんしたのはAの写真です。




ではどこが改ざんされているのでしょうか。

答え:胸の谷間に〇〇〇という文字を入れてみました。

胸の谷間

写真を見比べすぐ分かった方は、普段からその部分に関心が高い相当スケベな方ですね。😅


改ざんを見破る方法

テキストファイルは文字を比較することで改ざんされた部分を発見することは可能ですが、画像・音声・動画・圧縮ファイル等のバイナリーデータは無理です。

そこでファイル(データ)の同一性を確認するのに使われているのが、ハッシュ値(hash value)で、ハッシュ値が一致すれば本物と同一であると判断することができます。


ハッシュ値とハッシュ関数

ハッシュ値とはハッシュ関数(hash function)で計算された値で、不可逆的な変換により元データを復元できないことから、暗号や認証に使われてます。

良く使用されるハッシュ関数は、MD5(Message Digest 5)、SHA-1(Secure Hash Algorithm 1)、SHA-256 (Secure Hash Algorithm 256-bit)があります。

これらのハッシュ値の符号の長さはそれぞれ32文字(128bit)、40文字(160bit)、64文字(256bit)で、符号が長いほどセキュリティ強度が高くなってます。

大容量のデータも32文字~64文字のハッシュ値に変換できるため、同一のものか照合するのに非常に便利ですね。


ハッシュ値の計算方法

前置きがかなり長くなってしまいましたが、ハッシュ値はWindowsの標準機能で簡単に調べることが出来ますので、その方法を説明します。


CertUtil -hashfileの実行

コマンドプロンプトで下記コマンドを実行するとハッシュ値が計算ができます。

CertUtil -hashfile <ファイル名> [ハッシュアルゴリズム]

ハッシュアルゴリズムは、MD2,MD4,MD5,SHA1,SHA256,SHA384,SHA512 の7種類を計算でき、指定しない場合は、SHA1のハッシュ値が算出されます。

それでは写真Aと写真BのSHA1,SHA256のハッシュ値を調べてみます。

SHA256のハッシュ値

ハッシュ値は1bitでも異なると大きく変わりますが、写真Aと写真Bのハッシュ値は似たところがないことが分かります。

このように、本物のファイルのハッシュ値が公開されていれば、ダウンロードしたデータのハッシュ値を調べることで、改ざんされたファイルか確認できます。


しかし初心者の方は、コマンドプロンプトを起動し、ハッシュ値を計算する呪文、ファイル名、ハッシュアルゴリズムを手入力するなんで、どうやるの?よく分からない、と感じていると思います。

管理人もコマンドプロンプトなんて滅多に使わないし、わざわざ調べるのも面倒だと思ってます。

そこでハッシュ値を計算するバッチファイルを作ることにしました。

ネットに良いのが転がってないかなーと探したのですが、やりたいことが出来るものが見つからなかったので、仕方なく自作しました。


ハッシュ値を簡単に計算するバッチファイル

今回作成したバッチファイルは、複数のファイルをドラッグ&ドロップするだけで、ハッシュ値の計算と処理時間を計測できるものです。

Webのツールで計算するより高速で安全だと思います。また、結果をテキストファイルで保存するので、後で確認することもできます。

21.4GBのISOファイルのSHA-256のハッシュを調べた時は、管理人のPCでは284secの処理時間でした。

興味がある方は、下記バッチファイルを自己責任でご利用下さい。


コード
REM 複数のファイルのハッシュ値を調べ、結果を保存するバッチファイル
@echo off
chcp 65001
setlocal enabledelayedexpansion
set result=_hash-value

REM (注)ハッシュを計算しないアルゴリズムはsetの前にREMを入れ、計算するものはREMを削除して下さい
REM set hash_1=MD2   
REM set hash_2=MD4   
REM set hash_3=MD5   
set hash_4=SHA1  
set hash_5=SHA256
REM set hash_6=SHA384
REM set hash_7=SHA512


for %%f in (%*) do (
	@echo.
	@echo. === %%~nxfのハッシュ計算 ===
	@echo.
  	@echo.> %%f%result%.txt
	if not exist %%f%result%.txt (
		@echo.
  		@echo|set /p=  フォルダに書込み権限がないので終了します。
		pause;
		exit /b
	) 
  	@echo.  %%~nxfのハッシュ値  >> %%f%result%.txt
  	@echo.>> %%f%result%.txt
	for /f "usebackq delims== tokens=1,2" %%a in (`set hash`) do (
		@echo|set /p=・%%b calculating hash …

		set "t0=!time: =0!"
		set /a m0=1!t0:~3,2!-100
		set /a s0=1!t0:~6,2!-100
		set /a ms0=1!t0:~9,2!-100

		for /f "delims=" %%c in ('certutil -hashfile %%f %%b ^| find /v ":"') do (

			set "t1=!time: =0!"
			set /a m1=1!t1:~3,2!-100
			set /a s1=1!t1:~6,2!-100
			set /a ms1=1!t1:~9,2!-100

			if !m1! lss !m0! (
				set /a m1=m1+60
			)
			if !s1! lss !s0! (
				set /a s1=s1+60
				set /a m1=m1-1
			)
			if !ms1! lss !ms0! (
				set /a ms1=ms1+100
				set /a s1=s1-1
			)
			set /a calc_int=m1*60+s1-m0*60-s0
			set /a calc_dec=ms1-ms0

			@echo.・%%b hash:%%c >> %%f%result%.txt
			if !calc_dec! lss 10 (
				@echo  processing time:!calc_int!.0!calc_dec!sec
			) else (
				@echo  processing time:!calc_int!.!calc_dec!sec
			)	
		)
	)
	type %%f%result%.txt
	@echo.
	@echo. 結果は%%~nxf%result%.txtで保存しました。
	@echo.
)
@echo.
@echo.|set /p= 何かキーを押すと終了します。
pause;
exit /b


バッチファイルの使用方法と注意事項


注意事項

文字列のハッシュを調べたい場合は、文字列をテキストで保存し、そのファイルをドラッグ&ドロップして下さい。

計算しないハッシュには行の先頭にREMが入っており、デフォルトはSHA1,SHA256のハッシュを計算してます。お好みに応じてREMを修正下さい。

修正は「バッチファイルを右クリック」→「 編集」 を選択して下さい。

バッチファイルを右クリック

システムフォルダのファイルは結果を保存出来ないのでAccess is denied.のエラーが発生します。調べたいファイルはデスクトップ等にコピーしてご利用下さい。


バッチファイルの使用方法

テキストファイルに上記バッチファイルのコマンドをコピー&ペーストし、適当な名前.batで適当な場所に保存して下さい。バッチファイルはハッシュ値を調べるフォルダと同じ場所になくても大丈夫です。

バッチファイル



上記バッチファイルにハッシュを確認したい調査ファイルをドラッグ&ドロップして下さい。

ドラッグ&ドロップ

バッチファイルが起動しハッシュ値の計算結果は、調査ファイルと同じフォルダに保存されます。

ハッシュ値の計算


お勉強できたところ

バッチファイルはとてもクセがあり、いろいろお勉強させて頂きました。苦労した点を備忘録で書いておきます。


バッチファイルは配列を使えない

変数を使った繰り返し計算は配列を使うと簡単なのですが、バッチファイルは配列を使えません。

最初、ハッシュアルゴリズムの変数を格納したテキストファイルを読み込むものを作ったのですが、別の方法がないか調べたら、setコマンドの環境変数一覧を表示する機能が配列のように使えることが分かり、これに変えました。

バッチファイルで配列とforeachを使う方法 - Qiita

バッチファイルで配列とforeachを使う方法 - Qiita

はじめに Windows バッチファイルには、値の集合を取り扱うためのデータ構造や文法規則はありませんが、シンボル名をうまく処理することで、配列やforeachに近い処理を行うことが出来ます。 要素番号をカウントカウントアッ...


処理時間の計算

これは想定外に大変でした。

最初、forループの中で時刻の変数が上手く取得できませんでした。これは遅延環境変数を使うことで解決できました。

【バッチ】時刻を比較して処理を終了させる - Qiita

【バッチ】時刻を比較して処理を終了させる - Qiita

こんにちはtsuttieです(*'▽') 今回はバッチファイルで時刻の比較をしたときにハマったポイントを記載します。 1. なにをしたのか バッチファイルは手軽で好きなのですが、如何せん癖が強くてあんまり得意ではありません・・・...


バッチファイルは整数しか使用できなので、時刻の小数点2桁の時間の計算が複雑な判定処理になってしまいました。

一番困ったのは、完成したと思ってテストすると、Numeric constants are either decimal (17)のエラーがランダムに出たことです。

原因を調べたら、時刻を分解した符号の頭に0があると8進数と解釈されエラーになることが分かりました。これはトリッキーな計算で回避することが出来ました。

Windowsバッチで日付計算を扱う際の注意点 - Qiita

Windowsバッチで日付計算を扱う際の注意点 - Qiita

Windowsバッチで、日付の計算を行う必要があり、自作でロジックを組んだが、本番障害を起こしてしまった。 原因は、現在日(%DATE%)をそれぞれ年、月、日に分割して足し引きを行うところで、 日が10未満の場合に「08」のようにな...


出来上がったコードは謎の呪文の塊のようになってしまい、作った本人も数か月後には分からなくなっているかも、と思いました。


バッチファイルの変数置換方法

バッチファイルで文字列を処理する場合、変数を置換する呪文の意味が分からないと、お手上げです。

バッチファイルの変数の置換方法をネットで調べたので表にまとめました。変数の置換方法が分からない方は参考にして下さい。

例ではPATHという変数に「今日は雨のち曇り時々晴れ」という文字列を代入した場合の表示結果を示してます。

書式意味結果
%PATH%変数全体%PATH%今日は雨のち曇り時々晴れ
%PATH:~m%m+1文字目以降全部%PATH:~8%時々晴れ
%PATH:~m,n%m+1文字目からn文字%PATH:~3,5%雨のち曇り
%PATH:~,n%先頭からn文字%PATH:~,4%今日は雨
%PATH:~m,-n%m+1文字目から末尾n文字を除く%PATH:~6,-4%曇り
%PATH:~-m%末尾m文字%PATH:~-6%曇り時々晴れ
%PATH:~-m,n%末尾m文字目からn文字分%PATH:~-6,4%曇り時々
%PATH:~-m,-n%末尾m文字目から末尾n文字分を除く%PATH:~-9,-2%雨のち曇り時々
%PATH:str1=str2%文字列str1を文字列str2に置換%PATH:曇り=%今日は雨のち時々晴れ
%PATH:*str1=str2%先頭から文字列str1までを文字列str2に置換%PATH:*時々=%晴れ


以上でファイルの改ざんをWindowsで調べる方法の説明は終わりです。

ここからは、ハッシュの安全性について調べたことを、記録として残しておきます。興味がある方はお読みください。


ハッシュ化はどれくらい安全なのか

実はMD5とSHA-1は安全では無くなってました。

ハッシュ値の衝突

1991年にRon Rivestが開発したMD5は2004年4月に同じハッシュ値を生成する“衝突”に成功してます。2007年4月には、情報の一部を固定し同一のMD5ハッシュ値を生成する計算法が発見されており、PCで10分程度で算出できるようになりました。

従って、パスワードのMD5ハッシュ値が流出した場合、同じハッシュ値を生成する文字列を探すことができるため、パスワードのMD5ハッシュ値は安全でなくなってます。

またNSA(米国家安全保障局)が1995年に開発したSHA-1も2017年2月にGoogleとオランダの研究機関CWI InstituteがPDFの“衝突”に成功してます。

SHA-1の衝突に成功した、背景色が異なる2つのPDFファイルがSHAtteredで公開されていたので、さっそくダウンロードしてSHA-1を確認してみました。

SHA-1を確認


どちらのPDFファイルもSHA-1のハッシュ値は38762cf7f55934b34d179ae6a4c80cadccbb7f0aで同一でした。

SHA-1のハッシュ値

以上の研究よりMD5とSHA-1は脆弱性が確認されているので、ハッシュ関数はSHA-2(SHA-256,SHA-384,SHA-512)の使用が推奨されてます。


SHA-2は安全なのか?

しかしながら、SHA-2を使っても特定の文字列は特定のハッシュ値を生成します。

文字列とそのハッシュ値の組み合わせのリスト:レインボーテーブルを用意し、還元関数(Reduction Function)を用いれば、ハッシュ値から元の文字列を見つけ出すことが可能と言われてます。

この脅威を回避する方法がソルトと呼ばれてます。

ソルトとは、ハッシュ化する前の元の文字列にランダムな文字列を追加する手法です。

仮にパスワードのハッシュ値とソルトの文字列が流出したとしても、ソルトの文字列が何文字でどのように使われているか分からないので、レインボーテーブルを作るにしても、膨大な計算が必要となります。

銀行のキャッシュカードの暗唱番号は数字4桁ですが、機械を流れているデータがソルトで生成されたハッシュ値なら、通信を傍受されても暗唱番号が特定されることはありません。

しかし、サイバー攻撃でデータが流出したという事故をよく聞きますが、データをハッシュ化せず平文で保存していた、というマヌケなサービスが今も無くなってないのが悲しいですね。


気軽に足跡残してね!

この記事が「気になった・参考になった」と感じた方は、リアクションボタンか、ツイッターで♡いいねを押して、足跡を残して頂けると嬉しいです。

それでは今回の記事はこれでおしまい。

New PostOld Post
No Comment
    Please Enter Comments in Light mode
    comment url