首页
社区
课程
招聘
[求助][内核]怎么取到原地址
发表于: 2013-2-8 16:45 6143

[求助][内核]怎么取到原地址

2013-2-8 16:45
6143
disk fsd  atapi hook原理基本髙清楚了~~~~
但是如何取到他们的源地址

[课程]Linux pwn 探索篇!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (12)
雪    币: 608
活跃值: (643)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
1.解析原始文件搜索特征码
2.解析PDB
2013-2-8 17:06
0
雪    币: 219
活跃值: (738)
能力值: (RANK:290 )
在线值:
发帖
回帖
粉丝
3
饿~~~~~~~~具体代码~ 娶不到原地址 直接上去就会挂的
2013-2-8 17:14
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
4
模拟执行DriverEntry来自动填充
2013-2-8 17:57
0
雪    币: 371
活跃值: (72)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
5
又学到了...
2013-2-8 18:04
0
雪    币: 219
活跃值: (738)
能力值: (RANK:290 )
在线值:
发帖
回帖
粉丝
6
不是这个~~~  我说被别人hook了   ~~~~  我想得到它原来地址
如果 a 先 吧 b hook了
我是c
c 在hook b  这个是派遣函数式a
取到a 把他当做我的 下层
如果他写在了 我会直接访问无效地址
一定会出现8e错误的
2013-2-8 18:26
0
雪    币: 219
活跃值: (738)
能力值: (RANK:290 )
在线值:
发帖
回帖
粉丝
7
来人啊
2013-2-9 13:47
0
雪    币: 7651
活跃值: (523)
能力值: ( LV9,RANK:610 )
在线值:
发帖
回帖
粉丝
8
不知道你说的无效地址是什么意思。。。或者你没理解我的意思
2013-2-9 18:39
0
雪    币: 219
活跃值: (738)
能力值: (RANK:290 )
在线值:
发帖
回帖
粉丝
9
应该是我的理解有问题~~~~ 还是我在找找资料~~~  新年好啊~~
2013-2-9 19:06
0
雪    币: 773
活跃值: (442)
能力值: ( LV9,RANK:200 )
在线值:
发帖
回帖
粉丝
10
呵呵 这些地址有可能是没有原始地址,因为微软初始化的时候并没有为这些 IRP 指定函数,就好像你的驱动一样,没用的你设置他干啥
2013-2-9 20:06
0
雪    币: 219
活跃值: (738)
能力值: (RANK:290 )
在线值:
发帖
回帖
粉丝
11
楼上的新年快乐啊
2013-2-9 20:37
0
雪    币: 227
活跃值: (66)
能力值: ( LV7,RANK:100 )
在线值:
发帖
回帖
粉丝
12
FSD通常是分别处理Fastfat.sys和Ntfs.sys。Disk则是CLASSPNP.sys,同理。
以Fastfat.sys为例,DriverEntry里有如下代码
loc_3433D:
push    70h
pop     edi
push    edi             ; size_t
mov     eax, offset _FatFastIoDispatch
push    ebx             ; int
push    eax             ; void *
mov     dword ptr [esi+34h], offset _FatUnload@4 ; 此处esi == DriverEntry
mov     dword ptr [esi+38h], offset _FatFsdCreate@8 ; FatFsdCreate(x,x)
mov     dword ptr [esi+40h], offset _FatFsdClose@8 ; FatFsdClose(x,x)
mov     dword ptr [esi+44h], offset _FatFsdRead@8 ; FatFsdRead(x,x)
mov     dword ptr [esi+48h], offset _FatFsdWrite@8 ; FatFsdWrite(x,x)
mov     dword ptr [esi+4Ch], offset _FatFsdQueryInformation@8 ; FatFsdQueryInformation(x,x)
mov     dword ptr [esi+50h], offset _FatFsdSetInformation@8 ; FatFsdSetInformation(x,x)
mov     dword ptr [esi+54h], offset _FatFsdQueryEa@8 ; FatFsdQueryEa(x,x)
mov     dword ptr [esi+58h], offset _FatFsdQueryEa@8 ; FatFsdQueryEa(x,x)
mov     dword ptr [esi+5Ch], offset _FatFsdFlushBuffers@8 ; FatFsdFlushBuffers(x,x)
mov     dword ptr [esi+60h], offset _FatFsdQueryVolumeInformation@8 ; FatFsdQueryVolumeInformation(x,x)
mov     dword ptr [esi+64h], offset _FatFsdSetVolumeInformation@8 ; FatFsdSetVolumeInformation(x,x)
mov     dword ptr [esi+80h], offset _FatFsdCleanup@8 ; FatFsdCleanup(x,x)
mov     dword ptr [esi+68h], offset _FatFsdDirectoryControl@8 ; FatFsdDirectoryControl(x,x)
mov     dword ptr [esi+6Ch], offset _FatFsdFileSystemControl@8 ; FatFsdFileSystemControl(x,x)
mov     dword ptr [esi+7Ch], offset _FatFsdLockControl@8 ; FatFsdLockControl(x,x)
mov     dword ptr [esi+70h], offset _FatFsdDeviceControl@8 ; FatFsdDeviceControl(x,x)
mov     dword ptr [esi+78h], offset _FatFsdShutdown@8 ; FatFsdShutdown(x,x)
mov     dword ptr [esi+0A4h], offset _FatFsdPnp@8 ; FatFsdPnp(x,x)
mov     [esi+28h], eax


