程式者的胡言亂語

pageicon 星期五 五月 18, 2007

乖,葛格幫你打個針

說實話,我對Windows作業系統實在是外行(啊,其實對每個作業系統都外行),不過,前一陣子在玩API hooking時,看到WindowsDLL injection的技巧,還是不免覺得很妙。前幾天又在重溫API hooking的相關東西,又看到DLL injectioncode,所以覺得下這個標題不錯,就想說來給它記錄一下。


DLL injection就是把你的DLL注射到另一個process定址空間裡。在現代作業系統裡頭個別的process都是在各自獨立的定址空間裡,要像DOS那樣,所有的process共用同一個定址空間(如果連TSR也算的話,是可以有process啦),已經不多見了。所以,作業系統的基本責任之一,就是保護各個process彼此之間互不侵犯,所以因為有獨立的定址空間,同一個位址值,對不同的process可能具有不同的意義。這意謂著,你不能隨便的去寫甚至是讀取別的processmemory內容。


API hooking有很多實現的技巧,無論如何,你都需要進入你想要hook它的process,以便做一些事情。但這在有Windows作業系統維持各process之領域範圍的情況下,要怎麼去達到了。這就是我當初看到打針技巧時,覺得很妙的地方。


怎麼做DLL injection呢?隨便在Googlesearch一下,應該可以找到一堆。不過你可以參考


它的主要精神,大概是兩個重點,第一個是先利用GetProcAddress()取得kernal32.dll裡的LoadLibraryALoadLibraryW這兩個函式的位址,接著呢,用一個叫做CreateRemoteThread()API指定你想要注射的process,去執行LoadLibrary()這個函式。LoadLibrary是用來載入某個DLL的,這時候要載入那個DLL呢?當然就是你想注射的DLL。所以當CreateRemoteThread()做完後,你的DLL就會被你的對象process給載入,也就是說,它會成為該process定址空間的一部份,它就被注射進去了。


好啦,注射進去後,已經成為該process的一部份,和該process一整個融為一體。但這還不夠,因為被注射進去後,你通常還會想要做一些事情(例如去把人家API的函式位址換成自己提供的)。所以,要怎麼讓這「一些事情」被執行呢?如果你寫的是C++,你可以宣告一個globalobject,此時為了要初始化這個object,這個objectconstructor就會被執行,所以想做什麼就統統丟到它的constructor去吧。如果寫的是C,那也沒關係,寫到DllMain()裡,當process attach上這個DLL時,就做你想做的事吧。這時候你的DLL已經在別人的process裡了,所以想改什麼就改什麼啊。


當初想到用CreateRemoteThread()叫別的processLoadLibrary()的人,還真是厲害又有創意啊。

pageicon 星期二 二月 27, 2007

偵測Win32上視窗的建立及被開啟

最近在做一個有趣的東西,是要偵測MSN Messenger的對話視窗。當MSN有一個新的對話視窗被產生時,我得要知道。另外,當這個視窗首次被使用者開啟起來檢視時,我也得要知道。


MSN每次收到每段對話的第一個訊息時,都會在Task Bar上產生一個新的視窗,但不會加以開啟。


要做到上述的目的,利用API hooking可以做的到。第一樣事,也就是偵測MSN有一個新的對話視窗被產生,只要hook MSN的執行檔所呼叫的CreateWindowExW()即可。因為如果傳來的對話訊息導致新的對話視窗被建立,那麼便會呼叫CreateWindowExW()來產生這個對話視窗。


但要達到第二個目的,也就是偵測這個視窗首次被使用者開啟起來檢視,可花了我一些時間。針對MSN著手,無論是什麼ShowWindow()SwitchToThisWindow()SetWindowPos()…之類的user32.dll中的function,都沒有用。我覺得這真是太怪了。


仔細思考了一下,倘若直接從MSN的連絡人清單中開啟,視窗的活動便能攔截到。但如果是從Task Bar上把它點選出來,卻絲毫沒有反應。是呀,Task Bar是另一個process啊!如果只hookMSN Messengerprocess是沒用的,因為呼叫user32.dll中函式的並不是MSN Messengerprocess,而是擁有Task Barprocess呀。


