64 SSDTHOOKに勝つ



Win 64 Ssdt Hook



次のコンテンツは、ハッカー防衛線2012小冊子の294ページを参照しています。

実際、コード上で直接言うことは何もありません。



ssdtの構造はwin32の構造と似ていますが、ここでのポインタタイプをULONGに置き換えることはできないことに注意してください。 ULONGLONGを交換したい場合、理由は記載されていません。

//SSDT structure typedef struct _SystemServiceDescriptorTable { PVOID ServiceTableBase PVOID ServiceCounterTableBase ULONGLONG NumberOfService PVOID ParamTableBase }SystemServiceTable, *PSystemServiceTable PSystemServiceTable KeServiceDescriptorTable

上記の構造のアドレスのコードを取得します



ULONGLONG GetKeSeviceDescriptorTable64() { /* The idea is to read the value of 0xC0000082, which is the address of the KiSystemCall64 function, and then search through the signature. The ssdt signature is 0x4c8d15 and then the offset of the address value of ssdt, and then through the formula: Real address = current address + current instruction length + offset Get ssdt address Looking for a shadow ssdt address is similar */ PUCHAR startSearchAddress = (PUCHAR)__readmsr(0xC0000082) PUCHAR endSearchAddress = startSearchAddress + 0x500 PUCHAR i = 0 UCHAR b1 = 0, b2 = 0, b3 = 0 ULONG temp = 0 ULONGLONG addr = 0 for ( i = startSearchAddress i ) { if (MmIsAddressValid(i) && MmIsAddressValid(i + 1) && MmIsAddressValid(i + 2)) { b1 = *i b2 = *(i + 1) b3 = *(i + 2) if (b1 == 0x4c && b2 == 0x8d && b3 == 0x15) { memcpy(&temp, i + 3, 4) addr = (ULONGLONG)temp + (ULONGLONG)i + 7//Plus instruction length KdPrint(('find ssdt is %p
', addr)) return addr } } } KdPrint(('find ssdt error
')) return 0 }

すべてのネイティブAPIアドレスをトラバースします。

void througnAllServiceFuncAddr() { ULONG dwTemp = 0 PULONG ServiceTableBase = 0 ULONG i = 0 for ( i = 0 i NumberOfService i++) { if (MmIsAddressValid(KeServiceDescriptorTable->ServiceTableBase)) { ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase dwTemp = ServiceTableBase[i] dwTemp = dwTemp >> 4 DbgPrint('the %dth func addr is %p!
', i, ((ULONGLONG)dwTemp + (ULONGLONG)ServiceTableBase) & 0xffffffff0fffffff) } else { DbgPrint('ServiceTableBase is fault!
') return 0 } } }

試験結果:



Windbgビューの結果:

例としてZwOpenProcessを取り上げます。

Idaは、彼のIDが0x23、つまり35であることを発見しました。対応するテスト結果はfffff8000419b038です。

Windbgの結果:

テストは正しいです。

ただし、フックする場合は、win32よりもはるかに厄介です。ServiceTableBase配列の要素は4バイトしかないため、win32の下のメモリ空間全体を自然にトラバースできます。
ただし、win64では、メモリスペースは16T(44ビットアドレス指定に制限)です。 1つの4GBスペースを完全に占有できますが、使用するスペースはまだたくさんあります。したがって、このインデックスを直接変更してください。

ドライバ関数アドレスに到達できません。したがって、システムntモジュール内のこのスプリングボード関数のアドレスであるスプリングボード関数(4GBの範囲内)にジャンプして、その関数を変更できます。

最初のアドレスはjmpです。私たちのドライバーフック関数はフックを実装することができます。

たとえば、KeBugCheckEx関数を使用すると、この関数の関数はシステムがハングしたときに呼び出される関数であるため、他のアイドル状態が見つかった場合はもちろん、踏み台として使用できます。

メモリスペースは、踏み台としても使用できます。

アイデアを整理し、以下のコードを貼り付けます。

ssdtフックのプロセス:
1.最初にGetKeSeviceDescriptorTable64を呼び出して、KeServiceDescriptorTableグローバル変数に値を割り当てます。
ssdt
2. GetSSDTFuncAddrByIdを呼び出して、ターゲット関数アドレスを取得し、それをグローバル変数real_NtTerminateProcessに保存します。
3.関数Fuck_KeBugCheckExの踏み台としてKeBugCheckExコードの最初の12バイトを変更します
4.ターゲット関数のオフセットを取得し、グローバル変数real_NtTerminateProcessOffsetに保存します
5. KeBugCheckEx関数のオフセットを計算し、それをssdtテーブルに書き込みます

フックを復元します。
1.保存したターゲット関数のオフセットをssdtテーブルに直接書き込みます。
KeBugCheckEx関数はここでは実行されないため、ここで復元する必要はありません。実行すると、ブルースクリーンもクラッシュします。

KIRQL WPOFFx64() //Similar to win32 off memory write protection { KIRQL irql = KeRaiseIrqlToDpcLevel() UINT64 cr0 = __readcr0() cr0 &= 0xfffffffffffeffff __writecr0(cr0) _disable() return irql } void WPONx64(KIRQL irql)//Similar to win32 to enable memory write protection = 0x10000 _enable() __writecr0(cr0) KeLowerIrql(irql) ULONGLONG GetSSDTFuncAddrById(ULONG id) { ULONG dwTemp = 0 PULONG ServiceTableBase = 0 if (MmIsAddressValid(KeServiceDescriptorTable->ServiceTableBase)) { ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase dwTemp = ServiceTableBase[id] dwTemp = dwTemp >> 4 //return ((ULONGLONG)dwTemp + (ULONGLONG)ServiceTableBase) & 0xffffffff0fffffff return ((ULONGLONG)dwTemp + (ULONGLONG)ServiceTableBase) } else { DbgPrint('ServiceTableBase is fault!
') return 0 } } ULONG GetOffsetBySSDTFuncAddress(ULONGLONG funcAddr) { ULONG dwtemp = 0 PULONG ServiceTableBase = 0 ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase dwtemp = (ULONG)(funcAddr - (ULONGLONG)ServiceTableBase) return dwtemp << 4 } NTSTATUS __fastcall Fuck_NtTerminateProcess( IN HANDLE ProcessHandle, IN NTSTATUS ExitStatus ) { PEPROCESS pe NTSTATUS status status = ObReferenceObjectByHandle(ProcessHandle, 0, *PsProcessType, KernelMode, &pe, 0) DbgPrint('enter Fuck_NtTerminateProcess!!!
') if (!NT_SUCCESS(status)) { DbgPrint('ObReferenceObjectByHandle failed !!!
') return real_NtTerminateProcess(ProcessHandle, ExitStatus) } if (!_stricmp(PsGetProcessImageFileName(pe),'calc.exe')) { return STATUS_ACCESS_DENIED } return real_NtTerminateProcess(ProcessHandle, ExitStatus) } void Fuck_KeBugCheckEx() { KIRQL irql ULONGLONG myFunc = (ULONGLONG)Fuck_NtTerminateProcess UCHAR jmp_code[] = 'x48xB8xFFxFFxFFxFFxFFxFFxFFx00xFFxE0' memcpy(jmp_code + 2, &myFunc, 8) irql = WPOFFx64() memset(KeBugCheckEx, 0x90, 15)//Fill 15 nop memcpy(KeBugCheckEx, jmp_code, 12) WPONx64(irql) } void hookSSDT64() { ULONGLONG dwtemp = 0 PULONG ServiceTableBase = 0 KIRQL irql //UNICODE_STRING funcName //RtlInitUnicodeString(&funcName, L'NtTerminateProcess') real_NtTerminateProcess = GetSSDTFuncAddrById(NtTerminateProcessId) //2 DbgPrint('real_NtTerminateProcess is %p
', real_NtTerminateProcess) //DbgPrint('search real_NtTerminateProcess is %p
', MmGetSystemRoutineAddress(&funcName)) Fuck_KeBugCheckEx() //3 ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase real_NtTerminateProcessOffset = ServiceTableBase[NtTerminateProcessId]//4 //Hook 5 irql = WPOFFx64() ServiceTableBase[NtTerminateProcessId] = GetOffsetBySSDTFuncAddress((ULONGLONG)KeBugCheckEx) WPONx64(irql) DbgPrint('KeBugCheckEx: %p
', (ULONGLONG)KeBugCheckEx) DbgPrint('NtTerminateProcess: %p
', GetSSDTFuncAddrById(NtTerminateProcessId)) } void unHookSSDT64() { KIRQL irql ULONGLONG dwtemp = 0 PULONG ServiceTableBase = 0 DbgPrint('enter unHookSSDT64
 ') ServiceTableBase = (PULONG)KeServiceDescriptorTable->ServiceTableBase irql = WPOFFx64() ServiceTableBase[NtTerminateProcessId] = real_NtTerminateProcessOffset WPONx64(irql) DbgPrint('KeBugCheckEx: %p
', (ULONGLONG)KeBugCheckEx) DbgPrint('NtTerminateProcess: %p
', GetSSDTFuncAddrById(NtTerminateProcessId)) }

転載:https://www.cnblogs.com/freesec/p/7617752.html