Изменение области памяти - возвращает 0xCC VC++

Я изменяю некоторые разделы исполняемого кода, скомпилированного в dll. Но один байт по фиксированному адресу из всего сегмента, который я модифицирую, не может быть изменен, даже прочитан.

Код очень прост:

SEGMENT_DATA segInfo = getSegmentInfo(mHandle, segmentName);

if (segInfo.inFileSegmentAddr == 0) return false;

DWORD mOlProtection;
DWORD mOlProtection_1;

if (segInfo.architecture != MY_ARCH) {
    printf(" Not the same architecture!\n");
    return 0;
}

if(VirtualProtect((LPVOID)segInfo.segmentAddr, segInfo.segmentSize, PAGE_EXECUTE_READWRITE, &mOlProtection)==0) return false;
DWORD i=0;
for (size_t k = 0; k < segInfo.segmentSize; k++) {
    BYTE *lpByteValue = (BYTE*)(segInfo.segmentAddr + k);

    BYTE temp = *lpByteValue;
    *lpByteValue = temp ^ lDecryptionKey[i];
    i++;
    i %= decryptionKeyLength;
}

if(VirtualProtect((LPVOID)segInfo.segmentAddr, segInfo.segmentSize, mOlProtection, &mOlProtection_1)==0) return false;

Наблюдения:

  1. Прежде чем модифицировать память, я «снимаю защиту» с региона с флагом PAGE_EXECUTE_READWRITE.
  2. Представление памяти в визуальной студии ясно показывает мне значение по этому конкретному адресу. Еще более странным является то, что во второй раз, когда я изменяю значение вручную из отладчика, мой код также может изменить это значение.
  3. переменная temp в примере кода содержит значение 0xCC
  4. Этот байт буквально единственный неизменный в море сотен других байтов. Это единственный байт, отмеченный черным цветом в представлении памяти (остальные выделены красным, потому что они были изменены).
  5. Dll компилируется в Debug/x86. Флаг /MTd установлен. Нет случайного адреса (/DYNAMICBASE : NO , /FIXED: NO). Нет Оптимизация всей программы.
  6. Немодифицированный байт НЕ ЯВЛЯЕТСЯ переменной. Таким образом, он не может быть «неинициализирован». На самом деле это очень важный байт: это код операции инструкции. Все рушится на этом байте.
  7. Процедура расшифровки (код XOR) не влияет на ошибку. Я вхожу в код и смотрю на значение temp до того, как оно достигнет xor. Это означает, что ключ дешифрования никогда не используется и, следовательно, не может вызвать проблему.
  8. Виртуальная защита удалась.


Снимки: Черный байт не может быть прочитан или записан, хотя визовая студия может его отобразить


Visual studio может прочитать адрес Visual Studio может прочитать адрес



Невозможно прочитать байт внутри программы Невозможно прочитать байт внутри программы


Я знаю, что проблемы вызывает не значение байта по этому единственному адресу (потому что я нашел другие байты с тем же значением, которые были успешно обработаны). Возможно, байт все еще «защищен»?

Почему это происходит?


person sergiu reznicencu    schedule 25.04.2019    source источник
comment
Ваш ключ дешифрования содержит несколько нулевых байтов?   -  person Ben Voigt    schedule 26.04.2019
comment
Не могли бы вы предоставить больше контекста, а также краткий код, который мы можем скомпилировать и использовать для тестирования?   -  person Alecto Irene Perez    schedule 26.04.2019
comment
Нет, ключ не содержит нулей. Что касается компиляции: я не могу предоставить дополнительный код. Но я хочу знать только одно: что нет скрытой функции virtualprotect или другого очевидного поведения памяти, которое могло бы вызвать эту ошибку. Если код, который я предоставил, обычно не генерирует эту ошибку, по крайней мере, вы дали мне подсказку: ошибка находится где-то еще, спрятанная в моем коде.   -  person sergiu reznicencu    schedule 26.04.2019
comment
Кстати, при каких обстоятельствах Visual Studio вернет 0xCC? Я нашел кое-что, связанное с унитиализом памяти. Может ли это быть?   -  person sergiu reznicencu    schedule 26.04.2019
comment
Добавлено больше деталей   -  person sergiu reznicencu    schedule 26.04.2019
comment
Проблема действительно не в коде расшифровки. Интерес представляет переменная temp. Он содержит 0xCC. Это простое чтение памяти. Никакой код не должен мешать этому   -  person sergiu reznicencu    schedule 26.04.2019
comment
Я не смогу ответить до завтра.   -  person sergiu reznicencu    schedule 26.04.2019
comment
0xCC означает неинициализированную память. Когда и почему ОС будет инициализировать память до 0xCD, 0xDD и т. д. на malloc/free/new/delete?   -  person phuclv    schedule 26.04.2019
comment
Но как его можно не инициализировать? После нескольких строк кода будет выполнен тот участок памяти, который я изменяю. И кроме того, я ясно вижу значение в представлении памяти.   -  person sergiu reznicencu    schedule 26.04.2019
comment
Единственное, что приходит на ум, это то, что ваш ключ либо содержит нулевой байт, либо короче, чем вы думаете: отсутствие проверки или связи между i и segInfo.segmentSize выглядит подозрительно.   -  person Quentin    schedule 26.04.2019
comment
Ключ ничего не делает. Я вхожу в код, и когда lpByteValue достигает адреса этого странного байта, я смотрю на значение temp. Я не выполняю этот XOR. Значение temp равно 0xCC. Это не имеет ничего общего с кодом расшифровки. Я мог бы также удалить весь этот код. И код, который я предоставил, изменен. Это i правильно проверено в исходном коде. Я отредактирую вопрос.   -  person sergiu reznicencu    schedule 26.04.2019
comment
А как насчет стола для ремонта? Как вы справляетесь с этим?   -  person rustyx    schedule 26.04.2019
comment
Что... исправить? Я проведу небольшое исследование. (вы имеете в виду перемещения? Потому что, если вы это сделаете, я правильно с этим справлюсь. На самом деле этот проблемный байт - это код операции, а следующие 4 байта - это данные. Но это просто память ... он не может знать, что я собираюсь делать с я не выполняю этот код, а просто модифицирую его)   -  person sergiu reznicencu    schedule 26.04.2019
comment
Да переезды. Или связать с /FIXED:YES. Кроме того, убедитесь, что VirtualProtect действительно успешно работает.   -  person rustyx    schedule 26.04.2019
comment
Стоит ли упоминать, что весь код отлаживается на виртуальной машине?   -  person sergiu reznicencu    schedule 26.04.2019
comment
Хорошая идея. Я не проверял, удалось ли VirtualProtect. я проверю это   -  person sergiu reznicencu    schedule 26.04.2019
comment
Я не понимаю. Адрес есть, я вижу всю память, я могу изменить все, что хочу, Visual Studio его видит, но несмотря на все это, оператор деференцирования ПРОСТО возвращает 0xCC. Почему? Могу ли я отлаживать саму визуальную студию? Возможно, это как-то связано с кастингом? Возможно, без подписи/подписания? Я действительно не знаю, что искать сейчас.   -  person sergiu reznicencu    schedule 26.04.2019


Ответы (1)


Вы вполне можете справиться с очень распространенным сценарием Software Breakpoints. Software breakpoints на самом деле устанавливаются путем замены инструкции, на которую устанавливается точка останова, инструкцией точки останова.

Инструкция точки останова присутствует в большинстве ЦП и обычно такая же короткая, как и самая короткая инструкция, поэтому только one byte on x86 (0xCC, INT 3).

Поскольку я не знаю, есть ли вообще какие-либо точки останова в вашем источнике, я могу только предположить, что это ваша проблема.

person Reznicencu Bogdan    schedule 27.04.2019
comment
Да, в самом деле. У меня была точка останова именно на этой инструкции. Эта точка останова многое объясняет - person sergiu reznicencu; 27.04.2019