ASLR

•Ноябрь 7, 2009 • Комментарии (3)

Краткая справка. Механизм ASLR – Address Space Layout Randomization (случайное расположение в адресном пространстве) появился впервые в XP и затрагивал PEB и TEB only. Начиная с Vista сабж уже стал применяться к базам загрузки исполняемых файлов и длл (в частности системных  ntdll, kernel32 etc), а также к стеку и куче. Для XP можно было для получения такой возможности юзать какой-нибуть аналог линуксового PaX под винду (BufferShield, например).

ASLR разрабатывался как средство для предотвращения атак типа ret-to-libc (адрес искомой функции при рандомной базе загрузки либы становится трудновычислим).

Довелось столкнуться с сабжем и заинтересовало как оно работает.

Как оказалось, выбор базы загрузки exe происходит следующим образом (ring0)

NtCreateSection ->  MmCreateSection -> MiRelocateImage (MiRelocateImageAgain) -> MiSelectImageBase

Основная работа по выбору базы загрузки проводится в функции MiSelectImageBase. В зависимости от того с чем имеем дело, с dll или с exe имеем разный алгоритм.  «Случайность» для базы во втором случае достигается путем использования rdtsc. Для dll при вычилениях используется переменная MiImageBias (причем при ее инициализации в функции (MiInitSystem->)MiInitializeRelocations тоже юзается rdtsc)

Чтобы мне не повторяться, псевдокод функции MiSelectImageBase можно посмотреть в статье  (как оказалось, сабж полностью расковыряли до меня) Bypassing Browser Memory Protections

http://taossa.com/archive/bh08sotirovdowd.pdf

В ней кстати не только про ASLR (дока описывает также механизмы GS, SafeSEH и DEP).

RIP-relative addressing

•Сентябрь 27, 2009 • 1 комментарий

заметка  proc

Продолжаю писать про особенности 64-битного режима.
На этот раз, речь пойдет об относительной адресации и соответственно, специфики работы с всяческими неэкспортируемыми символами в ядре. Итак,

RIP-relative addressing

Адрес формируется путем прибавления смещения к адресу следующей инструкции. Пример.
Секция .data ntoskrnl, переменная PsInvertedFunctionTable.

.data:00000000005748B0 PsInvertedFunctionTable dd 0

Берем какую-нибудь функцию, в которой есть ссылки на искомую переменную. Пусть это будет RtlInsertInvertedFunctionTable.

.text:0000000000417CB0 mov [rsp+arg_0], rcx
.text:0000000000417CB5 sub rsp, 48h
.text:0000000000417CB9 mov ecx, cs:PsInvertedFunctionTable
.text:0000000000417CBF mov [rsp+48h+var_10], rsi

Однако, как раньше мы не можем взять адрес переменной из инструкции mov ecx (как это было на x86). У нас есть только 32-х битное смещение данной переменной относительно следующей за mov ecx инструкции.
Значит, чтобы получить нужный нам адрес

PsInvertedFunctionTableAddress = 0000000000417CBF (адрес следующей инструкции) + 0×15CBF1

0×15CBF1 – есть смещение (опкод mov ecx,смещение – 8B 0D F1 CB 15 00)

Получаем 00000000005748B0 – адрес PsInvertedFunctionTable.

заметка endp

Инструкция inc reg в 64-битном режиме

•Сентябрь 25, 2009 • Комментарии (2)

Доступен only 2-х байтовый вариант, однобайтовая недоступна (в compatibility mode доступна).

Example

Instruction     | Opcode
______________________
inc cl             | FE C1

inc cx            | 66 FF C1

inc ecx          | FF C1

inc rcx          | 48 FF C1

Подробнее следует сказать о REX – префиксах (в варианте с rcx юзается)

Но сначала о формате команды, чтобы знать где префикс REX располагается. Значит инструкция может быть от 1 до 15 байт

Состоит из следующих полей (от старшего к младшему)

  • Legacy Prefix
  • REX Prefix
  • Opcode (1-2 байта)
  • ModRM
  • SIB
  • Смещение (1,2,4 или 8 байт)
  • Непосредственный операнд (1,2,4 или 8 байт)

REX – префиксы (40h-4fh). Они позволяют

  1. использовать дополнительные регистры общего назначения (GPR) r8-r15 и xmm регистры (xmm8-xmm15).
  2. использовать 64-битный размер операнда
  3. позволяют использовать cr8-cr15 регистры и dr8-dr15

Формат REX префикса
Название биты значение/описание

  • - 7-4 0100
  • REX.W 3 Размер операнда (0 – по умолчанию, 1 – 64 бита)
  • REX.R 2 Старший бит поля reg байта режима адресации (он же ModRM), позволяет  использовать 16 регистров (поле reg – 3 байта + 1 байт, 4 байта => 16 регистров)
  • REX.X 1 расширение поля index байта SIB (если без аббревиатуры и по русски – байт масштаба, индекса и базы) -старший бит, также для того, чтобы можно было юзать 16 регистров
  • REX.B 0 старший бит поля r/m байта ModRM, SIB.base или поля reg опкода – для доступа к 16-ти регистрам

Хм, ну после того, как становиться известен диапазон rex префиксов – очевидно почему нельзя использовать однобайтовые inc ;)
Подробнее об этом обо всем в AMD64 Programmer’s Manual, Volume 3: General-Purpose and System Instructions

VMWare WinXP 64

•Сентябрь 11, 2009 • 1 комментарий

Конкретно при работе с WinXP 64-bit под VmWare 6 [64 битная винда запускается из-под 32-битной] был обнаружен такой баг. Можно вызвать с помощью инструкции int с третьего кольца те обработчики прерываний, которые не под vmware не вызвать таким способом (dpl = 0). Например int 13h – вызов из юзермода. Итог – бсод.

DEFAULT_BUCKET_ID:  DRIVER_FAULT

PROCESS_NAME:  1.exe

CURRENT_IRQL:  0

LAST_CONTROL_TRANSFER:  from fffff8000102e5b4 to fffff8000102e890

STACK_TEXT: 
fffffadf`f54f8ae8 fffff800`0102e5b4 : 00000000`0000007f 00000000`00000009 00000000`80050031 00000000`000006f8 : nt!KeBugCheckEx
fffffadf`f54f8af0 fffff800`0102dd05 : fffffadf`ff94f4b0 00000000`00000000 00000000`00000001 00000000`00000000 : nt!KiBugCheckDispatch+0×74
fffffadf`f54f8c70 00000000`01001002 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiXmmException+0×145
00000000`0012ff78 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0×1001002

STACK_COMMAND:  kb

FOLLOWUP_IP:
nt!KiXmmException+145
fffff800`0102dd05 90              nop

SYMBOL_STACK_INDEX:  2

SYMBOL_NAME:  nt!KiXmmException+145 

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: nt

int 2d. KiDebugServiceTrap

•Сентябрь 8, 2009 • Добавить комментарий

int 2d. KiDebugServiceTrap [x64]. Раньше [в 32-битной винде]  мы могли вызывать int 2d – KiDebugService и выводить отладочную строку. Теперь мы тем же int 2d можем вызвать исключение EXCEPTION_BREAKPOINT.

Ниже код сабжевого обработчика.

