WINDOWS9x 的后台进程

    技术2022-05-11  105

    WINDOWS9x 的后台进程 加入时间:01-1-6 下午 04:47:20   上海仙霞路山特公司软件中心黄飞 ----1.后台进程 ----在WINDOWSNT中有一个功能强大的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_MACHINE/SOFTWARE /Microsoft/Windows /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中退出到LOGON状态,你会看见MessageBox一直保持打开状态直至受到响应或系统关机.所以要做WINDOWS95下系统级的后台进程,并不一定非要去编写容易引起系统混乱的VXD程序,在硬件部分允许的情况下,我认为本文介绍的方法更加方便有效.

    最新回复(0)