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

news2024/11/22 19:29:44

前提

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

  • how-does-navicat-encrypt-password

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

25770e146ee2ee8ba439e414287bee3d.png
navicat-watcher-1.png

大致原理

参考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版本代码并且强行转换为Go实现:

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{...})
}

小结

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

  • navicat-watcher

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

(本文完 c-1-d e-a-20230802 很久没写文章了)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/840120.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

IL汇编语言读取控制台输入和转换为整数

新建一个testcvt.il&#xff1b; .assembly extern mscorlib {}.assembly Test{.ver 1:0:1:0}.module test.exe.method static void main() cil managed{.maxstack 1.entrypointldstr "\n请输入一个数字:"call void [mscorlib]System.Console::Write(string)call st…

二分图笔记

什么是二分图&#xff1f; 二分图一般针对无向图问题 一张图中&#xff0c;如果能够把全部的点分到两个集合中&#xff0c;保证两个集合内部没有任何边 &#xff0c;图中的边只存在于两个集合之间&#xff0c;即为二分图 判断二分图 1. 染色法 即用两种颜色对于这张图进行染…

Redis内网主从节点搭建

Redis内网主从节点搭建 1、文件上传2、服务安装3、服务启动4、配置主从复制 1、文件上传 内网环境手动上传gcc-c、redis.tar文件 2、服务安装 # 解压 unzip gcc-c.zip unzip gcc_rpm.zip tar -zxvf redis-6.2.13.tar.gz# 安装 cd gcc_rpm/ rpm -ivh *.rpm --nodeps --force…

LIME(可解释性分析方法)

目录 1.什么是LIME 2.思路 3.LIME在不同任务中的范式&#xff08;待补充&#xff09; 1.什么是LIME 简单理解&#xff1a; 对于分类任务&#xff1a;如下图所示&#xff0c;LIME可以列出分类结果&#xff0c;所依据特征对应给比重。 对于图像分类任务&#xff1a;如下图所示&a…

Python(六十八)元组的创建方式

❤️ 专栏简介&#xff1a;本专栏记录了我个人从零开始学习Python编程的过程。在这个专栏中&#xff0c;我将分享我在学习Python的过程中的学习笔记、学习路线以及各个知识点。 ☀️ 专栏适用人群 &#xff1a;本专栏适用于希望学习Python编程的初学者和有一定编程基础的人。无…

JVM详情

JVM详情 一、JVM内存划分二、双亲委派模型&#xff08;重点考察&#xff09;三、 GC&#xff08;垃圾回收机制&#xff09;垃圾的判定算法垃圾回收算法 一、JVM内存划分 堆&#xff1a;存放new出来的对象&#xff1b;&#xff08;成员变量&#xff09; 方法区&#xff1a;存放…

【代码源每日一题div2 】简单的异或问题

简单的异或问题 - 题目 - Daimayuan Online Judge 题意&#xff1a; 思路&#xff1a; 首先这有一个结论&#xff1a;0~2^m-1的所有数进行XOR运算后&#xff0c;得到的结果是0。我们来证明一下这个结论&#xff1a; 比如m3时&#xff0c;一共是0 1 2 3 4 5 6 7&#xff0c;八…

炼钢工艺流程入门(1)

1. 工序简略词 BF(Blast Furnace)&#xff1a;高炉 KR(Kambara Reactor)&#xff1a;脱硫 BOF(Basic Oxygen Furnace)&#xff1a;氧气顶吹转炉炼钢法 LF(Ladle Furnace)&#xff1a;钢包精炼炉 CCM(Continuous Casting Machine) &#xff1a;连铸机 2. 软处罚约束与硬处…

【N32L40X】学习笔记13-软件IIC读写EEPROM AT24C02

AT24C02 8个字节每页,累计32个页 通讯频率MAX 400K AT24C02大小 2K 芯片地址 对于at24c02 A2A1A0 这三个引脚没有使用 写时序 由于设备在写周期中不会产生ACK恢复&#xff0c;因此这可用于确定周期何时完成&#xff08;此特性可用于最大限度地提高总线吞吐量&#xff09;…

