本人有一个利用sys驱动Hook进程、注册表和内核的VC源码,运行后可以通过exe程序和sys之间通信来决定是否Hook。
现在本人把整个exe的VC源码全部改写为Delphi源码,完成后可以实现服务安装、启动和停止等,也可以实现拦截,但是最大的问题是无法实现sys向exe的信息输出,现在把代码如数列出,完整代码可点击这里下载
目前的问题如下:
第一个问题:接收不到驱动程序返回的文件字符串信息 ;
第二个问题:进程监控开启关闭一次后,再开启不出现提示对话框,强行关闭后造成蓝屏死机。exe的VC代码如下:#include <windows.h>
#include <stdio.h>#include "resource.h"
HWND hDialog;
HANDLE device;
char outputbuff[256]; 
char * strings[256]; 
DWORD stringcount;
DWORD controlbuff[64];DWORD dw;
NOTIFYICONDATA nid;
HWND hwnd;
BOOL bdrv;
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam);
void steup();
void CloseSrv();
void Begin();
void thread();
#define WM_PRM_NOTIFY WM_USER+1int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
HACCEL hAccel; hAccel = LoadAccelerators (hInstance, MAKEINTRESOURCE(IDR_ACCELERATOR1));  //调入指定的加速键表
hDialog = CreateDialog(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, DialogProc);
hwnd = hDialog;
nid.cbSize = sizeof(NOTIFYICONDATA);
nid.hWnd = hDialog;
nid.hIcon  = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
nid.uCallbackMessage = WM_PRM_NOTIFY;
nid.uFlags = NIF_ICON|NIF_TIP|NIF_MESSAGE;
nid.uID = 100001; Shell_NotifyIcon(NIM_ADD, &nid  );  //用于托盘的Shell API RECT   rect;   
int   ScreenWidth= GetSystemMetrics(SM_CXSCREEN);   
int   ScreenHeight=  GetSystemMetrics(SM_CYSCREEN); 
GetWindowRect(hDialog,&rect);
int width = rect.right-rect.left;
int height = rect.bottom-rect.top;
MoveWindow(hDialog,ScreenWidth/2-width/2,ScreenHeight/2-height/2,width,height,TRUE);  
ShowWindow(hDialog, nCmdShow);
UpdateWindow(hDialog);
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(hDialog, hAccel, &msg))  //设置加速键表
{
if(!IsDialogMessage(hDialog, &msg)) 
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
return msg.wParam;
}
//该函数为一个应用程序定义可与DialogBOX函数一起使用的回调函数。
BOOL CALLBACK DialogProc(HWND hwndDlg, UINT message, WPARAM wParam, LPARAM lParam) //回调函数
{
    switch (message)   //判断获得的消息,由此做出响应
    {
    case WM_SHOWWINDOW:  //显示窗口?
if (bdrv)
{
SetWindowText(GetDlgItem(hwnd,IDC_SA),"内核模块加载成功!"); //强迫一开始就打开进程监控(相当于按下“开启”按钮)
DeviceIoControl(device,1000,controlbuff,256,controlbuff,256,&dw,0);
EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_PMON),FALSE); //禁用“开启”按钮
EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_PMOFF),TRUE); //启用“关闭”按钮
}
else
{
//SetWindowText(GetDlgItem(hwnd,IDC_SA),"内核模块加载失败!");
CloseSrv();   //内核模块加载失败就自杀(活着也没什么意思)
DestroyWindow(hwndDlg);
PostQuitMessage(0); }
return TRUE;
case WM_INITDIALOG:  //收到窗口初始化消息
Begin();         //安装监控服务,打开虚拟设备
        return (TRUE);
