WINDOWS9x 的後臺程式 (轉)
WINDOWS9x 的後臺程式 (轉)[@more@]9x 的後臺程式 加入時間:01-1-6 下午 04:47:20
上海仙霞路山特公司中心黃飛
----1.後臺程式
----在WINDOWSNT中有一個功能強大的SERVICE管理器,它管理著一部分實現重要功能的後臺程式,例如.HTTP.RAS.Message等等,這些後臺程式被稱之為Service,他們可以在啟動時就載入,可以執行在較高的優先順序,可以說是非常靠近系統核心的裝置中的一種.在WINDOWS95下,沒有提供這樣一個高度集中化了的管理器,不過我們透過VC自帶的PVIEW可以看到,在桌面背後同樣有秘密的後臺程式存在,例如:SysTray,電源管理等.其實,這些就是WINDOWS95管理的後臺程式,WINDOWS95沒有提供SERVICE管理器,取而代之的是一個簡單的登記介面,可以類似的稱之為WINDOWS95下的Service(不過嚴格的講,WINDOWS95下是沒有Service的),同樣的,透過這個登記介面,我們可以使自己的程式隨系統啟動而最先執行,隨系統關閉而最後停止,和結合在一起,實現許多獨特的功能.我在實際工作中,仔細的分析了這個Windows95的介面,並且測試後發現,在WINDOWS97和最新的WINDOWS98中它一樣有效.並透過這個機制,成功的實現了WINDOWS95.98下的無人職守.下面是關於這個介面的分析結果和一些準備知識.
----2.程式(P)介紹
----在Windows的核心資料結構中,有一個重要的程式管理結構叫程式資料庫,它位於Kernel32的公用堆中,可以透過GetCurrentProcessID(...)得到指向該結構的指標,以下是部分PDB的組成,與本文直接相關的是PDB偏移21h處的Service標誌位元組,透過後面的偽碼分析,我們可以清楚的看到所謂登記為Windows95或Windows98下的Service程式,只不過是把它相應的PDB中該標誌位元組置為1而已.
偏移量長度 說明
============================================
+00h D Type // Kernel32的型別
+04h DWORD CReference //參考計數
+08h DWORD Un1 //未知
+0ch DWORD pSomeEvent //指向K32OBJ_EVENT指標
+10h DWORD TenationStatus //活動標誌或返回值
+14h DWORD Un2 //未知
...
+21h BYTE Flags1 // Service標記,
// "1"是Service程式,
// "0"普通程式
...
+24h DWORD pPSP // DPSP指標
...
============================================
---- 3. 實 現 接 口
---- (1) Windows95 中 提 供 的 簡 單 的Service 接 口 是 一 個32 位 的: RegisterServiceProcess, 由 於 在VC++ 的Online help 中 得 不 到 關 於 這 個API 的 確 切 解 釋, 筆 者 不 得 不 針 對 此API 進 行 了 逆 向 分 析, 以 下 是 在Windows95 的Kernel32.dll 中 該API 的 偽 碼. 我 們 可 以 清 楚 的 看 到Window95 內 部 到 底 是 怎 樣 做 的, 其 實 處 理 的 非 常 簡 單.
BOOL RegisterServiceProcess
( DWORD dwProcessID, DWORD dwType )
{
HANDLE dwPID;
if( dwProcessID == NULL )
dwPID = dwCurrentProcessID;
// Get global kernel32 variable
else
// Call some kernel functions
if( ( dwPID = CheckPID( dwProcessID ) == NULL )
return FALSE;
if( dwType == 1 )
{
*(BYTE *)( dwPID + 0x21 ) | = 0x01;
return TRUE;
}
if( dwType == 0 )
{
*(BYTE *)( dwPID + 0x21 ) & = 0xFE;
return TRUE;
}
return FALSE;
}
以下為原形:
BOOL RegisterServiceProcess( DWORD dwPID, DWORD dwType )
引數: dwPID:程式ID, NULL代表當前程式
dwType: RSP_SIMPLE_SERVICE為登記
RSP_UNREGISTER_SERVICE為取消登記
返回值: TRUE: 成功
FALSE: 呼叫失敗
---- (2) 另 外, 為 了 讓Service 進 程 有 機 會 在BOOT 後 就 啟 動,Windows95 的Registry 中 提 供 了 加 載 方 法: 在KEY " MyComputer HKEY_LOCAL_MACHINESOFTWARE MicrosoftWindows CurrentVersion RunServices " 加 入 自 己 的 應 用 程 序 命 令 行, 即 可 實 現 開 機 自 動 加 載. 當 然, 如 果 你 得 機 器 中 沒 有 這 個Key, 自 己 建 一 個 也 是 可 以 的.
---- 4. 例 程
---- 下 面 是 實 現 例 程, 所 有 代 碼 經 過 了WINDOWS95. WINDOWS98 BETA3 的 測 試, 可 以 方 便 的 加 入 到 自 己 的 項 目 文 件 中.
---- 頭 文 件:
// File: service.h
// The head file of "service.cpp"
// Note: 1. You must use C++ compiler
// 2. The platfois (WINNT & WIN95)
#ifndef _SERVICE_H
#define _SERVICE_H
/////////////////////////////////////
////////////// USED FOR WIN95 SERVICE
// Micros
#define RSP_SIMPLE_SERVICE 1
#define RSP_UNREGISTER_SERVICE 0
// Function types for GetProcAddress
#define RegisterServiceProcess_PROFILE
(DWORD (__stdcall *) (DWORD, DWORD))
// Service Fuctions in Win95
BOOL W95ServiceRegister(DWORD dwType);
BOOL W95StartService( DWORD dwType );
#endif
CPP 文 件:
// File: service.cpp --- implement the service
#include "service.h"
/////////////////////////////////////
////////////// USED FOR WIN95 SERVICE
登 記 為Service 子 程 序:
/////////////////////////////////////////
////////////////////////////////////////
// Define: BOOL
W95ServiceRegister(DWORD dwType)
// Parameters: dwType --- Flag to
register or unregister the service
// RSP_SIMPLE_SERVICE means register
// RSP_UNREGISTER_SERVICE means unregister
// Return: TRUE --- call success;
FALSE --- call failer
BOOL W95ServiceRegister( DWORD dwType )
{
// Function address defination
DWORD (__stdcall * hookRegisterServiceProcess)
( DWORD dwProcessId, DWORD dwType );
// Get address of function
hookRegisterServiceProcess =
RegisterServiceProcess_PROFILE
GetProcAddress
(GetModuleHandle("KERNEL32"),
TEXT("RegisterServiceProcess"));
// Register the WIN95 service
if(hookRegisterServiceProcess(NULL,dwType)==0)
return FALSE;
return TRUE;
}
---- 加 入 注 冊 表 子 程 序:
#define SERVICE_NAME TEXT("SERVICE")
// Define: BOOL W95StartService( DWORD dwType )
// Parameters: dwType --- Flag to
register or unregister the service
// RSP_SIMPLE_SERVICE means register
// RSP_UNREGISTER_SERVICE means unregister
// Return: TRUE --- call success; FALSE --- call failer
BOOL W95StartService( DWORD dwType )
{
// Local Variables
TCHAR lpszBuff[256];
LPTSTR lpszStr = lpszBuff +128;
LPTSTR lpszName = lpszBuff;
HANDLE hKey = NULL;
DWORD dwStrCb = 0;
DWORD dwValueType = 0;
// Get service name currently
lpszName = GetCommandLine();
for( int i = _tcslen(lpszName)-1; I >=0; i-- )
{
if( ( lpszName[i] != '"' )&&( lpszName[i]!=' ') )
break;
else if( lpszName[i] == '"' )
lpszName[i] = '';
}
if( lpszName[0] == '"' )
lpszName = lpszName +1;
// Registe as start up service
if( RegOpenKeyEx (HKEY_LOCAL_MACHINE,
TEXT( "SOFTWAREMicrosoftWindows
CurrentVersionRunServices"),
0,
KEY_QUERY_VALUE | KEY_SET_VALUE,
&hKey ) != ERROR_SUCCESS )
{
if( RegCreateKey( HKEY_LOCAL_MACHINE,
TEXT( "SOFTWAREMicrosoft
WindowsCurrentVersionRunServices"),
&hKey ) != ERROR_SUCCESS )
{
//DeOut( "RegCreateKey() error!");
return FALSE;
}
}
dwValueType = REG_SZ;
dwStrCb = 128;
// Take value
if( RegQueryValueEx(hKey,
SERVICE_NAME,
0,
&dwValueType,
(LPBYTE)lpszStr,
&dwStrCb ) == ERROR_SUCCESS )
{
// Find this key value
if( _tcscmp( lpszStr, lpszName )==0 )
{
// Remove the service
if( dwType == RSP_UNREGISTER_SERVICE )
{
if(RegDeleteValue( hKey, SERVICE_NAME )
== ERROR_SUCCESS )
{
RegCloseKey ( hKey );
return TRUE;
}
RegCloseKey( hKey );
return FALSE;
}
// Already exist service
if( dwType == RSP_SIMPLE_SERVICE )
{
//DebugOut("Already registed!");
RegCloseKey( hKey );
return TRUE;
}
}
// Not find it
} // No this value
// Unregiste return
if( dwType == RSP_UNREGISTER_SERVICE )
{
RegCloseKey( hKey );
return TRUE;
}
// No this value then create it
if( dwType == RSP_SIMPLE_SERVICE )
{
dwStrCb = 128;
// Set value
if( RegSetValueEx(hKey,
SERVICE_NAME,
0,
REG_SZ,
(CONST BYTE *)lpszName,
dwStrCb ) != ERROR_SUCCESS )
{
//DebugOut("RegSetValueEx() error!");
RegCloseKey( hKey );
return FALSE;
}
RegCloseKey( hKey );
return TRUE;
}
// Unknow type
RegCloseKey( hKey );
return FALSE;
}
---- 主 程 序:
// WinMain function is the entry of the this program
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
if( W95ServiceRegister( RSP_SIMPLE_SERVICE ) )
{
W95StartService( RSP_SIMPLE_SERVICE );
}
MessageBox(NULL, "Sample service", "SERVICE", MB_OK );
UNREFERENCED_PARAMETER( hInstance );
UNREFERENCED_PARAMETER( lpCmdLine );
UNREFERENCED_PARAMETER( nCmdShow );
UNREFERENCED_PARAMETER( hPrevInstance );
return 0;
}
----執行這個程式,等到MessageBox彈出後,從WINDOWS中退出到LOGON狀態,你會看見MessageBox一直保持開啟狀態直至受到響應或系統關機.所以要做WINDOWS95下系統級的後臺程式,並不一定非要去編寫容易引起系統混亂的VXD程式,在部分允許的情況下,我認為本文介紹的方法更加方便有效.
----1.後臺程式
----在WINDOWSNT中有一個功能強大的SERVICE管理器,它管理著一部分實現重要功能的後臺程式,例如.HTTP.RAS.Message等等,這些後臺程式被稱之為Service,他們可以在啟動時就載入,可以執行在較高的優先順序,可以說是非常靠近系統核心的裝置中的一種.在WINDOWS95下,沒有提供這樣一個高度集中化了的管理器,不過我們透過VC自帶的PVIEW可以看到,在桌面背後同樣有秘密的後臺程式存在,例如:SysTray,電源管理等.其實,這些就是WINDOWS95管理的後臺程式,WINDOWS95沒有提供SERVICE管理器,取而代之的是一個簡單的登記介面,可以類似的稱之為WINDOWS95下的Service(不過嚴格的講,WINDOWS95下是沒有Service的),同樣的,透過這個登記介面,我們可以使自己的程式隨系統啟動而最先執行,隨系統關閉而最後停止,和結合在一起,實現許多獨特的功能.我在實際工作中,仔細的分析了這個Windows95的介面,並且測試後發現,在WINDOWS97和最新的WINDOWS98中它一樣有效.並透過這個機制,成功的實現了WINDOWS95.98下的無人職守.下面是關於這個介面的分析結果和一些準備知識.
----2.程式(P)介紹
----在Windows的核心資料結構中,有一個重要的程式管理結構叫程式資料庫,它位於Kernel32的公用堆中,可以透過GetCurrentProcessID(...)得到指向該結構的指標,以下是部分PDB的組成,與本文直接相關的是PDB偏移21h處的Service標誌位元組,透過後面的偽碼分析,我們可以清楚的看到所謂登記為Windows95或Windows98下的Service程式,只不過是把它相應的PDB中該標誌位元組置為1而已.
偏移量長度 說明
============================================
+00h D Type // Kernel32的型別
+04h DWORD CReference //參考計數
+08h DWORD Un1 //未知
+0ch DWORD pSomeEvent //指向K32OBJ_EVENT指標
+10h DWORD TenationStatus //活動標誌或返回值
+14h DWORD Un2 //未知
...
+21h BYTE Flags1 // Service標記,
// "1"是Service程式,
// "0"普通程式
...
+24h DWORD pPSP // DPSP指標
...
============================================
---- 3. 實 現 接 口
---- (1) Windows95 中 提 供 的 簡 單 的Service 接 口 是 一 個32 位 的: RegisterServiceProcess, 由 於 在VC++ 的Online help 中 得 不 到 關 於 這 個API 的 確 切 解 釋, 筆 者 不 得 不 針 對 此API 進 行 了 逆 向 分 析, 以 下 是 在Windows95 的Kernel32.dll 中 該API 的 偽 碼. 我 們 可 以 清 楚 的 看 到Window95 內 部 到 底 是 怎 樣 做 的, 其 實 處 理 的 非 常 簡 單.
BOOL RegisterServiceProcess
( DWORD dwProcessID, DWORD dwType )
{
HANDLE dwPID;
if( dwProcessID == NULL )
dwPID = dwCurrentProcessID;
// Get global kernel32 variable
else
// Call some kernel functions
if( ( dwPID = CheckPID( dwProcessID ) == NULL )
return FALSE;
if( dwType == 1 )
{
*(BYTE *)( dwPID + 0x21 ) | = 0x01;
return TRUE;
}
if( dwType == 0 )
{
*(BYTE *)( dwPID + 0x21 ) & = 0xFE;
return TRUE;
}
return FALSE;
}
以下為原形:
BOOL RegisterServiceProcess( DWORD dwPID, DWORD dwType )
引數: dwPID:程式ID, NULL代表當前程式
dwType: RSP_SIMPLE_SERVICE為登記
RSP_UNREGISTER_SERVICE為取消登記
返回值: TRUE: 成功
FALSE: 呼叫失敗
---- (2) 另 外, 為 了 讓Service 進 程 有 機 會 在BOOT 後 就 啟 動,Windows95 的Registry 中 提 供 了 加 載 方 法: 在KEY " MyComputer HKEY_LOCAL_MACHINESOFTWARE MicrosoftWindows CurrentVersion RunServices " 加 入 自 己 的 應 用 程 序 命 令 行, 即 可 實 現 開 機 自 動 加 載. 當 然, 如 果 你 得 機 器 中 沒 有 這 個Key, 自 己 建 一 個 也 是 可 以 的.
---- 4. 例 程
---- 下 面 是 實 現 例 程, 所 有 代 碼 經 過 了WINDOWS95. WINDOWS98 BETA3 的 測 試, 可 以 方 便 的 加 入 到 自 己 的 項 目 文 件 中.
---- 頭 文 件:
// File: service.h
// The head file of "service.cpp"
// Note: 1. You must use C++ compiler
// 2. The platfois (WINNT & WIN95)
#ifndef _SERVICE_H
#define _SERVICE_H
/////////////////////////////////////
////////////// USED FOR WIN95 SERVICE
// Micros
#define RSP_SIMPLE_SERVICE 1
#define RSP_UNREGISTER_SERVICE 0
// Function types for GetProcAddress
#define RegisterServiceProcess_PROFILE
(DWORD (__stdcall *) (DWORD, DWORD))
// Service Fuctions in Win95
BOOL W95ServiceRegister(DWORD dwType);
BOOL W95StartService( DWORD dwType );
#endif
CPP 文 件:
// File: service.cpp --- implement the service
#include "service.h"
/////////////////////////////////////
////////////// USED FOR WIN95 SERVICE
登 記 為Service 子 程 序:
/////////////////////////////////////////
////////////////////////////////////////
// Define: BOOL
W95ServiceRegister(DWORD dwType)
// Parameters: dwType --- Flag to
register or unregister the service
// RSP_SIMPLE_SERVICE means register
// RSP_UNREGISTER_SERVICE means unregister
// Return: TRUE --- call success;
FALSE --- call failer
BOOL W95ServiceRegister( DWORD dwType )
{
// Function address defination
DWORD (__stdcall * hookRegisterServiceProcess)
( DWORD dwProcessId, DWORD dwType );
// Get address of function
hookRegisterServiceProcess =
RegisterServiceProcess_PROFILE
GetProcAddress
(GetModuleHandle("KERNEL32"),
TEXT("RegisterServiceProcess"));
// Register the WIN95 service
if(hookRegisterServiceProcess(NULL,dwType)==0)
return FALSE;
return TRUE;
}
---- 加 入 注 冊 表 子 程 序:
#define SERVICE_NAME TEXT("SERVICE")
// Define: BOOL W95StartService( DWORD dwType )
// Parameters: dwType --- Flag to
register or unregister the service
// RSP_SIMPLE_SERVICE means register
// RSP_UNREGISTER_SERVICE means unregister
// Return: TRUE --- call success; FALSE --- call failer
BOOL W95StartService( DWORD dwType )
{
// Local Variables
TCHAR lpszBuff[256];
LPTSTR lpszStr = lpszBuff +128;
LPTSTR lpszName = lpszBuff;
HANDLE hKey = NULL;
DWORD dwStrCb = 0;
DWORD dwValueType = 0;
// Get service name currently
lpszName = GetCommandLine();
for( int i = _tcslen(lpszName)-1; I >=0; i-- )
{
if( ( lpszName[i] != '"' )&&( lpszName[i]!=' ') )
break;
else if( lpszName[i] == '"' )
lpszName[i] = '';
}
if( lpszName[0] == '"' )
lpszName = lpszName +1;
// Registe as start up service
if( RegOpenKeyEx (HKEY_LOCAL_MACHINE,
TEXT( "SOFTWAREMicrosoftWindows
CurrentVersionRunServices"),
0,
KEY_QUERY_VALUE | KEY_SET_VALUE,
&hKey ) != ERROR_SUCCESS )
{
if( RegCreateKey( HKEY_LOCAL_MACHINE,
TEXT( "SOFTWAREMicrosoft
WindowsCurrentVersionRunServices"),
&hKey ) != ERROR_SUCCESS )
{
//DeOut( "RegCreateKey() error!");
return FALSE;
}
}
dwValueType = REG_SZ;
dwStrCb = 128;
// Take value
if( RegQueryValueEx(hKey,
SERVICE_NAME,
0,
&dwValueType,
(LPBYTE)lpszStr,
&dwStrCb ) == ERROR_SUCCESS )
{
// Find this key value
if( _tcscmp( lpszStr, lpszName )==0 )
{
// Remove the service
if( dwType == RSP_UNREGISTER_SERVICE )
{
if(RegDeleteValue( hKey, SERVICE_NAME )
== ERROR_SUCCESS )
{
RegCloseKey ( hKey );
return TRUE;
}
RegCloseKey( hKey );
return FALSE;
}
// Already exist service
if( dwType == RSP_SIMPLE_SERVICE )
{
//DebugOut("Already registed!");
RegCloseKey( hKey );
return TRUE;
}
}
// Not find it
} // No this value
// Unregiste return
if( dwType == RSP_UNREGISTER_SERVICE )
{
RegCloseKey( hKey );
return TRUE;
}
// No this value then create it
if( dwType == RSP_SIMPLE_SERVICE )
{
dwStrCb = 128;
// Set value
if( RegSetValueEx(hKey,
SERVICE_NAME,
0,
REG_SZ,
(CONST BYTE *)lpszName,
dwStrCb ) != ERROR_SUCCESS )
{
//DebugOut("RegSetValueEx() error!");
RegCloseKey( hKey );
return FALSE;
}
RegCloseKey( hKey );
return TRUE;
}
// Unknow type
RegCloseKey( hKey );
return FALSE;
}
---- 主 程 序:
// WinMain function is the entry of the this program
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
if( W95ServiceRegister( RSP_SIMPLE_SERVICE ) )
{
W95StartService( RSP_SIMPLE_SERVICE );
}
MessageBox(NULL, "Sample service", "SERVICE", MB_OK );
UNREFERENCED_PARAMETER( hInstance );
UNREFERENCED_PARAMETER( lpCmdLine );
UNREFERENCED_PARAMETER( nCmdShow );
UNREFERENCED_PARAMETER( hPrevInstance );
return 0;
}
----執行這個程式,等到MessageBox彈出後,從WINDOWS中退出到LOGON狀態,你會看見MessageBox一直保持開啟狀態直至受到響應或系統關機.所以要做WINDOWS95下系統級的後臺程式,並不一定非要去編寫容易引起系統混亂的VXD程式,在部分允許的情況下,我認為本文介紹的方法更加方便有效.
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-987811/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- Linux與Windows9x/2000的印表機共享(轉)LinuxWindows
- 將程式在後臺執行和殺掉後臺的程式
- 實現熱鍵啟用後臺程式 (轉)
- ORACLE後臺程式Oracle
- oracle 後臺程式Oracle
- Clusterware 後臺程式
- Nohup命令讓Linux下的程式在後臺執行 - 轉Linux
- RAC後臺GTX程式
- WINDOWS ORACLE 後臺程式WindowsOracle
- Oracle後臺程式列表Oracle
- 後臺程式介紹
- Dataguard(Standby) 後臺程式
- oracle中容易忽略的後臺程式Oracle
- Oracle後臺程式的功能簡介Oracle
- oracle 後臺程式的理解筆記Oracle筆記
- Oracle 10g 的後臺程式Oracle 10g
- 活用Linux的後臺任務(轉)Linux
- oracle dg後臺程式及wait event--轉載-精OracleAI
- [轉]php中使用ignore_user_abort()函式後,如何停止後臺執行的程式?PHP函式
- 切換歸檔模式後後臺程式的情況模式
- Oracle 後臺程式 說明Oracle
- Oracle後臺程式詳述Oracle
- 幾個必要後臺程式
- [zt] Oracle RAC 後臺程式Oracle
- linux程式前臺-後臺執行Linux
- WPF 後臺程式碼做 TranslateTransform 的動畫ORM動畫
- ORACLE 11G 新的後臺程式Oracle
- RAC例項中附加的後臺程式
- ERP平臺口水戰的背後(轉)
- 從後臺到webshell的一點思路(轉)Webshell
- IOS 後臺掛起程式 當程式到後臺後,繼續完成Long Running Task 任務iOS
- 玩轉全新的 Android 8.0 Oreo 後臺策略Android
- CRS啟動的三個主要的後臺程式
- jenkins後臺程式執行Jenkins
- 關於Oracle RAC後臺程式Oracle
- Oracle RAC後臺程式介紹Oracle
- 編寫python後臺程式Python
- Oracle VKRM 後臺程式介紹Oracle