基于Go编写一个可视化Navicat本地密码解析器

 更新时间:2023年08月03日 09:56:28   作者:Throwable  
这篇文章主要给大家介绍了基于Go编写一个可视化Navicat本地密码解析器的方法,文中有详细的代码示例和图文介绍,有需要的朋友可以参考阅读本文

前提

开发小组在测试环境基于docker构建和迁移一个MySQL8.x实例,过程中大意没有记录对应的用户密码,然后发现某开发同事本地Navicat记录了根用户,于是搜索是否能够反解析Navicat中的密码掩码(这里可以基本断定Navicat对密码是采用了对称加密算法),于是发现了这个仓库:

密码的解密算法显然是被泄露了,那么就可以利用起来。加之笔者之前花了一点点时间入门了一下Go,于是业余花了点时间编写了一个GUI工具。这个工具主要功能是:在Windows系统下,自动读取Navicat在注册列表中写入的所有(数据库)服务器连接数据作为列表展示,对于每个服务器连接数据的密码尝试进行解密。效果如下:

大致原理

参考how-does-navicat-encrypt-password仓库,因为Navicat两种版本的对称加密算法的具体算法、秘钥和加密向量都被泄露了,得知:

  • 版本一(Low):使用Blowfish/ECB/NoPadding模式
  • 版本二(High):使用AES/CBC/PKCS5Padding模式

其中AES/CBC/PKCS5Padding实现是比较简单的,Blowfish/ECB/NoPaddingGo的原生类库中刚好缺少了ECB解码器,只能仔细翻阅how-does-navicat-encrypt-passwordJava版本代码

func (l *LowVersionCipher) Decrypt(input string) (string, error) {
	ciphertext, err := hex.DecodeString(input)
	if err != nil {
		return "", err
	}
	if len(ciphertext)%8 != 0 {
		return "", errors.New("ciphertext length must be a multiple of 8")
	}
	plaintext := make([]byte, len(ciphertext))
	cv := make([]byte, len(l.iv))
	copy(cv, l.iv)
	blocksLen := len(ciphertext) / blowfish.BlockSize
	leftLen := len(ciphertext) % blowfish.BlockSize
	decrypter := NewECBDecrypter(l.cipher)
	for i := 0; i < blocksLen; i++ {
		temp := make([]byte, blowfish.BlockSize)
		copy(temp, ciphertext[i*blowfish.BlockSize:(i+1)*blowfish.BlockSize])
		if err != nil {
			panic(err)
		}
		decrypter.CryptBlocks(temp, temp)
		xorBytes(temp, cv)
		copy(plaintext[i*blowfish.BlockSize:(i+1)*blowfish.BlockSize], temp)
		for j := 0; j < len(cv); j++ {
			cv[j] ^= ciphertext[i*blowfish.BlockSize+j]
		}
	}
	if leftLen != 0 {
		decrypter.CryptBlocks(cv, cv)
		temp := make([]byte, leftLen)
		copy(temp, ciphertext[blocksLen*blowfish.BlockSize:])
		xorBytes(temp, cv[:leftLen])
		copy(plaintext[blocksLen*blowfish.BlockSize:], temp)
	}
	return string(plaintext), nil
}
func xorBytes(a []byte, b []byte) {
	for i := 0; i < len(a); i++ {
		aVal := int(a[i]) & 0xff // convert byte to integer
		bVal := int(b[i]) & 0xff
		a[i] = byte(aVal ^ bVal) // xor aVal and bVal and typecast to byte
	}
}

接着基于golang.org/x/sys/windows/registry加载Windows系统注册列表下的服务器连接数据列表,Navicat多个版本测试发现服务器连接数保存在注册列表的Software\PremiumSoft\Navicat\Servers目录下,只需要全量读取出来并且按照每个服务器连接数据的明细k-v一步一步解析即可。这个解析过程的伪代码如下:

const NsPath = `Software\PremiumSoft\Navicat\Servers`
nsp, _ := registry.OpenKey(registry.CURRENT_USER, NsPath, registry.READ)
subKeys, _ := nsp.ReadSubKeyNames(999)
var servers []*Server
for _, subKey := range subKeys {
    serverPath := strings.Join([]string{NsPath, subKey}, `\`)
    sp, _ := registry.OpenKey(registry.CURRENT_USER, serverPath, registry.READ)
    // 数据库的版本
    serverVersion, _, _ := sp.GetIntegerValue("ServerVersion")
    // host
    host, _, _ := sp.GetStringValue("Host")
    // 用户名
    username, _, _ := sp.GetStringValue("UserName")
    // 密码密文
    pwd, _, _ := sp.GetStringValue("Pwd")
    // 端口,一般是3306
    port, _, _ := sp.GetIntegerValue("Port")
    realPwd := pwd
    if (len(pwd) > 0){
        // 解密得到密码明文
        realPwd, _ = cipher.Decrypt(pwd)
    }
    servers = append(servers, &Server{...})
}

小结

提醒 - 这个项目仅仅是提供参考和学习,供个人本地开发时候使用,切勿用于窃取他人的数据库密码。项目仓库:

顺带一提使用fyneGUI开发效果还可以,不过目前这个库还存在比较多BUG,性能高的同时占用的资源也比较高。

以上就是基于Go编写一个可视化Navicat本地密码解析器的详细内容,更多关于Go编写Navicat密码解析器的资料请关注脚本之家其它相关文章!

相关文章

  • golang动态创建类的示例代码

    golang动态创建类的示例代码

    这篇文章主要介绍了golang动态创建类的实例代码,本文通过实例代码给大家讲解的非常详细,需要的朋友可以参考下
    2023-06-06
  • Go语言普通指针unsafe.Pointer uintpt之间的关系及指针运算

    Go语言普通指针unsafe.Pointer uintpt之间的关系及指针运算

    这篇文章主要为大家介绍了Go语言普通指针unsafe.Pointer uintpt之间的关系及指针运算示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • 关于golang中平行赋值浅析

    关于golang中平行赋值浅析

    这篇文章主要给大家介绍了关于golang中平行赋值的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用golang具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-08-08
  • Go语言基础闭包的原理分析示例详解

    Go语言基础闭包的原理分析示例详解

    这篇文章主要为大家介绍了Go语言基础闭包的底层原理及实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步早日升职加薪
    2021-11-11
  • Go语言开源库实现Onvif协议客户端设备搜索

    Go语言开源库实现Onvif协议客户端设备搜索

    这篇文章主要为大家介绍了Go语言Onvif协议客户端设备搜索示例实现,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • 提升Golang应用性能:深入理解Context的应用

    提升Golang应用性能:深入理解Context的应用

    本文将深入探讨如何通过深入理解和正确应用Go语言中的Context来提升应用性能。需要的朋友可以参考下
    2023-09-09
  • Go语言中次方表示的实现

    Go语言中次方表示的实现

    本文主要介绍了Go语言中次方表示的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-03-03
  • Golang使用gin框架实现一个完整的聊天室功能

    Golang使用gin框架实现一个完整的聊天室功能

    由于我们项目的需要,我就研究了一下关于websocket的相关内容,去实现一个聊天室的功能,经过几天的探索,现在使用Gin框架实现了一个完整的聊天室+消息实时通知系统,感兴趣的小伙伴欢迎阅读本文
    2023-08-08
  • 基于Go语言对浮点数进行比较的方法

    基于Go语言对浮点数进行比较的方法

    在 Go 语言(以及大多数遵循 IEEE 754 标准的编程语言)中,‌差值容限(Epsilon) ‌ 是指在进行浮点数比较时,允许两个数值之间存在的最大微小误差范围,本文给大家介绍了基于Go语言对浮点数进行比较的方法,需要的朋友可以参考下
    2026-05-05
  • Go interface接口声明实现及作用详解

    Go interface接口声明实现及作用详解

    这篇文章主要为大家介绍了Go interface接口声明实现及作用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03

最新评论