連載 [第7回] :
  脆弱性診断の現場から

パッチを当てるPythonスクリプトを生成するIDAプラグイン「genpatch」を作った話

2025年2月14日(金)
小竹 泰一
第7回の今回は、IDA Pro上で当てたパッチと同じパッチを当てるPythonスクリプトを生成するIDAプラグイン「genpatch」について解説します。

はじめに

株式会社ステラセキュリティ 取締役CTOの小竹(@tkmru)です。

2023年にgenpatchというIDA Pro上で当てたパッチと同じパッチを当てるPythonスクリプトを生成するIDAプラグインを公開しました。この記事では、作成した「genpatch」の使い方、仕組みを紹介します。

困っていたこと

スマホアプリが対象の脆弱性診断では、準備段階でリバースエンジニアリングを行い、パッチを当てることがあります。SSL Pinning(Certificate Pinning、証明書のピン留め)をお客様側で無効化していただけなかった場合には、解析を行い、無効化するパッチを当てた上で、APIとの通信を診断します。SSL Pinningは、使用するSSL証明書をアプリ内にハードコートし、通信時にSSL証明書がアプリ内のものか検証を行うことで、SSL通信の中間者攻撃を防ぐ仕組みです。Burp Suiteなどのプロキシツールを使ってSSL通信を閲覧する際には、PCにインストールしたプロキシツールの証明書を使用しています。そのため、SSL Pinningが実装されているアプリに対して、プロキシツールを使用して通信を閲覧しようとすると、SSL証明書の検証に失敗し、通信が行えません。

診断期間中に診断対象のアプリがアップデートされた場合、パッチを当て直す必要があります。その際に、IDA Proを起動し、パッチを当て直す1のは面倒です。また、IDA Proの操作に慣れていないチームメンバーにパッチを当ててもらうのも、大変です2。そのため、IDA Pro上で当てたのと同じパッチを当てるPythonスクリプトを生成するプラグインを作成しました。

1: Unity製のスマホアプリではすべてのロジックがC++製の共有ライブラリに実装されるのでパッチを当てるのにIDA ProやGhidraを使う必要があります。Javaで実装されたAndroidアプリであればSmaliファイルを編集するだけで済みます。 2: IDA Proのライセンスを用意するのも大変です。

作ったツール

genpatchというIDA Pro上で当てたパッチと同じパッチを当てるPythonスクリプトを生成するIDAプラグインを作成しました。genpatchが生成したパッチを当てるPythonスクリプトを使用することで、 繰り返しバイナリにパッチを当てる際に、Pythonスクリプトを実行するだけで済みます。このプラグインはPythonで実装しています。

インストール方法

リポジトリ内のgenpatch.pypatch_script_template.txtをIDA Pluginフォルダにコピーし、IDA Proを再起動するとgenpatchが使えるようになります。Windowsの場合、コピー先のフォルダはC:\Program FilesIDA 8.x\pluginsです。macOSの場合、コピー先のフォルダは/Applications/IDA Pro 8.x/idaq.app/Contents/MacOS/pluginsにあります。

パッチを当てるPythonスクリプトを生成する

IDA Pro上でパッチを当てた後、Edit -> Plugins -> genpatchボタンをクリックすると、IDA Proで読み込んだバイナリがあるディレクトリにパッチスクリプトが生成されます。スクリプトの名前は、解析中のバイナリに接尾辞_patch.pyを付けたものになります。例えば、バイナリ名がa.outの場合、パッチスクリプト名はa.out_patch.pyとなります。

Pythonスクリプトが正常に生成されると、以下のようなダイアログが表示されます。

生成したPythonスクリプトを実行する

コマンドライン第一引数にパッチを当てたいバイナリへのパスを指定して実行することで、パッチを当てることができます。

$ python a.out_patch.py <target_binary_path>

生成されたPythonスクリプトは次のようになります。16進数のデータ列を置換します。

#!/usr/bin/env python
# coding: UTF-8

import binascii
import os
import re
import sys

target_path = sys.argv[1]
target_data = None
with open(target_path, 'rb') as target_file:
    target_data = binascii.hexlify(target_file.read()).decode('utf-8')

# address: 0x100000ecb
# function name: __text: _main
# comment: Keypatch modified this from:   jz loc_100000EF6 Keypatch padded NOP to next boundary: 4 bytes
matches = re.findall('0f8425000000', target_data)
if len(matches) == 1:
    target_data = target_data.replace('0f8425000000', '752990909090')
else:
    print("Patch pattern isn't unique")
    sys.exit()

result_path = f'{target_path}_patched'
with open(result_path, 'wb') as result_file:
    if sys.version_info[0] >= 3:
        result_file.write(bytes.fromhex(target_data))
    else:
        result_file.write(target_data.decode('hex'))

print("Successfully generated patched binary to '%s'" % result_path)

おわりに

弊社ではこのように脆弱性診断中に遭遇した課題を解決するべく、適宜ツールを開発し、業界内に知見を共有していきます。また、「genpatch」が脆弱性診断、マルウェア解析などリバースエンジニアリングを伴う仕事に従事するエンジニアに広く使われるよう育てていきたいと思っています。ぜひ、気づいたことがあればフィードバックしてもらえるとうれしいです。 みなさまからのIssueやプルリクエストをお待ちしております。

※本記事は、株式会社ステラセキュリティが配信しているコンテンツ「Sterra Security Tech Blog」からの転載です。
元記事についてはこちらをご覧ください。

株式会社ステラセキュリティ 取締役副社長 CTO
大学卒業後、株式会社ディー・エヌ・エーに入社し、セキュリティエンジニアとして活躍。その後、株式会社アカツキに1人目のセキュリティエンジニアとして入社し、脆弱性診断内製化、セキュリティチーム組成に尽力。 著書に『ポートスキャナ自作ではじめるペネトレーションテスト』『マスタリングGhidra』(いずれもオライリー・ジャパン)、『リバースエンジニアリングツールGhidra実践ガイド』(マイナビ出版)

連載バックナンバー

セキュリティ技術解説
第7回

パッチを当てるPythonスクリプトを生成するIDAプラグイン「genpatch」を作った話

2025/2/14
第7回の今回は、IDA Pro上で当てたパッチと同じパッチを当てるPythonスクリプトを生成するIDAプラグイン「genpatch」について解説します。
セキュリティ技術解説
第6回

クロスコンパイルできるC言語のビルド&実行環境をGitHubActionsとQEMUで作る

2024/12/27
第6回の今回は、GitHub Actionsを利用して、x64とARM32/ARM64のバイナリをコミット毎にビルドする環境の構築方法を解説します。
セキュリティ技術解説
第5回

32ビット/64ビットの両方のARM環境で有効なディスアセンブルを妨害するテクニック

2024/11/22
第5回の今回は、ドキュメントが少ない32ビット/64ビットのARM環境におけるアンチディスアセンブル技術の使い方を解説します。

Think ITメルマガ会員登録受付中

Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。

Think ITメルマガ会員のサービス内容を見る

他にもこの記事が読まれています