在mdb文件第0x42字節處的13個字節分別與0x86,0xfb,0xec,0x37,0x5d,0x44,0x9c,0xfa,0xc6,0x5e,0x28,0xe6,0x13異或后即可得到數據庫的密碼。但在access 2000和2002的版本里密鑰不再是固定的13個字節.而且加密的方式也有了變化。
經過ccrun用一下午的時間研究,終于將access2000的加密方式搞清楚了。嘿嘿。在此將偶的心得發布。希望對大家有用,如果您發現我的理解有誤,請來信告之我們。信箱:[email protected] 版權雖然有沒有都沒關系,不過如果您要轉載,請注明出處,并保證文檔的完整性。謝謝。
我用的分析工具是ultraedit32 v10.00,編程工具是c++ builder 6.0。
經過用ultraedit32分析,發現access2000和access2002的數據庫加密方式相同,所以以下只針對access2000的mdb文件。還有就是我用的是16進制的數表示,所以前面加了0x,如果你用的是vb或其他,要注意數值哦。
首先用accessxp創建了一個空密碼的數據庫文件db1.mdb,包含一個表,其中有一個字段,沒有填任何數據。保存退出然后復制一份為db2.mdb,以獨占方式打開2.mdb,并加上密碼1324567890123 保存退出。
用ultraedit32打開這兩個數據庫,并進行比較。我比較的方法也很簡單。在ultraedit32中,快速的來回點擊被打開文件的選項卡(就是在兩個文件間來回切換,呵呵。笨辦法吧),發現從文件頭開始0x42字節處發生變化。
| 以下為引用的內容: db1.mdb 00000060h:b1 33 0c f2 79 5b aa 26 7c 2a 4f e9 7c 99 05 13 ; 00000060h:b1 33 0c f2 79 5b aa 26 7c 2a 4f e9 7c 99 05 13 ; |
為了看的清楚些,我把不同的字節加了顏色。看出門道了吧,access97以后的版本里,密碼字節不再是連續存放,而是隔一個字節存一個。并且經過加密。到于解密的方法嘛,還是用老辦法“異或”!0xbe ^ 0x8f = 0x31,這正好是ascii碼"1"哦。下一個0xec ^ 0xde = 0x32 正好是ascii碼"2",呵呵。一直到最后一個不同的0x4f ^ 0x7c =0x33,將取得的字符合成字符串,便是密碼明文“1234567890123",千萬不要以為這樣就收工了。因為這一次是正好碰對了。呵呵。我剛開始也以為就這么簡單,于是用cb做了個小程序,試著解了幾個mdb密碼都還行,可是試到動網論壇的mdb文件時發現取出來的密碼不對,暈了。于是用另外一個取mdb密碼的工具看了一下,發現人家的就可以正確的取出密碼,是access2000的格式,于是感覺微軟加密的方式還是沒研究完。繼續工作,用ultraedit32打開動網論壇的數據庫dvbbs.mdb,和我前面的加過密的數據庫做比較,發現不同的地方很多。只好一個字節一個字節的試。。。。nnn次以后發現第0x62處的這個字節起著關鍵作用,暫稱之為加密標志。
| 以下為引用的內容: db1.mdb //空密碼 00000060h:b1 33 0c f2 79 5b aa 26 7c 2a 4f e9 7c 99 05 13 ; db2.mdb //密碼為:1234567890123 00000060h:b1 33 0c f2 79 5b aa 26 7c 2a 4f e9 7c 99 05 13 ; dvbbs.mdb //密碼為:yemeng.net 00000040h:bc 4e db 6a 89 37 14 d5 f9 fa 8c cf 4f e6 19 27 ; 00000050h:e4 60 15 05 0f 36 d1 e3 df b1 53 65 13 43 eb 3e ; 00000060h:b1 33 10 f0 79 5b b6 24 7c 2a 4a e0 7c 99 05 13 ; |
怎么試呢,還是異或。取0x42處開始的字節0xdb與空密碼文件的0x42處字節異或,取0x62處的加密標志與空密碼文件0x62處字節異或,然后再把取得的兩個值相異或:
(0xdb^0xbe)^(0x10^0x0c)=0x79 這個值是ascii的"y",然后取下一個字節(記得隔一個字節取一個)
(0x89^0xec)^(0x10^0x0c)=0x79 本來這個字節應該是"e"的,怎么變成"y"了?試著不與后面的兩個異或值相異或,只計算0x89^0xec=0x65 得到"e",哈。這下對了。下一個
(0x14^0x65)^(0x10^0c)=0x6d 得到"m",下一個
(0xf9^9c)=0x65 得到"e",注意這里只是這兩個數異或。后面的大家可以自己試。
這樣就總結出規律來了。
解密時,先取出加密文件從文件頭開始0x62處的字節,與空密碼數據庫文件第0x62處相異或,得到一個加密標志。
再從0x42處開始每隔一個字節取一個字節,取得13個加密后的密碼字節,分別與空密碼數據庫文件0x42處每隔一個字節取得的13個字節想異或,得到13個密碼半成品。為什么說是半成品呢,因為還要將13個字節的密碼每隔一個字節,就與加密標志相異或,最后得到的13個字節才是真正的密碼。當然,如果中間有0x0的字節,則說明密碼位數不夠13位。直接show出來就可以了。
另外我發現加密標志會隨著時間或機器不同而不同,所以也沒有萬能的,不過有一個參照的就可以了。以下代碼是我在寫這個程序的時候取得的數,和我寫這篇文章不是一個時間,所以數值不一樣,但最終解密的結果是一樣的。大家可以參考一下。
對了,還有個重要的就是先得判斷數據庫的版本,我用了個簡單的辦法,取0x14處的字節,如果為0就判斷為是access97,如果為1就認為是access2000或2002的。只是目前沒有研究出判斷2000和2002的辦法,如果哪位知道的話,請指點。
代碼:
//這里定義的是13個字節作為access2000異或的源碼。與之相對應的加密標志是0x13,ccrun特此注明
//當然你可以用這一組:be ec 65 9c fe 28 2b 8a 6c 7b cd df 4f 與這一組相對應的加密標志是0x0c
//呵呵.程序有些亂,希望大家能看的懂
char passsource2k[13]={0xa1,0xec,0x7a,0x9c,0xe1,0x28,0x34,0x8a,0x73,0x7b,0xd2,0xdf,0x50};
//access97的異或源碼
char passsource97[13]={0x86,0xfb,0xec,0x37,0x5d,0x44,0x9c,0xfa,0xc6,0x5e,0x28,0xe6,0x13};
| 以下為引用的內容: void __fastcall tmainform::getmdbpass() filehandle=fileopen(mdbfilename,fmopenread); //取得數據庫版本 //取得加密標志 //讀取加密后的密碼到緩沖區 if(ver<1) t1=char(0x13^encrypflag^passstrtemp[j*2]^passsource2k[j]); //每隔一個字節就與加密標志相異或。這里的加密標志為0x13 else t1=char(passstrtemp[j*2]^passsource2k[j]); |
新聞熱點
疑難解答