www.huntress.com Open in urlscan Pro
2606:2c40::c73c:671c  Public Scan

URL: https://www.huntress.com/blog/hackers-no-hashing-randomizing-api-hashes-to-evade-cobalt-strike-shellcode-detection
Submission: On October 04 via api from DE — Scanned from DE

Form analysis 4 forms found in the DOM

/hs-search-results

<form action="/hs-search-results" data-hs-cf-bound="true">
  <div class="pwr--relative">
    <input type="text" id="pwr-js-burger-search__input" class="pwr-burger-search__input hs-search-field__input" name="term" autocomplete="off" aria-label="Search" placeholder="Type search here">
    <button class="pwr-search-field__icon" type="submit"><span id="hs_cos_wrapper_module_167327601750737_" class="hs_cos_wrapper hs_cos_wrapper_widget hs_cos_wrapper_type_icon" style="" data-hs-cos-general-type="widget" data-hs-cos-type="icon"><svg
          version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" aria-hidden="true">
          <g id="search2_layer">
            <path
              d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z">
            </path>
          </g>
        </svg></span></button>
  </div>
</form>

/hs-search-results

<form action="/hs-search-results" data-hs-cf-bound="true">
  <input type="text" id="pwr-js-burger-search__input" class="" name="term" autocomplete="off" aria-label="Search" placeholder="Search">
</form>

/hs-search-results

<form action="/hs-search-results" data-hs-cf-bound="true">
  <div class="pwr--relative">
    <input type="text" id="pwr-header-search__input" class="pwr-header-search__input hs-search-field__input" name="term" autocomplete="off" aria-label="Search" placeholder="Type search here. Hit enter to submit or escape to close.">
    <button class="pwr-search-field__icon" type="submit"><span id="hs_cos_wrapper_module_167327601750737_" class="hs_cos_wrapper hs_cos_wrapper_widget hs_cos_wrapper_type_icon" style="" data-hs-cos-general-type="widget" data-hs-cos-type="icon"><svg
          version="1.0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" aria-hidden="true">
          <g id="search3_layer">
            <path
              d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z">
            </path>
          </g>
        </svg></span></button>
    <a href="#" id="pwr-js-header-search__close" class="pwr-header-search__close">
                  <span class="pwr-header-search__close-icon"></span>
                </a>
  </div>
</form>

POST https://forms.hsforms.com/submissions/v3/public/submit/formsnext/multipart/3911692/196be66c-f1bb-4156-af05-2952954526cd

