# Using binsnitch.py to detect files touched by malware

Yesterday, we released binsnitch.py – a tool you can use to detect unwanted changes to the file sytem. The tool and documentation is available here: https://github.com/NVISO-BE/binsnitch.

Binsnitch can be used to detect silent (unwanted) changes to files on your system. It will scan a given directory recursively for files and keep track of any changes it detects, based on the SHA256 hash of the file. You have the option to either track executable files (based on a static list available in the source code), or all files.

Binsnitch.py can be used for a variety of use cases, including:

• Use binsnitch.py to create a baseline of trusted files for a workstation (golden image) and use it again later on to automatically generate a list of all modifications made to that system (for example caused by rogue executables installed by users, or dropped malware files). The baseline could also be used for other detection purposes later on (e.g., in a whitelist);
• Use binsnitch.py to automatically generate hashes of executables (or all files if you are feeling adventurous) in a certain directory (and its subdirectories);
• Use binsnitch.py during live malware analysis to carefully track which files are touched by malware (this is the topic of this blog post).

In this blog post, we will use binsnitch.py during the analysis of a malware sample (VirusTotal link:

A summary of options available at the time of writing in binsnitchy.py:

``````usage: binsnitch.py [-h] [-v] [-s] [-a] [-n] [-b] [-w] dir

positional arguments:
dir               the directory to monitor

optional arguments:
-h, --help        show this help message and exit
-v, --verbose     increase output verbosity
-s, --singlepass  do a single pass over all files
-a, --all         keep track of all files, not only executables
-n, --new         alert on new files too, not only on modified files
-b, --baseline    do not generate alerts (useful to create baseline)

We are going to use binsnitch.py to detect which files are created or modified by the sample. We start our analysis by creating a “baseline” of all the executable files in the system. We will then execute the malware and run binsnitch.py again to detect changes to disk.

Creating the baseline

Command to create the baseline of our entire system.

We only need a single pass of the file system to generate the clean baseline of our system (using the “-s” option). In addition, we are not interested in generating any alerts yet (again: we are merely generating a baseline here!), hence the “-b” option (baseline). Finally, we run with the “-w” argument to start with a clean database file.

After launching the command, binsnitch.py will start hashing all the executable files it discovers, and write the results to a folder called binsnitch_data. This can take a while, especially if you scan an entire drive (“C:/” in this case).

Baseline creation in progress … time to fetch some cheese in the meantime! 🐀 🧀

After the command has completed, we check the alerts file in “binsnitch_data/alerts.log”. As we ran with the “-b” command to generate a baseline, we don’t expect to see alerts:

Baseline successfully created! No alerts in the file, as we expected.

Looks good! The baseline was created in 7 minutes.

We are now ready to launch our malware and let it do its thing (of-course, we do this step in a fully isolated sandbox environment).

Running the malware sample and analyzing changes

Next, we run the malware sample. After that, we canrun binsnitch.py again to check which executable files have been created (or modified):

Scanning our system again to detect changes to disk performed by the sample.

We again use the “-s” flag to do a single pass of all executable files on the “C:/” drive. In addition, we also provide the “-n” flag: this ensures we are not only alerted on modified executable files, but also on new files that might have been created since the creation of the baseline. Don’t run using the “-w” flag this time, as this would wipe the baseline results. Optionally, you could also add the “-a” flag, which would track ALL files (not only executable files). If you do so, make sure your baseline is also created using the “-a” flag (otherwise, you will be facing a ton of alerts in the next step!).

Running the command above will again take a few minutes (in our example, it took 2 minutes to rescan the entire “C:/” drive for changes). The resulting alerts file (“binsnitch_data/alerts.log”) looks as following:

Bingo! We can clearly spot suspicious behaviour now observing the alerts.log file. 🔥

A few observations based on the above:

• The malware file itself was detected in “C:/malware”. This is normal of-course, since the malware file itself was not present in our baseline! However, we had to copy it in order to run it;
• A bunch of new files are detected in the “C:/Program Files(x86)/” folder;
• More suspicious though are the new executable files created in “C:/Users/admin/AppData/Local/Temp” and the startup folder.

The SHA256 hash of the newly created startup item is readily available in the alerts.log file: 8b030f151c855e24748a08c234cfd518d2bae6ac6075b544d775f93c4c0af2f3

Doing a quick VirusTotal search for this hash results in a clear “hit” confirming our suspicion that this sample is malicious (see below). The filename on VirusTotal also matches the filename of the executable created in the C:/Users/admin/AppData/Local/Temp folder (“A Bastard’s Tale.exe”).

VirusTotal confirms that the dropped file is malicious.

You can also dive deeper into the details of the scan by opening “binsnitch_data/data.json” (warning, this file can grow huge over time, especially when using the “-a” option!):

Details on the scanned files. In case a file is modified over time, the different hashes per file will be tracked here, too.

From here on, you would continue your investigation into the behaviour of the sample (network, services, memory, etc.) but this is outside the scope of this blog post.

We hope you find binsnitch.py useful during your own investigations and let us know on github if you have any suggestions for improvements, or if you want to contribute yourself!

Squeak out! 🐁

Daan

# Wcry ransomware – Additional analysis

Introduction
Since May 12, a large number of organisations has fallen victim to the “wcry” (or “Wanacry”) ransomware, which abuses the SMB exploits / vulnerabilities that were famously released in the Shadow Brokers data dump in April 2017. Our aim in this short blog post is not to repeat existing information, but communicate some additional information that was derived by our NVISO CERT.

Note that our analysis is still ongoing and we will update our post with additional information, our CERT team is advising NVISO’s customers as we speak. Should you have any questions or require emergency support, please don’t hesitate to contact our 24/7 hotline on +32 (0)2 588 43 80 or incidents@nviso.be.

In short, the ransomware appears to initially enter the environment by traditional phishing (or via systems exposing SMB to the Internet), after which it leverages aforementioned SMB RCE (Remote Code Execution) vulnerabilities (MS17-010) to spread in the network like wildfire. The combination of “standard” ransomware with a recent remote code execution exploit make for a very effective attack, which is evidenced by the impact it has caused on a global scale.

On 13 May, it was reported that wcry, before starting its encryption process, attempts to connect to a seemingly random domain name (www[.]iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea[.]com) (EDIT: On May 15th, a second kill-switch domain was found in a new sample: www[.]ifferfsodp9ifjaposdfjhgosurijfaewrwergwea[.]com).

If these domains can be contacted, the malware stops its operations. This is most likely a kill-switch that was built in, but not effectively used, as the domain name had not been registered by the attackers. It has been registered by security researches in the meantime, hindering the ransomware’s advance. Note that the kill-switch is not proxy aware and is thus ineffective in environments where a proxy is used to access the Internet (NVISO’s analyst Didier Stevens published a quick-post on the killswitch here).

For additional background information, the following articles & blog post provide a good description of the observed wcry activity:

The main recommendations to prevent / limit the impact of wcry:

• Ensure Microsoft’s patch (MS17-010) is rolled out throughout your organisation (also in the internal network) to prevent the spread of the malware using the SMB exploit;
• If you cannot install the patch timely, TearSt0pper (developed by Rendition InfoSec) can be deployed to prevent the encryption from taking place;
• Ensure Windows SMB services (typically TCP port 445) are not directly exposed to the Internet;
• Implement network segmentation between different trust zones in the network;
• Ensure recent back-ups are available offline and can be easily restored;
• Upon infection: isolate any infected hosts from the network;
• Continue end-user awareness to prevent the initial compromise through phishing;
• Implement mail sandboxing solutions to block incoming malicious mail attachments.

Throughout the weekend, our analysts further investigated the attack, noticing only 2 known variants of the “wcry” ransomware were uploaded from Belgium on VirusTotal. Given the global scale of the attack, this is a surprisingly low number of hits.

From an analyst perspective, the malware does not take big efforts to obfuscate itself and a simple static analysis (e.g. looking for strings) comes up with a large number of strings that could be used in YARA rules:

• The ransomware manual language files that are dropped: (*.wnry)
• It uses icacls to change permissions, using the following hard-coded command: “icacls . /grant Everyone:F /T /C /Q
• Unicode string in the executable “WanaCrypt0r”
• The ransomware creates a Windows registry value to ensure persistence (survival upon reboot). We observed different variants of this behaviour, 2 examples are below:

cmd.exe /c reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v obsbeuqp321″ /t REG_SZ /d “\”C:\WINDOWS\system32\tasksche.exe\”” /f

cmd.exe /c reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run /v “mzaiifkxcyb819” /t REG_SZ /d “\”C:\tasksche.exe\”” /f

Note the creation of the “taschsche.exe” executable, which is different from the normal “taschsche.exe” (part of Windows).

Update 1

As stated, on networks where a proxy is the only way to access the Internet (e.g. corporate networks), the killswitch will not work because the code is not proxy aware. This means that the malware will attempt to resolve the killswitch domain name with internal DNS, and if it receives a DNS reply with an IP address, it will proceed with an HTTP request. It will not connect to the proxy.

Corporations are configuring internal DNS with the killswitch domain name and an internal sinkhole as mitigation. This prevents the sample from activating, provided that the sinkhole server sends a reply.

The reply can be a 404, that will work too. It can even be a single character x send via the TCP connection, that is fine too. But something has to be replied, just opening the connection and closing it, without sending anything to the malware, will result in activation of the malware.

FYI: this was tested via dynamic analysis with sample 5ad4efd90dcde01d26cc6f32f7ce3ce0b4d4951d4b94a19aa097341aff2acaec and with our own custom code simulating the killswitch test in the malware.

Our analysis is still ongoing and we will update our post with additional information, as our CERT team is advising NVISO’s customers as we speak. Should you have any questions or require emergency support, please don’t hesitate to contact our 24/7 hotline on +32 (0)2 588 43 80 or incidents@nviso.be. We would be happy to help!

# NVISO at Hack Belgium

Last week, a few of us attended the first edition of Hack Belgium. Describing what Hack Belgium is turns out to be a bit difficult: is it a conference? A hackaton? A hands-on workshop? A technology fair? A pitch? In my view, it’s all of those combined – and that made the event so interesting!

9AM – Daan, Jeroen, Kris & Kurt looking sharp at Hack Belgium ( … and ready for some ☕️!).

Hack Belgium offers its attendees 14 crucial challenges around topics that keep our world busy: from healthcare to mobility and building intelligent cities. Over the course of 3 days, all attendees put their heads together to come up with a bright solution to these challenges. With the help of more than 300 experts, it’s certainly a great experience and exercise in idea generation! The objective is to pitch your idea on Saturday and to walk out of Hack Belgium with a blueprint to start working on your project.

Our CEO Kurt ready to escape reality 🕶.

OK, I have to confess – we did not stay until Saturday for our pitch, however we did have a lot of fun and interesting moments on Thursday and Friday! We worked on a concept for the media to bring news in a more balanced format, we did a workshop on designing connected projects, we attended an expert session on the state of Virtual Reality (VR) and Augmented Reality (AR), and we had fun playing around with IBM Watson and other upcoming technologies.

Kris showing off his drawing skills 🐁.

Pulling off this type of event at this scale takes a lot of preparation (and guts!) – we want to congratulate  the Hack Belgium staff and all the volunteers involved! You truly made this into an interesting & worthwhile event.

We hope to be present for Hack Belgium 2018 and beyond (… and we will stay for the pitch, promise 🐀!).

A few more impressions after the break!

Proud to say we didn’t lose any fingers playing around with these beasts! 🖐

Beep Boop Beep Boop

Playing around with creative ways to design connected products during a workshop. My drawing skills are inferior to the one from Kris, so no close-up 😃!

# Let’s get the team together…

It was the last week of April: our entire NVISO team had packed their bags and was ready to board a plane. Where to? A secret location, to celebrate the achievements of our fantastic team !

Did all of you lab rats bring your passports? 🐀

Destination: unknown…
From the very beginning, it became clear that the discovery of our destination was a fun team-building event by itself: to find out, we’d have to solve a series of technical challenges eventually lifting the veil on that well-kept secret… right before getting our boarding passes !

In the morning, we were all supposed to meet up at our office. At exactly 9AM, we received a mail from HR containing a URL. The website was created using Drupal and contained a bit of teaser information concerning the offsite. It also had a login form, but we were lacking valid credentials. After some fiddling around and some scanning, we found it was vulnerable to Drupageddon. This allowed us to create a user account using SQL injection. Once logged into the website, we could create posts ourselves. This vulnerability also allowed us to run commands through PHP, but we weren’t able to simply launch a reverse shell. Using a Netcat pipe, we did succeed in getting shell access to the server. The next step was to look for some kind of flag. Some grepping and finding showed us the location of the flag, in a file containing instructions for the next piece of the puzzle.

Maybe we should have brought two computers into office this morning…

From there on, we were split up in two teams. Team A would remain in Brussels and team B was set off to a gas station near the highway in Breda, in The Netherlands. There, Team B was to find “Lou”. Upon arrival at the gas station, team B inquired for Lou: the lady behind the counter looked at them as if they were about to pull a gun. Looking all over the gas station, Team B eventually identified Lou: the challenge could continue. But what should Team B tell Lou ?

Team A had to assist them: very soon, they found a USB key taped to one of the GoPro action cameras left behind by the organizers to record our endeavors. Forensic analysis was on! After booting kali, performing some volatility magic, deciding it took too long and running strings on the dump file, Team A discovered the passphrase that should be given to Lou at the gas station.

Once Team B provided the correct passphrase to Lou, he gave the next set of instructions for both Team A and Team B. Through an image puzzle, Team B found out they had to carry on towards Schiphol, the Amsterdam Airport. Lou would be there, somewhere, ready to hand out the next hint. Meanwhile, Team A were told they should find an envelope at the office. After flipping over all the tables, the envelope was found : it contained yet another USB key. This time, the USB key contained an encrypted zip file with a PCAP file inside. After putting its youngest new recruit in front of the computer in true Swordfish-first-scene style, Team A cracked the password and started analysis of the PCAP file. Captured traffic in the PCAP consisted of web browsing traffic towards the website of Brussels International Airport: the hint was clear, Team A rushed to the airport !

The destination? Dubai!

Our precious bird, watching over the Burj…

Our time in the City of Endless Possibilities
Taking some time to reflect is important. Taking some space (literally) helps to step back and look at the bigger picture. While we did reflect on where we had come from, our eyes were decidedly focused on the future. We spent quite some time discussing what we stand for as individuals and as a team: we discussed which values we want to share and live by, and how these values can make NVISO better, both for us and for our clients. The conversation resulted in valuable insights. Putting words on what we believe in, together, made everyone feel committed to upholding them, because they are what we believe in, and represent us best.

To then put our money where our mouth was, the rest of our time was invested in taking concrete actions: we set off to select one initiative that would help NVISO improve in practice. Four teams together proposed 8 ideas, which were challenged and judged by a ‘shark tank’, our very own jury.

The proposal attracting the most support was an initiative on internal sharing of knowledge between colleagues. So in the coming months, we will be working to build a framework that supports and promotes informal sharing of experiences and skills within NVISO. Because sharing is caring!

The winners of the Shark Tank 2017 – congratulations Hans, Benoit, Mercedes, Nico and Jeroen!

But let’s not fool ourselves: the trip was not all hard work. We also found time to enjoy the local attractions of Dubai and have lots of team fun. Loyal to the good old “work hard, play hard” motto, and believing in laughter as a great way to bond with colleagues, we rushed down crazy water slides in Aquaventure, chilled at the local beach and were inspired to aim higher at Burj Khalifa. In short, we made the most of our time there, enjoying some well-deserved rest, having fun and getting to know each other better as a great team. After all, we don’t travel to the City of Endless Possibilities every week!

Aarg … we should have taken this picture before sunset! 🐀 😁

A while ago Michel wrote a blog post Tracking threat actors through .LNK files.

In this post, we want to illustrate how VirusTotal (retro) hunting can be leveraged to extract malware samples and metadata linked to a single threat actor. We use the power of YARA rules to pinpoint the metadata we are looking for.

With some of the metadata extracted from the .LNK file we wrote about in our previous blog post (Volume ID and MAC address), we’re going to search on VirusTotal for samples with that metadata. It is clear from the MAC address 00:0C:29:5A:39:04 that the threat actor used a virtual machine to build malware: 00:0C:29 is an OUI owned by VMware. We wonder if the same VM was used to create other samples.
With a VirusTotal Intelligence subscription, one can search through the VirusTotal sample database, for example with YARA rules. We use the following YARA rule for the metadata:

```rule MALDOC_LNK {
strings:
\$BirthObjectId = {C2 CC 13 98 18 B9 E2 41 82 40 54 A8 AD E2 0A 9A}
\$MACAddress = {00 0C 29 5A 39 04}
condition:
all of them
}
```

VTI supports hunting and retro-hunting with YARA rules. With hunting, you will be informed each time your YARA rules triggers on the VT servers each time a newly submitted sample matching your rule. With retro-hunting, YARA rules are used to scan through 75TB of samples in the VT database. This correspond more or less to the set of samples submitted in the last three months.
Here is the result from a retro-hunt using YARA rule MALDOC_LNK:

Next step is to download and analyse all these samples. Since we did not include a file type condition in our YARA rule, we get different types of files: Word .doc files, .lnk files, raw OLE streams containing .lnk files, and MIME files (e-mails with Word documents as attachment).
With this command we search for strings containing “http” in the samples:

So we see that the same virtual machine has been used to created several samples. Here we extract the commands launched via the .lnk file:

The metadata from the OLE files reveals that the virtual machine has been used for a couple of weeks:

Conclusion

With metadata and VirusTotal, it is possible to identify samples created by the same actor over a period of 3 months. These samples can provide new metadata and IOCs.

# Analysis of a CVE-2017-0199 Malicious RTF Document

There is a new exploit (CVE-2017-0199) going around for which a patch was released by Microsoft on 11/04/2017. In this post, we analyze an RTF document exploiting this vulnerability and provide a YARA rule for detection.

rtfdump.py is a Python tool to analyze RTF documents. Running it on our sample produces a list with all “entities” in the RTF document (text enclosed between {}):

This is often a huge list with a lot of information. But here, we are interested in OLE 1.0 objects embedded within this RTF file. We can use the filter with option -f O for such objects:

There are 2 entities (objdata and datastore) with indices 153 and 249 (this is a number generated by rtfdump, it is not part of the RTF code). The content of an object is encoded with hexadecimal characters in an RTF file,  entity 153 contains 5448 hexademical characters. So let’s take a look by selecting this entity for deeper analysis with option -s 153:

In this hex/ascii dump, we can see that the text starts with 01050000 02000000, indicating an OLE 1.0 object. As the second line starts with d0cf11e0, we can guess it contains an OLE file.

With option -H, we can convert the hexadecimal characters to binary:

So it is clearly an embedded OLE file, and the name OLE2Link followed by a zero byte was chosen to identify this embedded OLE file. With option -E, we can extract the embedded object:

Since this is an OLE file, we can analyze it with oledump.py: we dump the file with option -d and pipe it into oledump:

The OLE file contains 2 streams. Let’s take a look at the first stream:

We can recognize a URL, let’s extract it with strings:

Because of vulnerability CVE-2017-0199, this URL will automatically be downloaded. The web server serving this document, will identify it as an HTA file via a Content-Type header:

Because this download is performed by the URL Moniker, this moniker will recognize the content-type and open the downloaded file with Microsoft’s HTA engine. The downloaded HTA file might look to us like an RTF file, but the HTA parser will find the VBS script and execute it:

Detection

Let’s take a second look at the first stream in the OLE file (the stream with the malicious URL):

The byte sequence that we selected here (E0 C9 EA 79 F9 BA CE 11 8C 82 00 AA 00 4B A9 0B), is the binary representation of the URL Moniker GUID: {79EAC9E0-BAF9-11CE-8C82-00AA004BA90B}. Notice that the binary byte sequence and the text representation of the GUID is partially reversed, this is typical for GUIDs.

After the URL Moniker GUID, there is a length field, followed by the malicious URL (and then followed by a file closing sequence, …).

We use the following YARA rule to hunt for these RTF documents:

```rule rtf_objdata_urlmoniker_http {
strings:
\$objdata = "objdata 0105000002000000" nocase
\$urlmoniker = "E0C9EA79F9BACE118C8200AA004BA90B" nocase
\$http = "68007400740070003a002f002f00" nocase
condition:
\$header at 0 and \$objdata and \$urlmoniker and \$http
}

Remark 1: we do not search for string OLE2Link
Remark 2: with a bit of knowledge of the RTF language, it is trivial to modify documents to bypass detection by this rule
Remark 3: the search for http:// (string \$http) is case sensitive, and if you want, you can omit it (for example, it will not trigger on https).
Remark 4: there is no test for the order in which these strings appear
Happy hunting!
```

# CSCBE Challenge Write-up – Sufbo

The Sufbo challenge was tackled during the Cyber Security Challenge qualifiers and proved to be very difficult to solve. This write-up gives you a possible way of solving it!

Credits

All challenges of the Cyber Security Challenge are created by security professionals from many different organisations. The Sufbo challenge in particular was created by Adriaan Dens, one of our distinguished challenge contributors, from Proximus. Adriaan & Proximus have contributed multiple challenges over the years and they tend to be pretty hard to solve ;).

The challenge

And you thought Assembly was hard to read? Try this!

The solution

The challenge consists out of a heavily obfuscated piece of perl code. We can start by cleaning up the code which improves the readability by a small bit:

```print"Flag: ";
chomp(\$_=&lt;&gt;);
\$[=0;
die if y///c!=32;
chomp(@_=&lt;DATA&gt;);
\$/=join'',map{chr(ord\$_^\$=)}split//,pack"H*",shift(@_).shift(@_);

while(\$,=substr\$_,8*\$-,8) {
(\$@,\$*,\$#,\$x,\$y,\$z,\$!,\$.,\$,) = (unpack("N*",\$/.\$,),0,2**31*(sqrt(5)-1),(1&lt;&lt;32)-1);
map {
\$!+=\$.;
\$!&amp;=\$,;
\$y+=(((((\$z&lt;&lt;4)&amp;\$,)+\$@)&amp;\$,)^((\$z+\$!)&amp;\$,)^(((\$z&gt;&gt;5)+\$*)&amp;\$,));
\$y&amp;=\$,;
\$z+=(((((\$y&lt;&lt;4)&amp;\$,)+\$#)&amp;\$,)^((\$y+\$!)&amp;\$,)^(((\$y&gt;&gt;5)+\$x)&amp;\$,));
\$z&amp;=\$,;
\$"=pack("N*",\$y,\$z);
\$/=\$"x2
}0..31;
die if\$"ne pack"H*",\$_[\$-];
\$-++;
}
print "OK\n"

__DATA__
6c594e50630d4f63
7d515d4655525b1d
7872575285c742da
15c670798094a00b
54f08c6b937ed1f2
6810afed7372cd76
```

