status=ZwQuerySystemInformation(SystemModuleInformation,List,size,0);
if(!NT_SUCCESS(status))
{
KdPrint(("[FindModuleByAddress] query failed\n"));
//打印错误
KdPrint(("[FindModuleByAddress] status: 0x%x\n",status));
ExFreePool( List );
return ;
}
//得到了模块链表
//判断模块名
for( i=0; i<List->ulCount; i++)
{
//得到模块的范围
minAddress = (ULONG)List->smi[i].Base;
maxAddress = minAddress + List->smi[i].Size;
//判断地址
if( Address >= minAddress && Address <= maxAddress )
{
memcpy( buffer, List->smi[i].ImageName,sizeof(List->smi[i].ImageName));
KdPrint(("[FindModuleByAddress] modulename: %s\n",buffer));
//释放内存
ExFreePool(List);
break;
}
}
}
/***************************************************************************************
*
* 函数名:GetOriFunctionAddress
* 功能描述:得到原始SSDT表中函数地址
*
****************************************************************************************/
/***************************************************************************************
*
* 原理: 找到内核文件,获取基址BaseAddress
* 根据内核文件查找SSDT表的文件偏移SSDTFileOffset = SSDTRVA-(节RVA-节Offset)
* 读取函数的文件偏移FunctionFileOffset
* VA=BaseAddress+FunctionFileOffset-00400000=800d8000 + FunctionFileOffset
*
*****************************************************************************************/
/****************************************************************************************
*
* 根据RVA查找所在的文件偏移:FileOffset = Rva- (节Rva - 节Offset)
* 找到区块表
*****************************************************************************************/
ULONG FindFileOffsetByRva( ULONG ModuleAddress,ULONG Rva)
{
PIMAGE_DOS_HEADER dos;
PIMAGE_FILE_HEADER file;
PIMAGE_SECTION_HEADER section;
//区块数目
ULONG number;
ULONG i;
ULONG minAddress;
ULONG maxAddress;
ULONG SeFileOffset;
ULONG FileOffset;
dos = (PIMAGE_DOS_HEADER)ModuleAddress;
file = (PIMAGE_FILE_HEADER)( ModuleAddress + dos->e_lfanew + 4 );
//得到区块数量
number = file->NumberOfSections;
KdPrint(("[FindFileOffsetByRva] number :0x%x\n",number));
//得到第一个区块地址
section = (PIMAGE_SECTION_HEADER)(ModuleAddress + dos->e_lfanew + 4 + sizeof(IMAGE_FILE_HEADER) + file->SizeOfOptionalHeader);
for( i=0;i<number;i++)
{
minAddress = section[i].VirtualAddress;
maxAddress = minAddress + section[i].SizeOfRawData;
SeFileOffset = section[i].PointerToRawData;
if( Rva > minAddress && Rva < maxAddress)
{
KdPrint(("[FindFileOffsetByRva] minAddress :0x%x\n",minAddress));
KdPrint(("[FindFileOffsetByRva] SeFileOffset :0x%x\n",SeFileOffset));
FileOffset = Rva - ( minAddress - SeFileOffset);
KdPrint(("[FindFileOffsetByRva] FileOffset :0x%x\n",FileOffset));
break ;
}
}
return FileOffset;
}
//路径解析出子进程名
void GetModuleName( char *ProcessPath, char *ProcessName)
{
ULONG n = strlen( ProcessPath) - 1;
ULONG i = n;
KdPrint(("%d",n));
while( ProcessPath[i] != '\\')
{
i = i-1;
}
strncpy( ProcessName, ProcessPath+i+1,n-i);
}
/****************************************************************************************
*
* 根据传入的服务号得到函数原始地址
*
****************************************************************************************/
ULONG FindOriAddress( ULONG index )
{
//根据传入的index得到函数VA地址
//重定位函数地址
//BaseAddress - 0x00400000 + *(PULONG)(FileOffset+(index*4))
//ZwQuerySystemInformation得到内核文件基地址
//得到SSDT表的地址
//得到SSDT RVA 查找SSDT RVA所在的节
NTSTATUS status;
ULONG size;
ULONG BaseAddress;
ULONG SsdtRva;
ULONG FileOffset = 0;
PSYSMODULELIST list;
char Name[32]={0};
char PathName[256] = "\\SystemRoot\\system32\\";
ANSI_STRING name;
UNICODE_STRING modulename;
OBJECT_ATTRIBUTES object_attributes;
IO_STATUS_BLOCK io_status = {0};
HANDLE hFile;
//读取的位置
ULONG location;
LARGE_INTEGER offset;
ULONG address;
//得到需要申请的内存大小
ZwQuerySystemInformation( SystemModuleInformation,&size,0,&size );
//申请内存
list = (PSYSMODULELIST) ExAllocatePool( NonPagedPool,size );
//验证是否申请成功
if( list == NULL)
{
//申请失败
KdPrint(("[FindOriAddress] malloc memory failed\n"));
ExFreePool(list);
return 0;
}
status = ZwQuerySystemInformation( SystemModuleInformation,list,size,0);
if( !NT_SUCCESS( status ))
{
//获取信息失败
KdPrint(("[FindOriAddress] query failed\n"));
KdPrint(("[FindOriAddress] status:0x%x\n",status));
ExFreePool(list);
return 0;
}
//得到模块基址,第一个模块为内核文件
BaseAddress = (ULONG )list->smi[0].Base;
KdPrint(("[FindOriAddress] BaseAddress:0x%x\n",BaseAddress));
//分离出内核文件名
GetModuleName(list->smi[0].ImageName,Name);
KdPrint(("[FindOriAddress] processname:%s\n",Name));
strcat(PathName,Name);
RtlInitAnsiString(&name,PathName);
RtlAnsiStringToUnicodeString(&modulename,&name,TRUE);
KdPrint(("[FindOriAddress] modulename: %wZ\n",&modulename));
ExFreePool(list);
//经验证地址正确
//得到SSDT表的Rva
SsdtRva = (ULONG)KeServiceDescriptorTable->ServiceTableBase - BaseAddress;
//验证
KdPrint(("[FindOriAddress] SsdtRva:0x%x\n",SsdtRva));
//根据RVA查找文件偏移,//得到文件偏移了
FileOffset= FindFileOffsetByRva( BaseAddress,SsdtRva);
KdPrint(("[FindOriAddress] FileOffset:0x%x\n",FileOffset));
//读取的位置
location = FileOffset + index * 4;
offset.QuadPart =location;
KdPrint(("[FindOriAddress] location:0x%x\n",location));
//利用ZwReadFile读取文件
//初始化OBJECT_ATTRIBUTES结构
InitializeObjectAttributes(
&object_attributes,
&modulename,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL);
//打开文件
status = ZwCreateFile(
&hFile,
FILE_EXECUTE | SYNCHRONIZE,
&object_attributes,
&io_status,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE |
FILE_RANDOM_ACCESS |
FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0);
if( !NT_SUCCESS( status ))
{
KdPrint(("[FindOriAddress] open error\n"));
KdPrint(("[FindOriAddress] status = 0x%x\n", status));
ZwClose( hFile );
return 0;
}
status = ZwReadFile(
hFile,
NULL,
NULL,
NULL,
NULL,
&address,
sizeof(ULONG),
&offset,
NULL);
if( !NT_SUCCESS( status ))
{
KdPrint(("[FindOriAddress] read error\n"));
KdPrint(("[FindOriAddress] status = 0x%x\n", status));
ZwClose( hFile );
return 0;
}
KdPrint(("[FindOriAddress] address:0x%x\n",address));
//重定位
address = BaseAddress - 0x00400000 + address;
KdPrint(("[FindOriAddress] Oriaddress:0x%x\n",address));
//释放动态分配的内存
RtlFreeUnicodeString(&modulename);
ZwClose( hFile );
return address;
}
/******************************************************************************************
*
* 得到SSDT Shadow当前地址
* 1、KeServiceDescriptorTable - 0x40 + 0x10
* 2、搜索KeAddSystemServiceTable函数,特征码
* 3、Kthread->ServiceTable指向
* 4、MJ提出的搜索特定内存
*
*******************************************************************************************/
//方式1,XP下-0x40;
ULONG GetSSDTShadowAddress1()
{
ULONG address;
ULONG ssdt;
ssdt = (ULONG)KeServiceDescriptorTable;
address = ssdt - 0x30;
KdPrint(("[GetSSDTShadowAddress] ssdt:0x%x\n",ssdt));
KdPrint(("[GetSSDTShadowAddress] address:0x%x\n",address));
return address;
}
//方式2
ULONG GetSSDTShadowAddress2()
{
ULONG address;
PUCHAR addr;
PUCHAR p;
addr = (PUCHAR)KeAddSystemServiceTable;
for( p=addr; p<addr+PAGE_SIZE; p++)
{
if(*(PUSHORT)p == 0x888D)
{
address = *(PULONG)((ULONG)p+2);
break;
}
}
address = address + 0x10;
KdPrint(("[GetSSDTShadowAddress] address:0x%x\n",address));
return address;
}