<form id="hsForm_196be66c-f1bb-4156-af05-2952954526cd_6056" method="POST" accept-charset="UTF-8" enctype="multipart/form-data" novalidate=""
  action="https://forms.hsforms.com/submissions/v3/public/submit/formsnext/multipart/3911692/196be66c-f1bb-4156-af05-2952954526cd"
  class="hs-form-private hsForm_196be66c-f1bb-4156-af05-2952954526cd hs-form-196be66c-f1bb-4156-af05-2952954526cd hs-form-196be66c-f1bb-4156-af05-2952954526cd_06045364-21c8-4ab8-abef-7ca2b7ba2fe9 hs-form stacked hs-custom-form"
  target="target_iframe_196be66c-f1bb-4156-af05-2952954526cd_6056" data-instance-id="06045364-21c8-4ab8-abef-7ca2b7ba2fe9" data-form-id="196be66c-f1bb-4156-af05-2952954526cd" data-portal-id="3911692" data-hs-cf-bound="true">
  <div class="hs_email hs-email hs-fieldtype-text field hs-form-field"><label id="label-email-196be66c-f1bb-4156-af05-2952954526cd_6056" class="" placeholder="Enter your Work Email (required)"
      for="email-196be66c-f1bb-4156-af05-2952954526cd_6056"><span>Work Email (required)</span><span class="hs-form-required">*</span></label>
    <legend class="hs-field-desc" style="display: none;"></legend>
    <div class="input"><input id="email-196be66c-f1bb-4156-af05-2952954526cd_6056" name="email" required="" placeholder="" type="email" class="hs-input" inputmode="email" autocomplete="email" value=""></div>
  </div>
  <div class="hs_submit hs-submit">
    <div class="hs-field-desc" style="display: none;"></div>
    <div class="actions"><input type="submit" class="hs-button primary large" value="Subscribe"></div>
  </div><input name="hs_context" type="hidden"
    value="{&quot;embedAtTimestamp&quot;:&quot;1696427275716&quot;,&quot;formDefinitionUpdatedAt&quot;:&quot;1674667130846&quot;,&quot;lang&quot;:&quot;en&quot;,&quot;embedType&quot;:&quot;REGULAR&quot;,&quot;clonedFromForm&quot;:&quot;6da6c019-9d2a-47d7-8966-09563d0875cf&quot;,&quot;userAgent&quot;:&quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.5938.132 Safari/537.36&quot;,&quot;pageTitle&quot;:&quot;Hackers No Hashing: Randomizing API Hashes to Evade Cobalt Strike Shellcode Detection&quot;,&quot;pageUrl&quot;:&quot;https://www.huntress.com/blog/hackers-no-hashing-randomizing-api-hashes-to-evade-cobalt-strike-shellcode-detection&quot;,&quot;pageId&quot;:&quot;66424554568&quot;,&quot;isHubSpotCmsGeneratedPage&quot;:true,&quot;canonicalUrl&quot;:&quot;https://www.huntress.com/blog/hackers-no-hashing-randomizing-api-hashes-to-evade-cobalt-strike-shellcode-detection&quot;,&quot;contentType&quot;:&quot;blog-post&quot;,&quot;hutk&quot;:&quot;56b18107339c374c18ddbf164521d6fc&quot;,&quot;__hsfp&quot;:1666088104,&quot;__hssc&quot;:&quot;1139630.1.1696427276870&quot;,&quot;__hstc&quot;:&quot;1139630.56b18107339c374c18ddbf164521d6fc.1696427276869.1696427276869.1696427276869.1&quot;,&quot;formTarget&quot;:&quot;#hs_form_target_module_155266670085300_subscribe&quot;,&quot;formInstanceId&quot;:&quot;6056&quot;,&quot;pageName&quot;:&quot;Hackers No Hashing: Randomizing API Hashes to Evade Cobalt Strike Shellcode Detection&quot;,&quot;locale&quot;:&quot;en&quot;,&quot;timestamp&quot;:1696427276885,&quot;originalEmbedContext&quot;:{&quot;portalId&quot;:&quot;3911692&quot;,&quot;formId&quot;:&quot;196be66c-f1bb-4156-af05-2952954526cd&quot;,&quot;region&quot;:&quot;na1&quot;,&quot;target&quot;:&quot;#hs_form_target_module_155266670085300_subscribe&quot;,&quot;isBuilder&quot;:false,&quot;isTestPage&quot;:false,&quot;isPreview&quot;:false,&quot;formInstanceId&quot;:&quot;6056&quot;,&quot;formsBaseUrl&quot;:&quot;/_hcms/forms&quot;,&quot;css&quot;:&quot;&quot;,&quot;isMobileResponsive&quot;:true,&quot;pageName&quot;:&quot;Hackers No Hashing: Randomizing API Hashes to Evade Cobalt Strike Shellcode Detection&quot;,&quot;pageId&quot;:&quot;66424554568&quot;,&quot;contentType&quot;:&quot;blog-post&quot;,&quot;formData&quot;:{&quot;cssClass&quot;:&quot;hs-form stacked hs-custom-form&quot;},&quot;isCMSModuleEmbed&quot;:true},&quot;correlationId&quot;:&quot;06045364-21c8-4ab8-abef-7ca2b7ba2fe9&quot;,&quot;renderedFieldsIds&quot;:[&quot;email&quot;],&quot;captchaStatus&quot;:&quot;NOT_APPLICABLE&quot;,&quot;emailResubscribeStatus&quot;:&quot;NOT_APPLICABLE&quot;,&quot;isInsideCrossOriginFrame&quot;:false,&quot;source&quot;:&quot;forms-embed-1.3812&quot;,&quot;sourceName&quot;:&quot;forms-embed&quot;,&quot;sourceVersion&quot;:&quot;1.3812&quot;,&quot;sourceVersionMajor&quot;:&quot;1&quot;,&quot;sourceVersionMinor&quot;:&quot;3812&quot;,&quot;_debug_allPageIds&quot;:{&quot;embedContextPageId&quot;:&quot;66424554568&quot;,&quot;analyticsPageId&quot;:&quot;66424554568&quot;,&quot;pageContextPageId&quot;:&quot;66424554568&quot;},&quot;_debug_embedLogLines&quot;:[{&quot;clientTimestamp&quot;:1696427275828,&quot;level&quot;:&quot;INFO&quot;,&quot;message&quot;:&quot;Retrieved customer callbacks used on embed context: [\&quot;getExtraMetaDataBeforeSubmit\&quot;]&quot;},{&quot;clientTimestamp&quot;:1696427275831,&quot;level&quot;:&quot;INFO&quot;,&quot;message&quot;:&quot;Retrieved pageContext values which may be overriden by the embed context: {\&quot;pageTitle\&quot;:\&quot;Hackers No Hashing: Randomizing API Hashes to Evade Cobalt Strike Shellcode Detection\&quot;,\&quot;pageUrl\&quot;:\&quot;https://www.huntress.com/blog/hackers-no-hashing-randomizing-api-hashes-to-evade-cobalt-strike-shellcode-detection\&quot;,\&quot;userAgent\&quot;:\&quot;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.5938.132 Safari/537.36\&quot;,\&quot;pageId\&quot;:\&quot;66424554568\&quot;,\&quot;isHubSpotCmsGeneratedPage\&quot;:true}&quot;},{&quot;clientTimestamp&quot;:1696427275833,&quot;level&quot;:&quot;INFO&quot;,&quot;message&quot;:&quot;Retrieved countryCode property from normalized embed definition response: \&quot;DE\&quot;&quot;},{&quot;clientTimestamp&quot;:1696427276878,&quot;level&quot;:&quot;INFO&quot;,&quot;message&quot;:&quot;Retrieved analytics values from API response which may be overriden by the embed context: {\&quot;hutk\&quot;:\&quot;56b18107339c374c18ddbf164521d6fc\&quot;,\&quot;canonicalUrl\&quot;:\&quot;https://www.huntress.com/blog/hackers-no-hashing-randomizing-api-hashes-to-evade-cobalt-strike-shellcode-detection\&quot;,\&quot;contentType\&quot;:\&quot;blog-post\&quot;,\&quot;pageId\&quot;:\&quot;66424554568\&quot;}&quot;}]}"><iframe
    name="target_iframe_196be66c-f1bb-4156-af05-2952954526cd_6056" style="display: none;"></iframe>
