Stop the Malware

Objective #9.3
Santa's Secret Room

Identify a way to stop the malware in its tracks!

Unfortunately, Snort alerts show multiple domains, so blocking that one won't be effective. I remember another ransomware in recent history had a killswitch domain that, when registered, would prevent any further infections. Perhaps there is a mechanism like that in this ransomware? Do some more analysis and see if you can find a fatal flaw and activate it!


For hints on achieving this objective, please visit Shinny Upatree and help him with the Sleigh Bell Lottery Cranberry Pi terminal challenge.

Shinny Upatree

Have you heard that Kringle Castle was hit by a new ransomware called Wannacookie?
Several elves reported receiving a cookie recipe Word doc. When opened, a PowerShell screen flashed by and their files were encrypted.
Many elves were affected, so Alabaster went to go see if he could help out.
I hope Alabaster watched the PowerShell Malware talk at KringleCon before he tried analyzing Wannacookie on his computer.
An elf I follow online said he analyzed Wannacookie and that it communicates over DNS.
He also said that Wannacookie transfers files over DNS and that it looks like it grabs a public key this way.
Another recent ransomware made it possible to retrieve crypto keys from memory. Hopefully the same is true for Wannacookie!
Of course, this all depends how the key was encrypted and managed in memory. Proper public key encryption requires a private key to decrypt.
Perhaps there is a flaw in the wannacookie author's DNS server that we can manipulate to retrieve what we need.
If so, we can retrieve our keys from memory, decrypt the key, and then decrypt our ransomed files.


Ransomware Kill Switches hint from Alabaster Snowball
I think I remember reading an article recently about Ransomware Kill Switchs. Wouldn't it be nice if our ransomware had one!

To get the ransomware for analysis, several methods can be used.


$ sha256 wannacookie.min.ps1
SHA256 (wannacookie.min.ps1) = 2dc340bf960ced8365912d6b5684f4ef0eadee16d90a34331e1e99ffcc6e2bd4
As the code of wannacookie.min.ps1 (wannacookie.min.ps1.zip, password protected: KringleCon2018) is minified, it's hard to read and understand it, so it needs to be cleaned up. A good starting point is to replace ; with newline and add one before } and after {. Also, add a newline before each function.
cat wannacookie.min.ps1 | perl -pe 's#;#;\n#g' | perl -pe "s#\{#{\n#g" | perl -pe "s#\}#\n}#g" | perl -pe 's#^function#\nfunction#g' > wannacookie.fix1.ps1
Use PSScriptAnalyzer to format code more readable.
PS /kc18> Install-Module -Name PSScriptAnalyzer -Force
PS /kc18> Invoke-Formatter (Get-Content -Path ./wannacookie.fix1.ps1 -Raw) | Out-File ./wannacookie.fix2.ps1
Manually fix unnecessary newlines within quotes (lines 71-73, 95-97, 262-264, 275-279) and fix unnecessary newline in for loops (lines 114-116 and 166-168), save it to wannacookie.fix3.ps1. Then replace ; at the end of lines with a newline.
cat wannacookie.fix3.ps1 | perl -pe 's#;\n#\n#g'  > wannacookie.fix4.ps1
All of that results (archives are password protected: KringleCon2018) in following files: Code is pretty readable now and can by analyzed.


Another approach is to abuse the functionality of wannacookie author's DNS and just download the original source code by specifying to retrieve wannacookie.ps1 instead of wannacookie.min.ps1.

$ ./malware-get.py wannacookie.ps1 > wannacookie.ps1
$ sha256 wannacookie.ps1
SHA256 (wannacookie.ps1) = 81bff2602511f6ae29ea89202e4ec4d832a1ce3361caf4209b9f36c0ecd9f842
Curiously, compare the original source to cleaned minified source. Before that, fix line endings.
cat wannacookie.ps1 | tr '\r' '\n' > wannacookie.cr.ps1
diff -wruN wannacookie.cr.ps1 wannacookie.fix4.ps1
Turns out, it is pretty close, except that some functions and variables are named more understandable, e.g. e_d_file is Enc_Dec-File and so on.
Results (archives are password protected: KringleCon2018) in following files:


Analyzing the code and looking for early return in main function wannacookie, reveals that there are three cases, when malware exits early.

    $S1 = "1f8b080000000000040093e76762129765e2e1e6640f6361e7e202000cdd5c5c10000000"
    if ($null -ne ((Resolve-DnsName -Name $(H2A $(B2H $(ti_rox $(B2H $(G2B $(H2B $S1))) $(Resolve-DnsName -Server erohetfanu.com -Name 6B696C6C737769746368.erohetfanu.com -Type TXT).Strings))).ToString() -ErrorAction 0 -Server 8.8.8.8))) {return} 
    if ($(netstat -ano | Select-String "127.0.0.1:8080").length -ne 0 -or (Get-WmiObject Win32_ComputerSystem).Domain -ne "KRINGLECASTLE") {return}
Firstly, malware exits, if it's already running. Secondly, it exits if the computer is not in KRINGLECASTLE domain. Curious is the third and final case.

DNS look up is made to check for existence of domain. If the domain exists, the malware will exit.
Name of the domain is determined in interesting way, and after analyzing the functions, it is as simple as two values being xor-ed.

XORing 1f0f0202171d020c0b09075604070a0a with 66667272727869657268667865666B73 returns the domain yippeekiyaa.aaay.

$ python3
>>> import codecs
>>> v1 = codecs.decode('1f0f0202171d020c0b09075604070a0a', 'hex')
>>> v2 = codecs.decode('66667272727869657268667865666B73', 'hex')
>>> print(''.join(chr(a ^ b) for a,b in zip(v1,v2)))
yippeekiyaa.aaay

Opening HoHoHo Daddy ...

HoHoHo Daddy web page

... and registering domain yippeekiyaa.aaay solves the challenge.

registered domain at HoHoHo Daddy

Yippee-Ki-Yay! Now, I have a ma... kill-switch!


Die Hard (1988): Ho Ho Ho Scene
Die Hard (1988): Yippee-Ki-Yay Scene