土日の勉強ノート

AI、機械学習、最適化、Pythonなどについて、技術調査、技術書の理解した内容、ソフトウェア/ツール作成について書いていきます

picoCTF 2023:Reverse Engineeringの全9問をやってみた

前回 は、picoCTF の picoCTF 2023 の General Skills をやってみました。全6問を全て解きました。

今回は、引き続き、picoCTF 2023 の Reverse Engineering をやっていきます。Medium が 7問、Hard が 2問です。

それでは、やっていきます。

はじめに

「セキュリティ」の記事一覧です。良かったら参考にしてください。

セキュリティの記事一覧
・第1回:Ghidraで始めるリバースエンジニアリング(環境構築編)
・第2回:Ghidraで始めるリバースエンジニアリング(使い方編)
・第3回:VirtualBoxにParrotOS(OVA)をインストールする
・第4回:tcpdumpを理解して出力を正しく見れるようにする
・第5回:nginx(エンジンエックス)を理解する
・第6回:Python+Flask(WSGI+Werkzeug+Jinja2)を動かしてみる
・第7回:Python+FlaskのファイルをCython化してみる
・第8回:shadowファイルを理解してパスワードを解読してみる
・第9回:安全なWebアプリケーションの作り方(徳丸本)の環境構築
・第10回:Vue.jsの2.xと3.xをVue CLIを使って動かしてみる(ビルドも行う)
・第11回:Vue.jsのソースコードを確認する(ビルド後のソースも見てみる)
・第12回:徳丸本:OWASP ZAPの自動脆弱性スキャンをやってみる
・第13回:徳丸本:セッション管理を理解してセッションID漏洩で成りすましを試す
・第14回:OWASP ZAPの自動スキャン結果の分析と対策:パストラバーサル
・第15回:OWASP ZAPの自動スキャン結果の分析と対策:クロスサイトスクリプティング(XSS)
・第16回:OWASP ZAPの自動スキャン結果の分析と対策:SQLインジェクション
・第17回:OWASP ZAPの自動スキャン結果の分析と対策:オープンリダイレクト
・第18回:OWASP ZAPの自動スキャン結果の分析と対策:リスク中すべて
・第19回:CTF初心者向けのCpawCTFをやってみた
・第20回:hashcatの使い方(GPU実行時間の見積りとパスワード付きZIPファイル)
・第21回:Scapyの環境構築とネットワークプログラミング
・第22回:CpawCTF2にチャレンジします(クリア状況は随時更新します)
・第23回:K&Rのmalloc関数とfree関数を理解する
・第24回:C言語、アセンブラでシェルを起動するプログラムを作る(ARM64)
・第25回:機械語でシェルを起動するプログラムを作る(ARM64)
・第26回:入門セキュリhttps://github.com/SECCON/SECCON2017_online_CTF.gitティコンテスト(CTFを解きながら学ぶ実践技術)を読んだ
・第27回:x86-64 ELF(Linux)のアセンブラをGDBでデバッグしながら理解する(GDBコマンド、関連ツールもまとめておく)
・第28回:入門セキュリティコンテスト(CTFを解きながら学ぶ実践技術)のPwnable問題をやってみる
・第29回:実行ファイルのセキュリティ機構を調べるツール「checksec」のまとめ
・第30回:setodaNote CTF Exhibitionにチャレンジします(クリア状況は随時更新します)
・第31回:常設CTFのksnctfにチャレンジします(クリア状況は随時更新します)
・第32回:セキュリティコンテストチャレンジブックの「Part2 pwn」を読んだ
・第33回:セキュリティコンテストチャレンジブックの「付録」を読んでx86とx64のシェルコードを作った
・第34回:TryHackMeを始めてみたけどハードルが高かった話
・第35回:picoCTFを始めてみた(Beginner picoMini 2022:全13問完了)
・第36回:picoCTF 2024:Binary Exploitationの全10問をやってみた(Hardの1問は後日やります)
・第37回:picoCTF 2024:Reverse Engineeringの全7問をやってみた(Windowsプログラムの3問は後日やります)
・第38回:picoCTF 2024:General Skillsの全10問をやってみた
・第39回:picoCTF 2024:Web Exploitationの全6問をやってみた(最後の2問は解けず)
・第40回:picoCTF 2024:Forensicsの全8問をやってみた(最後の2問は解けず)
・第41回:picoCTF 2024:Cryptographyの全5問をやってみた(最後の2問は手つかず)
・第42回:picoCTF 2023:General Skillsの全6問をやってみた
・第43回:picoCTF 2023:Reverse Engineeringの全9問をやってみた ← 今回

picoCTF の公式サイトは以下です。英語のサイトですが、シンプルで分かりやすいので困らずに進めることができます。

picoctf.com

それでは、やっていきます。

picoCTF 2023:Reverse Engineering

ポイントの低い順にやっていきます。

Ready Gladiator 0(100ポイント)

Medium の問題です。サーバを起動して進める問題のようです。

Ready Gladiator 0問題
Ready Gladiator 0問題

インスタンス(サーバ)を起動すると、ソースコード?(imp.red)がダウンロードできました。内容は以下です。

;redcode
;name Imp Ex
;assert 1
mov 0, 1
end

とにかく、サーバに接続してみます。うーん、全く分かりません。

$ nc saturn.picoctf.net 52451 < imp.red
;redcode
;name Imp Ex
;assert 1
mov 0, 1
end
Submit your warrior: (enter 'end' when done)

Warrior1:
;redcode
;name Imp Ex
;assert 1
mov 0, 1
end

Rounds: 100
Warrior 1 wins: 0
Warrior 2 wins: 0
Ties: 100
Try again. Your warrior (warrior 1) must lose all rounds, no ties.

次は、imp.red を入力せずに接続してみます。あ、フラグが表示されました。全然分かりませんでした。

$ nc saturn.picoctf.net 52451
Submit your warrior: (enter 'end' when done)

end
end
Warrior1:

end

Warning:
        Missing ';assert'. Warrior may not work with the current setting
Warning:
        No instructions
Number of warnings: 2

Rounds: 100
Warrior 1 wins: 0
Warrior 2 wins: 100
Ties: 0
You did it!
picoCTF{h3r0_t0_z3r0_4m1r1gh7_a220a377}

「Ready Gladiator 1」、「Ready Gladiator 2」と続くみたいなので、その時に理解しようと思います。

Reverse(100ポイント)

Medium の問題です。1つのファイル()がダウンロードできます。

Reverse問題
Reverse問題

表層解析します。

$ file ret 
ret: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=32195c65c0c8ca5bd239fa824d4d79231cca5f78, for GNU/Linux 3.2.0, not stripped

$ checksec --file=ret
RELRO       STACK CANARY  NX          PIE          RPATH     RUNPATH     Symbols     FORTIFY  Fortified  Fortifiable  FILE
Full RELRO  Canary found  NX enabled  PIE enabled  No RPATH  No RUNPATH  69 Symbols  No       0          1            ret

実行できそうなので、やってみます。正しいパスワードを探す必要がありそうです。

$ ./ret
Enter the password to unlock this file: abc
You entered: abc
Access denied

Ghidra で見てみます。

main関数です。うーん、フラグが見えちゃってますね(笑)。

一応、local_38 と同じ値の文字列を入力すればいいようです。local_38 は、8byteですが、文字列なので local_30、local_28、local_20、local_18 と続きます。local_10 はスタックカナリアなので、何が入るかわかりません。これは、解けない問題ということかもしれません。

undefined8 main(void)

