深入淺出HOOKS(之伍) (轉)
用訊息攔截技術製作日誌:namespace prefix = o ns = "urn:schemas--com::office" />
康帕斯(中國)國際資訊服務有限公司 馬文騫
01-6-7 下午 03:33:05
--------------------------------------------------------------------------------
能夠完整記錄使用情況的日誌在 系統管理方面的作用是不可低估的。本文介紹了利用訊息攔截技術製作日誌檔案的方法,其中的關鍵是一個未公開的 系統。
一、利用鉤子(Hook)攔截系統訊息
日誌檔案對於一個大企業內部的維護與管理是至關重要的。另外還有許多其它場合也離不開日誌的使用,例如:多人共享一臺電腦,或在家庭中要記錄兒童使用電腦的細節,等等。
日誌若想完整記錄電腦執行期間有哪些啟動過、各使用了多長時間、以及使用訪問網際網路的情況等,必須對系統級訊息進行攔截。RegisterHook是一個未公開的 API系統函式,它可以幫助日誌程式在整個 Windows系統範圍內感知到其它窗體的建立、啟用或關閉等訊息,而且不要求這些窗體與日誌程式有父子關係,哪怕是 Windows最高階別的窗體也可以。RegisterShellHook 呼叫方法為:
Public Declare Function RegisterShellHook Lib "Shell32" Alias "#181" _
(ByVal hwnd As Long, ByVal nAction As Long) As Long
其中引數hwnd為日誌程式的控制程式碼,引數 nAction為所要進行操作的程式碼。具體的呼叫細節參見下面的例子及其註釋。
二、將日誌程式隱藏起來
把日誌程式的Visible屬性設為False當然是必要的一步。然後是 ShowInTaskbar屬性也設為 False,以便其在 Windows的工作列中不出現。最後,為了在 CTRL+ALT+DEL 所彈出的列表中隱藏日誌程式,需要呼叫RegisterServiceProcess函式:
Public Declare Function RegisterServiceProcess Lib "kernel32" _
(ByVal dwProcessID As Long, ByVal dwType As Long) As Long
其中引數dwType是操作程式碼,值“1”表示從CTRL+ALT+DEL列表中去除,值“0”表示在列表中恢復;引數 dwProcessID是要在列表中去除或恢復的程式標識,可以用GetCurrentProcessId() API 函式得到日誌程式的程式標識,也可以用更簡便的方法,即把 dwProcessID引數置為空值,其含義是用當前程式的程式標識作為引數(見下例)。
另外,為了讓日誌程式在 Windows每次啟動時都能自動執行,需要修改登錄檔,即在登錄檔的下述位置新建一個以日誌程式的路徑及名稱為值的“串值”:
HKEY_LOCAL_MACHINESoftwareMicrosoftWindowsCurrentVersionRun
此外,產生的日誌檔案也應妥為隱藏,最好用 Winsock隨時向傳送。
為了簡潔,下面的例子僅將日誌檔案放在了根目錄,並且略去了用傳送檔案的程式碼。
三、一個完整的例子
下面的程式碼雖然短小,卻是一個完整的能自我隱藏的日誌程式(用 .0實現,在 下測試透過)。
' 窗體部分的程式碼(Form1.frm)
Option Explicit
Private Sub Form_Load()
Dim tmp As Long
' 將日誌程式的名稱從 CTRL+ALT+DEL 列表中清除
tmp = RegisterServiceProcess(ByVal 0&, 1)
Timer1.Interval = 60000 ' 定時器的作用是每隔一分鐘將日誌存檔
' 定義一個新的系統級的訊息型別
Msg_ID = RegisterWindowMessage("SHELLHOOK")
Call RegisterShellHook(hwnd, 1) ' 呼叫未公開的函式(進行註冊)
' 實施攔截:在了原入口地址的同時,將新地址指向自定義的函式WindowProc
Original = SetWindowLong(hwnd, GWL_WNDPROC, AddressOf WindowProc)
End Sub
Private Sub Form_Unload(Cancel As Integer)
Dim tmp As Long
Call RegisterShellHook(hwnd, 0) ' 呼叫未公開的函式(取消註冊)
tmp = SetWindowLong(hwnd, GWL_WNDPROC, Original) ' 將入口地址還原
End Sub
Private Sub Timer1_Timer()
If Len(Text1.Text) > 0 Then
Open "C:SystemLog.Sys" For Append As #1 ' 以“新增”方式開啟日誌
Print #1, Text1.Text ' 日誌自動存檔
Text1.Text = ""
Close #1
End If
End Sub
' 模組部分的程式碼(模組1.bas)
Public Declare Function RegisterShellHook Lib "Shell32" Alias "#181" _
(ByVal hwnd As Long, ByVal nAction As Long) As Long
Public Declare Function RegisterWindowMessage Lib "user32" Alias _
"RegisterWindowMessageA" (ByVal lpString As String) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" _
(ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
(ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" _
(ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Long, ByVal _
wParam As Long, ByVal lParam As Long) As Long
Public Declare Function RegisterServiceProcess Lib "kernel32" _
(ByVal dwProcessID As Long, ByVal dwType As Long) As Long
Const HSHELL_WINDOWCREATED = 1 ' 系統級的窗體被建立
Const HSHELL_WINDOWDESTROYED = 2 ' 系統級的窗體即將被關閉
'Const HSHELL_ACTIVATESHELLWINDOW = 3 ' SHELL 的主窗體將被啟用(本例未用)
Const HSHELL_WINDOWACTIVATED = 4 ' 系統級的窗體被啟用
'Const HSHELL_GETMINRECT = 5 ' 窗體被最大化或最小化(本例未用)
'Const HSHELL_REDRAW = 6 ' Windows 工作列被重新整理(本例未用)
'Const HSHELL_TASKMAN = 7 ' 任務列表的內容被選中(本例未用)
'Const HSHELL_LANGUAGE = 8 ' 中英文切換或輸入法切換(本例未用)
Public Const GWL_WNDPROC = -4 ' 該用來建立視窗類的子類
Public Msg_ID As Long, Original As Long
Public Function WindowProc(ByVal hwnd As Long, ByVal uMsg As Long, ByVal _
wParam As Long, ByVal lParam As Long) As Long ' 回撥函式
Dim tmp1 As String, tmp2 As String, i As Long
If uMsg = Msg_ID Then
tmp1 = String(200, "*")
i = GetWindowText(lParam, tmp1, 200) ' 取窗體的標題
If i > 0 Then tmp1 = Left(tmp1, i) Else tmp1 = "未命名"
tmp1 = tmp1 + " " + Str(Date) + " " + Str(Time) + vbCrLf ' 加入日期
' 下面對窗體控制程式碼值進行格式化的目的是為了日誌檔案在視覺上更美觀
tmp2 = Format(lParam, "000000")
If Right(Form1.Text1, 2) <> vbCrLf Then tmp2 = vbCrLf + tmp2
Case wParam
Case HSHELL_WINDOWCREATED
Form1.Text1 = Form1.Text1 + tmp2 + " 建立:" + tmp1
Case HSHELL_WINDOWDESTROYED
Form1.Text1 = Form1.Text1 + tmp2 + " 關閉:" + tmp1
Case HSHELL_WINDOWACTIVATED
Form1.Text1 = Form1.Text1 + tmp2 + " 啟用:" + tmp1
' 為了程式簡潔,本例僅處理“建立”、“啟用”和“關閉”這三個訊息,
' 其實就生成日誌檔案的目的,上述三個訊息已基本夠用。
' Case ...
' ...
End Select
Else
' 使用已被儲存下來的原入口地址
WindowProc = CallWindowProc(Original, hwnd, uMsg, wParam, lParam)
End If
End Function
下面列出的即為上述日誌程式所產生的日誌檔案(長約十分鐘的片段)。從中可以看出在該時間段內的電腦使用情況:曾撥號上網、瀏覽過“世界”、收過、訪問過登錄檔等。左列的數字是相應窗體的控制程式碼。
002624 啟用:Project1 - Microsoft [設計]
002624 關閉:Microsoft Visual Basic [設計]
001692 建立:正在連線到 95963
001692 啟用:正在連線到 95963
003512 關閉:Hot - 通行全球的免費 電子郵件 - Microsoft Inte Explorer
001880 建立:未命名 01-6-6 16:
001880 啟用:未命名 01-6-6 16:
001880 啟用:計算機世界網-應用與方案-首頁 - Microsoft Internet Explorer
001880 啟用:計算機世界網-應用與方案-應用 - Microsoft Internet Explorer
003488 建立:Microsoft Internet Explorer
003488 啟用:Microsoft Internet Explorer
003488 關閉:計算機世界網-用螢幕取詞技術實現動態標註 - Microsoft Internet Explorer
001880 啟用:計算機世界網-e海航標-首頁 - Microsoft Internet Explorer
001880 關閉:計算機世界網-e海航標-首頁 - Microsoft Internet Explorer
001132 啟用:瀏覽 - C:
001132 關閉:瀏覽 - C:
002772 建立: Express
002772 啟用:Outlook Express
002772 啟用:收件箱 - Outlook Express
002772 關閉:收件箱 - Outlook Express
003920 關閉:瀏覽 - 我的電腦
000640 建立:登錄檔編輯器
000640 啟用:登錄檔編輯器
000640 關閉:登錄檔編輯器
003756 建立:未命名 01-6-6 16:
003756 關閉:未命名 01-6-6 16:
001328 建立:網路監視器
001328 啟用:網路監視器
001328 啟用:網路監視器 - 0 連線到 CD_PROGRAM
001328 關閉:網路監視器 - 0 連線到 CD_PROGRAM
002700 關閉:連線到 95963
001804 關閉:未命名 01-6-6 16:
?
程式!
(網頁編輯:徐向陽)
相關文章
用螢幕取詞技術實現動態標註
幾種註冊OC資料來源的方法
在VB中Flash動畫
對Windows網路機制的改進
用VB6控制處理資料
您的姓名: 您朋友的:
[關閉視窗]
--------------------------------------------------------------------------------
Copyright(C) ccw.com.cn,All rights reserved
中國計算機世界出版服務公司版權所有
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10748419/viewspace-998285/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 深入淺出 FlatBuffers 之 Schema
- 深入淺出 Flutter Framework 之 PaintingContextFlutterFrameworkAIGCContext
- PostgreSQL VACUUM 之深入淺出 (一)SQL
- PostgreSQL VACUUM 之深入淺出 (二)SQL
- PostgreSQL VACUUM 之深入淺出 (三)SQL
- 深入淺出 Flutter Framework 之 BuildOwnerFlutterFrameworkUI
- 深入淺出 Flutter Framework 之 ElementFlutterFramework
- 深入淺出 Flutter Framework 之 WidgetFlutterFramework
- 深入淺出之切空間
- 深入淺出FE(十四)深入淺出websocketWeb
- Spring框架系列(3) - 深入淺出Spring核心之控制反轉(IOC)Spring框架
- 深入淺出說強制型別轉換型別
- (十八)深入淺出TCPIP之HTTP和HTTPSTCPHTTP
- Java容器深入淺出之String、StringBuffer、StringBuilderJavaUI
- iOS開發之 Method Swizzling 深入淺出iOS
- 淺讀-《深入淺出Nodejs》NodeJS
- 深入淺出 RabbitMQMQ
- ArrayList 深入淺出
- 深入淺出——MVCMVC
- 深入淺出IO
- 深入淺出PromisePromise
- 深入淺出 ZooKeeper
- 深入淺出mongooseGo
- HTTP深入淺出HTTP
- 深入淺出decorator
- 深入淺出WebpackWeb
- 深入淺出HTTPHTTP
- mysqldump 深入淺出MySql
- 前端筆記之React(五)Redux深入淺出前端筆記ReactRedux
- SSL/TLS 深入淺出TLS
- Tomcat深入淺出(一)Tomcat
- 深入淺出 Laravel MacroableLaravelMac
- flutter ScopedModel深入淺出Flutter
- 反射的深入淺出反射
- 《深入淺出webpack》有感Web
- 深入淺出Spring MVCSpringMVC
- 深入淺出Spark JoinSpark
- 深入淺出:HTTP/2HTTP
- Flutter | 深入淺出KeyFlutter