killchain-compendium/post exploitation/docs/windows/Signature-Evasion.md

3.0 KiB

Antimalware Signature Evasion

Check Binary Against AV

  • Split the binary to create signature
head --bytes <number of bytes> > sig.exe
  • To test running antivirus, split it in half multiple times and check if it would be detected by the AV. Check for bad bytes

Automation

Static Code

  • Obfuscation of classes

    • Class Hierarchy Flattening, create proxies via interfaces
    • Class Splitting & Coalescing, shift variables to other classes
    • Dropping Modifiers, drop private use public only
  • Obfuscation of methods

    • Method Proxy, proxy method or object replacement
    • Method Scattering & Aggregation, coalesce or split methods
    • Method Clone, replication of methods

Property Based

  • Properties may be hash checksum or entropy of a binary

  • While having the source code at hand, simple white spaces can change the checksum or adding strings to the text section may lower the entropy

Bit Flipping

  • When only the binary is accessible add some NOPs or do bit flipping via
import sys

with open (sys.argc[1], "rb") as _f:
    orig = list(_f.read)

for i,c in enumerate(orig):
    current=list(orig)
    current[i] = chr(ord(c) ^ 0xde)
    path = f"{i}.exe" 
	
    with open (path, "wb") as _f:
        _f.write(''.join(str(x) for x in current)

print("[+] Success")
return 0
  • Verify if the portable executables generated from the script above are still well formed
FOR /L %%A IN (1,1,10000) DO (
	signtool verify /v /a flipped\\%%A.exe
)

Behavior Based

  • Import Adress Table (IAT) is the PLT of windows. It contains addresses of the (standard) lib functions provided by DLLs.
  • IAT can be found in a PE's header under IMAGE_OPTIONAL_HEADER. The references are provided by an API call or the Thunk Table
  • Dynamic Loading can be used to call the address of a library function instead of IAT

Dynamic Loading

  • The structure of a call has to be defined, an example is GetComputerNameA

  • Get the handle of the module where the address that will be called resides in

  • Get the process address of the loaded function address

#include <windows.h>
#include <stdio.h>
#include <lm.h>

// Compilation via i686-w64-mingw32-g++ -fPIC nosig.c -o nosig.exe 

typedef BOOL (WINAPI* myNotGetComputerNameA)(
	LPSTR   lpBuffer,
	LPDWORD nSize
);

int main ( void ) {
    HMODULE hkernel32 = LoadLibraryA("kernel32.dll");
    myNotGetComputerNameA notGetComputerNameA = (myNotGetComputerNameA) GetProcAddress(hkernel32, "GetComputerNameA");
    printf("GetComputerNameA: 0x%p\\n", notGetComputerNameA);
    CHAR hostName[260];
    DWORD hostNameLength = 260;
    if (notGetComputerNameA(hostName, &hostNameLength)) {
        printf("hostname: %s\\n", hostName);
    }
}