tommy

It's hard to tell the world we live in is either a reality or a dream
posts - 52, comments - 17, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

Hook SSDT

Posted on 2009-03-21 16:19 Tommy Liang 阅读(1250) 评论(0)  编辑 收藏 引用 所属分类: 进程与线程
看了《Rootkit》和《黑客防线2009》的文章,代码写了一下,有些体会:

驱动程序代码:
#include "ntddk.h"
#define NT_DEVICE_NAME L"\\Device\\ProtectProcess"
#define DOS_DEVICE_NAME L"\\DosDevices\\ProtectProcess"
#define IOCTL_PROTECT_CONTROL CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)

NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp);
void OnUnload(IN PDRIVER_OBJECT DriverObject);

#pragma pack(
1)
typedef 
struct ServiceDescriptorEntry{
    unsigned 
int *ServiceTableBase;
    unsigned 
int *ServiceCounterTableBase;
    unsigned 
int NumberOfServices;
    unsigned 
char *ParamTableBase;
}
 SSDT_Entry,*pSSDT_Entry;
#pragma pack()
__declspec(dllimport) SSDT_Entry KeServiceDescriptorTable;

#define SYSTEMSERVICE(_func) \
    KeServiceDescriptorTable.ServiceTableBase[
*(PULONG)((PUCHAR)_func+1)]

NTSYSAPI NTSTATUS NTAPI ZwOpenProcess(OUT PHANDLE ProcessHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes,
    IN PCLIENT_ID ClientId OPTIONAL);

typedef NTSTATUS (
*ZWOPENPROCESS)(OUT PHANDLE ProcessHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes,
    IN PCLIENT_ID ClientId OPTIONAL);

ZWOPENPROCESS OldZwOpenProcess;
long pid = 0;

NTSTATUS NewZwOpenProcess(OUT PHANDLE ProcessHandle,
    IN ACCESS_MASK DesiredAccess,
    IN POBJECT_ATTRIBUTES ObjectAttributes,
    IN PCLIENT_ID ClientId OPTIONAL)
{
    NTSTATUS nStatus 
= STATUS_SUCCESS;
    
if((long)ClientId->UniqueProcess == pid)
    
{
        DbgPrint(
"保护进程 PID:%d\n",pid);
        
return STATUS_ACCESS_DENIED;
    }

    nStatus 
= OldZwOpenProcess(ProcessHandle,DesiredAccess,ObjectAttributes,ClientId);
    
return nStatus;
}


void OnUnload(IN PDRIVER_OBJECT DriverObject)
{
    UNICODE_STRING DeviceLinkString;
    PDEVICE_OBJECT DeviceObjectTemp1 
= NULL;
    PDEVICE_OBJECT DeviceObjectTemp2 
= NULL;
    DbgPrint(
"驱动程序卸载\n");
    RtlInitUnicodeString(
&DeviceLinkString,DOS_DEVICE_NAME);
    IoDeleteSymbolicLink(
&DeviceLinkString);
    
if(DriverObject)
    
{
        DeviceObjectTemp1 
= DriverObject->DeviceObject;
        
while(DeviceObjectTemp1)
        
{
            DeviceObjectTemp2 
= DeviceObjectTemp1;
            DeviceObjectTemp1 
= DeviceObjectTemp1->NextDevice;
            IoDeleteDevice(DeviceObjectTemp2);
        }

    }

    DbgPrint(
"设备已卸载\n");
    DbgPrint(
"修复SSDT\n");
    (ZWOPENPROCESS)(SYSTEMSERVICE(ZwOpenProcess)) 
= OldZwOpenProcess;
    DbgPrint(
"驱动卸载完毕\n");
}


NTSTATUS DispatchDeviceControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    NTSTATUS nStatus 
= STATUS_SUCCESS;
    ULONG IoControlCode 
= 0;
    PIO_STACK_LOCATION IrpStack 
= NULL;
    
long* inBuf = NULL;
    
char* outBuf = NULL;
    ULONG inSize 
= 0;
    ULONG outSize 
= 0;
    PCHAR buffer 
= NULL;
    PMDL mdl 
= NULL;

    Irp
->IoStatus.Status = STATUS_SUCCESS;
    Irp
->IoStatus.Information = 0;
    IrpStack 
= IoGetCurrentIrpStackLocation(Irp);

    
switch(IrpStack->MajorFunction)
    
