新手对shellcode编写思路

本文内容仅供网络安全学习与防御研究,严禁用于非法用途,作者不承担任何法律责任

一.什么是shellcode

作者自己认为shellcode 就是一段纯二进制的机器码,它能让计算机直接执行一些你想要的结果,不需要编译器、不需要运行环境,丢进内存触发就能跑。那么问题来了如何把他丢进内存触发呢?

二.shellcode的运行一般流程

一般是把shellcode与一些其他功能部分的代码做成.exe文件(也就是所谓的shellcode加载器)执行,大概流程为——做好的.exe双击 → 系统创建进程 → 加载器代码运行 → 申请可执行内存 → 写入shellcode到内存 → 告诉CPU去执行这段内存 → CPU开始跑shellcode→ 达到你要的效果

三.shellcode加载器的编写

按照第二步所说我们主要要完成三个步骤

1.申请可执行内存

2.写入shellcode到内存

3.执行内存中的代码

我们这里主讲Windows了,那下面就看看如何做到这三步了

第一步:申请可执行内存

Windows系统自带了可供我们使用的api函数,这里要用到第一个api函数——VirtualAlloc 函数 (memoryapi.h)
这里给予微软官方的解释


语法使用框架如下:

LPVOID VirtualAlloc(
  [in, optional] LPVOID lpAddress,  
  [in]           SIZE_T dwSize, 
  [in]           DWORD  flAllocationType,
  [in]           DWORD  flProtect
);

我给大家总结一下参数意思(官方给的解释太多了,真晕,我会用{}里的内容补充说明,想看原版的去微软官网看吧):

lpAddress:目标内存起始地址{
为NULL:系统自动选择合适的地址
为非 NULL:手动指定地址。
无效指定地址会返回 ERROR_INVALID_ADDRESS 错误
}

dwSize: 分配内存大小(字节){
lpAddress=NULL:大小自动向上取整到下一页边界
lpAddress≠NULL:分配所有包含指定地址范围的内存页(跨页会占用两个页)
最终分配大小一定是内存页大小的整数倍(系统最小分配单位)
}

flAllocationType:内存分配类型{

类型有

MEM_COMMIT (0x1000):为已保留内存分配实际存储,首次访问清零且物理页延迟分配;可搭配MEM_RESERVE一步分配;单独使用且无保留地址会报错;重复提交无异常;enclave地址必须使用。

MEM_RESERVE (0x2000):保留进程的虚拟地址空间范围,而无需在内存或磁盘上的分页文件中分配任何实际物理存储。
可以在对 VirtualAlloc 函数的后续调用中提交保留页。 若要在一个步骤中保留和提交页面,请使用 MEM_COMMIT | MEM_RESERVE调用 VirtualAlloc。其他内存分配函数(如 malloc 和 LocalAlloc)在释放之前无法使用保留的内存范围。

MEM_RESET (0x80000):标记指定内存区域数据无需保留,暂停分页文件读写且不取消提交。此标志不可与其他值混用,不保证内存清零,忽略 flProtect 但需设有效值,仅支持分页文件共享视图。

MEM_RESET_UNDO (0x1000000):撤销MEM_RESET,恢复内存数据

flProtect:内存保护属性
定义分配后内存的访问权限,提交内存时必选:{

常用取值

PAGE_READWRITE 可读可写(最常用

PAGE_EXECUTE_READWRITE 可读可写可执行

PAGE_READONLY 只读

PAGE_EXECUTE 仅可执行

PAGE_NOACCESS 禁止任何访问

特殊:使用MEM_RESET时,此参数无效,但仍需填合法值(如PAGE_NOACCESS)
}

2.写入shellcode到内存

我们到了第二步就要认识一个Windows api函数—— RtlCopyMemory(其实有很多很多相似功能的API来写入这里就挑选一种)


语法如下:

void RtlCopyMemory(
   void*       Destination,
   const void* Source,
   size_t      Length
);

参数解释如下:

[out] Destination

指向要将字节复制到的目标内存块的指针。

[in] Source

指向要从中复制字节的源内存块的指针。

[in] Length

要从源复制到目标的字节数。

3.执行内存中的代码
方法有很多种,咱们假设定已经用 VirtualAlloc 分配好内存、拷贝好 Shellcode,变量统一用:LPVOID pAlloc;

我们大概列出几种如:

1.直接调用:

((void(*)())pAlloc)();

2.CreateThread 创建子线程执行

HANDLE hThread = CreateThread(
    NULL, 0,
    (LPTHREAD_START_ROUTINE)pAlloc,
    NULL, 0, NULL
);

WaitForSingleObject(hThread, INFINITE);

CloseHandle(hThread);

等等很多方法这里就不细说了,网上都有模板方法任你挑选

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值