.text:0000000000440C00 KiDebugServiceTrap proc near            ; DATA XREF: SepAdtInitializePrivilegeAuditing+10928o
.text:0000000000440C00

[...skipped...]

.text:0000000000440C62                 cld
.text:0000000000440C63                 stmxcsr dword ptr [rbp-54h]
.text:0000000000440C67                 ldmxcsr dword ptr gs:180h
.text:0000000000440C70                 movdqa  oword ptr [rbp-10h], xmm0
.text:0000000000440C75                 movdqa  oword ptr [rbp+0], xmm1
.text:0000000000440C7A                 movdqa  oword ptr [rbp+10h], xmm2
.text:0000000000440C7F                 movdqa  oword ptr [rbp+20h], xmm3
.text:0000000000440C84                 movdqa  oword ptr [rbp+30h], xmm4
.text:0000000000440C89                 movdqa  oword ptr [rbp+40h], xmm5
.text:0000000000440C8E                 test    qword ptr [rbp+0F8h], 200h
.text:0000000000440C99                 jz      short loc_440C9C
.text:0000000000440C9B                 sti
.text:0000000000440C9C
.text:0000000000440C9C loc_440C9C:                             ; CODE XREF: KiDebugServiceTrap+99j
.text:0000000000440C9C                 mov     ecx, 80000003h ; EXCEPTION_BREAKPOINT
.text:0000000000440CA1                 mov     edx, 1
.text:0000000000440CA6                 mov     r9, [rbp-50h]
.text:0000000000440CAA                 mov     r8, [rbp+0E8h] ; exception address [в чистом виде]
.text:0000000000440CB1                 call    KiExceptionDispatch

Вот такое небольшое замечание. То есть от вызова KiDebugServiceTrap то же исключение, что и от int 3 (CD 03) – KiBreakpointTrap. Почти то же самое. Разница в адресе исключения (на 2 байта).

.text:000000000043F740 KiBreakpointTrap proc near              ; DATA XREF: SepAdtInitializePrivilegeAuditing+10808o

[...skipped...]

.text:000000000043F79E
.text:000000000043F79E loc_43F79E:                             ; CODE XREF: KiBreakpointTrap+3Bj
.text:000000000043F79E                                         ; KiBreakpointTrap+57j
.text:000000000043F79E                 cld
.text:000000000043F79F                 stmxcsr dword ptr [rbp-54h]
.text:000000000043F7A3                 ldmxcsr dword ptr gs:180h
.text:000000000043F7AC                 movdqa  oword ptr [rbp-10h], xmm0
.text:000000000043F7B1                 movdqa  oword ptr [rbp+0], xmm1
.text:000000000043F7B6                 movdqa  oword ptr [rbp+10h], xmm2
.text:000000000043F7BB                 movdqa  oword ptr [rbp+20h], xmm3
.text:000000000043F7C0                 movdqa  oword ptr [rbp+30h], xmm4
.text:000000000043F7C5                 movdqa  oword ptr [rbp+40h], xmm5
.text:000000000043F7CA                 test    qword ptr [rbp+0F8h], 200h
.text:000000000043F7D5                 jz      short loc_43F7D8
.text:000000000043F7D7                 sti
.text:000000000043F7D8
.text:000000000043F7D8 loc_43F7D8:                             ; CODE XREF: KiBreakpointTrap+95j
.text:000000000043F7D8                 mov     ecx, 80000003h
.text:000000000043F7DD                 mov     edx, 1
.text:000000000043F7E2                 mov     r8, [rbp+0E8h]
.text:000000000043F7E9                 dec     r8 ; Длина опкода 0xCC, 1 байт
.text:000000000043F7EC                 mov     r9d, 0
.text:000000000043F7F2                 call    KiExceptionDispatch

Упущение здесь в том, что не учитывается, что мы можем вызвать KiBreakpointTrap не с помощью 0xCC, а с помощью 0xCD 03. В итоге адрес эксепшена – середина команды  0xCD 03 (int 3)

Appendix [64-bit services]

•Сентябрь 7, 2009 • Добавить комментарий

Дополнение к предыдущей записи

