Помогите найти косяк

Тема в разделе "WASM.ASSEMBLER", создана пользователем FakeMan, 6 ноя 2008.

  1. FakeMan

    FakeMan New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    17
    Доброго времени суток.
    Вот выдалось немного свободного времени и я решил поэксперементировать с патчингом DLL
    Изрядно покурив маны, получилось что-то вроде этого.
    Код (Text):
    1. use32
    2.  
    3. API_NUMS equ 2h     ; - Количество необходимых нам функций
    4.  
    5. Delta:               ; Entry Point
    6.  pushad ; 1 Байт
    7.  pushf ; 1 байт
    8.  
    9.   ;--- определение _dwReason
    10.   cmp dword [ebp+10h],01h ;  4 Б
    11.   jne _Exit               ;  2 Б
    12.  
    13.   call $+5
    14.   pop edx            ; Находим дельта смещение
    15.   sub edx, 11h
    16. ;  xor edx, edx
    17. ;  mov edx, ebx
    18.  
    19.   push edx           ; Для работы блока. Кладем в стек адрес дельта смещения
    20.  
    21. ;------------------- "БЛОК" поиска АПИ функций по ХЕШ значениям ----------------------------------------
    22.  
    23. _ReadSEH:
    24.   xor edx,edx      ; EDX=0
    25.   db 64h,8Bh,02h   ;mov eax,FS:[edx]- EAX=Указатель на 1st SEH
    26.   dec edx          ; EDX=FFFFFFFFh  - Маркировка последнего SEH (Kernel)
    27.  
    28. _SrchKernelSEH:
    29.   cmp [eax],edx       ; IF 1st SEH=SEH(Kernel)
    30.   je _GetAddrInK      ; TRUE  находим  Kernel Base
    31.   mov eax,dword [eax] ; FALSE указатель Next SEH
    32.   jmp _SrchKernelSEH  ; Цикл "поиск SEH(Kernel)"
    33.  
    34. _GetAddrInK:
    35.   mov eax,[eax+4]     ; Адресс ExepProc(Kernel) в SEH
    36.   xor ax,ax           ; Кратно 64кб = 10000h
    37.  
    38. _SearchMZ:
    39.   mov edx,[eax]        ; EDX=DWORD [начало страницы (Kernel)]
    40.   cmp dx,5A4Dh  ; "MZ" ; Если WORD<>"MZ"
    41.   jne _ContinueSearchMZ; TRUE Kernel База Найдена
    42.   xor ecx, ecx         ; проверка на кол-во этов в таблице импорта
    43.   mov ecx, [eax+3Ch]   ;
    44.   add ecx, 84h         ;
    45.   cmp dword [eax+ecx], 0h ; Если 0 значит мы в Ntdll.dll
    46.   jne _CheckPE         ; <> 0 Проверим PE
    47. _ContinueSearchMZ:
    48.   sub eax,10000h       ; EAX=EAX-10000h (След Страница)
    49.   jmp _SearchMZ        ; Цикл "поиск KernelBase"
    50.  
    51. _CheckPE:
    52.   xor edx,edx          ; Дополнительная проверка
    53.   mov edx,[eax+3Ch]    ; Кернела на формат PE EXE
    54.   cmp dword [eax+edx],4550h  ; "PE"
    55.   jne _ApiErrorExit    ; КРАХ! ВЫХОД!
    56.  
    57. _SearchAPI:
    58.   mov esi,[eax+edx+78h]         ; ESI=Export Table RVA (смещение от Base)
    59.   add esi,eax                   ; ESI=ESI+KernelBase -- Указатель Export Table
    60.   add esi,18h                   ; Указатель на (Num of Name Pointers)
    61.   xchg eax,ebx                  ;  EBX = KERNEL BASE
    62.   lodsd
    63.   push eax                      ; Num of Name Pointers DWORD [+18h]
    64.   lodsd
    65.   push eax                      ; Address Table RVA    DWORD [+1Ch]
    66.   lodsd
    67.   push eax                      ; Name Pointers RVA    DWORD [+20h]
    68.   ;mov eax,[esp+4*1]
    69.   add eax,ebx                   ; EAX=EAX+KERNEL BASE
    70.   push eax                      ; EAX= Index (Name Pointers VA)
    71.    lodsd
    72.   push eax                      ; Ordinal Table RVA    DWORD [+24h]
    73.  
    74.   mov edi,[esp+4*5]             ; Delta offset
    75.   lea edi, [edi+HashAPI-Delta]  ; EDI=HASH TABLE lea edi,[edi+HeshTable]
    76.   mov ebp,esp
    77.  
    78. _BeginSearch:
    79.   mov ecx,[ebp+4*4]             ; ECX=Кол-во Имен Функций (NumOfNamePointers)
    80.   xor edx,edx                   ; EDX=0
    81.  
    82. _SearchAPIName:
    83.   mov esi,[ebp+4*1]             ; ESI=STACK + 4
    84.   mov esi,[esi]                 ; ESI=Index RVA (Указатель на 1st API ASCII)
    85.   add esi,ebx                   ; ESI=Index VA (+ Kernel Base)
    86.  
    87. _GetHash:
    88.   xor  eax,eax                  ; EAX=0
    89.   push eax                      ; PUSH 0000h
    90.  
    91. _CalcHash:
    92.   ror  eax,7
    93.   xor dword [esp],eax
    94.   lodsb
    95.   test al,al
    96.   jnz _CalcHash
    97.   pop eax ; в eax ХЕШ
    98.  
    99. _OkHash:
    100.   cmp eax, dword [edi]
    101.   je _OkAPI
    102.   add dword [ebp+4*1],4h
    103.   inc edx
    104.   loop _SearchAPIName
    105.  
    106. _OkAPI:
    107.   shl edx,1h                ; номер функции
    108.   mov ecx,[ebp]             ; OrdinalTableRVA
    109.   add ecx,ebx
    110.   add ecx,edx
    111.   mov ecx,[ecx]
    112.   and ecx,0FFFFh
    113.   mov edx,[ebp+4*3]         ;AddressTableRVA
    114.   add edx,ebx
    115.   shl ecx,2h
    116.   add edx,ecx
    117.   mov edx,[edx]
    118.   add edx,ebx
    119.   push edx                  ; сохраняем адрес найденной функции стеке
    120.   cmp word [edi+4],0FFFFh   ; 0FFFFh-End of HeshTable
    121.   je _SearchEnd             ; следующее hash-значение функции
    122.   add edi,4
    123.  
    124. _NextName:
    125.   mov ecx,[ebp+4*2]             ;NamePointersRVA
    126.   add ecx,ebx
    127.   mov [ebp+4*1],ecx             ;Index в таблице имен
    128.   jmp  _BeginSearch
    129.  
    130. _SearchEnd:
    131.   mov edi,[esp+4*(5+API_NUMS)]             ; Delta offset
    132.   lea edi, [edi+AddrAPI-Delta]    ; EDI=HASH TABLE lea edi,[edi+HeshTable]
    133.   mov ecx,API_NUMS
    134.   _@loop:
    135.     pop eax
    136.     stosd
    137.   loop _@loop
    138.  
    139.  
    140.   mov edi,[esp+4*5]             ; Delta offset
    141.   add esp,4*5                   ; Восстанавливаем стек. Работа блока закончена
    142.  
    143. ;-------------
    144.  pop edx ;Берем из стека базовый адрес
    145.  
    146.  jmp _Exit; Для отладки, по началу думал что косяк где-то дальше по коду
    147.  
    148.  call [@GetCommandLineA + edx]
    149.  
    150.  ; -- поиск имени файла
    151.   mov esi, eax
    152. _SearchStart:
    153.   cmp byte [eax], '\'
    154.   jne _NextChar
    155.   lea esi, [eax + 1]
    156.   _NextChar:
    157.    inc eax
    158.    cmp byte [eax], '"'
    159.    je _GetHash2
    160.    cmp byte [eax], 0
    161.  jne _SearchStart
    162.  
    163. _GetHash2:
    164.   xor  eax,eax                  ; EAX=0
    165.   push eax                      ; PUSH 0000h
    166.  
    167. _CalcHash2:
    168.   ror  eax,7
    169.   xor dword [esp],eax
    170.   lodsb ; загрузка символа в AL
    171.   cmp al,'a'
    172.   jb _CheckChar
    173.   cmp al,'z'
    174.   ja _CheckChar
    175.   sub al, 20h
    176.  _CheckChar:
    177.   cmp byte al, '"'
    178.  jne _CalcHash2
    179.  pop eax                        ; в eax хеш
    180.  
    181.  ; ---- поиск хеша в таблице
    182.  lea edi, [HashProc + edx]
    183.  _@SearchLoop:
    184.   cmp eax, dword [edi]
    185.   je _Found
    186.   cmp word[edi + 4], 0FFFFh
    187.   je _Exit;
    188.   add edi, 4h
    189.  loop _@SearchLoop
    190.  
    191. _Found:
    192.  lea ebp, [libName + edx]
    193.  push ebp
    194.  call [@LoadLibraryA + edx];
    195.  jmp _Exit
    196.  
    197. _ApiErrorExit:
    198.  pop edx ; Ппц костыль
    199.  
    200. _Exit:
    201.   popf
    202.   popad
    203.   ;ret ;
    204.   jmp near 0 ;; <- адрес оригинальной точки входа
    205.  
    206. ;-------------------------- Таблица ХЕШей всех необходимых нам функций -------------------------
    207.  HashAPI:
    208.   dd 071E40722h  ; "LoadLibraryA"
    209.   dd 0FCFED34Ah  ; "GetCommandLineA"
    210.   dd 0FFFFh  ; EndOfHashTable      Конец таблицы. необходимо
    211.  
    212. ;------------------------ После выполнения блока эта таблица заполнится адресами функций. ------------
    213.  AddrAPI:
    214.   @GetCommandLineA     dd 0h
    215.   @LoadLibraryA        dd 0h
    216.  
    217. ; --------------------------------- Таблица ХЕШей имен процессов ---------------------------------
    218.  HashProc :
    219.   dd 0F2F32210h ; ShellDebug.exe
    220.   dd 0FFFFh ; EndOfHashTable
    221.  
    222.  libName db 'test.dll',0
    Все как обычно. Беру Dll, создаю секцию, меняю точку входа. Заручаю осел в оле. И... Вуаля! Все казалось бы работает.
    Но только до перезагрузки. После ребута система ( точнее explorer.exe ) начинает себя крайне неадекватно вести.
    Это еще более сильно раззадорило мой интерес. На какой подводный камень я наткнулся?
    Зы. Простите за кривой код, просто пока не знаю как лучше, я новичек в асме
     
  2. wsd

    wsd New Member

    Публикаций:
    0
    Регистрация:
    8 авг 2007
    Сообщения:
    2.824
    // офтоп
    Помогите найти косяк
    это как-же обкуриться надо, чтобы косяк потерять :)
     
  3. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    //оффтоп
    а чем плох метод получения базы kernel через PEB?
    mov eax, [fs:30h]
    mov eax, [eax+0ch]
    mov eax, [eax+1ch]
    mov eax, [eax+0]
    mov eax, [eax+08h]
     
  4. FakeMan

    FakeMan New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    17
    Вы хотите сказать что возникает ситуация когда я не получаю адрес базы kernel32. В таком случае все вызовы ф-й будут в никуда. ( Отсюда возможно эксцепшены и глюки. Хотя все проходит молча )
    Но этот код исключает возможность вызова ф-й kernela
    И всеравно ситуация не меняется
     
  5. PE_Kill

    PE_Kill New Member

    Публикаций:
    0
    Регистрация:
    16 янв 2006
    Сообщения:
    107
    А где инициализация ebp??
     
  6. CrystalIC

    CrystalIC New Member

    Публикаций:
    0
    Регистрация:
    26 июл 2008
    Сообщения:
    500
    GoldFinch
    Почему оффтоп ?
    Детский, ламерский способ - получение базы модуля из блока загрузчика.
    Альтернатива - анализ стекового фрейма в SEH при исключении.
     
  7. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    Регистрация:
    29 мар 2008
    Сообщения:
    1.775
    CrystalIC, так какие минусы у этого способа-то?
    Альтернатива - получение адреса в kernel32.dll из таблицы импорта зараженного модуля
     
  8. CrystalIC

    CrystalIC New Member

    Публикаций:
    0
    Регистрация:
    26 июл 2008
    Сообщения:
    500
    GoldFinch
    Какой импорт :lol: , отсылаю тебя изучать механизмы обработки исключений, зарегистрированная процедура(SEH) вызыватеся из модуля kernel32 посредством инструкции Call. Минусы - используется Ldr. Что это значит - гугли.
     
  9. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    упс. но вот тут вы обсуждаете хорошие грабли. дело в том, что не все виндовсы одинаковы полезны при таком подходе. я уже столкнулся с тем, что на висте SEH установлен не на процедуру из kernel'а!, а на ntdll проще получить базу по адресу возврата. Да и настоятельно рекомендую проверить хэш. дело в том, что простые способы хэширования имен API дают повторные результаты! (это еще одни недокументированные грабли, я лично проверял много способов, но самым лучшим считаю CRC32, он не простой, но с кодом CRC сливается очень даже не плохо, даже при дизассемблировании).
    +
    Код (Text):
    1. jmp near 0 ;; <- адрес оригинальной точки входа
    я вот только одного не наблюдаю. где исправляем 0 на адрес оригинальной точки входа?
     
  10. FakeMan

    FakeMan New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    17
    Эм.... Я патчу точку входа в DLL, которую вызывает загрузчик.

    Я написал простенькую программу, которая делает все сама )

    В отладчике все норм. Я исключил возможность вызова ф-й, следовательно на данном этапе это не имеет ровно никакого отношения к возникающему багу.

    Я исходил из соображений что в Win Xp Sp2-Sp3 ntdll.dll и kernel32.dll непременно присутствуют в ап процесса.
    Возникали ситуации когда в результате анализа SEH я оказывался в ntdll. Для этого реализована следующая проверка :
    Код (Text):
    1.   xor ecx, ecx         ; проверка на кол-во этов в таблице импорта
    2.   mov ecx, [eax+3Ch]   ;
    3.   add ecx, 84h         ;
    4.   cmp dword [eax+ecx], 0h ; Если 0 значит мы в Ntdll.dll
    5.   jne _CheckPE         ; <> 0 Проверим PE
    базирующаяся на определении кол-ва элементов таблицы импорта ( ntdll ничего не импортирует )

    Ps Хотелось бы уточнить суть проблеммы. Беру ws2_32 и патчу. Запускаю любой софт -- все работает, причем отладчик ( OllyDbg ) это подтверждает. Перезагружаюсь... И тут начинается самое интересмное. Очень долго запускается explorer.exe, пропадает возможность копипаста, на таскбаре не появляются окна... Вобщем глюки. Вопросс в том, какую ситуацию я не учел, что приводит к таким артефактам
     
  11. PE_Kill

    PE_Kill New Member

    Публикаций:
    0
    Регистрация:
    16 янв 2006
    Сообщения:
    107
    Т.е. ты патчишь сразу после команд?
    push ebp
    mov ebp, esp

    если нет, то лучше тогда дергать esp
     
  12. FakeMan

    FakeMan New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    17
    Pe заголовок я патчу
     
  13. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    FakeMan что значит сама. этого она точно не делает!
    спокойно может оказаться, что kernel выше чем ntdll или ито вовсе они не подряд расположены
     
  14. FakeMan

    FakeMan New Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    17
    И как же тогда быть?
     
  15. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    ищите имя dll в секции импорта/экспорте. да и в ntdll есть querysysteminformation - получай список модулей или LdrGetDllHandle!
     
  16. only

    only New Member

    Публикаций:
    0
    Регистрация:
    21 окт 2008
    Сообщения:
    147
    max7C4
    В импорте ее может и не быть.
     
  17. only

    only New Member

    Публикаций:
    0
    Регистрация:
    21 окт 2008
    Сообщения:
    147
    Вопрос к Клерку, но хотелось бы услышать и других, кто его поддерживает в этом.
    Почему?
    Возьмем к примеру ntdll
    База хранится там на постоянном месте.
    Можно и иначе получить, о какие минусы именно этого способа?
     
  18. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    only
    в системных библиотеках все ок.
     
  19. Quatre_R_Winner

    Quatre_R_Winner Member

    Публикаций:
    0
    Регистрация:
    10 ноя 2008
    Сообщения:
    66
    Я использую поиск через обработчик SEH. Естественно там может оказаться как ntdll (что обычное дело для NT) так и kernel32 (что обычное дело для 9x). Обе эти библиотеки обязательно что либо экспортируют (для того они и нужны собственно), а следовательно, у них есть блок экспорта (кстати не обязательно,что это отдельная секция - я данные, импорт и экспорт частенько сливаю в одну секцию для уменьшения объёма результирующего файла). В блоке экспорта обязательно должно быть имя этого модуля (у системных библиотек оно обязательно должно быть и совпадать с именем самого файла библиотеки) которое мы и используем для определения в какой мы библиотеке. Если мы угодили в ntdll то, как уже сказал max7C4, используем функцию LdrGetDllHandle для поиска kernel32 (правда там слегка специфический формат строк). Это у меня одинаково успешно работает и в 9x и в NT. Находить загрузочные базы библиотек через PEB быстро, но на совместимость влияет плохо (только NT и то не все) и защитное ПО такой подход ой как не любит. Сами модули могут располагаться в памяти как угодно (зависит от билда винды и от установленных заплаток и сервис-паков). Встречал случаи когда левые dll выбивали системные с их законных адресов. У меня ntdll ниже по адресам чем kernel32 и между ними ещё 5 модулей впихнуто. Для имён функций, ИМХО, лучший хэш, это CRC32. Вот такие дела.
     
  20. only

    only New Member

    Публикаций:
    0
    Регистрация:
    21 окт 2008
    Сообщения:
    147
    Например. Разве не все?
    9х это разве актуально? Я к тому что разве есть смысл беспокоиться о 9х?
    То есть это и не преимущество значит? Нет?
    В каком смысле?