这里还是看windows黑客编程技术详解 学的
其实 里面很多东西 自己以前都会 主要 的是不知道索引号 放在了哪里
看了这本书 才发现 索引号 如果大家对PE不理解 可以去补一下 PE 现在回头来看看 还是比较简单的
至于索引号 这里可以 说一下
以下代码均是 windows黑客编程技术详解 一书自带的代码
#ifdef _WIN64
ulFunctionIndex = *(ULONG *)((PUCHAR)lpFuncAddr + 4);
#else
ulFunctionIndex = *(ULONG *)((PUCHAR)lpFuncAddr + 1);
之所以 这样搞 是因为
win32:
mov eax,SSDT函数索引号(4字节)
win64:
mov r10,ecx
mov eax,ssdt函数索引号(4字节)
然后 步骤的话 其实也是很简单
先初始化InitalizeObjectAttributes 宏初始化文件对象 内核文件路径前面需要加上\\?\\ 然后 用ZwOpenFile 打开映射的文件
然后调用ZwCreateSection 然后 再用ZwMapVIewOfSection 就行了 记得当时写壳的时候也用到了 看来知识是需要预习的了
都忘得差不多了
UNICODE_STRING ustrDllFileName;
RtlInitUnicodeString(&ustrDllFileName, L"\\??\\C:\\Windows\\System32\\ntdll.dll");
ULONG ulSSDTFunctionIndex = GetSSDTFunctionIndex(ustrDllFileName, "ZwOpenProcess");
然后
ULONG GetSSDTFunctionIndex(UNICODE_STRING ustrDllFileName, PCHAR pszFunctionName)
{
ULONG ulFunctionIndex = 0;
NTSTATUS status = STATUS_SUCCESS;
HANDLE hFile = NULL;
HANDLE hSection = NULL;
PVOID pBaseAddress = NULL;
// 内存映射文件
status = DllFileMap(ustrDllFileName, &hFile, &hSection, &pBaseAddress);
if (!NT_SUCCESS(status))
{
KdPrint(("DllFileMap Error!\n"));
return ulFunctionIndex;
}
// 根据导出表获取导出函数地址, 从而获取 SSDT 函数索引号
ulFunctionIndex = GetIndexFromExportTable(pBaseAddress, pszFunctionName);
// 释放
ZwUnmapViewOfSection(NtCurrentProcess(), pBaseAddress);
ZwClose(hSection);
ZwClose(hFile);
return ulFunctionIndex;
}
在这里 可以看得出来
NTSTATUS DllFileMap(UNICODE_STRING ustrDllFileName, HANDLE *phFile, HANDLE *phSection, PVOID *ppBaseAddress)
{
NTSTATUS status = STATUS_SUCCESS;
HANDLE hFile = NULL;
HANDLE hSection = NULL;
OBJECT_ATTRIBUTES objectAttributes = { 0 };
IO_STATUS_BLOCK iosb = { 0 };
PVOID pBaseAddress = NULL;
SIZE_T viewSize = 0;
// 打开 DLL 文件, 并获取文件句柄
InitializeObjectAttributes(&objectAttributes, &ustrDllFileName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);
status = ZwOpenFile(&hFile, GENERIC_READ, &objectAttributes, &iosb,
FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
if (!NT_SUCCESS(status))
{
KdPrint(("ZwOpenFile Error! [error code: 0x%X]", status));
return status;
}
// 创建一个节对象, 以 PE 结构中的 SectionALignment 大小对齐映射文件
status = ZwCreateSection(&hSection, SECTION_MAP_READ | SECTION_MAP_WRITE, NULL, 0, PAGE_READWRITE, 0x1000000, hFile);
if (!NT_SUCCESS(status))
{
ZwClose(hFile);
KdPrint(("ZwCreateSection Error! [error code: 0x%X]", status));
return status;
}
// 映射到内存
status = ZwMapViewOfSection(hSection, NtCurrentProcess(), &pBaseAddress, 0, 1024, 0, &viewSize, ViewShare, MEM_TOP_DOWN, PAGE_READWRITE);
if (!NT_SUCCESS(status))
{
ZwClose(hSection);
ZwClose(hFile);
KdPrint(("ZwMapViewOfSection Error! [error code: 0x%X]", status));
return status;
}
// 返回数据
*phFile = hFile;
*phSection = hSection;
*ppBaseAddress = pBaseAddress;
return status;
}
DllFileMap 是 申请一段内存并映射
然后 下面就是寻找PE就可以了
// 根据导出表获取导出函数地址, 从而获取 SSDT 函数索引号
ULONG GetIndexFromExportTable(PVOID pBaseAddress, PCHAR pszFunctionName)
{
ULONG ulFunctionIndex = 0;
// Dos Header
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pBaseAddress;
// NT Header
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((PUCHAR)pDosHeader + pDosHeader->e_lfanew);
// Export Table
PIMAGE_EXPORT_DIRECTORY pExportTable = (PIMAGE_EXPORT_DIRECTORY)((PUCHAR)pDosHeader + pNtHeaders->OptionalHeader.DataDirectory[0].VirtualAddress);
// 有名称的导出函数个数
ULONG ulNumberOfNames = pExportTable->NumberOfNames;
// 导出函数名称地址表
PULONG lpNameArray = (PULONG)((PUCHAR)pDosHeader + pExportTable->AddressOfNames);
PCHAR lpName = NULL;
// 开始遍历导出表
for (ULONG i = 0; i < ulNumberOfNames; i++)
{
lpName = (PCHAR)((PUCHAR)pDosHeader + lpNameArray[i]);
// 判断是否查找的函数
if (0 == _strnicmp(pszFunctionName, lpName, strlen(pszFunctionName)))
{
// 获取导出函数地址
USHORT uHint = *(USHORT *)((PUCHAR)pDosHeader + pExportTable->AddressOfNameOrdinals + 2 * i);
ULONG ulFuncAddr = *(PULONG)((PUCHAR)pDosHeader + pExportTable->AddressOfFunctions + 4 * uHint);
PVOID lpFuncAddr = (PVOID)((PUCHAR)pDosHeader + ulFuncAddr);
// 获取 SSDT 函数 Index
#ifdef _WIN64
ulFunctionIndex = *(ULONG *)((PUCHAR)lpFuncAddr + 4);
#else
ulFunctionIndex = *(ULONG *)((PUCHAR)lpFuncAddr + 1);
#endif
break;
}
}
return ulFunctionIndex;
}
上图就是效果图
代表了 SSDT ZwOpenProcess 的索引值是 35