之前分析pchunter时的笔记,懒得整理了,凑合看
1.pchunter调试
IDA打开驱动文件
设置调试器
运行vmmon
启动vmware虚拟机系统,
运行调试器
com:pipe,resets=0,reconnect,port=\\.\pipe\kd_windows_7_x64,
com:pipe,resets=0,reconnect,port=\\.\pipe\kd_Windows_7_x64
prot值可以从vmmon处观察
其实都一样
.sympath srv*http://msdl.microsoft.com/download/symbols;D:\localsymbols
dt _driver_object 不好使先设置符号路径,仍然不好使用.reload命令重新加载符号
找到driverEntry的iocontrol例程,找到里面的call eax为处理某个功能号,在此处下断点, dd rbx,查看功能号,输入输出等。
驱动分析技巧:驱动就是主要根据结构特征来定位,driver_object device_object, 各种的device_extension可以参考ddk sample和reactos
功能号:0x13号为判断地址是否可写
功能号:31列出所有的模块名称
通过DirverObject找到 DriverSection, 枚举 KLDR_DATA_TABLE_ENTRY 中的 InLoadOrderLinks 双向链表,获取加载的模块名称
//
qword_FFFFF8800389E558 = (__int64)DriverObject;
WINDBG>dt _driver_object
nt!_DRIVER_OBJECT
+0x000 Type : Int2B
+0x002 Size : Int2B
+0x008 DeviceObject : Ptr64 _DEVICE_OBJECT
+0x010 Flags : Uint4B
+0x018 DriverStart : Ptr64 Void
+0x020 DriverSize : Uint4B
+0x028 DriverSection : Ptr64 Void
+0x030 DriverExtension : Ptr64 _DRIVER_EXTENSION
+0x038 DriverName : _UNICODE_STRING
+0x048 HardwareDatabase : Ptr64 _UNICODE_STRING
+0x050 FastIoDispatch : Ptr64 _FAST_IO_DISPATCH
+0x058 DriverInit : Ptr64 long
+0x060 DriverStartIo : Ptr64 void
+0x068 DriverUnload : Ptr64 void
+0x070 MajorFunction : [28] Ptr64 long
dt _device_object
v8 = qword_FFFFF8800389FF58; //driver_object dt _driver_object
if ( !qword_FFFFF8800389FF58 )
v8 = **(_QWORD **)(qword_FFFFF8800389E558 + 0x28);driver_section
DriverSection输出出来是以下结构体 // dt _LDR_DATA_TABLE_ENTRY
WINDBG>dt _LDR_DATA_TABLE_ENTRY
nt!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY
+0x010 InMemoryOrderLinks : _LIST_ENTRY
+0x020 InInitializationOrderLinks : _LIST_ENTRY
+0x030 DllBase : Ptr64 Void
+0x038 EntryPoint : Ptr64 Void
+0x040 SizeOfImage : Uint4B
+0x048 FullDllName : _UNICODE_STRING
+0x058 BaseDllName : _UNICODE_STRING
+0x068 Flags : Uint4B
+0x06c LoadCount : Uint2B
+0x06e TlsIndex : Uint2B
+0x070 HashLinks : _LIST_ENTRY
+0x070 SectionPointer : Ptr64 Void
+0x078 CheckSum : Uint4B
+0x080 TimeDateStamp : Uint4B
+0x080 LoadedImports : Ptr64 Void
+0x088 EntryPointActivationContext : Ptr64 _ACTIVATION_CONTEXT
+0x090 PatchInformation : Ptr64 Void
+0x098 ForwarderLinks : _LIST_ENTRY
+0x0a8 ServiceTagLinks : _LIST_ENTRY
+0x0b8 StaticLinks : _LIST_ENTRY
+0x0c8 ContextInformation : Ptr64 Void
+0x0d0 OriginalBase : Uint8B
+0x0d8 LoadTime : _LARGE_INTEGER
{
if ( v8 <= MmSystemRangeStart )
break;
++v11;
v10 = 0;
if ( v11 > 0x1000 || *(_QWORD *)(v8 + 0x30) == qword_FFFFF8800389E568 )
break;
v8 = *(_QWORD *)v8; //InLoadOrderLinks
}
//
WINDBG>dt _LDR_DATA_TABLE_ENTRY
nt!_LDR_DATA_TABLE_ENTRY
+0x000 InLoadOrderLinks : _LIST_ENTRY
+0x010 InMemoryOrderLinks : _LIST_ENTRY
+0x020 InInitializationOrderLinks : _LIST_ENTRY
+0x030 DllBase : Ptr64 Void
+0x038 EntryPoint : Ptr64 Void
+0x040 SizeOfImage : Uint4B
+0x048 FullDllName : _UNICODE_STRING
+0x058 BaseDllName : _UNICODE_STRING
+0x068 Flags : Uint4B
+0x06c LoadCount : Uint2B
+0x06e TlsIndex : Uint2B
+0x070 HashLinks : _LIST_ENTRY
+0x070 SectionPointer : Ptr64 Void
+0x078 CheckSum : Uint4B
+0x080 TimeDateStamp : Uint4B
+0x080 LoadedImports : Ptr64 Void
+0x088 EntryPointActivationContext : Ptr64 _ACTIVATION_CONTEXT
+0x090 PatchInformation : Ptr64 Void
+0x098 ForwarderLinks : _LIST_ENTRY
+0x0a8 ServiceTagLinks : _LIST_ENTRY
+0x0b8 StaticLinks : _LIST_ENTRY
+0x0c8 ContextInformation : Ptr64 Void
+0x0d0 OriginalBase : Uint8B
+0x0d8 LoadTime : _LARGE_INTEGER
v24 = *(_WORD *)(v8 + 0x48) & 0xFFFE;
memmove((void *)(v17 + 36), *(const void **)(v8 + 0x50), (unsigned int)v24);
//点击内核钩子,FSD
枚举下列模块,记录下他们的加载地址和镜像大小
单机键盘选项卡
读取原始函数地址
1.打开文件,读取文件
2.分配镜像大小,按内存展开
3.找到OEP,
4.在oep函数内存中通过特征码,找到irp处理函数的偏移。
//内核钩子选项卡下的内核钩子
从磁盘中读取文件
根据导出表来检查 钩子
根据区段来检查钩子 判断区段是否可读,0x20000020 is executalbe contains code
IDT hook
35号功能
KeGetProcessorNumberFromIndex
KeSetSystemGroupAffinityThread
dt _KPCR
dt _KPRCB
(GS:[0x20] is the "KPCR.CurrentPrcb" pointer
http://www.securiteam.com/securitynews/6U00D0AN5G.html
@0环的ETHREAD结构体是记录线程的相关信息,EPROCESS结构体是记录进程相关的信息,同样我们每个CPU也有一个结构体来记录每个CPU的状态这个结构体就是KPCR结构体KPCR结构体如下下面该结构体中几个主要的成员,
先KeStartDynamicProcessor 函数处开始,(rva = 0x4f6a70)从内存中搜索,搜索不到的话 通过kpcr来获取原函数地址,搜索的函数为sub_FFFFxxxxxx1e50()
278a48 ntoskernel的地址加上这个数,就是上面的v1
v1的指向的值加上6就是了
__int64 sub_1405A62E0() ntoskernel对处理器的处理
在KeStartDynamicProcessor函数中找到 v10 = sub_1401A0B10(v7, v6, v5, v9);
在sub_1401A0B10函数中找到
v7 = sub_1403FA9D0(&v33, &Dst, v8, v13, (unsigned __int16)v23, v4, dword_1402B10C0, SHIDWORD(v26), v14, v9, v10);
在sub_1403FA9D0中定位到1403FAA68
1403FAA68为找地址 278a48的关键点,该地址位于hal *__usercall sub_1403FA9D0函数处
读取sidt寄存器来获取中段处理历程,获取挂钩后的地址
pchunter的不一定准,它的结果和windbg !idt输出有不一致的地方,windbg能找到的 51号,在pci驱动中,pchunter找不到
内核选项卡
枚举过滤驱动的功能号45
枚举的驱动:
\FileSystem\RAW \Driver\KbdClass \Driver\i8042prt
\Driver\Tcpip \Driver\nsiproxy \Driver\tdx
\Driver\Mouclass \Driver\NDIS \Driver\PnpManager
ObReferenceObjectByName获取驱动对象,枚举device object 的attchached device,获取attached device的驱动对象名,设备名 和驱动路径
dt _DEVICE_OBJECT
dt _DRIVER_OBJECT
工作线程队列:
功能号:0xc3
在ntoskrnl中
rva 0x8cc01 ExQueueWorkItem
在函数中找道到rva 0x21D600,此处为ExWorkerQueue全局变量,枚举ExWorkerQueue可以得到工作线程队列,枚举WORK_QUEUE_ITEM
参考9.4 内核劳务线程 reactos http://book.51cto.com/art/200912/174648.htm,
ExWorkerQueue是全局数组
一共三类
typedef enum _WORK_QUEUE_TYPE {
CriticalWorkQueue,
DelayedWorkQueue,
HyperCriticalWorkQueue,
MaximumWorkQueue
} WORK_QUEUE_TYPE;
WINDBG>dt _KQUEUE 0xFFFFF80004076600
ntdll!_KQUEUE
+0x000 Header : _DISPATCHER_HEADER
+0x018 EntryListHead : _LIST_ENTRY [ 0xfffff800`04076618 - 0xfffff800`04076618 ]
+0x028 CurrentCount : 0
+0x02c MaximumCount : 1
+0x030 ThreadListHead : _LIST_ENTRY [ 0xfffffa80`018fd208 - 0xfffffa80`018fed28 ]
ThreadListHead 是这类劳务线程链表,nt!_KTHREAD.QueueListEntry的队列
!exqueue命令显示了关于工作队列和工作线程的详细信息。
hal回调:
haldispatch table:
功能号:0xf0
ntoskrnl.exe导出全局变量:HalDispatchTable
从此处HalDsipatchTable+8的地址处枚举0x15个地址
halPrivateDispathTable:
功能号0xf1:
ntoskrne.exe导出变量:HalPrivateDispatchTable:
从此处HalPrivateDispatchTable+8的地址处枚举0x2D个地址
halAcpiDispatchTable:
功能号0xf2:
找到HalInitializeProcessor函数的地址
在.data数据段搜索 特征码1212238880(48414C20h)
找到rva为0x254c0的全局变量
+8处开始计算地址
原函数地址处的也是从此处复制过去的。有什么用呢
wdf
wdf01000派发函数:
功能号:0xaf
当前函数地址通过driverobject获得 " \Driver\wdf01000"
原始函数地址通过,打开SystemRoot\System32\drivers\wdf01000.sys,通过oep查找原函数地址,
下图为ida反汇编wdf01000.sys入口点的部分截图
找到wdf中IRP_MJ_CREATE, IRP_MJ_CLEANUP, IRP_MJ_CLOSE,这几个派发函数位于wdf01000.sys中
找到rva 0x91148,,此rva后面后4个常量地址,这四个函数是干嘛的?
保存后面四个函数的特征码
派发函数好多在ntoskrnl中,派遣函数地址都是填的下面的地址
ntoskernel导出表中找到iocreatedriver,在该函数中找到rva0x661d4,该函数名称为IopInvalidDeviceRequest
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2019-4-24 11:00
被littlewisp编辑
,原因: