當前位置:名人名言大全網 - 名人名言 - 簡述最常用的加密標準及其實現方法和技術?

簡述最常用的加密標準及其實現方法和技術?

作者:老羅

這是轉自《VC編程經驗總結7》

如何通過崩潰地址找到錯誤的代碼行

作為程序員,我們最擔心看到的是什麽?是內存泄露嗎?界面不好看嗎.....不對!我相信沒有人會反對我的意見——就是程序已經崩潰了!

"該程序執行了非法操作,很快將被關閉。請聯系您的軟件供應商。呵呵,M$的這句名言大概是程序員最擔心看到的吧。有時候,自己的程序在自己的機器上運行的很好,但是在別人的機器上就崩潰了;有時候在編寫和測試的過程中,莫名其妙的遇到非法操作,但又不能確定是源代碼中的哪壹行導致的...很痛苦嗎?不要緊,這篇文章可以幫助妳走出這個困境,甚至妳可以從現在開始自豪地要求用戶告訴妳崩潰地址,然後妳就可以準確定位源代碼中的錯誤行了。(是不是很神奇?哈哈。)

首先我必須強調,這種方法可以在目前市面上的任何編譯器上使用。但我只熟悉M$的VC和MASM,所以下面部分只介紹如何在這兩個編譯器中實現,讀者可以自行掌握在其他編譯器中使用的方法。

好了,廢話說夠了。我們開始吧!:)

首先,必須生成程序的映射文件。什麽是地圖文件?簡單來說,映射文件是程序的全局符號、源文件和代碼行號信息的唯壹文本表示。它可以隨時隨地使用,無需額外程序的支持。而且,這是唯壹能找出程序崩潰的地方的救世主。

好吧,既然地圖文件這麽神奇,那應該怎麽生成呢?在VC中,我們可以按Alt+F7打開“項目設置”選項頁,選擇C/C++選項卡,在底部項目選項中輸入:/Zd,然後選擇Link選項卡,在底部項目選項中輸入:/mapinfo:lines和/map:PROJECT_NAME.map。最後,按F7編譯生成EXE可執行文件和映射文件。

在MASM,我們需要設置編譯和連接參數,我通常會這樣做:

rc %1.rc

ml /c /coff /Zd %1.asm

鏈接/子系統:windows/mapinfo:exports/mapinfo:lines/map:% 1 . map % 1 . obj % 1 . RES

保存為makem.bat,可以在命令行輸入makem文件名,編譯生成EXE可執行文件和映射文件。

讓我先解釋壹下添加參數的含義:

/Zd表示在編譯時生成行信息。

/MAP[:filename]表示生成的映射文件的路徑和文件名。

/MAPinfo:lines表示在生成地圖文件時添加線信息。

/MAPinfo:exports表示在生成映射文件時添加導出的函數(如果生成DLL文件,則應添加此選項)。

好了,通過以上步驟,我們得到了地圖文件,那麽我們該如何使用它呢?

讓我們從壹個簡單的例子開始,請打開妳的VC並像這樣創建壹個新文件:

01 file://* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *。

02 file://程序名:演示如何通過崩潰地址找出錯誤的源代碼行。

03文件://作者:羅聰

04文件://日期:2003年2月7日

05文件://來源:(老羅的多彩世界)

06 file://這個程序會生成“除以0錯誤”,這樣就會彈出“非法操作”對話框。

07文件://“被0除錯誤”只會在調試版生成,為了演示這個程序盡量簡化。

08文件://註:如需轉載,請保持本程序完整並註明:

09文件://轉載自《老羅的多彩世界》()

10文件://* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *。

11

12無效崩潰(無效)

13 {

14 int I = 1;

15 int j = 0;

16 I/= j;

17 }

18

19空幹管(空)

20 {

21崩潰();

22 }

很明顯,這個程序存在“被0除錯誤”,如果在調試模式下編譯,運行時肯定會產生“非法操作”。好吧,讓我們運行它。果然,出現“非法操作”對話框。這時我們點擊“詳情”按鈕,記錄下崩潰發生的地址——我的機器上0x0040104a。

再看看它的地圖文件:(因為文件內容太長,我省略了中間沒用的部分)

碰撞演示

時間戳是3e 430 a 76(Fri 2003年2月7日09時23分02秒)

首選加載地址是00400000

開始長度名稱類別

0001:00000000 0000de04H。文本代碼

0001:0000 de04 0001000 ch。textbss代碼

0002:0000000000000001346h。rdata數據

0002:00001346 0000000h。數據數據

0003:00000000000000104h。CRT$XCA數據

0003:00000104 00000104h。CRT$XCZ數據

0003:00000208 00000104H。CRT$XIA數據

0003:0000030c 00000109H。CRT$XIC數據

0003:00000418 00000104h。CRT$XIZ數據

0003:0000051c 00000104h。CRT$XPA數據

0003:00000620 00000104H。CRT$XPX數據

0003:00000724 00000104H。CRT$XPZ數據