case WM_PRM_NOTIFY:
if (lParam == WM_LBUTTONDOWN )
{

ShowWindow(hwndDlg,SW_RESTORE);
SetForegroundWindow(hwndDlg);
}
else if (lParam == WM_RBUTTONDOWN)
{ }
return TRUE ;
case WM_SIZE :
if (wParam == SIZE_MINIMIZED)
{
ShowWindow(hwndDlg,SW_HIDE);
}
else
{
return TRUE;
}
return TRUE;
    case WM_COMMAND:     //收到命令消息        switch (LOWORD(wParam))  //接收按钮消息
        {
        case IDC_BTN_PMON: //当进程监控按钮“开启”按下时
DeviceIoControl(device,
1000,
controlbuff,
256,
controlbuff,
256,
&dw,
0);
EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_PMON),FALSE); //禁用“开启”按钮
EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_PMOFF),TRUE); //启用“关闭”按钮
return TRUE;
        case IDC_BTN_PMOFF:     //当进程监控按钮“关闭”按下时
DeviceIoControl(device,
1001,
NULL,
NULL,
NULL,
NULL,
&dw,
0);
EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_PMON),TRUE);
EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_PMOFF),FALSE);
return TRUE;
case IDC_BTN_RMON:     //注册表监控开启
DeviceIoControl(device,
1002,
controlbuff,
256,
controlbuff,
256,
&dw,
0);
EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_RMON),FALSE);
EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_RMOFF),TRUE);
return TRUE;
case IDC_BTN_RMOFF:     //注册表监控关闭
DeviceIoControl(device,
1003,
NULL,
NULL,
NULL,
NULL,
&dw,
0);
EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_RMON),TRUE);
EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_RMOFF),FALSE);
return TRUE;
case IDC_BTN_MMON:     //内核监控开启
 DeviceIoControl(device,
 1004,
 controlbuff,
 256,
 controlbuff,
 256,
 &dw,
 0);
 EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_MMON),FALSE);
 EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_MMOFF),TRUE);
 return TRUE;
case IDC_BTN_MMOFF:     //内核监控关闭
 DeviceIoControl(device,
 1005,
 NULL,
 NULL,
 NULL,
 NULL,
 &dw,
 0);
 EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_MMON),TRUE);
 EnableWindow(GetDlgItem(hwndDlg,IDC_BTN_MMOFF),FALSE);
 return TRUE;
        default:
            break;
        }
        return (FALSE);

    case WM_CLOSE:
CloseSrv();
DestroyWindow(hwndDlg);
PostQuitMessage(0);
break;
    case WM_DESTROY:
