LoginSignup
0
0

More than 1 year has passed since last update.

Pwn2Win CTF 2021 Writeup

Posted at

English version is in the latter half of this page.

概要

Pwn2Win CTF 2021 (2021/05/29 01:37 ~ 2021/05/31 01:37 JST) に1人チームで参加した。
結果は405点で、正の点数を取った720チーム中55位だった。

got first blood

first blood を得たようだ。

解けた問題

問題 点数 時刻 (JST)
~Rhiza - founded on the human being 50 2021/05/29 05:29:26
Oldschool Adventures - Apple II 355 2021/05/29 08:02:16

~Rhiza - founded on the human being

問題文として長文が書かれており、最後の行にflagが書かれていた。

この解くだけなら最後だけ見ればいい感じ、
Geeky Fun Fact (The 2013 ACM-ICPC Asia Danang Regional Contest) を思い出すなあ。

CTF-BR{join_Lauras_fight_against_opression_and_discover_the_truth!}

Oldschool Adventures - Apple II

問題文の情報

Applesoft BASIC のプログラムを実行できる、Apple II のエミュレータがある。
プログラムの実行結果としてQRコードを生成すると、
その読み取り結果をLinuxのシェルコマンドとして実行してくれる。

実行させるプログラムは、以下の条件を満たすことを求められる。

  • 長さは 268 chars (サーバのソースコードより、268バイト?) 以内
  • 1行で送信する
  • プログラム中の改行文字は§で表し、高々1個のみ
  • QRコードの生成まで50秒以内

TCPサーバの接続情報と、ローカルテスト用のDockerおよびLXC Containerのファイルがある。
また、DockerおよびLXC Container用の起動コマンドも示されている。

サーバの観察結果

指定のサーバにTera Termで接続すると、

Send the solution for "hashcash -mb 25 xyttzzozyb":

のような文字列が送られてきた。このhashcashとやらでググったところ、Hashcash.orgが見つかった。
ページ左側のメニューから「binaries」をクリックし、実行するプラットフォームと種類を選ぶ
(例えばwindows → console) と、ファイルの一覧の画面になった、
最新の実行ファイルぽいもの(hashcash-1.22-win32-exe.zip)をダウンロードした。
ダウンロードしたファイルを展開すると、その中にhashcash.exeがあったので、
これを用いてサーバーから送られてくる文字列

hashcash -mb 25 xyttzzozyb

をコマンドとして実行すると、数秒後以下のような出力が得られた。

hashcash stamp: 1:25:210530:xyttzzozyb::EKSU6xxV8EuRwams:0000002k/iI

このうち、 1:25:210530:xyttzzozyb::EKSU6xxV8EuRwams:0000002k/iI の部分をコピペして
サーバーに送信することで、次の段階に進むことができた。
次の段階では、

Send your payload here:

という文字列が送られてきた。
この後に条件を満たすApplesoft BASIC のプログラムを送れば実行してくれるようだが、
ちょっともたもたするとタイムアウトになってしまい、素早い操作が求められた。
また、hashcashの出力を貼り付けした後エンターキーを押してしまうと、それがプログラムと認識されてしまうようだった。
エンターキーは押さず、次の出力があるまで待つのがいいようだった。

試しにプログラムとして空文字列(改行のみ)を送ると、しばらくした後で

Not a valid QR!

と出力され、接続が切断された。
また、試しにUTF-8で§§§§§を送信したところ、

Just 1 line break (§) is allowed!

と出力された。このことから、プログラムはUTF-8で送ればいいことがわかった。
ちなみに、§はUTF-8で2バイト(C2 A7)である。

Dockerによるローカルテスト環境の構築

今回はDockerとLXC Containerのデータが用意された。
LXC Containerとやらについての知識は無いが、
Dockerは最近インストールしたので、Dockerで環境を構築することにした。

問題文には、

$ docker-compose up
$ nc localhost 1337

とあった。また、Docker用のファイルがtar.gz形式で与えられた。
他の多くの問題では圧縮されたtarファイルはattachments.tarという扱いやすいファイル名であったかわりに、
@PaxHeaderという謎のデータが含まれ、7-Zipで展開するとファイル名の衝突が何度も起こることがあった。
一方、この問題のファイルは、tarファイルの名前がやたら長かった一方、@PaxHeaderは含まれていなかった。

tarファイルの中身を適当なディレクトリに入れ、
そこでdocker-compose upコマンドを実行すると、エラーになった。

エラーメッセージ
Traceback (most recent call last):
  File "docker\api\client.py", line 214, in _retrieve_server_version
  File "docker\api\daemon.py", line 181, in version
  File "docker\utils\decorators.py", line 46, in inner
  File "docker\api\client.py", line 237, in _get
  File "requests\sessions.py", line 543, in get
  File "requests\sessions.py", line 530, in request
  File "requests\sessions.py", line 643, in send
  File "requests\adapters.py", line 439, in send
  File "urllib3\connectionpool.py", line 670, in urlopen
  File "urllib3\connectionpool.py", line 392, in _make_request
  File "http\client.py", line 1255, in request
  File "http\client.py", line 1301, in _send_request
  File "http\client.py", line 1250, in endheaders
  File "http\client.py", line 1010, in _send_output
  File "http\client.py", line 950, in send
  File "docker\transport\npipeconn.py", line 32, in connect
  File "docker\transport\npipesocket.py", line 23, in wrapped
  File "docker\transport\npipesocket.py", line 72, in connect
  File "docker\transport\npipesocket.py", line 52, in connect
