-
-
[原创]遍历内核中的DpcTimer
-
发表于:
2012-3-20 11:17
30257
-
typedef struct _KTIMER {
DISPATCHER_HEADER Header;
ULARGE_INTEGER DueTime; //+0x10
LIST_ENTRY TimerListEntry;
PKDPC Dpc; //+0x20
LONG Period; //+0x24
} KTIMER, *PKTIMER, *PRKTIMER;
// 取KeUpdateSystemTime地址
RtlInitUnicodeString(&destString,(PWCHAR)L"KeUpdateSystemTime");
Address = (ULONG)MmGetSystemRoutineAddress(&destString);
if (Address == 0) return 0;
// 反汇编找到C_LEA<就是 lea 指令>首次出现的地址
Address = DisAsmFindFirstSpecialInstructionAddress(Address, C_LEA);
if ( Address == 0 ) return 0;
if ( *(PUSHORT)Address != 0x0C8D ) return 0;
Address = *(PULONG)(Address + 3);
if ( MmIsAddressValidEx((PVOID)Address) == VCS_INVALID ) return 0;
ULONG DisAsmFindFirstSpecialInstructionAddress(ULONG BeginAddress, ULONG CmdType)
{
ULONG DecodedLength = 0;
ULONG dw = 0;
ULONG Address = 0;
Disasm dis;
while (TRUE)
{
if ( MmIsAddressValidEx((PVOID)(BeginAddress + DecodedLength)) == VCS_INVALID ) return 0;
dw = DisasmCode((PUCHAR)(BeginAddress + DecodedLength),36,&dis);
DecodedLength = DecodedLength + dw;
if ( dis.cmdtype != CmdType ) continue;
Address = BeginAddress + DecodedLength - dw; //返回指令地址 此时指向指令
break;
}
if ( MmIsAddressValidEx((PVOID)Address) == VCS_INVALID ) Address = 0;
return Address;
}
//自定义的回传DPC TIMER结构
typedef struct _MyDpcTimer{
ULONG TimerAddress; //KTIMER结构地址
ULONG Period; //循环间隔
ULONG DpcAddress; //DPC结构地址
ULONG DpcRoutineAddress; //例程地址
}MyDpcTimer,*PMyDpcTimer;
#define MAX_DPCTIMER_COUNT 250
#pragma PAGECODE
static ULONG GetDpcTimerInformation_XP(PVOID* pvBuf)
{
ULONG NumberOfTimerTable;
ULONG i;
ULONG ulCount = 0;
PLIST_ENTRY pList = NULL;
PLIST_ENTRY pNextList = NULL;
MyDpcTimer MyDpc;
PKDPCTIMER pTimer = NULL;
NumberOfTimerTable = 0x100; //_KTIMER_TABLE_ENTRY数量
pList = (PLIST_ENTRY)GetDpcTimerListHeadForXp_2K3(); //取得链表头
if (pList == NULL) return 0;
*pvBuf = CallExAllocatePoolWithTag(PagedPool,MAX_DPCTIMER_COUNT*sizeof(MyDpcTimer),652); //分配足够大的缓冲
if (*pvBuf == NULL) return 0;
RtlZeroMemory(*pvBuf,MAX_DPCTIMER_COUNT*sizeof(MyDpcTimer));
for ( i = 0; i < NumberOfTimerTable; i++, pList++ ) //NumberOfTimerTable 个list
{
if ( MmIsAddressValidEx((PVOID)&pList) == VCS_INVALID ) goto __exit1;
if ( MmIsAddressValidEx((PVOID)pList->Blink) == VCS_INVALID ) continue; //如果listentry域地址无效,continue
if ( MmIsAddressValidEx((PVOID)pList->Flink) == VCS_INVALID ) continue;
for ( pNextList = pList->Blink; pNextList != pList; pNextList = pNextList->Blink ) //遍历blink链
{
pTimer = CONTAINING_RECORD(pNextList,KDPCTIMER,TimerListEntry); //得到结构首
if ( MmIsAddressValid((PVOID)pTimer) &&
MmIsAddressValid((PVOID)pTimer->Dpc) &&
MmIsAddressValid((PVOID)pTimer->Dpc->DeferredRoutine) &&
MmIsAddressValid((PVOID)&pTimer->Period) ) //过滤
{
RtlZeroMemory(&MyDpc,sizeof(MyDpcTimer)); //准备更新结构信息
if ( !MmIsAddressValid((PVOID)pTimer) ) break;
MyDpc.TimerAddress = (ULONG)pTimer;
if ( !MmIsAddressValid((PVOID)pTimer->Dpc) ) break;
MyDpc.DpcAddress = (ULONG)pTimer->Dpc;
if ( !MmIsAddressValid((PVOID)pTimer->Dpc->DeferredRoutine) ) break;
MyDpc.DpcRoutineAddress = (ULONG)pTimer->Dpc->DeferredRoutine;
if ( !MmIsAddressValid((PVOID)&pTimer->Period) ) break;
MyDpc.Period = pTimer->Period;
RtlMoveMemory( (PVOID)((ULONG)*pvBuf+ulCount*sizeof(MyDpcTimer)),&MyDpc,sizeof(MyDpcTimer) );
ulCount++;
// 简单退出了,需要更改为重新分配更大的缓冲
if (ulCount >= MAX_DPCTIMER_COUNT) goto __exit1;
}
if ( !MmIsAddressValid(pNextList->Blink) ) break; //过滤
}// end for
}//end for
return ulCount * sizeof(MyDpcTimer);
__exit1:
if (*pvBuf != NULL) ExFreePool(*pvBuf);
*pvBuf = NULL;
return 0;
}
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)