{
  int iVar1;
  long in_FS_OFFSET;
  char local_68 [48];
  undefined8 local_38;
  undefined8 local_30;
  undefined8 local_28;
  undefined8 local_20;
  undefined8 local_18;
  long local_10;
  
  local_10 = *(long *)(in_FS_OFFSET + 0x28);
  local_38 = 0x7b4654436f636970;
  local_30 = 0x337633725f666c33;
  local_28 = 0x75735f676e693572;
  local_20 = 0x6c75663535656363;
  local_18 = 0x643536393338635f;
  printf("Enter the password to unlock this file: ");
  __isoc99_scanf(&DAT_00102031,local_68);
  printf("You entered: %s\n",local_68);
  iVar1 = strcmp(local_68,(char *)&local_38);
  if (iVar1 == 0) {
    puts("Password correct, please see flag: picoCTF{3lf_r3v3r5ing_succe55ful_c83965de}");
    puts((char *)&local_38);
  }
  else {
    puts("Access denied");
  }
  if (local_10 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}

文字列は以下です。フラグがパスワードになっていました。途中までですけど。

$ python -c 'import struct; print(struct.pack("<QQQQQ",0x7b4654436f636970, 0x337633725f66
6c33, 0x75735f676e693572, 0x6c75663535656363, 0x643536393338635f))'
b'picoCTF{3lf_r3v3r5ing_succe55ful_c83965d'

Safe Opener 2(100ポイント)

Medium の問題です。1つのファイル(SafeOpener.class)がダウンロードできます。

Safe Opener 2問題
Safe Opener 2問題

fileコマンドを実行してみます。Java の classファイルでした。

$ file SafeOpener.class
SafeOpener.class: compiled Java class data, version 52.0 (Java 1.8)

jadx を使ってデコンパイルします。また、フラグが見えちゃってます(笑)。

package defpackage;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Base64;

/* loaded from: SafeOpener.class */
public class SafeOpener {
    public static void main(String[] args) throws IOException {
        BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
        Base64.Encoder encoder = Base64.getEncoder();
        for (int i = 0; i < 3; i++) {
            System.out.print("Enter password for the safe: ");
            String key = keyboard.readLine();
            String encodedkey = encoder.encodeToString(key.getBytes());
            System.out.println(encodedkey);
            boolean isOpen = openSafe(encodedkey);
            if (!isOpen) {
                System.out.println("You have  " + (2 - i) + " attempt(s) left");
            } else {
                return;
            }
        }
    }

    public static boolean openSafe(String password) {
        if (password.equals("picoCTF{SAf3_0p3n3rr_y0u_solv3d_it_5bfbd6f1}")) {
            System.out.println("Sesame open");
            return true;
        }
        System.out.println("Password is incorrect\n");
        return false;
    }
}

簡単な問題と難しい問題の差が激しいですね。

timer(100ポイント)

Medium の問題です。1つのファイル(timer.apk)がダウンロードできます。

timer問題
timer問題

fileコマンドを実行してみます。APKファイルでした。2問続けて JAVAのようです。

$ file timer.apk
timer.apk: Android package (APK), with zipflinger virtual entry, with APK Signing Block

jadx を使ってデコンパイルします。今度は、とても大きなファイル(約4.5MB)です。

あ、2個目に見たファイル(AndroidManifest.xml)にフラグがありました(笑)。

picoCTF{t1m3r_r3v3rs3d_succ355fully_17496} でした。

Virtual Machine 0(100ポイント)

Medium の問題です。2つのファイル(input.txt と Virtual-Machine-0.zip)がダウンロードできます。

Virtual Machine 0問題
Virtual Machine 0問題

1つ目のファイルは、テキストファイルで、内容は、39722847074734820757600524178581224432297292490103995897672826024691504153 でした。16進数では、0x167b7a4973dda7b247d70a7d3ddfd67adfe2a34a0a463cd77aa43d09a41419 でした。ASCIIコードにはなりそうにない感じです。

2つ目のファイルは、ZIPファイルで解凍したら、Virtual-Machine-0.dae というファイルが得られました。うさみみハリケーンで確認します。COLLADAデータというもので、Web検索したところ、3DCG用のデータらしいです。

うーん、困ったときは、とりあえず、Chrome に放り込んでみます。XML形式でそれなりに読める感じです。オンラインにビューアがあったのでアップしてみます。なんか 3D でグルグル動かせる感じです。ビューアでは何ともならなさそうなので、XML のところを見てみると、MecaBricks というソフトで作られたようで、オンラインでレゴブロックを作れるソフトのようです。

ただ、調べてみると、MecaBricks のソフトでは、dae の拡張子からはインポートできなさそうです。さらに調べてみると、blender というソフトがインポートできるようです。フリー、かつ、インストールせずに、実行ファイルがダウンロードできるようなので、Linux(ParrotOS)にダウンロードして実行してみました。しかし、セグメンテーションフォールトで起動しませんでした。仕方ないので、Windows にインストールしてみます。インストールが終わって、daeファイルをインポートすることが出来ました。黒い箱に赤と青のつまみ?があります。内部を見ると歯車があって、赤を回すと、青が回る感じになっています。周りの黒いレゴブロックが邪魔なので削除してみました。

レゴブロック
レゴブロック

赤を回すと青が回るようですが、実際に動かそうとしても、赤のつまみだけが動いて、連動して青を動かすことは出来ませんでした。YouTube で blender入門みたいな動画を見ると、連動して動かせそうでしたが、設定が難しそうだったので断念しました。

動かすことは本筋ではないので、問題の答えを考えていきます。input.txt の内容で赤を動かすと、青が出力ということなので、青がどれだけ回るかということでしょうか。赤い歯は 40個の凹凸がありました。上のキャプチャでは見にくいかもしれませんが、カメラ視点を動かして、黒の歯と青の歯が 8個だったことが分かりました。赤の歯が 1回転すると、黒と青の歯は 5回転することになります。入力が 5倍になるってことでしょうか。python でやってみます。

5倍にするとなんかいけそうな数字に見えてきました。フラグ出ました!インストールした甲斐がありました!

$ python
Python 3.11.2 (main, May  2 2024, 11:59:08) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> red = 39722847074734820757600524178581224432297292490103995897672826024691504153
>>> red
39722847074734820757600524178581224432297292490103995897672826024691504153
>>> blue = red * 5
>>> blue
198614235373674103788002620892906122161486462450519979488364130123457520765
>>> hex(red)
'0x167b7a4973dda7b247d70a7d3ddfd67adfe2a34a0a463cd77aa43d09a41419'
>>> hex(blue)
'0x7069636f4354467b67333472355f30665f6d3072335f30356535313034647d'
>>> hh = hex(blue)[2:]
>>> "".join([chr(int(hh[ii] + hh[ii+1], base=16)) for ii in range(0, len(hh), 2)])
'picoCTF{g34r5_0f_m0r3_05e5104d}'

これって、リバースエンジニアリングは関係あったんでしょうか(笑)

No way out(200ポイント)

200ポイントですが、Hard の問題です。Windows用のプログラムと MAC用のプログラムがダウンロードできるようです。Linux用はありません。

No way out問題
No way out問題

ダウンロードした ZIPファイルを解凍すると、いくつかのファイルを格納したフォルダが得られます。pico.exe というファイルがあるので、ダブルクリックで起動してみます。え、結構本格的なゲームっぽい感じです。どうやってリバースエンジニアリングするんでしょうか、Ghidra か、Windows の場合は、C# なら、ILSpy というツールがありますが、それ以外は知りません。

pico.exe
pico.exe

メニューを開くと、WASD で移動、SHIFT が SPRINT(走る)、CTRL が CROUPH(しゃがむ)、SPACE がジャンプのようです。

