Win2K下關聯程式/埠之程式碼初步分析(轉)
Win2K下關聯程式/埠之程式碼初步分析(轉)[@more@] 經常見到網友問:如何才能關聯我的程式和埠呀?沒錯,關聯程式和埠是一個非常有用的功能,你可以清楚地知道哪些程式在使用哪些埠,對於查殺木馬很有幫助。可是我們雖然可以使用工作管理員瀏覽程式列表,使用Netstat檢視埠的使用狀況,卻沒有一個命令可以直接關聯程式和埠(WinXP上增加了新的NetStat功能,支援直接檢視埠程式狀況),今年年初的時候,國外出了一個有名的軟體Fport,它可以顯示當前所有的埠及他們所屬的程式,可是,這個軟體並沒有公開原始碼,(太不符合自由軟體精神了吧?),我根據對這個軟體的逆向工程,做了一個類似的工具,在這裡和大家探討一下它的原理。 一拿到Fport的時候,我就對它進行了API分析,發現除了一些基本的API以外,它還呼叫了NTDLL.dll的幾個未公開API,如NtQuerySystemInfomation,NtQueryInfomationProcess,直覺告訴我,關鍵應該在這兩個函式中,特別是前者。為了能夠理解Fport的執行機理,我們首先要來複習一下SOCKET.SOCKET究竟是什麼?它的中文名稱叫做套介面,但是,實際上我們所謂的SOCKET資料結構只是一個32位的無符號整數(在UNIX中是16位的),它對於Windows作業系統來說其實是一個檔案控制程式碼(SOCKET是檔案?奇怪麼?作業系統在底層實現的時候,常常使用檔案的概念來完成一些基本的功能),這樣的話問題就明朗了,如果我們能夠列舉系統所有的控制程式碼,從中獲得屬性為SOCKET的,不就可以完成Fport的功能?現在你應該想到了,為什麼Fport要呼叫NtQuerySystemInfomation這個API,實際上,NtQuerySystemInfomation這個函式提供了一個簡單的途徑以獲得系統所有的HANDLE,我們先來看看這個函式的原型: DWORD NtQuerySystemInformation( DWORD dwRecordType, PDWORD pdwHandleList, DWORD dwNumBytes, PDWORD pdwNumBytesRet ); 我來解釋一下,NtQuerySystemInformation這個函式有四個引數,第一個引數是dwRecordType,這個引數指定了我們所查詢的系統資訊型別,為了查詢系統HANDLE列表,我們定義一個常量#define NT_HANDLE_LIST 16(這個數值我是查資料得到的,如果誰有更詳細的資料,也請讓我共享一下);第二個引數是一個指標,這個指標用來返回系統控制程式碼列表,在呼叫NtQuerySystemInformation函式之前,必須為這個指標分配足夠的記憶體空間,否則函式呼叫會出錯;第三個引數是指定你為HandleList所分配的記憶體空間大小,單位是byte;第四個引數是NtQuerySystemInformation返回的HandleList的大小;如果NtQuerySystemInformation函式呼叫成功,返回值將是0,否則可以使用GetLastError()獲得詳細的錯誤程式碼。 一旦NtQuerySystemInformation函式呼叫成功,系統中所有的控制程式碼將被存放在pdwHandleList所指向記憶體空間中,其中,pdwHandleList所指向的第一個32位數,是這個buf所包含的控制程式碼數量,之後是順序排列的控制程式碼指標pHandleInfo,指向的是HANDLEINFO結構: typedef struct _HandleInfo { USHORT dwPid; USHORT CreatorBackTraceIndex; BYTE ObjType; BYTE HandleAttributes; USHORT HndlOffset; DWORD dwKeObject; ULONG GrantedAccess; }HANDLEINFO, *PHANDLEINFO; 看到這個結構,我們心中就有底了,控制程式碼資訊中包括了控制程式碼所屬程式的PID,這樣我們就可以關聯程式和SOCKET了,可是,在NT中有各種各樣的控制程式碼:程式控制程式碼、令牌控制程式碼、檔案控制程式碼、視窗控制程式碼……我們怎樣才能判斷一個控制程式碼究竟是不是SOCKET呢?這就要靠HANDLEINFO結構中的ObjType屬性了,經過分析,我們發現,SOCKET控制程式碼的型別值為0x1A,所以,我們將所有型別為0x1A的控制程式碼取出,進行getsockname操作就可以得到當前的程式/埠對應列表,實際上並不然,要知道,我們得到的控制程式碼都屬於其他的程式,在NT中根據程式保護的原則,一個程式沒有辦法直接得到其他程式的各種資訊,特別是控制程式碼,不同程式中的同一控制程式碼(控制程式碼的數值相同)根本就不是同樣的東西,因此,我們還必須進行一次轉換,將其他程式的控制程式碼轉換為本程式的控制程式碼,這個轉換工作只要簡單地呼叫DuplicateHandle函式就可以完成了: DuplicateHandle(hSourceProc, (HANDLE)pHandleInfo->HndlOffset, hCurrentProc, &hMyHandle, STANDARD_RIGHTS_REQUIRED, true, 0 ); 之後我們就可以透過getsockname、getsockopt等函式來獲得SOCKET的各種屬性了(使我困惑的是,Fport並沒有呼叫getsockname,這說明,應該有更簡單的方法來得到SOCKET控制程式碼的各種屬性,看來我對SOCKET控制程式碼的瞭解程度還是很膚淺呀) sockaddr_in name = {0}; name.sin_family = AF_INET; int namelen = sizeof(sockaddr_in); SOCKET s = (SOCKET)hMyHandle; char szSockType[6][6] = { "NUL", "TCP", "UDP", "RAW", "RDM", "SEQ" }; iRet = getsockname( s, (sockaddr*)&name, &namelen ); if ( iRet != SOCKET_ERROR ) { int sockType = 0; int optlen = 4; iRet = getsockopt( s, SOL_SOCKET, SO_TYPE, (char*)&sockType, &optlen ); printf("PID=%4d PORT=%5d %s
", pHandleInfo->dwPid, ntohs( name.sin_port ), szSockType[sockType] ); } 至此,程式和埠關聯的工作已經基本完成,可是,還有一些不足的地方,首先,這個軟體不像Fport一樣能夠檢視system程式(就是那個著名的8#程式)的SOCKET,錯誤程式碼是5(access denied),一個簡單的解決方法是將自己做成service,這樣就有了對Local System程式的訪問許可權,不過似乎Fport並不是這麼做的,此為疑點一;其次,由於我對HANDLE屬性的膚淺認識,有的時候會出現誤報或漏報的現象,即使沒有誤報,將所有屬性為0x1A的控制程式碼都進行getsockname效率也略微低了一點,這裡應該有更好的解決方案,此為疑點二;最後,Fport並沒有呼叫socket函式來獲得socket屬性,這說明有一個更簡單直接的方法可以從SOCKET控制程式碼中得到埠、協議等資訊,可惜我不知道,此為疑點三。不過令人欣慰的是,我寫出來的Gport可以在Win2K的非管理員使用者下執行,此時,僅能獲得本使用者所有程式的埠,這大概是Fport所沒有具備的功能。 寫本文的目的,一方面是為了解答某些網友對Fport原理的疑問,另一方面也是為了拋磚引玉,希望能解答我心中的這些疑點,望各位高手能不吝賜教。 最後附上Gport的程式碼,Gport的測試版和程式碼檔案可以在我的主頁上下載,地址為: 附:Gport.cpp #include #include #include #include #pragma comment ( lib, "ws2_32.lib" ) // NtQuerySystemInformation record type 16 #define NT_HANDLE_LIST 16 #define OBJECT_TYPE_SOCKET 0x1A #define MAX_HANDLE_LIST_BUF 0x200000 // 定義HanleInfo資料結構 typedef struct _HandleInfo { USHORT dwPid; USHORT CreatorBackTraceIndex; BYTE ObjType; BYTE HandleAttributes; USHORT HndlOffset; DWORD dwKeObject; ULONG GrantedAccess; }HANDLEINFO, *PHANDLEINFO; // 申明NtQuerySystemInformation()函式 typedef DWORD (CALLBACK* NTQUERYSYSTEMINformATION)( DWORD, PDWORD, DWORD, PVOID ); NTQUERYSYSTEMINformATION NtQuerySystemInformation; // 判斷SOCKET型別的陣列 char szSockType[6][6] = { "NUL", "TCP", "UDP", "RAW", "RDM", "SEQ" }; // // RaisePrivleges()函式用來提升本程式的特權 // bool RaisePrivleges( HANDLE hToken, char *pPriv ) { TOKEN_PRIVILEGES tkp; if ( !LookupPrivilegevalue( NULL, pPriv, &tkp.Privileges[0].Luid ) ) { printf( "LookupPrivilegevalue Error:%d
", GetLastError() ); return false; } tkp.PrivilegeCount = 1; tkp.Privileges[0].Attributes |= SE_PRIVILEGE_ENABLED; int iRet = AdjustTokenPrivileges( hToken, false, &tkp, 0, (PTOKEN_PRIVILEGES)NULL, 0 ); if ( iRet == NULL ) //AdjustTokenPrivileges函式呼叫失敗 { printf( "AdjustTokenPrivileges Error:%d
", GetLastError() ); re
·上一篇:·下一篇:
最新更新 | ||
······························ |
| ||
| | | | | | | | ||
| ||
Copyright © 2004 - 2007 All Rights Reserved
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10763080/viewspace-970134/,如需轉載,請註明出處,否則將追究法律責任。
上一篇:
電腦崩潰和當機原因分析總結大全(轉)
請登入後發表評論
登入
全部評論
|
相關文章
- Ubuntu下如何關閉指定埠的程式Ubuntu
- SQL worm sapphire 關鍵程式碼分析 (轉)SQLWormAPP
- Ubuntu下關閉佔用埠的程式更Ubuntu
- Winsock程式設計初步之<二> 源程式例項(一) (轉)程式設計
- Winsock程式設計初步之<三> 源程式例項(2) (轉)程式設計
- DirectX 7 程式設計初步 (轉)程式設計
- 【Lua篇】靜態程式碼掃描分析(一)初步介紹
- Winsock程式設計初步之<一> Winsock程式設計原理 (轉)程式設計
- Win2k"秘密武器"之遠端儲存分析(轉)
- Linux網橋原始碼框架分析初步(轉)Linux原始碼框架
- 第十四篇:Apriori 關聯分析演算法原理分析與程式碼實現演算法
- linux下檢視程式佔用埠和埠占用程式命令Linux
- 關機小程式的初步實現薦
- qmail-local程式碼分析(轉)AI
- Laravel核心程式碼學習 — 模型關聯底層程式碼實現Laravel模型
- Laravel核心程式碼學習 -- 模型關聯底層程式碼實現Laravel模型
- JS日期級聯元件程式碼分析及demoJS元件
- 快速程式碼展示之快速的例子程式碼片段(轉)
- Linux下init程式原始碼分析Linux原始碼
- 案例分析之JavaScript程式碼優化JavaScript優化
- 低程式碼 —— 初步認識 AppsmithAPPMIT
- 委託初步瞭解(程式碼段展示)
- linux下TCP socket程式設計初步(1)LinuxTCP程式設計
- 機器學習系列文章:Apriori關聯規則分析演算法原理分析與程式碼實現機器學習演算法
- memcached程式埠監控指令碼指令碼
- linux 下根據埠kill 程式Linux
- Windows下中止佔用埠的程式Windows
- Android之串列埠程式設計Android串列埠程式設計
- 程式碼分析
- 物件導向程式設計程式碼詳解(依賴關係,關聯關係,組合關係)物件程式設計
- 關於爛程式碼的那些事(下)
- SQL隱碼攻擊關聯分析SQL
- 檔案關聯型木馬的程式設計思路 (轉)程式設計
- select級聯下拉選單程式碼例項分析
- jaWE工作流時怎麼和程式中的程式碼關聯的!!!!
- linux下svn的常用程式碼【轉】Linux
- linux下檢視埠占用的程式Linux
- AttachXMLForSelect:XML自動關聯多級SELECT選單程式碼和例子 (轉)XML