101 lines
3.0 KiB
Markdown
101 lines
3.0 KiB
Markdown
|
# Antimalware Signature Evasion
|
||
|
|
||
|
## Check Binary Against AV
|
||
|
|
||
|
* Split the binary to create signature
|
||
|
```sh
|
||
|
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
|
||
|
|
||
|
* [Powersploit's Find-AVSignature](https://github.com/PowerShellMafia/PowerSploit/blob/master/AntivirusBypass/Find-AVSignature.ps1) finds it automatically
|
||
|
* [rasta-mouse's Threat Check](https://github.com/rasta-mouse/ThreatCheck)
|
||
|
|
||
|
|
||
|
## 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 `NOP`s or do bit flipping via
|
||
|
```python
|
||
|
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
|
||
|
```sh
|
||
|
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](https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-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
|
||
|
|
||
|
```c
|
||
|
#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);
|
||
|
}
|
||
|
}
|
||
|
```
|