0003:00000828 00000104H。CRT$XTA數據

0003:0000092c 0000104h。CRT$XTZ數據

0003:00000a30 00000b93H。數據數據

0003:000015c 4 00001974h。bss數據

0004:00000000 00000014H。idata$2數據

0004:00000014 00000014H。idata$3數據

0004:00000028 00000110H。idata$4數據

0004:00000138 00000110H。idata$5數據

0004:00000248 000004afH。idata$6數據

通過值Rva+基庫:Object來尋址Publics

0001:00000020 ?崩潰@ @ YAXXZ 00401020 f crash demo . obj

0001:00000070 _ main 00401070 f crash demo . obj

0004:00000000 _ _ IMPORT _ DESCRIPTOR _ kernel 32 00424000 kernel 32:kernel 32 . dll

0004:00000014 _ _ NULL _ IMPORT _ DESCRIPTOR 00424014 kernel 32:kernel 32 . dll

0004:00000138 _ _ imp _ _ GetCommandLineA @ 0 00424138 kernel 32:kernel 32 . dll

0004:0000013c _ _ imp _ _ GetVersion @ 0 0042413c kernel 32:kernel 32 . dll

0004:00000140 _ _ imp _ _ exit process @ 4 00424140 kernel 32:kernel 32 . dll

0004:00000144 _ _ imp _ _ debug break @ 0 00424144 kernel 32:kernel 32 . dll

0004:00000148 _ _ imp _ _ GetStdHandle @ 4 00424148 kernel 32:kernel 32 . dll

0004:0000014c _ _ imp _ _ WriteFile @ 20 0042414c kernel 32:kernel 32 . dll

0004:00000150 _ _ imp _ _ InterlockedDecrement @ 4 00424150 kernel 32:kernel 32 . dll

0004:00000154 _ _ imp _ _ OutputDebugStringA @ 4 00424154 kernel 32:kernel 32 . dll

0004:00000158 _ _ imp _ _ GetProcAddress @ 8 00424158 kernel 32:kernel 32 . dll

0004:0000015c _ _ imp _ _ loadlibrary a @ 4 0042415c kernel 32:kernel 32 . dll

0004:00000160 _ _ imp _ _ interlocked increment @ 4 00424160 kernel 32:kernel 32 . dll

0004:00000164 _ _ imp _ _ getmodulefilename a @ 12 00424164 kernel 32:kernel 32 . dll

0004:00000168 _ _ imp _ _ termin ate process @ 8 00424168 kernel 32:kernel 32 . dll

0004:0000016c _ _ imp _ _ GetCurrentProcess @ 0 0042416c kernel 32:kernel 32 . dll

0004:00000170 _ _ imp _ _ unhandledexception filter @ 4 00424170 kernel 32:kernel 32 . dll

0004:00000174 _ _ imp _ _ free environment stringsa @ 4 00424174 kernel 32:kernel 32 . dll

0004:00000178 _ _ imp _ _ free environment stringsw @ 4 00424178 kernel 32:kernel 32 . dll

0004:0000017c _ _ imp _ _ WideCharToMultiByte @ 32 0042417c kernel 32:kernel 32 . dll

0004:00000180 _ _ imp _ _ get environment strings @ 0 00424180 kernel 32:kernel 32 . dll

0004:00000184 _ _ imp _ _ GetEnvironmentStringsW @ 0 00424184 kernel 32:kernel 32 . dll

0004:00000188 _ _ imp _ _ SetHandleCount @ 4 00424188 kernel 32:kernel 32 . dll

0004:0000018c _ _ imp _ _ GetFileType @ 4 0042418c kernel 32:kernel 32 . dll

0004:00000190 _ _ imp _ _ GetStartupInfoA @ 4 00424190 kernel 32:kernel 32 . dll

0004:00000194 _ _ imp _ _ heap destroy @ 4 00424194 kernel 32:kernel 32 . dll

0004:00000198 _ _ imp _ _ heap create @ 12 00424198 kernel 32:kernel 32 . dll

0004:0000019c _ _ imp _ _ heap free @ 12 0042419c kernel 32:kernel 32 . dll

0004:000001a 0 _ _ imp _ _ virtual free @ 12 004241a 0 kernel 32:kernel 32 . dll

0004:000001 a4 _ _ imp _ _ RtlUnwind @ 16 004241 a4 kernel 32:kernel 32 . dll

0004:000001 A8 _ _ imp _ _ GetLastError @ 0 004241 A8 kernel 32:kernel 32 . dll

0004:000001ac _ _ imp _ _ setconsolectlhandler @ 8 004241ac kernel 32:kernel 32 . dll

0004:000001b0 _ _ imp _ _ IsBadWritePtr @ 8 004241b0 kernel 32:kernel 32 . dll

0004:000001 B4 _ _ imp _ _ IsBadReadPtr @ 8 004241 B4 kernel 32:kernel 32 . dll