</form>

Text Content

This website stores cookies on your computer. These cookies are used to improve
your website and provide more personalized services to you, both on this website
and through other media. To find out more about the cookies we use, see our
Privacy Policy.

Accept Decline
Skip to content
Close
 * Platform
    * Platform Overview Cybersecurity for the 99%
    * Managed EDR Stop Attacks with Process Insights
    * SOC 24/7 Human Threat Hunting
    * Persistent Footholds Find Attackers Hiding in Plain Sight
    * Managed Antivirus Strengthen Frontline Protection
   
    * MDR for Microsoft 365 Microsoft 365 Threat Detection
    * Ransomware Canaries Detect Ransomware Faster
    * External Recon Scan Ports & Potential Exposures
    * Security Awareness Training Sharpen Your Employees' Defenses
    * Partner Enablement Grow Your Cybersecurity Practice
   
   See The Huntress Managed Security Platform in Action
   
   Ask questions, explore the dashboard and more
   
   Book a demo >
   
   
 * Who We Serve
    * Managed Service Providers Empowering MSPs to Secure End Customers
    * Value Added Resellers A Complete ready-to-sell platform for VARs
    * Businesses & IT Teams Empowering IT to Bridge the Cyber Gap

 * Resources
    * Cybersecurity Education Webinars, eBooks and More
    * Upcoming Events Tradeshows and Live Industry Events
    * Tradecraft Tuesday No Product. No Pitches. Just Tradecraft.
    * Success Stories Case Studies & Testimonials
    * Community Fireside Chat Check out the latest Fireside Chats

 * Blog
 * Company
    * Leadership Team Meet the Team Taking the Fight to Hackers
    * Press Media Coverage, Interviews & More
    * Careers Join the Hunt - We're Hiring!
    * Contact Us Talk to Sales, Get Help or Say Hello :)

 * Partners
    * Partner Login Access Your Huntress Dashboard
    * Support Documentation Technical Product Support, FAQs & More