Jmeter 压测工具使用手册[详细]

1. jemter 简介 jmeter 是 apache 公司基于 java 开发的一款开源压力测试工具&#xff0c;体积小&#xff0c;功能全&#xff0c;使用方便&#xff0c;是一个比较轻量级的测试工具&#xff0c;使用起来非常简 单。因为 jmeter 是 java 开发的&#xff0c;所以运行的时候必须先…

gitbook编译报错gitbook\gitbook-plugin-fontsettings\fontsettings.js‘

找到本地电脑gitbook安装的目录&#xff1a;cd ~/.gitbook/versions/版本/lib/output/website/ 可以用 vim copyPluginAssets.js 也可以用记事本打开注释掉或者改为false

Redis 双写一致性实践及案例

面试问题&#xff1a; 你只要用缓存&#xff0c;就可能会涉及到redis缓存与数据库双存储双写&#xff0c;你只要是双写&#xff0c;就一定会有数据一致性的问题&#xff0c;那么你如何解决一致性问题&#xff1f;双写一致性&#xff0c;你先动缓存redis还是数据库mysql哪一个&…

MySQL建表和增添改查

1.创建一个名为mydb的数据库 mysql> show database mydb; 查询 mysql> show database mydb; 2.创建一个学生信息表 mysql> create table mydb.student_informtion( -> student_id int UNSIGNED NOT NULL PRIMARY KEY, //非空&#xff08;不允许为空&#xff0…

Axure RP9中使用Echarts示例

目录 在Axure中拖入一个矩形框&#xff0c;并命名tes 进入Echarts官网示例页面https://echarts.apache.org/examples/zh/index.html 选择自己需要的图表&#xff0c;修改数据&#xff0c;并复制左侧js代码 把上面复制的代码替换下方的option{}; javascript: var script docum…

扩散模型实战(二):扩散模型的发展

推荐阅读列表&#xff1a; 扩散模型实战&#xff08;一&#xff09;&#xff1a;基本原理介绍 扩散模型从最初的简单图像生成模型&#xff0c;逐步发展到替代原有的图像生成模型&#xff0c;直到如今开启 AI 作画的时代&#xff0c;发展速度可谓惊人。下面介绍一下2D图像生成相…

浅析 C 语言的共用体、枚举和位域

前言 最近在尝试阅读一些系统库的源码&#xff0c;但是其中存在很多让我感到既熟悉又陌生的语法。经过资料查阅&#xff0c;发现是 C 语言中的共用体和位域。于是&#xff0c;趁着课本还没有扔掉&#xff0c;将一些相关的知识点记录在本文。 文章目录 前言共用体 (union)枚举…

Python冷知识-为什么切片和区间会忽略最后一个元素

在 Python 里&#xff0c;像列表&#xff08;list&#xff09;、元组&#xff08;tuple&#xff09;和字符串&#xff08;str&#xff09;这类序列类型都支持切片操作&#xff0c;但是实际上切片操作比人们所想象的要强大很多。 在切片和区间操作里不包含区间范围的最后一个元…

0805hw

1. #include <myhead.h> void Bub_sort(int *arr,int n)//冒泡排序 {for(int i1;i<n;i){int count0;for(int j0;j<n-i;j){if(arr[j]>arr[j1]){int temparr[j];arr[j]arr[j1];arr[j1]temp;count;}}if(count0){break;}}printf("冒泡排序后输出结果:\n"…

OA会议管理系统之会议通知(送审成功可查看人员是否参与会议)

一、前言 1.导读 在上一次的博文中我们实现了会议审批&#xff0c;会议通过审批后&#xff0c;状态就会由原来的待审核变为待开&#xff0c;这时候我们就可以在我的会议下的反馈详情查看人员是否参与会议的反馈情况。这篇博客就是来了解&#xff0c;人员是怎么接收会议通知并反…