讀取HeidiSQL 配置文件中的密碼

讀取HeidiSQL 配置文件中的密碼
2017-1-21 5:42:01 codegaypython

HeidiSQL是一款開源的SQL管理工具,用管理MYSQL,MSSQL 等數據庫,
不少管理工具都會把密碼存在本地,HeidiSQL也是的,可是隻是通過很是簡單的編碼,因此我通過簡單的分析後就知道了解密的方法。
連HeidiSQL源碼都不用讀...git

我使用的是版本是HeidiSQL_9.4_Portable,配置會存在軟件目錄下的portable_settings.txt中,
HeidiSQL安裝版會配置信息存在如下注冊表中:github

HKEY_CURRENT_USER\Software\HeidiSQL\

密碼會保存在:
HKEY_CURRENT_USER\Software\HeidiSQL\Servers這個節點下面。sql

HeidiSQL portable版運行後也會創建註冊表信息,退出軟件會刪除,配置信息最終會保存到portable_settings.txt中:
HKEY_CURRENT_USER\Software\HeidiSQL Portable [一串隨機數]數據庫

相似這樣:HKEY_CURRENT_USER\Software\HeidiSQL Portable 9532session

打開portable_settings.txt能夠看到配置文件中有如下這樣的ip 密碼之類這樣的信息dom

HeidiSQL配置文件節選:函數

Servers\Unnamed-2\SessionCreated<|||>1<|||>2017-01-20 13:32:21
Servers\Unnamed-2\Host<|||>1<|||>127.0.0.1
Servers\Unnamed-2\WindowsAuth<|||>3<|||>0
Servers\Unnamed-2\User<|||>1<|||>root
Servers\Unnamed-2\Password<|||>1<|||>6A6A6A9
Servers\Unnamed-2\LoginPrompt<|||>3<|||>0
Servers\Unnamed-2\Port<|||>1<|||>3306
Servers\Unnamed-2\NetType<|||>3<|||>0
Servers\Unnamed-2\Compressed<|||>3<|||>0
Servers\Unnamed-2\LocalTimeZone<|||>3<|||>0
Servers\Unnamed-2\QueryTimeout<|||>3<|||>0
Servers\Unnamed-2\KeepAlive<|||>3<|||>0
Servers\Unnamed-2\FullTableStatus<|||>3<|||>1
Servers\Unnamed-2\Databases<|||>1<|||>
Servers\Unnamed-2\Comment<|||>1<|||>
Servers\Unnamed-2\StartupScriptFilename<|||>1<|||>
Servers\Unnamed-2\SSHtunnelHost<|||>1<|||>
Servers\Unnamed-2\SSHtunnelHostPort<|||>3<|||>0
Servers\Unnamed-2\SSHtunnelUser<|||>1<|||>
Servers\Unnamed-2\SSHtunnelPassword<|||>1<|||>1
Servers\Unnamed-2\SSHtunnelTimeout<|||>3<|||>4
Servers\Unnamed-2\SSHtunnelPrivateKey<|||>1<|||>
Servers\Unnamed-2\SSHtunnelPort<|||>3<|||>3307
Servers\Unnamed-2\SSL_Active<|||>3<|||>0
Servers\Unnamed-2\SSL_Key<|||>1<|||>
Servers\Unnamed-2\SSL_Cert<|||>1<|||>
Servers\Unnamed-2\SSL_CA<|||>1<|||>
Servers\Unnamed-2\SSL_Cipher<|||>1<|||>

當時分析的過程中,我嘗試去看HeidiSQL的源碼中對密碼編碼解碼的部分,稍微在GITHUB上搜索了一下,
不過沒有定位到對應的代碼段。哈哈,太水了。
我經過反覆把密碼填爲a r 1 aaa aaaa rrrr 之類這樣的,而後查ASCII碼錶和配置文件中的密碼串對比,工具

終於發現了算出密碼的規則,以密碼aaa爲例子,
在配置文件能夠獲得6A6A6A9
6A轉爲10進制獲得106 減最後一位的9獲得97,恰好能夠對應ASCII碼上的字母a,有3個6A,因此還能夠還原獲得aaa
也就是說前面的都是ASCII碼,最後一位是偏移量,ASCII減偏移量就是對應的密碼字符。網站

如下是在ipython中解碼的演示

int("6A",16)
Out[1]: 106

106 - 9
Out[2]: 97

chr(97)
Out[3]: 'a'

如下是一個讀取HeidiSQL 配置文件中的密碼的python3代碼:

# -*- coding: utf-8 -*-
"""
2017-1-21 3:42:54 codegay
"""
import re
settings = r"D:\臨安初雨\Soft\HeidiSQL_9.4_Portable\portable_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]

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

for r in passwords:
    print(heidipass(r))

參考資料:

HeidiSQL官方網站: http://www.heidisql.com/
HeidiSQL源碼(非官方)https://github.com/HeidiSQL/HeidiSQL
ASCII碼對照表 http://tool.oschina.net/commons?type=4 (沒有16進制,差評)

2017-1-22 3:30:25 補充: 這個連接有其餘用戶帖出了各類語言版本的代碼 https://gist.github.com/jpatters/4553139

2017-1-28 2:06:53 補充: Heidisql 源碼中密碼加密解密的函數名分別是encrypt decrypt:
https://github.com/HeidiSQL/HeidiSQL/blob/c62da41849ff943bf913ad76f16bc60c1653abc5/source/helpers.pas

爲了防止原連接失效,我把代碼摘出來:

{***
  Password-encryption, used to store session-passwords in registry
  @param string Text to encrypt
  @return string Encrypted Text
}
function encrypt(str: String) : String;
var
  i, salt, nr : integer;
  h : String;
begin
  randomize();
  result := '';
  salt := random(9) + 1;
  for i:=1 to length(str) do begin
    nr := ord(str[i])+salt;
    if nr > 255 then
      nr := nr - 255;
    h := inttohex(nr,0);
    if length(h) = 1 then
      h := '0' + h;
    result := result + h;
  end;
  result := result + inttostr(salt);
end;



{***
  Password-decryption, used to restore session-passwords from registry
  @param string Text to decrypt
  @return string Decrypted Text
}
function decrypt(str: String) : String;
var
  j, salt, nr : integer;
begin
  result := '';
  if str = '' then exit;
  j := 1;
  salt := StrToIntDef(str[length(str)],0);
  result := '';
  while j < length(str)-1 do begin
    nr := StrToInt('$' + str[j] + str[j+1]) - salt;
    if nr < 0 then
      nr := nr + 255;
    result := result + chr(nr);
    inc(j, 2);
  end;
end;
相關文章
相關標籤/搜索