struct _KTHREAD {
  // non-static data ——————————–
  /*<thisrel this+0×0>*/ /*|0×18|*/ struct _DISPATCHER_HEADER Header;
  /*<thisrel this+0×18>*/ /*|0×10|*/ struct _LIST_ENTRY MutantListHead;
  /*<thisrel this+0×28>*/ /*|0×8|*/ void* InitialStack;
  /*<thisrel this+0×30>*/ /*|0×8|*/ void* StackLimit;
  /*<thisrel this+0×38>*/ /*|0×8|*/ void* KernelStack;
  /*<thisrel this+0×40>*/ /*|0×8|*/ unsigned __int64 ThreadLock;
  /*<thisrel this+0×48>*/ /*|0×30|*/ struct _KAPC_STATE ApcState;
  /*<thisrel this+0×48>*/ /*|0×2b|*/ unsigned char ApcStateFill[43];
  /*<thisrel this+0×73>*/ /*|0×1|*/ unsigned char ApcQueueable;
  /*<thisrel this+0×74>*/ /*|0×1|*/ unsigned char NextProcessor;
  /*<thisrel this+0×75>*/ /*|0×1|*/ unsigned char DeferredProcessor;
  /*<thisrel this+0×76>*/ /*|0×1|*/ unsigned char AdjustReason;
  /*<thisrel this+0×77>*/ /*|0×1|*/ char AdjustIncrement;
  /*<thisrel this+0×78>*/ /*|0×8|*/ unsigned __int64 ApcQueueLock;
  /*<thisrel this+0×80>*/ /*|0×8|*/ __int64 WaitStatus;
  /*<thisrel this+0×88>*/ /*|0×8|*/ struct _KWAIT_BLOCK* WaitBlockList;
  /*<thisrel this+0×88>*/ /*|0×8|*/ struct _KGATE* GateObject;
  /*<thisrel this+0×90>*/ /*|0×1|*/ unsigned char Alertable;
  /*<thisrel this+0×91>*/ /*|0×1|*/ unsigned char WaitNext;
  /*<thisrel this+0×92>*/ /*|0×1|*/ unsigned char WaitReason;
  /*<thisrel this+0×93>*/ /*|0×1|*/ char Priority;
  /*<thisrel this+0×94>*/ /*|0×1|*/ unsigned char EnableStackSwap;
  /*<thisrel this+0×95>*/ /*|0×1|*/ unsigned char SwapBusy;
  /*<thisrel this+0×96>*/ /*|0×2|*/ unsigned char Alerted[2];
  /*<thisrel this+0×98>*/ /*|0×10|*/ struct _LIST_ENTRY WaitListEntry;
  /*<thisrel this+0×98>*/ /*|0×8|*/ struct _SINGLE_LIST_ENTRY SwapListEntry;
  /*<thisrel this+0xa8>*/ /*|0×8|*/ struct _KQUEUE* Queue;
  /*<thisrel this+0xb0>*/ /*|0×8|*/ void* Teb;
  /*<thisrel this+0xb8>*/ /*|0×40|*/ struct _KTIMER Timer;
  /*<thisrel this+0xb8>*/ /*|0×3c|*/ unsigned char TimerFill[60];
  /*<bitfield this+0xf4>*/ /*|0×4|*/ unsigned long AutoAlignment:0:1;
  /*<bitfield this+0xf4>*/ /*|0×4|*/ unsigned long DisableBoost:1:1;
  /*<bitfield this+0xf4>*/ /*|0×4|*/ unsigned long GuiThread:2:1;
  /*<bitfield this+0xf4>*/ /*|0×4|*/ unsigned long ReservedFlags:3:1d;
  /*<thisrel this+0xf4>*/ /*|0×4|*/ long ThreadFlags;
  /*<thisrel this+0xf8>*/ /*|0xc0|*/ struct _KWAIT_BLOCK WaitBlock[4];
  /*<thisrel this+0xf8>*/ /*|0×2b|*/ unsigned char WaitBlockFill0[43];
  /*<thisrel this+0×123>*/ /*|0×1|*/ unsigned char SystemAffinityActive;
  /*<thisrel this+0xf8>*/ /*|0×5b|*/ unsigned char WaitBlockFill1[91];
  /*<thisrel this+0×153>*/ /*|0×1|*/ char PreviousMode;
  /*<thisrel this+0xf8>*/ /*|0×8b|*/ unsigned char WaitBlockFill2[139];
  /*<thisrel this+0×183>*/ /*|0×1|*/ unsigned char ResourceIndex;
  /*<thisrel this+0xf8>*/ /*|0xbb|*/ unsigned char WaitBlockFill3[187];
  /*<thisrel this+0×1b3>*/ /*|0×1|*/ unsigned char LargeStack;
  /*<thisrel this+0xf8>*/ /*|0×2c|*/ unsigned char WaitBlockFill4[44];
  /*<thisrel this+0×124>*/ /*|0×4|*/ unsigned long ContextSwitches;
  /*<thisrel this+0xf8>*/ /*|0×5c|*/ unsigned char WaitBlockFill5[92];
  /*<thisrel this+0×154>*/ /*|0×1|*/ unsigned char State;
  /*<thisrel this+0×155>*/ /*|0×1|*/ unsigned char NpxState;
  /*<thisrel this+0×156>*/ /*|0×1|*/ unsigned char WaitIrql;
  /*<thisrel this+0×157>*/ /*|0×1|*/ char WaitMode;
  /*<thisrel this+0xf8>*/ /*|0×8c|*/ unsigned char WaitBlockFill6[140];
  /*<thisrel this+0×184>*/ /*|0×4|*/ unsigned long WaitTime;
  /*<thisrel this+0xf8>*/ /*|0xbc|*/ unsigned char WaitBlockFill7[188];
  /*<thisrel this+0×1b4>*/ /*|0×2|*/ short KernelApcDisable;
  /*<thisrel this+0×1b6>*/ /*|0×2|*/ short SpecialApcDisable;
  /*<thisrel this+0×1b4>*/ /*|0×4|*/ unsigned long CombinedApcDisable;
  /*<thisrel this+0×1b8>*/ /*|0×10|*/ struct _LIST_ENTRY QueueListEntry;
  /*<thisrel this+0×1c8>*/ /*|0×8|*/ struct _KTRAP_FRAME* TrapFrame;
  /*<thisrel this+0×1d0>*/ /*|0×8|*/ void* CallbackStack;
  /*<thisrel this+0×1d8>*/ /*|0×1|*/ unsigned char ApcStateIndex;
  /*<thisrel this+0×1d9>*/ /*|0×1|*/ unsigned char IdealProcessor;
  /*<thisrel this+0×1da>*/ /*|0×1|*/ unsigned char Preempted;
  /*<thisrel this+0×1db>*/ /*|0×1|*/ unsigned char ProcessReadyQueue;
  /*<thisrel this+0×1dc>*/ /*|0×1|*/ unsigned char KernelStackResident;
  /*<thisrel this+0×1dd>*/ /*|0×1|*/ char BasePriority;
  /*<thisrel this+0×1de>*/ /*|0×1|*/ char PriorityDecrement;
  /*<thisrel this+0×1df>*/ /*|0×1|*/ char Saturation;
  /*<thisrel this+0×1e0>*/ /*|0×8|*/ unsigned __int64 UserAffinity;
  /*<thisrel this+0×1e8>*/ /*|0×8|*/ struct _KPROCESS* Process;
  /*<thisrel this+0×1f0>*/ /*|0×8|*/ unsigned __int64 Affinity;
  /*<thisrel this+0×1f8>*/ /*|0×10|*/ struct _KAPC_STATE* ApcStatePointer[2];
  /*<thisrel this+0×208>*/ /*|0×30|*/ struct _KAPC_STATE SavedApcState;
  /*<thisrel this+0×208>*/ /*|0×2b|*/ unsigned char SavedApcStateFill[43];
  /*<thisrel this+0×233>*/ /*|0×1|*/ char FreezeCount;
  /*<thisrel this+0×234>*/ /*|0×1|*/ char SuspendCount;
  /*<thisrel this+0×235>*/ /*|0×1|*/ unsigned char UserIdealProcessor;
  /*<thisrel this+0×236>*/ /*|0×1|*/ unsigned char CalloutActive;
  /*<thisrel this+0×237>*/ /*|0×1|*/ unsigned char CodePatchInProgress;
  /*<thisrel this+0×238>*/ /*|0×8|*/ void* Win32Thread;
  /*<thisrel this+0×240>*/ /*|0×8|*/ void* StackBase;
  /*<thisrel this+0×248>*/ /*|0×58|*/ struct _KAPC SuspendApc;
  /*<thisrel this+0×248>*/ /*|0×1|*/ unsigned char SuspendApcFill0[1];
  /*<thisrel this+0×249>*/ /*|0×1|*/ char Quantum;
  /*<thisrel this+0×248>*/ /*|0×3|*/ unsigned char SuspendApcFill1[3];
  /*<thisrel this+0×24b>*/ /*|0×1|*/ unsigned char QuantumReset;
  /*<thisrel this+0×248>*/ /*|0×4|*/ unsigned char SuspendApcFill2[4];
  /*<thisrel this+0×24c>*/ /*|0×4|*/ unsigned long KernelTime;
  /*<thisrel this+0×248>*/ /*|0×40|*/ unsigned char SuspendApcFill3[64];
  /*<thisrel this+0×288>*/ /*|0×8|*/ void* TlsArray;
  /*<thisrel this+0×248>*/ /*|0×48|*/ unsigned char SuspendApcFill4[72];
  /*<thisrel this+0×290>*/ /*|0×8|*/ void* LegoData;
  /*<thisrel this+0×248>*/ /*|0×53|*/ unsigned char SuspendApcFill5[83];
  /*<thisrel this+0×29b>*/ /*|0×1|*/ unsigned char PowerState;
  /*<thisrel this+0×29c>*/ /*|0×4|*/ unsigned long UserTime;
  /*<thisrel this+0×2a0>*/ /*|0×20|*/ struct _KSEMAPHORE SuspendSemaphore;
  /*<thisrel this+0×2a0>*/ /*|0×1c|*/ unsigned char SuspendSemaphorefill[28];
  /*<thisrel this+0×2bc>*/ /*|0×4|*/ unsigned long SListFaultCount;
  /*<thisrel this+0×2c0>*/ /*|0×10|*/ struct _LIST_ENTRY ThreadListEntry;
  /*<thisrel this+0×2d0>*/ /*|0×8|*/ void* SListFaultAddress;
  /*<thisrel this+0×2d8>*/ /*|0×8|*/ __int64 ReadOperationCount;
  /*<thisrel this+0×2e0>*/ /*|0×8|*/ __int64 WriteOperationCount;
  /*<thisrel this+0×2e8>*/ /*|0×8|*/ __int64 OtherOperationCount;
  /*<thisrel this+0×2f0>*/ /*|0×8|*/ __int64 ReadTransferCount;
  /*<thisrel this+0×2f8>*/ /*|0×8|*/ __int64 WriteTransferCount;
  /*<thisrel this+0×300>*/ /*|0×8|*/ __int64 OtherTransferCount;
};

