Security Tech Lounge Vol.6 春のCTFセンバツ 供養(Writeup)

Security Tech Lounge Vol.6 春のCTFセンバツに参加。12チーム中1位。

packet (100)

pcapngファイルが与えられる。

$ file packet 
packet: pcap-ng capture file - version 1.0

Wiresharkで開くとICMPパケットが並んでおり、パケット長が3種類の異なるバイト数になっていることがわかる。

f:id:inaz2:20190402172540p:plain

ICMPリクエストのパケット長を取り出し、.01 に置き換えてみる。

$ tshark -r packet.pcap -T fields -e frame.len 'icmp.type==8' >packet.txt

$ head packet.txt 
98
98
98
98
98
98
98
98
98
98

$ cat solve.py 
s = ''
with open('packet.txt') as f:
    for line in f:
        if line.startswith('98'):
            s += '.'
        elif line.startswith('99'):
            s += '0'
        elif line.startswith('153'):
            s += '1'
print(s)

$ python3 solve.py 
..........1000110.1001100.1000001.1000111.1011111.1110000.1101001.1101110.1100111.0110010.1100011...............................

2進数で表現されたASCII文字として解釈すると、フラグが得られた。

$ python3
Python 3.6.7 (default, Oct 22 2018, 11:32:17) 
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> ary = '1000110.1001100.1000001.1000111.1011111.1110000.1101001.1101110.1100111.0110010.1100011'.split('.')
>>> ''.join(chr(int(x,2)) for x in ary)
'FLAG_ping2c'

bin (125)

64 bit ELF実行ファイルが与えられる。

$ file ctf 
ctf: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, stripped

実行すると、localhostUDP 53(DNS)にsendto(2)でデータを繰り返し送信していることがわかる。

$ chmod +x ctf 

$ strace ./ctf
(snip)
sendto(11, "p\2\1\0\0\1\0\0\0\0\0\1'RFIE4RYNBINAUAAAAAG"..., 78, 0, NULL, 0) = 78
recvfrom(11, 0x42001d7010, 16384, 0, NULL, NULL) = -1 ECONNREFUSED (Connection refused)
write(9, "\1\0\0\0\0\0\0\0", 8)         = 8
close(11)                               = 0
futex(0x7fca08000bac, FUTEX_WAKE_PRIVATE, 1) = 1
futex(0x7fca08000bb0, FUTEX_WAKE_PRIVATE, 1) = 1
futex(0x7daa88, FUTEX_WAKE_PRIVATE, 1)  = 1
socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) = 11
fcntl(11, F_GETFL)                      = 0x2 (flags O_RDWR)
fcntl(11, F_SETFL, O_RDWR|O_NONBLOCK)   = 0
connect(11, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
write(9, "\1\0\0\0\0\0\0\0", 8)         = 8
sendto(11, "\2244\1\0\0\1\0\0\0\0\0\1%IAYAAAAEE7P7MEAAAAA"..., 76, 0, NULL, 0) = 76
recvfrom(11, 0x42001ce010, 16384, 0, NULL, NULL) = -1 ECONNREFUSED (Connection refused)
write(9, "\1\0\0\0\0\0\0\0", 8)         = 8
close(11)                               = 0
futex(0x7fca08000ba8, FUTEX_WAKE_PRIVATE, 1) = 1
futex(0x7fca08000bb0, FUTEX_WAKE_PRIVATE, 1) = 1
futex(0x7daa88, FUTEX_WAKE_PRIVATE, 1)  = 1
socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP) = 11
fcntl(11, F_GETFL)                      = 0x2 (flags O_RDWR)
fcntl(11, F_SETFL, O_RDWR|O_NONBLOCK)   = 0
connect(11, {sa_family=AF_INET, sin_port=htons(53), sin_addr=inet_addr("127.0.0.1")}, 16) = 0
write(9, "\1\0\0\0\0\0\0\0", 8)         = 8
sendto(11, "\235b\1\0\0\1\0\0\0\0\0\1'JCAAAAAAS4CILFZQAAA"..., 78, 0, NULL, 0) = 78
recvfrom(11, 0x42001c5010, 16384, 0, NULL, NULL) = -1 ECONNREFUSED (Connection refused)
write(9, "\1\0\0\0\0\0\0\0", 8)         = 8
close(11)                               = 0
(snip)

sendto(2)に絞ってデータを詳しく見ると、*.localhost に対する名前解決を繰り返しているように見える。 そこで、.localhost を除いたドメイン名のみを取り出してみる。

