最初听说卡巴斯基能自己增加服务,查了下资料,找到了份源代码,找个别人的模板驱动程序 整合整理并注释了下。
附件包含ring3和ring0代码
自己调用服务 则输出
Kernel service with 1 parameters called
param1=15
驱动加载完成后 查看RKU 看到了SSDT已经正确的增加了
RING3是这样调用的
function SampleService1( param : DWORD) : dword;
var
stackframe : Pointer; // 参数地址
begin
stackframe := @param;
asm
mov eax, ServiceStart
add eax, 1 //eax存放调用号 调用自己增加的第二个服务
mov edx, stackframe //edx存放参数堆栈的地址
int 2eh //这句执行后会看到dbgview输出上面的信息
end;
end;
下面是驱动中两个主要功能函数的实现
1,KeServiceDescriptorTableShadow的定位
2,KeServiceDescriptorTable的处理
// 得到KeServiceDescriptorTableShadow的地址 原理搜索KeAddSystemServiceTable中的常量 因为KeAddSystemServiceTable使用了得到KeServiceDescriptorTableShadow的地址
unsigned int GetAddrssofShadowTable()
{
int i;
unsigned char *p;
unsigned int dwordatbyte;
p=(unsigned char *)KeAddSystemServiceTable;
DbgPrint("KeServiceDescriptorTable->ServiceTableBase = %x\n", KeServiceDescriptorTable->ServiceTableBase);
DbgPrint("KeAddSystemServiceTable = %x\n", KeAddSystemServiceTable);
for (i=0; i<4096; i++, p++) {
__try {
dwordatbyte=*(unsigned int *)p;
}
__except (EXCEPTION_EXECUTE_HANDLER) {
DbgPrint("发生异常\n");
return 0;
}
if (MmIsAddressValid((PVOID)dwordatbyte)) {
if (memcmp((PVOID)dwordatbyte, KeServiceDescriptorTable, 16)==0) {
if ((PVOID)dwordatbyte==KeServiceDescriptorTable) {
continue;
}
return dwordatbyte;
}
}
}
return 0;
}
NTSTATUS AddServices()
{
ULONG Addrtemp;
DbgPrint("AddServices开始执行\n");
PServiceDescriptorTableEntry KeServiceDescriptorTableShadow;
unsigned int NumberOfServices;
NumberOfServices=sizeof(ServiceTableBase)/sizeof(ServiceTableBase[0]); // 将要增加的服务函数的个数
KeServiceDescriptorTableShadow=(PServiceDescriptorTableEntry)GetAddrssofShadowTable(); //获取 Shadow SSDT 地址
if (KeServiceDescriptorTableShadow==NULL) {
DbgPrint("没有找到TableShadow\n");
return STATUS_UNSUCCESSFUL;
}
DbgPrint("KeServiceDescriptorTableShadow=%x\n", KeServiceDescriptorTableShadow);
NewNumberOfServices=KeServiceDescriptorTable->NumberOfServices+NumberOfServices; //增加后服务数目
StartingServiceId=KeServiceDescriptorTable->NumberOfServices; //得到后来增加服务中第一个服务的序号
DbgPrint("增加的第一个服务号是StartingServiceId %x \n", StartingServiceId);
/* Allocate suffcient memory to hold the exising services as well as
the services you want to add */
NewServiceTableBase=(unsigned int *) ExAllocatePool(PagedPool, NewNumberOfServices*sizeof(unsigned int));
if (NewServiceTableBase==NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
NewParamTableBase=(unsigned char *) ExAllocatePool(PagedPool, NewNumberOfServices);
if (NewParamTableBase==NULL) {
ExFreePool(NewServiceTableBase);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Backup the exising SSDT and SSPT */
memcpy(NewServiceTableBase, KeServiceDescriptorTable->ServiceTableBase, //原来的SSDT服务地址表拷贝到分配的NewServiceTableBase内存中去
KeServiceDescriptorTable->NumberOfServices*sizeof(unsigned int));
memcpy(NewParamTableBase, KeServiceDescriptorTable->ParamTableBase, //原来的SSDT参数表拷贝到新分配的NewParamTableBase内存中去
KeServiceDescriptorTable->NumberOfServices);
/*对地址表和参数表追加*/
memcpy(NewServiceTableBase+KeServiceDescriptorTable->NumberOfServices,
ServiceTableBase, sizeof(ServiceTableBase));
memcpy(NewParamTableBase+KeServiceDescriptorTable->NumberOfServices,
ParamTableBase, sizeof(ParamTableBase));
/*更新KeServiceDescriptorTableEntry的SSDT和 SSPT*/
KeServiceDescriptorTable->ServiceTableBase=NewServiceTableBase;
KeServiceDescriptorTable->ParamTableBase=NewParamTableBase;
KeServiceDescriptorTable->NumberOfServices=NewNumberOfServices;
//这里输出新的SSDT 服务函数的地址
DbgPrint("NewServiceTableBase KeServiceDescriptorTable->ServiceTableBase = %x\n", KeServiceDescriptorTable->ServiceTableBase);
/* 更新KeServiceDescriptorTableShadow的SSDT和 SSPT*/
KeServiceDescriptorTableShadow->ServiceTableBase=NewServiceTableBase;
KeServiceDescriptorTableShadow->ParamTableBase=NewParamTableBase;
KeServiceDescriptorTableShadow->NumberOfServices=NewNumberOfServices;
//打印出第一个服务的地址
Addrtemp = (ULONG)KeServiceDescriptorTable->ServiceTableBase ;
Addrtemp = Addrtemp + StartingServiceId * 4;
Addrtemp = *(ULONG*)Addrtemp;
DbgPrint("增加的第一个服务的地址是 Addrtemp is %x\n", Addrtemp);
return STATUS_SUCCESS;
}
[注意]看雪招聘,专注安全领域的专业人才平台!
上传的附件: