How Malware Developers are able to evade detection

How Does This Work?

Code

#include <iostream>
#include <Windows.h>
#include <TlHelp32.h>

using namespace std;
// This function will run in a dummy thread
DWORD WINAPI DummyThread(LPVOID lpParam) {
    Sleep(INFINITE); // This thread simply waits indefinitely
    return 0;
}
// Function to manipulate the stack of a thread in a process
void CleanStack(HANDLE hThread) {
    CONTEXT ctx;
    ctx.ContextFlags = CONTEXT_FULL;
    // Suspend the thread before modifying its context
    SuspendThread(hThread);
    // Get the thread's context
    if (!GetThreadContext(hThread, &ctx)) {
        cerr << "Error retrieving thread context" << endl;
        ResumeThread(hThread);
        return;
    }
    DWORD64 originalRsp = ctx.Rsp;
    cout << "Original RSP: " << hex << originalRsp << endl;
    constexpr int STACK_CLEAN_SIZE = 16;
    DWORD64 stackValues[STACK_CLEAN_SIZE];
    // Read the target thread's stack
    SIZE_T bytesRead;
    if (!ReadProcessMemory(GetCurrentProcess(), (LPCVOID)originalRsp, stackValues, sizeof(stackValues), &bytesRead)) {
        cerr << "Error reading stack memory" << endl;
        ResumeThread(hThread);
        return;
    }
    // Clear the stack
    ZeroMemory(stackValues, sizeof(stackValues));
    // Write the cleaned values back to the thread's stack
    SIZE_T bytesWritten;
    if (!WriteProcessMemory(GetCurrentProcess(), (LPVOID)originalRsp, stackValues, sizeof(stackValues), &bytesWritten)) {
        cerr << "Error writing stack memory" << endl;
    }
    ctx.Rsp = originalRsp;  // Restore RSP
    // Apply the changes to the thread context
    if (!SetThreadContext(hThread, &ctx)) {
        cerr << "Error setting thread context" << endl;
    }
    // Resume the thread
    ResumeThread(hThread);
}
int main() {
    // Create a dummy thread within the same process
    HANDLE hThread = CreateThread(NULL, 0, DummyThread, NULL, 0, NULL);
    if (!hThread) {
        cerr << "Error creating thread" << endl;
        return 1;
    }
    // Get the Thread ID of the created thread
    DWORD threadId = GetThreadId(hThread);
    cout << "Thread ID: " << threadId << endl;
    // Wait for the thread to initialize
    Sleep(100);
    cout << "Before Cleaning stack..." << endl;
    getchar();
    // Manipulate the dummy thread's stack from the main thread
    CleanStack(hThread);
    cout << "After Cleaning stack..." << endl;
    getchar();
    // Now we can terminate the dummy thread
    TerminateThread(hThread, 0);
    // Wait for the thread to complete before closing the program
    WaitForSingleObject(hThread, INFINITE);
    // Close the thread handle
    CloseHandle(hThread);
    Sleep(100000); // Simulate a long wait before the program exits
    return 0;
}

Proof of Concept

Detection

Litterbox:

_____                        __          
  /     \   ____   ____   _____/  |______   
 /  \ /  \ /  _ \ /    \_/ __ \   __\__  \  
/    Y    (  <_> )   |  \  ___/|  |  / __ \_
\____|__  /\____/|___|  /\___  >__| (____  /
        \/            \/     \/          \/ 
Moneta v1.0 | Forrest Orr | 2020
09c3c3b7217907e384a13c73c15486f6_StackCallCleaner.exe : 3508 : x64 : C:\Users\s12de\Desktop\LitterBox\Uploads\09c3c3b7217907e384a13c73c15486f6_StackCallCleaner.exe
  0x00007FF63E920000:0x00029000   | EXE Image           | C:\Users\s12de\Desktop\LitterBox\Uploads\09c3c3b7217907e384a13c73c15486f6_StackCallCleaner.exe | Unsigned module
    0x00007FF63E920000:0x00001000 | R        | Header   | 0x00000000 | Primary image base
    0x00007FF63E921000:0x00010000 | RWX      | .textbss | 0x00010000 | Modified code
    0x00007FF63E931000:0x0000a000 | RX       | .text    | 0x00000000
      Thread 0x00007FF63E931320 [TID 0x00000f80]
      Thread 0x00007FF63E931276 [TID 0x00001ef0]
    0x00007FF63E93B000:0x00004000 | R        | .rdata   | 0x00000000
    0x00007FF63E93F000:0x00001000 | RW       | .data    | 0x00001000
    0x00007FF63E940000:0x00005000 | R        | .pdata   | 0x00001000
    0x00007FF63E940000:0x00005000 | R        | .idata   | 0x00001000
    0x00007FF63E945000:0x00001000 | WC       | .msvcjmc | 0x00000000
    0x00007FF63E946000:0x00003000 | R        | .00cfg   | 0x00000000
    0x00007FF63E946000:0x00003000 | R        | .rsrc    | 0x00000000
    0x00007FF63E946000:0x00003000 | R        | .reloc   | 0x00000000... scan completed (0.172000 second duration)

ThreatCheck

Windows Defender

BitDefender Free AV

Conclusions

2 thoughts on “How Malware Developers are able to evade detection

  1. At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga.

Leave a Reply

Your email address will not be published. Required fields are marked *