Вызов системных сервисов в winxp x64 [notes]

•Сентябрь 7, 2009 • Комментарии (6)

Вызов системных сервисов в winxp x64. Кое-какие наброски

Все начинается в ntdll.

public NtRegisterThreadTerminatePort
NtRegisterThreadTerminatePort proc near
mov     r10, rcx        ; NtRegisterThreadTerminatePort
mov     eax, 0E3h
syscall
retn
NtRegisterThreadTerminatePort endp

Значит, куда передается управление. Syscall в своей работе использует MSR lstar [для прог в 64-битном режиме] и cstar в  compatibility  mode (т.е. режиме совместимости)

lstar – C0000082h (для 64-битного софта) – по этому адресу KiSystemCall64
cstar – C0000083h (в режиме совместимости) – по этому адресу KiSystemCall32

Еще уточнение, что есть long mode, а 64-битный режим и режим совместимости (compatibility mode) являются его частью.

Команда rdmsr,кстати к вопросу чтения из msr,  работает в 64-битном режиме так же, как и в 32-битном. EDX:EAX содержат соответственно после того, как команда отработала, старшую и младшую часть адреса.  Старшие 32 бита rdx и rax не юзаются

Вернемся к нашей KiSystemCall64.

.text:0000000000440F40 KiSystemCall64  proc near               ; DATA XREF: SepAdtInitializePrivilegeAuditing-1ED1Co
.text:0000000000440F40
.text:0000000000440F40 var_110         = qword ptr -110h
.text:0000000000440F40
.text:0000000000440F40                 swapgs
.text:0000000000440F43                 mov     gs:1A0h, rsp
.text:0000000000440F4C                 mov     rsp, gs:1A8h
.text:0000000000440F55                 push    2Bh ; usermode ds/es/gs/ss
.text:0000000000440F57                 push    qword ptr gs:1A0h
.text:0000000000440F5F                 push    r11
.text:0000000000440F61                 push    33h ; usermode cs
.text:0000000000440F63                 push    rcx
.text:0000000000440F64                 mov     rcx, r10
.text:0000000000440F67                 sub     rsp, 8
.text:0000000000440F6B                 push    rbp
.text:0000000000440F6C                 sub     rsp, 158h
.text:0000000000440F73                 lea     rbp, [rsp+190h+var_110]
.text:0000000000440F7B                 mov     [rbp+0C0h], rbx
.text:0000000000440F82                 mov     [rbp+0C8h], rdi
.text:0000000000440F89                 mov     [rbp+0D0h], rsi
.text:0000000000440F90                 mov     byte ptr [rbp-55h], 2
.text:0000000000440F94                 mov     rbx, gs:188h ; KTHREAD
.text:0000000000440F9D                 prefetchw byte ptr [rbx+1C8h]
.text:0000000000440FA4                 stmxcsr dword ptr [rbp-54h]
.text:0000000000440FA8                 ldmxcsr dword ptr gs:180h
.text:0000000000440FB1                 test    byte ptr [rbx+3], 1
.text:0000000000440FB5                 mov     word ptr [rbp+80h], 0
.text:0000000000440FBE                 jz      short loc_440FEF
.text:0000000000440FC0                 mov     [rbp-50h], rax
.text:0000000000440FC4                 mov     [rbp-48h], rcx
.text:0000000000440FC8                 mov     [rbp-40h], rdx
.text:0000000000440FCC                 mov     [rbp-38h], r8
.text:0000000000440FD0                 mov     [rbp-30h], r9
.text:0000000000440FD4                 call    KiSaveDebugRegisterState
.text:0000000000440FD9                 mov     rax, [rbp-50h]
.text:0000000000440FDD                 mov     rcx, [rbp-48h]
.text:0000000000440FE1                 mov     rdx, [rbp-40h]
.text:0000000000440FE5                 mov     r8, [rbp-38h]
.text:0000000000440FE9                 mov     r9, [rbp-30h]
.text:0000000000440FED                 db      66h
.text:0000000000440FED                 nop
.text:0000000000440FEF
.text:0000000000440FEF loc_440FEF:                             ; CODE XREF: KiSystemCall64+7Ej
.text:0000000000440FEF                 sti
.text:0000000000440FEF KiSystemCall64  endp
.text:0000000000440FEF
.text:0000000000440FF0
.text:0000000000440FF0 ; ————— S U B R O U T I N E —————————————
.text:0000000000440FF0
.text:0000000000440FF0
.text:0000000000440FF0 KiSystemServiceStart proc near          ; DATA XREF: KiServiceInternal+5Ao
.text:0000000000440FF0
.text:0000000000440FF0 var_70          = qword ptr -70h
.text:0000000000440FF0 arg_10          = qword ptr  18h
.text:0000000000440FF0
.text:0000000000440FF0                 mov     [rbx+1C8h], rsp
.text:0000000000440FF7                 mov     edi, eax ; eax – номер системного сервиса, переданный из юзермода
.text:0000000000440FF9                 shr     edi, 7
.text:0000000000440FFC                 and     edi, 20h ; edi – индекс сервисной таблицы
.text:0000000000440FFF                 and     eax, 0FFFh ; номер сервиса в таблице
.text:0000000000441004
.text:0000000000441004 KiSystemServiceRepeat:                  ; CODE XREF: KiSystemServiceExit+187j
.text:0000000000441004                 lea     r10, KeServiceDescriptorTable ; отсюда можно утянуть адреса таблиц шадоу и ntos
.text:000000000044100B                 lea     r11, KeServiceDescriptorTableShadow ; достаточно получить адрес KiSystemCall64
.text:0000000000441012                 test    dword ptr [rbx+0F4h], 4 ; а дальше дело техники )

Для тех, кто не знает – инструкция swapgs доступна только в 64-битном режиме. Она обменивает текущее значение gs со значением, содержащиеся в регистре MSR_KERNELGSBase (0xC000_0102). Доступна при CPL=0. Инструкция stmxcsr – сохраняет значение регистра mxcsr, ldmxcsr соответственно загружает из памяти.  mxcsr – это 32-битный регистр, содержащий ряд флагов, связанных с SSE.

Теперь у нас KTHREAD лежит по адресу gs:188h (см ниже, откуда это очевидно)

.text:00000000004C8D80 ; PKTHREAD KeGetCurrentThread(void)
.text:00000000004C8D80                 public KeGetCurrentThread
.text:00000000004C8D80 KeGetCurrentThread proc near
.text:00000000004C8D80                 mov     rax, gs:188h    ; KeGetCurrentThread
.text:00000000004C8D89                 retn
.text:00000000004C8D89 KeGetCurrentThread endp