0004:000001b8 _ _ imp _ _ heap validate @ 12 004241b8 kernel 32:kernel 32 . dll

0004:000001bc _ _ imp _ _ GetCPInfo @ 8 004241bc kernel 32:kernel 32 . dll

0004:000001c 0 _ _ imp _ _ geta CP @ 0 004241c 0 kernel 32:kernel 32 . dll

0004:000001 C4 _ _ imp _ _ GetOEMCP @ 0 004241 C4 kernel 32:kernel 32 . dll

0004:000001 c8 _ _ imp _ _ HeapAlloc @ 12 004241 c8 kernel 32:kernel 32 . dll

0004:000001cc _ _ imp _ _ VirtualAlloc @ 16 004241cc kernel 32:kernel 32 . dll

0004:000001 d0 _ _ imp _ _ HeapReAlloc @ 16 004241 d0 kernel 32:kernel 32 . dll

0004:000001 D4 _ _ imp _ _ MultiByteToWideChar @ 24 004241 D4 kernel 32:kernel 32 . dll

0004:000001 D8 _ _ imp _ _ LCMapStringA @ 24 004241 D8 kernel 32:kernel 32 . dll

0004:000001dc _ _ imp _ _ LCMapStringW @ 24 004241dc kernel 32:kernel 32 . dll

0004:000001 E0 _ _ imp _ _ getstring typea @ 20 004241 E0 kernel 32:kernel 32 . dll

0004:000001 E4 _ _ imp _ _ getstring typew @ 16 004241 E4 kernel 32:kernel 32 . dll

0004:000001e 8 _ _ imp _ _ setfile pointer @ 16 004241e 8 kernel 32:kernel 32 . dll

0004:000001ec _ _ imp _ _ SetStdHandle @ 8 004241ec kernel 32:kernel 32 . dll

0004:000001f 0 _ _ imp _ _ FlushFileBuffers @ 4 004241f 0 kernel 32:kernel 32 . dll

0004:000001 F4 _ _ imp _ _ close handle @ 4 004241 F4 kernel 32:kernel 32 . dll

0004:000001 F8 \ 177 kernel 32 _ NULL _ THUNK _ DATA 004241 F8 kernel 32:kernel 32 . dll

入口點在0001:000000f0

的行號。\ Debug \ crash demo . obj(d:\ msdev \ my projects \ crash demo \ crash demo . CPP)段。文本

13 0001:00000020 14 0001:00000038 15 0001:0000003f 16 0001:00000046

17 0001:00000050 20 0001:00000070 21:0001:00000088 22 0001:0000008d

如果仔細瀏覽Rva+Base列,會發現第壹個大於崩潰地址0x0040104a的函數地址是0x00401070,所以地址0x00401070之前的條目就是導致崩潰的函數,也就是這壹行:

0001:00000020 ?崩潰@ @ YAXXZ 00401020 f crash demo . obj

崩潰的函數是。崩潰@@YAXXZ,所有以問號開頭的函數名都是C++修飾名。在我們的源程序中,也就是子函數Crash()。

好了,現在我們輕而易舉地知道了崩潰函數的名字,激動嗎?呵呵,先別忙。接下來,更厲害的招數還會出來。

請註意映射文件的最後壹部分——行號信息,它以如下形式顯示:

13 0001:00000020

第壹個數字表示源代碼中的代碼行號,第二個數字是代碼行在其所屬的代碼段中的偏移量。

如果妳想找到代碼行號,妳需要用下面的公式做壹些十六進制減法:

崩潰線偏移量=崩潰地址)-圖像基地址)-0x1000。

為什麽要這麽做?細心的朋友可能註意到了Rva+Base這壹列。我們得到的崩潰地址都是由偏移地址(Rva)+基址得來的,所以在計算行號的時候要減去基址。通常,基址的值是0x00400000。另外,由於壹般PE文件的代碼段都是以偏移量0x1000開頭的,所以也必須減去0x1000。

好了,明白了這個,我們就可以做小學減法計算了:

崩潰線偏移量= 0x 0040104 a-0x 00400000-0x 1000 = 0x4a。

如果您瀏覽映射文件中的代碼行信息,您會看到不超過計算結果的數字,但最接近的數字在CrashDemo.cpp文件中:

16 0001:00000046

也就是源代碼中的16行。讓我們看看源代碼:

16 I/= j;

哈!!!真的是16線!

激動嗎?我也是!:)

介紹了方法。從現在開始,我們可以準確定位源代碼中的崩潰線,只要編譯器能夠生成映射文件(包括VC、MASM、VB、BCB、Delphi……)都適用這種方法...).我們經常抱怨M$的產品有多差,但實際上M$已經有意無意地為我們提供了很多有價值的信息,只是我們常常不知道如何去利用它...相信這樣的話,妳可以更加坦然的面對“非法操作”的提示。妳甚至可以要求用戶提供崩潰的地址,然後妳就可以舒舒服服地在家裏找到錯誤的線路並改正它。