owned this note
owned this note
Published
Linked with GitHub
[toc]
# DarkSide Ransomware - Malware Analysis
- [Download Link](https://samples.vx-underground.org/Samples/Families/Darkside/06355667ea0deef9cfeedc864d74edfe986cf9a9f129532f4a442f7098e1e054.7z)
## File Analysis
### SHA256 Checksum
- `06355667ea0deef9cfeedc864d74edfe986cf9a9f129532f4a442f7098e1e054`
### File Type
- `PE 32-bit architecture`
### Sections
| Section | Virtual Address | Size |
| ------- | --------------- | --------- |
| `.text` | `0x1000` | `0x8400` |
| `.text1` | `0xa000` | `0x400` |
| `.rdata` | `0xb000` | `0x200` |
| `.data` | `0xc000` | `0x3400` |
| `.rsrc` | `0x10000` | `0x1000` |
### Original Entry Point
- OEP : `0xA30F`
<div style='display: flex-column; text-align: center;'><img src='https://hackmd.io/_uploads/Hkxj9BQBR.png'/><br/><br/><img src="https://hackmd.io/_uploads/HkugYrXB0.png"/></div>
At the beginning, the start function's end address was `0x40a334` but I changed it to `0x40a33c` because I saw the call to `ExitProcess(0)`.
### Imports
Only one.
- `kernel32.dll`
- `ExitProcess`
### Early Comments
- Two `.text` segments is a bit suspicious.
- There is only one function import.
- `.text` is writeable. This probably means runtime patching.
## (Stage 1) Static and Dynamic Analysis
### `sub_40A288` (init_peb_variables)

In brief, this function accesses the PEB structure and stores the following fields into some global variables:
1. `ProcessHeap`. Address of process' first heap allocated by Loader.
2. `ImageBaseAddress`. The base address of the current executable.
3. `NumberOfProcessors`. The number of processors being used in this executable.
4. `ProcessParameters->CommandLine.Buffer`. The actual command line string that was used to run the executable.
Let's give the variables and the function name some proper names.

### `sub_40A2B5` (locate_and_decrypt_text_seg)
When we try decompiling this function we get the following prompt:

which indicates that the `.text` segment is written during runtime.
TL;DR
- [Skip the argument analysis](#Function-Arguments)
#### Detailed Argument Analysis

This function uses the image's base address which indicates that we should study the PE format to see what parts of the binary it accesses. Let's analyze the two arguments of `sub_40A000` separately. For brevity, we will denote the image's base address as `B`.
1. The argument is : `*(*(B + 0x3C) + B + 0x104) + B`. Let's analyze this. Note that, instead of doing it manually, one could use PEBear for automatic parsing of the PE and extracting all the useful info from the headers.
- `*(B + 0x3c)` : If we wanted to convert `B` to a structure, that would be `IMAGE_DOS_HEADER`. By looking up the [structure](http://pinvoke.net/default.aspx/Structures.IMAGE_DOS_HEADER) we can see that by moving `0x3c` bytes we land on the starting offset of the `NT Headers`; namely `e_lfanew`. Usually we recognize the start of the [`NT Headers`](https://www.nirsoft.net/kernel_struct/vista/IMAGE_NT_HEADERS.html) by the signature bytes `PE\x00\x00`. After these bytes, follows the File Header and the Optional Header. Thus, `*(B + 0x3c) = 0x80`.
- `*(B + 0x3C) + B` : This is equal to `B + 0x80`.
- `*(*(B + 0x3C) + B + 0x104) + B` : This is equivalent to `*(B + 0x80 + 0x104) + B = *(B + 0x184) + B`. Let's look into HexEditor what are the bytes at the offset `0x184`.

This is the Virtual Address of the `.text` segment. We can use PEBear to verify that.

Therefore, this whole expression evaluates to `B + 0x1000`. We can look at PEBear to find out that the image's base address is `0x400000`. The final evaluation is `0x401000`.
Eventually, we conclude that the first argument of the function is `0x401000` and is a pointer to the start of the `.text` segment.
#### Raw Address vs Virtual Address (Bonus)
Note that the `Raw Address` is different than the `Virtual Address`. The `Raw Address` tells us where should we look in the Hex Editor to find the corresponding segment; in the case of the `.text` segment is `0x400`.

The raw address represents the raw location within the physical file on disk. An application that is running does not access these raw offsets, instead it accesses virtual memory. For example, during runtime, the `.text` segment starts at `0x401000`, while on disk, it starts at `0x400`.
By looking up in IDA, we see the virtual addresses.

2. The argument is : `*(*(B + 0x3C) + B + 0x108)`.
As [aforementioned](#Detailed-Argument-Analysis), `*(B + 0x3c)` is equal to `0x80`. Therefore the expression evaluates to `*(B + 0x80 + 0x108) = *(B + 0x188) = 0x8400`. You can find `0x8400` by looking up in the HexEditor screenshot above.
From PEBear, one can see that this is the raw size of the `.text` segment. By navigating to the address `0x401000 + 0x8400 = 0x409400` in IDA, we see that this is indeed the end of the segment.

#### Function Arguments
We conclude that the arguments of `sub_40A000` are:
1. The starting virtual address of the `.text` segment.
2. The size of the `.text` segment.
At this point, we could assume that `sub_40A000` is a wrapper function for a decryption routine that receives two arguments; the starting address of the encrypted segment and its size and finally decrypts the encrypted segment. We will investigate it more closely later.
For now, let's move on by renaming `sub_40A2B5` to `locate_and_decrypt_text_seg`
### `sub_40A2DE` (locate_and_decrypt_data_seg)

At first glance, we can see that `sub_40A000` is called again as in the previous function. Therefore we expect that it receives an encrypted blob of data and their size. Let's analyze the arguments briefly:
1. `*(*(B + 0x3c) + B + 0x17c) + B` : As mentioned above, `*(B + 0x3c) = 0x80` so the expression evaluates to `*(B + 0x80 + 0x17c) + B = *(B + 0x1fc) + B`. By looking at HexEditor, we see that the bytes at offset `0x1fc` are `0xc000`.

Eventually, the first argument is `0x400000 + 0xc000 = 0x40c000`. PEBear tells us that this is the start of the `.data` segment.

2. The value of `i` depends on the for loop. This loop counts the bytes in the `.data` segment until `0xffffffff` (i.e. `-1`) is met.

> Therefore we expect that it receives an encrypted blob of data and their size.
Our expectations are met. Let's rename the function to `locate_and_decrypt_data_seg`.
### (fail) Function `sub_40911D` (far call)

~~This functions is weird. Looks like it jumps to the memory address `0x0474e2b8` of another segment in the binary (offset `0xef48`) which is 16-bit assembly. However this address is out of the bounds of this binary.
??? ??? ??? ??? ??? ???. We cannot determine statically what this does yet.~~
I should have noticed already. This function belongs in the `.text` section which is ENCRYPTED! The decompilation is not valid code. The actual function body is decrypted in the runtime by `locate_and_decrypt_text_seg`.
Lessons Learned : I should probably use dynamic analysis more often.
Before moving on, let's take a look at the first function that is called at the start method `sub_40A047`.
### `sub_40A047` (Buffer Initialization)
At a high level, this method initializes the global variable `byte_40F270`.
Here, the first argument is dereferenced:

And here, the second one:

*I will have to do some dynamic analysis for this function.*
Nvm, I am dumb, `0x410000` is the start of the `.rsrc` section (figured out from x32dbg).
This function receives three arguments:
1. `0x410010` : The second 16-byte string.
2. `0x410020` : The third 16-byte string.
3. `0x10` : The value `0x10 = 16`.

Having understood what this function does, we can rename it to `init_buffer_from_rsrc_keys`.
### `sub_40A000` and `sub_40A0D5` (Decryption Routines)
As aforementioned, `sub_40a000` is a wrapper for the actual decryption function `sub_40a0d5`.

In the main `do-while` loop, `enc_ptr` is moving by `255` positions which indicates that it decrypts the section block-by-block, where the block size is `255` and the number of blocks is `132`. Therefore we can rename `sub_40a0d5` to `decrypt_block` and `sub_40a000` to `decrypt`.
Recall that the arguments for decrypting the `.text` section are:
1. `0x401000`
2. `0x8400`
While for decrypting the `.data` section are:
1. `0x40c000`
2. `0x3261`
Having decrypted the sections, we create a new binary by replacing the encrypted sections with the decrypted ones.
## (Stage 2) - The Actual Ransomware
While there were only a few functions in the previous binary, this one has a whole lot more.
<div style='text-align:center;'><img src="https://hackmd.io/_uploads/HJDWQGKrR.png" /></div>
We are not going to analyze them all, it's enough to have an overall idea of how the malware operates. First, let's throw the binary in PEiD and run the Krypto ANALyzer plugin on it.

We see there are two references. `ADLER32` is an algorithm for calculating checksums and `aPLib` is a compression algorithm.
### Cutting a quick glance at various functions
By cutting a quick glance at some of the functions, we see a lot of ... callable global dword values which are uninitialized. This is a strong sign that there is some kind of runtime function resolving.
<div>
<img src="https://hackmd.io/_uploads/HJbHVGtrC.png" width="340" />
<img src="https://hackmd.io/_uploads/BkTL4ztHC.png" width="360" />
</div>
- At `sub_40132c` we can see the Base64 alphabet. Probably Base64 encoding is involved in the ransomware.
- At `sub_4017ae` we can see that the PEB structure is read and more specifically the `InLoadOrderModuleList` field. This is usually done by malware to get the base address of a loaded DLL by avoiding the use of WinAPI functions such as `LoadLibrary` or `GetModuleHandle`. We are already thinking that the malware resolves all WinAPI functions on the runtime by utilizing the API hashing technique.
- The function `sub_401000` is most likely the actual hash function. By researching the constants we find that this hash function is also known as the `Adler32` checksum.
Let's start reverse engineering the side functions instead of going directly to the core flow of the malware. Adding more labels will slowly help us understand how the malware works.
### `sub_4017AE` (API Resolver)
By converting the variables to the proper structures, we get a nice decompilation.

The function `to_lowercase` takes the DLL name as input and converts all the letters to lowercase.
The code in the picture does the following:
1. Iterates through each module in the `InLoadOrderModuleList`.
2. Converts its name to lowercase
3. Hashes it and
4. Checks the result against the target DLL hash.
The rest function looks like this:

Note that the following casts were performed to get this nice decompilation.
| Variable name | Cast |
| -------- | -------- |
| export_table |IMAGE_EXPORT_DIRECTORY* |
| Flink | LDR_DATA_TABLE_ENTRY* |
- Check my repository for the Python implementation of the API resolving. By running the code we get the following output:
```
[+] found target dll => kernel32.dll
[+] 0x1e2b04a4 => LoadLibraryA
[+] 0x288b0588 => GetProcAddress
```
Therefore we can rename the following global variables:

### `sub_4018D1` (Decrypting more API names)
In fact, `sub_4018d1` is the first function being called in the entry point of the second stage which is `sub_40911d`.
After that, there are a few calls to `sub_401867`. The third argument is a large array of `DWORDs`.

Cutting a quick glance at `sub_401867` we can see that it calls the `decrypt` function that we analyzed in stage 1. Moreover, it calls the dynamically resolved `LoadLibraryA` and `GetProcAddress`.
This is a good hint for what this function does in a high level. The encrypted values in the array are *probably* encrypted function names, so this function decrypts them, calls `GetProcAddress` some number of times (depending on the first argument) and store their base address in the second argument.

As one can see, reverse engineering involves a lot of (educational) guessing :)
We will need some dynamic analysis to understand how this works precisely. Interestingly, `LoadLibraryA` can take just the name of the dll without the extension. The first bytes of the large array are `06 00 00 00 C7 46 10 BF 0D 3B`. The first dword determines the size of the bytes that will be decrypted by `decrypt`; in this case, that's `0x6` and the encrypted bytes are `C7 46 10 BF 0D 3B`. We can run our custom decryptor to decrypt those. We get:
```
b'ntdll\x00'
```
After some debugging, we understand a pattern.

The data in `.data` segment follow the pattern below:
| Offset | Size | Encrypted Data |
| ---------- | -------- | -------- |
| `0x40c00c` | `0x06` | - |
| `0x40c010` | - |`c7 46 10 bf 0d 3b` |
| `0x40c016` | `0x10` | - |
| `0x40c01a` | - | `fb 46 18 92 0d 57 45 4e 30 97 18 8f b6 8a 4d 60` |
Having implemented the API resolver locally, I understood that the first parameter of `sub_401867` is the number of APIs that the malware extracts from the current DLL. For example, `47` APIs will be extracted from the first dll `ntdll`, `44` from the second `kernel32` etc.
By running the resolver we get the following output:
```
[+] buffer was successfully initialized
[+] found target dll => kernel32.dll
[+] 0x1e2b04a4 => LoadLibraryA
[+] 0x288b0588 => GetProcAddress
[+] decrypted dll => ntdll.dll (total=47)
[+] decrypted function => RtlAllocateHeap
[+] decrypted function => RtlReAllocateHeap
... REDACTED ...
[+] decrypted dll => kernel32.dll (total=44)
[+] decrypted function => SetFileAttributesW
[+] decrypted function => GetFileAttributesW
... REDACTED ...
[+] decrypted dll => advapi32.dll (total=23)
[+] decrypted function => LookupAccountSidW
[+] decrypted function => SetEntriesInAclW
... REDACTED ...
[+] decrypted dll => user32.dll (total=8)
[+] decrypted function => GetDC
[+] decrypted function => ReleaseDC
... REDACTED ...
[+] decrypted dll => gdi32.dll (total=13)
[+] decrypted function => CreateFontW
[+] decrypted function => GetDeviceCaps
... REDACTED ...
[+] decrypted dll => ole32.dll (total=6)
[+] decrypted function => CoInitialize
[+] decrypted function => CoUninitialize
... REDACTED ...
[+] decrypted dll => oleaut32.dll (total=2)
[+] decrypted function => VariantInit
[+] decrypted function => VariantClear
[+] decrypted dll => shell32.dll (total=5)
[+] decrypted function => SHTestTokenMembership
[+] decrypted function => CommandLineToArgvW
... REDACTED ...
[+] decrypted dll => shlwapi.dll (total=4)
[+] decrypted function => PathFindExtensionW
[+] decrypted function => PathIsNetworkPathW
... REDACTED ...
[+] decrypted dll => wininet.dll (total=8)
[+] decrypted function => InternetOpenW
[+] decrypted function => InternetConnectW
... REDACTED ...
[+] decrypted dll => netapi32.dll (total=6)
[+] decrypted function => NetGetJoinInformation
[+] decrypted function => NetShareEnum
... REDACTED ...
[+] decrypted dll => wtsapi32.dll (total=1)
[+] decrypted function => WTSQueryUserToken
[+] decrypted dll => activeds.dll (total=4)
[+] decrypted function => ADsOpenObject
[+] decrypted function => ADsBuildEnumerator
... REDACTED ...
[+] decrypted dll => userenv.dll (total=2)
[+] decrypted function => CreateEnvironmentBlock
[+] decrypted function => DestroyEnvironmentBlock
```
The second argument of `sub_401867` is a list of function pointers that will be initialized with each call to the function. Having decrypted the function names, we will write an IDA Python script that automatically renames the function pointers with the corresponding function name so that we improve our static analysis experience.
Before:

After:

### Stage 2 - Entry Point
We have to spend some time to labeling things around by researching known symbols etc. In summary, the malware initially tries to perform privilege escalation by checking whether the current user belongs to the administrators group, or whether the current account name is `NT AUTHORITY`.
The entry point function looks like this:

### Decrypting the resource section
We already talked about `dynamic_resolve_api_functions` so let's move on to decrypting the resource section which is done in the function `decrypt_rsrc_section_and_init_vars`. In this function, the resource section is decrypted, then APLib decompressed and then utilized to initialize some variables. We will use an online [implementation](https://github.com/snemes/aplib/blob/master/src/aplib.py) of APLib decompression. Eventually we get the following decrypted string:
```
b'\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa9\xcf\x9b\x015\xf9\x10\xd6\xb1\xd7\x1d\x8d\xd3\xb8\xba\xf5l>\xad\xc7\x03\xa14\x96!CaZk[\xbb\xeb+\x86\x1e\xf0\xf6\x8f\xf9\xb8\xd1&\xee(Q\xd3\x0c-\xd5l\xa0GJ(\x0c}\xb0\xba@\x13h\x96\xec\x8bg\x08q\x84\xf5\naC\x8f>\x9cjY\xe4r\xe7r5\xdb\n\x8fN\x87\xf5\x95x\xb2\x9a\xdb\xccu\xa4\\\xb2\xf81!SF\n\x8c\x113\x13\xed\xd8N\x11\xd5K\x933vc\x81\xd7\xb8\xaa\xe5cq\x9a\x1ds0601ac206b9e361\x00,\x8a\xa3\x13\x88%&A\xdb\x99H\xe3\xd6\xef`\x9f\x02\x01\x00\x01\x00\x00\x00\x00\x00\x01\x01\x01\x01\x01\x00\x00\x01\x01\x01\x01\x00\x000\x00\x00\x00\xdd\x02\x00\x00\x8a\x04\x00\x00o\x07\x00\x00\xa8\x07\x00\x00\xc9\x07\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8e\x08\x00\x00\x87\t\x00\x00JAByAGUAYwB5AGMAbABlAC4AYgBpAG4AAABjAG8AbgBmAGkAZwAuAG0AcwBpAAAAJAB3AGkAbgBkAG8AdwBzAC4AfgBiAHQAAAAkAHcAaQBuAGQAbwB3AHMALgB+AHcAcwAAAHcAaQBuAGQAbwB3AHMAAABhAHAAcABkAGEAdABhAAAAYQBwAHAAbABpAGMAYQB0AGkAbwBuACAAZABhAHQAYQAAAGIAbwBv[LARGE BASE64 STRING REDACTED]'
```
At first sight, the starting bytes do not make sense but the Base64 strings are definitely interesting, if we try decoding them we get the following utf-16 decoded strings:
```
[+] buffer was successfully initialized
[+] str = $recycle.binconfig.msi$windows.~bt$windows.~wswindowsappdataapplication databootgooglemozillaprogram filesprogram files (x86)programdatasystem volume informationtor browserwindows.oldintelmsocacheperflogsx64dbgpublicall usersdefault
[+] str = autorun.infboot.inibootfont.binbootsect.bakdesktop.iniiconcache.dbntldrntuser.datntuser.dat.logntuser.inithumbs.dbtest_white.txttest_new_white.txt
[+] str = 386advanibatbincabcmdcomcplcurdeskthemepackdiagcabdiagcfgdiagpkgdlldrvexehlpiclicnsicoicsidxldflnkmodmpamscmspmsstylesmsunlsnomediaocxprfps1romrtpscrshssplsysthemethemepackwpxlockkeyhtamsipdblog1log2regtrans-msdesklinkblf
[+] str = backuphere_backups
[+] str = sqlsqlite
[+] str = vmcompute.exevmms.exevmwp.exesvchost.exeTeamViewer.exeexplorer.exe
[+] str = Welcome to Dark Side!
All Your Files Are Encrypted!
Find %s And Follow Instructions!
```
Finally, there is a UTF-8 decoded string that looks like a message left by the malware authors for their victims. Later we will find out that they save this in a file `README.txt`:

### Decrypting the data section strings
After some testing, we realize that the entire data section can be decrypted with the same way as we [resolved](#sub_4018D1-Decrypting-more-API-names) the API names. So I did with the `decrypt_data_section.py` script.
```
[+] 0x40c004 => 2.0.0.0
. . .
[REDACTED API names]
. . .
[+] 0x40ce73 => SOFTWARE\Microsoft\Cryptography
[+] 0x40ceb7 => MachineGuid
[+] 0x40ced3 => NT AUTHORITY
[+] 0x40cef1 => AUTORITE NT
[+] 0x40cf0d => b'N\x00T\x00-\x00A\x00U\x00T\x00O\x00R\x00I\x00T\x00\xc4\x00T\x00\x00\x00'
[+] 0x40cf2b => dllhost.exe
[+] 0x40cf47 => Elevation:Administrator!new:
[+] 0x40cf85 => {3E5FC7F9-9A51-4367-9063-A120244FBEC7}
[+] 0x40cfd7 => b'tm\xddn\x07\xc0uN\xb7j\xe5t\t\x95\xe2L'
[+] 0x40cfeb => README%s.TXT
[+] 0x40d009 => Control Panel\Desktop
[+] 0x40d039 => WallPaper
[+] 0x40d051 => WallpaperStyle
[+] 0x40d073 => b'\x00\x00\x01\x00\x05\x00@@\x00\x00\x01\x00 \x00(B\x00\x00V\x00\x00\x0000\x00\x00\x01\x00 \x00\xa8%\x00\x00~B\x00\x00 \x00\x00\x01\x00 \x00\xa8\x10\x00\x00&h\x00\x00\x18\x18\x00\x00\x01\x00 \x00\x88\t\x00\x00\xcex\x00\x00\x10\x10\x00\x00\x01\x00 \x00h\x04\x00\x00V\x82\x00\x00(\x00\x00\x00@\x00\x00\x00\x80\x00\x00\x00\x01\x00 \x00\x00\x00\x00\x00\x00B\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00222\x00222\x02222\x03222\x04222\x05222\x05222\x04222\x03222\x02222\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00 ... REDACTED ...'
[+] 0x40e730 => \DefaultIcon
[+] 0x40e74e => b'\x01\x14\x02\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00F'
[+] 0x40e762 => b'\xf9\x14\x02\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00F'
[+] 0x40e776 => b'\x0b\x01\x00\x00\x00\x00\x00\x00\xc0\x00\x00\x00\x00\x00\x00F'
[+] 0x40e78a => Global\%.8x%.8x%.8x%.8x
[+] 0x40e7be => /C DEL /F /Q
[+] 0x40e7de => ComSpec
[+] 0x40e7f2 => >> NUL
[+] 0x40e806 => b'\xccU\x85\xcb(\x91\xd1\x11\xad\x9b\x00\xc0O\xd8\xfd\xff'
[+] 0x40e81a => b'\x87\xa6\x12\xdc\x7fs\xcf\x11\x88M\x00\xaa\x00K.$'
[+] 0x40e82e => ROOT\CIMV2
[+] 0x40e848 => WQL
[+] 0x40e854 => SELECT * FROM Win32_ShadowCopy
[+] 0x40e896 => ID
[+] 0x40e8a0 => Win32_ShadowCopy.ID='%s'
[+] 0x40e8d6 => b'MZ\x90\x00\x03\x00\x00\x00\x04\x00\x00\x00\xff\xff\x00\x00\xb8\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x0e\x1f\xba\x0e\x00\xb4\t\xcd!\xb8\x01L\xcd!This program cannot be run in DOS mode.\r\r\n$\x00\x00\x00\x00\x00\x00\x00PE\x00\x00d\x86\x05\x00\xdb\xbb\x9a_\x00\x00\x00\x00\x00\x00\x00\x00\xf0\x00"\x00\x0b\x02\x0c\x00\x00\x04\x00\x00\x00\n\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x10\x00\x00\x00\x00\x00@\x01\x00\x00\x00\x00\x10\x00\x00\x00\x02\x00\x00\x05\x00\x02\x00\x00\x00\x00\x00\x05\x00\x02\x00\x00\x00\x00\x00\x00`\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x02\x00`\x81\x00\x00\x10\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00t \x00\x00d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00@\x00\x00\x0c\x00\x00\x00\x00\x00\x00\x00 ... REDACTED ...'
[+] 0x40eca2 => b'\xd9x\xf9\xc4\x19\xdd\xb5\xed(\xe9\xfdyJ\xa0\xd8\x9d\xc6~7\x83+vS\x8ebLd\x88D\x8b\xfb\xa2\x17\x9aY\xf5\x87\xb3O\x13aEm\x8d\t\x81}2\xbd\x8f@\xeb\x86\xb7{\x0b\xf0\x95!"\\kN\x82T\xd6e\x93\xce`\xb2\x1csV\xc0\x14\xa7\x8c\xf1\xdc\x12u\xca\x1f;\xbe\xe4\xd1B=\xd40\xa3<\xb6&o\xbf\x0e\xdaFi\x07W\'\xf2\x1d\x9b\xbc\x94C\x03\xf8\x11\xc7\xf6\x90\xef>\xe7\x06\xc3\xd5/\xc8f\x1e\xd7\x08\xe8\xea\xde\x80R\xee\xf7\x84\xaar\xac5Mj*\x96\x1a\xd2qZ\x15ItK\x9f\xd0^\x04\x18\xa4\xec\xc2\xe0An\x0fQ\xcb\xcc$\x91\xafP\xa1\xf4p9\x99|:\x85#\xb8\xb4z\xfc\x026[%U\x971-]\xfa\x98\xe3\x8a\x92\xae\x05\xdf)\x10gl\xba\xc9\xd3\x00\xe6\xcf\xe1\x9e\xa8,c\x16\x01?X\xe2\x89\xa9\r84\x1b\xab3\xff\xb0\xbbH\x0c_\xb9\xb1\xcd.\xc5\xf3\xdbG\xe5\xa5\x9cw\n\xa6 h\xfe\x7f\xc1\xad'
[+] 0x40eda6 => b'\xd0V\x82\xfd\x15\xfd\xce\x11\xab\xc4\x02`\x8c\x9euS'
[+] 0x40edba => b'\xd0w\x16\x00\x16\xfd\xce\x11\xab\xc4\x02`\x8c\x9euS'
[+] 0x40edce => "os":{
"lang":"%s",
"username":"%s",
"hostname":"%s",
"domain":"%s",
"os_type":"windows",
"os_version":"%s",
"os_arch":"%s",
"disks":"%s",
"id":"%s"
}
[+] 0x40ef14 => Control Panel\International
[+] 0x40ef50 => LocaleName
[+] 0x40ef6a => sLanguage
[+] 0x40ef82 => SOFTWARE\Microsoft\Windows NT\CurrentVersion
[+] 0x40efe0 => ProductName
[+] 0x40effc => ProductId
[+] 0x40f014 => ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
[+] 0x40f057 => Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:79.0) Gecko/20100101 Firefox/80.0
[+] 0x40f0f7 =>
Accept: */*
Connection: keep-alive
Accept-Encoding: gzip, deflate, br
Content-Type: text/plain
[+] 0x40f1c3 => {
"bot":{
"ver":"%s",
"uid":"%s"
},
%s
}
[+] 0x40f1f6 => {
"id":"%s",
"uid":"%s",
"enc-num":"%u",
"enc-size":"%s",
"skip-num":"%u",
"elapsed-time":"%u.%u"
}
```
Some strings are not readable but we have enough info to do some more labelling in IDA.
## TODO
- Further and deeper analysis for the Privilege Escalation part.
## Appendix
The source code for the entire analysis can be found on my GitHub [repository](https://github.com/Tressos-Aristomenis/malware-analysis/tree/main/DarkSide).