This code might still not mean a lot to the average non-perl-speaking-person. Let’s take a look at the same code, but with some inline comments:

```print"Flag: "; # Prints "Flag: " to STDIN
chomp(\$_=&lt;&gt;); # Reads in the input into the variable \$_
\$[=0; # Changes the starting index of an array to 0 (It's a useless command actually)
die if y///c!=32; # y///c is a Perl golfing idiom that is similar to length(\$_), so the length of your input has to be a string of length 32.
chomp(@_=&lt;DATA&gt;); # Store the data below (under __DATA__) in the array @_
\$/=join'',map{chr(ord\$_^\$=)}split//,pack"H*",shift(@_).shift(@_); # Shift the first two elements of @_, "unhexify" the strings, split them per character, XOR with \$= (default value is 60), and join the characters back in the variable \$/.
#
while(\$,=substr\$_,8*\$-,8) { # While there are 8 characters left in the input do:
(\$@,\$*,\$#,\$x,\$y,\$z,\$!,\$.,\$,) = (unpack("N*",\$/.\$,),0,2**31*(sqrt(5)-1),(1&lt;&lt;32)-1); # Convert the variable \$/ (unknown) and \$, (our input) to unsigned numbers, assign 0 to \$!, assign 2**31*(sqrt(5)-1) to \$/ and assign (1&lt;&lt;32)-1 to \$,.
map { # Use map to loop 32 times (see below)
\$!+=\$.; # Add \$. to \$!
\$!&amp;=\$,; # Bitwise AND \$! with \$,
\$y+=(((((\$z&lt;&lt;4)&amp;\$,)+\$@)&amp;\$,)^((\$z+\$!)&amp;\$,)^(((\$z&gt;&gt;5)+\$*)&amp;\$,)); # Some bitwise operations added to \$y
\$y&amp;=\$,; # Bitwise AND \$y with \$,
\$z+=(((((\$y&lt;&lt;4)&amp;\$,)+\$#)&amp;\$,)^((\$y+\$!)&amp;\$,)^(((\$y&gt;&gt;5)+\$x)&amp;\$,)); # Some bitwise operations added to \$z
\$z&amp;=\$,; # Bitwise AND \$z with \$,
\$"=pack("N*",\$y,\$z); # Convert the unsigned numbers back to string representation
\$/=\$"x2 # Set \$/ to two times \$"
}0..31; # Use map to loop 32 times
die if\$"ne pack"H*",\$_[\$-]; # Die if \$" is not equal to the "unhexified" element (\$- contains the index) in @_
\$-++; # Increase the variable \$-
} #
print "OK\n" # Printed if you have the key
#
__DATA__ # Starting the DATA block (kinda like a here document)
6c594e50630d4f63 # This part was used for \$/ in line 6.
7d515d4655525b1d # This part was used for \$/ in line 6.
7872575285c742da # This part was used to compare with the input on line 20
15c670798094a00b # This part was used to compare with the input on line 20
54f08c6b937ed1f2 # This part was used to compare with the input on line 20
6810afed7372cd76 # This part was used to compare with the input on line 20
```