pywintypes.error: (2, 'CreateFile', '指定されたファイルが見つかりません。')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "docker-compose", line 3, in <module>
  File "compose\cli\main.py", line 81, in main
  File "compose\cli\main.py", line 199, in perform_command
  File "compose\cli\command.py", line 60, in project_from_options
  File "compose\cli\command.py", line 152, in get_project
  File "compose\cli\docker_client.py", line 41, in get_client
  File "compose\cli\docker_client.py", line 170, in docker_client
  File "docker\api\client.py", line 197, in __init__
  File "docker\api\client.py", line 221, in _retrieve_server_version
docker.errors.DockerException: Error while fetching server API version: (2, 'CreateFile', '指定されたファイルが見つかりません。')
[11476] Failed to execute script docker-compose

Docker Desktop を起動してからdocker-compose upコマンドを実行することで、エラーは解消した。
このコマンドを実行することで、apachehostchallhostの2台の仮想マシンが作られるようであった。
apachehostの構築は数十秒程度で終わったが、challhostの構築は長時間(15分以上)かかった。
構築が終わってもコマンドの実行は終わらず、そのまま仮想マシンのログらしきものが出力され始めた。

Tera Termでlocalhost:1337に接続し、同様にhashcashの実行結果の一部とApplesoft BASICのプログラムを送ると、
ここにCypressがインストールされていないというようなメッセージが出力され、
プログラムの実行結果は出力されずにTCPが繋がったままになった。

出力されたメッセージ
challhost     | > tira-screenshot@1.0.0 cypress:run /home/stevej/stuff/processing/172.19.0.1
challhost     | > cypress run --spec 'cypress/integration/manda-file/actions.spec.js'
challhost     |
challhost     | No version of Cypress is installed in: /home/stevej/.cache/Cypress/7.3.0/Cypress
challhost     |
challhost     | Please reinstall Cypress by running: cypress install
challhost     |
challhost     | ----------
challhost     |
challhost     | Cypress executable not found at: /home/stevej/.cache/Cypress/7.3.0/Cypress/Cypress
challhost     |
challhost     | ----------
challhost     |
challhost     | Platform: linux (Ubuntu - 20.04)
challhost     | Cypress Version: 7.3.0
challhost     | npm ERR! code ELIFECYCLE
challhost     | npm ERR! errno 1
challhost     | npm ERR! tira-screenshot@1.0.0 cypress:run: `cypress run --spec 'cypress/integration/manda-file/actions.spec.js'`
challhost     | npm ERR! Exit status 1
challhost     | npm ERR!
challhost     | npm ERR! Failed at the tira-screenshot@1.0.0 cypress:run script.
challhost     | npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
challhost     |
challhost     | npm ERR! A complete log of this run can be found in:
challhost     | npm ERR!     /home/stevej/.npm/_logs/2021-05-30T08_49_25_165Z-debug.log
challhost     | Unhandled exception in thread started by <function manipulador at 0x7f2ff1630150>
challhost     | Traceback (most recent call last):
challhost     |   File "server-cypress.py", line 123, in manipulador
challhost     |     cmd = readImg(pathPrincipal, barcodereaderPathCompleto)
challhost     |   File "server-cypress.py", line 27, in readImg
challhost     |     os.chdir(pathFinal)
challhost     | OSError: [Errno 2] No such file or directory: '/home/stevej/stuff/processing/172.19.0.1/cypress/screenshots/manda-file/actions.spec.js/'

Docker Desktop の Containers / Apps からchallhostのCLIを開き、
メッセージの通りにcypress installコマンドを実行したところ、

/bin/sh: 1: cypress: not found

と出てきた。
仮想マシンの構築時のメッセージを参考にnpm install cypressコマンドを実行してみても、
やはりApplesoft BASICのプログラムを送ると同様のエラーが出るし、cypressコマンドも見つからなかった。

npm install cypress 実行時に出力されたメッセージ
> cypress@7.4.0 postinstall /home/stevej/node_modules/cypress
> node index.js --exec install


Cypress 7.4.0 is installed in /home/stevej/.cache/Cypress/7.4.0

npm WARN saveError ENOENT: no such file or directory, open '/home/stevej/package.json'
npm WARN notsup Unsupported engine for cypress@7.4.0: wanted: {"node":">=12.0.0"} (current: {"node":"10.19.0","npm":"6.14.4"})
npm WARN notsup Not compatible with your version of node/npm: cypress@7.4.0
npm WARN enoent ENOENT: no such file or directory, open '/home/stevej/package.json'
npm WARN stevej No description
npm WARN stevej No repository field.
npm WARN stevej No README data
npm WARN stevej No license field.