剩下的問題就是,誰擁有Task Bar呢?答案是iexplorer.exe。把它也給inject進去後,果然,當對話視窗被開啟時,就能偵測到SwitchToThisWindow()被呼叫了。

pageicon 星期一 二月 26, 2007

介紹API Hooking的文章

有讀者留言問到他想要hook ws2_32.dll。我建議可以從一篇在code project網站上的文章著手。這篇文章的網址是在:


http://www.codeproject.com/system/Paladin.asp


所謂的API hooking就是讓某(或多個)process在執行某些特定的DLL中的函式時,執行的其實是你所撰寫、外表相同的函式。透過這種方式,可以偷天換日,讓原process以為它執行的仍舊是原先的DLL中的函式,卻不知道其實已經被換掉。而通常,在換掉的同時,也會串接回原先真正要被呼叫的函式,所以也仍舊可以保有它原始的作用,但你卻可以在這中間加工。


基本上,透過他所提供的libraryHookAPINT.dll),你只需要撰寫想要hookDLL functions,便可以把你想要注射的函式注射到目標DLL去。不過,如果想研究整個技巧,或是改寫他所提供的library,可以到原作者的網站上去下載原始碼:


http://www.programsalon.com/sell/hookapi.htm


他的原始碼在版權宣告上,僅供學習之用,倘若要應用於商業用途,在他的原始網站上有購買所需的相關資訊。


API Hooking是相當有用的技術,僅用於winsock函式的hooking來攔截網路訊息,也只是大材小用。但這個技術通常也都用於比較邪惡的用途,例如偷密碼、偷聽訊息呀之類的,所以還是大家希望多應用在正面的產品上。


 

pageicon 星期一 一月 08, 2007

Hook MSN Messenger之socket通訊的鳥事

如果要問我這幾天怎麼都沒寫blog,那除了正在搞DirectShow的心得分享外,卡在另一個API hooking上的問題,肯定是主因了。

這問題是怎樣的呢?話說我用API hooking的方式,試著掛上winsock API中的函式-recv()。其主要目的是要聽取MSN Messenger所傳送的所有訊息。程式寫好後,在自己的電腦上跑的也好好的,不過丟到另一台電腦上去,嘿,可怎麼都不會動。

接著開始漫長的診斷程序,我發現其餘的函式像send()sendto()都可以成功的掛上去,但就是recv()recvfrom()掛不上去。於是開始胡思亂想,猜想會不會是這台機器中毒了啊?請出了BirdmanArchon,也掃不出個所以然。

不過,就在快要絕望的時候,曙光竟然出現了-我發現,Messenger 7.5可以掛的上去,但Live Messenger不行啊。這是個好消息,經過反覆實驗後,發現的確如此。好,那問題就回到為什麼Live Messenger不行?難不成它用的不是recv()這個blocking的函式,而是non-blocking版本的WSARecv()嗎?

試著掛上WSARecv(),的確有反應,但截錄到的訊息並不是MSN用來傳遞訊息之用的。這這真是令人絕望啊。

等等,在hook函式時,我指定的是ws2_32.dll,也就是Winsock 2中的函式,而不是wsock32.dll,也就是Winsock 1.1中的函式,這Live Messenger該不會用的是Winsock 1.1中的函式吧?這也不對,因為讓我們先來看一張圖:

基本上整個Winsock API的發展,如果從Winsock 1.1講的話,首先要提的是針對當時仍是16 bits作業系統(Windows 3.1)的Winsock 1.1應用程式。當時以winsock.dll提供16 bits的應用程式使用Winsock 1.1中的功能。到Windows 95問世後,得以出現32 bitsWinsock應用程式,為了與16 bitswinsock.dll區隔,另行提供了wsock32.dll。在wsock32.dll中,為32 bits的應用程式,提供了Winsock 1.1的實作。之後Winsock 2API推出(ws2_32.dll),自然進行了許多的加強,但基於Winsock的遺產龐大,勢必處理相容Winsock 1.1的問題。而處理的最佳方式,自然是利用Winsock 2中的API來提供原先Winsock 1.1API的功能。所以我們可以在上圖中看到倘若在提供Winsock 2的環境上,Winsock 1.1的函式是基於Winsock 2而達成的。