{
        
case IRP_MJ_CREATE:
            DbgPrint(
"IRP_MJ_CREATE 被调用\n");
            
break;
        
case IRP_MJ_CLOSE:
            DbgPrint(
"IRP_MJ_CLOSE 被调用\n");
            
break;
        
case IRP_MJ_DEVICE_CONTROL:
            DbgPrint(
"IRP_MJ_DEVICE_CONTROL 被调用\n");
            IoControlCode 
= IrpStack->Parameters.DeviceIoControl.IoControlCode;
            
switch(IoControlCode)
            
{
                
case IOCTL_PROTECT_CONTROL:
                    inSize 
= IrpStack->Parameters.DeviceIoControl.InputBufferLength;
                    outSize 
= IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
                    inBuf 
= (long*)Irp->AssociatedIrp.SystemBuffer;
                    pid 
= *inBuf;
                    DbgPrint(
"=========================================\n");
                    DbgPrint(
"IOCTRL_PROTECT_CONTROL 被调用,通讯成功!\n");
                    DbgPrint(
"输入缓冲区大小:%d\n",inSize);
                    DbgPrint(
"输出缓冲区大小:%d\n",outSize);
                    DbgPrint(
"输入缓冲区内容:%ld\n",*inBuf);
                    DbgPrint(
"当前保护进程ID:%ld\n",pid);
                    DbgPrint(
"=========================================\n");
                    
                    strcpy(Irp
->UserBuffer,"OK\n");
                    
break;
                
default:
                    
break;
            }

            
break;
        
default:
            DbgPrint(
"未知请求包被调用\n");
            
break;
    }

    nStatus 
= Irp->IoStatus.Status;
    IoCompleteRequest(Irp,IO_NO_INCREMENT);
    
return nStatus;
}


NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING theRegistryPath)
{
    NTSTATUS ntStatus 
= STATUS_SUCCESS;
    UNICODE_STRING ntDeviceName;
    UNICODE_STRING DeviceLinkString;
    PDEVICE_OBJECT deviceObject 
= NULL;
    DbgPrint(
"驱动程序加载\n");
    RtlInitUnicodeString(
&ntDeviceName,NT_DEVICE_NAME);
    ntStatus 
= IoCreateDevice(
        DriverObject,
        
0,
        
&ntDeviceName,
        FILE_DEVICE_UNKNOWN,
        
0,
        FALSE,
        
&deviceObject);

    
if(!NT_SUCCESS(ntStatus))
    
{
        DbgPrint(
"无法创建驱动设备");
        
return ntStatus;
    }

    RtlInitUnicodeString(
&DeviceLinkString,DOS_DEVICE_NAME);
    ntStatus 
= IoCreateSymbolicLink(&DeviceLinkString,&ntDeviceName);
    
if(!NT_SUCCESS(ntStatus))
    
{
        DbgPrint(
"无法创建驱动设备");
        
return ntStatus;
    }

    DriverObject
->MajorFunction[IRP_MJ_CREATE] = DispatchDeviceControl;
    DriverObject
->MajorFunction[IRP_MJ_CLOSE] = DispatchDeviceControl;
    DriverObject
->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
    DriverObject
->DriverUnload = OnUnload;

    DbgPrint(
"驱动程序已经启动\n");
    DbgPrint(
"修改SSDT\n");

    OldZwOpenProcess 
= (ZWOPENPROCESS)(SYSTEMSERVICE(ZwOpenProcess));
    (ZWOPENPROCESS)(SYSTEMSERVICE(ZwOpenProcess)) 
= NewZwOpenProcess;
    DbgPrint(
"驱动程序加载完毕\n");
    
return STATUS_SUCCESS;
}

 
服务安装程序:
// ProtectInstaller.cpp : Defines the entry point for the console application.
//

#include 
"stdafx.h"

#define BUF_SIZE 4096

int main(int argc, char* argv[])
{
    
char path[BUF_SIZE];
    
char base[BUF_SIZE];
    
char sername[BUF_SIZE];
    
char disname[BUF_SIZE];
    memset(path,
0,BUF_SIZE);
    memset(
base,0,BUF_SIZE);
    memset(sername,
0,BUF_SIZE);
    memset(disname,
0,BUF_SIZE);

    SC_HANDLE rh 
= NULL;
    SC_HANDLE sh 
= NULL;
    
if(argc == 1)
    
{
        printf(
"use:install/start/uninstall\n");
        exit(
0);
    }


    ::GetModuleFileName(
0,base,BUF_SIZE);
    
int p = strlen(base);
    
while(base[p] != '\\'){ p --; }
    strncpy(path,
base,p+1);
    memset(
base,0,BUF_SIZE);
    sprintf(
base,"%sInstall.ini",path);
    memset(path,
0,BUF_SIZE);

    ::GetPrivateProfileString(
"Config","Path","",path,BUF_SIZE,base);
    ::GetPrivateProfileString(
"Config","ServiceName","",sername,BUF_SIZE,base);
    ::GetPrivateProfileString(
"Config","DisplayName","",disname,BUF_SIZE,base);

    printf(
"[*]Service Name:%s\n",sername);
    printf(
"[*]Display Name:%s\n",disname);
    printf(
"[*]Driver Path:%s\n",path);
    sh 
= OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS);

    
if(!sh){
        printf(
"[-]Error OpenSCManager.\n");
        exit(
0);
    }

    
if(argc == 2 && !strcmp(argv[1],"install"))
    
{
        
if(!strcmp(path,""))
        
{
            printf(
"[-]error read Install.ini\n");
            exit(
0);
        }

        rh 
= CreateService(sh,
            sername,
            disname,
            SERVICE_ALL_ACCESS,
            SERVICE_KERNEL_DRIVER,
            SERVICE_DEMAND_START,
            SERVICE_ERROR_NORMAL,
            path,
            NULL,NULL,NULL,NULL,NULL);
        
if(!rh)
        
{
            printf(
"[-]error CreateService.\n");
            exit(
0);
        }

        printf(
"[-]Install Service Complete\n");
    }

    
else if(argc == 2 && !strcmp(argv[1],"start"))
    
{
        rh 
= OpenService(sh,sername,SERVICE_ALL_ACCESS);
        
if(!rh)
        
{
            printf(
"[-]error OpenService.\n");
            exit(
0);
        }

        StartService(rh,NULL,NULL);
        printf(
"[-]Start Service Complete\n");
    }

    
else if(argc == 2 && !strcmp(argv[1],"uninstall"))
    
{
        rh 
= OpenService(sh,sername,SERVICE_ALL_ACCESS);
        
if(!rh)
        
{
            printf(
"[-]error OpenService.\n");
            exit(
0);
        }

        SERVICE_STATUS ss;
        ControlService(rh,SERVICE_CONTROL_STOP,
&ss);
        printf(
"[-]Stop Service Complete\n");
        DeleteService(rh);
        printf(
"[-]Delete Service Complete\n");
    }

    CloseServiceHandle(rh);
    CloseServiceHandle(sh);
    
return 1;
}



INI文件:
[Config]
Path
=D:\hacker\ddk\Protect\sys\i386\Protect.sys
ServiceName
=Rootkit
DisplayName
=RootkitKernel

VC05搞了个解决方案

 


驱动编译通过了,安装程序也通过了,也能启动,
打开DeviceTree看看,搜索 ProtectProcess,找到了:


现在轮到告诉驱动PID的程序:
#include <stdio.h>
#include 
<stdlib.h>
#include 
<windows.h>
#include 
<winioctl.h>

#ifndef _WIN32_WINNT        
// Allow use of features specific to Windows XP or later.                   
#define _WIN32_WINNT 0x0501    // Change this to the appropriate value to target other versions of Windows.
#endif

#undef UNICODE

#define IOCTL_HELLO_CONTROL CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS)

int main(int argc,char* argv[])
{
    
long pid = 0;
    
char ret[4096];
    DWORD ReBytes 
= 0;
    HANDLE hDevice 
= CreateFile(L"\\\\.\\ProtectProcess",GENERIC_READ|GENERIC_WRITE,0,NULL,
        OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
    
if(hDevice == INVALID_HANDLE_VALUE)
    
{
        
if(2 == GetLastError())
        
{
            printf(
"驱动程序未注册\n");
        }

        
else
        
{
            printf(
"CreateFile() GetLastError reports %d \n",GetLastError());            
        }

        
return FALSE;
    }

    memset(ret,
0,4096);
    printf(
"请输入要保护的进程PID");
    scanf(
"%ld",&pid);
    DeviceIoControl(hDevice,IOCTL_HELLO_CONTROL,
        
&pid,sizeof(long),ret,4096,&ReBytes,NULL);
    printf(
"Return Value:%s\n",ret);
    CloseHandle(hDevice);
    
return 1;
}

开始的时候,在 CreateFile的第一个参数那里犯了一个错误,没有在前面加上“L”,结果一个下午花了3个小时在烦躁,一直提示驱动未安装,现在好了,PASS。

启动记事本,找到pid,运行通信程序,输入pid,打开任务管理器,好了,现在杀不掉notepad.exe了:


很有意思。




只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理