+ cypress@7.4.0
updated 1 package and audited 352 packages in 4.518s

16 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities



   ╭────────────────────────────────────────────────────────────────╮
   │                                                                │
   │      New major version of npm available! 6.14.4 -> 7.15.0      │
   │   Changelog: https://github.com/npm/cli/releases/tag/v7.15.0   │
   │               Run npm install -g npm to update!                │
   │                                                                │
   ╰────────────────────────────────────────────────────────────────╯

ここでcypress@7.4.0と出てきたこと、およびエラーメッセージには7.3.0とあったことを参考に、
npm install cypress@7.3.0コマンドを実行した。
その結果。ローカルでもサーバーと同様にApplesoft BASICのプログラムの実行結果が得られるようになった。

サーバープログラムの改造

Docker用の配布ファイルを展開した中にあったfiles.tar.gzの中に、
サーバープログラムserver-cypress.pyがあった。
また、これは仮想マシンchallhost内の/home/stevej/stuff/server-cypress.pyに配置されていた。

ローカルでのテストがやりやすくなるよう、これに以下の改造を加えた。

まず、いちいちhashcashの情報を求められるのは邪魔なので、75行目からの以下の部分をコメントアウトした。

        clientsock.send("Send the solution for \"hashcash -mb 25 " + randomstr + "\": ")
        solution = clientsock.recv(BUFF)

        if not check_pow(solution.strip(), randomstr):
            clientsock.send("\nInvalid PoW.\n")
            clientsock.close()
            return

さらに、プログラムの実行結果の画像を取り出せるよう、28行目の

    os.system("mv \"Actions -- .type() - type into a DOM element.png\" qr.png")

の次に

    os.system("cp qr.png /tmp/a.png")

を加えた。
仮想マシンではvivimemacsnanoも使えないようだったので、
仮想マシン外で編集し(このファイルをserver-cypress-mod.pyとする)、

docker cp server-cypress-mod.py (仮想マシンのID):/home/stevej/stuff/server-cypress.py

というコマンドで仮想マシンに入れた。
なお、ここで「仮想マシンのID」はdocker psコマンドで出力されるCONTAINER IDである。

そして、生成された画像ファイルは

docker cp (仮想マシンのID):/tmp/a.png result.png

というコマンドで取り出すことができた。

参考:Dockerでホストとコンテナ間でのファイルコピー - Qiita

QRコードの作成

Psytec QR Code Editorを用い、表示させるQRコードのパターンを作成した後、手動で打ち込んでテキストに変換した。
最初はモジュールサイズを1にして画像出力し、ペイントでグリッド線付きで表示しようとしたが、
なぜか表示がおかしくなってしまった。
(他の画像編集ソフトでは正しく表示されたので、QRコード作成ソフトではなくペイントの問題だろう)
以下の例はlsを表すQRコードである。

ペイントの表示(100%)
(MegaZoomで拡大)
ペイントの表示(400%) 正しいQRコード
ペイントの表示(100%) ペイントの表示(400%) 正しいQRコード

そこで、ペイントを経由せず、作成ソフトに表示されるQRコードをそのまま見て打ち込むことにした。

打ち込み結果の例
#######...#.#.#######
#.....#.#.#.#.#.....#
#.###.#.#.##..#.###.#
#.###.#.....#.#.###.#
#.###.#.#####.#.###.#
#.....#.###...#.....#
#######.#.#.#.#######
........#............
##.#..##..###.###.##.
#####...#..#.#.#.#..#
..#...#..#.#..####..#
...##..#..#.#####..##
.#..#.######.###..##.
........##...##.#.#.#
#######.#####.#.##.#.
#.....#..#....#...###
#.###.#..#..###...###
#.###.#.#.#..###...##
#.###.#...##.###.##.#
#.....#.#..##..#.#...
#######.###..#.#..##.

Applesoft BASIC でのプログラミング

サーバにApplesoft BASICのプログラムを送ることで実行してくれるようだが、
結果が出るまで長時間かかる上、具体的な出力の情報はくれないので、開発には向かない。
「Applesoft BASIC」でググると、以下のインタプリタとリファレンスが見つかった。

このインタプリタで試してみたところ、この環境での数値は浮動小数点数で、32ビットを超える精度があるようだった。
さらに、IchigoJamが持っている

  • 複数の文を:で繋げて1行に入れることができる
  • 多くの空白を省略できる

という特徴をこの環境も持っていることがわかった。
このことを踏まえ、生成したQRコードのデータを数値として埋め込み、描画することにした。

QRコードのデータを数値に変換するプログラム
convert.pl
#!/usr/bin/perl

use strict;
use warnings;

my $first = 1;
while (my $line = <STDIN>) {
    my $res = 0;
    chomp($line);
    my $l = length($line);
    for (my $i = 0; $i < $l; $i++) {
        my $c = substr($line, $l - 1 - $i, 1);
        if ($c eq ".") {
            $res *= 2;
        } elsif ($c eq "#") {
            $res = $res * 2 + 1;
        }
    }
    unless ($first) { print ","; }
    print $res;
    $first = 0;
}
print "\n";

結果、Lo-Res Graphicsを用いた以下のプログラムを送信することで、lsを実行させることができた。
実験の結果、COLORは0を代入すると黒に、15を代入すると白になるようだった。

1GR:FORY=0TO22:READD:HLIN0,39ATY:FORX=4TO25:E=INT(D/2):COLOR=(1-D+E*2)*15:PLOTX,Y:D=E:NEXT:NEXT
2DATA0,2086015,1070401,1527133,1527901,1531741,1066817,2086271,256,908491,1222943,1296964,1701016,847826,1401600,745343,1851969,1864285,1631581,1502301,170305,829311,0

最初の行の背景用の色を初期化していないバグがあるが、認識してくれたのでヨシ。

実行結果として、1337が出力された。
ローカルテスト環境と照らし合わせた結果、これは/home/stevej/stuff/secretディレクトリの中身のようで、
ここにある1337/1338/1339/1337/1338/flag_here_a5605a97da7d0e714adf9ee8a355ca12.txt
内容を出力させればいいようだった。
これは、

cat */*/*/*/*/*

というコマンドで実現できるようだった。これは

`cat */*/*/*/*/*`を表すQRコード

テキスト表現
#######.#####.#######
#.....#.#.#.#.#.....#
#.###.#.#.....#.###.#
#.###.#.####..#.###.#
#.###.#.....#.#.###.#
#.....#.##.#..#.....#
#######.#.#.#.#######
.........####........
##..###..#.#...#.####
.#####.##.#.#..#..##.
##.#..#.#..#..#....#.
.####....###.###...##
###..####.##..##.#.##
........##...#.#####.
#######......##..#.#.
#.....#.##..###..#.##
#.###.#.##.#..#.#..##
#.###.#...#..#.##.###
#.###.#...#..##.##...
#.....#.###.##.#.....
#######.#.#....#....#

というQRコードで表現できる。
画像を表す数値データを差し替えたプログラム

1GR:FORY=0TO22:READD:HLIN0,39ATY:FORX=4TO25:E=INT(D/2):COLOR=(1-D+E*2)*15:PLOTX,Y:D=E:NEXT:NEXT
2DATA0,2088831,1070401,1524061,1527645,1527901,1067841,2086271,7680,2001523,824766,543051,1633822,1756647,1024768,680063,1733441,1657693,1942621,222301,46913,1082751,0

を送ることで、flagを得ることができた。
なお、実際に送ったのは、改行を§に置き換えた

1GR:FORY=0TO22:READD:HLIN0,39ATY:FORX=4TO25:E=INT(D/2):COLOR=(1-D+E*2)*15:PLOTX,Y:D=E:NEXT:NEXT§2DATA0,2088831,1070401,1524061,1527645,1527901,1067841,2086271,7680,2001523,824766,543051,1633822,1756647,1024768,680063,1733441,1657693,1942621,222301,46913,1082751,0

である。

実行結果の画像

ローカルで得られた実行結果の画像

flag

CTF-BR{Appl3's_II_b4s1c_1s_1nt3r3st1ng_a5_w3ll}

おまけ

バグ修正版 (未初期化の色を使わない)

1GR:FORY=4TO26:READD:FORX=4TO26:E=INT(D/2):COLOR=(1-D+E*2)*15:PLOTX,Y:D=E:NEXT:NEXT
2DATA0,4177662,2140802,3048122,3055290,3055802,2135682,4172542,15360,4003046,1649532,1086102,3267644,3513294,2049536,1360126,3466882,3315386,3885242,444602,93826,2165502,0

サーバーに送るため、改行を§に置き換えるとこうなる。

1GR:FORY=4TO26:READD:FORX=4TO26:E=INT(D/2):COLOR=(1-D+E*2)*15:PLOTX,Y:D=E:NEXT:NEXT§2DATA0,4177662,2140802,3048122,3055290,3055802,2135682,4172542,15360,4003046,1649532,1086102,3267644,3513294,2049536,1360126,3466882,3315386,3885242,444602,93826,2165502,0

IchigoJam 1.4版

1CLV:LET[8],8063,127,5441,65,349,93,3933,93,4189,93,2881,65,5503,127,7680,0,2675,122,5566,50,2379,33,11806,99,3559,107,8960,62,8319,41,13121,105,2909,101,9309,118,9309,13,14145,2,1407,66
2FORY=0TO28:DRAW8,Y,37,Y:FORX=0TO20:DRAWX+12,Y,1-[Y*2+X/14]>>(X%14)&1:NEXT:NEXT

IchigoJam web で実行する

IchigoJamで扱う数値は16ビットの整数であり、
QRコードの無圧縮での表現に必要な21ビットには足りないので、1行を2個の数値で表現した。

IchigoJam 1.4版用の変換プログラム
convert-extra.pl
#!/usr/bin/perl

use strict;
use warnings;

my $first = 1;
while (my $line = <STDIN>) {
    my $res = 0;
    chomp($line);
    my $l = length($line);
    for (my $i = 0; $i < $l; $i++) {
        my $c = substr($line, $l - 1 - $i, 1);
        if ($c eq ".") {
            $res *= 2;
        } elsif ($c eq "#") {
            $res = $res * 2 + 1;
        }
    }
    unless ($first) { print ","; }
    printf("%d,%d", $res & ((1 << 14) - 1), $res >> 14);
    $first = 0;
}
print "\n";

商標について

  • 「QRコード」は(株)デンソーウェーブの登録商標です。
  • 「IchigoJam」はjig.jpの登録商標です。

About

I participated in Pwn2Win CTF 2021 (2021/05/29 01:37 ~ 2021/05/31 01:37 JST (UTC+9)) as a solo team.
I got 405 points, ranked 55th among the 720 teams that earned positive score.

got first blood

It seems I got first blood.

Challenges I solved

Challenge Score Solved time (JST : UTC+9)
~Rhiza - founded on the human being 50 2021/05/29 05:29:26
Oldschool Adventures - Apple II 355 2021/05/29 08:02:16

~Rhiza - founded on the human being

A long sentence was given as the challenge description, and the flag was on the last line.

This challenge looked like Geeky Fun Fact (The 2013 ACM-ICPC Asia Danang Regional Contest) because there were much sentence not directly related to the solution and we only had to look at the last part to solve.

CTF-BR{join_Lauras_fight_against_opression_and_discover_the_truth!}

Oldschool Adventures - Apple II

Information from the challenge description

An Apple II emulator that can run Applesoft BASIC programs is provided.
If the program generates a QR Code after being run, it executes what is read from that as a Linux shell command.

The program to run is required to satisfy following conditions:

  • The length is at most 268 chars (looks like 268 bytes, according to the server source code)
  • Sent in a single line
  • Newline characters in the program is written as §, and it can appear at most once
  • Take at most 50 seconds to generate a QR Code

Information to connect to a TCP server, and files for Docker and LXC Container for testing locally were provided.
There also were some commands to start the local-testing environment for Docker and LXC Container.

Observation of the server

Connecting the specified server with Tera Term, it sent a string like

Send the solution for "hashcash -mb 25 xyttzzozyb":

I googled "hashcash"and found Hashcash.org.
I firstly clicked the "binaries" from the menu in the left of the page.
Then I chose the platform to run on and the type of software (windows > console, for example) in the menu.
Finally I downloaded what looked like latest executable (hashcash-1.22-win32-exe.zip) from the list of files.

I found hashcash.exe from files extracted from the downloaded archive.
Using this file, I executed the string sent from server

hashcash -mb 25 xyttzzozyb

as a command. After a few seconds, I got some output like this:

hashcash stamp: 1:25:210530:xyttzzozyb::EKSU6xxV8EuRwams:0000002k/iI

By copy-and-pasting the 1:25:210530:xyttzzozyb::EKSU6xxV8EuRwams:0000002k/iI part of the output to the server, I succeeded to proceed to the next step.

In the next step, the server sent me this string:

Send your payload here:

The server will run the Applesoft BASIC programs sent after this,
but it timed out only after a few seconds and a quick operation was required.
Also, when I pressed Enter after pasting the Hashcash output, the server took the Enter (newline) as the program to run.
Therefore, I should wait for next message from the server without Pressing Enter key after pasting.

Sending only a newline character as a trial, the server gave me this after a while:

Not a valid QR!

and the connection was closed.

Also, when I sent §§§§§ encoded in UTF-8, the server responded:

Just 1 line break (§) is allowed!

This fact suggests that the program should be sent in UTF-8.
The § symbol takes 2 bytes (C2 A7) in UTF-8.

Building a local-testing environment with Docker

In this challenge, data for Docker and LXC Container was provided.
I don't know about LXC Container, but I recently installed Docker, so I decided to use Docker for building the local-testing environment.

The challenge description said:

$ docker-compose up
$ nc localhost 1337

Also files for Docker were given in tar.gz archive.
In most of other challenges in this CTF, the compressed tar files had an easy-to-handle name attachments.tar, but they contained @PaxHeader file and they caused many collisions in file names when extracted via 7-Zip.
On the other hand, the compressed tar file had a very long name, but it contained no @PaxHeader files.

I put the contents of the tar file in some directory and executed docker-compose up command.
It resulted in error.

The error message
Traceback (most recent call last):
  File "docker\api\client.py", line 214, in _retrieve_server_version
  File "docker\api\daemon.py", line 181, in version
  File "docker\utils\decorators.py", line 46, in inner
  File "docker\api\client.py", line 237, in _get
  File "requests\sessions.py", line 543, in get
  File "requests\sessions.py", line 530, in request
  File "requests\sessions.py", line 643, in send
  File "requests\adapters.py", line 439, in send
  File "urllib3\connectionpool.py", line 670, in urlopen
  File "urllib3\connectionpool.py", line 392, in _make_request
  File "http\client.py", line 1255, in request
  File "http\client.py", line 1301, in _send_request
  File "http\client.py", line 1250, in endheaders
  File "http\client.py", line 1010, in _send_output
  File "http\client.py", line 950, in send
  File "docker\transport\npipeconn.py", line 32, in connect
  File "docker\transport\npipesocket.py", line 23, in wrapped
  File "docker\transport\npipesocket.py", line 72, in connect
  File "docker\transport\npipesocket.py", line 52, in connect
pywintypes.error: (2, 'CreateFile', 'The system cannot find the file specified.')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "docker-compose", line 3, in <module>
  File "compose\cli\main.py", line 81, in main
  File "compose\cli\main.py", line 199, in perform_command
  File "compose\cli\command.py", line 60, in project_from_options
  File "compose\cli\command.py", line 152, in get_project
  File "compose\cli\docker_client.py", line 41, in get_client
  File "compose\cli\docker_client.py", line 170, in docker_client
  File "docker\api\client.py", line 197, in __init__
  File "docker\api\client.py", line 221, in _retrieve_server_version
docker.errors.DockerException: Error while fetching server API version: (2, 'CreateFile', 'The system cannot find the file specified.')
[11476] Failed to execute script docker-compose

I resolved this error by executing the docker-compose up command after launching Docker Desktop.

Executing this command, it created two virtual machines: apachehost and challhost.
apachehost took only a few tens of seconds, but challhost took long time (over 15 minuts) to be built.
After completing building them, the command didn't exit and it started to emit some logs about the virtual machines.

After that, I connected to localhost:1337 via Tera Team, and sent data from Hashcash and an Applesoft BASIC program like I did for the remote server.
As a result, the docker-compose up command emitted some message that is suggesting that Cypress is not installed, and the TCP connection was left connected.

The message given
challhost     | > tira-screenshot@1.0.0 cypress:run /home/stevej/stuff/processing/172.19.0.1
challhost     | > cypress run --spec 'cypress/integration/manda-file/actions.spec.js'
challhost     |
challhost     | No version of Cypress is installed in: /home/stevej/.cache/Cypress/7.3.0/Cypress
challhost     |
challhost     | Please reinstall Cypress by running: cypress install
challhost     |
challhost     | ----------
challhost     |
challhost     | Cypress executable not found at: /home/stevej/.cache/Cypress/7.3.0/Cypress/Cypress
challhost     |
challhost     | ----------
challhost     |
challhost     | Platform: linux (Ubuntu - 20.04)
challhost     | Cypress Version: 7.3.0
challhost     | npm ERR! code ELIFECYCLE
challhost     | npm ERR! errno 1
challhost     | npm ERR! tira-screenshot@1.0.0 cypress:run: `cypress run --spec 'cypress/integration/manda-file/actions.spec.js'`
challhost     | npm ERR! Exit status 1
challhost     | npm ERR!
challhost     | npm ERR! Failed at the tira-screenshot@1.0.0 cypress:run script.
challhost     | npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
challhost     |
challhost     | npm ERR! A complete log of this run can be found in:
challhost     | npm ERR!     /home/stevej/.npm/_logs/2021-05-30T08_49_25_165Z-debug.log
challhost     | Unhandled exception in thread started by <function manipulador at 0x7f2ff1630150>
challhost     | Traceback (most recent call last):
challhost     |   File "server-cypress.py", line 123, in manipulador
challhost     |     cmd = readImg(pathPrincipal, barcodereaderPathCompleto)
challhost     |   File "server-cypress.py", line 27, in readImg
challhost     |     os.chdir(pathFinal)
challhost     | OSError: [Errno 2] No such file or directory: '/home/stevej/stuff/processing/172.19.0.1/cypress/screenshots/manda-file/actions.spec.js/'

I opened the CLI for challhost from Containers / Apps on Docker Desktop, and executed cypress install command as the message told.
It resulted in getting a message:

/bin/sh: 1: cypress: not found

After executing npm install cypress command inspired from the massage given while building the virtual machine, the error after sending Applesoft BASIC program persisted and cypress command was not found.

The message given in the execution of npm install cypress command
> cypress@7.4.0 postinstall /home/stevej/node_modules/cypress
> node index.js --exec install


Cypress 7.4.0 is installed in /home/stevej/.cache/Cypress/7.4.0

npm WARN saveError ENOENT: no such file or directory, open '/home/stevej/package.json'
npm WARN notsup Unsupported engine for cypress@7.4.0: wanted: {"node":">=12.0.0"} (current: {"node":"10.19.0","npm":"6.14.4"})
npm WARN notsup Not compatible with your version of node/npm: cypress@7.4.0
npm WARN enoent ENOENT: no such file or directory, open '/home/stevej/package.json'
npm WARN stevej No description
npm WARN stevej No repository field.
npm WARN stevej No README data
npm WARN stevej No license field.

+ cypress@7.4.0
updated 1 package and audited 352 packages in 4.518s

16 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities



   ╭────────────────────────────────────────────────────────────────╮
   │                                                                │
   │      New major version of npm available! 6.14.4 -> 7.15.0      │
   │   Changelog: https://github.com/npm/cli/releases/tag/v7.15.0   │
   │               Run npm install -g npm to update!                │
   │                                                                │
   ╰────────────────────────────────────────────────────────────────╯

Here I saw a phrase cypress@7.4.0. Also the error message contained 7.3.0.
Using this as a hint, I executed npm install cypress@7.3.0 command.
This let me get the results of execution of Applesoft BASIC program like what I get from the remove server from the local environment.

Modification of the server program

I found the server program server-cypress.py in the file files.tar.gz, which was in the files for Docker.
I also found that this is placed at /home/stevej/stuff/server-cypress.py in the virtual machine challhost.

I made following modifications to this to make local-testing easier.

Firstly, I commented out the following part from the 75th line because it was annoying to be asked for information from Hashcash while testing locally.

        clientsock.send("Send the solution for \"hashcash -mb 25 " + randomstr + "\": ")
        solution = clientsock.recv(BUFF)

        if not check_pow(solution.strip(), randomstr):
            clientsock.send("\nInvalid PoW.\n")
            clientsock.close()
            return

Then, to obtain the images produced by running Applesoft BASIC programs, I added

    os.system("cp qr.png /tmp/a.png")

after the 28th line

    os.system("mv \"Actions -- .type() - type into a DOM element.png\" qr.png")

I found that none of vi, vim, emacs, nor nano were available in the virtual machine, so I edited the file outside the virtual machine, named the modified version server-cypress-mod.py, and used the command

docker cp server-cypress-mod.py (the virtual machine ID):/home/stevej/stuff/server-cypress.py

to put the edited file into the virtual machine.
We can obtain "the virtual machine ID" as the CONTAINER ID printed from docker ps command.

Also I could take the image files generated out by the command:

docker cp (the virtual machine ID):/tmp/a.png result.png

Generating QR Code

I used Psytec QR Code Editor (Japanese page and software) to generate QR Code patterns and converted the pattern into texts by manually entering the pattern.
To do this, I saved a QR Code image with the module size set to 1 and viewed that via Microsoft Paint with the grid lines, but the display was broken for some reason.
(This looked like an error in Microsoft Paint, not in the QR Code generator, because some other image-editing software succeeded to display the image correctly.)

The QR Code standing for ls is shown below as an example:

Display in Microsoft Paint (100%)
(enlarged via MegaZoom)
Display in Microsoft Paint (400%) True QR Code
Display in Microsoft Paint (100%) Display in Microsoft Paint (400%) True QR Code

Seeing this, I decided not to use Microsoft Paint and to enter the pattern seeing the QR Code displayed on the generator.

An example of the pattern entered
#######...#.#.#######
#.....#.#.#.#.#.....#
#.###.#.#.##..#.###.#
#.###.#.....#.#.###.#
#.###.#.#####.#.###.#
#.....#.###...#.....#
#######.#.#.#.#######
........#............
##.#..##..###.###.##.
#####...#..#.#.#.#..#
..#...#..#.#..####..#
...##..#..#.#####..##
.#..#.######.###..##.
........##...##.#.#.#
#######.#####.#.##.#.
#.....#..#....#...###
#.###.#..#..###...###
#.###.#.#.#..###...##
#.###.#...##.###.##.#
#.....#.#..##..#.#...
#######.###..#.#..##.

Programming in Applesoft BASIC

The server runs Applesoft BASIC programs after sending them, but it didn't looked useful for development because it takes a while before producing the result and it doesn't give me the actual output of my programs.

I googled "Applesoft BASIC", finding an interpreter and a reference:

After doing some tests with this interpreter, I found that numbers in this environment are floating-point numbers and their precision is more than 32 bits.

Moreover, I found that the environment also has following characteristics that IchigoJam has:

  • We can put multiple statements in one line, concatenating them with :
  • Most white-space characters can be omitted

Based on these findings, I decided to embed the QR Code image generated as numbers and draw the image from them.

The program to convert QR Code patterns into numbers
convert.pl
#!/usr/bin/perl

use strict;
use warnings;

my $first = 1;
while (my $line = <STDIN>) {
    my $res = 0;
    chomp($line);
    my $l = length($line);
    for (my $i = 0; $i < $l; $i++) {
        my $c = substr($line, $l - 1 - $i, 1);
        if ($c eq ".") {
            $res *= 2;
        } elsif ($c eq "#") {
            $res = $res * 2 + 1;
        }
    }
    unless ($first) { print ","; }
    print $res;
    $first = 0;
}
print "\n";

As a result, I succeeded to have the server execute ls command via the following program using Lo-Res Graphics:

1GR:FORY=0TO22:READD:HLIN0,39ATY:FORX=4TO25:E=INT(D/2):COLOR=(1-D+E*2)*15:PLOTX,Y:D=E:NEXT:NEXT
2DATA0,2086015,1070401,1527133,1527901,1531741,1066817,2086271,256,908491,1222943,1296964,1701016,847826,1401600,745343,1851969,1864285,1631581,1502301,170305,829311,0

I found that 0 in COLOR means black and 15 in COLOR means white with some experiments.

This program contains a bug that the color for the background of the first line is not initialized, but fortunately the server kindly recognized the image.

The server gave me 1337 as the result.

Comparing with the local testing environment, this looked like the contents of the /home/stevej/stuff/secret directory and the goal looked like having the server print the contents of
1337/1338/1339/1337/1338/flag_here_a5605a97da7d0e714adf9ee8a355ca12.txt.
This goal could be achieved by a command:

cat */*/*/*/*/*

A QR Code for this command is:

A QR Code for `cat */*/*/*/*/*`

Pattern expressed as text
#######.#####.#######
#.....#.#.#.#.#.....#
#.###.#.#.....#.###.#
#.###.#.####..#.###.#
#.###.#.....#.#.###.#
#.....#.##.#..#.....#
#######.#.#.#.#######
.........####........
##..###..#.#...#.####
.#####.##.#.#..#..##.
##.#..#.#..#..#....#.
.####....###.###...##
###..####.##..##.#.##
........##...#.#####.
#######......##..#.#.
#.....#.##..###..#.##
#.###.#.##.#..#.#..##
#.###.#...#..#.##.###
#.###.#...#..##.##...
#.....#.###.##.#.....
#######.#.#....#....#

I succeeded to get the flag by sending this program with the numerical data replaced:

1GR:FORY=0TO22:READD:HLIN0,39ATY:FORX=4TO25:E=INT(D/2):COLOR=(1-D+E*2)*15:PLOTX,Y:D=E:NEXT:NEXT
2DATA0,2088831,1070401,1524061,1527645,1527901,1067841,2086271,7680,2001523,824766,543051,1633822,1756647,1024768,680063,1733441,1657693,1942621,222301,46913,1082751,0

To clarify, I actually sent this (with the newline character replaced with § symbol):

1GR:FORY=0TO22:READD:HLIN0,39ATY:FORX=4TO25:E=INT(D/2):COLOR=(1-D+E*2)*15:PLOTX,Y:D=E:NEXT:NEXT§2DATA0,2088831,1070401,1524061,1527645,1527901,1067841,2086271,7680,2001523,824766,543051,1633822,1756647,1024768,680063,1733441,1657693,1942621,222301,46913,1082751,0

The outcome of this program

The outcome of this program obtained in the local environment

The flag

CTF-BR{Appl3's_II_b4s1c_1s_1nt3r3st1ng_a5_w3ll}

Extra

Bug-fixed version (don't draw without setting color)

1GR:FORY=4TO26:READD:FORX=4TO26:E=INT(D/2):COLOR=(1-D+E*2)*15:PLOTX,Y:D=E:NEXT:NEXT
2DATA0,4177662,2140802,3048122,3055290,3055802,2135682,4172542,15360,4003046,1649532,1086102,3267644,3513294,2049536,1360126,3466882,3315386,3885242,444602,93826,2165502,0

This is for sending to the server (with the newline character replaced with §):

1GR:FORY=4TO26:READD:FORX=4TO26:E=INT(D/2):COLOR=(1-D+E*2)*15:PLOTX,Y:D=E:NEXT:NEXT§2DATA0,4177662,2140802,3048122,3055290,3055802,2135682,4172542,15360,4003046,1649532,1086102,3267644,3513294,2049536,1360126,3466882,3315386,3885242,444602,93826,2165502,0

IchigoJam 1.4 version

1CLV:LET[8],8063,127,5441,65,349,93,3933,93,4189,93,2881,65,5503,127,7680,0,2675,122,5566,50,2379,33,11806,99,3559,107,8960,62,8319,41,13121,105,2909,101,9309,118,9309,13,14145,2,1407,66
2FORY=0TO28:DRAW8,Y,37,Y:FORX=0TO20:DRAWX+12,Y,1-[Y*2+X/14]>>(X%14)&1:NEXT:NEXT

Execute on IchigoJam web

The numbers on IchigoJam are 16-bit integers and it is less than 21 bits for expressing QR Code rows without compression, so one row is expressed in two integers in this version.

Puttern-to-number conversion program for IchigoJam 1.4 version
convert-extra.pl
#!/usr/bin/perl

use strict;
use warnings;

my $first = 1;
while (my $line = <STDIN>) {
    my $res = 0;
    chomp($line);
    my $l = length($line);
    for (my $i = 0; $i < $l; $i++) {
        my $c = substr($line, $l - 1 - $i, 1);
        if ($c eq ".") {
            $res *= 2;
        } elsif ($c eq "#") {
            $res = $res * 2 + 1;
        }
    }
    unless ($first) { print ","; }
    printf("%d,%d", $res & ((1 << 14) - 1), $res >> 14);
    $first = 0;
}
print "\n";

Trademark notice

  • "QR Code" is a registered trademark of DENSO WAVE INCORPORATED.
  • "IchigoJam" is a registered trademark of jig.jp.
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0