VC:WINDOWS 9x的后台进程
---- 1. 后 台 进 程 ----
在WINDOWS NT 中 有 一 个 功 能 强 大 的SERVICE 管 理 器, 它 管 理 着 一 部 分 实
现 重 要 功 能 的 后 台 进 程, 例 如FTP.HTTP.RAS. 网 络Message 等 等, 这 些 后 台
进 程 被 称 之 为Service, 他 们 可 以 在 系 统 启 动 时 就 加 载, 可 以 运 行 在 较 高 的
优 先 级, 可 以 说 是 非 常 靠 近 系 统 核 心 的 设 备 驱 动 程 序 中 的 一 种. 在WINDOWS95
下,Microsoft 没 有 提 供 这 样 一 个 高 度 集 中 化 了 的 管 理 器, 不 过 我 们 通 过VC
自 带 的PVIEW 可 以 看 到, 在 桌 面 背 后 同 样 有 秘 密 的 后 台 进 程 存 在, 例 如:SysTray,
电 源 管 理 等. 其 实, 这 些 就 是WINDOWS95 管 理 的 后 台 进 程,WINDOWS95 没 有 提
供SERVICE 管 理 器, 取 而 代 之 的 是 一 个 简 单 的 登 记 接 口, 可 以 类 似 的 称 之 为WINDOWS95
下 的Service( 不 过 严 格 的 讲,WINDOWS95 下 是 没 有Service 的), 同 样 的, 通
过 这 个 登 记 接 口, 我 们 可 以 使 自 己 的 程 序 随 系 统 启 动 而 最 先 运 行, 随 系 统
关 闭 而 最 后 停 止, 和 操 作 系 统 结 合 在 一 起, 实 现 许 多 独 特 的 功 能. 我 在 实 际
工 作 中, 仔 细 的 分 析 了 这 个Windows95 的 接 口, 并 且 测 试 后 发 现, 在WINDOWS97
和 最 新 的WINDOWS98 中 它 一 样 有 效. 并 通 过 这 个 机 制, 成 功 的 实 现 了WINDOWS95.98
下 的 无 人 职 守 监 控. 下 面 是 关 于 这 个 接 口 的 分 析 结 果 和 一 些 准 备 知 识. ----
2. 进 程 数 据 库(PDB) 介 绍 ---- 在Windows 的 核 心 数 据 结 构 中, 有 一 个 重 要
的 进 程 管 理 结 构 叫 进 程 数 据 库, 它 位 于Kernel32 的 公 用 内 存 堆 中, 可 以 通
过GetCurrentProcessID(...) 得 到 指 向 该 结 构 的 指 针, 以 下 是 部 分PDB 的
组 成, 与 本 文 直 接 相 关 的 是PDB 偏 移21h 处 的Service 标 志 字 节, 通 过 后 面 的
伪 码 分 析, 我 们 可 以 清 楚 的 看 到 所 谓 登 记 为Windows95 或Windows98 下 的Service
进 程, 只 不 过 是 把 它 相 应 的PDB 中 该 标 志 字 节 置 为1 而 已. 偏移量长度 说明 ============================================
+00h DWORD Type // Kernel32对象的类型 +04h DWORD CReference //参考计数
+08h DWORD Un1 //未知 +0ch DWORD pSomeEvent //指向K32OBJ_EVENT指针 +10h
DWORD TerminationStatus //活动标志或返回值 +14h DWORD Un2 //未知 ..... +21h
BYTE Flags1 // Service标记, // "1"是Service进程, // "0"普通进程 ..... +24h
DWORD pPSP // DOS PSP指针 ..... ============================================
---- 3. 实 现 接 口 ---- (1) Windows95 中 提 供 的 简 单 的Service 接 口 是
一 个32 位 的API: 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 platform is WIN32 (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] = '0'; } if(
lpszName[0] == '"' ) lpszName = lpszName +1; // Registe as start
up service if( RegOpenKeyEx (HKEY_LOCAL_MACHINE, TEXT( "SOFTWARE\Microsoft\Windows\
CurrentVersion\RunServices"), 0, KEY_QUERY_VALUE | KEY_SET_VALUE,
&hKey ) != ERROR_SUCCESS ) { if( RegCreateKey( HKEY_LOCAL_MACHINE,
TEXT( "SOFTWARE\Microsoft\ Windows\CurrentVersion\RunServices"),
&hKey ) != ERROR_SUCCESS ) { //DebugOut( "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 中 退 出 到LOG ON
状 态, 你 会 看 见MessageBox 一 直 保 持 打 开 状 态 直 至 受 到 响 应 或 系 统 关 机.
所 以 要 做WINDOWS95 下 系 统 级 的 后 台 进 程, 并 不 一 定 非 要 去 编 写 容 易 引 起
系 统 混 乱 的VXD 程 序, 在 硬 件 部 分 允 许 的 情 况 下, 我 认 为 本 文 介 绍 的 方 法 更
加 方 便 有 效.
|