Если необходимо, то тред конвертируется в гуи

.text:0000000000441298                 mov     [rbp-80h], eax
.text:000000000044129B                 mov     [rbp-78h], rcx
.text:000000000044129F                 mov     [rbp-70h], rdx
.text:00000000004412A3                 mov     [rbp-68h], r8
.text:00000000004412A7                 mov     [rbp-60h], r9
.text:00000000004412AB                 call    KiConvertToGuiThread
.text:00000000004412B0                 or      eax, eax
.text:00000000004412B2                 mov     eax, [rbp-80h]
.text:00000000004412B5                 mov     rcx, [rbp-78h]
.text:00000000004412B9                 mov     rdx, [rbp-70h]
.text:00000000004412BD                 mov     r8, [rbp-68h]
.text:00000000004412C1                 mov     r9, [rbp-60h]
.text:00000000004412C5                 mov     [rbx+1C8h], rsp
.text:00000000004412CC                 jz      KiSystemServiceRepeat

KiConvertToGuiThread вызывает  PsConvertToGuiThread, та в свою очередь PspW32Thread[Process]Callout [о работе callouts я уже здесь писала].

В ntoskrnl вызов сервисов выглядит так

.text:000000000043D850 ZwPowerInformation proc near            ; CODE XREF: PoInitHiberServices+2Bp
.text:000000000043D850                                         ; NtPowerInformation+6E0p …
.text:000000000043D850                 mov     rax, rsp
.text:000000000043D853                 cli
.text:000000000043D854                 sub     rsp, 10h
.text:000000000043D858                 push    rax
.text:000000000043D859                 pushf
.text:000000000043D85A                 push    10h
.text:000000000043D85C                 lea     rax, KiServiceLinkage
.text:000000000043D863                 push    rax
.text:000000000043D864                 mov     eax, 5Ch
.text:000000000043D869                 jmp     KiServiceInternal
.text:000000000043D869 ZwPowerInformation endp

Т.е. по ret из сервиса мы отправимся по адресу KiServiceLinkage, по которому кроме ret ничего не лежит.

Далее  смотрим KiServiceInternal, она просто устанавливает PreviousMode и передает управление в KiSystemCall64

text:0000000000440EC0 KiServiceInternal proc near             ; CODE XREF: ZwMapUserPhysicalPagesScatter+19j
.text:0000000000440EC0                                         ; ZwWaitForSingleObject+19j …
.text:0000000000440EC0
.text:0000000000440EC0 var_E8          = qword ptr -0E8h
.text:0000000000440EC0
.text:0000000000440EC0                 sub     rsp, 8
.text:0000000000440EC4                 push    rbp
.text:0000000000440EC5                 sub     rsp, 158h
.text:0000000000440ECC                 lea     rbp, [rsp+168h+var_E8]
.text:0000000000440ED4                 mov     [rbp+0C0h], rbx
.text:0000000000440EDB                 mov     [rbp+0C8h], rdi
.text:0000000000440EE2                 mov     [rbp+0D0h], rsi
.text:0000000000440EE9                 sti
.text:0000000000440EEA                 mov     rbx, gs:188h ; KTHREAD
.text:0000000000440EF3                 prefetchw byte ptr [rbx+1C8h]
.text:0000000000440EFA                 movzx   edi, byte ptr [rbx+153h]
.text:0000000000440F01                 mov     [rbp-58h], dil ; dil – младший байт регистра edi
.text:0000000000440F05                 mov     byte ptr [rbx+153h], 0 ;PreviousMode
.text:0000000000440F0C                 mov     r10, [rbx+1C8h] ;*TrapFrame
.text:0000000000440F13                 mov     [rbp+0B8h], r10
.text:0000000000440F1A                 lea     r11, KiSystemServiceStart  ; прыгаем в середину KiSystemCall64
.text:0000000000440F21                 jmp     r11
.text:0000000000440F21 KiServiceInternal endp

В зависимости от того, откуда пришел вызов, из юзермода или сервис был вызван из ядра с помощью KiServiceInternal выполняем выход

.text:0000000000441219 goto_usermode:                          ; CODE XREF: KiSystemServiceExit+C7j
.text:0000000000441219                 mov     r8, [rbp+100h]
.text:0000000000441220                 mov     r9, [rbp+0D8h]
.text:0000000000441227                 xor     edx, edx
.text:0000000000441229                 xor     r10, r10
.text:000000000044122C                 pxor    xmm0, xmm0
.text:0000000000441230                 pxor    xmm1, xmm1
.text:0000000000441234                 pxor    xmm2, xmm2
.text:0000000000441238                 pxor    xmm3, xmm3
.text:000000000044123C                 pxor    xmm4, xmm4
.text:0000000000441240                 pxor    xmm5, xmm5
.text:0000000000441244                 mov     rcx, [rbp+0E8h]
.text:000000000044124B                 mov     r11, [rbp+0F8h]
.text:0000000000441252                 mov     rbp, r9
.text:0000000000441255                 mov     rsp, r8
.text:0000000000441258                 swapgs ; меняем gs
.text:000000000044125B                 sysret
.text:000000000044125E
.text:000000000044125E if_fromkernelmode:                      ; CODE XREF: KiSystemServiceExit+25j
.text:000000000044125E                 mov     rcx, gs:188h
.text:0000000000441267                 mov     rdx, [rbp+0B8h]
.text:000000000044126E                 mov     [rcx+1C8h], rdx ;*TrapFrame
.text:0000000000441275                 mov     dl, [rbp-58h]
.text:0000000000441278                 mov     [rcx+153h], dl ; PreviousMode
.text:000000000044127E                 cli
.text:000000000044127F                 mov     rsp, rbp
.text:0000000000441282                 mov     rbp, [rbp+0D8h]
.text:0000000000441289                 mov     rsp, [rsp+arg_F8]
.text:0000000000441291                 sti
.text:0000000000441292                 retn ;->KiServiceLinkage

В заключение хочу сказать пару слов об KiSystemCall32.

.text:0000000000440CC0 KiSystemCall32:                         ; DATA XREF: SepAdtInitializePrivilegeAuditing-1ED31o
.text:0000000000440CC0                 swapgs
.text:0000000000440CC3                 mov     gs:1A0h, rsp
.text:0000000000440CCC                 mov     rsp, gs:1A8h
.text:0000000000440CD5                 push    2Bh
.text:0000000000440CD7                 push    qword ptr gs:1A0h
.text:0000000000440CDF                 push    r11
.text:0000000000440CE1                 push    23h
.text:0000000000440CE3                 push    rcx
.text:0000000000440CE4                 swapgs
.text:0000000000440CE7                 sub     rsp, 8
.text:0000000000440CEB                 push    rbp
.text:0000000000440CEC                 sub     rsp, 158h
.text:0000000000440CF3                 lea     rbp, [rsp+2F8h+var_278]
.text:0000000000440CFB                 mov     byte ptr [rbp-55h], 1
.text:0000000000440CFF                 mov     [rbp-50h], rax
.text:0000000000440D03                 mov     [rbp-48h], rcx
.text:0000000000440D07                 mov     [rbp-40h], rdx
.text:0000000000440D0B                 mov     [rbp-38h], r8
.text:0000000000440D0F                 mov     [rbp-30h], r9
.text:0000000000440D13                 mov     [rbp-28h], r10
.text:0000000000440D17                 mov     [rbp-20h], r11
.text:0000000000440D1B                 test    byte ptr [rbp+0F0h], 1
.text:0000000000440D22                 jz      short loc_440D45
.text:0000000000440D24                 swapgs
.text:0000000000440D27                 mov     r10, gs:188h
.text:0000000000440D30                 test    byte ptr [r10+3], 1
.text:0000000000440D35                 mov     word ptr [rbp+80h], 0
.text:0000000000440D3E                 jz      short loc_440D45
.text:0000000000440D40                 call    KiSaveDebugRegisterState
.text:0000000000440D45
.text:0000000000440D45 loc_440D45:                             ; CODE XREF: KiDebugServiceTrap+122j
.text:0000000000440D45                                         ; KiDebugServiceTrap+13Ej
.text:0000000000440D45                 cld
.text:0000000000440D46                 stmxcsr dword ptr [rbp-54h]
.text:0000000000440D4A                 ldmxcsr dword ptr gs:180h
.text:0000000000440D53                 movdqa  oword ptr [rbp-10h], xmm0
.text:0000000000440D58                 movdqa  oword ptr [rbp+0], xmm1
.text:0000000000440D5D                 movdqa  oword ptr [rbp+10h], xmm2
.text:0000000000440D62                 movdqa  oword ptr [rbp+20h], xmm3
.text:0000000000440D67                 movdqa  oword ptr [rbp+30h], xmm4
.text:0000000000440D6C                 movdqa  oword ptr [rbp+40h], xmm5
.text:0000000000440D71                 test    qword ptr [rbp+0F8h], 200h ; rflags
.text:0000000000440D7C                 jz      short loc_440D7F
.text:0000000000440D7E                 sti
.text:0000000000440D7F
.text:0000000000440D7F loc_440D7F:                             ; CODE XREF: KiDebugServiceTrap+17Cj
.text:0000000000440D7F                 mov     ecx, 0C000001Dh
.text:0000000000440D84                 xor     edx, edx
.text:0000000000440D86                 mov     r8, [rbp+0E8h]
.text:0000000000440D8D                 call    KiExceptionDispatch

Реально, как мы видим этот обработчик только вызывает STATUS_ILLEGAL_INSTRUCTION. Если попытаться заюзать syscall из 32-битной программы она грохнется с этим исключением.

Следующая запись в блоге – KTHREAD  64-бит.

x64 idt [3xperimentum crucis]

•Сентябрь 4, 2009 • Добавить комментарий

Работа с idt x64, драйвер. ml64 [из ddk можно утянуть]  отказался понимать assume, к сожалению. Еще нельзя юзать .while, тоже не распознает. Пока не особо привычно работать с 64-битным кодом, хотя ничего сложного в общем-то нет.

; compile ml64 driver.asm /link /subsystem:native /entry:DriverEntry /driver /base:0×10000 /out:driver.sys
includelib amd64\ntoskrnl.lib

extrn DbgPrint: PROC
.data
; компилировать ml64

IDTR struct
dwLimit word  ?
qwBase qword ?
IDTR ends

; формат 64-битного дескриптора шлюза прерывания

InterruprGate64 struct
_OffsetLow01 word ?
SegSel word ?
Attributes word ?
_OffsetLow02 word ?
_OffsetHi dword ?
Reserved  dword  ?
InterruprGate64 ends

FormatIdt db «Idt base = %I64x; Idt limit %X»,13,10,0
IdtEntryInfo db «Idt entry offset %I64x; selector %X; vector %X»,13,10,0
kinterruptinfo db «KINTERRUPT = %I64x; KINTERRUPT.ServiceRoutine = %I64x; vector %X»,13,10,0

.data?

idtrReg IDTR <?>


.code

DriverEntry proc
sidt  idtrReg
sub r8,r8
mov r8w, idtrReg.dwLimit
push idtrReg.qwBase
pop rdx
mov rcx, offset FormatIdt
sub rsp, 8*4
call DbgPrint
add rsp, 8*4
mov rax,idtrReg.qwBase
mov rcx, 0ffh
idt_loo:
dec rcx
push rcx
; сохраняем вектор
mov r9,rcx
; в 64-битном режиме у нас дескрптор 16 байт, а не 8
imul rcx,10h
lea rdx,qword ptr [rax + rcx]
push rax
; селектор
sub r8,r8
mov r8w,word ptr [rdx+2]
; офсет
mov r10,qword ptr [rdx]
and r10,0FFFFh
mov rdx, qword ptr [rdx+4]
mov dx,r10w
; проверка на DispatchCode
cmp dword ptr [rdx],8d485550h
jnz _print_no_kinterrupt
; у нас есть KINTERRUPT
sub rdx, 70h
mov r8,qword ptr [rdx+18h] ; KINTERRUPT->ServiceRoutine
mov rcx, offset kinterruptinfo
sub rsp, 8*4
call DbgPrint
add rsp, 8*4
jmp nxt_
_print_no_kinterrupt:
mov rcx,offset IdtEntryInfo
sub rsp, 8*4
call DbgPrint
add rsp, 8*4
nxt_:
pop rax
pop rcx
cmp rcx,0
jnz idt_loo
ret_:
mov eax,0C0000001h
ret
DriverEntry endp

end

IDT x64 win xp [theory]

•Сентябрь 4, 2009 • Комментарии (3)

В этой заметке [которая разбита на 2 части]  речь пойдет об 64-битной IDT. Для нормального восприятия того, что здесь напишу нужно иметь в наличии Debugging Tools for Windows x64 – вообще незаменимая вещь, dbgview Руссиновича + livekd его же [опционально] , ml64 [в ddk есть].  
В 64-битном режиме регистр idtr имеет размер 10 байт [база - 8 байт]

Пример идт  xp x64

kd> !idt

Dumping IDT:

00:     fffff8000103f200 nt!KiDivideErrorFault
01:     fffff8000103f2c0 nt!KiDebugTrapOrFault
02:     fffff8000103f400 nt!KiNmiInterrupt      Stack = 0xFFFFF80000392000

03:     fffff8000103f740 nt!KiBreakpointTrap
04:     fffff8000103f800 nt!KiOverflowTrap
05:     fffff8000103f8c0 nt!KiBoundFault
06:     fffff8000103f980 nt!KiInvalidOpcodeFault
07:     fffff8000103fb40 nt!KiNpxNotAvailableFault
08:     fffff8000103fc00 nt!KiDoubleFaultAbort  Stack = 0xFFFFF80000390000

09:     fffff8000103fcc0 nt!KiNpxSegmentOverrunAbort
0a:     fffff8000103fd80 nt!KiInvalidTssFault
0b:     fffff8000103fe40 nt!KiSegmentNotPresentFault
0c:     fffff8000103ff40 nt!KiStackFault
0d:     fffff80001040040 nt!KiGeneralProtectionFault
0e:     fffff80001040140 nt!KiPageFault
10:     fffff80001040480 nt!KiFloatingErrorFault
11:     fffff800010405c0 nt!KiAlignmentFault
12:     fffff80001040680 nt!KiMcheckAbort       Stack = 0xFFFFF80000394000