$ strace -e trace=sendto -s1000 ./ctf
Sending data...
sendto(11, {{len=20, type=RTM_GETADDR, flags=NLM_F_REQUEST|NLM_F_DUMP, seq=1554171854, pid=0}, {ifa_family=AF_UNSPEC, ...}}, 20, 0, {sa_family=AF_NETLINK, nl_pid=0, nl_groups=00000000}, 12) = 20
sendto(11, "\251\277\1\0\0\1\0\0\0\0\0\1'RFIE4RYNBINAUAAAAAGUSSCEKIAAAAM7AAAACOA\tlocalhost\0\0\20\0\1\0\0)\20\0\0\0\0\0\0\0", 78, 0, NULL, 0) = 78
sendto(11, "\5@\1\0\0\1\0\0\0\0\0\1%IAYAAAAEE7P7MEAAAAACHGQSJKQEAQCAIPQEG\tlocalhost\0\0\20\0\1\0\0)\20\0\0\0\0\0\0\0", 76, 0, NULL, 0) = 76
sendto(11, "w,\1\0\0\1\0\0\0\0\0\1'JCAAAAAAS4CILFZQAAAPKQAAAD2UAFPLT46BAAA\tlocalhost\0\0\20\0\1\0\0)\20\0\0\0\0\0\0\0", 78, 0, NULL, 0) = 78
sendto(11, "\252\352\1\0\0\1\0\0\0\0\0\1%AAGLUIVMHIU3PMZ2HOYLSMUAHO53XFZUW423T\tlocalhost\0\0\20\0\1\0\0)\20\0\0\0\0\0\0\0", 76, 0, NULL, 0) = 76
(snip)

$ strace -e trace=sendto -s1000 ./ctf |& grep -o -P '[\w=]+(?=\\tlocalhost)' | tee ctf.txt
RFIE4RYNBINAUAAAAAGUSSCEKIAAAAM7AAAACOA
IAYAAAAEE7P7MEAAAAACHGQSJKQEAQCAIPQEG
JCAAAAAAS4CILFZQAAAPKQAAAD2UAFPLT46BAAA
AAGLUIVMHIU3PMZ2HOYLSMUAHO53XFZUW423T
(snip)
BDXQAEAFQR7YAAAKYI34AAANMEJ6AAAOWCA7ACA
HLBAPADADVQQHABQB3YIDACYI54ABABMEP6AA
ACWCG7AAADLBCPQAADVQQHYAQB276D5FZLJGUEB
31MPHRQAAAAABEUKTSEVZBGBAQ=

コンテスト中はここまでしかわからず解けなかった。

取り出したデータをよく見ると、英大文字、数字、= のみであることがわかる。 そこで、Base32 としてデコードしてみる。 最後の行のみBase32で使用されない 1 が含まれているため、最後の行を除きパディング文字 = を調整した。 その結果データの先頭にPNGファイルのシグネチャが見えたため、これをPNGファイルとして保存する。

import base64

with open('ctf.txt') as f:
    lines = f.read().splitlines()
    data = ''.join(lines[:-1])

decoded = base64.b32decode(data + '=')
print(decoded)

with open('ctf.png', 'wb') as f:
    f.write(decoded)
$ python3 solve.py 
b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x01\x9f\x00\x00\x018\x08\x06\x00\x00\x00\x84\xfb\xfe ...(snip)... \x8e\xf0\x01\x00XG\xf8\x00\x00\xac#|\x00\x00\xd6\x11>\x00\x00\xeb\x08\x1f\x00\x80u\xff\x0f\xa5\xca\xd2j\x10'

PNGファイルの末尾が欠けていることになるが、Firefoxブラウザで開くと画像が確認でき、フラグが得られた。

f:id:inaz2:20190403092941p:plain

最後の行の 31\31 を誤って抜き出してしまった模様。

reg (150)

UTF-16LEのテキストファイルが与えられる。

$ file reg 
reg: Little-endian UTF-16 Unicode text, with very long lines, with CRLF, CR line terminators

内容を確認すると、Base64文字列が入ったレジストリ値二つとPowerShellスクリプトが入ったレジストリ値一つが書かれている。

$ cat reg 
??Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Mandiant\CTF]
"Anchovy"="QhdMGkZMUkxCRE9HT0xPXEIXTklMEVJD ...(snip)... EkMdRRJDHTdAThtMT05ETE9ORkxPRw=="
"Herring"="bVNbi9s8EH2Of8UQDGuTKvShlI+Y72F3 ...(snip)... NnhBrNvRtg3rc+u32LMyPLcVQ/NeAA=="
"Mackerel"="$raw=Get-ItemProperty('hklm:\\Software\\Mandiant\\CTF')|Select-Object -ExpandProperty Herring;sal a New-Object;iex(a IO.StreamReader((a IO.Compression.DeflateStream([IO.MemoryStream][Convert]::FromBase64String($raw),[IO.Compression.CompressionMode]::Decompress)),[Text.Encoding]::ASCII)).ReadToEnd()"

Mackerelのコードに従い、HerringのデータをBase64デコードしてDeflate展開すると次のようになる。