所以幾乎可以猜想,wsock32.dll中的函式,最終大概就是會轉遞至ws2_32.dll中的函式,因為提供重複的Winsock實作是很奇怪也不合邏輯的事。這是為什麼我即使有點懷疑Live Messenger用的是Winsock 1.1中的函式,但還是繼續認為即便如此,我只要hookws2_32.dll就可以。

嘿,debug這回事呀,就是要捐棄所有的成見,放掉所有的偏見。當事情無論如何都不在你想要的軌道上運行時,就只能把大腦清成空白,然後把自己變成白痴,不受某些既定的推論影響,才能夠有所收獲。

所以最後一條路,就掛掛看啊。

天啊,就是它。當我把自己的recv()掛到wsock32.dll時,發現Live Messenger傳的訊息都收到了。

這要怎麼解釋呀?東西既然會動了,那就來找答案吧。

看看這篇:

http://www.dcsoft.com/private/winsock_api.htm

On WinXP, if you hook wsock32.dll, most of the API's are forwarded to either ws2_32.dll or to mswsock.dll.  Only a couple API's are handled directly.

是的,Only a couple API's are handled directly

我要的recv()該不會就是吧?

中整理了wsock32.dll中的每個函式究竟是自行實作,或是forwardmswsock.dllws2_32.dll

很不幸或很幸運的(因為我終於找到解釋了)

………
16   3F 00001020 recv
17   40 00002E5F recvfrom
………
19   45          send (forwarded to ws2_32.send)
20   46          sendto (forwarded to ws2_32.sendto)

哈!夠鳥吧。wsock32.dll中的send()sentto()都是forwardws2_32.dll中的send()sendto()。但recv()recvfrom()卻都有自己的實作。這就是之所以之前hook ws2_32.dll中的recv()Live Messenger一直不能起作用的原因啊,因為它用的竟然是Winsock 1.1中的recv()而不是Winsock 2中的recv()

這整件事,從頭到尾都很詭異。為什麼7.5版的MSN Messenger用的是Winsock 2,但到了MSN Live Messenger後,反而用回了Winsock 1.1中的recv()。然後,為什麼Winsock 1.1中的recv()recvfrom()不像其他的函式一樣都forwardWinsock 2中的函式呢?這兩個謎團希望日後可以找到答案。

今天要開心的去睡覺了。

pageicon 星期五 六月 16, 2006

error LNK2005 operator new(unsigned int) already defined

最近在VC 6.0上作業,有幾個地方都遇到一個十分惱人的錯誤。就是出現下述的錯誤:






Linking...


nafxcwd.lib(afxmem.obj) : error LNK2005: "void * __cdecl operator new(unsigned int)" (??2@YAPAXI@Z) already defined in LIBCMTD.lib(new.obj)


nafxcwd.lib(afxmem.obj) : error LNK2005: "void __cdecl operator delete(void *)" (??3@YAXPAX@Z) already defined in LIBCMTD.lib(dbgdel.obj)


Debug/DCap.exe : fatal error LNK1169: one or more multiply defined symbols found


這樣的錯誤,明顯就是兩個被link到的library都提供了同名的函式。但直接ignoreLIBCMTD.lib當然是不行的,因為它是Clibrary。之所以發生這個問題,是因為MFClibraryClibrary相衝突,必須設定它們被link的順序,也就是先nafxcwd.libLIBCMTD.lib。但是這二者都是default libraries,所以要怎麼設定它們的順序呢?我找到一個解法其實挺tricky的:先把它們分別都ignore掉,再額外將它們加入。也就是說:在Link頁籤上的Ignore Libraries輸入:nafxcwd.lib,libcmtd.lib,再到同一頁籤的Object/library modules輸入:nafxcwd.lib libcmtd.lib。這麼一來,加入它們的順序就成了我們所強迫設定的順序了。

把對母乳媽媽的感謝與支持傳出去

« 三月 2010
星期日星期一星期二星期三星期四星期五星期六
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
   
       
今日

Search this blog

Links

Weblog menu

Today's referrers

Feeds