кто-нибудь ломал VMProtect

Тема в разделе "WASM.RESEARCH", создана пользователем avraam, 27 апр 2009.

  1. sl0n

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

    Публикаций:
    0
    Регистрация:
    26 сен 2003
    Сообщения:
    684
    хватет флудить =)
    гнобите же дальше виртуальные машины =)
     
  2. sl0n

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

    Публикаций:
    0
    Регистрация:
    26 сен 2003
    Сообщения:
    684
    и стрелки пирса =)
     
  3. JCronuz

    JCronuz New Member

    Публикаций:
    0
    Регистрация:
    26 сен 2007
    Сообщения:
    1.240
    Адрес:
    Russia
    ВМ это будущее :)
     
  4. Vam

    Vam New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2008
    Сообщения:
    149
    Деобфускация и трассировка флагов процессора

    При обфускации примитивов ВМ могут вставляться в код примитива "лишние" условные переходы (JCC). Работает это следующим образом - производятся некие математические или логические преобразования константы, после чего стоит условный переход, понятно, что он будет работать только в одном направлении (jcc или direct) в зависимости от значения константы и операции перед переходом. Чтобы правильно выполнить статическую трассировку нужно сделать анализ флагов перед переходом. Вопрос в том, как правильно сэмулировать значение разных флагов?
    На входе задачи имеем:
    - опкод инструкции, изменяющей флаги (add, sub, neg, and и т.д.)
    - значение константы до инструкции (V1)
    - значение константы после инструкции (V2)
    На выходе нужно получить значения всех флагов процессора.

    Рассмотрим эмуляцию всех флагов:
    1. Флаг Z (ноль).
    Здесь всё просто: если V2 == 0, то Z = 1
    2. Флаг S (знак)
    Тоже просто: если старший бит V2 == 1, то S = 1
    3. Флаг P (паритет)
    Достаточно просто: если число единиц в младшем байте V2 четно, то P = 1
    4. Флаг C (перенос)
    - если инструкция устанавливает или сбрасывает этот флаг, то всё просто, C = флаг инструкции
    - если инструкция изменяет этот флаг, то анализ V1, V2 и инструкции даст требуемый результат, например, для add, если V2 < V1, то С = 1
    т.е. если есть перенос или заем, то С = 1
    5. Флаг O (переполнение)
    - если инструкция устанавливает или сбрасывает этот флаг, то всё просто, О = флаг инструкции
    - для inc, если V2 == 0, то О = 1
    - для add, если V2 < V1, то О = 1
    т.е. для для операций "верхнего" переполнения достаточно просто, если размер значения V2 > размера V1, то О = 1
    а как быть с операциями "нижнего" переполнения (вычитающими), одного лишь анализа заёма недостаточно, ведь команда neg не установит флаг переполнения?

    Прошу высказать, если я в чем то ошибаюсь или неточен, и как сделать полный анализ флага переполнения.
     
  5. Killer

    Killer New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2008
    Сообщения:
    316
    Vam

    Брат, организуй статью:) Ну цены бы ей небыло....
     
  6. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Vam
    С чего бы это neg не выставляла OF? Выставляет. Правда, знаковое переполнение там возникает в единственном случае: когда аргумент равен минимально возможному значению для данной разрядности. Например,
    mov eax,80000000h
    neg eax
    выставит OF в единицу.
     
  7. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Vam
    Да... забыл досказать. :) Непохоже, чтобы Вам это было неизвестно... :) Но на всякий случай: OF равен xor'у значений переноса (заёма) из предстаршего в старший (из старшего в предстарший) разряд и из старшего (в старший) разряд. Соответственно, OF выставляется тогда и только тогда, когда меняется знаковый бит аргумента. Учитывая, что neg arg = 0-arg, аргументом в данном случае будет считаться нуль, а не V1.
    Аналогично, например, инструкция shl eax,1 в случае eax равного 80000000h выставит OF в единицу, т.к. переноса в старший разряд не будет, но будет перенос из старшего разряда в CF.
     
  8. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    *из старшего (в старший) разряда (разряд)
     
  9. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Подумал, что ерунду полную написал. :) Имелось в виду в отношении переносов, а не при переходе от V1 к V2. :)
     
  10. Vam

    Vam New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2008
    Сообщения:
    149
    l_inc
    Спасибо за ответ.
    Если бы мне это было точно известно, то я бы и не спрашивал.
    Честно сказать я не понял, что с чем нужно хорить, перенос (заем), т.е. это бит C со старшим разрядом? Чего? Результата (V2)? Прошу написать формулой.
    Если это действительно так, то и анализ флага С тоже можно упростить и исключить из анализа операцию изменяющую флаг, например, флаг С = старший бит V1 ^ старший бит V2, так ли это?

    PS: Процессор, оперируя с числами, не знает какое это число знаковое или беззнаковое и выставляет флаги для этих чисел одинаково в зависимости от значения конкретных бит.
     
  11. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Vam
    Думаю, проще будет на примере показать. В самом низу — сумма. Между линиями — биты переноса.
    Код (Text):
    1.   11010010
    2. + 01110110
    3.   --------
    4.  11110110
    5.   --------
    6.   01001000
    Самый левый бит переноса - это, очевидно, CF. А предыдущий - бит переноса в старший разряд. Вот эти два бита и ксорятся. Т.е. OF = 1 xor 1 = 0. Соответственно знакового переполнения здесь не произошло. Аналогично для вычитания, но там ксорятся биты заёма ([в старший разряд] и [из старшего разряда]).
     
  12. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Vam
    Если это Вы мне, то спасибо за информацию, я в курсе. :)
     
  13. Vam

    Vam New Member

    Публикаций:
    0
    Регистрация:
    16 июл 2008
    Сообщения:
    149
    l_inc
    Ок, с этим разобрались.
    Следовательно, к сожалению, получение (расчет) битов переноса/заема не является тривиальной задачей и зависит от инструкции, изменяющей эти биты, т.е. алгоритм расчета этих битов будет разным для разных инструкций.
    В итоге, чтобы получить биты переноса/заема, необходимо сделать побитовую эмуляцию инструкции. Как получить эти биты для операций сдвига или операций умножения/деления?
    Всё это говорит о том, что эмуляция флагов C и O является сложной задачей.

    Конечно, есть ещё один метод получения этих флагов - динамический. Создаем эту инструкцию на ассемблере, ассемблируем, выполняем и сохраняем регистр флагов - получится универсально и быстрее статической эмуляции.
     
  14. l_inc

    l_inc New Member

    Публикаций:
    0
    Регистрация:
    29 сен 2005
    Сообщения:
    2.566
    Vam
    xor битов переноса - это действия процессора для получения OF. Вытекают они из вполне очевидных условий знакового переполнения (OF = 1):
    1) Либо превышение максимального положительного числа (7F...).
    2) Либо уход в сторону уменьшения минимального отрицательного числа (80...).
    Т.е. каким образом эмулировать — это уже Ваше дело. И совсем не обязательно делать это так же, как и процессор.
    Например, OF выставляется в 0 всегда, когда не происходит смены знака (при переходе от V1 к V2).
    Если происходит смена знака, то надо рассматривать два случая:
    1) Смена знака с + на -.
    OF выставляется в 0, если V1 меньше V2 со сброшенным знаковым битом. Иначе OF = 1.
    2) Смена знака с - на +.
    OF выставляется в 0, если V2 меньше V1 со сброшенным знаковым битом. Иначе OF = 1.

    В случае операций однобитного сдвига процессор работает с OF точь-в-точь, как и с операциями сложения/вычитания. Пример (shl):
    Код (Text):
    1. <- 01011010
    2.    ————————
    3.   010110100
    Здесь результат совпадает с битами переноса. Т.к. произошёл перенос в старший разряд, но не произошло переноса из старшего разряда (1 xor 0), то OF выставляется в 1. В случае многобитных сдвигов OF согласно Intel Instruction Reference не изменяется. С умножением и делением ещё проще (см. Intel Instruction Reference).
     
  15. ut2004

    ut2004 New Member

    Публикаций:
    0
    Регистрация:
    6 дек 2006
    Сообщения:
    5
    нефик его ломать.
    люди, пользующиеся вмпротом либо дибилы, либо конкретно вылечены рекламой этого прота.
    Это же надо додумацца - изменять логику программы при прогоне ее через виртуальную машину! (флаги, фар переходы, свитчкейс)
    Хотя че взять с человека, который смотрит на асм код только и исключительно после борландовского компиля.
    Политех привет.
     
  16. d2k9

    d2k9 Алексей

    Публикаций:
    0
    Регистрация:
    14 сен 2008
    Сообщения:
    325
    Главное что не ломают его - остальное пофигу :)
    ut2004
    видно денег на лицензию, зависть берёт? ;)
     
  17. Robix

    Robix New Member

    Публикаций:
    0
    Регистрация:
    16 мар 2008
    Сообщения:
    13
    Небольшая статистика. Запротектил одну среднюю субрутину. Написано на C++ 6.0 Количество инструкций до: 919 После протекта: 40 822. По скорости примерно во столько же раз медленнее. Но впринципе это неважно, когда речь идеит о защите нескольких подпрограмм.
    Ради интереса сделал статистику :
    ДО ПОСЛЕ VM-ПРОТЕКТА
    PUSH = 65 PUSH = 1874
    CALL = 24 CALL = 24
    POP = 20 POP = 1803
    POPAD = 0 POPAD = 0
    PUSHAD = 0 PUSHAD = 0
    PUSHFD = 0 PUSHFD = 519
    POPFD = 0 POPFD = 9
    JMP = 33 JMP = 5182
    MOV = 255 MOV = 6061
    SUB = 3 SUB = 1032
    ADD = 77 ADD = 851
    AND = 11 AND = 1228
    XOR = 6 XOR = 8450
    NOT = 1 NOT = 2913
    NOP = 0 NOP = 0
    INC = 33 INC = 5591
    DEC = 65 DEC = 2652
    TEST = 44 TEST = 43
    CMP = 29 CMP = 29
    JE = 7 JE = 10
    JNE = 0 JNE = 0
    JZ = 0 JZ = 0
    JNZ = 82 JNZ = 81
    LEA = 41 LEA = 350
    RETN = 8 RETN = 15
    JA = 4 JA = 4
    JB = 8 JB = 8
    LOOP = 0 LOOP = 0
    SET = 1 SET = 1
    ROL = 0 ROL = 254
    MUL = 3 MUL = 3
    SHR = 3 SHR = 28
    SHL = 33 SHL = 101
    ROR = 0 ROR = 595
    XCHG = 0 XCHG = 3
    STOS = 0 STOS = 0
    REP = 0 REP = 771
    LEAVE = 2 LEAVE = 2
    IDIV = 0 IDIV = 0
    NEG = 0 NEG = 411
     
  18. bartolomeo

    bartolomeo New Member

    Публикаций:
    0
    Регистрация:
    20 окт 2008
    Сообщения:
    1
    Сорри за некропост - но насчёт Спектрума в посте №161 написана полная ересь, впрочем как и о сговоре MS и Intel ))
    Ну а если по теме - то тема плавно переехала вот сюда:
    http://exelab.ru/f/index.php?action=vthread&forum=13&topic=15906