Логика работы INT3 в Anti-Debugging

Тема в разделе "WASM.BEGINNERS", создана пользователем SGWW, 23 апр 2020.

  1. SGWW

    SGWW New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2020
    Сообщения:
    11
    Всем привет!

    Есть у меня crackme где есть вот такой код:

    Код (Text):
    1.  
    2. 0040B051   56               PUSH ESI
    3. 0040B052   51               PUSH ECX
    4. 0040B053   50               PUSH EAX
    5. 0040B054   8D75 87          LEA ESI,DWORD PTR SS:[EBP-79]
    6. 0040B057   B9 B1000000      MOV ECX,0B1
    7. 0040B05C   0FB6440E FF      MOVZX EAX,BYTE PTR DS:[ESI+ECX-1]
    8. 0040B061   03D8             ADD EBX,EAX
    9. 0040B063   C1CB 04          ROR EBX,4
    10. 0040B066   03D9             ADD EBX,ECX
    11. 0040B068  ^E2 F2            LOOPD SHORT fp2.0040B05C
    12. 0040B06A   58               POP EAX
    13. 0040B06B   59               POP ECX
    14. 0040B06C   5E               POP ESI
    15. 0040B06D   C3               RETN
    16. 0040B06E   64:67:FF36 0000  PUSH DWORD PTR FS:[0]
    17. 0040B074   64:67:8926 0000  MOV DWORD PTR FS:[0],ESP
    18. 0040B07A   E8 00000000      CALL fp2.0040B07F
    19. 0040B07F   5D               POP EBP
    20. 0040B080   8D7D 3B          LEA EDI,DWORD PTR SS:[EBP+3B]
    21. 0040B083   8B5D CE          MOV EBX,DWORD PTR SS:[EBP-32]
    22. 0040B086   CC               INT3                                     ; INT3 anti-debug
    23. 0040B087   E8 C5FFFFFF      CALL fp2.0040B051                        ; being debugged
    24. 0040B08C   B9 EE010000      MOV ECX,1EE                              ; not being debugged
    25. 0040B091   F7C1 0F000000    TEST ECX,0F
    26. 0040B097   75 10            JNZ SHORT fp2.0040B0A9                   ; jump if ZF = 0
    27. 0040B099   9C               PUSHFD
    28. 0040B09A   810C24 00010000  OR DWORD PTR SS:[ESP],100
    29. 0040B0A1   9D               POPFD
    30. 0040B0A2   90               NOP
    31. 0040B0A3   90               NOP
    32. 0040B0A4   E8 A8FFFFFF      CALL fp2.0040B051
    33. 0040B0A9   D3C3             ROL EBX,CL
    34. 0040B0AB   305C0F FF        XOR BYTE PTR DS:[EDI+ECX-1],BL           ; PTR 40B2A7 - for first iteration
    35. 0040B0AF  ^E2 E0            LOOPD SHORT fp2.0040B091                 ; Loop while equal, after this loop code is decrypted
    36.  
    Насколько я понимаю, CALL fp2.0040B051 выполняется только в случае если программу дебажат.
    Чтобы обойти этот момент я пробовал занопить INT3 и CALL fp2.0040B051, однако если сохраняю эти изменения на диск, то crackme перестает работать.

    Далее я попробовал установить в настроках Olly "Ignore (pass to program) following exception: INT3 breaks". Правильно ли я понимаю, что благодаря этой опции crackme сам будет обрабатывть CC opcode и не поймет, что его дебажат?

    В таком случае получается, что после Step Into (F7) в 0040B086

    EIP становится 0040B0A3
    а вот если F8 то EIP -> 0040B08C

    Откуда такое разное поведение и как оно работает на самом деле? Спасибо за помощь

    PS файл crackme приложил
    PPS Использую OllyDgb v1.10
     

    Вложения:

    • fp2_original.7z
      Размер файла:
      21,6 КБ
      Просмотров:
      269
  2. SGWW

    SGWW New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2020
    Сообщения:
    11
    Я немного продвинулся в понимании этого кода, получается, что в

    Код (Text):
    1. 0040B06E   64:67:FF36 0000  PUSH DWORD PTR FS:[0]
    2. 0040B074   64:67:8926 0000  MOV DWORD PTR FS:[0],ESP                 ;  new SEH exception
    Добавляется новая запись в SEH, в stack это выглядит как

    Код (Text):
    1. 0019FF4C   0019FFCC  Pointer to next SEH record
    2. 0019FF50   0040B006  SE handler
    И когда случается INT3 прерывание, то управление должно переходить по адресу 0040B006 (должно ли?)

    Правда в отладчике этого не происходит, что меня совсем запутало ((
     
  3. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    875
    В коде устанавливается SEH обработчик по адресу 0040B006, по этому адресу содержится код который проверяет код исключения должен быть
    EXCEPTION_BREAKPOINT или EXCEPTION_SINGLE_STEP. Если исключение EXCEPTION_BREAKPOINT то обработчик обнуляет DWORD по адресу 0040B04D. Далее идет дешифровка тела основного кода на основе функции расчета хеша (0040B051). Если продолжить исполнение без обработчика ошибки то DWORD (0040B04D) не обнулится и хеш будет неверный. Для передачи управления обработчику необходимо к примеру нажать Ctrl+F9. Далее есть еще место где генерируется исключение EXCEPTION_SINGLE_STEP через POPFD, этот обработчик также изменяет DWORD (0040B04D), что влияет на хеш. Чтобы декодировать код можно просто поставить хардварный бряк на 0040B0B1 и пропускать все исключения.
     
  4. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    SGWW,

    Вот активность семпла. Посмотри где в реестре ключ через процмон или через отладчик, на сервис останов.
     

    Вложения:

    • fp2.png
      fp2.png
      Размер файла:
      19,1 КБ
      Просмотров:
      265
  5. SGWW

    SGWW New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2020
    Сообщения:
    11
    Thetrik, спасибо большое за пояснение, очень помогло.
    --- Сообщение объединено, 24 апр 2020 ---
    Indy_, спасибо, похоже в реесте должен находиться ключ с помощью которого расшифровывается код который и показывает ,что crackme успешно решен.
    Но как подобрать этот ключ, ведь нам неизвестно какой код зашифрован, а известно только что он рабочий.

    Немного облегчило ситуацию следующая часть

    Код (Text):
    1. 0040B140   E8 3C000000      CALL fp2.0040B181                        ; Key retrival?
    2. 0040B145   85C0             TEST EAX,EAX                             ; EAX should be zero, EAX = EBX from CALL 0040B181
    3. 0040B147   0F85 DD000000    JNZ fp2.0040B22A                         ; If jump -> wrong key message
    4. 0040B14D   85C9             TEST ECX,ECX                             ; ECX should be zero
    5. 0040B14F   0F85 D5000000    JNZ fp2.0040B22A
    CALL fp2.0040B181 как раз генерирует EAX и ECX на основе того значения ключа который берется из реестра.
    Я думаю нужно пербрать все возможные значения и найти такое при котором EAX = ECX = 0x0
    --- Сообщение объединено, 24 апр 2020 ---
    А тут еще и анти дебаг на основе RDTSC есть красота
    0040B1D8 0F31 RDTSC ; rdtsc anti-debuggin
     
  6. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    SGWW,

    Крэкми нужен для тебя, не для решения. Могу найти автоматикой решение, но зачем. Это всё для обучения, что бы поработать с окружением.

    > 0040B1D8 0F31 RDTSC ; rdtsc anti-debugging

    занопь.
     
  7. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    875
    Ключ легко подобрать перебором. Просто извлечь процедуру подсчета и написать код перебора. Просто извлек процедуру в decrypt.bin и написал процедуру перебора (FASM):
    Код (ASM):
    1. format PE
    2.  
    3. mov edi, 0
    4. .next:
    5. push edi
    6. push 0x2FB8813C
    7. push 0x3C9DB5D6
    8. call calc
    9. test eax, eax
    10. jne @f
    11. test ecx, ecx
    12. jne @f
    13. int 3
    14. @@: inc edi
    15. jmp .next
    16.  
    17. calc:
    18. file "decrypt.bin"
    19.                            
    Через несколько минут упал на бряке, ключ 459f6937 должен лежать в HKCU\Software\Aalto раздел FP2KEY тип REG_DWORD.
    upload_2020-4-24_21-14-24.png
     
    Indy_ нравится это.
  8. SGWW

    SGWW New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2020
    Сообщения:
    11
    Thetrik, я тоже сделал перебор, но только на питоне, выглядит вот так:

    Код (Text):
    1. ESI = 0x00000000
    2. ECX = 0x2FB8813C
    3. EBX = 0x3C9DB5D6
    4.  
    5.  
    6. # yep, this is a brute-force
    7. for ESI in range(0x459f6937, 0x0,-1):
    8.  
    9.     ECX = 0x2FB8813C
    10.     EBX = 0x3C9DB5D6
    11.     EAX = 0xC6EF3720
    12.     EDI = 0x9E3779B9
    13.     EDX = 0x0
    14.     i = 0x20
    15.  
    16.     while i > 0:
    17.  
    18.         """
    19.         MOV EDX, EBX
    20.         SHL EDX,4
    21.         SUB ECX,EDX
    22.         """
    23.  
    24.         ECX = ECX - ((EBX << 4) & 0xFFFFFFFF)& 0xFFFFFFFF
    25.         # print(hex(ECX).upper())
    26.  
    27.         """
    28.         MOV EDX,ESI
    29.         XOR EDX,EBX
    30.         """
    31.  
    32.         EDX = (ESI ^ EBX) & 0xFFFFFFFF
    33.         # print(hex(EDX).upper())
    34.  
    35.         """
    36.         SUB ECX, EDX
    37.         """
    38.  
    39.         ECX = (ECX - EDX) & 0xFFFFFFFF
    40.         # print(hex(ECX).upper())
    41.  
    42.         """
    43.         MOV EDX,EBX
    44.         SHR EDX,5
    45.         XOR EDX,EAX
    46.         """
    47.  
    48.         EDX = (((EBX >> 5) & 0xFFFFFFFF) ^ EAX) & 0xFFFFFFFF
    49.         # print(hex(EDX).upper())
    50.  
    51.         """
    52.         SUB ECX,EDX
    53.         """
    54.  
    55.         ECX = (ECX - EDX) & 0xFFFFFFFF
    56.         # print(hex(ECX).upper())
    57.  
    58.         """
    59.         SUB ECX, ESI
    60.         """
    61.  
    62.         ECX = (ECX - ESI) & 0xFFFFFFFF
    63.         # print(hex(ECX).upper())
    64.  
    65.  
    66.         """
    67.         MOV EDX, ECX
    68.         SHL EDX,4
    69.         """
    70.  
    71.         EDX = (ECX << 4) & 0xFFFFFFFF
    72.         # print(hex(EDX).upper())
    73.  
    74.  
    75.         """
    76.         SUB EBX, EDX
    77.         """
    78.  
    79.         EBX = (EBX - EDX) & 0xFFFFFFFF
    80.         # print(hex(EBX).upper())
    81.  
    82.  
    83.         """
    84.         MOV EDX, ESI
    85.         XOR EDX, ECX
    86.         """
    87.  
    88.         EDX = (ESI ^ ECX) & 0xFFFFFFFF
    89.         # print(hex(EDX).upper())
    90.  
    91.  
    92.         """
    93.         SUB EBX,EDX
    94.         """
    95.  
    96.         EBX = (EBX - EDX) & 0xFFFFFFFF
    97.         # print(hex(EBX).upper())
    98.  
    99.         """
    100.         MOV EDX, ECX
    101.         SHR EDX,5
    102.         """
    103.  
    104.         EDX = (ECX >> 5) & 0xFFFFFFFF
    105.         # print(hex(EDX).upper())
    106.  
    107.         """
    108.         XOR EDX, EAX
    109.         """
    110.  
    111.         EDX = (EDX ^ EAX) & 0xFFFFFFFF
    112.         # print(hex(EDX).upper())
    113.  
    114.         """
    115.         SUB EBX,EDX
    116.         """
    117.  
    118.         EBX = (EBX - EDX) & 0xFFFFFFFF
    119.         # print(hex(EDX).upper())
    120.  
    121.         """
    122.         SUB EBX, ESI
    123.         """
    124.  
    125.         EBX = (EBX - ESI) & 0xFFFFFFFF
    126.         # print(hex(EBX).upper())
    127.  
    128.         """
    129.         Sub EAX, EDI
    130.         """
    131.  
    132.         EAX = (EAX - EDI) & 0xFFFFFFFF
    133.         # print(hex(EAX).upper())
    134.  
    135.  
    136.         """  
    137.         print("Iteration :", i)
    138.         print("EBX: ",hex(EBX).upper())
    139.         print("ECX: ",hex(ECX).upper())
    140.         print("ESI: ",hex(ESI).upper())
    141.         print("EAX: ",hex(EAX).upper())
    142.         print("EDI: ",hex(EDI).upper())
    143.         """
    144.  
    145.         i = i - 1;
    146.  
    147.     if ESI % 10000000 == 0:
    148.         print(hex(ESI).upper())
    149.  
    150.     if EBX == 0x0:
    151.         print("This is the right key ", hex(ESI).upper())
    152.         break
    Всю ночь считало))

    Большое вам спасибо за советы@Thetrik, Indy_,
     
  9. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    SGWW,

    Ну и какой смысл, ты ничего не узнал а тупо подобрал ключ. Это не решение.
     
  10. SGWW

    SGWW New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2020
    Сообщения:
    11
    Indy_, ты шутишь, я два дня с этим crackme сидел и разбирался в куче механик, узнал как работает SEH и как установить свои обработчик исключений, логику работы INT3, узнал что RDTSC может использоваться как анти-дебаг. В конце концов я полностью разобрался в том как сделан первый стаб и почему поначалу код расшифровывался не корректно, в чем мне помог Thetrik. Что ключ храниться в реестре стало сразу очевидно после работы первого стаба, так как в расшифрованном коде есть обращения к RegOpenKeyExW и RegQueryValueExW.

    Возможно подбор на питоне не самая изящная вещь и в следующий раз я постараюсь использовать ASM, но как если не перебором найти этот ключ?
     
  11. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    352
    Шутит, щутит - Инди, вообще, любитель пошутить. :) А, вообще, тред получился неплохой, многим новичкам будет интересно. Я даже вспомнил какую-то статью К. Касперски, где я подставлял через FS свой адрес и программа на исключении, перескакивала туда, а отладчик на этом месте "спотыкался". Правда, это было чуть проще, чем в этом треде, но все же родственная тема. Сюда бы еще дополнение SReg'а с exelab'а добавить и, вообще, тема была бы полностью раскрытой. На exelab'е был же, вроде, подобный вопрос?

    P.S. За саму методику объяснения, я бы поставил Indy_ тройку, а Thetrik пятерку (по пятибальной системе). Ждем новых тем и объяснений. :)
     
  12. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    SGWW,

    Но ты ничего не написал, что узнал из семпла. Тебе дали место для брута, цель же не ключ. Такие простые крэкми это обучающий материал для самостоятельной работы, а не для конечного решения. Если же брут, то можно решить так - создать карту исполнения(кэш инструкций для обнаружения новой обработки, кл пока не доступен я бы ссылку дал), выделить крипто функцию, затем на ней начать брутфорс. Это тупо автоматическое решение.
     
  13. SGWW

    SGWW New Member

    Публикаций:
    0
    Регистрация:
    28 мар 2020
    Сообщения:
    11
    extravert, да был вопрос, но у меня что-то exelab не открывается, сервер не отвечает, поэтому не могу сказать что там ответили.
    Indy_, тут же главное понять, что именно нужно брутфорсить, а это целая история. А как создать эту карту исполнений, с помощью какого инструмента?
     
  14. GRAFik

    GRAFik Active Member

    Публикаций:
    0
    Регистрация:
    14 мар 2020
    Сообщения:
    352
    Так ведь режим самоизоляции же, поэтому БэдГай и все его модераторы, кроме одного, - уехали на шашлыки, от греха подальше и во имя спасения exelab'а. Коронавирус - это же такая зараза, что и сайт может сожрать и не подавиться. :)