Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 12 ноября!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Иследование HTTP Sniffer 4 по просьбам "трудящихся"

Обсудить статью на форуме

Хорошая подборка видеоуроков, инструментов крэкера, книг и статей - здесь.

Автор: RSI <RS1@tut.by>

Всем привет!
Значит началось все с того, что сравнительно недавно появилась тема на форуме cracklab!
-----------------------------------------------------------------------------------------------------------------------
CRACKL@B —› Основной форум —› Написание статьи
------------------------------------------------------------------------------------------------------------------------
Dr3d
Ранг: 7.1 (гость)
Статус: Участник
Создано: Дек 20, 2006 13:11:53
------------------------------------------------------------------------------------------------------------------------
У меня просьба к тем, кто умеет и хочет написать статью для продвинутых новичков.
Существует множество статей для новичков и для профи, а вот для начально-среднего уровня как всегда нет. Суть просьбы, написать статью на примере программ с сайта http://www.effetech.com/download/, подобного рода защиты я встречал довольно часто, но до конца сломать их так и не смог, думаю это и есть тот самый начально-средний уровень.
-------------------------------------------------------------------------------------------------------------------------

Ну вот нашлось время и я решил более основательно посмотреть данную прожку и написать статью про то, что у меня собственно получилось...

Думаю объяснять зачем эта программа не нужно, должно быть уже понятно из ее названия...

Итак, что нам понадобится:
1) PEiD - для проверки на упакованность
2) Calc.exe - для вычислений и перевода чисел
3) OllyDbg - для исследования
4) Сама прога соответственно

Начнем ;)

1) Первое с чего всегда надо начинать - это проверять программу на упакованность какими-нить злобными протекторами/ пакерами.

Берем PEiD - он нам показывает Microsoft Visual C++ 7.0
Хорошо, значит возится с распаковкой не нужно...

2) Запускаем программу и смотрим что от нас хотят и какие у нее ограничения.

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

name: RSI
Code: 12345

Жмем "Register" и видим ссобщение "Wrong User or Serial Number!" - понятно...
Впринципе узнали все что хотели, идем дальше!

3) Грузим программу в отладчик

Итак мы знаем текст собщения о неправильном коде, можно было бы поискать эту строку и
смотреть где она используется, но мы пойдем другим путем(т.к. он мне больше нравится)

Запускаем программу (F9)
Снова вводим свои данные, теперь я предполагаю, что функция отвечающая за вывод сообщения это MessageBoxA, но это может быть и другая функция...
Ставим брэйкпоинт на эту функцию (т.е. в коммандной строке пишем: bp MessageBoxA) и жмем "Register", если мы правильно определили функцию, то мы вывалимся в отладчике, если нет, то придется искать другие функции ( например ShowWindow или MessageBoxW или ....)

Угадал - вываливаемся в отладчик, снимаем бряк (F2) и жмем ctrl+F9 значит дойти до конца данной функции, после этого появляется наше сообщение жмем OK,
и снова попадаем в отладчик на RETN 10

77D5ADD7 > 833D C4D3D877 00 CMP DWORD PTR DS:[77D8D3C4],0
77D5ADDE   0F85 377E0100    JNZ USER32.77D72C1B
77D5ADE4   6A 00            PUSH 0
77D5ADE6   FF7424 14        PUSH DWORD PTR SS:[ESP+14]
77D5ADEA   FF7424 14        PUSH DWORD PTR SS:[ESP+14]
77D5ADEE   FF7424 14        PUSH DWORD PTR SS:[ESP+14]
77D5ADF2   FF7424 14        PUSH DWORD PTR SS:[ESP+14]
77D5ADF6   E8 03000000      CALL USER32.MessageBoxExA
77D5ADFB   C2 1000          RETN 10				; <- Мы тут

теперь трассируем по F8 ( построчно не заходя в тело функции ), после выхода из 2-х функций попадаем вот на такой кусок:

004155B0   > 33C0           XOR EAX,EAX
004155B2   > 68 A0CF4500    PUSH EHSniffe.0045CFA0    ;  ASCII "EffeTech HTTP Sniffer"
004155B7   . 8BC8           MOV ECX,EAX
004155B9   . E8 175B0200    CALL EHSniffe.0043B0D5
004155BE   . 6A 00          PUSH 0
004155C0   . 6A 00          PUSH 0
004155C2   . 68 B8DD4500    PUSH EHSniffe.0045DDB8    ;  ASCII "Thank you for supporting our software!"
004155C7   . E8 84F80200    CALL EHSniffe.00444E50
004155CC   . 5F             POP EDI
004155CD   . 5E             POP ESI
004155CE   . 8BCD           MOV ECX,EBP
004155D0   . 5D             POP EBP
004155D1   . 5B             POP EBX
004155D2   . 83C4 04        ADD ESP,4
004155D5   . E9 3E170200    JMP EHSniffe.00436D18
004155DA   > 6A 00          PUSH 0
004155DC   . 6A 00          PUSH 0
004155DE   . 68 98DD4500    PUSH EHSniffe.0045DD98    ;  ASCII "Wrong User or Serial Number!"
004155E3   . E8 68F80200    CALL EHSniffe.00444E50
004155E8   . 5F             POP EDI		      ; <- мы вышли тут	
004155E9   . 5E             POP ESI                                  
004155EA   . 5D             POP EBP
004155EB   . 5B             POP EBX
004155EC   . 59             POP ECX
004155ED   . C3             RETN

Итак нам нужно узнать откуда мы прыгаем на это сообщение, для этого ставим курсор на 004155DA и видим оля нам показывает:

Jumps from 0041549E, 0041552D, 00415540

Значит перейдем на самый верхний джамп - 0041549E, и поставим бряк чуть выше (скажем 415480), отпускаем программу на дальнейшее выполнение (F9) и опять жмем "Register" прерываемся на бряке.
Посмотрим что мы видим (пройдем эту часть построчно):

serial[] - это строка с нашим кодом

00415480   . 51             PUSH ECX			      ;<- наш бряк
00415481   . 53             PUSH EBX
00415482   . 55             PUSH EBP
00415483   . 56             PUSH ESI
00415484   . 57             PUSH EDI
00415485   . 6A 01          PUSH 1
00415487   . 8BE9           MOV EBP,ECX
00415489   . E8 56310200    CALL EHSniffe.004385E4
0041548E   . 8B85 C4000000  MOV EAX,DWORD PTR SS:[EBP+C4]    ; <- наш код
00415494   . 8378 F4 12     CMP DWORD PTR DS:[EAX-C],12	     ; сравниваем длину кода с 12h	
00415498   . 8DBD C4000000  LEA EDI,DWORD PTR SS:[EBP+C4]
0041549E   . 0F85 36010000  JNZ EHSniffe.004155DA	     ; если 12h то идем дальше и не облом	
004154A4   . 8B5C24 10      MOV EBX,DWORD PTR SS:[ESP+10]
004154A8   . 8B7424 10      MOV ESI,DWORD PTR SS:[ESP+10]
004154AC   . 8B4424 10      MOV EAX,DWORD PTR SS:[ESP+10]
004154B0   . 33D2           XOR EDX,EDX				; начинается цикл ( 12h = 18 раз)
004154B2   > 85D2           TEST EDX,EDX
004154B4   . 0F8C EC000000  JL EHSniffe.004155A6
004154BA   . 8B0F           MOV ECX,DWORD PTR DS:[EDI]		; ecx - указывает на наш код
004154BC   . 3B51 F4        CMP EDX,DWORD PTR DS:[ECX-C]
004154BF   . 0F8F E1000000  JG EHSniffe.004155A6
004154C5   . 85D2           TEST EDX,EDX			
004154C7   . 8A0C11         MOV CL,BYTE PTR DS:[ECX+EDX]	; cl = serial[edx]	
004154CA   . 75 05          JNZ SHORT EHSniffe.004154D1		; if( edx == 0)
004154CC   . 0FBED9         MOVSX EBX,CL			;  ebx = cl
004154CF   . EB 4E          JMP SHORT EHSniffe.0041551F
004154D1   > 83FA 01        CMP EDX,1				; if( edx == 1 )
004154D4   . 75 07          JNZ SHORT EHSniffe.004154DD
004154D6   . 0FBEC1         MOVSX EAX,CL			;  eax = cl;
004154D9   . 8BF0           MOV ESI,EAX				;  esi = eax;
004154DB   . EB 42          JMP SHORT EHSniffe.0041551F
004154DD   > 83FA 03        CMP EDX,3				; if( edx == 3 )
004154E0   . 74 2E          JE SHORT EHSniffe.00415510
004154E2   . 83FA 06        CMP EDX,6				; if( edx == 6)
004154E5   . 75 07          JNZ SHORT EHSniffe.004154EE
004154E7   . 0FBEC1         MOVSX EAX,CL			;  eax = cl
004154EA   . 8BF0           MOV ESI,EAX				;  esi = eax
004154EC   . EB 31          JMP SHORT EHSniffe.0041551F
004154EE   > 83FA 0A        CMP EDX,0A 				; if( edx == 10)
004154F1   . 75 09          JNZ SHORT EHSniffe.004154FC
004154F3   . 0FBEC1         MOVSX EAX,CL			; eax = cl
004154F6   . 894424 10      MOV DWORD PTR SS:[ESP+10],EAX	; [ESP+10] = eax
004154FA   . EB 23          JMP SHORT EHSniffe.0041551F
004154FC   > 83FA 0E        CMP EDX,0E				; if( edx == 14 )
004154FF   . 75 05          JNZ SHORT EHSniffe.00415506
00415501   . 83EB 50        SUB EBX,50				;  ebx = ebx - 50h
00415504   . EB 16          JMP SHORT EHSniffe.0041551C
00415506   > 83FA 12        CMP EDX,12				; if( edx == 18)
00415509   . 74 11          JE SHORT EHSniffe.0041551C
0041550B   . 83FA 08        CMP EDX,8				; if( edx == 8)
0041550E   . 75 07          JNZ SHORT EHSniffe.00415517
00415510   > 0FBEC1         MOVSX EAX,CL			;  eax = cl
00415513   . 8BF0           MOV ESI,EAX				;  esi = eax
00415515   . EB 08          JMP SHORT EHSniffe.0041551F
00415517   > 83FA 0F        CMP EDX,0F
0041551A   . 75 03          JNZ SHORT EHSniffe.0041551F		; if( edx == 15)
0041551C   > 0FBEC1         MOVSX EAX,CL			;  eax = cl
0041551F   > 42             INC EDX				;  edx++;
00415520   . 83FA 12        CMP EDX,12
00415523   .^7C 8D          JL SHORT EHSniffe.004154B2		; проверка на выход из цикла
00415525   . 2B4424 10      SUB EAX,DWORD PTR SS:[ESP+10]	; eax = eax - [ESP+10]
00415529   . 2BC6           SUB EAX,ESI				; eax = eax - esi	
0041552B   . 03C3           ADD EAX,EBX				; eax = eax + ebx
0041552D   . 0F85 A7000000  JNZ EHSniffe.004155DA		; если eax = 0, то не прыгаем
00415533   . 57             PUSH EDI				; иначе прыгаем на облом
00415534   . B9 C8364700    MOV ECX,EHSniffe.004736C8
00415539   . E8 B295FFFF    CALL EHSniffe.0040EAF0		; <- функция проверки кода
0041553E   . 85C0           TEST EAX,EAX			; если вернула eax = 0
00415540   . 0F84 94000000  JE EHSniffe.004155DA		; тогда прыгаем на облом	