$ python3
Python 3.6.7 (default, Oct 22 2018, 11:32:17) 
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import base64
>>> import zlib
>>> herring = 'bVNbi9s8EH2Of8UQDGuTKvShlI+Y72F3 ...(snip)... NnhBrNvRtg3rc+u32LMyPLcVQ/NeAA=='
>>> zlib.decompress(base64.b64decode(herring), -15)
b'function Invoke-AES {\n\t\tparam($e_str, $method)\n\t\t$enc = new-object -TypeName System.Text.UTF8Encoding\n\t\t$super_long_key = $enc.GetBytes("flog")\n\n\t\tif ($method -eq "decrypt"){\n\t\t\t$e_str = $enc.GetString([System.Convert]::FromBase64String($e_str))\n    }\n\n\t\t$byteString = $enc.GetBytes($e_str)\n\t\t$AESdData = $(for ($i = 0; $i -lt $byteString.length; ) {\n\t\t\tfor ($j = 0; $j -lt $super_long_key.length; $j++) {\n\t\t\t\t$byteString[$i] -bxor $super_long_key[$j]\n\t\t\t\t$i++\n\t\t\t\tif ($i -ge $byteString.Length) {\n\t\t\t\t\t$j = $super_long_key.length\n\t\t\t\t}\n\t\t\t}\n\t\t})\n\n\t\tif ($method -eq "encrypt") {\n\t\t\t$AESdData = [System.Convert]::ToBase64String($AESdData)\n\t\t} else {\n\t\t\t$AESdData = $enc.GetString($AESdData)\n\t\t}\n\n\t\treturn $AESdData\n}\n$RegPath = \'hklm:\\Software\\Mandiant\\CTF\';\n$raw = Get-ItemProperty $RegPath | Select-Object -ExpandProperty Anchovy;\n$raw_obj = Invoke-AES -e_str $raw -method decrypt;\niex $raw_obj;'
>>> print(_.decode('utf-8'))
function Invoke-AES {
        param($e_str, $method)
        $enc = new-object -TypeName System.Text.UTF8Encoding
        $super_long_key = $enc.GetBytes("flog")

        if ($method -eq "decrypt"){
            $e_str = $enc.GetString([System.Convert]::FromBase64String($e_str))
    }

        $byteString = $enc.GetBytes($e_str)
        $AESdData = $(for ($i = 0; $i -lt $byteString.length; ) {
            for ($j = 0; $j -lt $super_long_key.length; $j++) {
                $byteString[$i] -bxor $super_long_key[$j]
                $i++
                if ($i -ge $byteString.Length) {
                    $j = $super_long_key.length
                }
            }
        })

        if ($method -eq "encrypt") {
            $AESdData = [System.Convert]::ToBase64String($AESdData)
        } else {
            $AESdData = $enc.GetString($AESdData)
        }

        return $AESdData
}
$RegPath = 'hklm:\Software\Mandiant\CTF';
$raw = Get-ItemProperty $RegPath | Select-Object -ExpandProperty Anchovy;
$raw_obj = Invoke-AES -e_str $raw -method decrypt;
iex $raw_obj;