ハシゴに近づくと、ハシゴに登れるか?とメッセージが出ました。まずは、ハシゴを上ることが目標です。ハシゴに真っすぐ向かって、W を押し続けてると、ハシゴを登ることが出来ました。次はどうしたらいいでしょうか。あ、最初はバールを持ってましたが、上がった後は、スコップ?みたいなものに変わりました。うっかり下に落ちてしまいましたが、落ちた後もスコップのままです。次はこれで何かをするようです。久しぶりの 3D のゲームで、ちょっと気持ち悪くなってきました。

次の日になりました。落ち着いて考えたら、まだうさみみハリケーンで確認してませんでした。解凍したフォルダに対して、YARAルールスキャンをやってみます。うーん、何も見つかりませんでした。仕方ないおんで、また、ゲームと向き合います。

ハシゴで上がったあと、周りの塀の上を歩くことが出来るようです。グルっと一周できます。あと、マウスホイールを回すと武器が変わります。2階に上がったから武器が変わったわけではありませんでした。今のところ、何か変化というか動きがあったのは、ハシゴだけです。2階に上がると、旗と近づけます。この旗がめちゃくちゃ怪しいですよね。しかし、旗には近づけません。

pico.exe2
pico.exe2

よく分からなくなったので、本題のリバースエンジニアリングについてやり方を考えていきます。ダウンロードした ZIPファイルを解凍したフォルダには多くのファイルが含まれている状態です。

とりあえず、起動する pico.exe というプログラムを ILSpy で開いてみました。「PE file does not contain any managed metadata.」と言われて、うまくいってなさそうです。

次に、Ghidra で、pico.exe を開いてみます。解析は順調に進んでいます。何となく、フォルダ内にある依存関係のあるファイルについても解析が進んでいるようです。結構な時間がかかって完了しました。entry は以下の感じです。__security_init_cookie() はセキュリティ機構の何かだと思います。そうすると、FUN_1400010ec() だけになります。

FUN_1400010ec() の真ん中より少し下に、UnityMain という関数が見えます。いくつか関数名が見えてるものもあります。おそらく、外部関数なんだと思います。ちらちらと下の層に潜っていったりはりましたが、GUIプログラムの見方が分からず、規模も大きそうで厳しい感じです。

void entry(void)
{
  __security_init_cookie();
  FUN_1400010ec();
  return;
}

ulonglong FUN_1400010ec(void)
{
  code *pcVar1;
  bool bVar2;
  char cVar3;
  undefined uVar4;
  undefined2 uVar5;
  int iVar6;
  uint uVar7;
  code **ppcVar8;
  longlong *plVar9;
  undefined8 uVar10;
  ulonglong uVar11;
  ulonglong unaff_RBX;
  
  cVar3 = __scrt_initialize_crt(1);
  if (cVar3 == '\0') {
    __scrt_fastfail(7);
  }
  else {
    bVar2 = false;
    uVar4 = __scrt_acquire_startup_lock();
    unaff_RBX = CONCAT71((int7)(unaff_RBX >> 8),uVar4);
    if (DAT_140015a18 != 1) {
      if (DAT_140015a18 == 0) {
        DAT_140015a18 = 1;
        iVar6 = _initterm_e(&DAT_14000c260,&DAT_14000c290);
        if (iVar6 != 0) {
          return 0xff;
        }
        _initterm(&DAT_14000c248,&DAT_14000c258);
        DAT_140015a18 = 2;
      }
      else {
        bVar2 = true;
      }
      __scrt_release_startup_lock(uVar4);
      ppcVar8 = (code **)FUN_1400015d4();
      if ((*ppcVar8 != (code *)0x0) &&
         (cVar3 = __scrt_is_nonwritable_in_current_image(ppcVar8), cVar3 != '\0')) {
        (**ppcVar8)(0,2);
      }
      plVar9 = (longlong *)FUN_1400015dc();
      if ((*plVar9 != 0) && (cVar3 = __scrt_is_nonwritable_in_current_image(plVar9), cVar3 != '\0'))
      {
        _register_thread_local_exe_atexit_callback(*plVar9);
      }
      uVar5 = __scrt_get_show_window_mode();
      uVar10 = _get_wide_winmain_command_line();
      uVar7 = UnityMain(&IMAGE_DOS_HEADER_140000000,0,uVar10,uVar5);
      unaff_RBX = (ulonglong)uVar7;
      cVar3 = __scrt_is_managed_app();
      if (cVar3 != '\0') {
        if (!bVar2) {
          _cexit();
        }
        __scrt_uninitialize_crt(1,0);
        return unaff_RBX;
      }
      goto LAB_14000124d;
    }
  }
  __scrt_fastfail(7);
LAB_14000124d:
  FUN_140003520(unaff_RBX & 0xffffffff);
  FUN_1400034d8(unaff_RBX & 0xffffffff);
  pcVar1 = (code *)swi(3);
  uVar11 = (*pcVar1)();
  return uVar11;
}