SEARCH

Free Trial
 * Platform
    * Platform Overview Cybersecurity for the 99%
    * Managed EDR Stop Attacks with Process Insights
    * SOC 24/7 Human Threat Hunting
    * Persistent Footholds Find Attackers Hiding in Plain Sight
    * Managed Antivirus Strengthen Frontline Protection
   
    * MDR for Microsoft 365 Microsoft 365 Threat Detection
    * Ransomware Canaries Detect Ransomware Faster
    * External Recon Scan Ports & Potential Exposures
    * Security Awareness Training Sharpen Your Employees' Defenses
    * Partner Enablement Grow Your Cybersecurity Practice
   
   See The Huntress Managed Security Platform in Action
   
   Ask questions, explore the dashboard and more
   
   Book a demo >
   
   
 * Who We Serve
    * Managed Service Providers Empowering MSPs to Secure End Customers
    * Value Added Resellers A Complete ready-to-sell platform for VARs
    * Businesses & IT Teams Empowering IT to Bridge the Cyber Gap

 * Resources
    * Cybersecurity Education Webinars, eBooks and More
    * Upcoming Events Tradeshows and Live Industry Events
    * Tradecraft Tuesday No Product. No Pitches. Just Tradecraft.
    * Success Stories Case Studies & Testimonials
    * Community Fireside Chat Check out the latest Fireside Chats

 * Blog
 * Company
    * Leadership Team Meet the Team Taking the Fight to Hackers
    * Press Media Coverage, Interviews & More
    * Careers Join the Hunt - We're Hiring!
    * Contact Us Talk to Sales, Get Help or Say Hello :)

 * Partners
    * Partner Login Access Your Huntress Dashboard
    * Support Documentation Technical Product Support, FAQs & More

Free Trial



Matthew Brennan 02.16.2022 17 min read


HACKERS NO HASHING: RANDOMIZING API HASHES TO EVADE COBALT STRIKE SHELLCODE
DETECTION

Previous Post

Next Post
Share on Twitter
Share on LinkedIn
Share on Facebook
Share on Reddit

While researching Application Programming Interface (API) hashing techniques
commonly used in popular malware (particularly Metasploit and Cobalt Strike),
the Huntress ThreatOps Team found that hackers are sticking to the default
settings that come with hacker tooling. Our research has suggested that many
detection/antivirus (AV) vendors have realized this and have built their
detection logic around the presence of artifacts left by these defaults.

With a bit of tinkering and curiosity, we found that if trivial changes are made
to those defaults, a large number of vendors will fail to detect otherwise
simple and commodity malware. As a result, simple and commodity malware suddenly
starts approaching FUD status. 😅

In this post, we’ll dive into how we discovered those minor changes and how you
can implement them yourself to test your detection tooling. We have included a
script that automates a large portion of this process, as well as a YARA rule
which will detect most modifications made using this technique. 

Whether you’re on Team Red, Team Blue, or anywhere in between, we hope this blog
provides some useful insight into an interesting bypass and detection
technique. 

If screenshots like this excite you, read on.



Technical TL;DR

Our research suggests that a large number of vendors have based their Cobalt
Strike and Metasploit shellcode detection capability on the presence of ROR13
API hashes. By making trivial changes to the ROR13 logic and updating the hashes
accordingly, a large number of vendor detections can be seemingly bypassed
without breaking code functionality. 

In order to detect this behavior, YARA rules that previously detected ROR13
hashes can be modified to detect blocks of code associated with typical
ROR-based hashing. This move to detection of ROR blocks can provide a more
robust means of detection than detecting on hashes alone.

Graphical TL;DR




BUT FIRST, A QUICK REFRESHER ON API HASHING

API hashing is a technique often used by malware to disguise the usage of
suspicious APIs (essentially functions) from the prying eyes of a detection
analyst or security engineer.

Traditionally, if a piece of software needed to call a function of the Windows
API (for example, if it wanted to use CreateFileW to create a file), the
software would need to reference the API name “directly” in the code. This
typically looks like the screenshot below.



By “directly” using an API, the name of the API is left present in the code.
This enables an analyst to easily identify what the piece of suspicious code
might be doing. In this case, that suspicious action is creating or opening a
file.

When a “direct” API call is used, it also leaves the API present in the import
table of the file. This import table can be easily viewed within PeStudio or any
other analysis tool and looks like the screenshot below. Note we can also see
the other APIs that the malware is using. 



If you’re an attacker trying to hide the creation of a malicious file, then
neither of these situations is ideal. It would be far better if you could hide
your API usage away from an analyst who may see `CreateFileW` and then go
searching for suspicious files. 

If an attacker doesn’t want their API to show up in an import table, then the
alternative is to load the APIs dynamically (when the malware actually runs).
The easiest way to do this is to use a Windows function called GetProcAddress.
This method avoids leaving suspicious APIs in the import table as we saw above
in PeStudio.

A quick caveat using dynamic loading is that although the original suspicious
API `CreateFileW` would be absent from the import table, the usage of
“GetProcAddress” will now be in the import table instead. A keen-eyed analyst
who sees the presence of GetProcAddress can run the malware in a debugger and
find out what is being loaded. 

With a well-placed breakpoint, an analyst can view the arguments being passed to
the GetProcAddress function and find out what is being loaded. Upon running the
suspicious code, a debugger would then present something like this, revealing
the usage of CreateFileW and indicating to an analyst that they should go
looking for suspicious files that may have been created. 



A common means of avoiding both of these situations is to use a technique known
as API hashing. 

This is a technique where attackers will implement their own version of
GetProcAddress that will load a function by a hash rather than a name. This
avoids leaving suspicious APIs in import tables and avoids using suspicious APIs
that can be easily viewed in a debugger. 

If an analyst wants to find out what’s going on, they would need to get familiar
with x86 assembly. 


THE TL;DR TAKEAWAYS

 * There are multiple ways to load suspicious APIs; however, most will leave
   easy-to-find indicators for malware analysts
 * API hashing uses unique hashes rather than function names. This hinders the
   analysis of function names that target strings or arguments at breakpoints


HASHING INDICATORS

Now that we know why someone might want to use API hashing, we can take a look
at how to deal with it when analyzing suspicious code. It is relatively easy to
identify, as you will often see random hex values pushed to the stack, followed
by an immediate call to a register value. 

Typically, this call will resemble call rbp, but the register could technically
be any value. Below is a screenshot taken from some Cobalt Strike shellcode
where API hashing was used. 



In the screenshot, we can see two hex values pushed to a register prior to a
`call rbp`. These are the hashes that will be resolved and used to load
suspicious functions used by malware. 

The hashes above correspond to 0x726774c (LoadLibraryA) and 0xa779563a
(InternetOpenA). 

If you were to find the value of rbp in this situation, you would find that it
points to the “manual” implementation of GetProcAddress, which then resolves the
hash and calls the associated API.

At a high level, the hash resolution logic is similar to the below pseudo code.



Additionally, you would find that the Calculatehash Logic, which is largely
based on the ror13 hashing algorithm, is similar to this. The value of 0xd (13)
is important here as later we will change this value to generate new hashes that
can bypass detection.



This is a simplification, and the actual logic is slightly more complex. If
you’re interested in understanding the logic in more detail, there are some
great write-ups on the topic from Nviso and Avast.

After analyzing numerous malware samples using API hashing in shellcode, we
noticed that similar malware families will often use extremely similar hashing
logic to calculate and resolve API hashes. 

In particular, we found that most Cobalt Strike, Msfvenom and Metasploit use
exactly the same hashing logic for resolving API hashes. Since they utilize the
same logic, they produce the same hashes for any given function.

For example, both Cobalt Strike and Metasploit will use the hash 0x726774c when
resolving “LoadLibraryA”.


THE TL;DR TAKEAWAYS

 * API hashing is relatively simple to identify through static analysis,
   although it is difficult to find what the hashes resolve to
 * Similar hashing logic is often used across similar malware families 
 * The exact same hashing logic is often across samples from MsfVenom,
   Metasploit and Cobalt Strike


POKING A BIT FURTHER

We eventually found that it was easy to identify shellcode that was generated by
Cobalt Strike or Metasploit simply by googling the hash values present in the
code. 

If we were to google the value of 0x726774c (LoadLibraryA), we would immediately
get hits for the Metasploit framework (which shares code with Cobalt Strike). We
see the same if we google the hash for 0xa779563a (InternetOpenA).



Generating our own shellcode samples from these frameworks, we observed that the
hashes present in our payloads were consistently identifiable as those used by
Metasploit and Cobalt Strike. 


THE TL;DR TAKEAWAYS 

 * Metasploit and Cobalt Strike (at least by default) use the same API hashing
   routine and will produce the same hash values when using the same function
 * These hashes introduce unique hex values that can be used to easily identify
   the malware families by using Google 


YARA RULES

From the perspective of a security analyst or detection engineer, this was great
information. Without performing a deep dive into shellcode and assembly, we
could easily identify that a payload likely belonged to either Metasploit or
Cobalt Strike.

This got us thinking—if these hash values are unique to tools like Cobalt Strike
and Metasploit
 what if those hashes are unique enough to be used for YARA
rules?

We found a fantastic article from Avast that captured the same idea. Their
article details the use of these same API hashes to detect Cobalt Strike and
Metasploit shellcode. Below we can see a YARA rule from Avast which relies
largely on the hashes we previously identified (as well as the other hashes
required for an HTTP stager). 



Testing these YARA rules against our raw Cobalt Strike and Metasploit shellcode
(without any encoders enabled), we confirmed the Avast YARA ruleset reliably
detected and identified all of our generated payloads. Great news for Team
Blue—and great work from the Threat Intel Team at Avast. 


THE TL;DR TAKEAWAYS

 * API hashes present in shellcode are reliable indicators that can be used for
   detection
 * Vendors are actively using these indicators to detect malicious shellcode 


BUT WHAT IF THE HASHES IN THE SHELLCODE ARE CHANGED?

At face value, the usage of API hashes for detection is a great idea. But that
got us thinking, what happens if those hash values were to change?

As an initial proof-of-concept, we took our payloads and rather crudely changed
the hashes to 0x11111111. We knew this would break the shellcode as the hashes
would no longer resolve—but it would allow us to check how well the shellcode is
detected without the presence of known API hashes.

Our new shellcode would contain hashes like this in place of the actual hashes
seen before.

We then did a before and after check on a Cobalt Strike HTTP payload using
Virustotal, and found that 15 vendors failed to detect the shellcode after these
changes were made.



As a proof-of-concept, this was pretty interesting. But as an attacker, this is
largely useless. In its current modified state, the shellcode would no longer
resolve hashes and would not be able to find the APIs it requires in order to
execute—turning our shellcode into a nice digital paperweight. 


THE TL;DR TAKEAWAYS

 * At least some vendors are using API hashes to detect Cobalt Strike and
   similar malware
 * If these defaults are changed, at least some vendors will fail to detect
   previously detected payloads
 * Crudely modifying API hashes will break your code


BUT WHAT IF MODIFIED HASHES COULD RESOLVE PROPERLY?

After confirming our suspicion that vendors were using API hashes to detect
shellcode, we decided to explore what would happen if the hashes were modified
less crudely, in a way that would still enable the modified hashes to resolve
and execute. 

First, we needed to understand exactly how the hashes were generated. Our
ThreatOps team was able to discover this through a combination of the Metasploit
source code and by analyzing the assembly instructions present in samples of
shellcode. 

By nature of how hashing works, we theorized that it should only take minor
changes to the hashing logic to produce vastly different hashes. In the end,
rather than getting fancy with any entirely new hashing routines, we decided to
just change the rotation value in the existing logic from 0xd/13 to 0xf/15.

In theory, this would result in entirely new hashes, while maintaining largely
the same logic and hashing structure. 



We then created a script to generate new hashes according to our new rotation
value of 0xf. This logic can be found in the final script included in this
post. 

After generating new hash values, we then updated our shellcode to correspond to
our new hashes, and our new ror value of 0xf. Note that our shellcode structure
is still largely intact, the only thing that changed is the hash and rotation
(ror) values. 



We then confirmed that our code was still able to function as expected. This
process was vastly sped up using the Speakeasy tool from FireEye. 

Below we can see a screenshot of the APIs still successfully resolving in our
newly modified shellcode. 



Using a combination of netcat and the BlobRunner tool from OAlabs, we did an
extra check to confirm that our shellcode still worked and would “call out” as
expected.



