Проблемы с перехватом функции из win32k.sys на ассемблере

Тема в разделе "WASM.NT.KERNEL", создана пользователем spirom, 18 авг 2010.

  1. spirom

    spirom New Member

    Публикаций:
    0
    Регистрация:
    18 авг 2010
    Сообщения:
    24
    Добрый день!
    Я решил написать простой перехватчик NtUserSetWindowsHookEx на ассемблере. Драйвер находит адрес KeServiceDescriptorTableShadow, находит главный поток винлогона и в нем делает apc. Эта процедура уже и записывает по нужному смещению адрес моей ловушки, которая должна вывести текстовое сообщение и передать управление реальной функции. Но проблема в том, что как только я запускаю банальный кейлогер, система перезагружается и до моей ловушки дело вообще не доходит (я пробовал ее зациклить в выводе сообщений, результат прежний). В чем может быть проблема?
     
  2. spirom

    spirom New Member

    Публикаций:
    0
    Регистрация:
    18 авг 2010
    Сообщения:
    24
    Если как-то может помочь, то вот код. Я не силен в ассемблере и в С, поэтому прошу не судить строго). Здесь не предусмотрена передача управления реальной функции + нет возвращения в таблицу исходного адреса. Пока я пытаюсь сделать так, чтобы моей ловушке хотя бы передавалось управление...
    Код (Text):
    1. ;@echo off
    2. ;goto make
    3.  
    4. .386
    5. .model flat, stdcall
    6. option casemap:none
    7.  
    8. ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    9. ;                                  I N C L U D E   F I L E S                                        
    10. ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    11.  
    12. include \masm32\include\w2k\ntstatus.inc
    13. include \masm32\include\w2k\ntddk.inc
    14. include \masm32\include\w2k\ntoskrnl.inc
    15.  
    16. includelib \masm32\lib\w2k\ntoskrnl.lib
    17.  
    18. include \masm32\mProgs\Macros\Strings.mac
    19. include seh0.inc
    20. include common1.inc
    21. include ProcPath.asm
    22.  
    23. .data?
    24.  
    25. StartAPC KAPC <>
    26. StopAPC KAPC <>
    27. SDTShAdr DWORD ?
    28. FileNameOffset DWORD ?
    29. ThreadListHeadOffset DWORD ?
    30. PETHREAD DWORD ?
    31. CR0Reg DWORD ?
    32. TrueProcAddress DWORD ?
    33.  
    34. ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    35. ;                                         C O D E                                                  
    36. ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    37.  
    38. .code
    39.  
    40. NewHook proc Param1:DWORD, Param2:DWORD, Param3:DWORD, Param4:DWORD,Param5:DWORD, Param6:DWORD
    41.  
    42.     mov ecx, 0ffffffffh
    43.     .while ecx
    44.     dec ecx
    45.     invoke DbgPrint, $CTA0("...")
    46.     .endw
    47.     xor eax, eax
    48.     ret
    49.  
    50. NewHook endp
    51.  
    52. PatchSDTShadowTable proc Apc:PKAPC, NormalRoutine:PVOID, NormalContext:DWORD, SystemArgument1:DWORD, SystemArgument2:DWORD
    53.  
    54.     cli                
    55.     mov eax, cr0
    56.     mov CR0Reg,eax
    57.     and eax,0FFFEFFFFh     
    58.     mov cr0, eax  
    59.     mov eax, SDTShAdr
    60.     _try
    61.     add eax, 16
    62.     mov eax, [eax]
    63.     mov edx, [eax+225h*4]
    64.     mov TrueProcAddress, edx
    65.     mov [eax+225h*4], NewHook
    66.     _finally
    67.     mov eax,CR0Reg
    68.     mov cr0,eax
    69.     sti
    70.     invoke DbgPrint, $CTA0("Adress Table Pointer: %X\n"), TrueProcAddress
    71.     mov eax, 0
    72.     ret
    73.  
    74. PatchSDTShadowTable endp
    75.  
    76. UnPatchSDTShadowTable proc Apc:PKAPC, NormalRoutine:PVOID, NormalContext:DWORD, SystemArgument1:DWORD, SystemArgument2:DWORD
    77.  
    78.     ret
    79.  
    80. UnPatchSDTShadowTable endp
    81.  
    82.  
    83.  
    84. ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    85. ;                            GetServiceDescriptorTableShadowAddress                                
    86. ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    87.  
    88. GetServiceDescriptorTableShadowAddress proc uses esi edi ebx
    89.  
    90. local dwThreadId:DWORD
    91. local peThread:PVOID
    92. local dwCurThread:DWORD
    93. local TargetPeProcess:DWORD
    94. local PeProcessEntry:DWORD
    95. local us1:UNICODE_STRING
    96. local as1:ANSI_STRING
    97. local TargetPeThread:DWORD
    98. local peTHREAD:DWORD
    99. local flag:DWORD
    100.  
    101.     xor ebx, ebx                ; = NULL. Assume ServiceDescriptorTableShadow will be not found
    102.     mov flag, ebx
    103.  
    104.     mov eax, KeServiceDescriptorTable
    105.     mov esi, [eax]
    106.  
    107.     ; Find KTHREAD.ServiceTable field
    108.     ; For non-GUI threads this field == KeServiceDescriptorTable
    109.     ; and it points to ServiceDescriptorTable
    110.     ; For GUI threads
    111.     ; ServiceDescriptorTableShadow
    112.  
    113.     invoke KeGetCurrentThread
    114.     mov edi, 200h-4
    115.     .while edi
    116.         .break .if dword ptr [eax][edi] == esi
    117.         dec edi
    118.     .endw
    119.     push eax
    120.     invoke DbgPrint, $CTA0("KSDT Entry In PETHREAD: %X\n"), edi
    121.     pop eax
    122.     push eax
    123.     push esi
    124.     push edi   
    125.  
    126.     invoke PsGetCurrentProcess
    127.     push eax
    128.     invoke DbgPrint, $CTA0("Current process PEPROCESS: %X\n"), eax
    129.     pop ecx
    130.     invoke KeGetCurrentThread
    131.     mov edi, 200h-4
    132.     .while edi
    133.         .break .if dword ptr [eax][edi] == ecx
    134.         dec edi
    135.     .endw
    136.     mov PeProcessEntry, edi
    137.     invoke DbgPrint, $CTA0("PEPROCESS Entry In PETHREAD: %X\n"), edi
    138.  
    139.     invoke PsGetCurrentProcessId
    140.     invoke DbgPrint, $CTA0("Current process ID: %X\n"), eax
    141.     pop edi
    142.     pop esi
    143.     pop eax
    144.  
    145.     .if edi != 0
    146.         ; edi = offset to ServiceTable field in KTHREAD structure
    147.         mov dwThreadId, 080h
    148.         .while dwThreadId < 400h
    149.             push eax                    ; reserve DWORD on stack
    150.             invoke PsLookupThreadByThreadId, dwThreadId, esp
    151.             pop ecx                     ; -> ETHREAD/KTHREAD
    152.             mov peThread,ecx
    153.             .if eax == STATUS_SUCCESS
    154.                 push esi
    155.                 push edi
    156.                 mov ecx, peThread
    157.                 mov edi, PeProcessEntry
    158.                 push dword ptr [ecx][edi]
    159.                 pop esi
    160.                 mov TargetPeProcess, esi
    161.                 pop edi
    162.                 pop esi
    163.                 push dword ptr [ecx][edi]
    164.                 ;fastcall ObfDereferenceObject, ecx
    165.                 pop eax
    166.                 .if eax != esi
    167.                     mov edx, MmSystemRangeStart
    168.                     mov edx, [edx]
    169.                     mov edx, [edx]
    170.                     .if eax > edx       ; some stupid error checking
    171.                         push eax
    172.                         push ecx
    173.                         push esi
    174.                         push edi
    175.                         ;mov ecx, peThread
    176.                         ;mov edi, PeProcessEntry
    177.                         ;push dword ptr [ecx][edi]
    178.                         ;pop esi
    179.                         ;mov TargetPeProcess, esi
    180.                         push eax
    181.                         invoke GetImageFilePath, TargetPeProcess, addr us1     
    182.                         .if eax==STATUS_SUCCESS
    183.                         invoke RtlUnicodeStringToAnsiString,addr as1,addr us1,TRUE
    184.                         invoke DbgPrint,as1.Buffer
    185.                         invoke ExFreePool,us1.Buffer   
    186.                         invoke RtlFreeAnsiString,addr as1  
    187.                         .endif
    188.                         invoke DbgPrint, $CTA0("Target Process PEPROCESS: %X\n"), TargetPeProcess
    189.                         mov eax, TargetPeProcess
    190.                         add eax, FileNameOffset
    191.                         invoke _strnicmp, eax, $CTA0("winlogon.exe"), 12
    192.                         .if eax == NULL
    193.                         invoke DbgPrint, $CTA0("Found")
    194.                         mov ecx, peThread
    195.                         mov TargetPeThread, ecx
    196.                         mov eax, TargetPeProcess
    197.                         add eax, ThreadListHeadOffset
    198.                         mov eax, (LIST_ENTRY PTR [eax]).Flink
    199.                         sub eax, 22Ch
    200.                         mov PETHREAD, eax
    201.                         invoke DbgPrint, $CTA0("FirstThread: %X\n"), eax
    202.                         inc flag
    203.                         .endif
    204.                         pop eax
    205.                         mov ebx, eax
    206.                         mov SDTShAdr,ebx
    207.                         invoke DbgPrint, $CTA0("FindShadowTable: Found in thread with ID: %X\n"), dwThreadId
    208.                         mov ecx, peThread
    209.                         fastcall ObfDereferenceObject, ecx
    210.                         pop edi
    211.                         pop esi
    212.                         pop ecx
    213.                         pop eax
    214.                         .break .if flag
    215.                     .endif
    216.                 .endif
    217.             .endif
    218.             add dwThreadId, 4
    219.         .endw
    220.     .endif
    221.  
    222.  
    223.     ;mov ecx, peThread
    224.     ;fastcall ObfDereferenceObject, ecx
    225.     mov ebx, SDTShAdr
    226.     mov eax, ebx
    227.     ret
    228.  
    229. GetServiceDescriptorTableShadowAddress endp
    230.  
    231.  
    232. GetImageFileNameOffset proc uses esi ebx
    233.  
    234. ; Finds EPROCESS.ImageFileName field offset
    235.  
    236. ; W2K       EPROCESS.ImageFileName = 01FCh
    237. ; WXP       EPROCESS.ImageFileName = 0174h
    238. ; WNET      EPROCESS.ImageFileName = 0154h
    239.  
    240. ; Instead of hardcoding above offsets we just scan
    241. ; the EPROCESS structure of System process one page down.
    242. ; It's well-known trick.
    243.  
    244.     invoke IoGetCurrentProcess
    245.     mov esi, eax
    246.  
    247.     xor ebx, ebx
    248.     .while ebx < 1000h          ; one page more than enough.
    249.         ; Case insensitive compare.
    250.         lea eax, [esi+ebx]
    251.         invoke _strnicmp, eax, $CTA0("system"), 6
    252.         .break .if eax == 0
    253.         inc ebx
    254.     .endw
    255.  
    256.     .if eax == 0
    257.         ; Found.
    258.         mov eax, ebx
    259.     .else
    260.         ; Not found.
    261.         xor eax, eax
    262.     .endif
    263.  
    264.     ret
    265.  
    266. GetImageFileNameOffset endp
    267.  
    268. ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    269. ;                                       DriverEntry                                                
    270. ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    271.  
    272. DriverEntry proc pDriverObject:PDRIVER_OBJECT, pusRegistryPath:PUNICODE_STRING
    273.  
    274.     invoke DbgPrint, $CTA0("\nFindShadowTable: Entering DriverEntry\n")
    275.  
    276.     invoke GetImageFileNameOffset
    277.     mov FileNameOffset, eax
    278.     invoke DbgPrint, $CTA0("ImageFileNameOffset: %X\n"), eax
    279.  
    280.     mov eax, 190h
    281.     sub eax, 174h
    282.     add eax, FileNameOffset
    283.     mov ThreadListHeadOffset, eax
    284.     invoke DbgPrint, $CTA0("ThreadListHeadOffset: %X\n"), eax  
    285.        
    286.     mov eax, KeServiceDescriptorTable
    287.     mov eax, [eax]
    288.     invoke DbgPrint, $CTA0("FindShadowTable: ServiceDescriptorTable at address: %08X\n"), eax
    289.  
    290.     _try
    291.     lea eax, KeServiceDescriptorTable
    292.     mov eax, [eax]
    293.     ;add eax, 16
    294.     mov eax, [eax]
    295.     mov eax, [eax+225h*4]
    296.     _finally
    297.     invoke DbgPrint, $CTA0("FindShadowTable: ServiceDescriptorTable at address: %08X\n"), eax
    298.  
    299.     _try
    300.     lea eax, KeServiceDescriptorTable
    301.     mov eax, [eax]
    302.     ;add eax, 16
    303.     mov eax, [eax]
    304.     mov eax, [eax+125h*4]
    305.     _finally
    306.     invoke DbgPrint, $CTA0("FindShadowTable: ServiceDescriptorTable at address: %08X\n"), eax
    307.  
    308.     invoke GetServiceDescriptorTableShadowAddress
    309.     .if eax != NULL
    310.         invoke DbgPrint, $CTA0("FindShadowTable: ServiceDescriptorTableShadow found at address: %08X\n"), eax
    311.     .endif
    312.  
    313.     invoke KeInitializeApc, addr StartAPC, PETHREAD, 0, PatchSDTShadowTable, NULL, NULL, NULL, NULL
    314.     invoke KeInsertQueueApc, addr StartAPC, NULL, NULL, 0  
    315.  
    316.     invoke DbgPrint, $CTA0("FindShadowTable: Leaving DriverEntry\n")
    317.  
    318.     mov eax, STATUS_DEVICE_CONFIGURATION_ERROR
    319.     ret
    320.  
    321. DriverEntry endp
    322.  
    323. ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    324. ;                                                                                                  
    325. ;:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    326.  
    327. end DriverEntry
    328.  
    329. :make
    330.  
    331. set drv=FindShadowTable
    332.  
    333. \masm32\bin\ml /nologo /c /coff %drv%.bat
    334. \masm32\bin\link /nologo /driver /base:0x10000 /align:32 /out:%drv%.sys /subsystem:native %drv%.obj
    335.  
    336. del %drv%.obj
    337.  
    338. echo.
    339. pause
     
  3. spirom

    spirom New Member

    Публикаций:
    0
    Регистрация:
    18 авг 2010
    Сообщения:
    24
    P. s. Это немного измененный GetShadowTable, автором которого является Four-F.
     
  4. spirom

    spirom New Member

    Публикаций:
    0
    Регистрация:
    18 авг 2010
    Сообщения:
    24
    Неужели никто не писал подобные вещи?! Гугл дает только примеры на С (который я не очень перевариваю...). Пытался перевести на асм, но результат прежний(
     
  5. TSS

    TSS New Member

    Публикаций:
    0
    Регистрация:
    13 апр 2009
    Сообщения:
    494
    spirom
    Недостаточный уровень знаний (точнее нулевой), Вам в commerce.
     
  6. spirom

    spirom New Member

    Публикаций:
    0
    Регистрация:
    18 авг 2010
    Сообщения:
    24
    TSS
    Мой уровень знаний действительно недостаточен (я упоминал выше), но он не может быть нулевым... Как мне кажется, вопросы задают для того, чтобы те, кому есть что сказать, помогли решить проблему, а не указывали на уровень знаний задавшего этот вопрос. Прошу прощения конечно, без наездов, а Вам так случайно не кажется?!
     
  7. TSS

    TSS New Member

    Публикаций:
    0
    Регистрация:
    13 апр 2009
    Сообщения:
    494
    Начал смотреть, написал скрипт для перечисления потоков:

    Код (Text):
    1. .echo Find process:
    2.  
    3. r $t0 = nt!PsActiveProcessHead
    4.  
    5. .for (r $t1 = poi(@$t0); (@$t1 != 0) & (@$t1 != @$t0); r $t1 = poi(@$t1))
    6. {
    7.     r? $t2 = #CONTAINING_RECORD(@$t1, nt!_EPROCESS, ActiveProcessLinks);
    8.  
    9.     as /x ${/v:$Procc} @$t2
    10.     as /ma ${/v:$ImageName} @@c++(&@$t2->ImageFileName[0])
    11.  
    12.     .block
    13.     {
    14.         .if ( $scmp( "${$ImageName}", "winlogon.exe" ) == 0 )
    15.         {
    16.             .echo ${$ImageName} at ${$Procc}
    17.             .echo "      KTHREAD               Tid      Alertable"
    18.  
    19.             r? $t3 = (nt!_LIST_ENTRY *)&@$t2->ThreadListHead;
    20.  
    21.             .for (r $t4 = poi(@$t3); (@$t4 != 0) & (@$t4 != @$t3); r $t4 = poi(@$t4))
    22.             {
    23.                 r? $t5 = #CONTAINING_RECORD(@$t4, nt!_ETHREAD, ThreadListEntry)
    24.  
    25.                 r? $t6 = @$t5->Cid
    26.                 r? $t6 = (nt!_CLIENT_ID *)&@$t6
    27.                 r $t6 = @@c++(@$t6->UniqueThread)
    28.  
    29.                 r? $t7 = (nt!_KTHREAD *)@$t5
    30.                 r $t8 = @@c++(@$t7->Alertable)
    31.  
    32.                 as /x ${/v:$Kthread} @$t7
    33.                 as /x ${/v:$Tid} @$t6
    34.                 as /x ${/v:$Alertable} @$t8
    35.  
    36.                 .block
    37.                 {
    38.                     .echo ${$Kthread}      ${$Tid}        ${$Alertable}
    39.                 }
    40.  
    41.                 ad ${/v:$Kthread}
    42.                 ad ${/v:$Tid}
    43.                 ad ${/v:$Alertable}
    44.             }
    45.  
    46.             ad ${/v:$ImageName}
    47.             ad ${/v:$Procc}
    48.  
    49.             .break
    50.         }
    51.     }
    52.  
    53.     ad ${/v:$ImageName}
    54.     ad ${/v:$Procc}
    55. }
    Таки да, есть у winlogon потоки которым можно apc послать, потом глянул код, в драйвере(!) шлется apc винлогонуЮ, чтобы пропатчить shadow sdt(ранее вычисленный адрес таблицы благополучно оставляется в забытьи) вобщем бредокод скопипащенный откудато, автор не мучай себя и обитателей сего форума, в коммерц дружище, в коммерц :)
     
  8. spirom

    spirom New Member

    Публикаций:
    0
    Регистрация:
    18 авг 2010
    Сообщения:
    24
    Да нет, с адресом таблицы как раз все в порядке+адрес реальной функции, считываемый внутри апц является действительным адресом внутри вин32к!
     
  9. spirom

    spirom New Member

    Публикаций:
    0
    Регистрация:
    18 авг 2010
    Сообщения:
    24
    Проблема в том, что как только на месте реального адреса оказывается адрес моей ловушки, то система через некоторое время падает...
     
  10. TSS

    TSS New Member

    Публикаций:
    0
    Регистрация:
    13 апр 2009
    Сообщения:
    494
    Еще бы, драйвер то выгружен.
     
  11. spirom

    spirom New Member

    Публикаций:
    0
    Регистрация:
    18 авг 2010
    Сообщения:
    24
    Ох... Да, теперь я должен согласиться
     
  12. spirom

    spirom New Member

    Публикаций:
    0
    Регистрация:
    18 авг 2010
    Сообщения:
    24
    Я забыл исправить STATUS_DEVICE_CONFIGURATION_ERROR на STATUS_SUCCESS. Что ж, и такое бывает... Спасибо