So now we more or less know what each line does but we still miss context on a higher level (what it is doing). As always in reverse engineering, you try to find some “known parts” which allow you to understand the code a lot faster. These parts are usually strings, metadata, fixed numbers or familiar code blocks.

In our case, we have 2 fixed numbers: $2**31*(sqrt(5)-1)$ and $(1<<32)-1$. In this representation they don’t mean much but if we convert them to hex numbers we get 0x9e3779b9 and 0xffffffff respectively.

Hmm, interesting! Seems like we’ve got a Perl implementation of Tiny Encryption Algorithm (TEA) on our hands here!

More specifically, the while loop block in the code is the actual TEA implementation, which decrypts the second half of the __DATA__ section using the first half as the key.

Retrieving the key can be done using the following perl one-liner:

```perl -E 'say join"",map{chr(ord\$_^\$=)}split//,pack"H*","6c594e50630d4f637d515d4655525b1d"
```

Which yields us “Perl_1s_Amazing!” as the key.

So now we have they key and the data to be decrypted. Let’s be lazy and copy the reference code listed on the wikipedia page we found earlier.

```#include&lt;stdint.h&gt;
#include&lt;stdio.h&gt;

void decrypt (uint32_t* v, uint32_t* k) {
uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i; /* set up */
uint32_t delta=0x9e3779b9; /* a key schedule constant */
uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; /* cache key */
for (i=0; i&lt;32; i++) { /* basic cycle start */
v1 -= ((v0&lt;&lt;4) + k2) ^ (v0 + sum) ^ ((v0&gt;&gt;5) + k3);
v0 -= ((v1&lt;&lt;4) + k0) ^ (v1 + sum) ^ ((v1&gt;&gt;5) + k1);
sum -= delta;
} /* end cycle */
v[0]=v0; v[1]=v1;
printf("%x%x", v0, v1);
}

void main() {
/* Our cipher chunks, found in the __DATA__ block of the Perl code */
uint32_t c0[] = { 0x78725752, 0x85c742da };
uint32_t c1[] = { 0x15c67079, 0x8094a00b };
uint32_t c2[] = { 0x54f08c6b, 0x937ed1f2 };
uint32_t c3[] = { 0x6810afed, 0x7372cd76 };

/* The used keys for encrypting */
uint32_t k[] = { 0x5065726c, 0x5f31735f, 0x416d617a, 0x696e6721 }; /* Original key: Perl_1s_Amazing! */
uint32_t k0[] = { 0x78725752, 0x85c742da, 0x78725752, 0x85c742da }; /* c0 . c0 */
uint32_t k1[] = { 0x15c67079, 0x8094a00b, 0x15c67079, 0x8094a00b }; /* c1 . c1 */
uint32_t k2[] = { 0x54f08c6b, 0x937ed1f2, 0x54f08c6b, 0x937ed1f2 }; /* c2 . c2 */

/* Decrypting the chunks */
decrypt(c0,k);
decrypt(c1,k0);
decrypt(c2,k1);
decrypt(c3,k2);
}
```
```\$ gcc --std=c99 solution.c
\$ ./a.out
43534342457b5065726c31735772317465306e6365526534646e33766552727d
\$ ./a.out | perl -nle 'print pack("H*", \$_)'
&gt;&gt;&gt; CSCBE{Perl1sWr1te0nceRe4dn3veRr}
```

There we go! CSCBE{Perl1sWr1te0nceRe4dn3veRr} was the flag.