(Посвящается Lawyer'у) Аллоха, братья! Пару слов в микрофон: Классная софтина, мне понравилась. Ребята постарались на славу. И диз хорош, и ничего лишнего. Но еще больше мне понравилось то, что в логах был зафиксирован весь процесс ее регистрации: что запускал, в котором часу и на какие кнопки тыкал. Клево... Правда, эти логи были последним, что смог создать Perfect Keylogger, хе-хе... О защите: Использовался стандартный набор: Имя-серийник вкупе с nag-экраном и ограничением времени. Да, сроки триала ребята из Blazingtools Software урезали как могли, оставив лишь 3 дня. Скоро, чувствую, счет вообще будет идти на часы. Но не будем о грустном. Оборудование: ------------- .SoftICE .W32Dasm Рутину генерации серийника в проге найти более чем легко: Вводим какое-нибудь имя, например, Lawyer А потом какой-нибудь с/н: 1111-2222-3333-4444 Давим на 'ОК' и читаем мессагу: "Registration code or user name is invalid. Please check all fields and try again!". Затем грузим W32Dasm и ищем обращение к строке. Поднимаемся по ссылкам... и вот оно! ... :004110D1 8D8534FFFFFF lea eax, dword ptr [ebp+FFFFFF34] :004110D7 50 push eax :004110D8 8D8568FFFFFF lea eax, dword ptr [ebp+FFFFFF68] :004110DE 6880744300 push 00437480 :004110E3 50 push eax :004110E4 E861FEFFFF call 00410F4A ;<--- возможно генерация :004110E9 83C40C add esp, 0000000C :004110EC 8D459C lea eax, dword ptr [ebp-64] :004110EF 50 push eax :004110F0 8D8534FFFFFF lea eax, dword ptr [ebp+FFFFFF34] :004110F6 50 push eax :004110F7 FF151C414300 Call KERNEL32.lstrcmpiA ;<--- проверка :004110FD 5E pop esi :004110FE 85C0 test eax, eax :00411100 6A40 push 00000040 :00411102 7531 jne 00411135 ;<--- перейти, если неудача ... Анализируем: :004110F7 FF151C414300 Call KERNEL32.lstrcmpiA Эта API функция сравнивает строки, значит генерация уже была. И наверняка не очень давно. Смотрим, что у нас выше... :004110E4 E861FEFFFF call 00410F4A Незнамо что. Надо глянуть... :00410F4A 55 push ebp :00410F4B 8BEC mov ebp, esp :00410F4D 51 push ecx :00410F4E 51 push ecx :00410F4F 53 push ebx :00410F50 56 push esi :00410F51 FF750C push [ebp+0C] :00410F54 8B35B4404300 mov esi, KERNEL32.lstrlenA :00410F5A FFD6 call esi :00410F5C FF7508 push [ebp+08] :00410F5F 8BD8 mov ebx, eax :00410F61 895DFC mov dword ptr [ebp-04], ebx :00410F64 FFD6 call esi :00410F66 8BF0 mov esi, eax :00410F68 85F6 test esi, esi :00410F6A 8975F8 mov dword ptr [ebp-08], esi :00410F6D 7508 jne 00410F77 :00410F6F 8B4510 mov eax, dword ptr [ebp+10] :00410F72 802000 and byte ptr [eax], 00 :00410F75 EB4E jmp 00410FC5 :00410F77 57 push edi :00410F78 8B7D10 mov edi, dword ptr [ebp+10] :00410F7B FF750C push [ebp+0C] :00410F7E 57 push edi :00410F7F FF153C414300 Call KERNEL32.lstrcpyA :00410F85 3BF3 cmp esi, ebx :00410F87 89750C mov dword ptr [ebp+0C], esi :00410F8A 7F03 jg 00410F8F :00410F8C 895D0C mov dword ptr [ebp+0C], ebx :00410F8F 33F6 xor esi, esi :00410F91 39750C cmp dword ptr [ebp+0C], esi :00410F94 7E2C jle 00410FC2 :00410F96 8BC6 mov eax, esi :00410F98 6A19 push 00000019 :00410F9A 99 cdq :00410F9B F77DFC idiv [ebp-04] :00410F9E 8BC6 mov eax, esi :00410FA0 5B pop ebx :00410FA1 8D0C3A lea ecx, dword ptr [edx+edi] :00410FA4 99 cdq :00410FA5 F77DF8 idiv [ebp-08] :00410FA8 8B4508 mov eax, dword ptr [ebp+08] :00410FAB 0FB60402 movzx eax, byte ptr [edx+eax] :00410FAF 0FB611 movzx edx, byte ptr [ecx] :00410FB2 33C2 xor eax, edx :00410FB4 99 cdq :00410FB5 F7FB idiv ebx :00410FB7 80C241 add dl, 41 :00410FBA 46 inc esi :00410FBB 3B750C cmp esi, dword ptr [ebp+0C] :00410FBE 8811 mov byte ptr [ecx], dl :00410FC0 7CD4 jl 00410F96 :00410FC2 8BC7 mov eax, edi :00410FC4 5F pop edi :00410FC5 5E pop esi :00410FC6 5B pop ebx :00410FC7 C9 leave :00410FC8 C3 ret Отлично, она самая... В SoftICE можно ставить курсор на :00410FC4 5F pop edi и в командной строке here [ввод] d eax [ввод] Увидите что-то типа "TTMTMMNFPKMQHJQO" Разделяете строку на 4 равные части - вот вам и серийник (TTMT-MMNF-PKMQ-HJQO). Все, взлом завершен успешно... А теперь о рутине генерации. :00410F51 FF750C push [ebp+0C] :00410F54 8B35B4404300 mov esi, KERNEL32.lstrlenA :00410F5A FFD6 call esi Определяем длину "странной строки". Под "странной строкой" будем понимать 16 байт 5F 72 20 3C 40 7E 3D 31 2D 5A 32 5B 6C 35 2C 5E по адресу :00437480 или смещению в файле @37480. :00410F5C FF7508 push [ebp+08] :00410F5F 8BD8 mov ebx, eax :00410F61 895DFC mov dword ptr [ebp-04], ebx :00410F64 FFD6 call esi :00410F66 8BF0 mov esi, eax :00410F68 85F6 test esi, esi :00410F6A 8975F8 mov dword ptr [ebp-08], esi :00410F6D 7508 jne 00410F77 Записываем длину "странной строки" по адресу [ebp-4], а затем определяем длину имени. Полученное значение сравниваем с нулем и пишем по адресу [ebp-8]. Если длина имени равна нулю - на выход. :00410F77 57 push edi :00410F78 8B7D10 mov edi, dword ptr [ebp+10] :00410F7B FF750C push [ebp+0C] :00410F7E 57 push edi :00410F7F FF153C414300 Call KERNEL32.lstrcpyA Копируем "странную строку" в буфер. Дальше работаем с этим буфером. В нем же будет накапливаться правильный серийник. :00410F85 3BF3 cmp esi, ebx :00410F87 89750C mov dword ptr [ebp+0C], esi :00410F8A 7F03 jg 00410F8F :00410F8C 895D0C mov dword ptr [ebp+0C], ebx :00410F8F 33F6 xor esi, esi :00410F91 39750C cmp dword ptr [ebp+0C], esi :00410F94 7E2C jle 00410FC2 Сравниваем длину имени и "странной строки". Большее значение пишем по адресу [ebp+0C]. Если получилось не больше нуля - на выход. :00410F96 8BC6 mov eax, esi ;берем номер текущего символа :00410F98 6A19 push 00000019 :00410F9A 99 cdq :00410F9B F77DFC idiv [ebp-04] ;делим на длину "странной строки" :00410F9E 8BC6 mov eax, esi ;берем номер текущего символа :00410FA0 5B pop ebx :00410FA1 8D0C3A lea ecx, dword ptr [edx+edi] :00410FA4 99 cdq :00410FA5 F77DF8 idiv [ebp-08] ;делим на длину имени :00410FA8 8B4508 mov eax, dword ptr [ebp+08] :00410FAB 0FB60402 movzx eax, byte ptr [edx+eax] :00410FAF 0FB611 movzx edx, byte ptr [ecx] :00410FB2 33C2 xor eax, edx :00410FB4 99 cdq :00410FB5 F7FB idiv ebx :00410FB7 80C241 add dl, 41 :00410FBA 46 inc esi :00410FBB 3B750C cmp esi, dword ptr [ebp+0C] :00410FBE 8811 mov byte ptr [ecx], dl :00410FC0 7CD4 jl 00410F96 Основной цикл генерации. Прост до безобразия. Берем символ из "странной строки", ксорим (выполняем операцию XOR) его с символом из имени, результат делим на 25, а к остатку прибавляем 65 (чтобы получился ASCII-символ). Пишем результат на место текущего символа из "странной строки". Если символы одной из строк заканчиваются, перебор этой строки начинается с нуля. И так пока не наберется 16 символов регистрационного ключа. Так, теперь у нас достаточно данных для построения генератора. Вот вам в пример процедура в синтаксисе MASM32 Generate proto :DWORD, :DWORD, :DWORD, :DWORD
Generate proc uses edi esi ebx lpName:DWORD, nameLen:DWORD, lpStr:DWORD, strLen:DWORD LOCAL Len:DWORD mov edi, lpStr mov eax, nameLen cmp eax, strLen mov Len, eax jg _lb1 push strLen pop Len _lb1: xor esi, esi _lbLOOP: mov eax, esi push 19h xor edx, edx idiv strLen pop ebx lea ecx, dword ptr [edx+edi] mov eax, esi xor edx, edx idiv nameLen mov eax, lpName movzx eax, byte ptr [edx+eax] movzx edx, byte ptr [ecx] xor eax, edx xor edx, edx idiv ebx add dl, 41h inc esi cmp esi, Len mov byte ptr [ecx], dl jl _lbLOOP mov eax, edi ret Generate endp Параметры: lpName - указатель на имя (завершаемая нулем ASCII-строка) nameLen - длина имени (без учета завершающего нуля) lpStr - указатель на "странную строку" strLen - длина "странной строки" Возврат: регистр EAX - указывает на буфер, содержащий правильный рег. ключ На сегодня все, мальчики и девочки. Спокойной ночи и до новых встреч! P.S. Stop shareware expansion...
Дата: август 29, 2oo3 Автор: (ry0 E-mail: cryo#cydem.org.ua ICQ #: l79S2lSOS
Материалы размещены на http://cracklab.narod.ru/doc/ с разрешения http://cydem.zp.ua/