std::string crash

mingw (GNU Make 3.82)
VMProtect 2.12 x32

ошибка возникает в только в релиз версии при конструировании std::string с заданной длиной (например std::string(“aaa”, 3);).
crash.zip (11.4 KB)

А какой пароль на архив?

прошу прощения. пароль “vmp”

библиотеки qt можно исключить из проекта

Причина такого поведения заключается в том, что MinGW при инициализации своего рантайма патчит исполняемый код.
Было:

004013F2  81FB 9C614000          CMP EBX, 0040619C

Стало:

004013F2  81FB 988FCC6F          CMP EBX, 6FCC8F98

В данном случае адрес 004013F2 принадлежит вашей функции crash(). В процессе виртуализации протектор используется освободившееся место для своих нужд и с большой вероятностью на этот адрес будет попадать исполнитель ВМ и результат работы такого кода будет непредсказуем (крах приложения это один из возможных вариантов).

Как этого можно избежать? Можно ли настроить MinGW не патчить исполняемый код или указать vmprotect не перезаписывать освободившееся место?

Как этого можно избежать?

Никак. VMProtect совершенно ничего не знает про то, что бинарник сам себя патчит :slight_smile:)

Можно ли настроить MinGW не патчить исполняемый код

Задайте этот вопрос разработчикам MinGW.

или указать vmprotect не перезаписывать освободившееся место?

Здесь гораздо больше проблем чем вы видите :slight_smile:) Даже если VMProtect не будет использовать это место, то все равно условие будет работать неправильно, т.к. VMProtect на этапе виртуализации будет виртуализировать CMP EBX, 0040619C, и ничего не будет знать про CMP EBX, 6FCC8F98

P.S. У “нормальных” компиляторов принято все изменяемые ячейки (если они настраиваются не операционной системой) хранить в секции данных, а не кода. В этом бы случае условие выглядело бы как CMP EBX, [var_xxx] и вообще бы никаких проблем не возникло.

P.P.S. К слову сказать у таких самоизменяющимся бинарников нельзя никак контролировать целостность секции кода, т.е. любой подсчет CRC будет всегда отличаться от правильного после того как по нему прошелся рантайм MinGW.