うーん、ギブアップします。writeup を見てみます。Unity で作られていて、C# を解析してゲームの挙動を変えることで解けるらしいです。なるほど、Ghidra で見えるところは低いレイヤのところで、ちょっと見当違いでした。

dnSpy というツールでデコンパイルできるそうです。解析する対象も pico.exe ではなく、pico_Data/Managed/Assenbly-CSharp.dll は C# としてデコンパイル出来るようです。試しに、ILSpy で、このファイルをデコンパイルすると、見れました。Unity のディレクトリ構成を知る必要があったようです。普通では行けないはずの白のフラグのところに行けるように出来るようです。

調べてみると、ILSpy はデコンパイルは出来るけど、ソースの変更は出来ないようです。実際にやってみましたが、確かに変更は出来なかったです。dnSpy はソースの変更や、デバッグする機能などがあり、かなり高機能なようです。dnSpy を使ってみます。

dnSpy は、以下からダウンロードできます。右側にある Releases のリンクをクリックして、v6.1.8 の dnSpy-net-win64.zip をダウンロードします。

github.com

インストールは不要で、解凍したフォルダにある dnSpy.exe をダブルクリックして起動します。File → Open... をクリックして、pico_Data/Managed/Assenbly-CSharp.dll を開きます。EvolveGames に各クラスが見えるので、PlayerController を開きます。なんとなく、Updateメソッドが、何らかのコールバック関数(イベントハンドラの方が適切?)です。