Ну вот видим, что сначала идет проверка на длинну кода она должна быть 12h = 18 символов, затем идет проверка на то, чтобы серийник проходил определенный фэйс контроль иначе облом!
Если очистить от мусорного кода, то условие фэйс контроля это уравнение:

serial[15]-serial[10]-serial[8]+(serial[0] - 80) = 0

Если оно выполняется тогда переходим к функции дальнейшей проверки кода, которая вернет
eax = 0 - если код левый
eax = 1 - если все ОК
Обычно такая защита с возвратом 0 и 1 у многих программ..., но есть и исключения.

4) Анализ защиты программы

Итак посидев 3 минутки над листочком для решения этого уравнения с 4 неизвестными, получилось:

'a' - '0' - '1' + ('P' - 80) = 0 - конечно можно было бы и по другому, но на вкус и цвет...

Подставив вместо букв их коды получим: 97 - 48 - 49 + (80 - 80) = 0

Таким образом серийник пока имеет вид: Pyyyyyyy1y0yyyyayy , где y-неизвестные

Вводим этот код и пробуем - прошли фэйс-контроль заходим в функцию проверки стоя на начале этой функции видим, что она вызывается из 4-х мест:

Local calls from 0040A0BE, 0040B1BD, 0040CEB2, 0040FA06, 00415539

Поэтому поставим бряк на ее начало(F2) и идем вперед построчно(F8), видим дохренищща математических действий (+,-,*,/) я пока приведу только конец этой функции:

0040F072   . 83C4 0C        ADD ESP,0C
0040F075     81FD A52B0000  CMP EBP,2BA5			; if( ebp == 2bA5h )
0040F07B     74 45          JE SHORT EHSniffe.0040F0C2		; прыг на хорошее завершений
0040F07D   . 81FD 303A0000  CMP EBP,3A30			; if( ebp == 3A30h )
0040F083   . 74 3D          JE SHORT EHSniffe.0040F0C2		; прыг на хорошее завершений
0040F085   . 8B4424 4C      MOV EAX,DWORD PTR SS:[ESP+4C]	; плохое завершений функции
0040F089   . 83C0 F0        ADD EAX,-10	
0040F08C   . C74424 44 FFFF>MOV DWORD PTR SS:[ESP+44],-1
0040F094   . 8D48 0C        LEA ECX,DWORD PTR DS:[EAX+C]
0040F097   . 83CA FF        OR EDX,FFFFFFFF
0040F09A   . F0:0FC111      LOCK XADD DWORD PTR DS:[ECX],EDX         
0040F09E   . 4A             DEC EDX
0040F09F   . 85D2           TEST EDX,EDX
0040F0A1   . 7F 08          JG SHORT EHSniffe.0040F0AB
0040F0A3   . 8B08           MOV ECX,DWORD PTR DS:[EAX]
0040F0A5   . 8B11           MOV EDX,DWORD PTR DS:[ECX]
0040F0A7   . 50             PUSH EAX
0040F0A8   . FF52 04        CALL DWORD PTR DS:[EDX+4]
0040F0AB   > 5F             POP EDI
0040F0AC   . 5B             POP EBX
0040F0AD   . 5D             POP EBP
0040F0AE   . 33C0           XOR EAX,EAX				; вернем eax = 0 - плохо
0040F0B0   . 5E             POP ESI
0040F0B1   . 8B4C24 2C      MOV ECX,DWORD PTR SS:[ESP+2C]
0040F0B5   . 64:890D 000000>MOV DWORD PTR FS:[0],ECX
0040F0BC   . 83C4 38        ADD ESP,38
0040F0BF   . C2 0400        RETN 4
0040F0C2   > 8B4424 4C      MOV EAX,DWORD PTR SS:[ESP+4C]	; хорошее завершений функции
0040F0C6   . 83C0 F0        ADD EAX,-10
0040F0C9   . C74424 44 FFFF>MOV DWORD PTR SS:[ESP+44],-1
0040F0D1   . 8D48 0C        LEA ECX,DWORD PTR DS:[EAX+C]
0040F0D4   . 83CA FF        OR EDX,FFFFFFFF
0040F0D7   . F0:0FC111      LOCK XADD DWORD PTR DS:[ECX],EDX         
0040F0DB   . 4A             DEC EDX
0040F0DC   . 85D2           TEST EDX,EDX
0040F0DE   . 7F 08          JG SHORT EHSniffe.0040F0E8
0040F0E0   . 8B08           MOV ECX,DWORD PTR DS:[EAX]
0040F0E2   . 8B11           MOV EDX,DWORD PTR DS:[ECX]
0040F0E4   . 50             PUSH EAX
0040F0E5   . FF52 04        CALL DWORD PTR DS:[EDX+4]
0040F0E8   > 8B4C24 3C      MOV ECX,DWORD PTR SS:[ESP+3C]
0040F0EC   . 5F             POP EDI
0040F0ED   . 5B             POP EBX
0040F0EE   . 5D             POP EBP
0040F0EF   . B8 01000000    MOV EAX,1				; веренм eax = 1 - хорошо
0040F0F4   . 5E             POP ESI
0040F0F5   . 64:890D 000000>MOV DWORD PTR FS:[0],ECX
0040F0FC   . 83C4 38        ADD ESP,38
0040F0FF   . C2 0400        RETN 4

Видим что если ebp будет равен одной из 2-х констант тогда мы зарегистрированы, для этого подправим инструкцию:

0040F07B     74 45          JE SHORT EHSniffe.0040F0C2
на
0040F07B     EB 45          JMP SHORT EHSniffe.0040F0C2

и посмотрим что будет дальше...
Теперь функция вернула eax = 1, и мы увидили собщение "Thank you for supporting our software!"
Видим пропала надпись Trial version из заголовка окна, попробуем зайти в About...
И вываливаемся в отладчик - сработал бряк на функцию проверки серийника, посмотрим что будет после нее, идем до выхода из функции и выходим тут:

0040A0B9   . B9 C8364700    MOV ECX,EHSniffe.004736C8
0040A0BE   . E8 2D4A0000    CALL EHSniffe.0040EAF0
0040A0C3   . 85C0           TEST EAX,EAX		 ; <- вышли тут
0040A0C5   . 0F84 BB000000  JE EHSniffe.0040A186
0040A0CB   . E8 561D0300    CALL EHSniffe.0043BE26
0040A0D0   . 8B10           MOV EDX,DWORD PTR DS:[EAX]
0040A0D2   . 8BC8           MOV ECX,EAX
0040A0D4   . FF52 0C        CALL DWORD PTR DS:[EDX+C]
0040A0D7   . 83C0 10        ADD EAX,10
0040A0DA   . 894424 10      MOV DWORD PTR SS:[ESP+10],EAX
0040A0DE   . 8B0D 44374700  MOV ECX,DWORD PTR DS:[473744]	; ecx -> наш серийник
0040A0E4   . 8B41 F4        MOV EAX,DWORD PTR DS:[ECX-C]
0040A0E7   . 83F8 03        CMP EAX,3
0040A0EA   . C74424 1C 0000>MOV DWORD PTR SS:[ESP+1C],0
0040A0F2   . 7D 0A          JGE SHORT EHSniffe.0040A0FE
0040A0F4   . 68 57000780    PUSH 80070057
0040A0F9   . E8 D26FFFFF    CALL EHSniffe.004010D0
0040A0FE   > 83F8 07        CMP EAX,7
0040A101   . 8A51 03        MOV DL,BYTE PTR DS:[ECX+3]		; dl = serial[3]
0040A104   . 7D 0A          JGE SHORT EHSniffe.0040A110
0040A106   > 68 57000780    PUSH 80070057
0040A10B   . E8 C06FFFFF    CALL EHSniffe.004010D0
0040A110   > 80FA 78        CMP DL,78				; if( dl == 78h)
0040A113   . 8A49 07        MOV CL,BYTE PTR DS:[ECX+7]		; cl = serial[7];
0040A116   . 75 17          JNZ SHORT EHSniffe.0040A12F
0040A118   . 80F9 63        CMP CL,63				; if( cl == 63h)
0040A11B   . 75 12          JNZ SHORT EHSniffe.0040A12F
0040A11D   . A1 48374700    MOV EAX,DWORD PTR DS:[473748]
0040A122   . 50             PUSH EAX
0040A123   . 68 9CAF4500    PUSH EHSniffe.0045AF9C            ;  ASCII "Commercial License"
0040A128   . 8D4C24 18      LEA ECX,DWORD PTR SS:[ESP+18]
0040A12C   . 51             PUSH ECX
0040A12D   . EB 11          JMP SHORT EHSniffe.0040A140
0040A12F   > 8B15 48374700  MOV EDX,DWORD PTR DS:[473748]
0040A135   . 52             PUSH EDX
0040A136   . 68 38AF4500    PUSH EHSniffe.0045AF38           ;  ASCII "Non-Commercial License"
0040A13B   . 8D4424 18      LEA EAX,DWORD PTR SS:[ESP+18]

Видим, что могут быть 2 вида лицензии:
1)Commercial License
2)Non-Commercial License

Сейчас у нас Non-Commercial License! Чтобы это была Commercial License, нужно чтобы

serial[3] = 78h = 'x'
serial[7] = 63h = 'c'

Значит в итоге получаем виды лицензий:
1)Commercial License - Pyyxyyyc1y0yyyyayy , где y-неизвестные
2)Non-Commercial License - Pyyyyyyy1y0yyyyayy , где y-неизвестные

5) Генерация серийного номера

Теперь, когда мы столько знаем, можем пропатчить переход и программа будет полностью зарегистрированна, но можно пойти по более сложному пути попробовать разобрать алгоритм генерации и проверки серийного номера.( не для слабонервных... ;) )
Вот что собой представляет начало функции проверки серийника:

							                    
                                                                                          ; ecx = 12h - всегда