13:     fffff800010409c0 nt!KiXmmException
1f:     fffff80001043800 nt!KiApcInterrupt
2c:     fffff80001040b40 nt!KiRaiseAssertion
2d:     fffff80001040c00 nt!KiDebugServiceTrap
2f:     fffff8000100ca40 nt!KiDpcInterrupt

Как и в 32-битной IDT, в 64-битной есть часть входов с KINTERRUPT. Эта структура в  x64 претерпела некоторые изменения

struct _KINTERRUPT {

  // static data ————————————

  // non-static data ——————————–
  /*<thisrel this+0×0>*/ /*|0×2|*/ short Type;
  /*<thisrel this+0×2>*/ /*|0×2|*/ short Size;
  /*<thisrel this+0×8>*/ /*|0×10|*/ struct _LIST_ENTRY InterruptListEntry;
  /*<thisrel this+0×18>*/ /*|0×8|*/ unsigned char  (ServiceRoutine*)(struct _KINTERRUPT*, void*);
  /*<thisrel this+0×20>*/ /*|0×8|*/ void* ServiceContext;
  /*<thisrel this+0×28>*/ /*|0×8|*/ unsigned __int64 SpinLock;
  /*<thisrel this+0×30>*/ /*|0×4|*/ unsigned long TickCount;
  /*<thisrel this+0×38>*/ /*|0×8|*/ unsigned __int64* ActualLock;
  /*<thisrel this+0×40>*/ /*|0×8|*/ void  (DispatchAddress*)();
  /*<thisrel this+0×48>*/ /*|0×4|*/ unsigned long Vector;
  /*<thisrel this+0×4c>*/ /*|0×1|*/ unsigned char Irql;
  /*<thisrel this+0×4d>*/ /*|0×1|*/ unsigned char SynchronizeIrql;
  /*<thisrel this+0×4e>*/ /*|0×1|*/ unsigned char FloatingSave;
  /*<thisrel this+0×4f>*/ /*|0×1|*/ unsigned char Connected;
  /*<thisrel this+0×50>*/ /*|0×1|*/ char Number;
  /*<thisrel this+0×51>*/ /*|0×1|*/ unsigned char ShareVector;
  /*<thisrel this+0×54>*/ /*|0×4|*/ enum _KINTERRUPT_MODE Mode;
  /*<thisrel this+0×58>*/ /*|0×4|*/ unsigned long ServiceCount;
  /*<thisrel this+0×5c>*/ /*|0×4|*/ unsigned long DispatchCount;
  /*<thisrel this+0×60>*/ /*|0×8|*/ struct _KTRAP_FRAME* TrapFrame;
  /*<thisrel this+0×68>*/ /*|0×8|*/ void* Reserved;
  /*<thisrel this+0×70>*/ /*|0×10|*/ unsigned long DispatchCode[4];

  // base classes ———————————–

  // friends —————————————-

  // static functions ——————————-

  // non-virtual functions ————————–

  // virtual functions ——————————
};
// <size 0×80>

Теперь посмотрим на внешний вид DispatchCode. 

kd> U fffff8000083f400+70
hal!HalpKInterruptHeap+0×470:
fffff800`0083f470 50              push    rax
fffff800`0083f471 55              push    rbp
fffff800`0083f472 488d2d87ffffff  lea     rbp,[hal!HalpKInterruptHeap+0x400 (fffff800`0083f400)]
fffff800`0083f479 ff6540          jmp     qword ptr [rbp+40h]
fffff800`0083f47c cc              int     3
fffff800`0083f47d cc              int     3
fffff800`0083f47e cc              int     3
fffff800`0083f47f cc              int     3

Этот код идентичен для всех входов, являющихся частью KINTERRUPT. Т.е. идентифицировать их [по сигнатуре скажем 8d485550h – первый дворд] проблемы не составит, даже дизассемблер не нужен.

Ну и в качестве бонуса, x64 KTRAP_FRAME

struct _KTRAP_FRAME {

  // static data ————————————

  // non-static data ——————————–
  /*<thisrel this+0×0>*/ /*|0×8|*/ unsigned __int64 P1Home;
  /*<thisrel this+0×8>*/ /*|0×8|*/ unsigned __int64 P2Home;
  /*<thisrel this+0×10>*/ /*|0×8|*/ unsigned __int64 P3Home;
  /*<thisrel this+0×18>*/ /*|0×8|*/ unsigned __int64 P4Home;
  /*<thisrel this+0×20>*/ /*|0×8|*/ unsigned __int64 P5;
  /*<thisrel this+0×28>*/ /*|0×1|*/ char PreviousMode;
  /*<thisrel this+0×29>*/ /*|0×1|*/ unsigned char PreviousIrql;
  /*<thisrel this+0×2a>*/ /*|0×1|*/ unsigned char FaultIndicator;
  /*<thisrel this+0×2b>*/ /*|0×1|*/ unsigned char ExceptionActive;
  /*<thisrel this+0×2c>*/ /*|0×4|*/ unsigned long MxCsr;
  /*<thisrel this+0×30>*/ /*|0×8|*/ unsigned __int64 Rax;
  /*<thisrel this+0×38>*/ /*|0×8|*/ unsigned __int64 Rcx;
  /*<thisrel this+0×40>*/ /*|0×8|*/ unsigned __int64 Rdx;
  /*<thisrel this+0×48>*/ /*|0×8|*/ unsigned __int64 R8;
  /*<thisrel this+0×50>*/ /*|0×8|*/ unsigned __int64 R9;
  /*<thisrel this+0×58>*/ /*|0×8|*/ unsigned __int64 R10;
  /*<thisrel this+0×60>*/ /*|0×8|*/ unsigned __int64 R11;
  /*<thisrel this+0×68>*/ /*|0×8|*/ unsigned __int64 GsBase;
  /*<thisrel this+0×68>*/ /*|0×8|*/ unsigned __int64 GsSwap;
  /*<thisrel this+0×70>*/ /*|0×10|*/ struct _M128A Xmm0;
  /*<thisrel this+0×80>*/ /*|0×10|*/ struct _M128A Xmm1;
  /*<thisrel this+0×90>*/ /*|0×10|*/ struct _M128A Xmm2;
  /*<thisrel this+0xa0>*/ /*|0×10|*/ struct _M128A Xmm3;
  /*<thisrel this+0xb0>*/ /*|0×10|*/ struct _M128A Xmm4;
  /*<thisrel this+0xc0>*/ /*|0×10|*/ struct _M128A Xmm5;
  /*<thisrel this+0xd0>*/ /*|0×8|*/ unsigned __int64 FaultAddress;
  /*<thisrel this+0xd0>*/ /*|0×8|*/ unsigned __int64 ContextRecord;
  /*<thisrel this+0xd0>*/ /*|0×8|*/ unsigned __int64 TimeStamp;
  /*<thisrel this+0xd8>*/ /*|0×8|*/ unsigned __int64 Dr0;
  /*<thisrel this+0xe0>*/ /*|0×8|*/ unsigned __int64 Dr1;
  /*<thisrel this+0xe8>*/ /*|0×8|*/ unsigned __int64 Dr2;
  /*<thisrel this+0xf0>*/ /*|0×8|*/ unsigned __int64 Dr3;
  /*<thisrel this+0xf8>*/ /*|0×8|*/ unsigned __int64 Dr6;
  /*<thisrel this+0×100>*/ /*|0×8|*/ unsigned __int64 Dr7;
  /*<thisrel this+0×108>*/ /*|0×8|*/ unsigned __int64 DebugControl;
  /*<thisrel this+0×110>*/ /*|0×8|*/ unsigned __int64 LastBranchToRip;
  /*<thisrel this+0×118>*/ /*|0×8|*/ unsigned __int64 LastBranchFromRip;
  /*<thisrel this+0×120>*/ /*|0×8|*/ unsigned __int64 LastExceptionToRip;
  /*<thisrel this+0×128>*/ /*|0×8|*/ unsigned __int64 LastExceptionFromRip;
  /*<thisrel this+0×108>*/ /*|0×8|*/ unsigned __int64 LastBranchControl;
  /*<thisrel this+0×110>*/ /*|0×4|*/ unsigned long LastBranchMSR;
  /*<thisrel this+0×130>*/ /*|0×2|*/ unsigned short SegDs;
  /*<thisrel this+0×132>*/ /*|0×2|*/ unsigned short SegEs;
  /*<thisrel this+0×134>*/ /*|0×2|*/ unsigned short SegFs;
  /*<thisrel this+0×136>*/ /*|0×2|*/ unsigned short SegGs;
  /*<thisrel this+0×138>*/ /*|0×8|*/ unsigned __int64 TrapFrame;
  /*<thisrel this+0×140>*/ /*|0×8|*/ unsigned __int64 Rbx;
  /*<thisrel this+0×148>*/ /*|0×8|*/ unsigned __int64 Rdi;
  /*<thisrel this+0×150>*/ /*|0×8|*/ unsigned __int64 Rsi;
  /*<thisrel this+0×158>*/ /*|0×8|*/ unsigned __int64 Rbp;
  /*<thisrel this+0×160>*/ /*|0×8|*/ unsigned __int64 ErrorCode;
  /*<thisrel this+0×160>*/ /*|0×8|*/ unsigned __int64 ExceptionFrame;
  /*<thisrel this+0×168>*/ /*|0×8|*/ unsigned __int64 Rip;
  /*<thisrel this+0×170>*/ /*|0×2|*/ unsigned short SegCs;
  /*<thisrel this+0×172>*/ /*|0×6|*/ unsigned short Fill1[3];
  /*<thisrel this+0×178>*/ /*|0×4|*/ unsigned long EFlags;
  /*<thisrel this+0×17c>*/ /*|0×4|*/ unsigned long Fill2;
  /*<thisrel this+0×180>*/ /*|0×8|*/ unsigned __int64 Rsp;
  /*<thisrel this+0×188>*/ /*|0×2|*/ unsigned short SegSs;
  /*<thisrel this+0×18a>*/ /*|0×2|*/ unsigned short Fill3[1];
  /*<thisrel this+0×18c>*/ /*|0×4|*/ long CodePatchCycle;

  // base classes ———————————–

  // friends —————————————-

  // static functions ——————————-

  // non-virtual functions ————————–

  // virtual functions ——————————
};
// <size 0×190>

Поиск SuspendAPC в KTHREAD

•Август 30, 2009 • Добавить комментарий

Вот, что-то написалось утром. Пишу в блоге, чтобы он жил :) См комментарии к коду, там есть все. Просто чтобы смещения не прописывать, они в разных версиях винды разные. Привожу 2 функции для этого дела

BOOLEAN IsAPCSuspendAPC(PKAPC pAPC,ULONG uKernelBase,ULONG uKernelSize)
{
    // Функция проверяет принадлежность
    // KernelRoutine,RundownRoutine, NormalRoutine
    // к диапазону адресов указанного модуля
    BOOLEAN isSuspendAPC = TRUE;

    ULONG uKernelRoutine = (ULONG)pAPC->KernelRoutine;

    ULONG uNormalRoutine = (ULONG)pAPC->NormalRoutine;

    ULONG uRundownRoutine = (ULONG)pAPC->RundownRoutine;

    DbgPrint("IsAPCSuspendAPC: KernelRoutine = %X NormalRoutine = %X RundownRoutine =%X\n",
        uKernelRoutine,
        uNormalRoutine,
        uRundownRoutine);

    if(!((uKernelRoutine>=uKernelBase)&&(uKernelRoutine<(uKernelBase+uKernelSize))))
        isSuspendAPC = FALSE;

    if(!((uNormalRoutine>=uKernelBase)&&(uNormalRoutine<(uKernelBase+uKernelSize))))
        isSuspendAPC = FALSE;

    if(!((uRundownRoutine>=uKernelBase)&&(uRundownRoutine<(uKernelBase+uKernelSize))))
        isSuspendAPC = FALSE;

    return isSuspendAPC;
}

 

PKAPC PsSearchSuspendApc(PETHREAD pthr)
{
    /*
    Функция поиска указателя на SuspendAPC в KTHREAD
    */
    PKAPC pApc = 0;

    if(pthr->Tcb.Header.Type != OB_TYPE_THREAD) return pApc;

    DbgPrint("PsSearchSuspendApc: KTHREAD =%X\n", pthr);

    //ограничиваем поиск страницей [я там всякие PSE не учитываю, пускай будет 4кб страница]

    ULONG uCount = (0x1000 - (((ULONG)pthr)&0xFFF))/4 - 8;

    // получаем базу ntoskrnl и его размер в памяти
    ULONG uNtosBase,uNtosSize;

    uNtosBase = GetNtoskrnlBase(&uNtosSize);

    if(!uNtosBase)
    {
        DbgPrint("PsSearchSuspendApc: GetNtoskrnlBase error\n");

        return 0;
    }

    DbgPrint("PsSearchSuspendApc: ntoskrnl base %X ntoskrnl size = %X\n",
        uNtosBase,
        uNtosSize);

    // Type = 0x12
    // Size = 0x30
    while(uCount)
    {
        // прибавляем по 4, по крайней мере это поле всегда было по 4 выровнено
        pthr = (PETHREAD)((ULONG)pthr + 4);

        // в vista произошли изменения в структуре, там теперь поле Size имеет длину 1 байт,
        // так же как поле Type.

        // Type
        if((*(PUCHAR)pthr==0x12))
        {
            // Size, одинаков на всех билдах

            if(*((PUCHAR)pthr+2)==0x30)
            {
              // шаг второй. Проверяем, действительно ли это SuspendAPC
             // для этого надо проверить адреса обработчиков
                //  KernelRoutine,RundownRoutine, NormalRoutine
                // они  равны соответственно KiSuspendNop, KiSuspendRundown, KiSuspendThread
                // эти адреса принадлежат ntoskrnl

              if(IsAPCSuspendAPC((PKAPC)pthr,uNtosBase,uNtosSize))
              {
                DbgPrint("PsSearchSuspendApc: Suspend APC founded!\n");

                pApc = (PKAPC)pthr;

                break;
              }
            }
        }

        uCount --;
    }

    return pApc;
}

Проверила сабж на висте, семерке, икспе и все определилось ок. везде смещения разные и соответствуют действительности