1、基本語法
這包括static、final、transient等關鍵字的作用,foreach循環的原理等等。
2、集合
非常重要,基本上就是List、Map、Set,各種實現類的底層實現原理,實現類的優缺點。
集合要掌握的是ArrayList、LinkedList、Hashtable、HashMap、ConcurrentHashMap、HashSet的實現原理,
(1)ConcurrentHashMap的鎖分段技術
(2)ConcurrentHashMap的讀是否要加鎖,為什麼
(3)ConcurrentHashMap的迭代器是強一致性的迭代器還是弱一致性的迭代器
3、設計模式
設計模式在工作中是非常重要、非常有用的,23種設計模式中重點研究常用的十來種就可以了,面試中關於設計模式的問答主要是三個方向:
(1)你的項目中用到了哪些設計模式,如何使用
(2)知道常用設計模式的優缺點
(3)能畫出常用設計模式的UML圖
4、多線程
假如有Thread1、Thread2、Thread3、Thread4四條線程分別統計C、D、E、F四個盤的大小,所有線程都統計完畢交給Thread5線程去做匯總,應當如何實現?
聰明的網友們對這個問題是否有答案呢?不難,java.util.concurrent下就有現成的類可以使用。
另外,線程池在面試中也是比較常問的一塊,常用的線程池有幾種?這幾種線程池之間有什麼區別和聯系?線程池的實現原理是怎麼樣的?實際一些的,會給你一些具體的場景,讓你回答這種場景該使用什麼樣的線程池比較合適。
最後,雖然面試問得不多,但是多線程同步、鎖這塊也是重點。synchronized和ReentrantLock的區別、synchronized鎖普通方法和鎖靜態方法、死鎖的原理及排查方法等等,關於多線程,
5、JDK源碼
要想拿高工資,JDK源碼不可不讀。總結一下比較重要的源碼:
(1)List、Map、Set實現類的源代碼
(2)ReentrantLock、AQS的源代碼
(3)AtomicInteger的實現原理,主要能說清楚CAS機制並且AtomicInteger是如何利用CAS機制實現的
(4)線程池的實現原理
(5)Object類中的方法以及每個方法的作用
6、框架
老生常談,面試必問的東西。一般來說會問你一下你們項目中使用的框架,然後給你一些場景問你用框架怎麼做,比如我想要在Spring初始化bean的時候做一些事情該怎麼做、想要在bean銷毀的時候做一些事情該怎麼做、MyBatis中$和#的區別等等,這些都比較實際了,平時積累得好、有多學習框架的使用細節自然都不成問題。
7、資料庫
一些基本的像union和union all的區別、left
join、幾種索引及其區別就不談了,比較重要的就是資料庫性能的優化,如果對於資料庫的性能優化一竅不通,那麼有時間,還是建議你在面試前花一兩天專門把SQL基礎和SQL優化的內容准備一下。
8、數據結構和演算法分析
數據結構和演算法分析,對於一名程序員來說,會比不會好而且在工作中絕對能派上用場。數組、鏈表是基礎,棧和隊列深入一些但也不難,樹挺重要的,比較重要的樹AVL樹、紅黑樹,可以不了解它們的具體實現,但是要知道什麼是二叉查找樹、什麼是平衡樹,AVL樹和紅黑樹的區別。
9、Java虛擬機
Java虛擬機中比較重要的內容:
(1)Java虛擬機的內存布局
(2)GC演算法及幾種垃圾收集器
(3)類載入機制,也就是雙親委派模型
(4)Java內存模型
(5)happens-before規則
(6)volatile關鍵字使用規則
B. 編程原理是什麼
簡單的說,編程就是為了藉助於計算機來達到某一目的或解決某個問題,而使用某種程序設計語言編寫程序代碼,並最終得到結果的過程。
計算機雖然功能十分強大。可以供你上網、打游戲、管理公司人事關系等等,但是沒有程序,它就等於是一堆廢鐵,不會理會我們對它下達的「命令」。於是,我們要馴服它,只有通過一種方式——程序,這也是我們和計算機溝通的唯一方式。
那程序到底是什麼呢?
程序也就是指令的集合,它告訴計算機如何執行特殊的任務。
打個比方說,它好比指導你烹調菜品的菜譜或指揮行駛一路到達目的地的交警(或者交通路標)。沒有這些特殊的指令,就不能執行預期的任務。計算機也一樣,當你想讓計算機為你做一件事情的時候,計算機本身並不能主動為我們工作,因此我們必須對它下達指令,而它根本不會也不可能聽懂人類自然語言對事情的描述,因此我們必須使用程序來告訴計算機做什麼事情以及如何去做?甚至對最簡單的任務也需要指令,例如如何取得擊鍵,怎樣在屏幕上放一個字母,怎樣在磁碟中保存文件等等。
這么麻煩,連這些東西編程都要考慮!怪不得人家說編程好難!你錯了,其實許多這樣的指令都是現成的,包含在處理晶元中內置於操作系統中,因此我們不必擔心它們工作,他們都是由處理器和操作系統來完成的,並不需要我們來干預這些過程。
上面講到的計算機本身不會主動的做任何事情。因此我們要通過程序的方式來讓計算機為我們「效勞」。而這個過程就是我們「編」出來的。編程可以使用某一種程序設計語言來實現,按照這種語言的語法來描述讓計算機要做的事情。
我們這里所講的語法和外語中的語法完全兩碼事,這里講的語法只是讀你的程序書寫做出一寫規定而已。
寫出程序後,再由特殊的軟體將你的程序解釋或翻譯成計算機能夠識別的「計算機語言」,然後計算機就可以「聽得懂」你的話了,並會按照你的吩咐去做事了。因此,編程實際上也就是「人給計算機出規則」這么一個過程。
隨計算機語言的種類非常的多,總的來說可以分成機器語言,匯編語言,高級語言三大類。
電腦每做的一次動作,一個步驟,都是按照已經用計算機語言編好的程序來執行,程序是計算機要執行的指令的集合,而程序全部都是用我們所掌握的語言來編寫的。所以人們要控制計算機一定要通過計算機語言向計算機發出命令。
計算機所能識別的語言只有機器語言,即由構成的代碼。但通常人們編程時,不採用機器語言,因為它非常難於記憶和識別。
目前通用的編程語言有兩種形式:匯編語言和高級語言。
匯編語言的實質和機器語言是相同的,都是直接對硬體操作,只不過指令採用了英文縮寫的標識符,更容易識別和記憶。它同樣需要編程者將每一步具體的操作用命令的形式寫出來。
匯編程序的每一句指令只能對應實際操作過程中的一個很細微的動作,例如移動、自增,因此匯編源程序一般比較冗長、復雜、容易出錯,而且使用匯編語言編程需要有更多的計算機專業知識,但匯編語言的優點也是顯而易見的,用匯編語言所能完成的操作不是一般高級語言所能實現的,而且源程序經匯編生成的可執行文件不僅比較小,而且執行速度很快。
高級語言是目前絕大多數編程者的選擇。和匯編語言相比,它不但將許多相關的機器指令合成為單條指令並且去掉了與具體操作有關但與完成工作無關的細節,例如使用堆棧、寄存器等,這樣就大大簡化了程序中的指令。由於省略了很多細節,所以編程者也不需要具備太多的專業知識。
高級語言主要是相對於匯編語言而言,它並不是特指某一種具體的語言,而是包括了很多編程語言,如目前流行的VB、VC、FoxPro、Delphi等,這些語言的語法、命令格式都各不相同。
(1)解釋類:執行方式類似於我們日常生活中的「同聲翻譯」,應用程序源代碼一邊由相應語言的解釋器「翻譯」成目標代碼(機器語言),一邊執行,因此效率比較低,而且不能生成可獨立執行的可執行文件,應用程序不能脫離其解釋器,但這種方式比較靈活,可以動態地調整、修改應用程序。
(2)編譯類:編譯是指在應用源程序執行之前,就將程序源代碼「翻譯」成目標代碼(機器語言),因此其目標程序可以脫離其語言環境獨立執行,使用比較方便、效率較高。但應用程序一旦需要修改,必須先修改源代碼,再重新編譯生成新的目標文件(*.OBJ)才能執行,只有目標文件而沒有源代碼,修改很不方便。現在大多數的編程語言都是編譯型的,例如Visual Basic、Visual C++、Visual Foxpro、Delphi等。
這個問題其實很簡單。前面我們講到,程序是人與計算機進行溝通的唯一方式,因此我們要讓計算機為我們服務,就必須有程序,而程序從哪裡來?當然是由我們編寫出來了。或許你又會問到另一個問題:現在要什麼程序有什麼程序,我幹嘛還要編程呢?這你就錯了,現在的程序雖然很多,需要什麼樣的程序直接到網上不需要很長時間就可以找到類似的,而且有可能就是你所需要的。但是,就好比去買衣服,雖然賣衣服的到處都是,但是哪一件是為你「量身定做」的呢!
程序還能夠做很多事情不同的程序可以完成不同的事情。從大的方面到管理國家的財務,小的方面管理家庭的帳務。
又如,如果你想要你的計算機能播放動畫,那麼你的計算機中也要有相應的動畫播放程序,下面所示的就是一個F1ssh動畫播放器。我們將會在後面的章節具體講述這個程序的編制過程。
隨著計算機的飛速發展,總會有那麼一天將不會編程的人列為「文盲」。你不希望吧?那麼就好好的學習一種程序設計語言吧。
編程會過時嗎
編程會過時嗎?這個問題,讓我先問你一個問題:計算機會消失嗎?這兩者答案是一樣的。知道了計算機會不會消失,就知道了編程會不會過時。
編程工具會過時,而編程卻不會過時
計算機系統由可以看見的硬倒:系統和看不見的軟體系統組成。要使計算機能夠正常的工作,僅僅有硬體系統是不行的,沒有軟倒系統(即沒有程序)的計算機可以說只是—堆廢鐵,什麼事情都幹不了。例如當你撰寫—篇文章的時候,你需要在操作系統中用文字編輯軟體來實現文字的輸入,但如果沒有這些文字輸入軟體的話,你是否想過如何向計算機中輸入文章呢?很難想像出如何在一個沒有任何軟體的計算機(我們稱之為裸機)上進行文字的輸入。而這些軟體其實就是通常我們所說的程序。
編程會過時嗎?我們從另一個角度來考慮這個問題,計算機有——天會消失嗎?如果有一天當世界上所有的事情處理都用不到計算機了,那麼計算機將會很快的消失,那時編程不僅過時了,而且也會隨之消失了。但是計算機會消失嗎?當然不會,如今計算機應用到每一領域,為人類的發展做出了不可估量的貢獻。試想一下如果有一天全世界的計算機突然消失了,那麼這個世界將變成什麼樣子,或許和全世界都停電了一樣恐怖,甚至還會有更大的損失。計算機的存在必須要有軟體系統來維持。因此編程永遠不會、也不可能會過時。
計算機程序設計語言發展到今天,已經從最原始的機器語言發展到如今可視化的集成開發環境,甚至集多種語言在同一開發平台上,像微軟的NET平台。回頭看看程序設計語言的發展史,不難看出對於編程來說,只會出現編程工具的過時,不會出現編程本身的過時。
不斷變化的技術需要不斷變化的程序員
從二十世紀60年代以後,計算機得到了突飛猛進的發展。似乎歷史上沒有任何一門科學的發展速度超過了計算機的發展,無論硬體、軟體、還是網路都以驚人的速度向前發展。計算機的硬體發展速度遵循「摩爾定律」每十八個月速度翻一倍(實際現在已超過了這個速度)。 軟體的發展速度和硬體一樣,二十世紀九十年代中國的軟體業還不是很成熟,而現在大大小小 的軟體企業四處聳立,共享軟體網上隨處可見。不斷發展的技術需要不斷變化的程序員,例如,如今Visual Basic可以快速構Windows下的應用程序,程序設計方面的技術不斷發展著,不斷引進新的概念、新的方法,如從結構化的C開始,當面向對象的思想被提出後,出現了C++,微軟在C++的基礎上為使用戶構建win32應用程序更加方便,推出了Visual C++。這也就需要程序員也要不斷的更新自己的技術。
計算機科學與別的學科很不一樣,不像語言學、歷史學那樣,幾乎是永久不變的東西。計算機科學要求不斷的更新自己的知識,否則很快就會被淘汰,即便是編程亦是如此。
編寫程序是一件很有趣的事情,因為編寫程序可以干很多高級的事情。例如我們在後面的章節中介紹如何使用Visual Basic編寫Flash動畫播放器,以及如何編寫下載軟體管理器等。如果你願意的話,你完全可以編寫出比這些更高級的程序來。
隨著計算機軟體業的發展,誕生了「程序員」這個職位。於是便形成了一種理念,編寫程 序的人就是程序員,因此編程是程序員的事情。但程序員並不是一開始就是程序員,他們也是從現在我們的位置慢慢成為程序員的。
編寫程序是一件很有趣的事情,因為編寫程序可以干很多高級的事情。例如我們在後面的章節中介紹如何使用Visual Basic編寫Flash動畫播放器,以及如何編寫下載軟體管理器等。如果你願意的話,你完全可以編寫出比這些更高級的程序來。
編程也可以作為——種愛好或興趣,如果你對它感興趣學起來就容易多了!因為如果對編程感興趣的話,就會多看些有關方面的書、多編些小程序上機實踐,這些對於學習編程的幫助是非常大的,而且隨著學習的進程不斷的推進就會覺得它並不是很困難,相反卻是很容易的。
總之,在學習編程時一定要堅持不懈,只要有信心、有毅力就一定能學好;不能因為一些似是而非的觀念就動搖了自己的信心。
我們一起來編程
面對擺在面前的計算機該如何操作,相信這個問題已經不再是困擾大家的首要問題了。現在軟體的種類那麼多,在選用的時候「電腦發燒友」的心裡是否也想過有一天自己能編寫一款屬於自己的軟體呢?想學習編程的朋友在選擇程序語言時會不會因為不知道如何選擇而大感頭痛呢?在不知如何下手的時候,朋友們的心中是不是會產生「我是不是可以編程」的思想呢?但是又有哪個程序員是不經過學習就能成功的呢!其實編寫程序並不是人們所想像的那麼困難、那麼復雜,每個有心致力於學習計算機的朋友都是可以嘗試的!
選擇適合自己的程序語言的必要性
目前常用的基本程序語言的種類比較繁多,比較簡單的有:Pascal、c語言、qBasic、 Fortran、Visual Basic等等。但前幾種都是在DOS下進行編程的工具,Visual Basic是在 Windows下進行應用程序設計的編程工具,現在一般的計算機用戶幾乎都不再使用DOS了,因此我們通常會選擇Visual Basic作為初學者的編程工具。Visual Basic是Windows應用程序設計中最容易上手的編程工具,學習步驟也比較容易被初學者接受。對於剛開始學習編程的初學者來說,還是選擇Visual Basic,學習編程語言不能想像著一步登天,一步一個腳印的學習才是最佳方法。
堅定自己學習編寫程序的信心
編寫程序並不是具有專業知識的人員才有的專利,每個學習計算機的人都可以編寫程序,每個人的靈感不同,在編寫程序的思路和作法上又有區別。但共同的想法就是編寫成功的程序。學習編程是一個漫長的過程,其中要付出艱辛的努力和汗水,不過成功者的喜悅又不是別人所能體會的。克服學習中的困難,努力去實踐,要有一個思想:別人能做到的事情自己也一定可以做到。計算機的普及讓更多的人有了學習的機會,也讓更多的人參與到編程人員的隊伍中來,每個人都有編程的權利,機遇給予每個人都是平等的。拿出自己必勝的信心,在編程的道路工勇於進取,相信成功就會在眼前。
三、我可以編程嗎
隨著計算機軟體業的發展,誕生了「程序員」這個職位。於是便形成了一種理念,編寫程 序的人就是程序員,因此編程是程序員的事情。但程序員並不是一開始就是程序員,他們也是從現在我們的位置慢慢成為程序員的。
編寫程序是一件很有趣的事情,因為編寫程序可以干很多高級的事情。例如我們在後面的章節中介紹如何使用Visual Basic編寫Flash動畫播放器,以及如何編寫下載軟體管理器等。如果你願意的話,你完全可以編寫出比這些更高級的程序來。
編程也可以作為——種愛好或興趣,如果你對它感興趣學起來就容易多了!因為如果對編程感興趣的話,就會多看些有關方面的書、多編些小程序上機實踐,這些對於學習編程的幫助是非常大的,而且隨著學習的進程不斷的推進就會覺得它並不是很困難,相反卻是很容易的。
總之,在學習編程時一定要堅持不懈,只要有信心、有毅力就一定能學好;不能因為一些似是而非的觀念就動搖了自己的信心。
四、我們一起來編程
面對擺在面前的計算機該如何操作,相信這個問題已經不再是困擾大家的首要問題了。現在軟體的種類那麼多,在選用的時候「電腦發燒友」的心裡是否也想過有一天自己能編寫一款屬於自己的軟體呢?想學習編程的朋友在選擇程序語言時會不會因為不知道如何選擇而大感頭痛呢?在不知如何下手的時候,朋友們的心中是不是會產生「我是不是可以編程」的思想呢?但是又有哪個程序員是不經過學習就能成功的呢!其實編寫程序並不是人們所想像的那麼困難、那麼復雜,每個有心致力於學習計算機的朋友都是可以嘗試的!
選擇適合自己的程序語言的必要性
目前常用的基本程序語言的種類比較繁多,比較簡單的有:Pascal、c語言、qBasic、 Fortran、Visual Basic等等。但前幾種都是在DOS下進行編程的工具,Visual Basic是在 Windows下進行應用程序設計的編程工具,現在一般的計算機用戶幾乎都不再使用DOS了,因此我們通常會選擇Visual Basic作為初學者的編程工具。Visual Basic是Windows應用程序設計中最容易上手的編程工具,學習步驟也比較容易被初學者接受。對於剛開始學習編程的初學者來說,還是選擇Visual Basic,學習編程語言不能想像著一步登天,一步一個腳印的學習才是最佳方法。
堅定自己學習編寫程序的信心
編寫程序並不是具有專業知識的人員才有的專利,每個學習計算機的人都可以編寫程序,每個人的靈感不同,在編寫程序的思路和作法上又有區別。但共同的想法就是編寫成功的程序。學習編程是一個漫長的過程,其中要付出艱辛的努力和汗水,不過成功者的喜悅又不是別人所能體會的。克服學習中的困難,努力去實踐,要有一個思想:別人能做到的事情自己也一定可以做到。計算機的普及讓更多的人有了學習的機會,也讓更多的人參與到編程人員的隊伍中來,每個人都有編程的權利,機遇給予每個人都是平等的。拿出自己必勝的信心,在編程的道路工勇於進取,相信成功就會在眼前。
C. 程序員需要精通底層實現及原理嗎
高級的程序員需要知道,因為他們開發的都是底層的東西需要這些知識。想我們普通的程序員你不做這方面的項目是不需要了解這些的。
D. 中高級IOS開發程序員要具備哪些能力和技能
一、數據加密必備技能-密碼學
在網路加速發展的時代,數據安全已經是一個必不可少的技術課題。如何讓用戶數據、網路數據、內容數據安
全可靠,也是每個開發者需要深思並捍衛的。熟練掌握密碼學原理,了解 MD5 演算法、非對稱、對稱加密演算法底 層實現,以及如何運用到項目開發中。讓開發者實力捍衛數據安全!
1.密碼的起源歷史
2.Base 64 編碼格式、散列函數
3.MD5 &加鹽、HMAC加密
4.對稱加密演算法
5.RSA Openssl、數字簽名
二、RunLoop
RunLoop是iOS和OS X中非常基礎的一個概念,在開發中不常用,在面試中也幾乎是都會問到的一個問題.對RunLoop的概念以及底層實現原理,都是我們應該要掌握的,並且要知道在開發中哪些地方可以使用到RunLoop。
1.能理解RunLoop概念
2.知道RunLoop的使用方式
3.RunLoop在開發中的使用
三、Runtime
OC 縱橫 iOS 開發已經多年,但是我們真的了解他們?他到底是怎麼樣的一個底層原理?在使用上難道就真的只有
這樣?我們該如何更加掌握這門語言的應用?另外 OC 能做到的 Swift 也能做到嗎?
1.runtime 到底是什麼
2.runtime 怎麼運用
3.runtime 怎麼運用
4.siwft 中如何使用runtime
四、SDWebImage源碼的分析
在開發中, 為了提高工作的效率, 我們大都會引入很多的框架, 覺得只要能能完成自己的工作達到目的就行, 當然這沒錯,但是確忽略了很多好框架中的編程思想,和實現的邏輯, 只知道使用框架, 不知道它裡面的精髓, 長遠來說對我們的發展是不好的, 所以讓我們從經典的框架開始學起,一起來學習SDWebImage的精髓.
1.SDWebImage的demo的分析
2.SDWebImage緩存的概念
3.下載超時和圖片的格式區分
4.SDWebImage的清理機制和內存的監聽
五、H264編碼
扎克伯格說「視頻是未來facebook社交的最重要的行為之一」。作為開發而言,我們應該了解視頻如何做到編碼。在直播平台編碼的技術也是頻頻使用,讓我們從業務層跨往視頻編碼底層的第一步。
1.了解直播項目的架構以及技術突破點;
2.視頻組成原理
3.H264文件的結構
4.軟編碼和硬編碼的區別以及應用場景
5.硬編碼的原理
6.使用硬編碼編碼視頻文件
7.H264解碼的多種處理方式
六、AAC編碼
直播、音視頻項目已經是iOS 應用類的APP的中堅力量。解密音頻編碼過程,讓開發者不在對編碼諱莫如深。映客、全名K歌、網易雲音樂等等知名APP都會用到的音頻AAC編碼方式。
1.了解聲音從模擬信號到數字信號的原理
2.PCM編碼解析
3.AAC編碼原理
4.AAC文件的結構
5.音頻在軟編碼FFmpeg 和 硬編碼的區別
6.利用硬編碼編碼音頻
7.捕獲媒體數據,如何區分音視頻數據
8.利用FFmpeg 合成 H264文件和AAC文件到MP4容器中
E. java工作原理
Java工作原理
由四方面組成:
(1)Java編程語言
(2)Java類文件格式
(3)Java虛擬機
(4)Java應用程序介面
當編輯並運行一個Java程序時,需要同時涉及到這四種方面。使用文字編輯軟體(例如記事本、寫字板、UltraEdit等)或集成開發環境(Eclipse、MyEclipse等)在Java源文件中定義不同的類 ,通過調用類(這些類實現了Java API)中的方法來訪問資源系統,把源文件編譯生成一種二進制中間碼,存儲在class文件中,然後再通過運行與操作系統平台環境相對應的Java虛擬機來運行class文件,執行編譯產生的位元組碼,調用class文件中實現的方法來滿足程序的Java API調用 。
F. 怎麼解釋軟體的工作原理
為什麼「瀏覽器劫持」能夠如此猖狂呢?放眼眾多論壇的求助貼,我們不時可以看到諸如「我的IE被主頁被改了,我用殺毒工具掃了一遍都沒發現病毒,我把主頁改回自己的地址,可是一重啟它又回來了!」、「我的系統一開機就跳出一個廣告,我明明用了最新版的殺毒軟體的啊!」等這類關於IE異常問題的求助,80%的提問者都表示納悶,他們已經安裝了殺毒軟體,可是IE仍然被「黑」了,這又是為什麼?
其實這些都是典型的「瀏覽器劫持」現象,但是受害者不是已經安裝了殺毒軟體嗎?為什麼瀏覽器依然躲不過這只黑手?許多用戶對這個領域都存在一種誤區心理:瀏覽器劫持?我有最新的殺毒軟體,我不怕!
於是,當他們遭遇「瀏覽器劫持」時,驚訝了。
要知道,殺毒軟體自身也只是一種輔助工具,它不可能完全保護系統的安全,更何況,殺毒軟體用戶必須知道一個事實:「瀏覽器劫持」的攻擊手段是可以通過被系統認可的「合法途徑」來進行的!殺毒軟體只能通過「特徵碼」的形式來判斷程序是否合法,但這是建立在人為定義以後的,而實施「瀏覽器劫持」的程序可以有很多,防不勝防。
為什麼說「瀏覽器劫持」可以說是合法的呢?因為大部分瀏覽器劫持的發起者,都是通過一種被稱為「BHO」(Browser Helper Object,瀏覽器輔助對象)的技術手段植入系統的。
BHO是微軟早在1999年推出的作為瀏覽器對第三方程序員開放交互介面的業界標准,它是一種可以讓程序員使用簡單代碼進入瀏覽器領域的「交互介面」(INTERACTIVED Interface)。通過BHO介面,第三方程序員可以自己編寫代碼獲取瀏覽器的一些行為(Action)和事件通知(Event),如「後退」、「前進」、「當前頁面」等,甚至可以獲取瀏覽器的各個組件信息,像菜單、工具欄、坐標等。由於BHO的交互特性,程序員還可以使用代碼去控制瀏覽器的行為,比如常見的修改替換瀏覽器工具欄、在瀏覽器界面上添加自己的程序按鈕等操作,而這些操作都被視為「合法」的,這就是一切罪惡根源的開始。
BHO的出現幫助程序員更好的打造個性化瀏覽器或者為自己的程序實現了方便簡潔的交互功能,可以說,如果沒有BHO介面的誕生,我們今天就不能用一些工具實現個性化IE的功能了。從某一方面來看,BHO的確是各種繽紛網路互動功能的幕後功臣,但是一切事物都是有兩面性的,這個恆古不變的真理同樣對BHO有效,於是就有了今天讓安全界頭痛的「瀏覽器劫持」的攻擊手段誕生。
看看前面我提到的BHO介面特性,你想到了什麼?BHO可以獲知和實現瀏覽器的大部分事件和功能,也就是說,它可以利用少量的代碼控制瀏覽器行為。程序員可以設計出一個BHO按鈕以實現用戶點擊時通知瀏覽器跳轉到某個頁面完成交互功能,當然就可以進一步寫出控制瀏覽器跳轉到他想讓用戶去的頁面,這就是最初的「瀏覽器劫持」的成因:BHO劫持。
在描述BHO劫持之前,我們先要對BHO介面的啟動做個簡單介紹:符合BHO介面標準的程序代碼被寫為DLL動態鏈接庫形式在注冊表裡注冊為COM對象,還要在BHO介面的注冊表入口處進行組件注冊,以後每次IE啟動時都會通過這里描述的注冊信息調用載入這個DLL文件,而這個DLL文件就因此成為IE的一個模塊(BHO組件),與IE共享一個運行周期,直到IE被關閉。
IE啟動時,會載入任何BHO組件,這些組件直接進入IE領域,而IE則成為它們的父進程和載體,從此IE的每一個事件都會通過IUnknown介面傳遞到BHO用以提供交互的IObjectWithSite介面里,這是BHO實現與IE交互的入口函數。
BHO接收到IE介面傳遞來的參數後開始判斷IE正在做什麼,理論上BHO可以獲取IE的大部分事件,然後根據程序員編寫的代碼,BHO持有對特定事件做出反應的決定權,例如一個可以實現「中文網址」的BHO,就是通過GetSite方法獲取到IE當前打開的站點URL(或通過IURLSearchHook介面來獲知),如果BHO發現獲取到的URL和內置的判斷條件匹配,該BHO就會啟用SetSite方法強制IE跳轉到程序員設定的頁面去,這個過程就是利用about:blank篡改主頁的「瀏覽器劫持」方法之一,它的實現原理其實很簡單,程序員編寫一個惡意BHO組件,當它獲取到IE窗口的當前站點為「about:blank」時就強制IE內部跳轉到指定的廣告頁面,於是鬧出了不久之前沸沸揚揚的「IE空白頁劫持事件」。
了解了這種類似惡作劇的作案手段,要解決它就容易了,只要找到並刪除這個隱藏在系統里的BHO程序即可。
除了這類「廣告軟體」性質的BHO,還有一種利用IURLSearchHook介面實現的另一類更隱蔽的BHO,這種BHO從某些方面來說大概不算BHO,因為它並不是響應IUnknown,而是等待IE創建IURLSearchHook來啟動。IURLSearchHook被瀏覽器用來轉換一個未知的URL協議地址,當瀏覽器企圖去打開一個未知協議的URL地址時,瀏覽器首先嘗試從這個地址得到當前的協議,如果不成功,瀏覽器將尋找系統里所有注冊為「URL Search Hook」(資源搜索鉤子,USH)的對象並把這個IE不能理解的地址發送過去,如果某個USH對象「認識」這個地址,它就返回一個特定的標識告訴IE它知道怎麼打開這個地址,然後IE就根據約定的方法調用它,最終打開這個地址。其實USH對象並不陌生,我們一些偷懶的用戶就經常為了省事而不輸入「http://」,但是IE最終還是能認出並打開某個地址,就是USH的功勞,但是這一點又被惡意程序員拿來磨刀了,通過創建自己的USH對象,惡意程序員能夠命令IE在找不到一些網站時自動跳轉到事先設置的站點里,如果這個站點帶毒或者掛馬,用戶就完了。
這類BHO的解決方法和前面一樣,只是它比較隱蔽,除非用戶經常偷懶,否則可能直到系統崩潰也不會知道自己已經感染了這種東西。也許你會說,只要用戶的輸入永遠不會讓IE無法識別,這種滲透不就白費了?但是事實不容樂觀,我們無法得知BHO作者還會不會通過其他方法攔截IE,說不定每隔一段時間就讓IE彈出一個廣告呢?
上面說了這么多BHO和IE合作搞破壞的事例,可能會給讀者造成一種「BHO必須在IE傳遞數據後才能行動」的誤解,然而事實並非如此,瀏覽器自身也是一個標準的可執行程序,而BHO只是借用這個程序進程啟動的DLL,它並非API那種要用的時候就讓你過來忙活,忙活完了就一腳踹開的奴隸形態DLL,前面說過了,BHO是一種在瀏覽器載入時一同啟動的常式,它相當於一種自身運行邏輯不太明確的子進程(裡面都是對IE事件的響應和操作代碼),這個特性就造成了BHO DLL和API DLL本質的區別,BHO並不需要所有事件都必須依賴這個大傢伙,它可以有自己決定的權利,只要適當的修改,就能用BHO實現類似DLL木馬的功能,當然,這並不是說我們就能在IE眼皮下公然的肆無忌彈干壞事的,由於BHO自身是作為IE子進程啟動的,它就必須受到一些限制,例如程序員不能在裡面自己創建網路連接,這樣會導致IE報錯崩潰並供出你寫的DLL,害怕BHO成為另一種後門的用戶可以鬆口氣了,要在BHO里實現Winsock大概只能在IE休息的時候才可以,但是會有哪個用戶開著個開空IE什麼事情都不做呢?
但這並不是說BHO就一定能無害了,雖然用它不能做到遠程式控制制,但是別忘記,BHO能看到IE的所有東西,也就能任意的訪問用戶文件和注冊表,在這個條件成立的前提下,入侵者可以編寫代碼查找用戶隱私,然後在適當時候通過SetSite提交出去——誰叫現在Webmail這么流行呢?這就是為什麼許多廠商發布諸如「中文網址」、「網路搜索」、「IE定製」、「IE監視」這些功能的BHO的同時都保證「不搜集用戶隱私」的原因,只要你想要,BHO就能得到一切。
有些人也許會想,既然BHO是微軟瀏覽器的權利,那我不用IE了,我用Opera、Firefox不行?對於這點固然無可厚非,但是你用不用Windows?用不用共享軟體?如果你用Windows,那麼,你仍然可能處於被BHO接觸到的世界,因為Windows本身就是和IE緊密結合的,這就把「IE進程」的范圍給擴大了,細心的用戶大概會發現,IE里能直接訪問「我的電腦」,「我的電腦」窗口也能迅速變成IE,因為它們實質都是依賴於IE內核的,正因為這個原因,BHO可以在你打開一個文件夾時跟著偷偷啟動。同時,現在的網路正處於一種「共享軟體捆綁戰略」大肆實施的時代,你再小心也不能避免某些共享軟體固定捆綁了BHO的行為,安裝後你才會發現文件夾上又多了個什麼「助手」、「搜索」了。要想徹底逃開BHO的圍困,大概只能放棄使用Windows了。
Hook,你鉤住瀏覽器了
正如《侏》里的這句話一樣,入侵者也在不斷尋找他們的新出路,雖然上面我說了這么多BHO的負面事例,但是真正的危機並不是只有BHO的,在一些使用BHO行不通的場合里,入侵者開始投擲他們的鉤子。
什麼是鉤子?讓我們先看看它的官方定義:
鉤子(Hook),是Windows消息處理機制的一個平台,應用程序可以在上面設置子程以監視指定窗口的某種消息,而且所監視的窗口可以是其他進程所創建的。當消息到達後,在目標窗口處理函數之前處理它。鉤子機制允許應用程序截獲處理window消息或特定事件。
鉤子實際上是一個處理消息的程序段,通過系統調用,把它掛入系統。每當特定的消息發出,在沒有到達目的窗口前,鉤子程序就先捕獲該消息,亦即鉤子函數先得到控制權。這時鉤子函數即可以加工處理(改變)該消息,也可以不作處理而繼續傳遞該消息,還可以強制結束消息的傳遞。
可能上面的官方定義對一部分讀者理解有點困難,其實,鉤子就像是一切程序的「先知」,一個實現了鉤子的程序自身雖然也是普通程序,但是它總能在別的程序得到數據之前就已經知道了一切,這是為什麼呢?對Windows系統有一定了解的讀者應該知道,Windows系統是一個通過「信息處理機制」運作的系統,在這個系統里傳遞的數據都是通過「消息」(Message)的形式發送的,各個消息都遵循了官方的約定,否則就不能讓系統產生回應。而且這個傳遞步驟是顛倒的,例如我們關閉了某個程序,我們可能會認為是程序自己關閉後通知系統的,其實不然,當用戶點擊關閉按鈕的時候,Windows就會把一個叫做WM_CLOSE的消息傳遞給這個程序,程序接收到消息後就執行卸載自身常式的操作。理解了這點,就能知道鉤子的原理了,所謂鉤子程序,就是利用了系統提供的Hook API,讓自己比每一個程序都提前接收到系統消息,然後做出處理,如果一個鉤子攔截了系統給某個程序的WM_CLOSE消息,那麼這個程序就會因為接收不到關閉消息而無法關閉自身。除了消息以外,鉤子還可以攔截API,像我們都熟悉的屏幕翻譯軟體就是Hook了一些文本輸出函數如TextOutA而達到了目的。
技術讓編程人員可以輕松獲取其他程序的一些有用數據或傳遞相關數據,像現在常見的一些游戲外掛,它們就是利用Hook技術鉤住了游戲窗體,然後就可以識別游戲裡面的行為和模擬發送按鍵滑鼠消息,最終實現電腦自己玩游戲的功能。把這個技術應用到瀏覽器上面,就成了另一種控制瀏覽器行為的方法。
鉤子有兩種,本地鉤子(Local Hook)和全局鉤子(Global Hook),本地鉤子只在本進程里起作用,故不屬於討論范圍;全局鉤子代碼必須以DLL形式編寫,以便在鉤子生效時被其它進程所載入調用,因此我們看到的大部分Hook程序都是DLL形式的。
其實之前提到的BHO也可以視為一種針對IE的鉤子,它鉤的是IE的事件,這就是IE與BHO交互的起點,但是對於再復雜一點的操作,例如判斷IE下載的是GIF圖片還是JPEG圖片,BHO無能為力,因為它僅僅知道IE的事件為DownloadBegin和DownloadComplete,對於具體內容,IE本身是不會告訴它的,否則IE豈不是要忙死了?至少我也沒見過哪個領導還需要向秘書匯報中午吃了雞肉還是鴨肉的吧,BHO可不是IE的老婆,或者說IE沒有氣管炎。
所以,為了得到IE的更多數據,程序員開始鉤IE了。與BHO不同,鉤子不需要被動的等待IE事件,它直接和IE形成上司對下屬的關系,這次輪到IE要做什麼都得經過它批准了。Hook形式的控制不需要DLL文件必須與IE的注冊表入口產生組件關系,它可以是一個獨立的DLL,通過Rundll32.exe或自帶的Loader EXE啟動,而且由於它屬於Hook形式, 在鉤子有效的情況下會被系統自動插入其他程序的進程中,是不是有點像DLL木馬呢?
IE鉤子程序載入進程後便能獲知所有的消息類型、API和內容,一旦發現某個符合要求的消息,如IE執行了某個事件,或者用戶輸入了特定內容,鉤子的處理代碼就開始工作了,它先攔截系統發送給IE的消息,然後分析消息內容,根據不同消息內容作出修改後再發給IE,就完成了一次Hook篡改過程。用著名的3721實名搜索做例子,一些人會以為它是採用了BHO或者IURLSearchHook完成中文域名的識別跳轉的,其實它是用了能夠第一個得到Windows消息的Hook技術,這樣一來就可以避免被其他的競爭對手搶先解析域名了:3721的主程序就是一個Hook DLL,它監視IE地址欄的消息,一旦用戶輸入的是中文,它便在其他BHO類插件工作之前攔截了這個消息,並調用自身代碼完成中文域名到英文URL的轉換工作,然後返回(也可能與自己的BHO DLL配合)一個讓IE跳轉到英文URL的消息,完成域名的翻譯任務。
IE鉤子能幫助程序員用少量代碼完成更多的IE交互工作,但是一旦這個鉤子被用於犯罪,其後果也是嚴重的,惡意程序員可以寫一個攔截IE輸入的鍵盤鉤子,達到竊取密碼的作用,這樣無論你是用HTTP明文協議還是SecurityHTTP加密協議都不能逃避密碼被盜的下場了,因為它抓的是你在IE里的輸入,後面的數據傳輸已經不重要了。
Winsock LSP
全稱為「Windows Socket Layered Service Provider」(分層服務提供商),這是Winsock 2.0才有的功能,它需要Winsock支持服務提供商介面(Service Provider Interface,SPI)才能實現,SPI是一種不能獨立工作的技術,它依賴於系統商已經存在的基本協議提供商,如TCP/IP協議等,在這些協議上派分出的子協議即為「分層協議」,如SSL等,它們必須通過一定的介面函數調用,LSP就是這些協議的介面。
通過LSP,我們可以比分析基本協議更簡單的得到我們想要的數據內容,如直接得到系統上運行的瀏覽器當前正在進行傳輸的地址和內容,不管這個瀏覽器是IE,還是Opera或Firefox,因為LSP是直接從Winsock獲取信息的,即使不用微軟生產的汽車,至少你這輛汽車一直是在微軟建造的公路上跑的吧。
LSP用在正途上可以方便程序員們編寫監視系統網路通訊情況的Sniffer,可是現在常見的LSP都被用於瀏覽器劫持,使用戶又多了個噩夢。