Security Tech Lounge Vol.6 春のCTFセンバツに参加。12チーム中1位。
packet (100)
pcapngファイルが与えられる。
$ file packet
packet: pcap-ng capture file - version 1.0
Wiresharkで開くとICMPパケットが並んでおり、パケット長が3種類の異なるバイト数になっていることがわかる。

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
実行すると、localhostのUDP 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ブラウザで開くと画像が確認でき、フラグが得られた。

最後の行の 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問解けなかったのは残念だったが、解読系の問題が多くおもしろかった。