为什么重新安装之后,LetsVPN 仍然会自动回到旧账号
最近在 Windows 上排查 LetsVPN 的一个现象:明明已经删掉客户端数据库,重新打开程序后却还是会自动回到之前的旧账号,连被封过的账号状态也会一起恢复。
这个现象第一眼很像“服务端根据设备指纹强行认回旧号”,但这次实际结合 ProcMon 日志、本地 SQLite 文件和注册表状态一起看,结论更接近下面这句话:
LetsVPN 的旧账号恢复,至少在当前版本里,不是单靠服务端完成的,而是强依赖本地持久化状态。关键状态不只在 Lets-Data.db3,也在
HKCU\Software\Lets下面的一组加密注册表值里。
一、问题现象
排查开始时,现象非常具体:
- 客户端曾经登录过某个旧账号。
- 删除本地数据库后,重新启动客户端。
- 客户端没有变成真正的“全新状态”,而是又自动恢复到了旧账号。
这就带来两个核心问题:
- LetsVPN 到底把账号状态保存在什么位置。
- 自动恢复旧号时,真正起决定作用的是本地缓存,还是服务端设备识别。
二、排查思路
为了回答这两个问题,我重点观察了三类行为:
- 客户端的网络访问。
Lets-Data.db3的文件访问。HKCU\Software\Lets和设备标识相关注册表项的访问。
这次使用的是 ProcMon 导出的 CSV 日志,重点筛选 LetsPRO.exe 的以下行为:
TCP Connect、UDP Send。ReadFile、CreateFile,目标为Lets-Data.db3。RegQueryValue、RegSetValue,目标为HKCU\Software\Lets和MachineGuid。
三、先看到的不是 SQLite,而是注册表和设备标识
重新检查完整日志后,能确认一件事:客户端在“恢复旧号”的那段时间里确实联网了,不是纯离线逻辑。
但更关键的是时间顺序。
在典型的一次恢复流程里,先发生的是:
- 读取
HKCU\Software\Lets下面的一批应用状态。 - 反复读取
HKLM\SOFTWARE\Microsoft\Cryptography\MachineGuid。 - 对多个
:https目标发起UDP Send和TCP Connect。 - 随后才集中读取
Lets-Data.db3。
这说明两点:
- SQLite 的确参与了恢复流程,但它不是唯一状态源。
- 程序在读取数据库之前,就已经开始依赖注册表状态和设备标识了。
四、HKCU\Software\Lets 下面有哪些可疑数据
在 ProcMon 里,LetsPRO.exe 反复读取或写入了下面这些值:
accountrecordInfouserHabitqjiwxewwqjGetDeviceInfoSendCountryGetDeviceInfoSendCountryTimeLocalCountryCode
其中最值得注意的是 account、recordInfo、userHabit、qjiwx、ewwqj 这几项。它们大多是 REG_BINARY,而且数据头部带有明显的 DPAPI 特征,也就是 Windows 用户态加密格式。
这意味着:
- 数据不是明文缓存。
- 数据和当前 Windows 用户上下文绑定。
- 这些值很可能就是 LetsVPN 用来恢复登录状态或设备状态的核心本地缓存。
从实验结果回看,最可疑的仍然是 qjiwx 和 ewwqj。
五、MachineGuid 的作用是什么
日志里还能看到客户端多次读取:
HKLM\SOFTWARE\Microsoft\Cryptography\MachineGuid
这说明设备级标识确实参与了客户端运行逻辑。它可能用于:
- 设备识别。
- 风控。
- 上报设备信息。
- 配合本地缓存做账号恢复判断。
但就这次实验结果而言,MachineGuid 更像辅助因素,而不是唯一决定因素。因为如果服务端完全靠设备标识就能强制恢复旧号,那么在本地状态被彻底清掉之后,客户端仍应当稳定回到旧号。实际结果并不是这样。
六、决定性的验证:同时清空注册表和 SQLite
真正把结论钉死的,不是日志本身,而是最后的清理实验。
在完全退出 LetsVPN 客户端之后,我同时清除了两部分本地状态:
HKCU\Software\Lets%LOCALAPPDATA%\LetsVPN\Lets-Data.db3及其附属文件
重新启动客户端之后,结果是:
- 客户端成功退出了旧账号。
- 客户端 ID 发生了变化。
- 之前被封的账号状态没有再自动恢复。
这个结果说明:
旧账号之所以能“回来”,不是因为服务端单靠机器就无条件认回来了,而是因为本地仍然保留着足以恢复身份的状态。
换句话说,只删除 Lets-Data.db3 并不够,因为 HKCU\Software\Lets 里还保留着另一套关键缓存。
七、正确的清理命令
下面是一组更稳妥的 PowerShell 命令,适合用于测试“清空本地状态后,客户端是否还会自动回旧号”。
它会做三件事:
- 先结束进程。
- 先备份注册表和数据库。
- 再删除
HKCU\Software\Lets和Lets-Data.db3相关文件。
$backup = Join-Path $env:USERPROFILE ("Desktop\\lets_backup_" + (Get-Date -Format 'yyyyMMdd_HHmmss'))
New-Item -ItemType Directory -Path $backup -Force | Out-Null
# 1. 结束客户端进程
Get-Process LetsPRO -ErrorAction SilentlyContinue | Stop-Process -Force
# 2. 备份注册表
reg export HKCU\Software\Lets (Join-Path $backup 'Lets.reg') /y | Out-Null
# 3. 备份数据库文件
$dataDir = Join-Path $env:LOCALAPPDATA 'LetsVPN'
if (Test-Path $dataDir) {
Get-ChildItem $dataDir -Force -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like 'Lets-Data.db3*' } |
Copy-Item -Destination $backup -Force -ErrorAction SilentlyContinue
}
# 4. 删除注册表
if (Test-Path 'HKCU:\Software\Lets') {
Remove-Item 'HKCU:\Software\Lets' -Recurse -Force
}
# 5. 删除数据库及附属文件
if (Test-Path $dataDir) {
Get-ChildItem $dataDir -Force -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like 'Lets-Data.db3*' } |
Remove-Item -Force -ErrorAction SilentlyContinue
}
# 6. 验证是否删干净
'Registry Exists: ' + (Test-Path 'HKCU:\Software\Lets')
if (Test-Path $dataDir) {
Get-ChildItem $dataDir -Force -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like 'Lets-Data.db3*' } |
Select-Object FullName
}
如果你只想做最小化测试,也可以直接用下面这组更短的命令:
Get-Process LetsPRO -ErrorAction SilentlyContinue | Stop-Process -Force
Remove-Item 'HKCU:\Software\Lets' -Recurse -Force -ErrorAction SilentlyContinue
Get-ChildItem (Join-Path $env:LOCALAPPDATA 'LetsVPN') -Force -ErrorAction SilentlyContinue |
Where-Object { $_.Name -like 'Lets-Data.db3*' } |
Remove-Item -Force -ErrorAction SilentlyContinue
八、如何验证是不是本地状态导致的
建议把测试分成三步,不要一次性下结论。
1. 同时清空后启动客户端
如果这一步启动后不再自动回旧号,而且客户端生成了新的 ID,那么说明本地状态确实是关键因素。
2. 关闭并重新启动一次客户端
如果新的 ID 稳定保留,没有再次恢复旧号,说明新的本地状态已经接管了客户端身份。
3. 联网一段时间后再重启一次
如果联网后仍然不会回旧号,那么可以基本判定:至少在当前版本里,恢复旧号的主导因素就是本地持久化数据,而不是服务端单独靠设备指纹强行识别。
九、结论
这次排查最后得到的结论并不复杂,但很关键:
Lets-Data.db3不是 LetsVPN 唯一的本地状态源。HKCU\Software\Lets下面还保存着一组关键的加密缓存。- 只删除 SQLite 文件,往往不足以让客户端真正“失忆”。
- 同时删除注册表状态和数据库后,客户端才会真正退出旧身份并生成新的本地状态。
所以,如果你遇到的是“删库后还是会回旧号”,那问题大概率不是删库没生效,而是你删得还不够全。
更直白一点说:
让 LetsVPN 自动回旧号的,不是某一个神秘的云端开关,而是一套混合的本地持久化机制。数据库只是其中一部分,注册表缓存同样是关键。
更多推荐



所有评论(0)