PowerShellを使い、Anchovyのデータから作られる $raw_obj の内容を調べてみる。

Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\Users\user> function Invoke-AES {
>>         param($e_str, $method)
>>         $enc = new-object -TypeName System.Text.UTF8Encoding
>>         $super_long_key = $enc.GetBytes("flog")
>>
>>         if ($method -eq "decrypt"){
>>             $e_str = $enc.GetString([System.Convert]::FromBase64String($e_str))
>>     }
>>
>>         $byteString = $enc.GetBytes($e_str)
>>         $AESdData = $(for ($i = 0; $i -lt $byteString.length; ) {
>>             for ($j = 0; $j -lt $super_long_key.length; $j++) {
>>                 $byteString[$i] -bxor $super_long_key[$j]
>>                 $i++
>>                 if ($i -ge $byteString.Length) {
>>                     $j = $super_long_key.length
>>                 }
>>             }
>>         })
>>
>>         if ($method -eq "encrypt") {
>>             $AESdData = [System.Convert]::ToBase64String($AESdData)
>>         } else {
>>             $AESdData = $enc.GetString($AESdData)
>>         }
>>
>>         return $AESdData
>> }
>>
PS C:\Users\user> $raw = "QhdMGkZMUkxCRE9HT0xPXEIXTklMEVJD ...(snip)... EkMdRRJDHTdAThtMT05ETE9ORkxPRw=="
PS C:\Users\user> $raw_obj = Invoke-AES -e_str $raw -method decrypt;
PS C:\Users\user> $raw_obj
${#}  =+$(  )  ;${!.*}=${#};${[/)}=  ++  ${#}  ;${).+}=  ++${#}  ;  ${=-$}  =++${#};${)}=++${#}  ;  ${+}=  ++  ${#}  ; ${``}=  ++  ${#};  ${/}  =++${#};${/[(}=  ++  ${#};${+-.}  =  ++${#}  ;  ${;%$}  =  "["  +"$(@{}  )"[  ${/}]+"$(@{})"[  "${[/)}"+"${+-.}"]  +  "$(  @{  }  )"[  "${).+}"  +"${!.*}"]  +"$?  "[  ${[/)}  ]  +  "]"  ;${#}="".("$(  @{}  )  "[ "${[/)}"  +"${)}"]+"$(  @{}  )  "["${[/)}"  +  "${``}"  ]+  "$(@{  }  )  "[${!.*}]+"$(  @{})  "[  ${)}  ]  +  "$?"[${[/)}  ]+  "$(@{  }  )"[  ${=-$}]  );  ${#}  ="$(@{  }  )"["${[/)}"  +"${)}"  ]  +"$(@{  })"[  ${)}]  +"${#}"["${).+}"+"${/}"  ]  ;.  ${#}  (  "  ${#}(${;%$}${``}${+}+  ${;%$}${[/)}${!.*}${!.*}  +  ${;%$}${[/)}${!.*}${!.*}+${;%$}${)}${+}  +${;%$}${/[(}${)}+  ${;%$}${[/)}${).+}${[/)}  +  ${;%$}${[/)}${[/)}${).+}+${;%$}${[/)}${!.*}${[/)}  +  ${;%$}${=-$}${).+}+  ${;%$}${)}${+}  +${;%$}${``}${+}+${;%$}${[/)}${[/)}${+}  +  ${;%$}${[/)}${[/)}${+}  +  ${;%$}${[/)}${!.*}${[/)}  +${;%$}${[/)}${!.*}${+-.}+${;%$}${+-.}${/[(}+  ${;%$}${[/)}${!.*}${/[(}  +  ${;%$}${[/)}${).+}${[/)}+${;%$}${/}${/[(}  + ${;%$}${+-.}${/}+  ${;%$}${[/)}${!.*}${+-.}+  ${;%$}${[/)}${!.*}${[/)}+${;%$}${=-$}${).+}+  ${;%$}${/[(}${=-$}  +  ${;%$}${[/)}${).+}${[/)}  +${;%$}${[/)}${[/)}${+}+  ${;%$}${[/)}${[/)}${``}  +${;%$}${[/)}${!.*}${[/)}  +  ${;%$}${[/)}${!.*}${+-.}+${;%$}${)}${``}+${;%$}${[/)}${[/)}${+}+${;%$}${[/)}${[/)}${).+}  +  ${;%$}${[/)}${!.*}${[/)}  +  ${;%$}${[/)}${!.*}${[/)}+${;%$}${+-.}${+-.}  +  ${;%$}${[/)}${!.*}${)}+  ${;%$}${[/)}${=-$}+  ${;%$}${[/)}${!.*}+  ${;%$}${=-$}${``}+${;%$}${[/)}${[/)}${+}  +  ${;%$}${[/)}${[/)}${).+}+  ${;%$}${[/)}${!.*}${[/)}+${;%$}${+-.}${/}  +${;%$}${[/)}${!.*}${/}+${;%$}${=-$}${).+}  +  ${;%$}${``}${[/)}  +  ${;%$}${=-$}${).+}+${;%$}${/}${/[(}  +  ${;%$}${[/)}${!.*}${[/)}+${;%$}${[/)}${[/)}${+-.}+  ${;%$}${)}${+}+  ${;%$}${/}${+-.}  +  ${;%$}${+-.}${/[(}  +${;%$}${[/)}${!.*}${``}+${;%$}${[/)}${!.*}${[/)}  +${;%$}${+-.}${+-.}  +${;%$}${[/)}${[/)}${``}+  ${;%$}${=-$}${).+}+  ${;%$}${/[(}${=-$}+${;%$}${[/)}${).+}${[/)}+${;%$}${[/)}${[/)}${+}+${;%$}${[/)}${[/)}${``}+  ${;%$}${[/)}${!.*}${[/)}  +  ${;%$}${[/)}${!.*}${+-.}+  ${;%$}${)}${``}+${;%$}${/[(}${=-$}  +${;%$}${[/)}${[/)}${).+}  +  ${;%$}${[/)}${!.*}${[/)}+  ${;%$}${[/)}${!.*}${[/)}  +${;%$}${+-.}${+-.}+${;%$}${[/)}${!.*}${)}  +${;%$}${)}${``}+  ${;%$}${/[(}${=-$}  +${;%$}${[/)}${).+}${[/)}+  ${;%$}${[/)}${[/)}${!.*}  +  ${;%$}${[/)}${[/)}${``}+  ${;%$}${[/)}${!.*}${)}+${;%$}${[/)}${!.*}${[/)}  +  ${;%$}${[/)}${[/)}${+}  +${;%$}${[/)}${!.*}${+}  +${;%$}${[/)}${[/)}${+}+  ${;%$}${)}${``}  +${;%$}${/[(}${=-$}+  ${;%$}${[/)}${[/)}${).+}  +  ${;%$}${[/)}${!.*}${[/)}  +  ${;%$}${[/)}${!.*}${[/)}  +${;%$}${+-.}${+-.}  +${;%$}${[/)}${!.*}${)}  +${;%$}${/[(}${=-$}+${;%$}${[/)}${).+}${[/)}  +  ${;%$}${[/)}${[/)}${!.*}+  ${;%$}${[/)}${[/)}${``}+  ${;%$}${[/)}${!.*}${)}  +  ${;%$}${[/)}${!.*}${[/)}  +  ${;%$}${[/)}${[/)}${+}  +  ${;%$}${[/)}${!.*}${+}+${;%$}${[/)}${).+}${).+}+${;%$}${[/)}${!.*}${[/)}+${;%$}${[/)}${[/)}${)}  +${;%$}${[/)}${=-$}+  ${;%$}${[/)}${!.*}+${;%$}${=-$}${``}  +${;%$}${[/)}${[/)}${+}+${;%$}${[/)}${[/)}${).+}+  ${;%$}${[/)}${!.*}${[/)}+${;%$}${+-.}${/}  +${;%$}${[/)}${!.*}${/}  +${;%$}${)}${``}+  ${;%$}${/[(}${=-$}+  ${;%$}${[/)}${[/)}${).+}+${;%$}${[/)}${!.*}${[/)}+  ${;%$}${+-.}${/}+  ${;%$}${[/)}${!.*}${/}  +  ${;%$}${)}${!.*}+${;%$}${=-$}${)}+  ${;%$}${/}${``}+  ${;%$}${[/)}${!.*}${+}  +  ${;%$}${[/)}${[/)}${+}+  ${;%$}${[/)}${[/)}${``}  +${;%$}${[/)}${!.*}${[/)}+  ${;%$}${[/)}${[/)}${!.*}  +  ${;%$}${=-$}${=-$}+  ${;%$}${=-$}${).+}+${;%$}${/}${``}  +  ${;%$}${[/)}${!.*}${+}  +  ${;%$}${[/)}${[/)}${+}  +  ${;%$}${[/)}${[/)}${``}+${;%$}${[/)}${!.*}${[/)}  +  ${;%$}${[/)}${[/)}${!.*}  +${;%$}${=-$}${=-$}+${;%$}${=-$}${).+}  +  ${;%$}${/}${!.*}+  ${;%$}${/}${``}  +${;%$}${``}${+}+  ${;%$}${/}${[/)}+  ${;%$}${=-$}${).+}  +  ${;%$}${[/)}${!.*}${+}+  ${;%$}${[/)}${[/)}${+}+  ${;%$}${=-$}${).+}  +  ${;%$}${/}${!.*}  +${;%$}${/}${``}+  ${;%$}${``}${+}  +${;%$}${/}${[/)}+  ${;%$}${+-.}${+}+  ${;%$}${+-.}${/}+  ${;%$}${[/)}${[/)}${!.*}+${;%$}${[/)}${!.*}${=-$}+  ${;%$}${[/)}${!.*}${/[(}+${;%$}${[/)}${!.*}${[/)}  +${;%$}${[/)}${[/)}${)}+${;%$}${[/)}${!.*}${).+}  +  ${;%$}${[/)}${!.*}${+}  +  ${;%$}${[/)}${[/)}${+}+  ${;%$}${[/)}${!.*}${)}  +${;%$}${=-$}${)}  +${;%$}${=-$}${).+}  +  ${;%$}${)}${[/)}  )"  )

. ${#}スクリプトを実行する iex であると仮定し、これを取り除いたコードを実行してみる。

Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\Users\user> ${#}  =+$(  )  ;${!.*}=${#};${[/)}=  ++  ${#}  ;${).+}=  ++${#}  ;  ${=-$}  =++${#};${)}=++${#}  ;  ${+}=  ++  ${#}  ; ${``}=  ++  ${#};  ${/}  =++${#};${/[(}=  ++  ${#};${+-.}  =  ++${#}  ;  ${;%$}  =  "["  +"$(@{}  )"[${/}]+"$(@{})"[  "${[/)}"+"${+-.}"]  +  "$(  @{  }  )"[  "${).+}"  +"${!.*}"]  +"$?  "[  ${[/)}  ]  +  "]"  ;${#}="".("$(  @{}  )  "[ "${[/)}"  +"${)}"]+"$(  @{}  )  "["${[/)}"  +  "${``}"  ]+  "$(@{  }  )  "[${!.*}]+"$(  @{})  "[  ${)}  ] +  "$?"[${[/)}  ]+  "$(@{  }  )"[  ${=-$}]  );  ${#}  ="$(@{  }  )"["${[/)}"  +"${)}"  ]  +"$(@{  })"[  ${)}]  +"${#}"["${).+}"+"${/}"  ]  ;  (  "  ${#}(${;%$}${``}${+}+  ${;%$}${[/)}${!.*}${!.*}  +  ${;%$}${[/)}${!.*}${!.*}+${;%$}${)}${+}  +${;%$}${/[(}${)}+  ${;%$}${[/)}${).+}${[/)}  +  ${;%$}${[/)}${[/)}${).+}+${;%$}${[/)}${!.*}${[/)}  +  ${;%$}${=-$}${).+}+  ${;%$}${)}${+}  +${;%$}${``}${+}+${;%$}${[/)}${[/)}${+}  +  ${;%$}${[/)}${[/)}${+}  +  ${;%$}${[/)}${!.*}${[/)}  +${;%$}${[/)}${!.*}${+-.}+${;%$}${+-.}${/[(}+  ${;%$}${[/)}${!.*}${/[(}  +  ${;%$}${[/)}${).+}${[/)}+${;%$}${/}${/[(}  +${;%$}${+-.}${/}+  ${;%$}${[/)}${!.*}${+-.}+  ${;%$}${[/)}${!.*}${[/)}+${;%$}${=-$}${).+}+  ${;%$}${/[(}${=-$}  +  ${;%$}${[/)}${).+}${[/)}  +${;%$}${[/)}${[/)}${+}+  ${;%$}${[/)}${[/)}${``}  +${;%$}${[/)}${!.*}${[/)}  +  ${;%$}${[/)}${!.*}${+-.}+${;%$}${)}${``}+${;%$}${[/)}${[/)}${+}+${;%$}${[/)}${[/)}${).+}  +  ${;%$}${[/)}${!.*}${[/)}  +  ${;%$}${[/)}${!.*}${[/)}+${;%$}${+-.}${+-.}  +  ${;%$}${[/)}${!.*}${)}+  ${;%$}${[/)}${=-$}+  ${;%$}${[/)}${!.*}+  ${;%$}${=-$}${``}+${;%$}${[/)}${[/)}${+}  +  ${;%$}${[/)}${[/)}${).+}+  ${;%$}${[/)}${!.*}${[/)}+${;%$}${+-.}${/}  +${;%$}${[/)}${!.*}${/}+${;%$}${=-$}${).+}  +  ${;%$}${``}${[/)}  +  ${;%$}${=-$}${).+}+${;%$}${/}${/[(}  +  ${;%$}${[/)}${!.*}${[/)}+${;%$}${[/)}${[/)}${+-.}+  ${;%$}${)}${+}+  ${;%$}${/}${+-.}  +  ${;%$}${+-.}${/[(}  +${;%$}${[/)}${!.*}${``}+${;%$}${[/)}${!.*}${[/)}  +${;%$}${+-.}${+-.}  +${;%$}${[/)}${[/)}${``}+  ${;%$}${=-$}${).+}+  ${;%$}${/[(}${=-$}+${;%$}${[/)}${).+}${[/)}+${;%$}${[/)}${[/)}${+}+${;%$}${[/)}${[/)}${``}+  ${;%$}${[/)}${!.*}${[/)}  +  ${;%$}${[/)}${!.*}${+-.}+  ${;%$}${)}${``}+${;%$}${/[(}${=-$}  +${;%$}${[/)}${[/)}${).+}  +  ${;%$}${[/)}${!.*}${[/)}+  ${;%$}${[/)}${!.*}${[/)}  +${;%$}${+-.}${+-.}+${;%$}${[/)}${!.*}${)}  +${;%$}${)}${``}+  ${;%$}${/[(}${=-$}  +${;%$}${[/)}${).+}${[/)}+  ${;%$}${[/)}${[/)}${!.*}  + ${;%$}${[/)}${[/)}${``}+  ${;%$}${[/)}${!.*}${)}+${;%$}${[/)}${!.*}${[/)}  +  ${;%$}${[/)}${[/)}${+}  +${;%$}${[/)}${!.*}${+}  +${;%$}${[/)}${[/)}${+}+  ${;%$}${)}${``}  +${;%$}${/[(}${=-$}+  ${;%$}${[/)}${[/)}${).+}  +  ${;%$}${[/)}${!.*}${[/)}  +  ${;%$}${[/)}${!.*}${[/)}  +${;%$}${+-.}${+-.}  +${;%$}${[/)}${!.*}${)}  +${;%$}${/[(}${=-$}+${;%$}${[/)}${).+}${[/)}  +  ${;%$}${[/)}${[/)}${!.*}+  ${;%$}${[/)}${[/)}${``}+  ${;%$}${[/)}${!.*}${)}  +  ${;%$}${[/)}${!.*}${[/)}  + ${;%$}${[/)}${[/)}${+}  +  ${;%$}${[/)}${!.*}${+}+${;%$}${[/)}${).+}${).+}+${;%$}${[/)}${!.*}${[/)}+${;%$}${[/)}${[/)}${)}  +${;%$}${[/)}${=-$}+  ${;%$}${[/)}${!.*}+${;%$}${=-$}${``}  +${;%$}${[/)}${[/)}${+}+${;%$}${[/)}${[/)}${).+}+  ${;%$}${[/)}${!.*}${[/)}+${;%$}${+-.}${/}  +${;%$}${[/)}${!.*}${/}  +${;%$}${)}${``}+  ${;%$}${/[(}${=-$}+  ${;%$}${[/)}${[/)}${).+}+${;%$}${[/)}${!.*}${[/)}+  ${;%$}${+-.}${/}+  ${;%$}${[/)}${!.*}${/}  +  ${;%$}${)}${!.*}+${;%$}${=-$}${)}+  ${;%$}${/}${``}+  ${;%$}${[/)}${!.*}${+}  +  ${;%$}${[/)}${[/)}${+}+  ${;%$}${[/)}${[/)}${``}  +${;%$}${[/)}${!.*}${[/)}+ ${;%$}${[/)}${[/)}${!.*}  +  ${;%$}${=-$}${=-$}+  ${;%$}${=-$}${).+}+${;%$}${/}${``}  +  ${;%$}${[/)}${!.*}${+}  +  ${;%$}${[/)}${[/)}${+}  +  ${;%$}${[/)}${[/)}${``}+${;%$}${[/)}${!.*}${[/)}  +  ${;%$}${[/)}${[/)}${!.*}  +${;%$}${=-$}${=-$}+${;%$}${=-$}${).+}  +  ${;%$}${/}${!.*}+  ${;%$}${/}${``}  +${;%$}${``}${+}+  ${;%$}${/}${[/)}+  ${;%$}${=-$}${).+}+  ${;%$}${[/)}${!.*}${+}+  ${;%$}${[/)}${[/)}${+}+  ${;%$}${=-$}${).+}  +  ${;%$}${/}${!.*}  +${;%$}${/}${``}+  ${;%$}${``}${+}  +${;%$}${/}${[/)}+  ${;%$}${+-.}${+}+  ${;%$}${+-.}${/}+  ${;%$}${[/)}${[/)}${!.*}+${;%$}${[/)}${!.*}${=-$}+${;%$}${[/)}${!.*}${/[(}+${;%$}${[/)}${!.*}${[/)}  +${;%$}${[/)}${[/)}${)}+${;%$}${[/)}${!.*}${).+}  +  ${;%$}${[/)}${!.*}${+}  +  ${;%$}${[/)}${[/)}${+}+  ${;%$}${[/)}${!.*}${)}  +${;%$}${=-$}${)}  +${;%$}${=-$}${).+}  +  ${;%$}${)}${[/)} )"  )
  iex([CHar]65+  [CHar]100  +  [CHar]100+[CHar]45  +[CHar]84+  [CHar]121  +  [CHar]112+[CHar]101  +  [CHar]32+  [CHar]45  +[CHar]65+[CHar]115  +  [CHar]115  +  [CHar]101  +[CHar]109+[CHar]98+  [CHar]108  +  [CHar]121+[CHar]78  + [CHar]97+  [CHar]109+  [CHar]101+[CHar]32+  [CHar]83  +  [CHar]121  +[CHar]115+  [CHar]116  +[CHar]101  +  [CHar]109+[CHar]46+[CHar]115+[CHar]112  +  [CHar]101  +  [CHar]101+[CHar]99  +  [CHar]104+  [CHar]13+  [CHar]10+  [CHar]36+[CHar]115  +  [CHar]112+  [CHar]101+[CHar]97  +[CHar]107+[CHar]32  +  [CHar]61  +  [CHar]32+[CHar]78  +  [CHar]101+[CHar]119+  [CHar]45+  [CHar]79  +  [CHar]98  +[CHar]106+[CHar]101  +[CHar]99  +[CHar]116+  [CHar]32+  [CHar]83+[CHar]121+[CHar]115+[CHar]116+  [CHar]101  +  [CHar]109+  [CHar]46+[CHar]83  +[CHar]112  +  [CHar]101+  [CHar]101  +[CHar]99+[CHar]104  +[CHar]46+ [CHar]83  +[CHar]121+  [CHar]110  +  [CHar]116+  [CHar]104+[CHar]101  +  [CHar]115  +[CHar]105  +[CHar]115+  [CHar]46 +[CHar]83+  [CHar]112  +  [CHar]101  +  [CHar]101  +[CHar]99  +[CHar]104  +[CHar]83+[CHar]121  +  [CHar]110+  [CHar]116+  [CHar]104  +  [CHar]101  +  [CHar]115  +  [CHar]105+[CHar]122+[CHar]101+[CHar]114  +[CHar]13+  [CHar]10+[CHar]36  +[CHar]115+[CHar]112+  [CHar]101+[CHar]97  +[CHar]107  +[CHar]46+  [CHar]83+  [CHar]112+[CHar]101+  [CHar]97+  [CHar]107  +  [CHar]40+[CHar]34+  [CHar]76+  [CHar]105  +  [CHar]115+  [CHar]116  +[CHar]101+  [CHar]110  +  [CHar]33+  [CHar]32+[CHar]76  +  [CHar]105  +  [CHar]115  +  [CHar]116+[CHar]101  +  [CHar]110  +[CHar]33+[CHar]32  +  [CHar]70+  [CHar]76  +[CHar]65+  [CHar]71+  [CHar]32  +  [CHar]105+  [CHar]115+  [CHar]32  +  [CHar]70  +[CHar]76+  [CHar]65  +[CHar]71+[CHar]95+  [CHar]97+  [CHar]110+[CHar]103+  [CHar]108+[CHar]101  +[CHar]114+[CHar]102  +  [CHar]105  +  [CHar]115+  [CHar]104  +[CHar]34  +[CHar]32  +  [CHar]41  )

iex で実行しようとしているコードの内容を調べると、フラグが得られた。

Windows PowerShell
Copyright (C) 2009 Microsoft Corporation. All rights reserved.

PS C:\Users\user> ([CHar]65+  [CHar]100  +  [CHar]100+[CHar]45  +[CHar]84+  [CHar]121  +  [CHar]112+[CHar]101  +  [CHar]32+  [CHar]45  +[CHar]65+[CHar]115  +  [CHar]115  +  [CHar]101  +[CHar]109+[CHar]98+  [CHar]108  +  [CHar]121+[CHar]78  + [CHar]97+  [CHar]109+  [CHar]101+[CHar]32+  [CHar]83  +  [CHar]121  +[CHar]115+  [CHar]116  +[CHar]101  +  [CHar]109+[CHar]46+[CHar]115+[CHar]112  +  [CHar]101  +  [CHar]101+[CHar]99  +  [CHar]104+  [CHar]13+  [CHar]10+  [CHar]36+[CHar]115  +  [CHar]112+  [CHar]101+[CHar]97  +[CHar]107+[CHar]32  +  [CHar]61  +  [CHar]32+[CHar]78  +  [CHar]101+[CHar]119+  [CHar]45+  [CHar]79  +  [CHar]98  +[CHar]106+[CHar]101  +[CHar]99  +[CHar]116+  [CHar]32+  [CHar]83+[CHar]121+[CHar]115+[CHar]116+  [CHar]101  +  [CHar]109+  [CHar]46+[CHar]83  +[CHar]112  +  [CHar]101+  [CHar]101  +[CHar]99+[CHar]104  +[CHar]46+ [CHar]83  +[CHar]121+  [CHar]110  +  [CHar]116+  [CHar]104+[CHar]101  +  [CHar]115  +[CHar]105  +[CHar]115+  [CHar]46 +[CHar]83+  [CHar]112  +  [CHar]101  +  [CHar]101  +[CHar]99  +[CHar]104  +[CHar]83+[CHar]121  +  [CHar]110+  [CHar]116+  [CHar]104  +  [CHar]101  +  [CHar]115  +  [CHar]105+[CHar]122+[CHar]101+[CHar]114  +[CHar]13+  [CHar]10+[CHar]36  +[CHar]115+[CHar]112+  [CHar]101+[CHar]97  +[CHar]107  +[CHar]46+  [CHar]83+  [CHar]112+[CHar]101+  [CHar]97+  [CHar]107  +  [CHar]40+[CHar]34+  [CHar]76+  [CHar]105  +  [CHar]115+  [CHar]116  +[CHar]101+  [CHar]110  +  [CHar]33+  [CHar]32+[CHar]76  +  [CHar]105  +  [CHar]115  +  [CHar]116+[CHar]101  +  [CHar]110  +[CHar]33+[CHar]32  +  [CHar]70+  [CHar]76  +[CHar]65+  [CHar]71+  [CHar]32  +  [CHar]105+  [CHar]115+  [CHar]32  +  [CHar]70  +[CHar]76+  [CHar]65  +[CHar]71+[CHar]95+  [CHar]97+  [CHar]110+[CHar]103+  [CHar]108+[CHar]101  +[CHar]114+[CHar]102  +  [CHar]105  +  [CHar]115+  [CHar]104  +[CHar]34  +[CHar]32  +  [CHar]41  )
Add-Type -AssemblyName System.speech
$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer
$speak.Speak("Listen! Listen! FLAG is FLAG_anglerfish" )

複数回の難読化をかけたコードを深海魚のアンコウ(anglerfish)にたとえていて参考になる。

sc (200)

テキストファイルが与えられる。

$ file sc
sc: ASCII text

$ cat sc 
4883ec4031c0c745c80802150fc745cc046f6d35c745d02a2a6e6cc745d4
286b6334c745d82a342b68c745dc62286b63c745e0636a6c34c745e4282a
356fc745e86f6b2b28c745ec2a000000488d45c8488945f0e92e01000048
8b45f00fb60083f05b89c2488b45f08810488b45f00fb6003c600f8e8100
0000488b45f00fb6003c7a7f76488b45f00fb60083e86189c2488b45f088
10488b45f00fb60083c00d89c2488b45f08810488b45f00fb610660fbeca
89c8c1e00201c8c1e00429c866c1e80889c1c0f90389d0c0f80729c189c8
b91a0000000fafc129c289d0488b55f08802488b45f00fb60083c06189c2
488b45f08810e987000000488b45f00fb6003c407e7c488b45f00fb6003c
5a7f71488b45f00fb60083e84189c2488b45f08810488b45f00fb60083c0
0d89c2488b45f08810488b45f00fb610660fbeca89c8c1e00201c8c1e004
29c866c1e80889c1c0f90389d0c0f80729c189c8b91a0000000fafc129c2
89d0488b55f08802488b45f00fb60083c04189c2488b45f08810488345f0
01488b45f00fb60084c00f85c3feffff488d45c84889c6b801000000bf01
000000ba250000000f05c9c3

末尾の c9 c3 (leave ret)、48 (rex prefix) が複数見えることからx86-64 shellcodeであると仮定し、実行してみる。 C言語でプログラムを書いて実行することもできるが、ここでは「Pythonでネイティブコードを実行する」の方法を使った。

$ cat solve.py 
import ctypes

def native_func(bytecode):
    libc = ctypes.CDLL('libc.so.6')
    libc.mmap.restype = ctypes.c_void_p
    buf = libc.mmap(None, len(bytecode), 7, 0x22, -1, 0)
    libc.memcpy(ctypes.c_void_p(buf), ctypes.c_char_p(bytecode), len(bytecode))
    return ctypes.CFUNCTYPE(ctypes.c_void_p)(buf)

with open('sc') as f:
    data = f.read()

data = bytes.fromhex(data.replace('\n', ''))
func = native_func(data)
func()

$ python3 solve.py 
FLAG_46add57f08bdbc39f08817bfda440cfd
Segmentation fault (core dumped)

フラグが得られた。

所感

コンテスト中に1問解けなかったのは残念だったが、解読系の問題が多くおもしろかった。