. _ . _ -|-------------------------/-//--|- // / _______________ | __ _____ | \_ _/_ \_____·/ \/ \ | / / / /_ / _ / t e a m | -/-----/\________/ \__\___/--/- 5 3 | /____/\____\ --- | . | wPx _ | _ | \ \\ -|--\\-\-------------------------|- Tutorials . Pack . Number . #13 Атака на ASProtect SKE. 1. Введение ASProtect SKE(далее - аспр) предоставляет разработчикам софта функцию СheckKeyAndDecrypt(прим.пер. - смотрим хелп аспра и сдк). Эта функция проверяет рег. код и сохраняет его. Если рег. код верный, то аспр расшифрует покриптованные куски кода (так называемые encrypted sections), помеченные макросами REG_CRYPT_BEGIN и REG_CRYPT_END(прим.пер.-опять таки смотрим сдк). Данный туториал состоит из двух частей - про замену экспонент и про брутфорс ключа. Инструментарий: - OllyDbg - UltraEdit Часть 1. Подмена экспонент Аспр использует криптосистему RSA в рег. кодах. Только создатель программы, который знает приватную экспоненту, может генерировать ключи. Аспр использует публичную экспоненту для проверки ключа. Практически невозможно самому сгенерировать ключ, так как приватную экпоненту знает только автор. Аспр получит некоторые данные из ключа, мы можем сгенерировать другие рса экспоненты, заменить их в аспре на свои, и используя эти данные - генерировать другие ключи. Нашей целью будет Asprotect 2.3 SKE build 03.19 Beta. Надеюсь у вас есть верный ключ(приведенный здесь - конечно ненастоящий), в путь ^_^. Name: shoooo Key: HGV8K-TVKCW-28L5K-2TZMT-LZNT3-GPJDM-NQG3D-N7QMT-VXVEE-FHK7K 1.1 Нахождение Encryption COnst Итак, грузим аспр в ольку. Включаем полный игнор всех исключений, а также какой-нибудь плагин, который "защитит" нас от IsDebuggerPresent. Жмем SHift+F9 и видим Activation Wizard аспра. Найдите image base дллки аспра, у меня - 1090000h. Поставьте бряк по RVA - 1B320h, относительно найденного image base. Это - процедура проверки введенной рег. инфы. 010AB3120 PUSH EBP 010AB3121 MOV EBP,ESP 010AB3123 ADD ESP,-18 010AB3126 PUSH EBX 010AB3127 PUSH ESI 010AB3128 PUSH EDI 010AB3129 XOR EBX,EBX 010AB312B MOV DWORD PTR SS:[EBP-10],EBX 010AB312E MOV DWORD PTR SS:[EBP-14],EBX 010AB3121 MOV DWORD PTR SS:[EBP-18],EBX Нажмите Next в Activation Wizard аспра, выберите Offline Activation, нажмите Next, введите 'ASP' и опять нажмите Next. Введите рег. данные и нажмите Next Name: shoooo Key: HGV8K-TVKCW-28L5K-2TZMT-LZNT3-GPJDM-NQG3D-N7QMT-VXVEE-FHK7K Брякнулись на 10AB320h, в самом начале проверки рег. инфы. Посмотрим в окно регистров. EAX 01164BB8 ASCII "shoooo" ECX 010CCDCA EDX 01164F08 ASCII "HGV8K-TVKCW-28L5K-2TZMT-LZNT3-GPJDM-NQG3D-N7QMT-VXVEE-FHK7K" EBX 010CC8DA ASCII "Single Developer License" ESP 0012F288 EBP 0012F2B8 ESI 011645F8 EIP 010AB320 EAX указывает на имя EDX - на рег. код EBX - название текущего режима ECX - структуру о регистрации, назовем ее структурой T ECX -> Follow in dump и видим структуру T в окне дампа: 010CCDCA 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 ............... 010CCDDA 00[01]00 00 00 00 00 00 00 00 00 00 00 00 00 00 ............... 010CCDEA 00 00 00[00 05 0E 01|C0 05 0E 01|80 06 0E 01]01 ....П.АП.ЂП. 010CCDFA 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 ............. Первая помеченная область([01]) - Use Hardware Locking, нам надо поменять этот байт на 00. Привязка по Hardware ID не играет важной роли при проверки ключа, я вернусь к этому позднее. 010E0500h указывает на RSA Public Key P5 010E05C0h указывает на RSA Public Key P6 010E0680h указывает на RSA Public Key P7 Я вернусь к P5,P6,P7 позднее. В Asprotect 2.3 SKE build 03.19 Beta - 2 рег. режима: - 'Single Developer License' - 'Company Developer License' Поэтому процедура 010AB320h будет вызвана дважды. И если хоть раз проверка вернет положительный результат(будь то режим 1 или 2), то прога будет зарегистрирована. 010AB320 push ebp 010AB321 mov ebp,esp 010AB323 add esp,-18 010AB326 push ebx 010AB327 push esi 010AB328 push edi 010AB329 xor ebx,ebx 010AB32B mov dword ptr ss:[ebp-10],ebx 010AB32E mov dword ptr ss:[ebp-14],ebx 010AB331 mov dword ptr ss:[ebp-18],ebx 010AB334 mov edi,ecx 010AB336 mov esi,edx 010AB338 mov dword ptr ss:[ebp-C],eax 010AB33B xor eax,eax 010AB33D push ebp 010AB33E push 10AB4D5 010AB343 push dword ptr fs:[eax] 010AB346 mov dword ptr fs:[eax],esp 010AB349 xor ebx,ebx 010AB34B xor eax,eax 010AB34D push ebp 010AB34E push 10AB4AE 010AB353 push dword ptr fs:[eax] 010AB356 mov dword ptr fs:[eax],esp 010AB359 lea edx,dword ptr ss:[ebp-10] 010AB35C mov eax,esi 010AB35E call 010AB0D4 010AB35Eh call 010AB0D4h - переводит введеный ключ в hex. Перевод осуществляется с помощью таблицы и комбинации из 5 бит. Было: HGV8K-TVKCW-28L5K-2TZMT-LZNT3-GPJDM-NQG3D-N7QMT-VXVEE-FHK7K Стало: E6 9F 93 19 A4 54 C7 95 B4 E2 37 5C 55 76 47 26 6A 06 B6 38 D9 1B 3A E5 C6 75 99 08 53 A7 A9 010AB363 test al,al 010AB365 jnz short 010AB374 010AB367 xor eax,eax 010AB369 pop edx 010AB36A pop ecx 010AB36B pop ecx 010AB36C mov dword ptr fs:[eax],edx 010AB36F jmp 010AB4BA 010AB374 mov eax,edi 010AB376 call 010AB29C 010AB37B mov esi,eax 010AB37D mov eax,dword ptr ss:[ebp-10] 010AB380 call 01093954 010AB385 mov ebx,eax 010AB387 sub ebx,esi 010AB389 lea eax,dword ptr ss:[ebp-14] 010AB38C push eax 010AB38D mov ecx,esi 010AB38F mov edx,1 010AB394 mov eax,dword ptr ss:[ebp-10] 010AB397 call 01093B5C 010AB39C lea eax,dword ptr ss:[ebp-18] 010AB39F mov ecx,dword ptr ss:[ebp-C] 010AB3A2 mov edx,dword ptr ss:[ebp-14] 010AB3A5 call 010939A0 010AB3AA lea eax,dword ptr ss:[ebp-10] 010AB3AD call 01093B24 010AB3B2 add eax,esi 010AB3B4 push eax 010AB3B5 push ebx 010AB3B6 mov eax,dword ptr ss:[ebp-18] 010AB3B9 call 01093954 010AB3BE push eax 010AB3BF lea eax,dword ptr ss:[ebp-18] 010AB3C2 call 01093B24 010AB3C7 mov edx,eax 010AB3C9 lea eax,dword ptr ds:[edi+23] 010AB3CC pop ecx 010AB3CD call 010AABA8 Тут ключ(вернее ключ в hex форме) разделяется на 2 части. Первые 7 байт: E6 9F 93 19 A4 54 C7 Остальные 24: 95 B4 E2 37 5C 55 76 47 26 6A 06 B6 38 D9 1B 3A E5 C6 75 99 08 53 A7 A9 010AB3CDh call 010AABA8h - проверка 24 байт-второй части ключа, с помощью P5, P6 и P7. Если проверка завершится успешно - процедура вернет 1. Мы можем это обойти, так что эти 24 байта не играют важной роли для нас. 010AB3D2 mov ebx,eax 010AB3D4 test bl,bl 010AB3D6 je 010AB4A4 010AB3DC mov eax,dword ptr ss:[ebp-C] 010AB3DF call 01093954 010AB3E4 push eax 010AB3E5 lea eax,dword ptr ss:[ebp-14] 010AB3E8 call 01093B24 010AB3ED push eax 010AB3EE mov eax,dword ptr ss:[ebp-C] 010AB3F1 call 01093B18 010AB3F6 mov ecx,eax 010AB3F8 mov edx,esi 010AB3FA pop eax 010AB3FB call 0109BE0C 010AB3FB call 0109BE0C - расшифровка первых 7 байт hex-ключа. Используется RC4. Ключ для RC4 - наше имя, в данном случае: "shoooo". Так что для нас важны - имя и первые 7 байт ключа. 010AB400 lea eax,dword ptr ss:[ebp-14] 010AB403 call 01093B24 010AB408 mov dword ptr ss:[ebp-4],eax 010AB40B mov byte ptr ss:[ebp-5],1 010AB40F push ebp 010AB410 mov eax,4 010AB415 call 010AB2DC 010AB41A pop ecx 010AB41B mov byte ptr ds:[edi+1],al Здесь в al будет текущий ModeID, полученный из ключа. Если вы хотите заполучить Single Developer License, в al должна быть еденица. 010AB41E push ebp 010AB41F mov eax,4 010AB424 call 010AB2DC 010AB429 pop ecx 010AB42A mov byte ptr ds:[edi],al 010AB42C push ebp 010AB42D mov eax,0C 010AB432 call 010AB2DC 010AB437 pop ecx 010AB438 mov word ptr ds:[edi+2],ax 010AB43C cmp byte ptr ds:[edi+E],0 010AB440 jnz short 010AB448 010AB442 cmp byte ptr ds:[edi+11],0 010AB446 jnz short 010AB45A 010AB448 push ebp 010AB449 mov eax,0C 010AB44E call 010AB2DC 010AB453 pop ecx 010AB454 mov word ptr ds:[edi+4],ax 010AB458 jmp short 010AB460 010AB45A mov word ptr ds:[edi+4],0 010AB460 cmp byte ptr ds:[edi+F],0 010AB464 jnz short 010AB46C 010AB466 cmp byte ptr ds:[edi+11],0 010AB46A jnz short 010AB47D 010AB46C push ebp 010AB46D mov eax,20 010AB472 call 010AB2DC 010AB472 call 010AB2DC - получение некоего DWORDа из расшифрованных первых 7 байт ключа. Если эти данные правильны, но пошифрованные куски кода будут расшифрованы. Назовем этот DWORD - Encrypted Const. 010AB4BE pop ecx 010AB4BF mov dword ptr fs:[eax],edx 010AB4C2 push 10AB4DC 010AB4C7 lea eax,dword ptr ss:[ebp-18] 010AB4CA mov edx,3 010AB4CF call 0109371C 010AB4D4 retn 010AB4D5 jmp 0109311C 010AB4DA jmp short 010AB4C7 010AB4DC mov eax,ebx 010AB4DE pop edi 010AB4DF pop esi 010AB4E0 pop ebx 010AB4E1 mov esp,ebp 010AB4E3 pop ebp 010AB4E4 retn Конец процедуры, если все прошло нормально, вернет 1. Смотрим на структуру T в окне дампа: 010CCDCA 01[01]A7 04 00 00[4E 61 BC 00]00 00 00 00 00 01 ?......... 010CCDDA 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ............... 010CCDEA 00 00 00 00 05 0E 01 C0 05 0E 01 80 06 0E 01 01 ....П.АП.ЂП. 010CCDFA 01 01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 ............. Первый выделенный байт([01]) - ModeID = 1. 00BC614Eh: 'EncryptionConst', для расшифровки encrypted sections. Теперь нам нужно создать проэкт, сгенерировать пару ключей RSA, прпоатчить публиную экспоненту в аспре на свою. 1.2 Создаем проэкт Запускаем Asprotect SKE(например Asprotect SKE 2.11 build 03.13 Release). В меню - Project->New project, выставляем опции, вкладка Modes: - помечаем Is This Mode Active? - Mode name: 'Single Developer License' - помечаем Is This Mode in Registered State? - помечаем Use Activations Keys - Singature size -> Type III - помечаем Unlock Encrypted Sections Ну, и Сохраняем проэкт в файл - 'test.aspr2'. Просмотрим test.aepr2 в UltraEdit: [Activation Keys 1] p1=E3F23E039A49EF1B3A3F6ED2B1008BC5 p3=F9909CC20901EEE1F11951AB62512123 p5=E013BB36B2659FC3EE22DBDD30F4E838AF1EE6910E35F7E880C72AF02E13396 04D5F8C30394A8D734ED6D29EE94FAF03E0C90D2FE8C54437DEAAAF1D77954DC5F 312BEC881AF845686858756795EC1F233FD1EEF2DA2E0EB68B579A2109C1C3A5FA 3F609F1FC7FBE8C0F008DF32C604711466AE11D02F43D47D68C6B2A70CC98 p6=10DF36C37A45990F17DE3C2BDDAF020A0140EA68AE0E570997A991F2B947F71 2599B6F1CA42315D94BFFC5E990B544FB898E9E9108E5A71869A2E145F32042EDA 713383FAA51483038A535C05B441782C48CB44085E8130E9A3A74EA8516E7D93D0 0464A918B6B4E8FE1D301511CE19FA57D0E485D1ED3821D907A19AE8A3FE64 p7=12D9DA3EA116EDB35C5723EBF30A9932FC27EE3CF73C4905C2016FFFF3177F7 E3C1A17C0E4DBEEE2E73CC260A495A00AAC9202213BB401D6A7540B09529042922 7F9BF41E57A889AB62FF81391651A99A29CA709DCF3ECC8A912B44D6C30DFF82EE 385144C9E31F63ED0F5D0CE7F991109A840F2A18F1F50B53346C67FAAFB005 SignatureSize=192 ModeID=1 UseHardwareLocking=0 -------------------- EncryptionConst=2383683100 // поменяйте на 12345678 (00BC614Eh) P1 - RSA Private Key P3 - RSA Private Key P5 - RSA Public Key P6 - RSA Public Key P7 - RSA Public Key Меняем EncryptionConst на нашу - и сохраняем файл. В Asprotect 2.3 SKE build 03.19 Beta мы можем найти p5, p6 и p7. p1, p3 и EncryptionConst знает только автор. Имея рабочий ключ - мы может узнать EncryptionConst, но мы не сможем узнать p1 и p3. Только что, мы сгенерировали пару ключей RSA и нашли EncryptedConst. Теперь нам нужно заменить публичные экспоненты в аспре на свои. Конечно, мы не будем публиковать наши p1 и p3. 1.3 Патч p5, p6, p7 P5, P6 и P7 хранятся в программе в зашифрованном виде. Мы должны расшифровать их, заменить и зашифровать. Запускаем ollydbg, доходим до EP дллки аспра. Жмем Ctrl+S (search a sequence of commands), вводим: push ebp mov ebp, esp add esp, -200 Жмем ОК. -- Если вы не знаете как дойти до EP дллки аспра - поставьте бряк в коцне GetModuleHandleA, когда брякнетесь второй раз - F8, найдите конце аспака, поставьте бряк, F9, F8. И мы на EP: 010CA14C push ebp 010CA14D mov ebp,esp 010CA14F add esp,-4C 010CA152 mov eax,10C9E7C 010CA157 call 01095D64 010CA15C call 010935C0 -- Команды нашлись здесь: 0109BE0C push ebp 0109BE0D mov ebp,esp 0109BE0F add esp,-200 0109BE15 push ebx 0109BE16 push esi 0109BE17 mov esi,edx 0109BE19 mov ebx,eax 0109BE1B lea eax,dword ptr ss:[ebp-200] 0109BE21 mov edx,ecx 0109BE23 mov ecx,dword ptr ss:[ebp+8] 0109BE26 call 0109BE50 0109BE2B push esi 0109BE2C lea eax,dword ptr ss:[ebp-200] 0109BE32 mov ecx,ebx 0109BE34 mov edx,ebx 0109BE36 call 0109BEE8 // ставим бряк 0109BE3B lea eax,dword ptr ss:[ebp-200] 0109BE41 call 0109BED8 0109BE46 pop esi 0109BE47 pop ebx 0109BE48 mov esp,ebp 0109BE4A pop ebp 0109BE4B retn 4 Поставьте бряк на 0109BE36h. F9! 0109BE36h call 0109BEE8h - расшифровка блока данных, по алгоритму RC4. EAX указывает на ключ RC4, длинной в 100h байт EDX указывает на зашифрованный блок Если ключ не меняется, то RC4 Encrypt == Decrypt. Так что, нам надо сохрнаить 100h байтный ключ. EAX->Follow in dump. И сохраните куда-нибудь эти 100h байт. B2 20 D7 58 3E 3C 48 18 7F F6 89 CD E3 4E 9D D8 69 9B 05 1E E9 BD 2D 98 A1 AF EE DA 31 FF CF 0E 88 DE 67 1D 40 60 13 D0 A6 4A 6A 54 57 50 BE 9C 5E 72 83 6E CA 3A 4B 35 70 B4 2C B0 2B 7B AC 14 7C 64 7D 5B D3 66 B7 5C 7A C0 5F 0C 39 C5 0F 4F E1 F2 D6 75 10 B6 29 F9 5D 92 FE CB 52 32 04 CC 74 D9 C9 0D 49 95 AE F0 91 36 09 76 8C B9 BC 0B 84 38 77 73 90 D2 BF E8 79 6B 8F BA 63 E2 6F 24 41 9F 94 47 A2 15 0A 6D AB A3 9A 82 E0 97 EF 8D 30 1A 59 12 03 65 F1 3B F4 B1 2F E6 A4 CE 11 B8 34 46 27 EC AA D1 28 42 33 22 96 DD 71 87 3F C1 A9 AD F7 1F 4C A7 80 23 7E 86 51 45 DF 44 08 56 3D 1B EB 00 4D 93 21 B5 99 F5 C3 85 DB 5A 16 E5 A8 E4 FC A5 C2 C4 53 2A 43 55 2E 25 1C 8E 61 FB FA 01 6C 78 06 F8 81 B3 D5 BB FD 8B D4 F3 8A 68 C7 C8 26 DC 19 07 C6 EA 02 A0 9E E7 62 ED 17 37 100h RC4 ключ EDX->Follow in dump. Жмем F8 и смотрим в окно дампа - на расшифрованные данные. Найдите P5, P6, P7. У меня они начинаются здесь - 010F356C. Третий байт 01 от этого адреса - Hardware Locking, дальше идут P5, P6 и P7. Посмотрим наши экспоненты в test.aspr2: p5=E013BB36B2659FC3EE22DBDD30F4E838AF1EE6910E35F7E880C72AF02E13 39604D5F8C30394A8D734ED6D29EE94FAF03E0C90D2FE8C54437DEAAAF1D779 54DC5F312BEC881AF845686858756795EC1F233FD1EEF2DA2E0EB68B579A210 9C1C3A5FA3F609F1FC7FBE8C0F008DF32C604711466AE11D02F43D47D68C6B2 A70CC98 p6=10DF36C37A45990F17DE3C2BDDAF020A0140EA68AE0E570997A991F2B947 F712599B6F1CA42315D94BFFC5E990B544FB898E9E9108E5A71869A2E145F32 042EDA713383FAA51483038A535C05B441782C48CB44085E8130E9A3A74EA85 16E7D93D00464A918B6B4E8FE1D301511CE19FA57D0E485D1ED3821D907A19A E8A3FE64 p7=12D9DA3EA116EDB35C5723EBF30A9932FC27EE3CF73C4905C2016FFFF317 7F7E3C1A17C0E4DBEEE2E73CC260A495A00AAC9202213BB401D6A7540B09529 0429227F9BF41E57A889AB62FF81391651A99A29CA709DCF3ECC8A912B44D6C 30DFF82EE385144C9E31F63ED0F5D0CE7F991109A840F2A18F1F50B53346C67 FAAFB005 Перевернем их: p5=98CC702A6B8CD6473DF4021DE16A461147602CF38D000F8CBE7FFCF109F6 A35F3A1C9C10A279B568EBE0A22DEF1EFD33F2C15E79568785865684AF81C8B E12F3C54D95771DAFAADE3744C5E82F0DC9E003AF4FE99ED2D64E738D4A3930 8C5F4D6039132EF02AC780E8F7350E91E61EAF38E8F430DDDB22EEC39F65B23 6BB13E0 p6=64FEA3E89AA107D92138EDD185E4D057FA19CE1115301DFEE8B4B618A964 04D0937D6E51A84EA7A3E930815E0844CB482C7841B4055C538A038314A5FA8 33371DA2E04325F142E9A86715A8E10E9E998B84F540B995EFCBF945D3142CA F1B69925717F942B1F997A9970E5E08AA60E14A020F0DABDC2E37DF19059A43 76CF30D01000000 p7=05B0AFFA676C34530BF5F1182A0F849A1091F9E70C5D0FED631FE3C94451 38EE82FF0DC3D6442B918ACC3ECF9D70CA299AA951163981FF62AB89A8571EF 49B7F2229042995B040756A1D40BB132220C9AA005A490A26CC732EEEBE4D0E 7CA1C1E3F77731FFFF16205C90C473CFE37EC22F93A930BF3E72C535DB6E11E AA39D2D01000000 И замените ими те, что в аспре(начиная с 010F356C). Теперь Set new origin here -> 0109BE2Bh. Протрассируем до 109BE36h. EAX->Follow in dump и вставляем сохраненный 100h байтный ключ. Ну, а дальше - трассируем до 0109BE3Bh по F8. Все, данные зашифрованы. Теперь надо заменить это все в файле. Это несложно, так как мы знаем зашифрованыне данные - ищем их в ехе и меняем на свои. 1.4 Патч проверки CRC После наших изменений в Asprotect.exe CRC файла изменилось. Грузим пропатченный файл в ollydbg. Доходим до EP дллки аспра, Ctrl+S и ищем: mov ebx, [eax] mov eax, esi Нашлось здесь: 010C8786 mov ebx,dword ptr ds:[eax] 010C8788 mov eax,esi 010C878A call 010ABA88 010C878F add eax,dword ptr ds:[10D4188] 010C8795 call 010C859C 010C879A mov dword ptr ds:[10D4180],eax 010C879F xor ebx,dword ptr ds:[10D4184] 010C87A5 cmp ebx,dword ptr ds:[10D4180] 010C87AB je short 010C87B1 Поставим бряк на 010C879Fh, нажмем SHIFT+F9 и брякнемся на 010C879Fh. EBX - значение CRC, которое мы можем найти в ехе файле. Новое CRC - [10D4184h] XOR [10D4180h], вычисляем его и заменяем старое в файле. Теперь - все ок! Все готов и мы можем сделать кейген. 2. Брутфорс ключа Если у нас нету рабочего ключа - что бы мы делали? Факторизация публичной экспоненты RSA - ужасно долгий процесс. Все, что придумал я - брутфорс EncryptionConst. Все делаем с тем жеAsprotect 2.3 SKE build 03.19 Beta. Процедура 010AB320h - проверка ключа. ЕСли ключ правильный - мы можем брякнуться на 010AB594h. 010AB594 push ebx 010AB595 push esi 010AB596 push edi 010AB597 push ebp 010AB598 add esp,-14 010AB59B mov edi,ecx 010AB59D mov esi,edx 010AB59F mov dword ptr ss:[esp],eax 010AB5A2 mov bl,1 010AB5A4 push 4 010AB5A6 lea eax,dword ptr ss:[esp+4] 010AB5AA push eax 010AB5AB lea eax,dword ptr ss:[esp+C] 010AB5AF push eax 010AB5B0 call 010A3FE8 010AB5B0h call 010A3FE8h - получение MD5 от EncryptionConst из ключа: MD5Init(&MD5_ctx); MD5Update(&MD5_ctx, (char *)&EncryptionConst, 4); MD5Final(outbuffer, &MD5_ctx); 010AB5B5 push esi 010AB5B6 push edi 010AB5B7 mov edi,esi 010AB5B9 lea esi,dword ptr ss:[esp+C 010AB5BD mov ecx,4 010AB5C2 rep movsd 010AB5C4 pop edi 010AB5C5 pop esi 010AB5C6 mov ebp,7530 // !!!!!!!! 010AB5CB push 10 010AB5CD push esi 010AB5CE lea eax,dword ptr ss:[esp+C 010AB5D2 push eax 010AB5D3 call 010A3FE8 010AB5D8 push esi 010AB5D9 push edi 010AB5DA mov edi,esi 010AB5DC lea esi,dword ptr ss:[esp+C 010AB5E0 mov ecx,4 010AB5E5 rep movsd 010AB5E7 pop edi 010AB5E8 pop esi 010AB5E9 dec ebp 010AB5EA jnz short 010AB5CB 010AB5EC mov dword ptr ds:[edi],10 010AB5F2 mov eax,ebx 010AB5F4 add esp,14 010AB5F7 pop ebp 010AB5F8 pop edi 010AB5F9 pop esi 010AB5FA pop ebx 010AB5FB retn Получение MD5 хеша 3000(7530h) раз: for (int i=0; i<30000; i++) { MD5Init(&MD5_ctx); MD5Update(&MD5_ctx, outbuffer, 16); MD5Final(outbuffer, &MD5_ctx); } Если EncryptionConst правильная, 010AB594h - получит уже 30001-й хеш. Поставим бряк на 010A49A7h. Тут уже начинается расшифровка encrypted sections: 010A49A2 mov eax,dword ptr ss:[ebp-4] 010A49A5 mov edx,dword ptr ds:[eax] 010A49A7 call dword ptr ds:[edx+8] 010A49A7h call [edx+8] - 30002-й хеш. 010A49AA mov eax,dword ptr ss:[ebp-4] 010A49AD mov eax,dword ptr ds:[eax] 010A49AF call dword ptr ds:[eax+10] 010A49B2 push eax 010A49B3 mov eax,dword ptr ss:[ebp-4] 010A49B6 mov edx,dword ptr ds:[eax] 010A49B8 call dword ptr ds:[edx+C] 010A49BB mov ecx,eax 010A49BD mov edx,esi 010A49BF mov eax,ebx 010A49C1 call 0109BE0C 010A49C1h call 0109BE0Ch - расшифровка таблицы encrypted sections, с помощью RC4. EAX - зашифрованная таблица ECX - 16 байтовый ключ из хеша EncryptionConst Зашифрованная таблица: 11 80 DC 56 AE A7 30 1C F4 09 7E 90 95 82 DC 56 2A A5 30 1C 04 09 7E 90 A4 9F DC 56 25 B8 30 1C 4C 09 7E 90 96 5E DF 56 17 79 33 1C 79 09 7E 90 AE 6F DF 56 2F 48 33 1C 30 09 7E 90 CB 69 DF 56 40 4E 33 1C D7 09 7E 90 59 7C DF 56 D6 5B 33 1C A6 09 7E 90 9C 7F DF 56 1D 58 33 1C 2F 09 7E 90 18 1F DF 56 91 38 33 1C 77 08 7E 90 56 62 DE 56 D7 45 32 1C F2 09 7E 90 9F 33 12 00 A4 33 12 00 61 00 00 00 1B 31 12 00 20 31 12 00 91 00 00 00 2A 2C 12 00 2F 2C 12 00 D9 00 00 00 18 ED 11 00 1D ED 11 00 EC 00 00 00 20 DC 11 00 25 DC 11 00 A5 00 00 00 45 DA 11 00 4A DA 11 00 42 00 00 00 D7 CF 11 00 DC CF 11 00 33 00 00 00 12 CC 11 00 17 CC 11 00 BA 00 00 00 96 AC 11 00 9B AC 11 00 E2 01 00 00 D8 D1 10 00 DD D1 10 00 67 00 00 00 Имея хотя бы 1 адрес пошифрованного куска кода(поиск E9 ?? ?????? в секции кода ) - мы можем начать брутфорс EncryptedConst. 2.2 Собственно брутфорс Наши выводы - если аспр поулчил из ключа правильную EncryptionConst, то он получает ее MD5 хш 30002 раза и расшифровывает таблицу encrypted sections. Но если у нас нет правильного ключа - мы не можем найти EncryptionConst. Но мы можем найти таблицу encrypted sections, хотя бы 1 такую секцию в коде и брутфорсить EncryptionConst. BOOL Check(BYTE key[4]) { …… MD5Init(&ctx); MD5Update(&ctx, key, 4); MD5Final(md5key, &ctx); for (i=0; i<30001; i++) { MD5Init(&ctx); MD5Update(&ctx, md5key, 16); MD5Final(md5key, &ctx); } rc4_initkey(md5key, 16, &rc4ctx); rc4_crypt(data1, 12, &rc4ctx); if (memcmp(data1, “….”, 12) == 0) { return TRUE; } return FALSE; } void main() { for (DWORD start = 0; start < 0xFFFFFFFF; start++) { Check(&(LPBYTE)start); } } 2.3 Другой пример Другим примером является Asprotect 1.35 Release 03.24, он сам защищен аспром SKE. Мы можем найти таблицу encrypted sections, часть данных из нее(найдя пошифрованный код) и начать брутфорсить. Мой компьютер не так уж силне для такого брутфорса - результат будет примерно через 3 месяца, если бы мой компьютер был бы в 100 раз быстрее - брутфорс длился бы всего лишь 1 день. Если у кого-нибудь есть рабочий ключ или кто-нибудь знает EncryptionConst - сообщите мне, я буду очень признателен! 3. Алгоритмы MD5 и RC4 - очень распространненые алгоритмы. Вот исходник RC4: typedef struct rc4_key { unsigned char state[256]; unsigned char x; unsigned char y; } rc4_key; #define swap_byte(x,y) t = *(x); *(x) = *(y); *(y) = t void init_key(unsigned char *key_data_ptr, int key_data_len, rc4_key *key) { int i; unsigned char t; unsigned char swapByte; unsigned char index1; unsigned char index2; unsigned char* state; unsigned char subkey[256]; short counter; state = &key->state[0]; for(counter = 0; counter < 256; counter++) { state[counter] = counter; subkey[counter] = key_data_ptr[counter% key_data_len]; } key->x = 0; key->y = 0; index1 = 0; index2 = 0; for(counter = 0; counter < 256; counter++) { index2 = (subkey [index1] + state[counter] + index2) % 256; swap_byte(&state[counter], &state[index2]); index1 = (index1 + 1) % 256; } } 4. Выводы В аспре используется RSA, но EncryptionConst - всего лишь DWORD, так что возможен брутфорс. Имея правильный ключ - каждый может прпоатчить экспоненты и сделать кейген для аспра! Этот документ напсиано только для образовательных целей! 5. Greetz tEAr, heXer, fly, CoDe_Inject, Cnbragon, kanxue -- written by: shoooo shoooo314@hotmail.com 2006-4-19 -- translated by: lord_Phoenix lord.Phoenix.revenge@gmail.com 2006-9-29 -- Примечание переводчика: Да, статья неплоха и научит новичков патчить экспоненты и делать кейгены(+патчи) для прог под аспром. Но есть парочка недочетов. Никакого RSA в аспре нет, про pX(экспоненты) ничего не рассказано, то есть про так называемый матем. аппарат аспра - ничего. Так что статья - просто о патче экспонент на свои, кому интересно - дампим длл аспра, кидаем в иду. Дальше - смотрим проверку ключа - а именно проверку оистачи-24 байт hex-ключа. Если вы все-таки не можете добраться до EP дллки аспра - используйте данный скрипт: var x var y var is_DLL mov x,esp sub x,48 bphws x,"r" mov y,[eip] and y,000000FF cmp y,60 jne zzz mov is_DLL,1 zzz: run mov y,[eip] cmp y,01B80875 jne zzz bphwc x sti sti sti