roaris / ctf-log

0 stars 0 forks source link

SECCON Beginners CTF 2024 : construct #56

Open roaris opened 1 week ago

roaris commented 1 week ago

(まだ問題がGitHubにアップロードされてないので後で追記)

roaris commented 1 week ago

時間中に解けなかった問題

$ ./construct
usage: construct <password>
$ ./construct test
WRONG

main関数をIDAで見ると、どういうわけかフラグを出力する処理しか書かれていない image

Ghidraで確認しても以下のようになっている

void main(undefined8 param_1,long param_2)

{
  puts("CONGRATULATIONS!");
  printf("The flag is ctf4b{%s}\n",*(undefined8 *)(param_2 + 8));
                    /* WARNING: Subroutine does not return */
  _exit(0);
}
roaris commented 1 week ago

そして、実行時に引数を与えなかった時に出てくる表示は、func_e0db2736という関数で行われている

image

では、func_e0db2736はどこからcallされているのだろうと思って、callで検索をかけたが、call func_e0db2736が見つからなかった

image

gdbで動的解析しようにも、上手くいかない

$ gdb -q construct
Reading symbols from construct...
(No debugging symbols found in construct)
gdb-peda$ b main
Breakpoint 1 at 0x191f
gdb-peda$ r test
Starting program: /home/roaris/SECCON_beginners_2024/construct/construct test
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
WRONG
[Inferior 1 (process 3607) exited with code 01]
Warning: 'set logging off', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled off'.

Warning: 'set logging on', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled on'.

Warning: not running

__libc_start_main関数にbreakpointを設定して、ステップ実行してみたが、mov r15,QWORD PTR [rip+0x1ab7fc]という命令の後にWRONGが表示されるという現象が発生し、訳が分からなくて諦めてしまった

