要去看埃菲尔铁塔的顶
欢迎关注本人微博:t.cn/RGSLVUk
目标API : NtOpenProcess
相关结构
SSDT结构体
#pragma pack(1)
typedef struct _ServiceDescriptorTable
{
PULONG ServiceTableBase;
PULONG ServiceCounterTable;
unsigned int NumberOfServices;
PVOID paramTableBase;
}*PServiceDescriptorTable ,ServiceDescriptorTable;
#pragma pack()
// 由 ntoskrnl 模块 导出的变量
__declspec(dllimport) ServiceDescriptorTable KeServiceDescriptorTable;
NTSTATUS
NtOpenProcess
(
__out PHANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__in_opt PCLIENT_ID ClientId
);
根据 进程ID 获得进程对象
NTSTATUS
PsLookupProcessByProcessId(
IN HANDLE ProcessId,
OUT PEPROCESS *Process
);
代码:
演示 用于保护 calc.exe 进程
//ssdt.h
#include "ntddk.h"
#pragma pack(1)
typedef struct _ServiceDescriptorTable
{
PULONG ServiceTableBase;
PULONG ServiceCounterTable;
unsigned int NumberOfServices;
PVOID paramTableBase;
}*PServiceDescriptorTable ,ServiceDescriptorTable;
#pragma pack()
__declspec(dllimport) ServiceDescriptorTable KeServiceDescriptorTable;
void Driver_Unload(IN PDRIVER_OBJECT pDriverObject);
typedef NTSTATUS
(*NTOPENPROCESS)
(
__out PHANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__in_opt PCLIENT_ID ClientId
);
NTSTATUS
PsLookupProcessByProcessId(
IN HANDLE ProcessId,
OUT PEPROCESS *Process
);
#include "SSDT.h"
int g_OldAddr;
NTSTATUS ProtectJudge( PCLIENT_ID ClientId ,char* ProcessName)
{
PEPROCESS p_eprocess;
NTSTATUS status;
char* ImageFileName;
if(! MmIsAddressValid(ProcessName)) //判断参数是否有效
{
return STATUS_UNSUCCESSFUL;
}
ImageFileName = ( (char*)PsGetCurrentProcess() + 0x174); //实际测试这个返回的是一个结构体
//DbgPrint("PsGetCurrentProcess(): %x , this:: %x",PsGetCurrentProcess(),ImageFileName);
//DbgPrint("NtOpenProcess %d from: %s", ClientId->UniqueProcess,ImageFileName );
status = PsLookupProcessByProcessId(ClientId->UniqueProcess , &p_eprocess);
//DbgPrint("p_eprocess %x", p_eprocess );
if(!NT_SUCCESS(status)) // PsLookupProcessByProcessId调用失败
{
DbgPrint("PsLookupProcessByProcessId error code: %x ",status );
return STATUS_UNSUCCESSFUL;
}
ObDereferenceObject(p_eprocess);
ImageFileName = (char*)p_eprocess + 0x174 ;
if(! strcmp(ImageFileName , ProcessName) ) //保护计算器
{
return STATUS_SUCCESS;
}
return STATUS_UNSUCCESSFUL;
}
NTSTATUS
MyNTOpenProcess
(
__out PHANDLE ProcessHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__in_opt PCLIENT_ID ClientId
)
{
NTSTATUS status;
status = ProtectJudge(ClientId , "calc.exe");
if(NT_SUCCESS(status)) //判断是否是需要保护的进程
{
DbgPrint("Protect Successful!");
return STATUS_UNSUCCESSFUL;
}
return ((NTOPENPROCESS)g_OldAddr)(ProcessHandle,DesiredAccess,ObjectAttributes,ClientId);
}
// 开启/取消 页保护
VOID PAGEPROTECTON()
{
__asm
{
mov eax,cr0
or eax , 10000h
mov cr0 ,eax
sti
}
}
VOID PAGEPROTECTOFF()
{
__asm
{
cli
mov eax , cr0
and eax , not 10000h
mov cr0,eax
}
}
NTSTATUS ssdt_hook()
{
int u_index;
// DbgPrint("123");
// KdPrint("----%x-----",(PULONG)KeServiceDescriptorTable.ServiceTableBase);
DbgPrint("----%x-----",(PULONG)KeServiceDescriptorTable.ServiceTableBase);
// DbgPrint("456");
// for( u_index=0 ; u_index < KeServiceDescriptorTable.NumberOfServices ; u_index++)
// {
// DbgPrint("[%d] , %x", u_index , KeServiceDescriptorTable.ServiceTableBase[u_index]);
// }
//保存
g_OldAddr = (int)KeServiceDescriptorTable.ServiceTableBase[122];
PAGEPROTECTOFF();
KeServiceDescriptorTable.ServiceTableBase[122] = (int)MyNTOpenProcess;
PAGEPROTECTON();
return STATUS_SUCCESS;
}
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject , PUNICODE_STRING RegistryPath)
{
DbgPrint(("DriverEntry"));
if(!NT_SUCCESS(ssdt_hook()))
{
DbgPrint(("error"));
}
pDriverObject->DriverUnload = Driver_Unload;
return STATUS_SUCCESS;
}
// 122 是NtOpenProcess 对应在SSDT表中的下标
VOID Driver_Unload(IN PDRIVER_OBJECT pDriverObject)
{
PAGEPROTECTOFF();
KeServiceDescriptorTable.ServiceTableBase[122] = (int)g_OldAddr;
PAGEPROTECTON();
DbgPrint(("Driver_Unload finish.."));
}
SSDT是 ring3 到ring0 中用于查找系统功能调用而由Windows Kernel 组织的一张表,
ring3层的API以外壳形式 将参数,系统调用号 传给ring0 层 , 由ring0层再根据SSDT查表后调用真实功能.