Эмуляции инструкций x86-32

Тема в разделе "WASM.RESEARCH", создана пользователем Smile, 25 янв 2007.

  1. Smile

    Smile New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2004
    Сообщения:
    129
    Долго но плохо искал, нашел SoftX86 на sourceforg.net, очень понравилось но ксожалению только для 16 битного кода.
    Можно ли использовать мутантов типа boch, или wine для этих целей, тоесть втроить в программц как модуль или есть какие другие средства?

    Мне вполне достаточно будет вычислять несложные выражения и проверять константность условий.

    Код (Text):
    1. mov eax,1
    2. mov ecx,2
    3. add eax,ecx
    Код (Text):
    1. xor eax,eax
    2. jz  true
    Если для этих целей использовать дизассемблер то там придется как-то отслеживать, даже с информацией об операндах и флагах(как в xde/disit), будет сложновато.
     
  2. _BC_

    _BC_ БЦ

    Публикаций:
    0
    Регистрация:
    20 янв 2005
    Сообщения:
    759
    если эмулировать только регистры и флажки, то вообщем-то ничего сложного -- на каждый регистр заводишь переменную-значение и переменную-тэг. 'Значение' хранит (как ни странно) текущее значение регистра. ;) Тэг показывает состояние эмулируемого регистра -- в простейшем случае флажок константа/неконстанта. Аналогично для eflags. Когда встречаешь команду загрузки/обнуления/etc. imm-значения в регистр, помечаешь тэг регистра как константу и запоминаешь значение регистра. Далее...
    1) встретив команду, все операнды которой 'известны', выполняешь ее над запомненнными значениями регистров, результат помечаешь как константу, флажки помечаешь как известные, pushf/pop в значение eflags.
    2) если хотя бы один операнд 'неизвестен' (например, операнд из памяти, если память не эмулится), помечаешь результат как unknown (и флажки, если надо).

    Такое может например понадобится для обнаружения заведомо срабатывающих/несрабатывающих условных переходов -- типа
    Код (Text):
    1. mov eax, 1243254543h
    2. xor eax, 432535354h
    3. add eax, 53453463h
    4. sub eax, 23424534h
    5. cmp eax, 345434554h
    6. jc somewhere
    и для твоего случая тоже должно по идее подойти. ;)
     
  3. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    В тулзах два эмулятора лежат, как плагины к IDA.
     
  4. _BC_

    _BC_ БЦ

    Публикаций:
    0
    Регистрация:
    20 янв 2005
    Сообщения:
    759
    такими точно будет сложновато, все равно что гирей муху на лету сбивать -- сложно и неэффективно. ;)
     
  5. Smile

    Smile New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2004
    Сообщения:
    129
    _BC_
    Ну раз ничего сложного, будем пробовать :)

    IceStudent
    Видел, разве удастся отделить их от иды и заюзать?
     
  6. droopy

    droopy New Member

    Публикаций:
    0
    Регистрация:
    2 окт 2004
    Сообщения:
    21
    Вот эмулятор www.droopy.narod.ru/download/lezgin.htm
    Правда он кривой немного и исходники все потерялись.
    Но я работаю над этим
     
  7. Smile

    Smile New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2004
    Сообщения:
    129
    droopy
    Прикольно, а что мне с ним делать, дизассемблировать? :)
     
  8. droopy

    droopy New Member

    Публикаций:
    0
    Регистрация:
    2 окт 2004
    Сообщения:
    21
    Что делать не знаю. Говорю исходников нет. Я сам его уже 2 недели дизассемблирую.
    А что именно за задача стоит? Можно написать что-нибудь похожее.
    Это не так уж сложно :)
     
  9. Smile

    Smile New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2004
    Сообщения:
    129
    droopy
    Вообще идеальная ситуация, задать состояние проца структурой
    Код (Text):
    1. struct Context
    2. {
    3.  DWORD ip
    4.  struct Register {
    5.   bool undefined; // не инициализирован
    6.   DWORD value;
    7.  }
    8.  Register regs[8];
    9.  bool (*om_memory_read)(DWORD address, DWORD size);
    10.  bool (*om_memory_write)(DWORD address, DWORD size);
    11. }
    12. bool execute(Context* context, byte* code, int length);
    Я устанавливаю контекст, колбеки на чтение запись, и пробую исполнить кусок кода,(мжно даже пошагово) получаю результат или болт :)

    А задача, ну вычислить статическое выражение или проверить условие перехода, там выше написано, тоесть полная эмуляция мне не нужна
     
  10. Smile

    Smile New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2004
    Сообщения:
    129
    А если подумать то и условия проверять не нужно.
    Ну кратко вообщем расскажу

    Код (Text):
    1. #pragma comment(linker,"/ENTRY:main")
    2. extern "C" {
    3. char* strcpy(char*,char*);
    4. int printf(char*,...);
    5. }
    6.  
    7. int
    8. main(int argc, char** argv)
    9. {
    10.   char buffer[10];
    11.   char program[10];
    12.   for(int i=0; i<argc; i++) {
    13.     if(i==0) {
    14.       strcpy(buffer,argv[i]);
    15.     }
    16.     else if(i==1) {
    17.       strcpy(buffer,argv[i]);
    18.     }
    19.     else {
    20.       return 0;
    21.     }
    22.   }
    23.   printf("%s %s\n",program,buffer);
    24.     return 1;
    25. }
    Код (Text):
    1. 00401000> sub_00401000-0
    2. 00401000: SUB       ESP,1CH
    3. 00401003: MOV       EAX,[0040A000H]
    4. 00401008: XOR       EAX,ESP
    5. 0040100A: MOV       [ESP+18H],EAX
    6. 0040100E: PUSH      EBX
    7. 0040100F: MOV       EBX,[ESP+24H]
    8. 00401013: PUSH      ESI
    9. 00401014: XOR       ESI,ESI
    10. 00401016: TEST      EBX,EBX
    11. 00401018: PUSH      EDI
    12. 00401019: JLE       L_00401063
    13. 0040101B: MOV       EDI,[ESP+30H]
    14. 0040101F: NOP
    15. L_00401020:
    16. 00401020: TEST      ESI,ESI                       ;+00401061
    17. 00401022: JNZ       L_0040103E
    18. 00401024: MOV       EAX,[EDI]
    19. 00401026: LEA       EDX,[ESP+0CH]
    20. 0040102A: SUB       EDX,EAX
    21. 0040102C: LEA       ESP,[ESP]
    22. L_00401030:
    23. 00401030: MOV       CL,[EAX]                      ;+0040103A
    24. 00401032: MOV       [EDX+EAX],CL
    25. 00401035: ADD       EAX,01H
    26. 00401038: TEST      CL,CL
    27. 0040103A: JNZ       L_00401030
    28. 0040103C: JMP       L_0040105C
    29. L_0040103E:
    30. 0040103E: CMP       ESI,01H                       ;-00401022
    31. 00401041: JNZ       L_00401091
    32. 00401043: MOV       EAX,[EDI+04H]
    33. 00401046: LEA       EDX,[ESP+0CH]
    34. 0040104A: SUB       EDX,EAX
    35. 0040104C: LEA       ESP,[ESP]
    36. L_00401050:
    37. 00401050: MOV       CL,[EAX]                      ;+0040105A
    38. 00401052: MOV       [EDX+EAX],CL
    39. 00401055: ADD       EAX,01H
    40. 00401058: TEST      CL,CL
    41. 0040105A: JNZ       L_00401050
    42. L_0040105C:
    43. 0040105C: ADD       ESI,01H                       ;-0040103C
    44. 0040105F: CMP       ESI,EBX
    45. 00401061: JL        L_00401020
    46. L_00401063:
    47. 00401063: LEA       EAX,[ESP+0CH]                 ;-00401019
    48. 00401067: PUSH      EAX
    49. 00401068: LEA       ECX,[ESP+1CH]
    50. 0040106C: PUSH      ECX
    51. 0040106D: PUSH      00408108H
    52. 00401072: CALL      sub_004010A5
    53. 00401077: ADD       ESP,0CH
    54. 0040107A: POP       EDI
    55. 0040107B: POP       ESI
    56. 0040107C: MOV       EAX,00000001H
    57. 00401081: POP       EBX
    58. 00401082: MOV       ECX,[ESP+18H]
    59. 00401086: XOR       ECX,ESP
    60. 00401088: CALL      sub_0040116A
    61. 0040108D: ADD       ESP,1CH
    62. 00401090: RET
    63. L_00401091:
    64. 00401091: MOV       ECX,[ESP+24H]                 ;-00401041
    65. 00401095: POP       EDI
    66. 00401096: POP       ESI
    67. 00401097: POP       EBX
    68. 00401098: XOR       ECX,ESP
    69. 0040109A: XOR       EAX,EAX
    70. 0040109C: CALL      sub_0040116A
    71. 004010A1: ADD       ESP,1CH
    72. 004010A4: RET
    В атаче рисунок, это типа граф переходов который я получаю после, анализа кода

    <С> условие, (J) прижок, поток инструкции, {T} завершающая инструкция.

    Теперь, нулевой блок представляет из себя, условие тоесть <C>
    и состоит из инструкций
    Код (Text):
    1. 00401000: SUB       ESP,1CH
    2. 00401003: MOV       EAX,[0040A000H]
    3. 00401008: XOR       EAX,ESP
    4. 0040100A: MOV       [ESP+18H],EAX
    5. 0040100E: PUSH      EBX
    6. 0040100F: MOV       EBX,[ESP+24H]
    7. 00401013: PUSH      ESI
    8. 00401014: XOR       ESI,ESI
    9. 00401016: TEST      EBX,EBX
    10. 00401018: PUSH      EDI
    11. 00401019: JLE       L_00401063
    Но насамом деле условие это
    Код (Text):
    1. 0040100F: MOV       EBX,[ESP+24H]
    2. 00401013: PUSH      ESI
    3. 00401014: XOR       ESI,ESI
    4. 00401016: TEST      EBX,EBX
    5. 00401018: PUSH      EDI
    6. 00401019: JLE       L_00401063
    И если это проэмулировать получится, более ясная картина, пролого функции
    -> <C> вместо <C>

    Также и с конструкциями типа IF, можно будет отделить, инструкции не относящиеся к вычислению перехода, например:
    Код (Text):
    1. bool calc=true;
    2. x = 1,y = 2;
    3. if(calc) {
    4. }
    Здесь получится определить что операции над "x = 1,y = 2;" не относятся к условию "if(calc)", и чем больше таких ситуаций распознается тем меньша нужно вмешательство интелекта в ход разбора :)

    А вот что с этим всем делать уже другая история
     
  11. _BC_

    _BC_ БЦ

    Публикаций:
    0
    Регистрация:
    20 янв 2005
    Сообщения:
    759
    хм, процедуры с алгоритмами, которые зависят от внешних (по отношению к процедуре) аргументов и переменных -- это совсем не статическое выражение, которое можно 'вычислить' эмулятором. Если уж тут что эмулировать, то только 'символьно'.
     
  12. Smile

    Smile New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2004
    Сообщения:
    129
    _BC_
    Ну значит мне нужно "символьно", низнаю как это но мне наверное подходит :)
    Смысл в чем, если можно получить дополнительную инфу через выполнение нескольких инструкций это хорошо, если выполнение невозможно, ну и без него справимся.

    Кароче, дело к ночи, толку нету, помогу себе сам.
     
  13. Smile

    Smile New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2004
    Сообщения:
    129
    Нет, всетаки процесс пошел, я зря парил вам мозг, технологии предложеной товарищем _BC_, мне вполне хвати, просто рашитывал получить все и сразу :)
     
  14. _BC_

    _BC_ БЦ

    Публикаций:
    0
    Регистрация:
    20 янв 2005
    Сообщения:
    759
    имхо лучше бы сказал, какая конечная задача. Что-то мне подсказывает, что размышления вида "а вот мы выполним эти несколько команд, а затем по изменениям регистров/флагов/и тп сделаем выводы" едва ли помогут в ее решении, анализ кода и эмуляция -- вещи разные.
     
  15. Smile

    Smile New Member

    Публикаций:
    0
    Регистрация:
    28 июл 2004
    Сообщения:
    129
    _BC_
    Задача анализ кода и декомпиляция, ращитана на компилятор С/С++.
     
  16. _BC_

    _BC_ БЦ

    Публикаций:
    0
    Регистрация:
    20 янв 2005
    Сообщения:
    759
    нда, было что-то такое, но оно выдавало сишный код, который читался куда хуже своей ассемблерной первообразной. ;)
     
  17. Asterix

    Asterix New Member

    Публикаций:
    0
    Регистрация:
    25 фев 2003
    Сообщения:
    3.576
    desquirr,
    bumerang,
    INQUISITION ?
     
  18. _BC_

    _BC_ БЦ

    Публикаций:
    0
    Регистрация:
    20 янв 2005
    Сообщения:
    759
    REC вроде, остальное особо не смотрел
     
  19. W4FhLF

    W4FhLF New Member

    Публикаций:
    0
    Регистрация:
    3 дек 2006
    Сообщения:
    1.050
    Rec 2.0 даёт довольно неплохие результаты, особенно когда надо какой-нибудь крипто/математический алгоритм зареверсить.
     
  20. droopy

    droopy New Member

    Публикаций:
    0
    Регистрация:
    2 окт 2004
    Сообщения:
    21
    Мой алгоритм эмуляции выглядит примерно так:
    Код (Text):
    1. call  GetNextByte   ;читает al <-[eip]
    2. and    eax, 0FFh
    3. call  dword ptr emul_table[eax*4]
    4. .....
    5.  
    6. emul_add_rmb:
    7.                   call   GetNextByte
    8.                   call   GetByteOperands
    9. ;возвращает в ebx и ecx указатели на операнды команды
    10. ;это может быть память или регистр (Reg...)
    11.                   mov  al, [ecx]
    12.                   add  [ebx], al
    13.                   pushfd
    14.                   pop  RegFlags
    15.                   ret
    16. ...
    17.  
    18. .data
    19. RegEax      dd 0
    20. RegEbx      dd 0
    21. RegEcx      dd 0
    22. RegEdx      dd 0
    23. RegEsi      dd 0
    24. RegEdi      dd 0
    25. RegEbp      dd 0
    26. RegEsp      dd 0
    27. RegEip      dd 0
    28. RegFlags    dd 0
    29.  
    30. emul_table   label  dword
    31.           dd    offset  emul_add_rmb
    32.           dd    offset  emul_add_rmd
    33.           ...
    Вот и все, по-моему, ничего сложного. Вооружаешься справочником по командам x86 и забиваешь всю таблицу.