drv experiment : 从内核API代码定位函数地址或结构指针地址

用WinDbg看已经导出的内核API代码, 如果看到需要的未导出函数调用或想直接从汇编代码中定位那个API地址,

可以定位 CALL指令中未导出函数地址.


未导出函数地址 = 已经导出的内核API首地址 + 计算出的 硬编码偏移.


得到已经导出的内核API地址

PVOID GetKernelApiAddress(wchar_t * pcApiName)
{
    UNICODE_STRING str;

    if (NULL == pcApiName)
        return NULL;

    RtlInitUnicodeString(&str, pcApiName);

    /// MmGetSystemRoutineAddress
    /// If the function name can be resolved, 
    /// the routine returns a pointer to the function. 
    /// Otherwise, the routine returns NULL.

    return MmGetSystemRoutineAddress(&str);
}

用WinDbg反汇编已导出内核API, 手工计算出未导出API地址的相对偏移.

例如: 从 KeCapturePersistentThreadState 中得到 KdGetDataBlockAPI地址.

kd> uf 0x804f286a
nt!KeCapturePersistentThreadState:
804f286a 8bff            mov     edi,edi
804f286c 55              push    ebp
804f286d 8bec            mov     ebp,esp
804f286f 51              push    ecx
804f2870 53              push    ebx
804f2871 8b5d24          mov     ebx,dword ptr [ebp+24h]
804f2874 56              push    esi
804f2875 e814510000      call    nt!KdGetDataBlock (804f798e)
804f287a 33f6            xor     esi,esi


uf nt!KdGetDataBlock

nt!KdGetDataBlock:
804f798e b8e06a5480      mov     eax,offset nt!KdDebuggerDataBlock (80546ae0)
804f7993 c3              ret

手工计算需要的未导出API的过程


addr_KeCapturePersistentThreadState = 0x804f286a

offset_call_KdGetDataBlock = 0x804f2875 - addr_KeCapturePersistentThreadState;

addr_call_KdGetDataBlock = addr_KeCapturePersistentThreadState + offset_call_KdGetDataBlock;

offset_KdGetDataBlock = (ULONG)(*(ULONG *)(addr_call_KdGetDataBlock + 1)); ///< Call命令为0xe8, 一个字节

len_call_KdGetDataBlock = 5; ///<  e814510000 一共5个字节

addr_KdGetDataBlock = addr_call_KdGetDataBlock  + len_call_KdGetDataBlock  + offset_KdGetDataBlock ;///< get it ~


如果在内核API反汇编代码中要得到数据结构指针地址, 同理.

只要有内核API用到了这个数据结构指针, 就能找到.

例如: nt!KdGetDataBlock API中的 数据结构指针 nt!KdDebuggerDataBlock


nt!KdDebuggerDataBlock 是未文档的数据结构 KD_DEBUGGER_DATA_BLOCK

如果该数据结构定义未知, 那就得在网上搜索前辈们逆向出来的数据结构资料了.

http://gr8lkd.googlecode.com/svn/trunk/sys/dumptypes.h

typedef struct _KD_DEBUGGER_DATA_BLOCK {
	ULONG  Unknown1[4];
	ULONG  ValidBlock; // 'GBDK'
	ULONG  Size; // 0x290
	PFUNC<PVOID>  _imp__VidInitialize;
	PFUNC<PVOID>  RtlpBreakWithStatusInstruction;
	ULONG  Unknown2[4];
	PFUNC<PVOID>  KiCallUserMode;
	ULONG  Unknown3[2];
	PFUNC<PVOID>  PsLoadedModuleList;
	PFUNC<PVOID>  PsActiveProcessHead;
	PFUNC<PVOID>  PspCidTable;
	PFUNC<PVOID>  ExpSystemResourcesList;
	PFUNC<PVOID>  ExpPagedPoolDescriptor;
	PFUNC<PVOID>  ExpNumberOfPagedPools;
	PFUNC<PVOID>  KeTimeIncrement;
	PFUNC<PVOID>  KeBugCheckCallbackListHead;
	PFUNC<PVOID>  KiBugCheckData;
	PFUNC<PVOID>  IopErrorLogListHead;
	PFUNC<PVOID>  ObpRootDirectoryObject;
	PFUNC<PVOID>  ObpTypeObjectType;
	PFUNC<PVOID>  MmSystemCacheStart;
	PFUNC<PVOID>  MmSystemCacheEnd;
	PFUNC<PVOID>  MmSystemCacheWs;
	PFUNC<PVOID>  MmPfnDatabase;
	PFUNC<PVOID>  MmSystemPtesStart;
	PFUNC<PVOID>  MmSystemPtesEnd;
	PFUNC<PVOID>  MmSubsectionBase;
	PFUNC<PVOID>  MmNumberOfPagingFiles;
	PFUNC<PVOID>  MmLowestPhysicalPage;
	PFUNC<PVOID>  MmHighestPhysicalPage;
	PFUNC<PVOID>  MmNumberOfPhysicalPages;
	PFUNC<PVOID>  MmMaximumNonPagedPoolInBytes;
	PFUNC<PVOID>  MmNonPagedSystemStart;
	PFUNC<PVOID>  MmNonPagedPoolStart;
	PFUNC<PVOID>  MmNonPagedPoolEnd;
	PFUNC<PVOID>  MmPagedPoolStart;
	PFUNC<PVOID>  MmPagedPoolEnd;
	PFUNC<PVOID>  MmPagedPoolInfo;
	PFUNC<PVOID>  Unknown4;
	PFUNC<PVOID>  MmSizeOfPagedPoolInBytes;
	PFUNC<PVOID>  MmTotalCommitLimit;
	PFUNC<PVOID>  MmTotalCommittedPages;
	PFUNC<PVOID>  MmSharedCommit;
	PFUNC<PVOID>  MmDriverCommit;
	PFUNC<PVOID>  MmProcessCommit;
	PFUNC<PVOID>  MmPagedPoolCommit;
	PFUNC<PVOID>  Unknown5;
	PFUNC<PVOID>  MmZeroedPageListHead;
	PFUNC<PVOID>  MmFreePageListHead;
	PFUNC<PVOID>  MmStandbyPageListHead;
	PFUNC<PVOID>  MmModifiedPageListHead;
	PFUNC<PVOID>  MmModifiedNoWritePageListHead;
	PFUNC<PVOID>  MmAvailablePages;
	PFUNC<PVOID>  MmResidentAvailablePages;
	PFUNC<PVOID>  PoolTrackTable;
	PFUNC<PVOID>  NonPagedPoolDescriptor;
	PFUNC<PVOID>  MmHighestUserAddress;
	PFUNC<PVOID>  MmSystemRangeStart;
	PFUNC<PVOID>  MmUserProbeAddress;
	PFUNC<PVOID>  KdPrintCircularBuffer;
	PFUNC<PVOID>  KdPrintWritePointer;
	PFUNC<PVOID>  KdPrintWritePointer2;
	PFUNC<PVOID>  KdPrintRolloverCount;
	PFUNC<PVOID>  MmLoadedUserImageList;
	PFUNC<PVOID>  NtBuildLab;
	PFUNC<PVOID>  Unknown6;
	PFUNC<PVOID>  KiProcessorBlock;
	PFUNC<PVOID>  MmUnloadedDrivers;
	PFUNC<PVOID>  MmLastUnloadedDriver;
	PFUNC<PVOID>  MmTriageActionTaken;
	PFUNC<PVOID>  MmSpecialPoolTag;
	PFUNC<PVOID>  KernelVerifier;
	PFUNC<PVOID>  MmVerifierData;
	PFUNC<PVOID>  MmAllocateNonPagedPool;
	PFUNC<PVOID>  MmPeakCommitment;
	PFUNC<PVOID>  MmTotalCommitLimitMaximum;
	PFUNC<PVOID>  CmNtCSDVersion;
	PFUNC<PVOID>  MmPhysicalMemoryBlock;
	PFUNC<PVOID>  MmSessionBase;
	PFUNC<PVOID>  MmSessionSize;
	PFUNC<PVOID>  Unknown7;
} KD_DEBUGGER_DATA_BLOCK, *PKD_DEBUGGER_DATA_BLOCK;










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值