先頭に重力の計算をしている感じのところがあるので、ここの - this.gravity * Time.deltaTime を削除してみます。そのままでは編集できないので、右クリックして Edit Method (C#)... をクリックすると編集できるようになります。編集が終わったら、Compile を押すと、元の画面に戻って、編集したコートが反映されています。最後に、File → Save All でコードを保存して完了です。

- this.gravity * Time.deltaTime を削除すると、クリアすることは可能なのですが、以下のように、上昇し続けてしまいます。

pico.exe3
pico.exe3

なので、削除するのではなく、- this.gravity * Time.deltaTime / 20 にして、大ジャンプできるようにした方が、フラグに到達できやすいと思います。

picoCTF{WELCOME_TO_UNITY!!} でした。

Ready Gladiator 1(200ポイント)

Medium の問題です。インスタンスを起動すると、1つのファイル(imp.red)がダウンロードできます。

Ready Gladiator 1問題
Ready Gladiator 1問題

Core Wars というものらしいです。コンピュータとの対戦で、アセンブラのような書き方で、自分の動きを決めて、相手の命令を潰せれば勝ち、逆に潰されたら負けです。メモリ内を順番に実行していきます。メモリには上限が設定されていて、それを超えると先頭に戻ります。

相手のプログラムを潰すためのプログラムを書く必要があります。ダウンロードしたファイルは、そのプログラムのサンプルみたいなもので、これを改良していき、コンピュータに勝つことが目的のようです。

しかし、Core Wars には、いくつかバージョンがあるようで、ルール、定義がはっきりしませんし、これを一生懸命頑張って得られるものは無さそうなので、スキップします。

Virtual Machine 1(300ポイント)

Hard の問題です。Virtual Machine 0(歯車の問題)の続きのようです。インスタンスを起動すると、1つのファイル(Virtual-Machine-1.zip)がダウンロードできます。

Virtual Machine 1問題
Virtual Machine 1問題

ダウンロードしたファイルを解凍すると、VirtualMachine1.dae が得られます。Virtual Machine 0 と同様に、Blender で開いてみます。なかなかにハードな感じです。

Blender1
Blender1

サーバに接続してみます。なるほど、固定の入力ではなく、その場で答える必要があるようですね。Python で計算させる必要がありそうです。

$ nc saturn.picoctf.net 52483
If the input to the machine is 12136, what is the output?
Answer>

地道にやっていくしかない、と想定して進めていきます。

最初の赤の車軸の歯車は、24個の凹凸があります。左側の歯車は 8個であり、3倍回転するということになります。その後ろの歯車は 16個で、その左の 2つの歯車は両方とも 8個です。つまり、3×2 で、6倍回転します。棒をつたって、しばらくは同じ数の歯車が接続されているので、変化なしです。

それが棒をつたって、24個に繋がっていて、12個の歯車を回します。よって、12倍です。それに繋がっているのが 16個で、右隣りの 8個の歯車を動かすので、2倍で、計24倍です。次も 16個で 8個を回すので、計48倍です。忘れそうなので、キャプチャにメモしていきました。

Blender2
Blender2

Blender3
Blender3

Blender4
Blender4

ということで、最終的に 9216倍となりました。早速、インスタンスを起動して、9216倍した値を答えましたが、不正解でした。

$ nc saturn.picoctf.net 61658
If the input to the machine is 6941, what is the output?
Answer> 63968256
63968256
That's not correct.
You have to wait 360.0 seconds before trying again.

歯車が左右に分岐してる場合、何となく数えやすそうな方を選んでいましたが、これはうすうす感じてましたが、間違いがありそうです。最後の 2倍、2倍、2倍のところは、右側を進みましたが、左側を進むと 6倍になります。左右で倍数が違うところを吸収するとかしないとおかしくなります。

Blender5
Blender5

以下のように、左右の回転数を吸収する機能を持つ歯車はディファレンシャルギアと言うそうです。左右の歯車の回転数の差が真ん中のギアが回ることで差を吸収します。

Blender6
Blender6

というわけで、見直します。最初の 6倍は合ってますが、次は左を通る必要があります。左を通ると、18倍で、計108倍です。

Blender7
Blender7

次は、20倍なので、計2160倍です。あとは、最後の6倍で、計12960倍です。

Blender8
Blender8

では、インスタンスを起動してやってみます。うーん、ダメです。

$ nc saturn.picoctf.net 61054
If the input to the machine is 23034, what is the output?
Answer> 298520640
298520640
That's not correct.
You have to wait 360.0 seconds before trying again.

合ってると思うんですよねぇ、でも、違うってことは、何か理解できてない部分があるようです。

Blender9
Blender9

ここでギブアップです。writeup を探しましたが、解説がされてるものが、あまりありませんでした。2つのギア比の平均が出力になると解説されているところはあったのですが、今回のディファレンシャルギアは、片方のギアに出力のギアが接続されているので、その場合でも、そうなるのかが、ちょっと分かりませんでした。また、詳しい解説が見つかったら追記しようと思います。

Ready Gladiator 2(400ポイント)

Medium の問題です。Ready Gladiator 1 と同様にスキップします。

おわりに

今回は、picoCTF の picoCTF 2023 のうち、Reverse Engineering の全9問に挑戦しました。今回の問題は今までやってきたリバースエンジニアリングと少し雰囲気の違う問題が多かったです。まだまだだな、と思いました。

最後になりましたが、エンジニアグループのランキングに参加中です。

気楽にポチッとよろしくお願いいたします🙇

今回は以上です!

最後までお読みいただき、ありがとうございました。