pefileとpydasm
pythonのライブラリ pefileとpydasmの日本語情報があんまり見つからなかったんで紹介記事書いてみるテスト。
まず、何ができるの?
pefileはWindowsの実行形式Portable Executableの解析を手助けしてくれるライブラリ。
pydasmはx86の逆アセンブルができるライブラリ。
この二つを組み合わせることで簡単にリバースエンジニアリングができちゃたりなんかするのです。
PEファイルのロード
モジュールをインポートして、ファイルをパースする
import pefile pe = pefile.PE(‘/path/to/pefile.exe’)
fast_loadをTrueで指定するとDirectoryを無視してパースするので、高速になる。
import pefile pe = pefile.PE(‘/path/to/pefile.exe’, fast_load=True)
あとでfull_load()メソッドを呼べば失われてる情報をパースできる。
生のPEデータをロードすることもできる。
pe = pefile.PE(data=str_object_with_pe_file_data)
ヘッダーメンバーの読み書き
PEファイルのパースが成功したら、PEインスタンスの属性を扱える。
pe.OPTIONAL_HEADER.AddressOfEntryPoint pe.OPTIONAL_HEADER.ImageBase pe.FILE_HEADER.NumberOfSections
writeメソッドでPEファイルに書き込むこともできる。
pe.write(filename='file_to_write.exe')
セクションのイテレート
PEインスタンスにはsectionsという属性がある。
for section in pe.sections: print (section.Name, hex(section.VirtualAddress), hex(section.Misc_VirtualSize), section.SizeOfRawData )
Output
('.text', '0x1000L', '0x6D72L', 28160L)
('.data', '0x8000L', '0x1BA8L', 1536L)
('.rsrc', '0xA000L', '0x8948L', 35328L)
インポートされたシンボルをリストアップ
for entry in pe.DIRECTORY_ENTRY_IMPORT: print entry.dll for imp in entry.imports: print '\t', hex(imp.address), imp.name
Output
comdlg32.dll
0x10012A0L PageSetupDlgW
0x10012A4L FindTextW
0x10012A8L PrintDlgExW
[snip]
SHELL32.dll
0x1001154L DragFinish
エクスポートされたシンボルをリストアップ
for exp in pe.DIRECTORY_ENTRY_EXPORT.symbols: print hex(pe.OPTIONAL_HEADER.ImageBase + exp.address), exp.name, exp.ordinal
Output
0x7ca0ab4f SHUpdateRecycleBinIcon 336
0x7cab44c0 SHValidateUNC 173
0x7ca7b0aa SheChangeDirA 337
0x7ca7b665 SheChangeDirExA 338
0x7ca7b3e1 SheChangeDirExW 339
0x7ca7aec6 SheChangeDirW 340
0x7ca8baae SheConvertPathW 341
エントリーポイント付近のバイトを取り出す
pydasmをインポートして、pefileと組み合わせる。
エントリーポイントアドレスをフェッチして、そこから100バイト取り出して逆アセンブルしていく。
ep = pe.OPTIONAL_HEADER.AddressOfEntryPoint ep_ava = ep+pe.OPTIONAL_HEADER.ImageBase data = pe.get_memory_mapped_image()[ep:ep+100] offset = 0 while offset < len(data): i = pydasm.get_instruction(data[offset:], pydasm.MODE_32) print pydasm.get_instruction_string(i, pydasm.FORMAT_INTEL, ep_ava+offset) offset += i.length
Output
push byte 0x70
push dword 0x1001888
call 0x1006ca8
xor ebx,ebx
push ebx
mov edi,[0x100114c]
call edi
cmp word [eax],0x5a4d
jnz 0x1006b1d
mov ecx,[eax+0x3c]
add ecx,eax
cmp dword [ecx],0x4550
jnz 0x1006b1d
movzx eax,[ecx+0x18
ま、こんな感じで簡単にPEファイルを取り扱って逆アセンブルしたりできるわけです。
面白いね!