0040EB63   > 85C9           TEST ECX,ECX
0040EB65   . 55             PUSH EBP
0040EB66   . BD 1E170000    MOV EBP,171E			; ebp  = 171Eh
0040EB6B   . 7D 0A          JGE SHORT EHSniffe.0040EB77
0040EB6D   . 68 57000780    PUSH 80070057			; < - мусор
0040EB72   . E8 5925FFFF    CALL EHSniffe.004010D0		; < - мусор
0040EB77   > 83F9 01        CMP ECX,1				; < - мусор	
0040EB7A   . 7D 0A          JGE SHORT EHSniffe.0040EB86		; < - мусор
0040EB7C   . 68 57000780    PUSH 80070057			; < - мусор
0040EB81   . E8 4A25FFFF    CALL EHSniffe.004010D0		; < - мусор
0040EB86   > 83F9 02        CMP ECX,2				; < - мусор
0040EB89   . 7D 0A          JGE SHORT EHSniffe.0040EB95		; < - мусор
0040EB8B   . 68 57000780    PUSH 80070057			; < - мусор
0040EB90   . E8 3B25FFFF    CALL EHSniffe.004010D0		; < - мусор
0040EB95   > 83F9 03        CMP ECX,3				; < - мусор
0040EB98   . 8A56 02        MOV DL,BYTE PTR DS:[ESI+2]		; dl = serial[2]
0040EB9B   . 885424 44      MOV BYTE PTR SS:[ESP+44],DL		; [12F104] = dl
0040EB9F   . 7D 0A          JGE SHORT EHSniffe.0040EBAB		; < - мусор
0040EBA1   . 68 57000780    PUSH 80070057			; < - мусор
0040EBA6   . E8 2525FFFF    CALL EHSniffe.004010D0		; < - мусор
0040EBAB   > 83F9 04        CMP ECX,4				; < - мусор
0040EBAE   . 53             PUSH EBX				; < - мусор
0040EBAF   . 8A5E 03        MOV BL,BYTE PTR DS:[ESI+3]		; bl = serial[3]
0040EBB2   . 7D 0A          JGE SHORT EHSniffe.0040EBBE		; < - мусор
0040EBB4   . 68 57000780    PUSH 80070057			; < - мусор
0040EBB9   . E8 1225FFFF    CALL EHSniffe.004010D0		; < - мусор
0040EBBE   > 8A56 04        MOV DL,BYTE PTR DS:[ESI+4]		; dl = serial[4]
0040EBC1   . 57             PUSH EDI
0040EBC2   . 0FBEC3         MOVSX EAX,BL			; eax = bl
0040EBC5   . BF 64000000    MOV EDI,64				; edi = 64h = 100
0040EBCA   . 2BF8           SUB EDI,EAX				; edi = edi - eax
0040EBCC   . 0FBE4424 4C    MOVSX EAX,BYTE PTR SS:[ESP+4C]	; eax = [12F104]
0040EBD1   . 8D0440         LEA EAX,DWORD PTR DS:[EAX+EAX*2]	; eax = eax + eax*2
0040EBD4   . 0FBED2         MOVSX EDX,DL
0040EBD7   . 8D0478         LEA EAX,DWORD PTR DS:[EAX+EDI*2]	; eax = eax + edi*2;
0040EBDA   . 03C2           ADD EAX,EDX				; eax = eax + edx
0040EBDC   . 0FBE56 01      MOVSX EDX,BYTE PTR DS:[ESI+1]	; edx = serial[1]
0040EBE0   . 03C2           ADD EAX,EDX				; eax = eax + edx;
0040EBE2   . 0FBE16         MOVSX EDX,BYTE PTR DS:[ESI]		; edx = serial[0]
0040EBE5   . 8D0442         LEA EAX,DWORD PTR DS:[EDX+EAX*2]	; eax = edx + eax*2
0040EBE8   . 99             CDQ					; edx = 0
0040EBE9   . BF E8000000    MOV EDI,0E8				; edi = 0E8h = 232
0040EBEE   . F7FF           IDIV EDI				; eax = eax/edi 
0040EBF0   . 83F9 03        CMP ECX,3				; (в dl остаток от деления)	
0040EBF3   . 885424 18      MOV BYTE PTR SS:[ESP+18],DL		; [12F0D0] = mas[0] = dl
.
.
.

Вот таким аналогичным образом происходит заполнение массива(назовем его mas) из 8 байт, если почистить этот код от ненужного мусора и переписать на Си получим:

int check_serial(char *serial)
{
	char mas[8];
	long eax,ebx,ecx,edx,edi,esi;
	long ebp = 5918;		// ebp  = 171Eh

//-- mas[0] -------------------------------------------------------------
	edi = 100-serial[3];
	eax = serial[2];
	eax = eax+eax*2;
	eax = eax+edi*2;
	eax += serial[4];
	eax += serial[1];
	eax = serial[0] + eax*2;
	mas[0] = eax%232;
//--- mas[1] ------------------------------------------------------------
	eax = serial[6];
	edx = serial[14];
	eax = eax+eax*2;
	eax = eax+edx*2;
	eax += serial[4];
	eax += serial[3];
	mas[1] = eax%233;
//--- mas[2] ------------------------------------------------------------
	eax = serial[5];
	eax += serial[14];
	eax += serial[3];
	eax += serial[6];
	eax += serial[2];
	eax += serial[4];
	mas[2] = eax%212;
//--- mas[3] ------------------------------------------------------------
	edx = serial[12];
	eax = serial[4];
	eax *= edx;
	eax += serial[13];
	mas[3] = eax%123;
//--- mas[4] ------------------------------------------------------------
	edx = serial[14];
	eax = serial[11];
	eax = edx + eax*2;
	edx = serial[6]*7;
	eax = edx + eax*2;
	edx = serial[2];
	edx = edx + edx*8;
	eax += edx;
	eax += serial[10];
	eax += serial[8];
	eax += serial[13];
	eax += serial[3];    
	eax += serial[12];
	mas[4] = eax%218;
//--- mas[5] -----------------------------------------------------------
	eax = serial[7];
	edx = serial[6];
	edx = edx + eax*4;
	eax = serial[4];
	eax = eax + eax*2;
	eax = eax + edx*2;
	eax += serial[2];
	eax += serial[8];
	eax += serial[3];
	eax += serial[2];
	mas[5] = eax%211;
//--- mas[6] -----------------------------------------------------------
	eax = serial[3];
	edx = eax + eax*2;
	eax = serial[9];
	eax = edx + eax*4;
	edx = serial[2]*11;
	eax += edx;
	edx = serial[5]*7;
	eax += edx;
	eax += serial[8];
	mas[6] = eax%244;
//--- mas[7] -----------------------------------------------------------
	eax = serial[11];
	ecx = serial[3];
	edx = ecx + eax*2;
	eax = serial[2];
	ecx = serial[9]*7;
	eax = eax + edx*2;
	edx = serial[12]*11;
	eax = eax + eax*2;
	eax += ecx;
	eax += edx;
	eax += serial[3];
	mas[7] = eax%123;
//-----------------------------------------------------------------------

Далее идет вот такой интересный кусок:

сейчас esi = 0;
сейчас ebp  = 171Eh

0040EFD9   . 8DA424 0000000>LEA ESP,DWORD PTR SS:[ESP]		; <- начало цикла
0040EFE0   > 3BEE           CMP EBP,ESI				; if( ebp > esi)
0040EFE2   . 7E 09          JLE SHORT EHSniffe.0040EFED
0040EFE4   . 8BFD           MOV EDI,EBP				; edi = ebp
0040EFE6   . 2BFE           SUB EDI,ESI				; edi = edi - esi
0040EFE8   . 83C7 59        ADD EDI,59				; edi = edi + 59h
0040EFEB   . EB 07          JMP SHORT EHSniffe.0040EFF4		; else
0040EFED   > 8BFE           MOV EDI,ESI				; edi = esi
0040EFEF   . 2BFD           SUB EDI,EBP				; edi = edi - ebp
0040EFF1   . 83C7 12        ADD EDI,12				; edi = edi + 12h
0040EFF4   > 3BEE           CMP EBP,ESI				
0040EFF6   . 7E 09          JLE SHORT EHSniffe.0040F001		; if( ebp > esi)
0040EFF8   . 8BC5           MOV EAX,EBP				; eax = ebp
0040EFFA   . 2BC6           SUB EAX,ESI				; eax = eax - esi
0040EFFC   . 83C0 03        ADD EAX,3				; eax = eax + 3
0040EFFF   . EB 07          JMP SHORT EHSniffe.0040F008		; else
0040F001   > 8BC6           MOV EAX,ESI				; eax = esi
0040F003   . 2BC5           SUB EAX,EBP				; eax = eax - ebp
0040F005   . 83C0 12        ADD EAX,12				; eax = eax + 12h
0040F008   > 99             CDQ					; edx = 0
0040F009   . B9 07000000    MOV ECX,7				; ecx = 7
0040F00E   . F7F9           IDIV ECX				; eax = eax/ecx ( в dl - остаток)
0040F010   . 33DB           XOR EBX,EBX
0040F012   . 8A5C34 18      MOV BL,BYTE PTR SS:[ESP+ESI+18]	; bl = mas[esi] - элемент массива
0040F016   . 53             PUSH EBX
0040F017   . FF5494 24      CALL DWORD PTR SS:[ESP+EDX*4+24]	; передаем bl в функцию
0040F01B   . 894424 50      MOV DWORD PTR SS:[ESP+50],EAX	; сохраняем результат в [12F104]
0040F01F   . 8BC7           MOV EAX,EDI				; eax = edi
0040F021   . 99             CDQ					; edx = 0
0040F022   . B9 07000000    MOV ECX,7				; ecx = 7
0040F027   . F7F9           IDIV ECX				; eax = eax/ecx ( в dl - остаток)
0040F029   . 53             PUSH EBX				
0040F02A   . FF5494 28      CALL DWORD PTR SS:[ESP+EDX*4+28]	; передаем bl в функцию
0040F02E   . 8B4C24 54      MOV ECX,DWORD PTR SS:[ESP+54]	; ecx = [12F104]
0040F032   . 03C1           ADD EAX,ECX				; eax = eax + ecx
0040F034   . 99             CDQ					; edx = 0
0040F035   . B9 2E250000    MOV ECX,252E			; ecx = 252Eh
0040F03A   . F7F9           IDIV ECX				; eax = eax/ecx ( в dl - остаток)
0040F03C   . 83C4 08        ADD ESP,8				; выравниваем стек
0040F03F   . 03EA           ADD EBP,EDX				; ebp = ebp + edx;
0040F041   . 46             INC ESI				; esi++;
0040F042   . 83FE 08        CMP ESI,8				; if( esi < 8)
0040F045   .^7C 99          JL SHORT EHSniffe.0040EFE0		; <- проверка на выход из цикла

Вот таким вот образом после 8 проходов по этому циклу ebp у нас должен стать равным
одной из 2-х констант, еще можно сказать пару слов про указатель на массив функций:

0040F017   . FF5494 24      CALL DWORD PTR SS:[ESP+EDX*4+24]
и он же
0040F02A   . FF5494 28      CALL DWORD PTR SS:[ESP+EDX*4+28]

Т.е в зависимости от значения EDX мы перейдем на ту или иную функцию этого массива. EDX - может принимать значения от 0 до 6, а сами функции очень маленькие и выполняют буквально 2,3 действия, поэтому (я решил массив функций заменить на switch() )
Получилось вот так:

	for( esi=0 ; esi<8 ; esi++)
	{
		if(ebp <= esi)
		{
			edi = esi;
			edi -= ebp;
			edi += 18;
		}
		else
		{
			edi = ebp;
			edi -= esi;
			edi += 89;
		}
        
		if(ebp <= esi)
		{
			eax = esi;
			eax -= ebp;
			eax += 18;
		}
		else
		{
			eax = ebp;
			eax -= esi;
			eax += 3;
		}
		
		ebx = mas[esi];
		edx = eax%7;

		switch(edx)
		{
			case 0:	eax = ebx + ebx*2; 
				eax = eax%58;
				eax += 888;		
				break;
			case 1:	eax = ebx + ebx + 91426;
				if( ebx != 0) eax = eax%ebx;
				break;
			case 2:	eax = ebx + 2373;		
				break;
			case 3:	eax = ebx*7 + 2126;
				eax = eax%253;
				break;
			case 4:	eax = ebx + 8537;
				eax = eax%2598;
				break;
			case 5:	eax = ebx - 79;
				break;
			case 6:	eax = ebx + 120;
				break;
		}
		
		ecx = eax;
		edx = edi%7;

		switch(edx)
		{
			case 0:	eax = ebx + ebx*2; 
				eax = eax%58;
				eax += 888;		
				break;
			case 1:	eax = ebx + ebx + 91426;
				if( ebx != 0) eax = eax%ebx;
				break;
			case 2:	eax = ebx + 2373;		
				break;
			case 3:	eax = ebx*7 + 2126;
				eax = eax%253;
				break;
			case 4:	eax = ebx + 8537;
				eax = eax%2598;
				break;
			case 5:	eax = ebx - 79;
				break;
			case 6:	eax = ebx + 120;
				break;
		}
		
		eax += ecx;

		ebp += eax%9518;
	}

Ну и соответственно нужно было придумать завершение функции, получилось так

	if(ebp == 11173 || ebp == 14896) return 1;

	return 0;
}

