Кто и как меняет опкод?

Тема в разделе "WASM.BEGINNERS", создана пользователем HoShiMin, 7 апр 2017.

  1. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.477
    Адрес:
    Россия, Нижний Новгород
    Добрый вечер форумчанам. Пишу простейший криптор с динамической расшифровкой и столкнулся с проблемой, что зашифрованный бинарник на диске некорректно расшифровывается изнутри. Стал разбираться и увидел, что у файла на диске и у кода в рантайме различаются байты (на диске байт 0х41, в рантайме - 0х31). Кто их меняет и каким образом?

    07-04-2017 18-14-02.png

    Сам код:
    Код (C):
    1. VOID SampleCode() {
    2.     PVOID StartAddress = NULL, StopAddress = NULL;
    3.     ULONG Size = 0;
    4.     __asm {
    5.         mov StartAddress, offset Start
    6.         mov StopAddress, offset SigStop
    7.     }
    8.     Size = (ULONG)StopAddress - (ULONG)StartAddress;
    9.  
    10.     DWORD OldProtect = 0;
    11.     // Расшифровываем:
    12.     UNLOCK_MEM(StartAddress, Size, &OldProtect);
    13.     XOR((PBYTE)StartAddress, Size);
    14.     RESTORE_MEM(StartAddress, Size, OldProtect);
    15.  
    16.     // Очищаем кэш инструкций, чтобы случайно не был выполнен закриптованный код:
    17.     FlushInstructionCache(GetCurrentProcess(), StartAddress, Size);
    18.     goto Start;
    19.     CRYPT_SIGNATURE_START;
    20. Start:
    21.     printf("Text");
    22.     goto Stop;
    23. SigStop:
    24.     CRYPT_SIGNATURE_STOP;
    25. Stop:
    26.     // Зашифровываем обратно:
    27.     UNLOCK_MEM(StartAddress, Size, &OldProtect);
    28.     XOR((PBYTE)StartAddress, Size);
    29.     RESTORE_MEM(StartAddress, Size, OldProtect);
    30. }
    31.  
    Если вместо printf'a в зашифрованный блок поставить что-нибудь простое (например, несколько нопов) - всё работает.
     
  2. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    887
    Релокации есть в результирующем файле?
     
  3. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.347
    Очевидно, что надо перепроверить свою функцию XOR().
     
  4. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    Покажите не зашифрованный блок.
     
  5. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    887
    Нет, если бы это было так то с чего бы байты в рантайме отличались от байтов файла на диске? У него скорее всего включены релокации и модуль грузится не по базовому адресу, соответственно загрузчик переписывает места где есть абсолютная адресация. Этим объясняется то что в рантайме байты отличаются от байтов в сыром EXE/DLL.
     
  6. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.477
    Адрес:
    Россия, Нижний Новгород
    [​IMG]

    Перепроверил, с ним всё правильно. На скрине запускаю без зашифровки, как собрал компиль.

    На скрине он и есть.
    Сигнатура начала: 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)
     
  7. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.347
    Thetrik,
    Видно же по коду, что изменяется не VA, а относительный оффсет. На них релоков не бывает.
     
  8. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.347
    Бряки на printf(), надеюсь, не ставишь, когда оно шифрует и сохраняет в файл?
     
  9. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.477
    Адрес:
    Россия, Нижний Новгород
    Нет конечно
     
  10. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    887
    HoShiMin, убирай релокации, либо делай поправку в функции расшифровки/шифровки.
    Где видно? У него шифрованый блок на скринах.
     
  11. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    Тогда 0x68 это опкод push imm32, тоесть загрузка указателя(смещение на текст). Ссылки могут правиться в одном случае - релокация.
     
  12. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    887
    Насколько я понял это у него шифрованный код и 0x68 это шифрованное значение которое в данном контексте не имеет смысла до расшифровки и которое не имеет смысла как-то интерпретировать. С большей вероятностью после расшифровки там будет что-то типа 0xFF15 xxxxxxxx - где xxxxxxxx - значение которое правится загрузчиком и на которое указывает таблица релокаций.
     
  13. sl0n

    sl0n Мамонт дзена **

    Публикаций:
    0
    Регистрация:
    26 сен 2003
    Сообщения:
    701
    тоже вангую что релоки портят код, их нужно обнулять а потом после расшифровки настраивать если это длл .. екзешнику и так сойдет (без настройки).
     
  14. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.477
    Адрес:
    Россия, Нижний Новгород
    Да, действительно оказались релоки. Снова с ними разбираюсь и не понимаю, как они работают. Из рантаймового 0x01C8E190 вычитаем 0x0041E190, получаем 0x1870000. В таблице нет ни одного намёка на это число. Откуда винда его узнала, чтобы правильно поправить адрес? И что означает число 3F66?

    [​IMG]
     
  15. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    HoShiMin,

    Вероятно это запись в таблице релокаций - RVA, фиксап. Это всё очень просто, все ссылки в модуле сформированы относительно базы, которая указана в хидере. При релокации все ссылки фиксятся на дельту адресов. При этом множество способов фикса юзается, в зависимости от архитектуры.
    Кстате если вам интересна данная тема, то можите изучить серийные фиксы - когда один релок наложен на другой. Поведение загрузчика в этом случае не известно, но авера полюбому вы обманите таким образом есчо до запуска эмуляции ;)
     
  16. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.477
    Адрес:
    Россия, Нижний Новгород
    Это, кстати, интересно - и понадобится, доберусь, но вопрос всё равно остаётся открытым: берём базу из хидера (400000), берём фактический адрес загрузки образа (B70000), вычитаем из второго первый, получаем дельту (770000). Теперь берём адрес из бинарника (0041E190, см. в Hexplorer'e), прибавляем к нему дельту (770000) и получаем B8E190, а должно получиться 01C8E190 (см. в x64dbg) - где разница в 1100000?
     
  17. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    887
    На что указывает 0x01C8E190 в рантайме? Что-то слишком большой оффсет. Можно увидеть карту памяти в рантайме? 0x3F66 - 3 это IMAGE_REL_BASED_HIGHLOW, 0xF66 - смещение относительно RVA блока. Один блок адресует 4096 диапазонов адресов.
     
  18. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Thetrik,

    Может вы сами откроете сурец нт и почитаете, там наверно и коменты есть =)
     
  19. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    887
    Для чего это мне? Я прекрасно знаю как релоки работают.
     
  20. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Thetrik,

    Не вам это извините, не тот ник кликнул. Имеется ввиду тс.