После компиляции MZ-crypt (пример криптера из папки "исходники") нашел ошибку, там переменные не в том месте были объявлены, но программа все равно криптует неправильно - после применения, подопытный exe говорит что в нем ошибка и предлагает отправить отчет. Никак не могу определить вторую ошибку... посмотрите кто может
ошибка возникает 100% в этой части кода... Код (Text): pushad invoke GetTickCount invoke nseed, eax invoke nrandom, 255 mov dwCryptKey, al mov esi, pFileHeader assume esi:ptr IMAGE_FILE_HEADER mov cx,[esi].NumberOfSections mov edi, pSectionTable assume edi:ptr IMAGE_SECTION_HEADER .while cx != 0 invoke CanCrypt, pPE, edi test eax,eax jnz @F or [edi].Characteristics, 80000000h ;ìîæåì çàïèñàòü lea ebx,[edi].PointerToLinenumbers mov word ptr [ebx], Sign mov edx,[edi].PointerToRawData add edx, hMap xor eax, eax .while eax <= [edi].SizeOfRawData push eax mov ah, dwCryptKey xor byte ptr [edx], ah pop eax inc eax inc edx .endw @@: add edi, sizeof IMAGE_SECTION_HEADER dec cx .endw popad
даже, вероятнее всего, в этом цикле: Код (Text): .while eax <= [edi].SizeOfRawData push eax mov ah, dwCryptKey xor byte ptr [edx], ah pop eax inc eax inc edx .endw
На Windows XP работает, _но_ перед запуском обработанного файла, нужно выставить флаг секции кода - Writeable (кстати, это указано в комментариях). На Windows 7 не работает, почему? just-in-time debugger в помощь. Скорее всего проблема _не_ в коде.
Да, под JIT уже второй час сижу... На XP точно работает? Вы компилили этот код или просто exe из архива автора запустили? Последний и в 7 работает, а вот скомпилированный код...
Ууфф.. ольга при JIT отладке встает на строке xor byte ptr [edx], ah Код (Text): Весь код до этой части облазил.. ниче не пойму, где же косяк
Давайте по порядку: 1.Код не выставляет атрибут секции как Writeable (IMAGE_SECTION_HEADER.Characteristics|IMAGE_SCN_MEM_WRITE) то есть, _перед_ запуском файла, нужно выставить этот флажок, для каждой секции которая "зашифрована" (используя например PETools), как узнать, а зашифрована ли? Посмотреть структуру секции IMAGE_SECTION_HEADER.PointerToLinenumbers, Mz-crypt выставляет это поле в '7'. 2. В коде есть бага, собственно здесь: Код (Text): .while cx != 0 invoke CanCrypt,pPE,edi test eax,eax jnz @F or [edi].characteristics,80000000h ;can write lea ebx,[edi].PointerToLinenumbers mov word ptr [ebx],Sign mov edx,[edi].PointerToRawData add edx,hMap xor eax,eax .while eax <= [edi].SizeOfRawData push eax mov ah,dwCryptKey xor byte ptr [edx],ah pop eax inc eax inc edx .endw @@: add edi,sizeof IMAGE_SECTION_HEADER dec cx .endw popad ;!!Хоть одна секция зашифрована? нет - завершение. ;////////////////////////////////// ;// Write Code // ;////////////////////////////////// mov eax,SizeOfStub функция CanCrypt проверяет, не содержит ли секция какой-небудь директории, если нет - тогда ксорит, но дело в том, что если каждая секция содержит директорию в конце цикла _должен_ бить выход с программы (ну и уведомление о неудавшийся роботе), но она просто пишет стаб в программу, выставляет точку входа, etc. Открывайте mz-crypt OllyDbg/WinDbg и пошагово смотрите, что он делает с файлом, также внимательно - куда собственно он пишет стаб, что в конкретном файле в этом месте. После записи, откройте файл (обработанный) в WinDbg например, bp ntdll!__RtlUserThreadStart, и отсюда к передачи управления на "загрузчик", нужно проверить атрибуты памяти (где загрузчик). Много чего может бить, но скорее всего - неправильная обработка таблиц директорий (Import/Export/Bound/etc). Бегло просмотрел код, наверное есть еще баги. P.S. Использовал исходник с сайта.
Надо лучше разобраться в коде.. Не совсем понятно, как CanCrypt проверяет наличие директории в секции. Правильно ли я понимаю, что assume esi:ptr IMAGE_SECTION_HEADER ... .if [edi].OptionalHeader.DataDirectory[sizeof IMAGE_DATA_DIRECTORY * ecx].VirtualAddress != 0 mov edx,[edi].OptionalHeader.DataDirectory[sizeof IMAGE_DATA_DIRECTORY * ecx].VirtualAddress .if edx >= [esi].VirtualAddress тут просматривается каждый из 14 массивов DataDirectory, проверяется его RVA в памяти, и если этот RVA > RVA IMAGE_SECTION_HEADER, то это значит, что секция присутствует(??)
Да Код (Text): .while ecx != 0 .if [edi].OptionalHeader.DataDirectory[sizeof IMAGE_DATA_DIRECTORY * ecx].VirtualAddress != 0 mov edx,[edi].OptionalHeader.DataDirectory[sizeof IMAGE_DATA_DIRECTORY * ecx].VirtualAddress .if edx >= [esi].VirtualAddress ;Если вирт. адрес директории больше вирт. адреса начала секции mov ebx,[esi].Misc.VirtualSize add ebx,[esi].VirtualAddress ;Начало секции в памяти + размер секции .if edx <= ebx ;если адрес директории попадает в эти границы, тогда директория находиться в этой секции, ;крипт не возможен. mov eax,1 jmp __ret .endif .endif .endif dec ecx .endw @@: mov eax,0 __ret: ret CanCrypt endp
Так и хочу. Но надо же понять вероятные ошибки. Эту тоже какой-то человек писал - но ведь не работает. Интересно все-таки почему
Clerk, а почему "это геррь"? т.е. на что обратить внимание, что бы не получилось подобия этому но не слишком сложно?