概述
用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;
最后
以上就是愤怒老师为你收集整理的drv experiment : 从内核API代码定位函数地址或结构指针地址的全部内容,希望文章能够帮你解决drv experiment : 从内核API代码定位函数地址或结构指针地址所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复