获取当前函数地址只需要得到Fastfat.DriverEntry->MajorFunction[]即可

获取原始函数地址则要解析磁盘上的Fastfat.sys文件,方法是根据特征码在DriverEntry函数段里暴力搜索,取得offset _FatFsdCreate等例程的RVA,然后根据Fastfat.sys内核模块基址计算出例程的原始内存地址。另外有些例程没有被驱动程序特殊指定,则使用系统默认的处理例程(对应ntoskrnl.exe模块),这些函数的原始地址没有办法通过解析Fastfat.sys取得

以前写过XPSP3的FSD HOOK检测,没有经过严格测试,代码很挫(算法完全凭感觉写的..),你可以简单参考一下思路:
#include <ntddk.h>
#include "File.h"

typedef struct _RESTORE_DISPATCH_FUNCTION {
	PDRIVER_OBJECT DriverObject;
	ULONG FuncId;
	ULONG OrginalValue;
} RESTORE_DISPATCH_FUNCTION, *PRESTORE_DISPATCH_FUNCTION;

typedef struct _DISPATCH_FUNCTION_INFORMATION {
	ULONG FuncAddr[29];
	ULONG OrginalFuncAddr[29];
} DISPATCH_FUNCTION_INFORMATION, *PDISPATCH_FUNCTION_INFORMATION;

typedef struct _QUERY_DISPATCH_FUNCTION_INFORMATION {
	PDRIVER_OBJECT DriverObject;
	WCHAR FilePath[260];
} QUERY_DISPATCH_FUNCTION_INFORMATION, *PQUERY_DISPATCH_FUNCTION_INFORMATION;

NTSTATUS FxRestoreDispatchFunctionHook(PRESTORE_DISPATCH_FUNCTION lpReDisFuncInfo)
{
	if (!MmIsAddressRangeValid(lpReDisFuncInfo->DriverObject->MajorFunction, 4 * 29)) {
		return STATUS_UNSUCCESSFUL;
	}
	//DbgPrint("DriverObject: %X, FuncId: %d, RealAddr: %X", lpReDisFuncInfo->DriverObject, lpReDisFuncInfo->FuncId, lpReDisFuncInfo->OrginalValue);
	lpReDisFuncInfo->DriverObject->MajorFunction[lpReDisFuncInfo->FuncId] = (PDRIVER_DISPATCH)lpReDisFuncInfo->OrginalValue;
	return STATUS_SUCCESS;
}

NTSTATUS FxGetDispatchFunction(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING DriverPath, PDISPATCH_FUNCTION_INFORMATION lpDispatchFunction) //PDISPATCH_FUNCTION_INFORMATION *pDispatchFunctionLinkHead)
{
	if (!MmIsAddressRangeValid(pDriverObject->MajorFunction, 4 * 29)) {
		return STATUS_UNSUCCESSFUL;
	}

	DISPATCH_FUNCTION_INFORMATION DispatchFunction;
	RtlZeroMemory(lpDispatchFunction, sizeof(DISPATCH_FUNCTION_INFORMATION));
	RtlCopyMemory(lpDispatchFunction->FuncAddr, pDriverObject->MajorFunction, 4 * 29);
	NTSTATUS Status = NULL;

	HANDLE hFile = NULL;
	OBJECT_ATTRIBUTES ObjAttr;
	RtlZeroMemory(&ObjAttr, sizeof(OBJECT_ATTRIBUTES));
	// \\??\\C:\\WINDOWS\\system32\\drivers\\Ntfs.sys
	InitializeObjectAttributes(&ObjAttr, DriverPath, NULL, NULL, NULL);
	//DbgPrint("(%d)%ws", DriverPath->Length, DriverPath->Buffer);
	IO_STATUS_BLOCK IoFileStatus;
	Status = ZwCreateFile(&hFile, GENERIC_READ | GENERIC_WRITE, &ObjAttr, &IoFileStatus, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, NULL, NULL, NULL);
	if (!NT_SUCCESS(Status)) {
		//DbgPrint("CreateFile faild!");
		return STATUS_UNSUCCESSFUL;
	}

	LARGE_INTEGER FilePointer;
	RtlZeroMemory(&FilePointer, sizeof(LARGE_INTEGER));
	IMAGE_DOS_HEADER DosHeader;
	Status = ZwReadFile(hFile, NULL, NULL, NULL, &IoFileStatus, &DosHeader, sizeof(IMAGE_DOS_HEADER), &FilePointer, NULL);
	if (!NT_SUCCESS(Status)) {
		ZwClose(hFile);
		return STATUS_UNSUCCESSFUL;
	}

	FilePointer.LowPart = DosHeader.e_lfanew + 24;
	FilePointer.HighPart = 0;
	IMAGE_OPTIONAL_HEADER OptionalHeader;
	ZwReadFile(hFile, NULL, NULL, NULL, &IoFileStatus, &OptionalHeader, sizeof(IMAGE_OPTIONAL_HEADER), &FilePointer, NULL);
	if (!NT_SUCCESS(Status)){
		ZwClose(hFile);
		return STATUS_UNSUCCESSFUL;
	}
	//DbgPrint("AddressOfEntryPoint: %X, ImageBase: %X", OptionalHeader.AddressOfEntryPoint, OptionalHeader.ImageBase);
	ULONG ImageBase = OptionalHeader.ImageBase;
	ULONG StartAddr = (ULONG)ExAllocatePool(NonPagedPool, 0x200);
	if (StartAddr == 0) {
		ZwClose(hFile);
		return STATUS_UNSUCCESSFUL;
	}

	FilePointer.LowPart = OptionalHeader.AddressOfEntryPoint;
	FilePointer.HighPart = 0;
	ZwReadFile(hFile, NULL, NULL, NULL, &IoFileStatus, (PVOID)StartAddr, 0x200, &FilePointer, NULL);
	if (!NT_SUCCESS(Status)) {
		ZwClose(hFile);
		ExFreePoolWithTag((PVOID)StartAddr, 0x200);
		return STATUS_UNSUCCESSFUL;
	}
	ZwClose(hFile);

	USHORT usHardCode1 = 0x46C7;
	USHORT usHardCode2 = 0x86C7;
	USHORT usHardCode3 = 0x4689;
	USHORT usHardCode4 = 0x8689;
	UCHAR ucHardCode5 = 0xB8;
	USHORT usCheckCode = NULL;
	ULONG ulEax = NULL;
	BOOLEAN bIsInEax = FALSE;
	UCHAR ucOffset = NULL;
	UCHAR ucIndex = NULL;
	ULONG ulOrginalAddr = NULL;

	for (ULONG CheckAddr = StartAddr; CheckAddr <= StartAddr + 0x200 - 7; CheckAddr++)
	{
		if (!MmIsAddressRangeValid((PUSHORT)CheckAddr, 7)) break;
		//DbgPrint("Valid: %X, Data: %X", CheckAddr, *(PUSHORT)CheckAddr);
		usCheckCode = *(PUSHORT)CheckAddr;
		if (usCheckCode == usHardCode1 || usCheckCode == usHardCode2) {
			ucOffset = *(PUCHAR)(CheckAddr + 2);
			if (!(ucOffset >= 0x38 && ucOffset <= 0xB0)) continue;
			ucIndex = (ucOffset - 0x38) / 4;
			if (usCheckCode == usHardCode1) {
				ulOrginalAddr = *(PULONG)(CheckAddr + 3);
			} else {
				ulOrginalAddr = *(PULONG)(CheckAddr + 6);
			}
			ulOrginalAddr = (ULONG)pDriverObject->DriverStart + ulOrginalAddr - ImageBase;
			//DbgPrint("(%d)ulOrginalAddr: %X", ucIndex, ulOrginalAddr);
			lpDispatchFunction->OrginalFuncAddr[ucIndex] = ulOrginalAddr;
		} else if (usCheckCode == usHardCode3 || usCheckCode == usHardCode4) {
			DbgPrint("Found HardCode3-4 At %X, bIsInEax: %d", CheckAddr, bIsInEax);
			if (!bIsInEax) {
				if (*(PUCHAR)(CheckAddr - 5) = ucHardCode5) {
					ulEax = *(PULONG)(CheckAddr - 4);
					bIsInEax = TRUE;
					ucOffset = *(PUCHAR)(CheckAddr + 2);
					DbgPrint("Just In Eax, ulEax: %X, ucOffset: %X", ulEax, ucOffset);
					if (!(ucOffset >= 0x38 && ucOffset <= 0xB0)) continue;
					ucIndex = (ucOffset - 0x38) / 4;
					ulOrginalAddr = (ULONG)pDriverObject->DriverStart + ulEax - ImageBase;
					lpDispatchFunction->OrginalFuncAddr[ucIndex] = ulOrginalAddr;
				}
			} else {
				ucOffset = *(PUCHAR)(CheckAddr + 2);
				DbgPrint("Already In Eax, ulEax: %X, ucOffset: %X", ulEax, ucOffset);
				if (!(ucOffset >= 0x38 && ucOffset <= 0xB0)) continue;
				ucIndex = (ucOffset - 0x38) / 4;
				ulOrginalAddr = (ULONG)pDriverObject->DriverStart + ulEax - ImageBase;
				lpDispatchFunction->OrginalFuncAddr[ucIndex] = ulOrginalAddr;
				if (usCheckCode == usHardCode3) {
					if (*(PUSHORT)(CheckAddr + 3) != usHardCode3 && *(PUSHORT)(CheckAddr + 3) != usHardCode4) {
						bIsInEax = FALSE;
					}
				} else {
					if (*(PUSHORT)(CheckAddr + 6) != usHardCode3 && *(PUSHORT)(CheckAddr + 6) != usHardCode4) {
						bIsInEax = FALSE;
					}
				}
			}
		}
	}

	ExFreePoolWithTag((PVOID)StartAddr, 0x200);

	return STATUS_SUCCESS;
}


另外还有一种方法我没实现,就是上面教主说的模拟执行待检测驱动的DriverEntry,这应该算是比较通用的Dispatch Hook检测方式,不过比较困难,个人认为可以设计一个轻量级的虚拟机处理mov lea add sub等简单指令,仅仅模拟一下DriverEntry,完毕后参数里的MajorFunction[]保存的就是原始地址。虽然通用但也是比较奇葩的方法,还是有针对性的
2013-2-9 21:48
0
雪    币: 219
活跃值: (738)
能力值: (RANK:290 )
在线值:
发帖
回帖
粉丝
13
O(∩_∩)O谢谢了   新年好啊
2013-2-9 22:10
0
游客
登录 | 注册 方可回帖
返回
//