Sei sulla pagina 1di 7

How To Check Export Functions Of Windows 8 NT Kernel By Using Windbg

by cawan (cawan[at]ieee.org)

on 4/11/2012

In most of the time, PE viewer approach is the most well-known technique in listing the export functions from the export directory of PE file. For windows kernel, it is common to use those PE viewers to parse the header of ntoskrnl.exe or ntkrnlpa.exe in getting

the contents under export directory. However, it is really cumbersome when we designing the shellcode in windbg and keep switching to PE viewer to refer the export function list.

It is getting more annoying when the base address is ASLRed do everything in windbg, because we are lazy

So, we need to find a way

First of all, let us parse the PE header of the windows kernel from windbg.

kd> !dh /f nt

File Type: EXECUTABLE IMAGE FILE HEADER VALUES 14C machine (i386) 14 number of sections 5010ADF0 time date stamp Thu Jul 26 10:39:44 2012

0 file pointer to symbol table

0 number of symbols E0 size of optional header

122 characteristics Executable App can handle >2gb addresses 32 bit word machine

OPTIONAL HEADER VALUES 10B magic # 10.10 linker version 4B3E00 size of code

CE200 size of initialized data

2800

size of uninitialized data

221310

address of entry point

1000

base of code ----- new -----

00400000

image base

1000

section alignment

200

file alignment

1

subsystem (Native)

6.02

operating system version

6.02

image version

6.02

subsystem version

58E000 size of image

800

size of headers

550165

checksum

00040000

size of stack reserve

00002000

size of stack commit

00100000

size of heap reserve

00001000

size of heap commit

0

DLL characteristics

4BA000 [

134CA] address [size] of Export Directory

20B394 [

DC] address [size] of Import Directory

538000

[

31A50] address [size] of Resource Directory

0

[

0] address [size] of Exception Directory

54C200 [

20F0] address [size] of Security Directory

56A000 [

23A14] address [size] of Base Relocation Directory

1C4AA4 [

38] address [size] of Debug Directory

0

[

0] address [size] of Description Directory

0

[

0] address [size] of Special Directory

0

[

0] address [size] of Thread Storage Directory

14490 [

40] address [size] of Load Configuration Directory

0 [

20B000 [

0] address [size] of Bound Import Directory 394] address [size] of Import Address Table Directory

0

[

0] address [size] of Delay Import Directory

0

[

0] address [size] of COR20 Header Directory

0

[

0] address [size] of Reserved Directory

Well, the export directory is at 4ba000 and the size of this structure is 134ca. Let us check it further

kd> dd nt+4ba000

81327000

00000000 5010adf0 00000000 004bff76

81327010

00000001 00000989 00000987 004ba028

81327020

004bc64c 004bec68 0035e96d 000f7470

81327030

000bc0d2 000ba677 000b2047 000d4a00

81327040

0007b7fb 0007ba2e 000d6718 000d679f

81327050

000ba781 000cee95 00170874 00163eb9

81327060

001708c0 00170100 00163ea4 00163e8f

81327070

00163e71 0017011c 00163e5c 00170174

We need to get the list of export functions name, from PE specification, we have this structure.

public struct IMAGE_EXPORT_DIRECTORY

{

public UInt32 Characteristics; public UInt32 TimeDateStamp; public UInt16 MajorVersion; public UInt16 MinorVersion; public UInt32 Name; public UInt32 Base; public UInt32 NumberOfFunctions; public UInt32 NumberOfNames; public UInt32 AddressOfFunctions; public UInt32 AddressOfNames; public UInt32 AddressOfNameOrdinals;

}

So, from IMAGE_EXPORT_DIRECTORY structure, AddressOfNames at offset 0x20 (32 in decimal) has what we are looking for. Let us check address 0x004bc64c.

kd> dd nt+004bc64c 8132964c 004bff83 004bff95 004bffad 004bffcc 8132965c 004bffe0 004bfff3 004c0005 004c0012 8132966c 004c0031 004c003d 004c005b 004c0066 8132967c 004c0073 004c007f 004c008d 004c00a2 8132968c 004c00c6 004c00d3 004c00e2 004c00f2 8132969c 004c0104 004c0111 004c0123 004c0133 813296ac 004c014a 004c0169 004c018b 004c01a1 813296bc 004c01b7 004c01cc 004c01df 004c01f4

Those are pointers to the export functions name. Verify it.

kd> db nt+004bff83

8132cf83

41 6c 70 63 47 65 74 48-65 61 64 65 72 53 69 7a

AlpcGetHeaderSiz

8132cf93

65 00 41 6c 70 63 47 65-74 4d 65 73 73 61 67 65

e.AlpcGetMessage

8132cfa3

41 74 74 72 69 62 75 74-65 00 41 6c 70 63 49 6e

Attribute.AlpcIn

8132cfb3

69 74 69 61 6c 69 7a 65-4d 65 73 73 61 67 65 41

itializeMessageA

8132cfc3

74 74 72 69 62 75 74 65-00 42 67 6b 44 69 73 70

ttribute.BgkDisp

8132cfd3

6c 61 79 43 68 61 72 61-63 74 65 72 00 42 67 6b

layCharacter.Bgk

8132cfe3

47 65 74 43 6f 6e 73 6f-6c 65 53 74 61 74 65 00

GetConsoleState.

8132cff3

42 67 6b 47 65 74 43 75-72 73 6f 72 53 74 61 74

BgkGetCursorStat

There are a lot of strings starting from 004bff83. Check the first 2 items.

kd> da nt+004bff83 8132cf83 "AlpcGetHeaderSize" kd> da nt+004bff95 8132cf95 "AlpcGetMessageAttribute"

By referring the IMAGE_EXPORT_DIRECTORY structure again, the NumberOfNames at offset 0x18 shows the number of export functions in the nt kernel. So, there are 987 export functions in the nt kernel. We can write a script to dump all the exported functions now.

Kd> r $t1=(nt+4bc64c); .for (r $t0=0; @$t0<987; r $t0=@$t0+1) {da poi(@$t1)+nt l20; r $t1=@$t1+4}

8132cf83 "AlpcGetHeaderSize" 8132cf95 "AlpcGetMessageAttribute" 8132cfad "AlpcInitializeMessageAttribute" 8132cfcc "BgkDisplayCharacter" 8132cfe0 "BgkGetConsoleState" 8132cff3 "BgkGetCursorState" 8132d005 "BgkSetCursor" 8132d012 "CcAddDirtyPagesToExternalCache" 8132d031 "CcCanIWrite" 8132d03d "CcCoherencyFlushAndPurgeCache" 8132d05b "CcCopyRead" 8132d066 "CcCopyReadEx" 8132d073 "CcCopyWrite" 8132d07f "CcCopyWriteEx" 8132d08d "CcCopyWriteWontFlush" 8132d0a2 "CcDeductDirtyPagesFromExternalCa" 8132d0c6 "CcDeferWrite" 8132d0d3 "CcFastCopyRead" 8132d0e2 "CcFastCopyWrite" 8132d0f2 "CcFastMdlReadWait" 8132d104 "CcFlushCache" 8132d111 "CcFlushCacheToLsn" 8132d123 "CcGetDirtyPages" 8132d133 "CcGetFileObjectFromBcb" 8132d14a "CcGetFileObjectFromSectionPtrs" 8132d169 "CcGetFileObjectFromSectionPtrsRe" 8132d18b "CcGetFlushedValidData" 8132d1a1 "CcGetLsnForFileObject" 8132d1b7 "CcInitializeCacheMap" 8132d1cc "CcIsThereDirtyData" 8132d1df "CcIsThereDirtyDataEx" 8132d1f4 "CcIsThereDirtyLoggedPages" 8132d20e "CcMapData" 8132d218 "CcMdlRead" 8132d222 "CcMdlReadComplete" 8132d234 "CcMdlWriteAbort" 8132d244 "CcMdlWriteComplete" 8132d257 "CcPinMappedData" 8132d267 "CcPinRead" 8132d271 "CcPrepareMdlWrite" 8132d283 "CcPreparePinWrite" 8132d295 "CcPurgeCacheSection" 8132d2a9 "CcRegisterExternalCache" 8132d2c1 "CcRemapBcb" 8132d2cc "CcRepinBcb" 8132d2d7 "CcScheduleReadAhead"

8132d2eb "CcScheduleReadAheadEx"

How about if we need to know that an function name is included in the export functions list or not ? Simple, let's say we need to know HalDispatchTable is in the export functions list or not

kd> .shell -ci "r $t1=(nt+4bc64c); .for (r $t0=0; @$t0<987; r $t0=@$t0+1) {da poi(@$t1)+nt l20; r $t1=@$t1+4}" find /I "haldispatchtable"

8132fed0 "HalDispatchTable" .shell: Process exited

Yes, it is included. How about we want to dump the list of native api of windows 8 ? Simple.

kd> .shell -ci "r $t1=(nt+4bc64c); .for (r $t0=0; @$t0<987; r $t0=@$t0+1) {da poi(@$t1)+nt l20; r $t1=@$t1+4}" find /I "zw"

81338eac "ZwAccessCheckAndAuditAlarm" 81338ec7 "ZwAddBootEntry" 81338ed6 "ZwAddDriverEntry" 81338ee7 "ZwAdjustPrivilegesToken" 81338eff "ZwAlertThread" 81338f0d "ZwAllocateLocallyUniqueId" 81338f27 "ZwAllocateVirtualMemory" 81338f3f "ZwAlpcAcceptConnectPort" 81338f57 "ZwAlpcCancelMessage" 81338f6b "ZwAlpcConnectPort" 81338f7d "ZwAlpcConnectPortEx" 81338f91 "ZwAlpcCreatePort" 81338fa2 "ZwAlpcCreatePortSection" 81338fba "ZwAlpcCreateResourceReserve"

81338fd6 "ZwAlpcCreateSectionView" 81338fee "ZwAlpcCreateSecurityContext" 8133900a "ZwAlpcDeletePortSection"

81339022 "ZwAlpcDeleteResourceReserve"

8133903e "ZwAlpcDeleteSectionView"

81339056

"ZwAlpcDeleteSecurityContext"

81339072

"ZwAlpcDisconnectPort"

81339087

"ZwAlpcQueryInformation"

8133909e "ZwAlpcSendWaitReceivePort" 813390b8 "ZwAlpcSetInformation" 813390cd "ZwAssignProcessToJobObject" 813390e8 "ZwCancelIoFile" 813390f7 "ZwCancelTimer"

81339105

"ZwClearEvent"

81339112

"ZwClose"

8133911a "ZwCloseObjectAuditAlarm"

81339132

"ZwCommitComplete"

81339143

"ZwCommitEnlistment"

81339156

"ZwCommitTransaction"

8133916a "ZwConnectPort"

81339178

"ZwCreateDirectoryObject"

81339190

"ZwCreateEnlistment"

813391a3 "ZwCreateEvent" 813391b1 "ZwCreateFile"

813391be "ZwCreateIoCompletion" 813391d3 "ZwCreateJobObject" 813391e5 "ZwCreateKey" 813391f1 "ZwCreateKeyTransacted"

81339207 "ZwCreateResourceManager"

8133921f "ZwCreateSection"

8133922f "ZwCreateSymbolicLinkObject" 8133924a "ZwCreateTimer"

81339258 "ZwCreateTransaction"

8133926c "ZwCreateTransactionManager"

81339287 "ZwCreateWnfStateName"

8133929c "ZwDeleteBootEntry" 813392ae "ZwDeleteDriverEntry" 813392c2 "ZwDeleteFile" 813392cf "ZwDeleteKey" 813392db "ZwDeleteValueKey"

813392ec "ZwDeleteWnfStateData"

81339301

"ZwDeleteWnfStateName"

81339316

"ZwDeviceIoControlFile"

8133932c "ZwDisplayString" 8133933c "ZwDuplicateObject" 8133934e "ZwDuplicateToken"

8133935f "ZwEnumerateBootEntries"

81339376 "ZwEnumerateDriverEntries"

8133938f "ZwEnumerateKey"

8133939e "ZwEnumerateTransactionObject" 813393bb "ZwEnumerateValueKey" 813393cf "ZwFlushBuffersFile" 813393e2 "ZwFlushBuffersFileEx" 813393f7 "ZwFlushInstructionCache" 8133940f "ZwFlushKey" 8133941a "ZwFlushVirtualMemory" 8133942f "ZwFreeVirtualMemory"

81339443

"ZwFsControlFile"

81339453

"ZwGetNotificationResourceManager"

81339474

"ZwImpersonateAnonymousToken"

81339490

"ZwInitiatePowerAction"

813394a6 "ZwIsProcessInJob" 813394b7 "ZwLoadDriver" 813394c4 "ZwLoadKey" 813394ce "ZwLoadKeyEx" 813394da "ZwLockFile"

813394e5 "ZwLockProductActivationKeys"

81339501

"ZwMakeTemporaryObject"

81339517

"ZwMapViewOfSection"

8133952a "ZwModifyBootEntry" 8133953c "ZwModifyDriverEntry"

81339550

"ZwNotifyChangeKey"

81339562

"ZwNotifyChangeSession"

81339578

"ZwOpenDirectoryObject"

8133958e "ZwOpenEnlistment" 8133959f "ZwOpenEvent" 813395ab "ZwOpenFile" 813395b6 "ZwOpenJobObject" 813395c6 "ZwOpenKey" 813395d0 "ZwOpenKeyEx" 813395dc "ZwOpenKeyTransacted"

813395f0 "ZwOpenKeyTransactedEx"

81339606

"ZwOpenProcess"

81339614

"ZwOpenProcessToken"

81339627

"ZwOpenProcessTokenEx"

8133963c "ZwOpenResourceManager"

81339652

"ZwOpenSection"

81339660

"ZwOpenSession"

8133966e "ZwOpenSymbolicLinkObject"

81339687

"ZwOpenThread"

81339694

"ZwOpenThreadToken"

813396a6 "ZwOpenThreadTokenEx"

813396ba "ZwOpenTimer" 813396c6 "ZwOpenTransaction"

813396d8 "ZwOpenTransactionManager" 813396f1 "ZwPowerInformation"

81339704

"ZwPrePrepareComplete"

81339719

"ZwPrePrepareEnlistment"

81339730

"ZwPrepareComplete"

81339742

"ZwPrepareEnlistment"

81339756

"ZwPropagationComplete"

8133976c "ZwPropagationFailed"

81339780 "ZwPulseEvent"

8133978d "ZwQueryBootEntryOrder"

813397a3 "ZwQueryBootOptions" 813397b6 "ZwQueryDefaultLocale" 813397cb "ZwQueryDefaultUILanguage" 813397e4 "ZwQueryDirectoryFile" 813397f9 "ZwQueryDirectoryObject"

81339810

"ZwQueryDriverEntryOrder"

81339828

"ZwQueryEaFile"

81339836

"ZwQueryFullAttributesFile"

81339850

"ZwQueryInformationEnlistment"

8133986d "ZwQueryInformationFile"

81339884 "ZwQueryInformationJobObject"

813398a0 "ZwQueryInformationProcess"

813398ba "ZwQueryInformationResourceManage" 813398dc "ZwQueryInformationThread" 813398f5 "ZwQueryInformationToken" 8133990d "ZwQueryInformationTransaction" 8133992b "ZwQueryInformationTransactionMan"

81339950

"ZwQueryInstallUILanguage"

81339969

"ZwQueryKey"

81339974

"ZwQueryLicenseValue"

81339988

"ZwQueryObject"

81339996

"ZwQueryQuotaInformationFile"

813399b2 "ZwQuerySection" 813399c1 "ZwQuerySecurityAttributesToken" 813399e0 "ZwQuerySecurityObject" 813399f6 "ZwQuerySymbolicLinkObject" 81339a10 "ZwQuerySystemEnvironmentValueEx" 81339a30 "ZwQuerySystemInformation" 81339a49 "ZwQueryValueKey" 81339a59 "ZwQueryVirtualMemory" 81339a6e "ZwQueryVolumeInformationFile" 81339a8b "ZwQueryWnfStateData" 81339a9f "ZwQueryWnfStateNameInformation" 81339abe "ZwReadFile" 81339ac9 "ZwReadOnlyEnlistment"

81339ade "ZwRecoverEnlistment" 81339af2 "ZwRecoverResourceManager" 81339b0b "ZwRecoverTransactionManager" 81339b27 "ZwRemoveIoCompletion" 81339b3c "ZwRemoveIoCompletionEx" 81339b53 "ZwRenameKey" 81339b5f "ZwReplaceKey" 81339b6c "ZwRequestPort" 81339b7a "ZwRequestWaitReplyPort" 81339b91 "ZwResetEvent" 81339b9e "ZwRestoreKey" 81339bab "ZwRollbackComplete" 81339bbe "ZwRollbackEnlistment" 81339bd3 "ZwRollbackTransaction" 81339be9 "ZwSaveKey" 81339bf3 "ZwSaveKeyEx"

81339bff "ZwSecureConnectPort" 81339c13 "ZwSetBootEntryOrder" 81339c27 "ZwSetBootOptions" 81339c38 "ZwSetCachedSigningLevel" 81339c50 "ZwSetDefaultLocale" 81339c63 "ZwSetDefaultUILanguage" 81339c7a "ZwSetDriverEntryOrder" 81339c90 "ZwSetEaFile" 81339c9c "ZwSetEvent" 81339ca7 "ZwSetInformationEnlistment" 81339cc2 "ZwSetInformationFile" 81339cd7 "ZwSetInformationJobObject" 81339cf1 "ZwSetInformationKey" 81339d05 "ZwSetInformationObject" 81339d1c "ZwSetInformationProcess" 81339d34 "ZwSetInformationResourceManager" 81339d54 "ZwSetInformationThread" 81339d6b "ZwSetInformationToken" 81339d81 "ZwSetInformationTransaction" 81339d9d "ZwSetInformationVirtualMemory" 81339dbb "ZwSetQuotaInformationFile" 81339dd5 "ZwSetSecurityObject" 81339de9 "ZwSetSystemEnvironmentValueEx" 81339e07 "ZwSetSystemInformation" 81339e1e "ZwSetSystemTime" 81339e2e "ZwSetTimer" 81339e39 "ZwSetTimerEx" 81339e46 "ZwSetValueKey" 81339e54 "ZwSetVolumeInformationFile" 81339e6f "ZwTerminateJobObject" 81339e84 "ZwTerminateProcess" 81339e97 "ZwTraceEvent" 81339ea4 "ZwTranslateFilePath" 81339eb8 "ZwUnloadDriver" 81339ec7 "ZwUnloadKey" 81339ed3 "ZwUnloadKeyEx" 81339ee1 "ZwUnlockFile" 81339eee "ZwUnlockVirtualMemory" 81339f04 "ZwUnmapViewOfSection" 81339f19 "ZwUpdateWnfStateData" 81339f2e "ZwWaitForMultipleObjects" 81339f47 "ZwWaitForSingleObject" 81339f5d "ZwWriteFile" 81339f69 "ZwYieldExecution" .shell: Process exited

Yes, we get the complete list. This technique is really helpful when I did memory analysis of kernel pool to build a kernel shellcode testing platform in windbg.