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

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

  1. FakeMan

    FakeMan New Member

    Публикаций:
    0
    Доброго времени суток.
    Вот выдалось немного свободного времени и я решил поэксперементировать с патчингом 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
    // офтоп
    Помогите найти косяк
    это как-же обкуриться надо, чтобы косяк потерять :)
     
  3. GoldFinch

    GoldFinch New Member

    Публикаций:
    0
    //оффтоп
    а чем плох метод получения базы 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
    Вы хотите сказать что возникает ситуация когда я не получаю адрес базы kernel32. В таком случае все вызовы ф-й будут в никуда. ( Отсюда возможно эксцепшены и глюки. Хотя все проходит молча )
    Но этот код исключает возможность вызова ф-й kernela
    И всеравно ситуация не меняется
     
  5. PE_Kill

    PE_Kill New Member

    Публикаций:
    0
    А где инициализация ebp??
     
  6. CrystalIC

    CrystalIC New Member

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

    GoldFinch New Member

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

    CrystalIC New Member

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

    max7C4 New Member

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

    FakeMan New Member

    Публикаций:
    0
    Эм.... Я патчу точку входа в 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
    Т.е. ты патчишь сразу после команд?
    push ebp
    mov ebp, esp

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

    FakeMan New Member

    Публикаций:
    0
    Pe заголовок я патчу
     
  13. max7C4

    max7C4 New Member

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

    FakeMan New Member

    Публикаций:
    0
    И как же тогда быть?
     
  15. max7C4

    max7C4 New Member

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

    only New Member

    Публикаций:
    0
    max7C4
    В импорте ее может и не быть.
     
  17. only

    only New Member

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

    max7C4 New Member

    Публикаций:
    0
    only
    в системных библиотеках все ок.
     
  19. Quatre_R_Winner

    Quatre_R_Winner Member

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

    only New Member

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