Skip to content

Instantly share code, notes, and snippets.

@devlights
Created May 29, 2026 07:25
Show Gist options
  • Select an option

  • Save devlights/23b7b61bb0775c8a7c87b0a3b5bb2f44 to your computer and use it in GitHub Desktop.

Select an option

Save devlights/23b7b61bb0775c8a7c87b0a3b5bb2f44 to your computer and use it in GitHub Desktop.
GNU Poke チートシート

GNU poke チートシート

対象読者: C言語の基本とバイナリ・エンディアン・ビット幅の基礎知識がある方
GNU poke 4.3 時点の情報です。
公式マニュアル: https://jemarch.net/poke-4.3-manual/poke.html


目次

  1. インストール・起動
  2. REPLの基本操作(ドットコマンド)
  3. dump:バイナリを眺める
  4. 数量と単位(United Values)
  5. マッピング:バイト列に型を割り当てる
  6. プリミティブ型一覧
  7. 配列・文字列
  8. 構造体(struct)の定義とマッピング
  9. 書き込み・値の変更
  10. IOスペース
  11. Poke言語:変数・制御フロー・関数
  12. pickle(.pk スクリプト)
  13. 応用:structの高度な機能
  14. tips・注意事項

1. インストール・起動

インストール(Ubuntu / Debian 系)

sudo apt install poke

ソースからビルドする場合は以下のパッケージが必要です:

sudo apt install libgc-dev gettext libnbd-dev libjson-c-dev tcl-dev tk-dev
wget https://ftp.gnu.org/gnu/poke/poke-4.3.tar.gz
tar xf poke-4.3.tar.gz && cd poke-4.3
./configure && make && sudo make install

起動

poke                    # ファイルなしで起動(空の状態)
poke hoge.bin           # ファイルを開いて起動
poke -L script.pk       # スクリプトをバッチ実行して終了(shebang用)

2. REPLの基本操作(ドットコマンド)

poke の REPL では「ドットコマンド(.xxx)」と「Poke言語式」の2種類を入力します。

コマンド 説明
.help ヘルプ表示
.exit / .quit poke を終了
.file <path> ファイルを開く(新しい IOスペースとして追加)
.mem <name> メモリバッファの IOスペースを作成
.ios <id> カレント IOスペースを切り替える
.info ios 開いている IOスペース一覧を表示
.close <id> IOスペースを閉じる
.load <file.pk> pickle(.pkスクリプト)を読み込んで実行
.set obase 16 出力の基数を変更(2, 8, 10, 16)
.set endian big デフォルトエンディアンを変更(little / big
.set pretty-print yes 構造体をきれいに表示
.info types 定義済み型の一覧
.info variables 定義済み変数の一覧
.doc <name> 型・関数のドキュメントを表示

3. dump:バイナリを眺める

(poke) dump

デフォルトで先頭 128 バイトを hex + ASCII で表示します。

76543210 00 11 22 33 44 55 66 77 88 99 aa bb cc dd ee ff 01234567 89ABCDEF
00000000: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 .ELF.... ........
  • 左列:ファイルオフセット(16進)
  • 中央列:各バイトの16進数
  • 右列:ASCII表現(非印字文字は .

dump のオプション

(poke) dump :from 0x10#B :size 32#B         # オフセット 0x10 から 32 バイト
(poke) dump :from 0x50#B :size 16#B         # オフセット 0x50 から 16 バイト
(poke) dump :ruler 0                        # ルーラーを非表示
(poke) dump :ascii 0                        # ASCII 列を非表示

オプションは :名前 値 の形式で渡します。


4. 数量と単位(United Values)

poke の独自機能。値に「単位」を付けて表現します。

<数量>#<単位>

主な単位

表記 意味
1#b 1 ビット
1#N 1 ニブル(4 ビット)
1#B 1 バイト(8 ビット)
1#KB 1 キロバイト(1000 B)
1#KiB 1 キビバイト(1024 B)
1#MB 1 メガバイト
1#Mib 2 メビビット

演算例

(poke) 16#B               # 16 バイト
0x10#B
(poke) 1#B + 4#b          # 1 バイト + 4 ビット = 12 ビット
12#b
(poke) 1#KB / 1#B         # 1 キロバイト ÷ 1 バイト = 1000(無次元数)
1000
(poke) 1#B * 1024 == 1#KiB
1                          # 真(true = 1)

カスタム単位の定義

(poke) unit sector = 512 * 8   # 512 バイト = 1 セクター
(poke) 2#sector                # 2 セクター分のオフセット

5. マッピング:バイト列に型を割り当てる

バイナリの「ある位置」に「ある型」を割り当てて読み出す操作を マッピング と呼びます。

<型> @ <オフセット>
(poke) byte @ 0#B          # 0バイト目を 1 バイト(uint8)として読む
0x7fUB
(poke) int @ 4#B           # 4バイト目から int32 として読む
0x00010001
(poke) uint<16> @ 0x10#B   # 0x10バイト目を 16 ビット符号なし整数として読む
0x003eUH

マッピングはデータを読むだけでなく、そのまま書き込む左辺値にもなります(後述)。


6. プリミティブ型一覧

整数型(任意ビット幅)

uint<N>   # 符号なし整数(N ビット)
int<N>    # 符号あり整数(N ビット)

N は 1〜64 の任意の値が指定できます。

主なエイリアス

エイリアス 実体 C での対応
bit uint<1> _Bool
nibble uint<4>
byte, char, uint8 uint<8> uint8_t / unsigned char
ushort, uint16 uint<16> uint16_t
short, int16 int<16> int16_t
uint, uint32 uint<32> uint32_t
int, int32 int<32> int32_t
ulong, uint64 uint<64> uint64_t
long, int64 int<64> int64_t

リテラルの接尾辞

接尾辞
0x7fUB unsigned byte(uint8)
0x003eUH unsigned half-word(uint16)
0x00000001U unsigned word(uint32)
0x00000001UL unsigned long(uint64)

独自型の定義

(poke) type int3 = int<3>          # 3ビット符号あり整数
(poke) type myword = uint<32>      # uint32 の別名

7. 配列・文字列

配列

<要素型>[<個数>] @ <オフセット>
(poke) byte[4] @ 0#B              # 先頭 4 バイトを byte 配列として読む
[0x7fUB, 0x45UB, 0x4cUB, 0x46UB]

(poke) char[3] @ 0x52#B           # 0x52 バイト目から 3 文字
[0x47UB, 0x4eUB, 0x55UB]          # "GNU"

文字列(NULL 終端 ASCII)

(poke) string @ 0x4c#B
"GCC: (GNU) 15.2.1 20260103"

string 型は C の char*(NULL 終端)と同じ概念です。
NULL 文字 (\x00) が現れるまでを1つの文字列として読みます。


8. 構造体(struct)の定義とマッピング

基本的な struct 定義

type <型名> = struct {
  <型> <フィールド名>;
  ...
};
(poke) type Elf64_Ehdr = struct {
  byte[16] e_ident;
  uint<16> e_type;
  uint<16> e_machine;
  uint<32> e_version;
  uint<64> e_entry;
  uint<64> e_phoff;
  uint<64> e_shoff;
  uint<32> e_flags;
  uint<16> e_ehsize;
  uint<16> e_phentsize;
  uint<16> e_phnum;
  uint<16> e_shentsize;
  uint<16> e_shnum;
  uint<16> e_shstrndx;
}

struct のマッピングとフィールドアクセス

(poke) var ehdr = Elf64_Ehdr @ 0#B
(poke) ehdr.e_machine       # フィールドアクセス
0x003eUH                    # x86-64
(poke) ehdr.e_shnum
0x000cUH                    # 12 セクション

フィールドラベル(特定オフセットへの配置)

@ <offset> をフィールドの後ろに付けると、構造体先頭からの相対オフセットを指定できます。

(poke) type CoffHdr = struct {
  uint<16> NumberOfSections @ 0x2#B;
  uint<16> SizeOfOptionalHeader @ 0x10#B;
  byte _end @ (0x14 - 1)#B;  # サイズ調整用ダミー
}

構造体のサイズを単位として使う

type SECTION_HDR = struct { ... byte _ @ (0x28 - 1)#B; };

# SECTION_HDR を単位として配列インデックスを計算
var s = SECTION_HDR @ base + i#SECTION_HDR;

9. 書き込み・値の変更

⚠️ 警告:変更はファイルに即時反映されます。undo はありません。
必ず事前にバックアップを取るか、メモリバッファ(.mem)で試してください。

方法 1:マッピング式への直接代入

(poke) byte @ 0#B = 0x41          # 0バイト目を 0x41 ('A') に書き換え
(poke) uint<16> @ 0#B = 0x4f47   # 0〜1 バイト目を "GO" に書き換え

方法 2:プリミティブ型変数(コピーセマンティクス)

プリミティブ型の @ は「値のコピー」を返します。変数を書き換えても IOスペースには反映されません。

(poke) var n = int @ 0#B        # コピーを取得
(poke) n = n + 1                # 変数だけ変わる(ファイルは変わらない)
(poke) int @ 0#B = n            # 明示的に書き戻す

方法 3:複合型変数(マップドセマンティクス)

struct などの複合型は「マップド値」を返します。フィールドへの代入が そのまま IOスペースに反映 されます。

(poke) var hdr = Elf64_Ehdr @ 0#B     # マップド値
(poke) hdr.e_type = 0x0002UH          # → ファイルの該当バイトが即書き換わる!

10. IOスペース

poke はファイルやメモリを「IOスペース」として抽象化します。マッピング操作は常に「現在のカレント IOスペース」に対して行われます。

IOスペースの操作

(poke) .file /path/to/file         # ファイルを開く(read-write)
(poke) .file /bin/ls               # 読み取り専用で開く
(poke) .mem scratch                # メモリバッファを作成(名前は任意)
(poke) .info ios                   # 一覧表示(* がカレント)
(poke) .ios 0                      # ID=0 に切り替え
(poke) .close 1                    # ID=1 を閉じる

.info ios の出力例

   Id Type   Mode Bias            Size  Name
 * 1  MEMORY rw   0x00000000#B  0x00001000#B  *scratch*
   0  FILE   rw   0x00000000#B  0x000004c0#B  /tmp/hoge.bin

IOスペース間のコピー

copy :from_ios 0 :from 0#B :size iosize(0) :to_ios 1
オプション 説明
:from_ios コピー元 IOスペース ID
:from コピー元開始オフセット
:size コピーサイズ
:to_ios コピー先 IOスペース ID
:to コピー先開始オフセット(省略時 = 0)

メモリバッファをファイルに保存

save :ios 1 :from 0#B :size iosize(0) :file "/path/to/output.bin"

iosize 関数

(poke) iosize(0)       # ID=0 の IOスペースのサイズを返す
0x000004c0#B

11. Poke言語:変数・制御フロー・関数

poke の REPL は Poke 言語のインタープリタです。変数・ループ・条件分岐・関数をそのまま書けます。

変数

(poke) var x = 42               # 型推論
(poke) var s = "hello"
(poke) var arr = [1, 2, 3]

算術・比較

(poke) 10 + 3       # 13
(poke) 0x0f & 0x07  # AND → 7
(poke) 1 << 4       # シフト → 16
(poke) 5 == 5       # 1(true)
(poke) 5 != 3       # 1(true)

条件分岐

if (ehdr.e_machine == 0x3e) {
    printf "x86-64\n";
} else {
    printf "other arch\n";
}

ループ

// for-in(コレクション走査)
for (c in arr) { printf "%d\n", c; }

// C スタイル for
for (var i = 0; i < 10; ++i) { printf "%d\n", i; }

// while
var i = 0;
while (i < 5) { printf "%d\n", i; ++i; }

関数定義

fun greet = (string name) void:
{
    printf "Hello, %s!\n", name;
}

fun add = (int a, int b) int:
{
    return a + b;
}

(poke) greet ("poke")
Hello, poke!
(poke) add (3, 4)
7

printf のフォーマット指定子

指定子 説明
%d 10 進数(符号あり)
%u 10 進数(符号なし)
%x 16 進数
%s 文字列
%c 文字(char)
%v 値の型付き表示(デバッグに便利)
%i8b 8 ビット 2 進数
(poke) printf "%v\n", ehdr.e_type
0x0001UH
(poke) printf "%i8b\n", 0xa8UB
10101000B

12. pickle(.pk スクリプト)

pickle の基本構造

// dump_section.pk

// 型定義
type MyHdr = struct {
    uint<32> magic;
    uint<16> version;
};

// メイン処理(ファイル読み込み時に自動実行)
var hdr = MyHdr @ 0#B;
printf "magic: 0x%08x, version: %d\n", hdr.magic, hdr.version;

pickle の読み込み

(poke) .load dump_section.pk

shebang で単体コマンドとして実行

#!/usr/bin/env poke -L
// このファイル単体でコマンドとして動く
chmod +x analyze.pk
./analyze.pk target.bin

標準付属 pickle の読み込み例

(poke) load elf                # ELF 解析用 pickle を読み込む
(poke) var ehdr = Elf64_Ehdr @ 0#B

poke に付属する主な pickle:

pickle 対象フォーマット
elf ELF(実行ファイル・オブジェクトファイル)
pcap libpcap パケットキャプチャ
jpeg JPEG 画像
mp3 MP3 ID3 タグ
mbr MBR パーティションテーブル

13. 応用:struct の高度な機能

Field-Constraints(フィールド制約)

フィールドの値に制約を設けます。制約違反時はエラーになります。バリデーションや optional フィールドの実現に使えます。

type Elf64_Ehdr = struct {
    byte[4] e_magic : e_magic == [0x7f, 'E', 'L', 'F']; // マジック検証
    byte    e_class;
    ...
};

Computed Fields(ゲッター)

メソッドで計算された値をフィールドのように参照できます。

type SECTION = struct {
    byte[8] Name;
    ...
    computed string NameStr;
    method get_NameStr = string:
    {
        var s = "";
        for (c in Name) {
            if (c == 0x00) { break; }
            s += c as string;
        }
        return s;
    }
};

(poke) sec.NameStr     # → ".text"

struct メソッド

type MyStruct = struct {
    uint<32> value;
    method double = uint<32>:
    {
        return value * 2;
    }
};
(poke) var s = MyStruct @ 0#B;
(poke) s.double

Pinned Struct(C の union に近いもの)

複数のフィールドが同じオフセットを共有します。

type IPv4OrIPv6 = struct {
    pinned;
    byte[4]  as_v4;
    byte[16] as_v6;
};

Union(条件付き型選択)

条件に応じて1つのフィールドだけがデコードされます。TLV 形式などに有用です。

type Payload = union {
    uint<8>  as_byte  : size == 1#B;
    uint<16> as_short : size == 2#B;
    uint<32> as_int   : size == 4#B;
};

offset 型の ref 属性

offset フィールドに型を指定し、ポインタのように参照を辿れます。

type DOS = struct {
    offset<uint<32>, B, NT> e_lfanew @ 0x3c#B;  // NT 型へのオフセット
};

var dos = DOS @ 0#B;
var nt  = dos.e_lfanew'ref;   // NT 型のマップド値として取得

14. tips・注意事項

⚠️ undo はない

変更はファイルに即時反映されます。必ずバックアップを取ってから編集しましょう。

cp target.bin target.bin.bak
poke target.bin

💡 メモリバッファで安全に実験する

(poke) .mem scratch
(poke) copy :from_ios 0 :from 0#B :size iosize(0) :to_ios 1  # ファイルを scratch にコピー
# scratch 上で自由に編集...
(poke) save :ios 1 :from 0#B :size iosize(0) :file "/tmp/output.bin"

エンディアンの切り替え

(poke) .set endian big     # ビッグエンディアン
(poke) .set endian little  # リトルエンディアン(デフォルト)

型のキャスト

(poke) 0x47UB as int<32>       # 型変換
(poke) 0x47UB as string        # "G"(1 文字の文字列に変換)

よく使う one-liner

# 先頭 4 バイトをマジックナンバーとして確認
(poke) char[4] @ 0#B

# 任意オフセットの uint32 を読む
(poke) uint<32> @ 0x3c#B

# ELF のマシンアーキテクチャを確認
(poke) uint<16> @ 18#B

# 特定バイトを 16 進で上書き
(poke) byte @ 0x10#B = 0xde

# ファイルサイズを確認
(poke) iosize(0)

公式リソース

リソース URL
公式サイト https://www.jemarch.net/poke
公式マニュアル(最新) https://jemarch.net/poke-4.3-manual/poke.html
GNU サイト https://www.gnu.org/software/poke/
バグ報告 https://sourceware.org/bugzilla/
開発メーリングリスト poke-devel(GNU Savannah)
IRC #poke @ Libera.Chat

このチートシートは GNU poke 4.3 時点の情報をもとに作成しました。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment