Navicat 数据库连接密码加密与破解

* 所有相关信息仅技术学习调研,不公开任何侵犯公司价值信息,若有侵犯,请联系删除

可以获取到 ip  port  username  password   conntype

 

PHP

<?php

namespace FatSmallTools;

class NavicatPassword
{
    protected $version = 0;
    protected $aesKey = 'libcckeylibcckey';
    protected $aesIv = 'libcciv libcciv ';
    protected $blowString = '3DC5CA39';
    protected $blowKey = null;
    protected $blowIv = null;
    
    public function __construct($version = 12)
    {
        $this->version = $version;
        $this->blowKey = sha1('3DC5CA39', true);
        $this->blowIv = hex2bin('d9c7c3c8870d64bd');
    }
    
    public function encrypt($string)
    {
        $result = FALSE;
        switch ($this->version) {
            case 11:
                $result = $this->encryptEleven($string);
                break;
            case 12:
                $result = $this->encryptTwelve($string);
                break;
            default:
                break;
        }
        
        return $result;
    }
    
    protected function encryptEleven($string)
    {
        $round = intval(floor(strlen($string) / 8));
        $leftLength = strlen($string) % 8;
        $result = '';
        $currentVector = $this->blowIv;
        
        for ($i = 0; $i < $round; $i++) {
            $temp = $this->encryptBlock($this->xorBytes(substr($string, 8 * $i, 8), $currentVector));
            $currentVector = $this->xorBytes($currentVector, $temp);
            $result .= $temp;
        }
        
        if ($leftLength) {
            $currentVector = $this->encryptBlock($currentVector);
            $result .= $this->xorBytes(substr($string, 8 * $i, $leftLength), $currentVector);
        }
        
        return strtoupper(bin2hex($result));
    }
    
    protected function encryptBlock($block)
    {
        return openssl_encrypt($block, 'BF-ECB', $this->blowKey, OPENSSL_RAW_DATA|OPENSSL_NO_PADDING); 
    }
    
    protected function decryptBlock($block)
    {
        return openssl_decrypt($block, 'BF-ECB', $this->blowKey, OPENSSL_RAW_DATA|OPENSSL_NO_PADDING); 
    }
    
    protected function xorBytes($str1, $str2)
    {
        $result = '';
        for ($i = 0; $i < strlen($str1); $i++) {
            $result .= chr(ord($str1[$i]) ^ ord($str2[$i]));
        }
        
        return $result;
    }
    
    protected function encryptTwelve($string)
    {
        $result = openssl_encrypt($string, 'AES-128-CBC', $this->aesKey, OPENSSL_RAW_DATA, $this->aesIv);
        return strtoupper(bin2hex($result));
    }
    
    public function decrypt($string)
    {
        $result = FALSE;
        switch ($this->version) {
            case 11:
                $result = $this->decryptEleven($string);
                break;
            case 12:
                $result = $this->decryptTwelve($string);
                break;
            default:
                break;
        }
        
        return $result;
    }
    
    protected function decryptEleven($upperString)
    {
        $string = hex2bin(strtolower($upperString));
        
        $round = intval(floor(strlen($string) / 8));
        $leftLength = strlen($string) % 8;
        $result = '';
        $currentVector = $this->blowIv;
        
        for ($i = 0; $i < $round; $i++) {
            $encryptedBlock = substr($string, 8 * $i, 8);
            $temp = $this->xorBytes($this->decryptBlock($encryptedBlock), $currentVector);
            $currentVector = $this->xorBytes($currentVector, $encryptedBlock);
            $result .= $temp;
        }
        
        if ($leftLength) {
            $currentVector = $this->encryptBlock($currentVector);
            $result .= $this->xorBytes(substr($string, 8 * $i, $leftLength), $currentVector);
        }
        
        return $result;
    }
    
    protected function decryptTwelve($upperString)
    {
        $string = hex2bin(strtolower($upperString));
        return openssl_decrypt($string, 'AES-128-CBC', $this->aesKey, OPENSSL_RAW_DATA, $this->aesIv);
    }
}





//namespace FatSmallTools\Tests;

use PHPUnit\Framework\TestCase;
//use FatSmallTools\NavicatPassword;

class NavicatPasswordTest
{
    public function testHandleTwelve()
    {
        $navicatPassword = new NavicatPassword(12);
        $string = '123456';
        $encrypted = $navicatPassword->encrypt($string);
        $this->assertEquals('833E4ABBC56C89041A9070F043641E3B', $encrypted);
        $decrypted = $navicatPassword->decrypt($encrypted);
        $this->assertEquals($string, $decrypted);
        
        $string = 'This is a test';
        $encrypted = $navicatPassword->encrypt($string);
        $this->assertEquals('B75D320B6211468D63EB3B67C9E85933', $encrypted);
        $decrypted = $navicatPassword->decrypt($encrypted);
        $this->assertEquals($string, $decrypted);
    }
    
    public function testHandleEleven()
    {
        $navicatPassword = new NavicatPassword(11);
        $string = '123456';
        $encrypted = $navicatPassword->encrypt($string);
        $this->assertEquals('15057D7BA390', $encrypted);
        $decrypted = $navicatPassword->decrypt($encrypted);
        $this->assertEquals($string, $decrypted);
        
        $string = 'This is a test';
        $encrypted = $navicatPassword->encrypt($string);
        $this->assertEquals('0EA71F51DD37BFB60CCBA219BE3A', $encrypted);
        $decrypted = $navicatPassword->decrypt($encrypted);
        $this->assertEquals($string, $decrypted);
    }
}

//use FatSmallTools\NavicatPassword;

//需要指定版本,11或12
$navicatPassword = new NavicatPassword(11);
//$navicatPassword = new NavicatPassword(12);

//加密
$encode = $navicatPassword->encrypt('123456'); // verstion 11 15057D7BA390, version 12 833E4ABBC56C89041A9070F043641E3B

//解密
$decode = $navicatPassword->decrypt('15057D7BA390');
//$decode = $navicatPassword->decrypt('833E4ABBC56C89041A9070F043641E3B');


//$result = print_r(getArrayData(), true); // 获取函数返回值并转换成字符串形式
echo $decode; // 输出函数返回值

*  如果解出来是乱码需要切换版本

 

Python

#!/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))

*  如果是 .ncx 文件需要编译调用 ncx 函数方法

 

* 所有相关信息仅技术学习调研,不公开任何侵犯公司价值信息,若有侵犯,请联系删除