gdb-peda$ b __libc_start_main
Breakpoint 1 at 0x7ffff7df2700: file ../csu/libc-start.c, line 311.
gdb-peda$ r test
...
gdb-peda$ n
[----------------------------------registers-----------------------------------]
RAX: 0x7ffff7fa6320 --> 0x7fffffffe050 --> 0x7fffffffe314 ("HOSTTYPE=x86_64")
RBX: 0x7fffffffe038 --> 0x7fffffffe2d8 ("/home/roaris/SECCON_beginners_2024/construct/construct")
RCX: 0x7ffff7f9e840 --> 0x7ffff7fa0300 --> 0x0
RDX: 0xecfa3b6713835b1d
RSI: 0x7ffff7fa0300 --> 0x0
RDI: 0x7ffff7fa0300 --> 0x0
RBP: 0x2
RSP: 0x7fffffffdfd0 --> 0x555555555917 (<main>: endbr64)
RIP: 0x7ffff7df2785 (<__libc_start_main_impl+133>:      mov    r15,QWORD PTR [rip+0x1ab7fc]        # 0x7ffff7f9df88)
R8 : 0x0
R9 : 0x7ffff7fcfb10 (<_dl_fini>:        push   r15)
R10: 0x7ffff7fcb7c8 --> 0xa0012000000c1
R11: 0x202
R12: 0x0
R13: 0x7fffffffe050 --> 0x7fffffffe314 ("HOSTTYPE=x86_64")
R14: 0x0
R15: 0x0
EFLAGS: 0x246 (carry PARITY adjust ZERO sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x7ffff7df277b <__libc_start_main_impl+123>: mov    rdx,rbx
   0x7ffff7df277e <__libc_start_main_impl+126>: mov    esi,ebp
   0x7ffff7df2780 <__libc_start_main_impl+128>: call   0x7ffff7df2650 <__libc_start_call_main>
=> 0x7ffff7df2785 <__libc_start_main_impl+133>: mov    r15,QWORD PTR [rip+0x1ab7fc]        # 0x7ffff7f9df88
   0x7ffff7df278c <__libc_start_main_impl+140>: mov    r14,QWORD PTR [r15]
   0x7ffff7df278f <__libc_start_main_impl+143>: mov    rcx,QWORD PTR [r14+0xa0]
   0x7ffff7df2796 <__libc_start_main_impl+150>: test   rcx,rcx
   0x7ffff7df2799 <__libc_start_main_impl+153>: je     0x7ffff7df27ac <__libc_start_main_impl+172>
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdfd0 --> 0x555555555917 (<main>:        endbr64)
0008| 0x7fffffffdfd8 --> 0x7fff00000000
0016| 0x7fffffffdfe0 --> 0x0
0024| 0x7fffffffdfe8 --> 0x0
0032| 0x7fffffffdff0 --> 0x0
0040| 0x7fffffffdff8 --> 0x555555555100 (<_start>:      endbr64)
0048| 0x7fffffffe000 --> 0x7fffffffe030 --> 0x2
0056| 0x7fffffffe008 --> 0x0
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
347     in ../csu/libc-start.c
gdb-peda$ n
WRONG
[Inferior 1 (process 3640) exited with code 01]
Warning: not running
roaris commented 1 week ago

他の人のwriteupを確認する

roaris commented 1 week ago

.init_arrayという関数のアドレスを格納する配列があって、リンカが順番に関数を実行していくという仕組みがあるらしい

https://docs.oracle.com/cd/E19683-01/817-3496/6mj39o7ia/index.html

制御をアプリケーションに移す前に、実行時リンカーは、アプリケーションおよび読み込まれた依存関係内で見つかった初期設定セクションを処理します。 初期設定セクションである .preinit_array、.init_array、および .init は、動的オブジェクトが構築される際にリンカーによって作成されます。 実行時リンカーは、.preinit_array セクションと .init_array セクションにアドレスが指定されている関数を実行します。これらの関数は、配列内でアドレスが出現する順序で実行されます。

roaris commented 1 week ago

.init_arrayを確認する方法が簡単に見つからなかったので、chatgptに聞いた objdumpコマンドで確認出来るらしい

$ objdump -s --section .init_array construct

construct:     file format elf64-x86-64

Contents of section .init_array:
 3cf8 e9110000 00000000 1e120000 00000000  ................
 3d08 fb160000 00000000 3f180000 00000000  ........?.......
 3d18 2f130000 00000000 c3120000 00000000  /...............
 3d28 b7150000 00000000 4b150000 00000000  ........K.......
 3d38 67170000 00000000 07140000 00000000  g...............
 3d48 df140000 00000000 ab180000 00000000  ................
 3d58 57120000 00000000 9b130000 00000000  W...............
 3d68 8f160000 00000000 23160000 00000000  ........#.......
 3d78 d3170000 00000000 73140000 00000000  ........s.......
 3d88 e0110000 00000000                    ........        

ちなみにreadelfコマンドを使うと、.init_arrayの開始位置とサイズが分かる

$ readelf -d construct

Dynamic section at offset 0x2da0 contains 27 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000c (INIT)               0x1000
 0x000000000000000d (FINI)               0x1980
 0x0000000000000019 (INIT_ARRAY)         0x3cf8
 0x000000000000001b (INIT_ARRAYSZ)       152 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x3d90
 0x000000000000001c (FINI_ARRAYSZ)       16 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x3b0
 0x0000000000000005 (STRTAB)             0x4f8
 0x0000000000000006 (SYMTAB)             0x3d8
 0x000000000000000a (STRSZ)              169 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000015 (DEBUG)              0x0
 0x0000000000000003 (PLTGOT)             0x3f90
 0x0000000000000002 (PLTRELSZ)           144 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x878
 0x0000000000000007 (RELA)               0x5f0
 0x0000000000000008 (RELASZ)             648 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000000000001e (FLAGS)              BIND_NOW
 0x000000006ffffffb (FLAGS_1)            Flags: NOW PIE
 0x000000006ffffffe (VERNEED)            0x5c0
 0x000000006fffffff (VERNEEDNUM)         1
 0x000000006ffffff0 (VERSYM)             0x5a2
 0x000000006ffffff9 (RELACOUNT)          22
 0x0000000000000000 (NULL)               0x0

開始位置が0x3cf8で、サイズが152バイトというのは、objdumpの結果と一致している

roaris commented 1 week ago

objdumpで出力した.init_arrayを確認しよう

$ objdump -s --section .init_array construct

construct:     file format elf64-x86-64

Contents of section .init_array:
 3cf8 e9110000 00000000 1e120000 00000000  ................
 3d08 fb160000 00000000 3f180000 00000000  ........?.......
 3d18 2f130000 00000000 c3120000 00000000  /...............
 3d28 b7150000 00000000 4b150000 00000000  ........K.......
 3d38 67170000 00000000 07140000 00000000  g...............
 3d48 df140000 00000000 ab180000 00000000  ................
 3d58 57120000 00000000 9b130000 00000000  W...............
 3d68 8f160000 00000000 23160000 00000000  ........#.......
 3d78 d3170000 00000000 73140000 00000000  ........s.......
 3d88 e0110000 00000000                    ........        

これは19個の関数のアドレスが、それぞれリトルエンディアンで並べられている 先頭から見ていくと、 0x11e9 : func_e0db2736 0x121e : func_f8db6e92 0x16fb : func_9e540c6a 0x183f : func_21670b38 ... 0x1473 : func_da53ce29 0x11e0 : frame_dummy となっている

func_e0db2736は先ほど見たように、実行時に引数を与えなかった時に出てくる表示を行う Ghidraで見るとこうなっている

void func_e0db2736(int param_1)

{
  if (param_1 != 2) {
    puts("usage: construct <password>");
                    /* WARNING: Subroutine does not return */
    _exit(1);
  }
  return;
}

func_f8db6e92は引数の長さが32かをチェックする関数である 長さが32じゃなかったらexitしている

void func_f8db6e92(undefined8 param_1,long param_2)

{
  size_t sVar1;

  sVar1 = strlen(*(char **)(param_2 + 8));
  if (sVar1 != 0x20) {
                    /* WARNING: Subroutine does not return */
    exit(1);
  }
  return;
}

param2 + 8の8が何なのか少し気になる

続く16個の関数ではstrncmpで文字列比較を行い、一致しなかったらexitしている

void func_9e540c6a(undefined8 param_1,long param_2)

{
  int iVar1;

  iVar1 = strncmp((char *)((long)i + *(long *)(param_2 + 8)),
                  "c0_d4yk261hbosje893w5igzfrvaumqlptx7n" + i,2);
  if (iVar1 != 0) {
                    /* WARNING: Subroutine does not return */
    exit(1);
  }
  i = i + 2;
  return;
}
void func_21670b38(undefined8 param_1,long param_2)

{
  int iVar1;

  iVar1 = strncmp((char *)((long)i + *(long *)(param_2 + 8)),
                  "oxnske1cgaiylz0mwfv7p9r32h6qj8bt4d_u5" + i,2);
  if (iVar1 != 0) {
                    /* WARNING: Subroutine does not return */
    exit(1);
  }
  i = i + 2;
  return;
}

strncmpの第3引数が2なのと、i = i + 2を見ると、引数として与えた文字列の先頭から2文字ずつ比較されると推測できる frame_dummyは謎だから置いとこう

roaris commented 1 week ago

以下のプログラムでフラグが出てくる

l = [
    'c0_d4yk261hbosje893w5igzfrvaumqlptx7n',
    'oxnske1cgaiylz0mwfv7p9r32h6qj8bt4d_u5',
    'lzau7rvb9qh5_1ops6jg3ykf8x0emtcind24w',
    '9_xva4uchnkyi6wb2ld507p8g3stfej1rzqmo',
    'r8x9wn65701zvbdfp4ioqc2hy_juegkmatls3',
    'tufij3cykhrsl841qo6_0dwg529zanmbpvxe7',
    'b0i21csjhqug_3erat9f6mx854pyol7zkvdwn',
    '17zv5h6wjgbqerastioc294n0lxu38fdk_ypm',
    '1cgovr4tzpnj29ay3_8wk7li6uqfmhe50bdsx',
    '3icj_go9qd0svxubefh14ktywpzma2l7nr685',
    'c7l9532k0avfxso4uzipd18egbnyw6rm_tqjh',
    'l8s0xb4i1frkv6a92j5eycng3mwpzduqth_7o',
    'l539rbmoifye0u6dj1pw8nqt_74sz2gkvaxch',
    'aj_d29wcrqiok53b7tyn0p6zvfh1lxgum48es',
    '3mq16t9yfs842cbvlw5j7k0prohengduzx_ai',
    '_k6nj8hyxvzcgr1bu2petf5qwl09ids!om347a'
]

flag = ''

for i in range(16):
    flag += l[i][2*i:2*i+2]

print(flag) # c0ns7ruc70rs_3as3_h1d1ng_7h1ngs!

constructors ease hiding things!とある まだ問題がGitHubにアップロードされていないので、元のソースコードが分からないが、.init_arrayの中にある関数はコンストラクタということだろうか

https://tyfkda.github.io/blog/2014/03/10/use-cpp.html

グローバル変数でクラスのインスタンスを定義した場合、main関数の呼び出しよりも先にそれらのコンストラクタが呼び出される必要がある。g++はそのような変数に対する初期化コードへの関数ポインタを.preinit_array, .init_arrayというセクションに、また終了処理を.fini_arrayに?出力する。 そこで、リンカスクリプトでこれらのデータをデータセクションに配置して、OSがアプリケーションを呼び出す際にmain関数の呼び出し前に呼び出してやれば良い。

roaris commented 1 week ago

.init_arrayのことを知らなくても解くことは可能(74チームに解かれていて、意外と解かれているという印象)

引数の長さが32じゃないといけないというのはGhidraから読み取る そしたらgdbでstrncmpを読んでいる16個の関数全てにbreakpointを設定し、関数の順番を特定することが出来る

以下のような手順である

gdb-peda$ b func_9e540c6a
Breakpoint 1 at 0x1703
gdb-peda$ b func_21670b38
Breakpoint 2 at 0x1847
gdb-peda$ b func_b548021f
Breakpoint 3 at 0x1337
gdb-peda$ r aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Starting program: /home/roaris/SECCON_beginners_2024/construct/construct aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Warning: 'set logging off', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled off'.

Warning: 'set logging on', an alias for the command 'set logging enabled', is deprecated.
Use 'set logging enabled on'.
[----------------------------------registers-----------------------------------]
RAX: 0x20 (' ')
RBX: 0x7fffffffe018 --> 0x7fffffffe2bc ("/home/roaris/SECCON_beginners_2024/construct/construct")
RCX: 0x555555557d08 --> 0x5555555556fb (<func_9e540c6a>:        endbr64)
RDX: 0x7fffffffe030 --> 0x7fffffffe314 ("HOSTTYPE=x86_64")
RSI: 0x7fffffffe018 --> 0x7fffffffe2bc ("/home/roaris/SECCON_beginners_2024/construct/construct")
RDI: 0x2
RBP: 0x7fffffffdfa0 --> 0x2
RSP: 0x7fffffffdfa0 --> 0x2
RIP: 0x555555555703 (<func_9e540c6a+8>: sub    rsp,0x10)
R8 : 0x0
R9 : 0x7ffff7fcfb10 (<_dl_fini>:        push   r15)
R10: 0x7ffff7fcb7c8 --> 0xa0012000000c1
R11: 0x206
R12: 0x0
R13: 0x7fffffffe030 --> 0x7fffffffe314 ("HOSTTYPE=x86_64")
R14: 0x555555557d10 --> 0x55555555583f (<func_21670b38>:        endbr64)
R15: 0x7ffff7ffd000 --> 0x7ffff7ffe2d0 --> 0x555555554000 --> 0x10102464c457f
EFLAGS: 0x212 (carry parity ADJUST zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x5555555556fb <func_9e540c6a>:      endbr64
   0x5555555556ff <func_9e540c6a+4>:    push   rbp
   0x555555555700 <func_9e540c6a+5>:    mov    rbp,rsp
=> 0x555555555703 <func_9e540c6a+8>:    sub    rsp,0x10
   0x555555555707 <func_9e540c6a+12>:   mov    DWORD PTR [rbp-0x4],edi
   0x55555555570a <func_9e540c6a+15>:   mov    QWORD PTR [rbp-0x10],rsi
   0x55555555570e <func_9e540c6a+19>:   mov    eax,DWORD PTR [rip+0x2900]        # 0x555555558014 <i>
   0x555555555714 <func_9e540c6a+25>:   cdqe
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdfa0 --> 0x2
0008| 0x7fffffffdfa8 --> 0x7ffff7df27f6 (<__libc_start_main_impl+246>:  mov    rcx,r14)
0016| 0x7fffffffdfb0 --> 0x555555555917 (<main>:        endbr64)
0024| 0x7fffffffdfb8 --> 0x555555557d90 --> 0x5555555551a0 (<__do_global_dtors_aux>:    endbr64)
0032| 0x7fffffffdfc0 --> 0x0
0040| 0x7fffffffdfc8 --> 0x0
0048| 0x7fffffffdfd0 --> 0x0
0056| 0x7fffffffdfd8 --> 0x555555555100 (<_start>:      endbr64)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x0000555555555703 in func_9e540c6a ()
gdb-peda$ c
Continuing.
WRONG
[Inferior 1 (process 5204) exited with code 01]
Warning: not running
gdb-peda$ r c0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Starting program: /home/roaris/SECCON_beginners_2024/construct/construct c0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[----------------------------------registers-----------------------------------]
RAX: 0x20 (' ')
RBX: 0x7fffffffe018 --> 0x7fffffffe2bc ("/home/roaris/SECCON_beginners_2024/construct/construct")
RCX: 0x555555557d08 --> 0x5555555556fb (<func_9e540c6a>:        endbr64)
RDX: 0x7fffffffe030 --> 0x7fffffffe314 ("HOSTTYPE=x86_64")
RSI: 0x7fffffffe018 --> 0x7fffffffe2bc ("/home/roaris/SECCON_beginners_2024/construct/construct")
RDI: 0x2
RBP: 0x7fffffffdfa0 --> 0x2
RSP: 0x7fffffffdfa0 --> 0x2
RIP: 0x555555555703 (<func_9e540c6a+8>: sub    rsp,0x10)
R8 : 0x0
R9 : 0x7ffff7fcfb10 (<_dl_fini>:        push   r15)
R10: 0x7ffff7fcb7c8 --> 0xa0012000000c1
R11: 0x206
R12: 0x0
R13: 0x7fffffffe030 --> 0x7fffffffe314 ("HOSTTYPE=x86_64")
R14: 0x555555557d10 --> 0x55555555583f (<func_21670b38>:        endbr64)
R15: 0x7ffff7ffd000 --> 0x7ffff7ffe2d0 --> 0x555555554000 --> 0x10102464c457f
EFLAGS: 0x212 (carry parity ADJUST zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x5555555556fb <func_9e540c6a>:      endbr64
   0x5555555556ff <func_9e540c6a+4>:    push   rbp
   0x555555555700 <func_9e540c6a+5>:    mov    rbp,rsp
=> 0x555555555703 <func_9e540c6a+8>:    sub    rsp,0x10
   0x555555555707 <func_9e540c6a+12>:   mov    DWORD PTR [rbp-0x4],edi
   0x55555555570a <func_9e540c6a+15>:   mov    QWORD PTR [rbp-0x10],rsi
   0x55555555570e <func_9e540c6a+19>:   mov    eax,DWORD PTR [rip+0x2900]        # 0x555555558014 <i>
   0x555555555714 <func_9e540c6a+25>:   cdqe
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdfa0 --> 0x2
0008| 0x7fffffffdfa8 --> 0x7ffff7df27f6 (<__libc_start_main_impl+246>:  mov    rcx,r14)
0016| 0x7fffffffdfb0 --> 0x555555555917 (<main>:        endbr64)
0024| 0x7fffffffdfb8 --> 0x555555557d90 --> 0x5555555551a0 (<__do_global_dtors_aux>:    endbr64)
0032| 0x7fffffffdfc0 --> 0x0
0040| 0x7fffffffdfc8 --> 0x0
0048| 0x7fffffffdfd0 --> 0x0
0056| 0x7fffffffdfd8 --> 0x555555555100 (<_start>:      endbr64)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 1, 0x0000555555555703 in func_9e540c6a ()
gdb-peda$ c
Continuing.
[----------------------------------registers-----------------------------------]
RAX: 0x2
RBX: 0x7fffffffe018 --> 0x7fffffffe2bc ("/home/roaris/SECCON_beginners_2024/construct/construct")
RCX: 0x555555557d10 --> 0x55555555583f (<func_21670b38>:        endbr64)
RDX: 0x7fffffffe030 --> 0x7fffffffe314 ("HOSTTYPE=x86_64")
RSI: 0x7fffffffe018 --> 0x7fffffffe2bc ("/home/roaris/SECCON_beginners_2024/construct/construct")
RDI: 0x2
RBP: 0x7fffffffdfa0 --> 0x2
RSP: 0x7fffffffdfa0 --> 0x2
RIP: 0x555555555847 (<func_21670b38+8>: sub    rsp,0x10)
R8 : 0x0
R9 : 0x7ffff7fcfb10 (<_dl_fini>:        push   r15)
R10: 0x7ffff7fcb7c8 --> 0xa0012000000c1
R11: 0x206
R12: 0x0
R13: 0x7fffffffe030 --> 0x7fffffffe314 ("HOSTTYPE=x86_64")
R14: 0x555555557d18 --> 0x55555555532f (<func_b548021f>:        endbr64)
R15: 0x7ffff7ffd000 --> 0x7ffff7ffe2d0 --> 0x555555554000 --> 0x10102464c457f
EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
   0x55555555583f <func_21670b38>:      endbr64
   0x555555555843 <func_21670b38+4>:    push   rbp
   0x555555555844 <func_21670b38+5>:    mov    rbp,rsp
=> 0x555555555847 <func_21670b38+8>:    sub    rsp,0x10
   0x55555555584b <func_21670b38+12>:   mov    DWORD PTR [rbp-0x4],edi
   0x55555555584e <func_21670b38+15>:   mov    QWORD PTR [rbp-0x10],rsi
   0x555555555852 <func_21670b38+19>:   mov    eax,DWORD PTR [rip+0x27bc]        # 0x555555558014 <i>
   0x555555555858 <func_21670b38+25>:   cdqe
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdfa0 --> 0x2
0008| 0x7fffffffdfa8 --> 0x7ffff7df27f6 (<__libc_start_main_impl+246>:  mov    rcx,r14)
0016| 0x7fffffffdfb0 --> 0x555555555917 (<main>:        endbr64)
0024| 0x7fffffffdfb8 --> 0x555555557d90 --> 0x5555555551a0 (<__do_global_dtors_aux>:    endbr64)
0032| 0x7fffffffdfc0 --> 0x0
0040| 0x7fffffffdfc8 --> 0x0
0048| 0x7fffffffdfd0 --> 0x0
0056| 0x7fffffffdfd8 --> 0x555555555100 (<_start>:      endbr64)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value

Breakpoint 2, 0x0000555555555847 in func_21670b38 ()
gdb-peda$ c
Continuing.
WRONG
[Inferior 1 (process 5207) exited with code 01]
Warning: not running

3個の関数にしかbreakpointを設定していないが、本当は16個の関数に設定する aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaを与えると、 func_9e540c6aが実行された後にWRONGと出るため、1個目に実行されるのはfunc_9e540c6aだと分かる 次に、c0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaを与えると、func_9e540c6aの後に、func_21670b38が実行されてWRONGと出るため、func_9e540c6aの次に実行されるのはfunc_21670b38だと分かる なので、今度はc0nsaaaaaaaaaaaaaaaaaaaaaaaaaaaaを試す、といった流れである