Blog. Just Blog

Исследование защиты скринсейвера Zen Light

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Темная сторона Силы | Автор: ManHunter
Скриншот скринсейвера Zen Light
Скриншот скринсейвера Zen Light

Сегодня будем разбирать защиту скринсейвера Zen Light. Эта заставка показывает очень красивые световые эффекты вроде северного сияния. Цена программы невелика, но это точно не наш метод.

Забираем с офсайта дистрибутив, устанавливаем, открываем настройки экрана. При попытке зарегистрировать скринсейвер левыми данными, появляется вот такое сообщение:

Сообщение о неправильной регистрации
Сообщение о неправильной регистрации

Попытаемся найти какие-нибудь характерные строки. Увы, несмотря на то, что основной файл ничем не упакован, в файле этих строчек нет. Посмотрим ресурсы.

Зашифрованные строки в ресурсах
Зашифрованные строки в ресурсах

Вечер перестает быть томным. В строковых ресурсах обнаруживается большое количество неких данных, которые выглядят как зашифрованный текст. Логично предположить, что в коде должна быть процедура для их расшифровки. Отправляем файл в дизассемблер, затем поищем какие-нибудь манипуляции со строкой из ресурсов с наиболее приметным индексом 2018 или 7E2h в шестнадцатеричной системе счисления. Обнаружится следующий код:
  1. .text:00408257                 push    eax             ; hWnd
  2. .text:00408258                 call    ds:EnableWindow
  3. ; Индекс строки в ресурсах
  4. .text:0040825E                 push    7E2h
  5. ; Загрузить и расшифровать строку
  6. .text:00408263                 call    sub_466D10
  7. .text:00408268                 add     esp, 4
  8. .text:0040826B                 push    eax             ; lpString
  9. .text:0040826C                 push    437h            ; nIDDlgItem
  10. .text:00408271                 mov     eax, [ebp+hWnd]
  11. .text:00408274                 push    eax             ; hDlg
  12. ; Установить расшифрованный текст куда-то в диалоговое окно
  13. .text:00408275                 call    ds:SetDlgItemTextW
  14. .text:0040827B                 mov     byte_4E9478, 1
Посмотрим поближе процедуру расшифровки. За каким-то непонятным она реализована через код-переходник. Или компилятор так постарался при сборке, или намеренно было закручено в исходнике, не знаю.
  1. .text:00466D10 sub_466D10      proc near
  2. .text:00466D10                 push    ebp
  3. .text:00466D11                 mov     ebp, esp
  4. .text:00466D13                 pop     ebp
  5. .text:00466D14                 jmp     sub_465ED0
  6. .text:00466D14 sub_466D10      endp
  7. ...
  8. ...
  9. .text:00465ED0 sub_465ED0      proc near
  10. .text:00465ED0                 push    ebp
  11. .text:00465ED1                 mov     ebp, esp
  12. .text:00465ED3                 push    ecx
  13. .text:00465ED4                 movsx   eax, word_4EDFE0
  14. .text:00465EDB                 inc     eax
  15. .text:00465EDC                 and     eax, 80000001h
  16. .text:00465EE1                 push    esi
  17. .text:00465EE2                 jns     short loc_465EE9
  18. .text:00465EE4                 dec     eax
  19. .text:00465EE5                 or      eax, 0FFFFFFFEh
  20. .text:00465EE8                 inc     eax
  21. .text:00465EE9 loc_465EE9:
  22. .text:00465EE9                 mov     word_4EDFE0, ax
  23. .text:00465EEF                 cwde
  24. .text:00465EF0                 sub     eax, 0
  25. .text:00465EF3                 jz      short loc_465F1B
  26. .text:00465EF5                 dec     eax
  27. .text:00465EF6                 jnz     short loc_465F3E
  28. .text:00465EF8                 movzx   ecx, [ebp+arg_0]
  29. .text:00465EFC                 mov     edx, hInstance
  30. .text:00465F02                 push    0FFh            ; cchBufferMax
  31. .text:00465F07                 push    offset Buffer   ; lpBuffer
  32. .text:00465F0C                 push    ecx             ; uID
  33. .text:00465F0D                 push    edx             ; hInstance
  34. .text:00465F0E                 call    ds:LoadStringW
  35. .text:00465F14                 mov     esi, offset Buffer
  36. .text:00465F19                 jmp     short loc_465F41
  37. .text:00465F1B ; -------------------------------
  38. .text:00465F1B loc_465F1B:
  39. .text:00465F1B                 movzx   eax, [ebp+arg_0]
  40. .text:00465F1F                 mov     ecx, hInstance
  41. .text:00465F25                 push    0FFh            ; cchBufferMax
  42. .text:00465F2A                 push    offset word_4EDBE0 ; lpBuffer
  43. .text:00465F2F                 push    eax             ; uID
  44. .text:00465F30                 push    ecx             ; hInstance
  45. .text:00465F31                 call    ds:LoadStringW
  46. .text:00465F37                 mov     esi, offset word_4EDBE0
  47. .text:00465F3C                 jmp     short loc_465F41
  48. .text:00465F3E ; -------------------------------
  49. .text:00465F3E loc_465F3E:
  50. .text:00465F3E                 mov     esi, [ebp+var_4]
  51. .text:00465F41 loc_465F41:
  52. ; Проверка, начинается ли строка с символа "!"
  53. .text:00465F41                 cmp     word ptr [esi], 21h
  54. ; Если нет, то строка считается обычной и расшифровывать ее не надо
  55. .text:00465F45                 jnz     short loc_465F9E
  56. .text:00465F47                 push    esi             ; lpString
  57. .text:00465F48                 call    ds:lstrlenW
  58. .text:00465F4E                 cmp     word ptr [esi+eax*2-2], 7Eh
  59. .text:00465F54                 jnz     short loc_465F9E
  60. .text:00465F56                 push    edi
  61. .text:00465F57                 lea     edi, [esi+2]
  62. .text:00465F5A                 mov     ecx, edi
  63. .text:00465F5C                 cmp     word ptr [ecx], 7Eh
  64. .text:00465F60                 jz      short loc_465F91
  65. .text:00465F62                 xor     esi, esi
  66. .text:00465F64                 push    ebx
  67. ; Цикл расшифровки строки
  68. .text:00465F65 loc_465F65:
  69. .text:00465F65                 movzx   eax, word ptr [ecx]
  70. .text:00465F68                 cmp     eax, 30h
  71. .text:00465F6B                 jb      short loc_465F84
  72. .text:00465F6D                 cmp     eax, 7Ah
  73. .text:00465F70                 ja      short loc_465F84
  74. .text:00465F72                 lea     eax, [eax+esi+59h]
  75. .text:00465F76                 cdq
  76. .text:00465F77                 mov     ebx, 4Bh
  77. .text:00465F7C                 idiv    ebx
  78. .text:00465F7E                 add     edx, 30h
  79. .text:00465F81                 mov     [ecx], dx
  80. .text:00465F84 loc_465F84:
  81. .text:00465F84                 add     ecx, 2
  82. .text:00465F87                 add     esi, 3
  83. .text:00465F8A                 cmp     word ptr [ecx], 7Eh
  84. .text:00465F8E                 jnz     short loc_465F65
  85. .text:00465F90                 pop     ebx
  86. .text:00465F91 loc_465F91:
  87. .text:00465F91                 xor     eax, eax
  88. .text:00465F93                 mov     [ecx], ax
  89. ; Вернуть в EAX указатель на расшифрованную строку
  90. .text:00465F96                 mov     eax, edi
  91. .text:00465F98                 pop     edi
  92. .text:00465F99                 pop     esi
  93. .text:00465F9A                 mov     esp, ebp
  94. .text:00465F9C                 pop     ebp
  95. .text:00465F9D                 retn
  96. .text:00465F9E ; -------------------------------
  97. .text:00465F9E loc_465F9E:
  98. ; Вернуть в EAX указатель на обычную строку
  99. .text:00465F9E                 mov     eax, esi
  100. .text:00465FA0                 pop     esi
  101. .text:00465FA1                 mov     esp, ebp
  102. .text:00465FA3                 pop     ebp
  103. .text:00465FA4                 retn
  104. .text:00465FA4 sub_465ED0      endp
