珞珈山水BBS电脑网络程序人生 → 单文区文章阅读

单文区文章阅读 [返回]
发信人: Stravadivaly (老子就是机器人), 信区: Programm
标  题: 伪驱动初级教程1
发信站: BBS 珞珈山水站 (Fri Sep  1 13:19:37 2006)

                                伪驱动初级教程1
  By Stravadivaly
    什么是驱动?  我的感觉,它就是工作在0x8000000以上地址中的“用户程序”。
    为什么要写驱动?  因为我们能直接在操作系统的内核中获取信息。而且这些信息很
“干净”, 没有被做过手脚,比如枚举进程。
    写驱动要怎样的基础?  最好是写过Windows API 程序。了解消息循环,异常处理。
会使用ring0调试工具,比如softice。
    怎么是伪驱动?   就是说我们只是利用驱动程序能工作在核心态的优势,干点我们想
干的事情。简单说,就是占着茅坑不拉屎。

1.安装DDK:
    DDK(Driver Development Kit, 驱动开发包)是我们写驱动必须安装的咚咚,现在M$已
经开始收费,不再是免费下载了。不过我们还有BT, eMule.(他们不仅仅可以用来下毛片)


    下载好了之后,开始安装,随便装到哪个目录。在开始菜单中我们就可以看到一个“
Development Kit”的目录,在其后面的 “Build Enviroments”项下面我们可以看到有许
多的DOS快捷方式,这些就是编译环境。他们之间的区别和VC中的checked , release的区
别是相同的。Cheched版本中保留了很多调试信息,因而体积比release肥。我们调试的时
候,就是用Checked 环境编译的程序。

    安装目录下面有DDK文档,就像MSDN。也有示例驱动。

2.编写环境:
    很抱歉,M$似乎还没有一个专门的驱动编写环境。DriverStdio有,也听说网上由帖子
教你把VC配置成驱动编写编译工具的文章, 我两个都不用, 只拿个记事本,或者就用VC
写。注意,只是用他们写。更听说过有类似MFC的,对DDK的封装后的编译环境,我没有尝
试,我喜欢干净点的,直接点的。

3.编译一个驱动需要的文件:
  .c 文件:就是我们编写的驱动源程序。不能是 .cpp 文件,不然会编译错误。
  Makefile:如同编译汇编语言的MakeFile,这里也需要一个Makefile文件,但所有的驱
动的这个文件都是一样的,你可以到DDK的安装目录下面随便考一个。
  Sources: 最简单的sources文件像下面这样:
          TARGETNAME=MYDRIVER0  //这个是可以更改的,怎么改以后再说
          TARGETTYPE=DRIVER
          TARGETPATH=obj

          SOURCES=MyDriver.c   //这个是我们编写的驱动源程序,也可以改。
    
    这三个文件放到一起,然后我们打开编译环境,也就是开始菜单中,DDK项下面的Che
cked Enviroments。可以看到提示符了吧?用一系列DOS命令转到我们准备的三个文件所在
目录。输入命令 Build Mydriver.c –cZ  。之后也许是错误连天, 也许我们会发现当前
目录下多了两个文件夹,其中一个叫objchk,它下面还有一个文件夹 i386, i386的下面你
可以找到你编译好的.sys文件。


3.安装驱动:
    我们写了驱动是要安装的,不然有什么用?  有两种加载方式:1.通过.inf文件直接
写注册表。  2.写用户态程序,加载。推荐用程序加载, 下面是个完整的程序,来自国外
的某个牛人:
//安装驱动程序代码 
/*++

Copyright (c) 1993 Microsoft Corporation

Module Name:

Instdrv.c

Abstract:

A simple Win32 app that installs a device driver

Environment:

user mode only

Notes:

See readme.txt

Revision History:

06-25-93 : created   //人家93年就写了…...
--*/
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

BOOL
InstallDriver(
IN SC_HANDLE SchSCManager,
IN LPCTSTR DriverName,
IN LPCTSTR ServiceExe
);

BOOL
RemoveDriver(
IN SC_HANDLE SchSCManager,
IN LPCTSTR DriverName
);

BOOL
StartDriver(
IN SC_HANDLE SchSCManager,
IN LPCTSTR DriverName
);

BOOL
StopDriver(
IN SC_HANDLE SchSCManager,
IN LPCTSTR DriverName
);

BOOL
OpenDevice(
IN LPCTSTR DriverName
);



VOID __cdecl main(IN int argc,IN char *argv[])
/*++

Routine Description:

Arguments:

Return Value:

--*/
{
    SC_HANDLE schSCManager;

    if (argc != 3){
        
        char currentDirectory[128];

        printf ("usage: instdrv <driver name> <.sys location>\n");
        printf (" to install a kernel-mode device driver, or:\n");
        printf (" instdrv <driver name> remove\n");
        printf (" to remove a kernel-mode device driver\n\n");

        GetCurrentDirectory (128,currentDirectory);

        printf(" Example: instdrv simpldrv %s\simpldrv.sys\n",currentDirectory
);

        exit (1);
    }

    schSCManager = OpenSCManager (NULL, // machine (NULL == local)
                                NULL, // database (NULL == default)
                                SC_MANAGER_ALL_ACCESS // access required    
                   );

    if (!_stricmp (argv[2],"remove")){

        StopDriver (schSCManager,argv[1]);
        RemoveDriver (schSCManager,argv[1]);
    }
    else{
        InstallDriver(schSCManager,argv[1],argv[2]);
        StartDriver (schSCManager,argv[1]);
        OpenDevice (argv[1]);
    }
    CloseServiceHandle (schSCManager);
}



BOOL
InstallDriver(
IN SC_HANDLE SchSCManager,
IN LPCTSTR DriverName,
IN LPCTSTR ServiceExe
)
/*++

Routine Description:

Arguments:

Return Value:

--*/
{
    SC_HANDLE schService;
    DWORD err;

//
// NOTE: This creates an entry for a standalone driver. If this
// is modified for use with a driver that requires a Tag,
// Group, and/or Dependencies, it may be necessary to
// query the registry for existing driver information
// (in order to determine a unique Tag, etc.).
//

schService = CreateService (SchSCManager, // SCManager database
                            DriverName, // name of service
                            DriverName, // name to display
                            SERVICE_ALL_ACCESS, // desired access
                            SERVICE_KERNEL_DRIVER, // service type
                            SERVICE_DEMAND_START, // start type
                            SERVICE_ERROR_NORMAL, // error control type
                            ServiceExe, // service's binary
                            NULL, // no load ordering group
                            NULL, // no tag identifier
                            NULL, // no dependencies
                            NULL, // LocalSystem account
                            NULL // no password
            );

    if (schService == NULL){
        err = GetLastError();
        if (err == ERROR_SERVICE_EXISTS){
        //
        // A common cause of failure (easier to read than an error code)
        //
            printf ("failure: CreateService, ERROR_SERVICE_EXISTS\n");
        }
        else{
            printf ("failure: CreateService (%d)\n",err);
        }

        return FALSE;
    }
    else{
        printf ("CreateService SUCCESS\n");
    }
    CloseServiceHandle (schService);
    return TRUE;
}



BOOL
RemoveDriver(
IN SC_HANDLE SchSCManager,
IN LPCTSTR DriverName
)
/*++

Routine Description:

Arguments:

Return Value:

--*/
{
    SC_HANDLE schService;
    BOOL ret;

    schService = OpenService (SchSCManager,
                              DriverName,
                              SERVICE_ALL_ACCESS);

    if (schService == NULL){
        printf ("failure: OpenService (%d)\n", GetLastError());
        return FALSE;
    }

    ret = DeleteService (schService);

    if (ret){
        printf ("DeleteService SUCCESS\n");
    }
    else{
        printf ("failure: DeleteService (%d)\n",GetLastError());
    }
    CloseServiceHandle (schService);
    return ret;
}

BOOL
StartDriver(
IN SC_HANDLE SchSCManager,
IN LPCTSTR DriverName
)
{
    SC_HANDLE schService;
    BOOL ret;
    DWORD err;

    schService = OpenService (SchSCManager,
                              DriverName,
                              SERVICE_ALL_ACCESS);

    if (schService == NULL){
        printf ("failure: OpenService (%d)\n", GetLastError());
        return FALSE;
    }

    ret = StartService (schService, // service identifier
                        0, // number of arguments
                        NULL // pointer to arguments
                        );
    if (ret){
        printf ("StartService SUCCESS\n");
    }
    else{
        err = GetLastError();

        if (err == ERROR_SERVICE_ALREADY_RUNNING){
        //
        // A common cause of failure (easier to read than an error code)
        //
            printf ("failure: StartService, ERROR_SERVICE_ALREADY_RUNNING\n");

        }
        else{
            printf ("failure: StartService (%d)\n",err);
        }
    }
    CloseServiceHandle (schService);
    return ret;
}



BOOL
StopDriver(
IN SC_HANDLE SchSCManager,
IN LPCTSTR DriverName
)
{
    SC_HANDLE schService;
    BOOL ret;
    SERVICE_STATUS serviceStatus;

    schService = OpenService (SchSCManager,
                              DriverName,
                              SERVICE_ALL_ACCESS
                 );

    if (schService == NULL){
        printf ("failure: OpenService (%d)\n", GetLastError());
        return FALSE;
    }

    ret = ControlService (schService,
                          SERVICE_CONTROL_STOP,
                          &serviceStatus
          );
    if (ret){
        printf ("ControlService SUCCESS\n");
    }
    else{
        printf ("failure: ControlService (%d)\n",GetLastError());
    }
    CloseServiceHandle (schService);
    return ret;
}



BOOL
OpenDevice(
IN LPCTSTR DriverName
)
{
    char completeDeviceName[64] = "";
    LPCTSTR dosDeviceName = DriverName;
    HANDLE hDevice;
    BOOL ret;
//
// Create a \.\XXX device name that CreateFile can use
//
// NOTE: We're making an assumption here that the driver
// has created a symbolic link using it's own name
// (i.e. if the driver has the name "XXX" we assume
// that it used IoCreateSymbolicLink to create a
// symbolic link "\DosDevices\XXX". Usually, there
// is this understanding between related apps/drivers.
//
// An application might also peruse the DEVICEMAP
// section of the registry, or use the QueryDosDevice
// API to enumerate the existing symbolic links in the
// system.
//

    strcat (completeDeviceName,"\\.\");
    strcat (completeDeviceName,dosDeviceName);

    hDevice = CreateFile (completeDeviceName,
                  GENERIC_READ | GENERIC_WRITE,
                  0,
                  NULL,
                  OPEN_EXISTING,
                  FILE_ATTRIBUTE_NORMAL,
                  NULL
              );

    if (hDevice == ((HANDLE)-1)){
        printf ("Can't get a handle to %s\n",completeDeviceName);
        ret = FALSE;
    }
    else{
        printf ("CreateFile SUCCESS\n");
        CloseHandle (hDevice);
        ret = TRUE;
    }
    return ret;
}
--
是吗? 不是吗?  对吗? 不对吗? 傻吗?   ......   的确很傻.  就像" 树动风欲静, 日涌大山流".

※ 来源:·珞珈山水BBS站 http://bbs.whu.edu.cn·[FROM: 218.247.215.*]
[返回单文区目录]

武汉大学BBS 珞珈山水站 All rights reserved.
wForum , 页面执行时间:19.069毫秒