Preface 序——“碼”途有道何為徑
你主要能得到什么
如果你想成為高級程序員或軟件架構(gòu)師,什么才是技術(shù)上的核心競爭力?僅僅是知識?在這個隨時可求助于谷歌和百度的年代,知識似乎已變得非常廉價了。而青春的流失并不能給我們留下技術(shù)財富,似乎只是將我們變成自嘲的“碼奴”。
核心競爭力究竟在哪里?本書認為,一個關(guān)鍵要素就是“系統(tǒng)觀”,這是高級軟件人才必備的素質(zhì)。系統(tǒng)觀是美妙的,它能自我生長,自我完善,有了它,你就擁有了一顆能成長的原核。系統(tǒng)觀是核心知識架構(gòu)和對它們不斷運用所形成的思維方式的復(fù)合體。本書的首要任務(wù)就是幫助大家建立系統(tǒng)觀。
◎ 本書采用獨特的自底向上貫通的方式幫助讀者完成系統(tǒng)觀的構(gòu)建,從反匯編、機器碼入手,以逆向分析貫穿,運用一點點增加的知識不斷探索出新知識并最終上升到框架。
◎ 本書采用生長式的學(xué)習(xí)方法,每個后續(xù)章節(jié)都是運用前面內(nèi)容探索而來的,既讓你制造“磚頭”,又讓你用它建造“大廈”。讀完本書后,你不僅能掌握一個小而全的可自我發(fā)展的核心知識架構(gòu),更能掌握一種被筆者稱為“猜測—實證—構(gòu)建”的系統(tǒng)觀的思維與學(xué)習(xí)方法。你將經(jīng)歷一次暢快的知識探索的發(fā)現(xiàn)之旅。
你還能得到什么
學(xué)完本書后,除了系統(tǒng)觀這一主要成果,你還能獲得一些有意思的能力,比如:
◎ 掌握被稱為“調(diào)構(gòu)學(xué)習(xí)法”的第三方源代碼學(xué)習(xí)方法(成為架構(gòu)師的重要能力)。
◎ 在C語言中模擬面向?qū)ο蟮睦^承、封裝、虛函數(shù)覆蓋等。
◎ 用病毒常用的自定位代碼技術(shù)解決框架級軟件的優(yōu)雅構(gòu)造。
◎ 利用鉤子技術(shù),在只有執(zhí)行程序的條件下改變第三方軟件的行為。
◎ 運用鏈接原理自己動手鏈接OBJ文件,使其可執(zhí)行。
◎ ……
對筆者而言,這是一本關(guān)于“探索知識、讓知識融入生命”的書;是一本關(guān)于能力與學(xué)習(xí)的書;是一本展示如何將看似瑣碎的知識碎片不斷打磨成珠玉,慢慢串成美麗珠寶的書;是一本展示編程技藝如何自我鍛造的書。也可以看成是與大家分享碼途人生的飛絮囈語。
學(xué)什么?少即多的系統(tǒng)觀
學(xué)什么?記得在Internet還沒有成為主流的時代,有個學(xué)通信的碩士被一個IP路由器問題困擾了一個多星期。筆者最好的朋友,學(xué)空氣動力學(xué)的,他玩了10多年DOS系統(tǒng),從沒實際接觸過網(wǎng)絡(luò),只是“看”過一本資料,還不是IP網(wǎng)絡(luò),僅花兩天就解決了這個問題。為什么有人學(xué)了很多技術(shù)和語言卻不如未學(xué)習(xí)該技術(shù)的人呢?該問題另一個問法就是“什么才是我們最需要掌握的?”
筆者的看法是:“少就是多,將這個少變成多”。下足工夫,將“少”做深、做厚、變多,就是將來應(yīng)對千變?nèi)f化的舵。這個“少”就是計算機的系統(tǒng)觀。看看上面的例子,那個朋友對DOS的熟悉程度已經(jīng)到了對任何一段地址空間作用都了如指掌的地步,自己還實現(xiàn)過一個漢化的DOS。他無疑是建立起了堅實的系統(tǒng)觀。這個系統(tǒng)觀能指導(dǎo)他按照計算機的“邏輯”方式思考,而路由器不過是這種思維方式的一個例子罷了。有了系統(tǒng)觀,學(xué)習(xí)新東西時,用它去猜測、構(gòu)想學(xué)習(xí)對象的可能做法并實證分析,是一種迅捷的辦法。筆者在處理SaaS軟件中的hibernate將同一持久化對象存入不同庫的問題時就是這樣,雖然沒用過hibernate,但通過猜測和調(diào)試,用了約半天時間就解決了問題(搜索并非銀彈,該問題當時在網(wǎng)絡(luò)的中英文查詢中均未查到)。
到底什么是系統(tǒng)觀?有些東西只可意會難以言傳,且見仁見智。這時,糾結(jié)含義不如能夠運用。詩詞意境頗似系統(tǒng)觀,詩人自身可能都說不清其內(nèi)涵,可他能運用這種意境,“運用為王”。其實,我們只要能建立系統(tǒng)觀就好了。
如何建立?一種方法是從無到有自己撰寫一個系統(tǒng)級軟件(哪怕是實驗性的),如嵌入式數(shù)據(jù)庫、小型操作系統(tǒng)或編譯器。這非常有效,那位朋友得益于撰寫漢化DOS的經(jīng)歷,在沒有學(xué)過嵌入式的情況下,一個月時間就解密了一個單片機太陽能系統(tǒng),并漢化。但這種方法需要較長一段時間完全投入,且難度不小。針對這些問題,本書給出了另一種方法。
本書內(nèi)容:逆向入道,自底向上建立系統(tǒng)觀
在建立系統(tǒng)觀方面,本書沒有選擇正規(guī)的站馬步的方式——構(gòu)建一個操作系統(tǒng)或編譯器,而是提供了一種劍走偏鋒的方法——自底向上,以逆向反匯編入道,貫穿從機器碼至框架的學(xué)習(xí)。因為,逆向是一把匕首,小巧,卻能劈開黑箱直見根本,實乃實證利器。
本書涉及范圍既廣也窄。從“廣”來說,覆蓋了匯編、反匯編、逆向、調(diào)試、鏈接、線程、插件風(fēng)格編程、設(shè)計模式、對象模型和機制、框架源代碼學(xué)習(xí)等內(nèi)容。從“窄”來講,本書緊緊圍繞運用基礎(chǔ)知識這把“瑞士軍刀”,披荊斬棘,最終建立系統(tǒng)觀這一主旨。同時,本書不僅讓我們多了一種能力(書中各章節(jié)均給出一些調(diào)試技巧),更將OS、Compiler等相關(guān)知識從壓箱底處翻到臺面上,并通過逆向思維有效整合在一起。你會發(fā)現(xiàn),這些原來似乎抽象的知識,完全滲透到我們破疑解惑的過程中了。
本書由7章構(gòu)成,其中第6章(除6.5節(jié))為李林著,其余為韓宏著。
第1章是最重要的基礎(chǔ),以逆向反匯編角度建立了語言的物理模型,充分利用GUI調(diào)試環(huán)境,將所有知識點做到可“把玩”。例如,在分析mov指令機器碼時,通過斷點,并利用內(nèi)存窗體修改機器碼,從而改變C語言賦值語句的效果,也展現(xiàn)了一種學(xué)習(xí)匯編的方法——基于分析RTL(runtime library)的學(xué)習(xí)方式。本章還充分展示了“猜測—實證—構(gòu)建”的思想。
第2章展現(xiàn)基礎(chǔ)知識的底層力量,給出多個運用前章逆向知識解決問題的例子。其中有的例子應(yīng)該是首次公開的。本章揭示出逆向分析的力量,不僅可運用于加密、解密,而且真的能指導(dǎo)我們解決平常的開發(fā)難題。部分內(nèi)容覆蓋了鉤子、異常、注入等技術(shù)。
第3章呈現(xiàn)以構(gòu)建為驅(qū)動的軟件開發(fā)學(xué)習(xí)方式,知識覆蓋鏈接器、測試驅(qū)動開發(fā)、數(shù)據(jù)結(jié)構(gòu)、軟件重用、文件訪問等。內(nèi)容有其特點,如以構(gòu)建的角度學(xué)習(xí)了鏈接器相關(guān)知識,并創(chuàng)建了一個最小“Linker”演示。在后續(xù)動態(tài)鏈接庫運用中,以此為基礎(chǔ)解決了棘手問題。
第4章以創(chuàng)造面向?qū)ο笳Z言方式,展示了對象模型、機制及其重要特點和使用模式,涉及構(gòu)造、析構(gòu)、基于棧構(gòu)造技巧、虛函數(shù)機制等。這種創(chuàng)造的方式集中體現(xiàn)了猜測、實證的思想,在理解的基礎(chǔ)上深入探討了在C語言中如何運用面向?qū)ο笏枷耄o出了相關(guān)宏;并分析了一些重要設(shè)計原則及其在C++中的利弊和不同語種的權(quán)衡。以逆向思維貫穿所有問題的解決是本章的特點。
第5章構(gòu)建了一個跨平臺線程類,充分利用了第4章的知識,最終創(chuàng)建了跨平臺線程庫,并展示不同語言下虛函數(shù)機制導(dǎo)致的軟件設(shè)計差異以及bug的解決過程。從設(shè)計到debug的過程體現(xiàn)了系統(tǒng)觀和底層調(diào)試的重要性。
第6章在第4章基礎(chǔ)上展示了一個實用插件框架的演化,在不修改已有代碼的前提下,運行時為系統(tǒng)添加新功能。其中,DLL內(nèi)存釋放bug的解決方案充分展示了調(diào)試和系統(tǒng)觀的力量。
第7章討論了閱讀優(yōu)秀源代碼的方法與技巧。這不僅是程序員成長的重要手段,也是開源時代的重要能力(對一個框架,在資料匱乏之下,你必須快速擴展框架,加入自己需要的功能)。以分析VCL框架為例,并對比MFC,結(jié)合框架閱讀和創(chuàng)建,展現(xiàn)了被筆者稱為“調(diào)構(gòu)學(xué)習(xí)法”的源代碼學(xué)習(xí)方法。調(diào)試、追蹤、分析了自定位機器碼解決this指針獲取的問題,并模仿這一機制創(chuàng)建了可重用的窗體控件框架。本章將猜測—實證—構(gòu)建思想貫穿到了框架源代碼學(xué)習(xí)和構(gòu)建中。
我的碼道:三步斬“碼”刀
修煉系統(tǒng)觀不是簡單知識的積累,需要一種“道”。筆者的“道”就是:猜測—實證—構(gòu)建。
“猜測”讓我們主動思考,發(fā)現(xiàn)問題。這樣學(xué)習(xí)不再是按部就班,而是“尋找式”,對癥下藥,有選擇地吸收,迅速且準確,直指癥結(jié)。如1.3.1節(jié)學(xué)習(xí)call指令時,不直接看其解釋,而是先分析機器碼,猜測哪部分可能包含轉(zhuǎn)跳地址,最后經(jīng)多次猜測實證才搞清楚。這樣,將一般被動接受式學(xué)習(xí)變成了主動研究式的破疑。簡單地說,學(xué)習(xí)任何不懂的技術(shù)或框架前先不要急于看它怎么做,而想想自己怎么做,要想到可實證的細節(jié),否則無意義。
“實證”體現(xiàn)為每個知識點都可觸摸,或調(diào)試、或編程、或使用,能驗證。許多人猜測后認為一些東西“很顯然”,而不驗證,此時“真知”就從指間溜走了。如2.9.3節(jié)猜測狀態(tài)保存時,細分了局部變量、參數(shù),并考慮優(yōu)化。實證與猜測相悖處即產(chǎn)生前進動力:我們常感嘆自己不善提問,而實證就是最好的設(shè)問及解答的過程。實證時往往一個知識點牽扯了很多復(fù)雜因素,看來幾乎無法實證。此時關(guān)鍵就是“領(lǐng)悟精髓,刪繁就簡”。本書第3章展示了如何通過摸索理清鏈接的關(guān)鍵邏輯,構(gòu)建一個2~3天能完成的Linker核心小程序。
“構(gòu)建”要求盡量將學(xué)到的知識通過編寫程序模仿出來。這非常有助于以系統(tǒng)觀思考問題。而構(gòu)建中會出現(xiàn)意想不到的問題,它們又是進步的階梯。比如,多年前學(xué)習(xí)《Windows核心編程》中內(nèi)存訪問API時,筆者拋開書上的例子,用這些API編寫了游戲修改器。之后就發(fā)現(xiàn)了新問題:遍歷整個線性地址空間尋找某個整數(shù)耗時太長,速度完全無法與真正的修改器比擬。最后,基于最基本的對齊原理解決這一問題,就不用挨個字節(jié)搜索了。基礎(chǔ)知識在一個個構(gòu)建、意外及調(diào)試解決中被貫穿起來,終成系統(tǒng)觀。本書每章均有展現(xiàn)構(gòu)建的威力。
其實,“碼”途之道最重要的就是“快樂”。有了它,你就有了自己的“道”。在本書中,你能看到面對問題的興奮和努力探索的快樂。如第2章最后兩個例子,就是筆者大年初一連續(xù)幾天瘋狂逆向的結(jié)果。一個個失望和驚喜后,明媚的陽光穿過0/1 bit的迷霧曬到皮膚上,這就是生命的味道。
如何使用本書
讀者有一定的C和C++語言的基礎(chǔ)知識就可上路了,你不需要很懂匯編,我們會一點點探索。中途遇到什么概念不懂,可上網(wǎng)查閱學(xué)習(xí)。既然強調(diào)體驗式,你就將本書當成游戲攻略吧,你一定要在計算機上“玩”成這個“游戲”,而不是在床頭“看”它,要通關(guān)哦。隨書附帶了源代碼,但你不要直接用,請自己實現(xiàn)一次,將源代碼當做答案吧。(所有源代碼并沒有采用附盤的形式提供給讀者,而是采取網(wǎng)站免費下載的方式,讀者可以登錄http://www.phei. com.cn或者http://www.hxedu.com.cn進行下載。)
本書以VS 2008為主要調(diào)試環(huán)境,還用到其他工具:Delphi、Ultraedit、PELord、PEView和IDA pro。
書中解決問題的體驗式過程只從文字看(特別糾纏了反匯編后)容易迷失,所以每章都挑選了一個較難的案例編寫了思維導(dǎo)圖(除第7章外),讀者可配合使用。通過導(dǎo)圖的符號能索引正文;通過頁側(cè)的標記又可快速定位導(dǎo)圖中位置,以便來回參閱,理順思路。
結(jié)束本文前,用一首打油詩以抒心意:
人被“碼”馴為碼奴,
何日馴“碼”騁康途。
老“碼”識途途何在,
三步斬“碼”刀自出。
我的斬“碼”刀就是“猜測—實證—構(gòu)建”,你的呢?
最后感謝家人、朋友與學(xué)生(特別是陳松進行了細致的校對),他們在著書的過程中給予了筆者莫大支持并提供了寶貴意見。還要致謝高輝老師,他就strlen算法給出了證明。
韓宏
二〇一二年八月
- UNIX編程藝術(shù)
- .NET之美:.NET關(guān)鍵技術(shù)深入解析
- Visual Basic程序開發(fā)(學(xué)習(xí)筆記)
- 深入淺出WPF
- Implementing Cisco Networking Solutions
- 數(shù)據(jù)結(jié)構(gòu)(C語言)
- PySide 6/PyQt 6快速開發(fā)與實戰(zhàn)
- Arduino家居安全系統(tǒng)構(gòu)建實戰(zhàn)
- Scratch趣味編程:陪孩子像搭積木一樣學(xué)編程
- Python語言科研繪圖與學(xué)術(shù)圖表繪制從入門到精通
- FPGA嵌入式項目開發(fā)實戰(zhàn)
- Docker:容器與容器云(第2版)
- 算法超簡單:趣味游戲帶你輕松入門與實踐
- 數(shù)據(jù)結(jié)構(gòu)與算法詳解
- Python程序設(shè)計現(xiàn)代方法