Как видим прога проверяет только серийник, имя ей по барабану.
Теперь у нас есть функция идентичная оригиналу...(вернет 1 - если серийник валидный и 0 если нет).

Многие спросят почему я решил переписать ее на другой язык и все-такое, мол, это гемор большой - просто мне так удобней да и если захотеть развернуть алгоритм генерации кода, то будет попроще (говорю про себя)! Можно было не переписывая попробовать вставить в экзешник свой код - тобишь сделать эдакий брут-форс(перебор серийников), который переходил бы на начало функции и потом если серийник левый менял его в памяти и повторял действие до получения правильного. Короче тут несколько способов - как говорится на любителя! Что сделал, то сделал...

После того как я получил работающую функцию проверки, мне разворачивать алгоритм генерации почему-то перехотелось ;) ( тем более неизвестно получилось бы), поэтому я написал простенькую рекурсивную функцию брут-форса! Поставил комп и думал идти хавать, так как это процесс обычно затяжной, но тут вдруг мне за 10 сек. вылезло 50 валидных серийников! ;)
Итак( вот несколько - проверяте! ):

Non-Commercial License:
P0000000100017Ya00
P0000000100023Pa00
P00000001000291a00
P000000010002Y1a00
P000000010009CGa00

Commercial License:
P00x000c10000Hva00
P00x000c10000Qxa00
P00x000c10000Zxa00
P00x000c10000j7a00
P00x000c10000wxa00

6) Вывод

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

Приветы всему cracklab, а также SniperZ, Nitrogen, Z0oMiK и др. которые поддержали... ;)

P.S. Если есть вопросы или нужны сорцы пишите в личку или на мыло ;)













Обсуждение статьи: Иследование HTTP Sniffer 4 по просьбам "трудящихся" >>>


Комментарии к статье: Иследование HTTP Sniffer 4 по просьбам "трудящихся"


Материалы находятся на сайте https://exelab.ru



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS