Критическая ошибка VMProtect всех версий (1.x, 2.x, 3.x)

Issues related to VMProtect
Post Reply
metos
Posts: 5
Joined: Wed Jul 09, 2014 6:13 pm

Критическая ошибка VMProtect всех версий (1.x, 2.x, 3.x)

Post by metos »

Имеется такая функция:

Code: Select all

int test_vmp_stk(int arg)
{                                      
  int loc[2];
  loc[arg - 0x0B] = 0x50;
  return arg + loc[0];
}

int main()
{
  int x = test_vmp_stk(0x0B);
  printf("Test stk (ret = 0x%08x) \n", x);  
  return 0;
}
По коду видно, что в консоль должно всегда выводится число 0x0000005B.
Так вот после виртуализации функции test_vmp_stk программа выдаёт некорректные значения (случайные).

Асм код функции такой:

Code: Select all

.text:00401000                      ; int __cdecl test_vmp_stk(int arg)
.text:00401000                      ?test_vmp_stk@@YAHH@Z proc near         ; CODE XREF: _main+12p
.text:00401000
.text:00401000                      var_34          = dword ptr -34h
.text:00401000                      loc             = dword ptr -8
.text:00401000                      arg             = dword ptr  4
.text:00401000
.text:00401000 8B 44 24 04                          mov     eax, [esp+arg]
.text:00401004 C7 44 84 CC 50 00 00 00              mov     [esp+eax*4+var_34], 50h
.text:0040100C 8B 4C 24 F8                          mov     ecx, [esp+loc]
.text:00401010 83 EC 08                             sub     esp, 8
.text:00401013 03 C1                                add     eax, ecx
.text:00401015 83 C4 08                             add     esp, 8
.text:00401018 C3                                   retn
.text:00401018                      ?test_vmp_stk@@YAHH@Z endp
Проект собирается в Visual Studio 2008 SP1 с включёной оптимизацией (/O2).
Проверял на версиях: 1.7, 2.11, 3.0.0.290

Я конечно понимаю из-за чего такая бяка возникает, но пусть автор VMP сам расскажет.
Admin
Site Admin
Posts: 2566
Joined: Mon Aug 21, 2006 8:19 pm
Location: Russia, E-burg
Contact:

Re: Критическая ошибка VMProtect всех версий (1.x, 2.x, 3.x)

Post by Admin »

Протектор не ожидает, что программа читает данные ниже границы стека (mov ecx, [esp - 4]), поэтому вы и получаете UB.
metos
Posts: 5
Joined: Wed Jul 09, 2014 6:13 pm

Re: Критическая ошибка VMProtect всех версий (1.x, 2.x, 3.x)

Post by metos »

Admin wrote:Протектор не ожидает, что программа читает данные ниже границы стека (mov ecx, [esp - 4]), поэтому вы и получаете UB.
И где в C-коде чтение ниже "границы стека" ? Укажите на некорректную строчку кода.

Вы не правы.
Инструкция sub esp, XXX не определяет "границу стека". Граница стека будет тогда, когда функцию пишет человек на асме (для этого он оформляет пролог и эпилог).
Но код функции может быть сгенерирован с использованием СУПЕР ПУПЕР оптимизации, когда значение регистра esp не изменяется явно, а значение ebp не используется для хранения этой "границы стека".

Вот более корректное написание ЧУДО функции:

Code: Select all

int test_vmp_stk(int arg)
{                                      
  int loc[2];
  loc[arg & 0x80000000] = 0x50;
  return arg + loc[0];
}
Admin
Site Admin
Posts: 2566
Joined: Mon Aug 21, 2006 8:19 pm
Location: Russia, E-burg
Contact:

Re: Критическая ошибка VMProtect всех версий (1.x, 2.x, 3.x)

Post by Admin »

mov [esp+eax*4-52], 50h при eax = 0xB получаем:

Code: Select all

mov  [esp - 8], 50h
mov  ecx, [esp - 8]
metos
Posts: 5
Joined: Wed Jul 09, 2014 6:13 pm

Re: Критическая ошибка VMProtect всех версий (1.x, 2.x, 3.x)

Post by metos »

Admin wrote:mov [esp+eax*4-52], 50h при eax = 0xB получаем:

Code: Select all

mov  [esp - 8], 50h
mov  ecx, [esp - 8]
На мой взгляд все тут корректно.

Вы лучше напишите где вы прочитали о том, что функция не имеет права обращаться к памяти, расположенной ниже "границы стека" ?
Хотя сама функция постоянно меняет эту границу.
metos
Posts: 5
Joined: Wed Jul 09, 2014 6:13 pm

Re: Критическая ошибка VMProtect всех версий (1.x, 2.x, 3.x)

Post by metos »

Возможно представить функцию, которая:
1) не имеет вызовов других функций (инструкции call отсутствуют);
2) не нуждается в хранении на стеке временных данных (регистров вполне хватает);
3) имеет несколько локальных переменных (для них не хватило регистров).

Так вот этой функции совсем не нужно изменять "границу стека".
Конечно вы можете сказать что это сферический конь в вакууме. И отчасти вы будете правы, т.к. я не знаю компиляторов, которые в этом случае не будут использовать инструкцию sub esp, XXX
Хотя, выше описанная функция test_vmp_stk очень похожа на описанного коня.

Да и можно представить ситуацию, когда в компилятор VS2016 добавят такую вот оптимизацию, и тогда автор протектора должен будет всем советовать отключить эту оптимизацию.
Admin
Site Admin
Posts: 2566
Joined: Mon Aug 21, 2006 8:19 pm
Location: Russia, E-burg
Contact:

Re: Критическая ошибка VMProtect всех версий (1.x, 2.x, 3.x)

Post by Admin »

VMProtect имеет стековую ВМ, которая работает на общем программном стеке, поэтому при записи данных ниже границы стека происходит их затирание.
Post Reply