After confirming that our code definitely still worked, we uploaded it to
VirusTotal. And found that we still had two vendors remaining, the same two
vendors from our previous dummy value testing. 



This was pretty interesting, since this was now functioning Cobalt Strike
shellcode—with 15 fewer detections than before it was modified. 

For a sanity check, we re-ran the same process using a TCP bind shell from
Metasploit (no encoders enabled). After confirming that the code still worked,
we submitted it to VirusTotal and found that 26 vendors had failed to detect the
modified payload. 





During our analysis, it was interesting to note that the two remaining vendors
differed between the modified payloads.



At this point, we also checked that the original YARA rules were no longer
detecting our payloads. And confirmed that they were no longer being detected.


THE TL;DR TAKEAWAYS

 * A large number of vendors are using default ror13 hashes to detect Cobalt
   Strike and Metasploit/Msfvenom payloads.
 * Modifying these hashes has a considerable impact on detection rates.
 * When done properly, modifying these hashes will not break shellcode
   functionality.
 * This technique works well on both Msfvenom and Cobalt Strike. Hence likely
   works on other malware families too.


SO WHAT ABOUT THOSE REMAINING VENDORS?

Rather than leave it at 2/55, we decided to tackle the two remaining vendors
detecting our shellcode. 

First, we noted that the remaining vendors were detecting generic shellcode and
not Cobalt Strike or Metasploit specifically. This led us to believe that they
were detecting generic shellcode indicators, rather than anything specific to
our family of malware. 

We theorized the following might be targeted by the remaining vendors, since
they are behaviors typically associated with shellcode. 

 * CLD/0xfc being the first instructions executed - (CLD is used to reset
   direction flags used in byte/string copy operations)
 * Suspicious calls to registers (eg call rbp)
 * Presence of library names in stack strings

To test, we slightly modified these indicators in our remaining payload. We
achieved this by

 * Moving the initial CLD instruction to another location in our shellcode, so
   that it still executed but was no longer the first instruction. (Assuming CLD
   executes before any string operations, this should have no impact on
   shellcode functionality)
 * Inserting a NOP/0x90 in place of the original CLD
 * Inserting an uppercase character in the arguments to the initial call to
   LoadLibraryA. (Since LoadLibraryA is not case sensitive, this shouldn’t break
   any functionality)

Below, we have a before and after of the modified shellcode. Note the minor
changes from “wininet” (all lower case) to “wIninet” (one upper case I). As well
as the CLD instruction now located after our pop rbp. 


We then confirmed that our shellcode still functioned, and then resubmitted it
to VirusTotal.



Finally, we had hit 0/55 detections without breaking our code.

We then checked the same with Antiscan and found that we had also hit zero
detections for our Cobalt Strike shellcode—whereas a non-modified copy had 13
detections. 

The TL;DR Takeaways

 * Vendors are definitely using API hashes to identify Cobalt Strike shellcode
 * Removing API hashes will remove most—but not all—VirusTotal detections
 * Lacking hashes, some vendors will detect on other generic shellcode
   indicators
 * We can modify these remaining indicators to achieve zero detections


AUTOMATING THE PROCESS

Since the hashing replacement process could be achieved with a byte-level search
and replace, the Huntress ThreatOps team developed a script to automate the
process. 

This script


 * Takes a raw shellcode file as input (no encoders present)
 * Automates the hash replacement process, using a randomized ror value between
   one and 255
 * Since a different ror value is used each time, a unique file and hash is
   generated upon each run, allowing multiple files to be created for a single
   piece of shellcode

We decided not to automate the process of upper-casing the library name and
moving the CLD/0xfc, so you will need to do those manually if you wish to have
zero detections. Both activities can be done manually and with minimal effort
using a hex editor. 

In order to use the script, generate a raw payload with Msfvenom or Cobalt
Strike (make sure your output is raw—do NOT use any encoders), save it to a raw
binary file and then pass it as an argument to the Python script. The script
will handle the hash replacement process with a random ror value and unique
hashes. 

An example of how to generate a simple reverse shell payload using msfvenom.
Note the use of “--format raw” to avoid using encoders. 

Below is an example of how to use the script to modify the shellcode file. 




NOTES AND LIMITATIONS OF THIS SCRIPT

 * This script only replaces hashes and the hashing logic. If there are other
   suspicious indicators in your shellcode, you may need to find your own method
   to hide them 
 * This script is NOT an encoder, so you will still need to deal with bad
   characters and null bytes within your shellcode 
 * Using a public and well-known encoder (like Shikata ga nai) will introduce
   its own indicators which will work against you 


DETECTION OF MODIFIED SHELLCODE

After confirming that our script for generating new shellcode works for
bypassing generic detections, we then developed a YARA rule for detecting
shellcode generated by our script.

Below we’ve included a copy of a YARA that detected all Msfvenom and Cobalt
Strike payloads that we tested with, regardless of whether they had been
modified by our script. In our testing, we did not hit any false positives
within our test set of binaries, but you may wish to modify the rule to fit your
needs if false positives arise. 


HOW IT WORKS

Since existing detection rules are detecting hashes generated by the hashing
routine (which can be easily changed), this rule detects the hashing routine
itself. This allows for slightly more robust detection of Cobalt Strike and
Metasploit shellcode. 

As with any detection, this rule is not bulletproof. A determined attacker can
introduce more complex changes to the hashing routine which will break this YARA
rule. We have allowed for minor variations in our rule, but more complex changes
will still defeat it. 




FINAL COMMENTS

Clearly, detections aren’t always perfect, and a well-determined attacker will
always be able to sneak through. If you’re a defender, make sure you’re always
testing and updating your detection rules (you never know what might sneak
past). 

If you’re an attacker (a Red Teamer, of course), don’t rely on defaults to get
you by—simple changes can have a significant impact on your chances of being
detected.

And finally, a few key takeaways for Blue and Red Teamers, respectively:

Team Blue

 * Continuously test and update your detection logic
 * Actively threat hunt! No alerts ≠ no malware
 * Search through a variety of log sources—an AV may not have caught this, but
   the network traffic might stand out like a sore thumb 

Team Red

 * Don’t use defaults! Tinker with everything
 * Don’t be afraid to get familiar with assembly!


SCRIPTS/YARA RULES

YARA



Main Script (view the full script here)



References

 * https://decoded.avast.io/threatintel/decoding-cobalt-strike-understanding-payloads/
 * https://github.com/rapid7/metasploit-framework/blob/master/external/source/shellcode/windows/x86/src/hash.py
 * https://blog.nviso.eu/2021/09/02/anatomy-and-disruption-of-metasploit-shellcode/
 * https://www.boozallen.com/insights/cyber/shellcode/shikata-ga-nai-encoder.html
 * https://www.youtube.com/watch?v=Tk3RWuqzvII

Share on Twitter
Share on LinkedIn
Share on Facebook
Share on Reddit

MATTHEW BRENNAN

Malware Enthusiast. Appreciator of Burritos. Detection Engineer at Huntress.




YOU MAY ALSO LIKE

Team Huntress 09.26.2023 13 min read


NETSCALER EXPLOITATION TO SOCIAL ENGINEERING: MAPPING CONVERGENCE OF ADVERSARY
TRADECRAFT ACROSS VICTIMS

The following is an analysis by the Huntress team of several recent intrusions
connected ...
Start Reading
Joe Slowik 09.14.2023 7 min read


SPIDERING THROUGH IDENTITY FOR PROFIT AND DISRUPTION

Dive into the recent Las Vegas casino cyberattacks linked to Scattered Spider,
and learn ...
Start Reading
Harlan Carvey 09.7.2023 6 min read


EVOLUTION OF USB-BORNE MALWARE, RASPBERRY ROBIN

A deep dive into the USB-borne Raspberry Robin malware and how Huntress Managed
EDR and ...
Start Reading

Hackers are constantly evolving to better attack small and mid-size
businesses—Huntress is how SMBs and managed service providers stay ahead with
managed cybersecurity solutions for endpoints, email, and identity.

LinkedIn Twitter Facebook YouTube BizRatings
 * Platform
   * Platform Overview
   * For MSPs
   * For VARs
   * Free Trial
 * Resources
   * Cybersecurity Education
   * Blog
   * Events
   * Careers

Sign Up for Blog Updates

Work Email (required)*



© 2023 Huntress - All rights reserved
 * Terms of Use
 * Privacy Policy
 * Legal
 * Cookie Policy