Добрый вечер форумчанам. Пишу простейший криптор с динамической расшифровкой и столкнулся с проблемой, что зашифрованный бинарник на диске некорректно расшифровывается изнутри. Стал разбираться и увидел, что у файла на диске и у кода в рантайме различаются байты (на диске байт 0х41, в рантайме - 0х31). Кто их меняет и каким образом? Сам код: Код (C): VOID SampleCode() { PVOID StartAddress = NULL, StopAddress = NULL; ULONG Size = 0; __asm { mov StartAddress, offset Start mov StopAddress, offset SigStop } Size = (ULONG)StopAddress - (ULONG)StartAddress; DWORD OldProtect = 0; // Расшифровываем: UNLOCK_MEM(StartAddress, Size, &OldProtect); XOR((PBYTE)StartAddress, Size); RESTORE_MEM(StartAddress, Size, OldProtect); // Очищаем кэш инструкций, чтобы случайно не был выполнен закриптованный код: FlushInstructionCache(GetCurrentProcess(), StartAddress, Size); goto Start; CRYPT_SIGNATURE_START; Start: printf("Text"); goto Stop; SigStop: CRYPT_SIGNATURE_STOP; Stop: // Зашифровываем обратно: UNLOCK_MEM(StartAddress, Size, &OldProtect); XOR((PBYTE)StartAddress, Size); RESTORE_MEM(StartAddress, Size, OldProtect); } Если вместо printf'a в зашифрованный блок поставить что-нибудь простое (например, несколько нопов) - всё работает.
Нет, если бы это было так то с чего бы байты в рантайме отличались от байтов файла на диске? У него скорее всего включены релокации и модуль грузится не по базовому адресу, соответственно загрузчик переписывает места где есть абсолютная адресация. Этим объясняется то что в рантайме байты отличаются от байтов в сыром EXE/DLL.
Перепроверил, с ним всё правильно. На скрине запускаю без зашифровки, как собрал компиль. На скрине он и есть. Сигнатура начала: FF 00 FF 00 1E E7 C0 DE FF 00 FF 00 Сигнатура конца: 00 FF 00 FF 1E E7 C0 DE 00 FF 00 FF На скрине всё, что между ними - оригинал и не зашифровывалось (начиная с 0x1315F65, с байтов 0x68 0x90)
HoShiMin, убирай релокации, либо делай поправку в функции расшифровки/шифровки. Где видно? У него шифрованый блок на скринах.
HoShiMin, Тогда 0x68 это опкод push imm32, тоесть загрузка указателя(смещение на текст). Ссылки могут правиться в одном случае - релокация.
Насколько я понял это у него шифрованный код и 0x68 это шифрованное значение которое в данном контексте не имеет смысла до расшифровки и которое не имеет смысла как-то интерпретировать. С большей вероятностью после расшифровки там будет что-то типа 0xFF15 xxxxxxxx - где xxxxxxxx - значение которое правится загрузчиком и на которое указывает таблица релокаций.
тоже вангую что релоки портят код, их нужно обнулять а потом после расшифровки настраивать если это длл .. екзешнику и так сойдет (без настройки).
Да, действительно оказались релоки. Снова с ними разбираюсь и не понимаю, как они работают. Из рантаймового 0x01C8E190 вычитаем 0x0041E190, получаем 0x1870000. В таблице нет ни одного намёка на это число. Откуда винда его узнала, чтобы правильно поправить адрес? И что означает число 3F66?
HoShiMin, Вероятно это запись в таблице релокаций - RVA, фиксап. Это всё очень просто, все ссылки в модуле сформированы относительно базы, которая указана в хидере. При релокации все ссылки фиксятся на дельту адресов. При этом множество способов фикса юзается, в зависимости от архитектуры. Кстате если вам интересна данная тема, то можите изучить серийные фиксы - когда один релок наложен на другой. Поведение загрузчика в этом случае не известно, но авера полюбому вы обманите таким образом есчо до запуска эмуляции
Это, кстати, интересно - и понадобится, доберусь, но вопрос всё равно остаётся открытым: берём базу из хидера (400000), берём фактический адрес загрузки образа (B70000), вычитаем из второго первый, получаем дельту (770000). Теперь берём адрес из бинарника (0041E190, см. в Hexplorer'e), прибавляем к нему дельту (770000) и получаем B8E190, а должно получиться 01C8E190 (см. в x64dbg) - где разница в 1100000?
На что указывает 0x01C8E190 в рантайме? Что-то слишком большой оффсет. Можно увидеть карту памяти в рантайме? 0x3F66 - 3 это IMAGE_REL_BASED_HIGHLOW, 0xF66 - смещение относительно RVA блока. Один блок адресует 4096 диапазонов адресов.