Исследование Special EXE Password Protector v1.0
Иструменты: TRW2000, IDA, Procdump, Delphi, Imprec 1.42 Var i:cardinal; buf:array [1..$58000] of char; //58000 - это IMAGE SIZE в PE h:thandle; f:file of char; j:dword; begin h:=OpenProcess(PROCESS_ALL_ACCESS,false,$fffd5d6b); //Pid я просто посмотрел в Procdump :) readprocessmemory(h,pointer($400000),@buf,$58000,i); closehandle(h); assignfile(f,'c:\sepphex.exe'); //ну самомнение у мя завышенное, не отрицаю :) rewrite(f); for j:=1 to i do write(f,buf[j]); closefile(f); end; Сдампил и сделал Rebuil Pe.Дойти к oep у нас не выйдет т.к. протектор просто каким-то извратным методом не дает запускать дебагер пока прога не распакуется и запустится, поэтому искать его будем в дампе по импорту. Все прекрасно знают, что практически все проги в самом начале выполняют GetModuleHandleA, так что если найдем эту функцию то уже очень скоро найдем oep. Но сначала нужно взять импорт. Для уверности я после запуска SEPP запустил TRW и зациклил прогу. Так как oep я не знал, нужно было как-то предположить где ж импорт. Я просто взял и глянул на код с адреса 401000 и увидел такое дело: 00401000 push 0 00401002 call dword ptr [00412188] 00401008 mov dword ptr [0040C081], eax412188 - это импорт. IAT начинается с 412000. Можно брать импорт в Imprec. Некоторые функции восстановятся, а некоторые придется искать самому. Весь импорт построен на полиморфных переходниках. При этом еще останется 6 функций которые у вас ну никак не будут восстанавливаться, потому что эти ненайденые функции будут выглядеть как длинные циклические полиморфы. Т.е. сильно не потрейсишь - задолбаешься. А тут и не надо трейсить. Импорт без этих 6 фунцкий будет выглядеть вот так: FThunk: 0001212C NbFunc: 00000001 1 0001212C comctl32.dll 0054 InitCommonControlsEx FThunk: 00012134 NbFunc: 00000001 1 00012134 comdlg32.dll 006E GetOpenFileNameA FThunk: 0001213C NbFunc: 00000014 1 0001213C kernel32.dll 02C6 SetEndOfFile 1 00012140 kernel32.dll 00B9 CreateFileA 1 00012144 kernel32.dll 00A0 CloseHandle 1 00012148 kernel32.dll 035F lstrlen 1 0001214C kernel32.dll 0177 GetFileSize 1 00012150 kernel32.dll 00BA CreateFileMappingA 1 00012154 kernel32.dll 0249 MapViewOfFile 1 00012158 kernel32.dll 00C6 CreateProcessA 1 0001215C kernel32.dll 00AD CopyFileA 1 00012160 kernel32.dll 00D8 DeleteFileA 1 00012164 kernel32.dll 0172 GetFileAttributesA 1 00012168 kernel32.dll 02CD SetFileAttributesA 1 0001216C kernel32.dll 0178 GetFileTime 1 00012170 kernel32.dll 02D0 SetFileTime 1 00012174 kernel32.dll 0319 VirtualAlloc 1 00012178 kernel32.dll 031B VirtualFree 1 0001217C ? 0000 06231F09 1 00012180 kernel32.dll 0314 UnmapViewOfFile 1 00012184 kernel32.dll 02CF SetFilePointer 1 00012188 ? 0000 06233276 FThunk: 00012190 NbFunc: 00000004 0 00012190 ? 0000 06236E2D 0 00012194 ? 0000 06236FC5 0 00012198 ? 0000 06238067 0 0001219C ? 0000 0623859D FThunk: 000121A4 NbFunc: 0000000E 1 000121A4 user32.dll 01F2 SendDlgItemMessageA 1 000121A8 user32.dll 00B7 EndDialog 1 000121AC user32.dll 0036 CheckDlgButton 1 000121B0 user32.dll 00FC GetDlgItem 1 000121B4 user32.dll 020E SetDlgItemTextA 1 000121B8 user32.dll 0246 ShowWindow 1 000121BC user32.dll 0051 CreateDialogParamA 1 000121C0 user32.dll 01F7 SendMessageA 1 000121C4 user32.dll 0091 DialogBoxParamA 1 000121C8 user32.dll 0195 LoadIconA 1 000121CC user32.dll 00FE GetDlgItemTextA 1 000121D0 user32.dll 01AD MessageBoxA 1 000121D4 user32.dll 0017 CallWindowProcA 1 000121D8 user32.dll 0182 IsDlgButtonCheckedКак мы видим 4 функции ваще хз какие, а 2 идут в разделе kernel32.dll. Если присмотреться, то можно заметить что функции GetmodulehandleA нет, и еще нет функции которой прога будет завершаться, т.е. ни Postquitmessage, ни TerminateProcess, ни ExitProcess... Можно предположить что одна из этих 2-х ненайденых в kernel32.dll функций это getmodulehandleA, а вторая - какая-то функция выхода. Как жеж определить кто есть who? Просто в запущеном SEPP поставить брейкпоинты на эти адреса и посмотреть что выполнится при выходе. А выполнится при выходе функция 0001217C (см. импорт) И при вызове ей дадут всего один параметр число 0. Это у нас ExitProcess. А вторая - это Getmodulehandlea (00012188). Вот с теми 4-мя сложнее, это у нас функции защиты, если поставить брейкпоинты на эти функции то можно увидеть, что 00012190 вызывается при вызове About. Как я понял это что-то типа GetRegInfo. С остальными у мя до сих пор непонятки, они ничего не берут, но без них прога не пашет. Я так понимаю, что функции проги, которые этот SVKP встраиваются в тело протектора чтоб никто их оттуда не выдрал. Поэтому я их просто оставил как есть и дописал полученый импорт. Теперь если дизасмнуть наш дамп в IDA и глянуть по адресу 401000, можно увидеть такое: .text:00401000 push 0 .text:00401002 call ds:GetModuleHandleA .text:00401008 mov dword_40C081, eax .text:0040100D push 0Ah .text:0040100F push 0 .text:00401011 push dword_40C081 .text:00401017 call sub_40102A .text:0040101C push 0 .text:0040101E call ds:ExitProcessИнтуиция :) Это OEP. А вообще можно было б поискать вызовы к адресу 412188 (это GetmodulehandleA) и мы как раз нашли бы тоже самое.
Теперь остались эти вредные 4 функции... Чо ж делать? Я забил на всякие попытки их эмулировать. Я просто сдампил весь код протектора от 6230000 до 6243000 (итого 13000h), дописал его в конец файла. Потом поправил ImageSize так чтоб получилось 6243000. Ну и задал нужные параметры для новой секции. Чтоб она грузилась по адресу 6230000. Т.е.
Теперь осталось убрать два ограничения: лимит на 3 символа в пароле и нагу, которую оно дописывает в защищенный exe. push ebp push 2000h push ecx push edx push 0 call dword ptr [ebp+7A04h] Это сооиветствует опкодам: 8D8DFF7700005568... и т.д. Ищем эту последовательность в нашем дампе. Она находится по адресу 403B51: .text:00403B51 push ebp .text:00403B52 push 2000h .text:00403B57 push ecx .text:00403B58 push edx .text:00403B59 push 0 .text:00403B5B call dword ptr [ebp+7A04h] .text:00403B61 pop ebp Правим дамп вот так: .text:00403B51 push ebp .text:00403B52 jmp loc_403B61 .text:00403B57 push ecx .text:00403B58 push edx .text:00403B59 push 0 .text:00403B5B call dword ptr [ebp+7A04h] .text:00403B61 pop ebp Наг больше не будет. Теперь про три буквы... :) Опять же bpx messageboxa и мы вот тут: .text:00401684 mov ebx, [ebp+hDlg] .text:00401687 push ebx .text:00401688 push 20h ; nMaxCount .text:0040168A push offset unk_40C7B1 ; lpString .text:0040168F push 3EBh ; nIDDlgItem .text:00401694 push ebx ; hDlg .text:00401695 call ds:GetDlgItemTextA .text:0040169B cmp eax, 3 .text:0040169E jbe short loc_4016BA .text:004016A0 push 2000h ; uType .text:004016A5 push offset aWarning ; lpCaption .text:004016AA push offset aInUnregistered ; lpText .text:004016AF push 0 ; hWnd .text:004016B1 call ds:MessageBoxAНадеюсь все понятно :) Но это тока месага, надо еще удостоверится что возмется именно более 3 символов, а то мало что оно там творит. Смотрим дальше: .text:004016BA push 4 ; nMaxCount - ага! Все-таки 4, а не 3 :) .text:004016BC push offset unk_40C7B1 ; lpString .text:004016C1 push 3EBh ; nIDDlgItem .text:004016C6 push ebx ; hDlg .text:004016C7 call ds:GetDlgItemTextA .text:004016CD test eax, eax .text:004016CF pop ebx .text:004016D0 jz short loc_40172C .text:004016D2 lea esi, ds:40C7B1h .text:004016D8 lea edi, ds:40C74Eh .text:004016DE mov ecx, eax .text:004016E0 repe movsb .text:004016E2 mov byte_40C74D, al - А это что-то интересное, записывет длина пароля, она как раз в EAX лежит. .text:004016E7 push 4 ; nMaxCount - угу ! :) .text:004016E9 push offset unk_40C76F ; lpString .text:004016EE push 3ECh ; nIDDlgItem .text:004016F3 push ebx ; hDlg .text:004016F4 call ds:GetDlgItemTextA .text:004016FA test eax, eax .text:004016FC jz short loc_40172C .text:004016FE lea esi, ds:40C74Eh .text:00401704 lea edi, ds:40C76Fh .text:0040170A mov ecx, 3 - опять 3 символа. .text:0040170F repe cmpsb - это проверяет чтоб пароли совпали .text:00401711 test ecx, ecx .text:00401713 jz short loc_401733Если поправить все nmaxcount чтоб читало более 4 символов пароля и этот mov ecx,3 - на mov ecx, eax(напоминаю, в eax после GetDlgItemTextA лежит длина строки), то прога перестанет кричать. Но все же проьектить паролем не будет, а начнет выдавать месаги типа "wrong Pe format" Это неправда :) Мы кое-что упустили. Мы не посмотрели что происходит со значением которое было занесено тут: .text:004016E2 mov byte_40C74D, al Поставим bpm 40C74D. Сработает оно тут: .text:00401A23 mov al, byte_40C74D .text:00401A28 add al, 33h .text:00401A2A cmp al, 36h .text:00401A2C jbe short loc_401A31 Это последняя проверка, исправив ее прога ставит пароли нужной длины.P.S. Я говорил что прога дразнится. Это правда. Если вы попытаетесь пройти до оер, то в коде распаковщика вы увидите вот такое: "If You are there, You are a good cracker, but this is only the beginning :) This is a special greeting to my friends:Hello boys: 3rt, EliCZ, VAG, Daemon, Gamumba, Chris, SACUnknown One and all boys from UG2000 and other good "unpackers" !If You will find the way how to decode SVKP, please contact me :)" P.S.S. Значит я таки "good cracker" :)
|