Shell_NotifyIcon(NIM_DELETE,&nid);
        EndDialog (hwndDlg, 0);
        return (TRUE);
    }
    return (FALSE);
}void steup()     //安装监控服务
{
int i;
char namebuff[256];
SC_HANDLE sch,scm; GetModuleFileName(NULL,namebuff,256); //该函数返回该应用程序全路径
i = strlen(namebuff);
while (namebuff[i] != '\\')
{
i--;
}
i++; strcpy(&namebuff[i],"PRMonitor.sys"); sch = OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);   //打开服务管理器
scm = CreateService(sch,
"PRMonitor",
"PRMonitor",
SERVICE_START|SERVICE_STOP,
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
namebuff,
0,
0,
0,
0,
0); StartService(scm,NULL,NULL);         //启动服务 CloseServiceHandle(scm);

}void CloseSrv()             //关闭服务
{
CloseHandle(device); SC_HANDLE sch ;
SERVICE_STATUS ss;
sch = OpenSCManager(NULL,0,0);
SC_HANDLE scm ;
scm = OpenService(sch,"PRMonitor",SERVICE_ALL_ACCESS);
ControlService(scm,SERVICE_CONTROL_STOP,&ss);
DeleteService(scm);
}void Begin()   //安装虚拟设备
{
steup();   //安装监控服务

Sleep(100); //以毫秒为单位,让函数滞留
//create processing thread
CreateThread(0,0,(LPTHREAD_START_ROUTINE)thread,0,0,&dw);  //在主线程的基础上创建一个新线程

//open device
device=CreateFile("\\\\.\\PRMONITOR", //创建File这个内核对象
GENERIC_READ|GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_SYSTEM,
0); if (device == INVALID_HANDLE_VALUE)
{
bdrv = FALSE;  //device打开失败
}
else
{
bdrv = TRUE;  //device打开成功
} DWORD * addr=(DWORD *)(1+(DWORD)GetProcAddress(GetModuleHandle("ntdll.dll"),"NtCreateProcess"));
ZeroMemory(outputbuff,256);  //用0来填充一块内存区域
controlbuff[0]=addr[0];
controlbuff[1]=(DWORD)&outputbuff[0];
MessageBox(0, (LPCTSTR)controlbuff[1],"WARNING",MB_YESNO|MB_ICONQUESTION|0x00200000L);

//CloseHandle(device);}void thread()
{
DWORD a,x; char msgbuff[512];
char *pdest;
int  result;

while(1)  //反复循环以下代码
{
//由src所指内存区域复制count个字节到dest所指内存区域。
memmove(&a,&outputbuff[0],4);  

if(!a){Sleep(10);continue;} //如果a为0,暂停10ms,返回进行下一轮循环

char*name=(char*)&outputbuff[8]; for(x=0;x<stringcount;x++)
{    //好像是:如果发现有以前已经同意执行的进程,则不询问直接执行
if(!stricmp(name,strings[x])){a=1;goto skip;}  //stricmp比较字符串s1和s2
}

pdest = strstr(name,"##");  //返回"##"第一次在name中出现的位置
if (pdest != NULL)
{
result = pdest-name;  //outputbuff[8]中:(准备创建进程的程序名)##(将被创建进程的完整路径)
strcpy(msgbuff, "是否允许“");
strncat(msgbuff,&outputbuff[8],result);  //准备创建进程的程序名
strcat(msgbuff,"”运行:");      
strcat(msgbuff,&outputbuff[result+10]);  //将被创建进程的完整路径
strcat(msgbuff," ?");
}
else if((pdest=strstr(name,"$$")) != NULL)
{
result = pdest-name;
strcpy(msgbuff, "是否允许");
strncat(msgbuff,&outputbuff[8],result);
strcat(msgbuff,"设置注册表");
strcat(msgbuff,&outputbuff[result+10]);
}
else
{
pdest = strstr(name,"&&");
result = pdest-name;
strcpy(msgbuff,"是否允许");
strncat(msgbuff,&outputbuff[8],result);
strcat(msgbuff,"加载驱动");
strcat(msgbuff,&outputbuff[result]+10);
}


if(IDYES==MessageBox(0, msgbuff,"WARNING",MB_YESNO|MB_ICONQUESTION|0x00200000L)) 
{
a=1;                                 //如果回答“是”
strings[stringcount]=_strdup(name);  
stringcount++;
}
else a=0;

skip:memmove(&outputbuff[4],&a,4);  
 
 a=0;
 memmove(&outputbuff[0],&a,4);
}
}
 

解决方案 »

  1.   

    ¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥¥
    本人改写的Delphi代码如下:unit Unit1;interfaceuses
      Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
      Dialogs, StdCtrls, WinSvc, StrUtils, ShellAPI;// SvcMgr;type
      TForm1 = class(TForm)
        GroupBox1: TGroupBox;
        Button1: TButton;
        Button2: TButton;
        GroupBox2: TGroupBox;
        Button3: TButton;
        Button4: TButton;
        GroupBox3: TGroupBox;
        Button5: TButton;
        Button6: TButton;
        Label1: TLabel;
        procedure FormCreate(Sender: TObject);
        procedure FormShow(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
        procedure Button1Click(Sender: TObject);
        procedure Button2Click(Sender: TObject);
        procedure Button3Click(Sender: TObject);
        procedure Button4Click(Sender: TObject);
     
      private
        { Private declarations }
      public
        { Public declarations }
      end;var
      Form1: TForm1;
      hDialog:HWND;
      device:THandle;  //HANDLE device;
      outputbuff:array[0..255] of Char;  //char outputbuff[256];
      controlbuff:array[0..63] of DWORD;  //DWORD controlbuff[64];
      dw:DWORD;  //DWORD dw;
      hhwnd:HWND;  //HWND hwnd;
      bdrv:Boolean;  //BOOL bdrv;implementation{$R *.dfm}
    //-------------------------------------------------------
    procedure steup;
    var
      //i:Integer;
      namebuff: ShortString;
      sch,scm:SC_HANDLE;
      lpServiceArgVectors:PAnsiChar;
    begin
      //int i;
    //char namebuff[256];
    //SC_HANDLE sch,scm;
      //GetModuleFileName(NIL,namebuff,255);
    namebuff:=Application.ExeName;
    namebuff:=AnsiReplaceText(namebuff,'.exe','.sys') ; //strcpy(&namebuff[i],"PRMonitor.sys");
    sch:= OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);   //连接服务数据库
    scm:= CreateService(sch,
    'PRMonitor',
    'PRMonitor',
    SERVICE_START or SERVICE_STOP,
    SERVICE_KERNEL_DRIVER,
    SERVICE_DEMAND_START,
    SERVICE_ERROR_NORMAL,
    PAnsiChar(AnsiString(namebuff)),
    nil,
    nil,
    nil,
    nil,
    nil);
      lpServiceArgVectors := nil;
    StartService(scm,0,lpServiceArgVectors);         //启动服务 CloseServiceHandle(scm);
    end;
    //----------------------------------------------------
    procedure thread;
    var
      a:DWORD; msgbuff:String;
      pdest:Integer;
      //result:Integer;
      name:ShortString;
    begin
    //DWORD a,x; char msgbuff[512];
    //char *pdest;
    //int  result; while 1=1 do //反复循环以下代码
    begin
    //由src所指内存区域复制count个字节到dest所指内存区域。
    Move(outputbuff[0],a,4);  //outputbuff[0]中值为1表示拦截到监控内容,为0表示已经询问完用户 if (a=0) then
        begin
         Sleep(10);
         continue; //如果a为0,暂停10ms,返回进行下一轮循环
        end;
    name:=MidStr(outputbuff,9,SIZEOF(outputbuff)-8);
    //问题主要就在这里:outputbuff中总是为空,得不到返回的字符串信息 pdest := AnsiPos('##',name);  //该函数返回"##"第一次在name中出现的位置
    if (pdest>0)  then
    begin
     //outputbuff[8]中保存的是:(准备创建进程的程序名)##(将被创建进程的完整路径)
    msgbuff:=msgbuff+'是否允许“';
          msgbuff:=msgbuff+ MidStr(outputbuff,9,pdest-1); //准备创建进程的程序名
          msgbuff:=msgbuff+'”运行:';
          msgbuff:=msgbuff+ outputbuff[pdest+10]+'?'; //将被创建进程的完整路径
    //strcat(msgbuff,@outputbuff[result+10]);
    //strcat(msgbuff,' ?');
    end
    else if(AnsiPos('$$',name) >0) then
    begin
          pdest:=AnsiPos('$$',name);
    //resultt := pdest-name;
    //strcpy(msgbuff, '是否允许');
    //strncat(msgbuff,&outputbuff[8],result);
    msgbuff:='设置注册表';
    //strcat(msgbuff,&outputbuff[result+10]);
    end
    else
    begin
    pdest := AnsiPos('&&',name);
    //result := pdest-name;
    //strcpy(msgbuff,'是否允许');
    //strncat(msgbuff,&outputbuff[8],result);
    msgbuff:='加载驱动';
    //strcat(msgbuff,&outputbuff[result]+10);
    end;
        msgbuff:=msgbuff +'name='+ name+';pdest='+inttostr(pdest);     // 询问用户是否允许执行
        if MessageDlg(msgbuff,  mtConfirmation, [mbYes, mbNo], 0) = mrYes then
          a:=1           //如果回答“是”
        else
          a:=0;    Move(a,outputbuff[4],4); //outputbuff[4]中值为1表示用户同意操作,为0表示不同意   a:=0;
        Move(a,outputbuff[0],4); //outputbuff[0]中值为1表示拦截到监控内容,为0表示已经询问完用户
    end;end;//----------------------------------------------------
    procedure Beginn;
    var
      addr:PDWORD;
    begin
      steup();   //安装监控服务

    Sleep(100); //以毫秒为单位,让函数滞留
    //create processing thread
    CreateThread(nil,0,@thread,nil,0,Dw);  //在主线程的基础上创建一个新线程
     
    //open device
    device:=CreateFile('\\.\PRMONITOR', //创建File这个内核对象
    GENERIC_READ or GENERIC_WRITE,
    0,
    nil,
    OPEN_EXISTING,
    FILE_ATTRIBUTE_SYSTEM,
    0); if (device = INVALID_HANDLE_VALUE) then
    bdrv := FALSE  //device打开失败
      else
       bdrv := TRUE;  //device打开成功
    addr:= Pdword(1+DWORD(GetProcAddress(GetModuleHandle('ntdll.dll'),'NtCreateProcess')));
    ZeroMemory(@outputbuff,256);  //用0来填充一块内存区域,填充的内存区域的大小,按字节来计算。
    controlbuff[0]:=addr^;//DWORD();
    controlbuff[1]:=DWORD(@outputbuff);
    end;//----------------------------------------------------------
    procedure CloseSrv;             //关闭服务
    var
      sch,scm:SC_HANDLE;
      ss:_SERVICE_STATUS; // SERVICE_STATUS ss;
    begin
    CloseHandle(device); sch := OpenSCManager(nil,nil,SC_MANAGER_ALL_ACCESS); scm := OpenService(sch,'PRMonitor',SERVICE_ALL_ACCESS);
    ControlService(scm,SERVICE_CONTROL_STOP,ss);
    DeleteService(scm);
    end;procedure TForm1.FormCreate(Sender: TObject);
    begin
      beginn();
    end;procedure TForm1.FormShow(Sender: TObject);
    begin
      if (bdrv) Then
        Label1.Caption:='内核模块加载成功!'
      else
        Label1.Caption:='内核模块加载失败!';
    end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      CloseSrv;
    end;procedure TForm1.Button1Click(Sender: TObject);
    begin
      DeviceIoControl(device,1000,@controlbuff,256,@controlbuff,256,dw,NIL);
      Button1.Enabled:=False;
      Button2.Enabled:=True;
    end;procedure TForm1.Button2Click(Sender: TObject);
    begin
      DeviceIoControl(device,1001,NIL,0,NIL,0,dw,NIL);
      Button2.Enabled:=False;
      Button1.Enabled:=True;
    end;procedure TForm1.Button3Click(Sender: TObject);
    begin
      DeviceIoControl(device,1002,@controlbuff,256,@controlbuff,256,dw,nil);
      Button3.Enabled:=False;
      Button4.Enabled:=True;
    end;procedure TForm1.Button4Click(Sender: TObject);
    begin
      DeviceIoControl(device,1003,NIL,0,NIL,0,dw,NIL);
      Button4.Enabled:=False;
      Button3.Enabled:=True;
    end;end.//第一个问题:接收不到驱动程序返回的文件字符串信息 ;
    //第二个问题:进程监控开启关闭一次后,再开启不出现提示对话框,强行关闭后造成蓝屏死机。
    敬请高手不吝赐教,万分感谢!!完整代码可点击这里下载
    此处不欢迎毫无意义的回复,此类人员请绕道。
      

  2.   

    outputbuff中总是为空,得不到返回的字符串信息
    的原因可能是outputbuff里面有 0 字符,所以,你要用其他函数来截取,至于第二个问题,你要自己调试了,光看,我还没有看出来.
      

  3.   


    第一个问题:
    Move(a,outputbuff[4],4); outputbuff前8个字节中还要保存a的值,一开始a的值是可以带过来和传过去的,只是字符串过不来。
    第二个问题可能还是因为后来的a值没带过来造成的,所以问题都还是出在outputbuff上。关键它是exe和驱动共享的内存区域,想换也不可能。