Функция реализована универсально, она может загружать из ресурсов как обычные строчки, так и обрабатывать "на лету" зашифрованные данные. Признак шифрованных данных - строка начинается с символа "!". Если посмотрите в ресурсы, то именно так оно и есть. Алгоритм шифрования несложный, но нам он сейчас не нужен. Загружаем скринсейвер в отладчик и ставим точку останова на адрес 00465F96, в этом случае мы будем получать в регистре EAX указатель на расшифрованную строку. Нас интересует или строка "Unlicensed Copy" в заголовке окна или текст сообщение о неправильной регистрации после ввода левых данных.

Расшифрованная строка
Расшифрованная строка

Запускаем отладчик. Несколько раз точка останова сработает на строчках типа "Name", "Number", это, скорее всего, проверяется наличие строчек в реестре. Затем отладчик остановится на строке заголовка незарегистрированной версии. Пошаговой трассировкой доходим до команды RET и следующим шагом попадаем на место вызова:
  1. ; Проверить наличие регистрации в реестре
  2. .text:004608E1                 call    sub_43C2E0
  3. .text:004608E6                 add     esp, 0Ch
  4. .text:004608E9                 test    eax, eax
  5. .text:004608EB                 jz      short loc_460909
  6. .text:004608ED                 lea     eax, [ebp+var_808]
  7. .text:004608F3                 push    eax
  8. .text:004608F4                 lea     ecx, [ebp+var_1010]
  9. .text:004608FA                 push    ecx
  10. ; Проверить правильность регистрации
  11. .text:004608FB                 call    sub_43D1F0
  12. .text:00460900                 add     esp, 8
  13. ; Признак зарегистрированности
  14. .text:00460903                 mov     [ebp+var_80C], eax
  15. .text:00460909 loc_460909:
  16. ; Программа зарегистрирована?
  17. .text:00460909                 cmp     [ebp+var_80C], 0
  18. .text:00460910                 jnz     short loc_460930
  19. ; Нет, загрузить в заголовок строку "Unlicensed Copy"
  20. .text:00460912                 push    8Ah
  21. .text:00460917                 call    sub_466D10
  22. .text:0046091C                 add     esp, 4
  23. .text:0046091F                 push    eax
Все понятно. Сперва проверяется наличие хоть каких-то регистрационных данных в реестре, затем проверяется их корректность. Результат проверки сохраняется в ячейку памяти. Первую функцию проверки можно оставить нетронутой, но все-таки лучше будет пропатчить, чтобы при любом раскладе скринсейвер чувствовал себя хорошо. Записываем пару команд MOV EAX,1 и RET по адресу 0043C2E0. Функция проверки правильности регистрационных данных представляет собой длиннющее скопление операций математического сопроцессора, разбирать весь этот винегрет я не хочу, ограничусь обычным патчем в начало. Раз проверка должна вернуть ненулевой результат, то это будут все те же команды MOV EAX,1 и RET по адресу 0043D1F0. Сохраняем изменения, запускаем настройки.

Сообщение о корректной регистрации
Сообщение о корректной регистрации

Теперь скринсейвер принимает любые регистрационные данные и сообщает, что теперь это полная версия. Текст в заголовке также меняется на "лицензионный". Теперь пробуем запустить собственно сам скринсейвер.

Сообщение взломанной версии
Сообщение взломанной версии

Через несколько секунд на экране появляется летающая надпись о том, что мужики не танцуют победители никогда не пиратят, а пираты никогда не победят. Еще через несколько секунд скрисейвер принудительно закрывается. С чувством юмора у автора все с порядке, да и подход к защите правильный. Как ни странно, эта строчка лежит в открытом виде посреди файла. Похоже, это было сделано специально для более глубокого понимания всей глубины наших глубин.
  1. .text:00414030 sub_414030      proc near
  2. .text:00414030                 push    ebp
  3. .text:00414031                 mov     ebp, esp
  4. .text:00414033                 sub     esp, 9Ch
  5. .text:00414039                 mov     eax, dword_4E7FF0
  6. .text:0041403E                 xor     eax, ebp
  7. .text:00414040                 mov     [ebp+var_C], eax
  8. .text:00414043                 push    esi
  9. .text:00414044                 push    edi
  10. .text:00414045                 mov     [ebp+var_98], ecx
  11. .text:0041404B                 mov     [ebp+var_8C], 1
  12. .text:00414055                 mov     eax, dword_4E9838
  13. .text:0041405A                 and     eax, 1
  14. .text:0041405D                 jnz     short loc_414086
  15. .text:0041405F                 mov     ecx, dword_4E9838
  16. .text:00414065                 or      ecx, 1
  17. .text:00414068                 mov     dword_4E9838, ecx
  18. .text:0041406E                 mov     edx, [ebp+var_98]
  19. .text:00414074                 fild    dword ptr [edx+1974h]
  20. .text:0041407A                 fdiv    ds:dbl_4ACF18
  21. .text:00414080                 fstp    dbl_4E9830
  22. .text:00414086 loc_414086:
  23. .text:00414086                 mov     ecx, 16h
  24. .text:0041408B                 mov     esi, offset aWinnersNeverPi
  25. ; "Winners never pirate, and Pirates never"...
  26. .text:00414090                 lea     edi, [ebp+chText]
  27. .text:00414096                 rep movsd
  28. .text:00414098                 movsw
  29. .text:0041409A                 push    offset aArial   ; "Arial"
  30. .text:0041409F                 push    0               ; iPitchAndFamily
  31. .text:004140A1                 push    0               ; iQuality
  32. .text:004140A3                 push    20h             ; iClipPrecision
  33. .text:004140A5                 push    4               ; iOutPrecision
  34. .text:004140A7                 push    1               ; iCharSet
  35. .text:004140A9                 push    0               ; bStrikeOut
  36. .text:004140AB                 push    0               ; bUnderline
  37. .text:004140AD                 push    1               ; bItalic
  38. .text:004140AF                 push    2BCh            ; cWeight
  39. .text:004140B4                 push    0               ; cOrientation
  40. .text:004140B6                 push    0               ; cEscapement
  41. .text:004140B8                 push    0               ; cWidth
  42. .text:004140BA                 push    16h             ; cHeight
  43. .text:004140BC                 call    ds:CreateFontW
  44. .text:004140C2                 mov     [ebp+ho], eax
И код, откуда это безобразие вызывается:
  1. .text:00425325                 mov     eax, [ebp+var_C]
  2. ; Проверить какой-то флаг
  3. .text:00425328                 cmp     dword ptr [eax+1848h], 2
  4. ; Строку рисовать не надо
  5. .text:0042532F                 jnz     short loc_42533F
  6. .text:00425331                 push    1               ; int
  7. .text:00425333                 mov     ecx, [ebp+hdc]
  8. .text:00425336                 push    ecx             ; hdc
  9. .text:00425337                 mov     ecx, [ebp+var_C]
  10. ; Нарисовать строку
  11. .text:0042533A                 call    sub_414030
Тут проверяется какой-то флаг, а дальше, в зависимости от его значения, или скринсейвер работает в штатном режиме, или надо будет нарисовать строку со всеми вытекающими последствиями. Раз флаг проверяется, значит он должен где-то инициализироваться. По конструкции "+1848h]" находим в листинге следующий интересный кусочек:
  1. .text:0042C360 sub_42C360
  2. .text:0042C360                 push    ebp
  3. .text:0042C361                 mov     ebp, esp
  4. .text:0042C363                 push    ecx
  5. .text:0042C364                 mov     [ebp+var_4], ecx
  6. .text:0042C367                 mov     eax, [ebp+var_4]
  7. .text:0042C36A                 mov     dword ptr [eax+1848h], 2
  8. .text:0042C374                 mov     esp, ebp
  9. .text:0042C376                 pop     ebp
  10. .text:0042C377                 retn
  11. .text:0042C377 sub_42C360      endp
Вызывается эта конструкция, в свою очередь, вот отсюда. Код надо смотреть снизу-вверх, так будет понятнее.
  1. .text:0043ED37                 cmp     [ebp+var_BA0], 464h
  2. .text:0043ED41                 jz      short loc_43EDBA
  3. .text:0043ED43                 cmp     [ebp+var_BA0], 465h
  4. .text:0043ED4D                 jz      loc_43F6A8
  5. .text:0043ED53                 jmp     loc_43F91F
  6. .text:0043ED58 ; -------------------------------
  7. .text:0043ED58 loc_43ED58:
  8. .text:0043ED58                 cmp     [ebp+wParam], 2
  9. .text:0043ED5C                 jnz     short loc_43ED90
  10. .text:0043ED5E                 push    2               ; uIDEvent
  11. .text:0043ED60                 mov     ecx, [ebp+hWnd]
  12. .text:0043ED63                 push    ecx             ; hWnd
  13. .text:0043ED64                 call    ds:KillTimer
  14. .text:0043ED6A                 push    0               ; lpTimerFunc
  15. .text:0043ED6C                 push    3A98h           ; uElapse
  16. .text:0043ED71                 push    3               ; nIDEvent
  17. .text:0043ED73                 mov     edx, [ebp+hWnd]
  18. .text:0043ED76                 push    edx             ; hWnd
  19. .text:0043ED77                 call    ds:SetTimer
  20. .text:0043ED7D                 push    0               ; lParam
  21. .text:0043ED7F                 push    64h             ; wParam
  22. .text:0043ED81                 push    464h            ; Msg
  23. .text:0043ED86                 mov     eax, [ebp+hWnd]
  24. .text:0043ED89                 push    eax             ; hWnd
  25. .text:0043ED8A                 call    ds:PostMessageW
  26. .text:0043ED90 loc_43ED90:
  27. .text:0043ED90                 cmp     [ebp+wParam], 3
  28. .text:0043ED94                 jnz     short loc_43EDB5
  29. .text:0043ED96                 push    3               ; uIDEvent
  30. .text:0043ED98                 mov     ecx, [ebp+hWnd]
  31. .text:0043ED9B                 push    ecx             ; hWnd
  32. .text:0043ED9C                 call    ds:KillTimer
  33. .text:0043EDA2                 push    0               ; lParam
  34. .text:0043EDA4                 push    65h             ; wParam
  35. .text:0043EDA6                 push    465h            ; Msg
  36. .text:0043EDAB                 mov     edx, [ebp+hWnd]
  37. .text:0043EDAE                 push    edx             ; hWnd
  38. .text:0043EDAF                 call    ds:PostMessageW
  39. .text:0043EDB5 loc_43EDB5:
  40. .text:0043EDB5                 jmp     loc_43F91F      ; default
  41. .text:0043EDBA ; -------------------------------
  42. .text:0043EDBA loc_43EDBA:
  43. .text:0043EDBA                 mov     ecx, dword_4ECCE8
  44. ; Взвести "пиратский" флаг
  45. .text:0043EDC0                 call    sub_42C360
  46. .text:0043EDC5                 jmp     loc_43F91F      ; default
Стоит немного пояснить, что тут происходит. При определенном событии (в данном случае факт наличия взлома) устанавливается таймер, по срабатыванию которого окну отправляется message с определенным кодом. Обработчик сообщений окна при получении этого кода (464h) взводит "пиратский" флаг, на основании которого начинается вывод строки, ожидание следующего кода (465h) и последующее завершение работы. Самый простой способ обойти это - сделать так, чтобы сообщения никогда не отправлялись и таймеры никогда не взводились. Заменяем два условных перехода по адресам 0043ED5C и 0043ED94 на безусловные. Таким образом окно скринсейвера никогда не получит "сигналов тревоги" и не отреагирует на них. Сохраняем изменения, запускаем.

Сообщение взломанной версии
Сообщение взломанной версии

Уведомление о пиратстве больше не появляется, скринсейвер не вылетает. Однако, через некоторое время поверх цветных узоров начинают появляться предложения метнуться в кассу или вовсе какие-то бредовые надписи типа этой. Эти строки зашифрованы, отлавливаются они под отладчиком точно так же, как описано выше.
  1. .text:0040F137                 mov     ecx, [ebp+var_1C4]
  2. ; Загрузить флаг
  3. .text:0040F13D                 mov     edx, [ecx+9E28h]
  4. .text:0040F143                 mov     [ebp+var_1C8], edx
  5. .text:0040F149                 cmp     [ebp+var_1C8], 10h ; switch 17 cases
  6. .text:0040F150                 ja      loc_40F741
  7. .text:0040F156                 mov     eax, [ebp+var_1C8]
  8. .text:0040F15C                 movzx   ecx, ds:byte_40F774[eax]
  9. .text:0040F163                 jmp     ds:off_40F760[ecx*4] ; switch jump
  10. .text:0040F16A loc_40F16A:
  11. .text:0040F16A                 mov     edx, [ebp+var_1C4]
  12. ; Загрузить случайное сообщение
  13. .text:0040F170                 mov     eax, [edx+9E28h]
  14. .text:0040F176                 add     eax, 6Ah
  15. .text:0040F179                 push    eax
  16. ; Расшифровать строку
  17. .text:0040F17A                 call    sub_466D10
  18. .text:0040F17F                 add     esp, 4
  19. .text:0040F182                 mov     [ebp+var_158], eax
  20. .text:0040F188                 mov     [ebp+var_154], 0
Тут выполняется конструкция SWITCH-CASE. При значениях выше 17 сообщения не показываются, иначе выбирается случайная строка. Надо заменить условный переход по адресу 0040F150 на безусловный, тогда условие не выполнится и сообщения показываться не будут. Сохраняем изменения, запускаем. Надписи больше не появляются, но в тот момент, когда они должны были это делать, внизу экрана выводится предложение нажать кнопку "V" для посещения офсайта. В принципе, можно было бы на этом и остановиться, надпись мелкая и совсем не мешает, но раз уж начали, то надо довести все до логического завершения. Индекс строки в ресурсах 123 или 7Bh в шестнадцатеричной системе. Отлавливается это также в отладчике. В листинге находим следующий код:
  1. .text:0040F809                 fstp    [ebp+var_C]
  2. .text:0040F80C                 mov     [ebp+var_8], 10h
  3. ; Проверить аргумент
  4. .text:0040F813                 cmp     [ebp+arg_8], 1
  5. .text:0040F817                 jnz     loc_40F904
  6. .text:0040F81D                 fld     ds:flt_4AB890
  7. .text:0040F823                 fstp    [ebp+var_C]
  8. .text:0040F826                 mov     [ebp+var_8], 0Eh
  9. ; Загрузить строку и вывести ее на экран
  10. .text:0040F82D                 push    7Bh
  11. .text:0040F82F                 call    sub_466D10
  12. .text:0040F834                 add     esp, 4
  13. .text:0040F837                 push    eax
  14. .text:0040F838                 push    40h
  15. .text:0040F83A                 lea     eax, [ebp+String]
  16. .text:0040F840                 push    eax
  17. .text:0040F841                 call    sub_401CC0
  18. .text:0040F846                 mov     ecx, [ebp+var_2FC]
  19. .text:0040F84C                 mov     edx, [ecx+9F34h]
  20. .text:0040F852                 push    edx             ; h
  21. .text:0040F853                 mov     eax, [ebp+hdc]
  22. .text:0040F856                 push    eax             ; hdc
  23. .text:0040F857                 call    ds:SelectObject
  24. .text:0040F85D                 mov     [ebp+h], eax
У скринсейвера есть возможность показывать пользовательские сообщения, скорее всего тут проверяется, какой тип сообщения нужно вывести. Если пользовательский, то предложение метнуться на сайт не показывается, а если это сообщение взломанной версии, то оно дополняется строкой снизу. Заменяем условный переход по адресу 0040F817 на безусловный, теперь любое сообщение будет считаться пользовательским и не будет дополняться лишними строками. Сохраняем изменения, запускаем.

Скринсейвер успешно "зарегистрирован"
Скринсейвер успешно "зарегистрирован"

Все, больше никаких ограничений нет, никаких надписей не появляется. Цель достигнута, счет 1:0, пираты снова победили. Спасибо автору за красивый скринсейвер и за грамотный подход к защите, получилась очень неплохая разминка для мозгов.

Поделиться ссылкой ВКонтакте
Просмотров: 1328 | Комментариев: 7

Внимание! Статья опубликована больше года назад, информация могла устареть!

Комментарии

Отзывы посетителей сайта о статье
ManHunter (11.06.2020 в 12:15):
Был тут разбор какой-то защиты, там использовалась api CheckSumMappedFile. Еще на TeamViewer встречал проверку целостности по сертификату, там было сделано через api WinVerifyTrust.
0101 (11.06.2020 в 07:12):
pawel97, понятно. Четыре байта нашёл, что за сумма и как "вручную" её подсчитать/исправить - нет. Просто есть одна програмка, которая, похоже, тоже считает CheckSum.. Я думал, может, api характерные есть, по которым искать проверку целостности файла..
pawel97 (10.06.2020 в 23:57):
0101, использовал conditional breakpoints в оле, сначала на оконную процедуру - отловил сообщение wm_timer с аргументом 2 - стало быть это id таймера. Потом на SetTimer с подсмотренным id 2, потом в листинге вышел на инициализацию флагов, из-за которых таймер взводится, и стал разбираться. Да, ещё до дизассемблеров случайно заметил, что к файлу оверлеем дописано 4 байта, подозрительно однако, небось чексумма какая. А разбор подтвердил.
ManHunter (10.06.2020 в 22:49):
Там чексум берется не из заголовка, а считается самостоятельно.
0101 (10.06.2020 в 21:49):
pawel97, расскажите, как нашли, что в этом месте идёт проверка целостности файла?
Что именно и где подглядываем? При патчиге CheckSum не меняется же..
п.с. есть похожий скринсервер "Gold Lace"
ManHunter (10.06.2020 в 11:52):
pawel97, 2:0 в пользу пиратов :)
pawel97 (10.06.2020 в 02:15):
Вся антипиратка из-за проверки целостности файла. Некая контрольная сумма считается и далее с ней происходят всякие колдунства, на основе этого ставятся флаги, взводятся таймеры...
Просто подглядываем в непатченном файле итоговое значение и хардкодим в патченном.
00460D4A  |.  8B8D 68FFFFFF mov ecx,ss:[ebp-98]
00460D50  |.  51            push ecx
00460D51  |.  8D8D 74FFFFFF lea ecx,[ebp-8C]
00460D57  |.  E8 E4AAFDFF   call 0043B840
Первые две команды меняем на push 0000AEC7 и 2 нопа.

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2024
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.07 сек. / MySQL: 2 (0.008 сек.) / Память: 4.5 Mb
Наверх