IDA и DOS4GW -- с чего начать?

Тема в разделе "WASM.BEGINNERS", создана пользователем tkzv, 20 апр 2018.

Метки:
  1. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Хочу расковырять игру 1994 года под MS-DOS. (Alien Legacy, интересна внутренняя логика — какие триггеры у ключевых событий, какие сюжетные линии авторы не доделали и отключили и т.п.) Экзешник с внедрённым DOS/4GW, собран Watcom C++. Имею IDA 7 Freeware и базовые познания в ассемблере. С чего начать? Есть какие-то руководства помимо документации по IDA и книг Касперского? Или лучше взять другой инструмент?

    Конкретные вопросы:

    1. IDA не может определить точку входа. Как её искать? — Ответ: Фриварная версия не имеет нужного лоадера "loaders/lx.*". Можно изучить структуру MZ- и LE- заголовков и написать скрипт на питоне, который будет задавать нужные параметры. (Примеры скриптов найти легче, чем полное описание формата LE.) Можно найти платную версию.

    2. Имеет ли смысл вырезать из файла DOS/4GW и дизассемблировать без него? — Ответ: Некоторые версии лоадера нормально с ним справляются, некоторые — нет. Возможно, это связано с небольшими отличиями файла от де-факто стандарта. (Часто смещение LE-заголовка указано по смещению 3Ch, но не в данном файле. Если заменять DOS4GW на стабы от DOS32A при помощи ST, она пишет смещение в 3Ch.)

    3. Текстовые строки выровнены на 4 байта. Но между ними встречается мусор ASCII. Как объяснить дизассемблеру, что адреса начал стрингов должны быть кратны 4? Дополнение: иногда начинает стринг не оттуда, даже если есть несколько ссылок на правильное начало.

    4. В функциях часто возникают выражения вида [esp+28h+var_18] Как придать им более понятный вид? В смысле заменить "28h+var_18" на имя переменной, вроде "arg_C". — Ответ: Ничего заменять не надо, это именно данные в var_18. Я перепутал выражения вида [esp+28h+var_18] и [ebp+var_18].

    5. Какой конструкции C++ или C может соответствовать эта функция, заполняющая массив указателями на функции?
    Код (Text):
    1. cseg01:0004DDF2  mov  edx, eax
    2. cseg01:0004DDF4  mov  eax, [eax]
    3. cseg01:0004DDF6  mov  dword ptr [eax], offset sub_4DEA0
    4. cseg01:0004DDFC  mov  eax, [edx]
    5. cseg01:0004DDFE  mov  dword ptr [eax+4], offset sub_4DEC0
    6. cseg01:0004DE05  mov  eax, [edx]
    7. ...
    и т.д. до [eax+38h]

    6. Для чего нужна такая таблица?
    Код (Text):
    1. int 0
    2. retn
    3. int 1
    4. retn
    5. ...
    6. int 0FFh
    7. retn
    Для вызова прерываний MS-DOS из защищённого режима?

    7. В 2 функциях, которые обращаются к этой таблице, есть фрагменты вида:
    Код (Text):
    1. cseg01:00076C3C  lea  esi, [esi+esi*2]
    2. cseg01:00076C3F  db  2Eh
    3. cseg01:00076C3F  lea  eax, intTable[esi]
    Какова роль "db 2Eh"? — Ответ: Префикс, заменяющий сегмент на CS вместо DS.
    Во что этот байт должен был бы декодироваться? Какие настройки в IDA изменить, чтобы декодировался правильно? — Ответ: Похоже, иначе IDA не умеет.

    8. db 0CDh, 20h превращается в вызов VxD вместо досовского int 20h. Какие настройки IDA поменять? — Ответ: В "Processor Options"=> "IBM PC specific analyzer options" отключить "Interpret int 20 as VxDcall".

    9. Что произойдёт при вызове int 21h, если AX=0FF00h и DX = 0078h ? Как поведёт себя версия MS-DOS, где такой функции нет? — Ответ: Это вызов DOS/4G installation check.

    10. Подгружается экзешник, в котором за MZ-заголовком идёт 16 байт указателей, а собственно код начинается с 10h. Правильно ли я понимаю, что в нём инструкции вида call word ptr [bp+si+0Ch] — вызов функции, на которую указывает 2-байтное число по смещению 0Ch после MZ-заголовка?

    11. Как объяснить IDA, что вызываемая таким образом функция сохраняет стек? Нередко при включённом "Stack pointer" показывает подобное:
    Код (ASM):
    1. fn1+55  034  call  word ptr [bp+si+0Ch]
    2. fn1+58  000  movzx  ax, ax
    P.S. В смысле, как это сделать автоматически для всех вызовов?

    (Вопросы по другому файлу: 16 бит, Турбо Паскаль, игра Reunion)
    12. Можно ли как-то присвоить имена переменным в "куче", к которым обращаются вот так:
    Код (ASM):
    1. mov     di, [bp+block2]
    2. shl     di, 2
    3. push    word ptr [di+7E2Eh]
    4. mov     di, [bp+block2]
    5. shl     di, 1
    6. mov     al, [di+7EB6h]
    Можно ли хотя бы присвоить имена этим константам: 7EB6h, 7E2Eh и т.д.?

    13. Как заставить IDA заменить последовательность push cs + call near на call far?

    14. Пытаюсь патчить, менять местами call-ы, либо вообще удалить 1-й, на его место поставить 2-й. Но просто менять адреса недостаточно. Умеет ли IDA редактировать relocation table? Или как лучше это делать?

    15. При ручном анализе кода и создании функций библиотечная функция то опознаётся, то нет. От чего это зависит?
     
    Последнее редактирование: 12 июн 2018
  2. Коцит

    Коцит Active Member

    Публикаций:
    0
    Регистрация:
    31 янв 2017
    Сообщения:
    130
    Hiew возьми. Он и перекрёсные ссылки найдёт, и EP, и править позволяет.
    Если отлаживать надумаешь, то не всякий дос-отладчик имеет доступ к памяти 1М+
    Как вариант, можешь попробовать под-эмулем 'Bochs'. У него имеется встроенный отладчик линуха GDB, который 32/64-битными регистрами видит всю память.
     
  3. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Бесплатная версия это умеет?
    До отладчиков мне далеко, но спрошу: а Dosbox так умеет?
    И кстати, умеет ли GDB выводить команды ассемблера в интеловской нотации?
    Попробовал, автоматически не нашлась. Искать LE 0x0000 и парсить заголовок LE вручную?
    Опыт показывает, что при замене dos4gw на dos4g эта игра начинает падать на ровном месте существенно чаще. То есть что-то в ней завязано на его размер. Поэтому я и пытался с неизменённым бинарником. За который браться?
    Он входит в пакет OpenWatcom? Или как он называется, если отдельная программа? Или он только в закрытой версии под ДОС был?
     
  4. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    168 100 байт вместе с MZ-заголовком. IDA я скармливал голый LE без MZ-заголовка.
    Чем это лучше сделать? Стаб я вырезал утилитами от DOS32A (когда выше писал "dos4g", имел в виду именно его) — они так могут сделать?
    Какие-то
    binw/wd.exe, binnt/wd.exe, binl/wd и rdos/wd.exe в дистрибутиве лежат.
     
  5. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Судя по тому, что отдельный файл экстендера отсутствует, эти 164 килобайта обеспечивают всю необходимую функциональность.
    И я возвращаюсь к вопросу: как узнать адреса, которые подставлять?
     
  6. njeen

    njeen Active Member

    Публикаций:
    0
    Регистрация:
    26 мар 2017
    Сообщения:
    138
    Адрес:
    Ташлинск
    Выложите файлик поглядеть - может, кто и ответит
     
  7. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Куда выкладывать? Аттачем к посту? Вот он.
    До иды доберусь только вечером. Пока спрашиваю, что делать. Вслепую уже наэкспериментировался.
     

    Вложения:

    • al.7z
      Размер файла:
      304 КБ
      Просмотров:
      300
  8. njeen

    njeen Active Member

    Публикаций:
    0
    Регистрация:
    26 мар 2017
    Сообщения:
    138
    Адрес:
    Ташлинск
    dos32a утилита выдает при распаковке выдает LE файл, который ида (6.8 точно) может загружать, находит main, start функции.
    Можете другим путем идти - загрузить в бинарном режиме, открыть описание формата, вручную размечать.
     
  9. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Фриварная 7.0 не умеет, похоже. Ковыряю вручную.

    Расписал поля MZ- и LE- заголовков. Куда дальше? Где точки входа в start() и main()? По адресу "Initial EIP"? Откуда его отсчитывать: от начала, или от "LE"? Если от начала — попадает в середину какой-то короткой функции. Если от "LE" — получается такая функция:
    Код (Text):
    1.  
    2. seg000:0008D43C                 add     eax, [eax]
    3. seg000:0008D43E                 mov     ebx, [eax]
    4. seg000:0008D440                 call    dword ptr [ebx+50h]
    5. seg000:0008D443                 mov     eax, [edx]
    6. seg000:0008D445                 lgs     ebx, [eax+40h]
    7. seg000:0008D449                 mov     esi, [eax+46h]
    8. seg000:0008D44C                 mov     ebx, gs:[ebx]
    9. seg000:0008D44F                 mov     ecx, edx
    10. seg000:0008D451                 cmp     ebx, esi
    11. seg000:0008D453                 jnb     short loc_8D458
    12. seg000:0008D455                 add     [eax+4Ah], esi
    13. seg000:0008D458
    14. seg000:0008D458 loc_8D458:                              ; CODE XREF: seg000:0008D453↑j
    15. seg000:0008D458                 mov     eax, [ecx]
    16. seg000:0008D45A                 mov     [eax+46h], ebx
    17. seg000:0008D45D                 mov     eax, [ecx]
    18. seg000:0008D45F                 mov     ebp, [eax+4Ah]
    19. seg000:0008D462                 mov     eax, [edx]
    20. seg000:0008D464                 add     ebx, ebp
    21. seg000:0008D466                 mov     [eax+52h], ebx
    22. seg000:0008D469                 mov     eax, [edx]
    23. seg000:0008D46B                 mov     [eax+5Ah], ebx
    24. seg000:0008D46E
    25. seg000:0008D46E loc_8D46E:                              ; CODE XREF: seg000:0008D437↑j
    26. seg000:0008D46E                 pop     ebp
    27. seg000:0008D46F                 pop     esi
    28. seg000:0008D470                 pop     edx
    29. seg000:0008D471                 pop     ecx
    30. seg000:0008D472                 pop     ebx
    31. seg000:0008D473                 retn
    32.  
    Выглядит правдоподобно? Или просто совпадение? И что с ней делать дальше? Как понять, куда пойдёт call dword ptr [ebx+50h] ?
     
  10. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    В опенсорсной версии 1.9.0 тоже есть. Но игра под ним стабильно падает при инициализации.
    Никакого сложного шифрования там нет, вроде, так что обойдусь без него, надеюсь.
     
  11. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Очередной вопрос. В функциях часто возникают выражения вида [esp+28h+var_18] Как придать им более понятный вид? В смысле заменить "28h+var_18" на имя переменной.
     
  12. njeen

    njeen Active Member

    Публикаций:
    0
    Регистрация:
    26 мар 2017
    Сообщения:
    138
    Адрес:
    Ташлинск
    Здесь var_18 уже есть имя переменной. Вы можете только переименовать её. Редактировать определение переменных на стеке в функции нужно в соотв. вьюхе стека (ctrl+k, кажется) функции. Там же можно изменить тип переменной.
    Вообще, откройте для себя уже 'The Ida pro book' .
     
  13. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Ответ не на тот вопрос, который я подразумевал :) Когда IDA пишет [esp+28h+var_18], она имеет в виду именно данные в var_18, а не в 28h байтах от var_18. При первом прочтении The Ida pro book я этот момент упустил.
     
  14. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Наткнулся на такую функцию:
    Код (Text):
    1. cseg01:0004DDF0 fillSomeTable  proc near  ; CODE XREF: sub_4DDD0+14p
    2. cseg01:0004DDF0  push  ebx
    3. cseg01:0004DDF1  push  edx
    4. cseg01:0004DDF2  mov  edx, eax
    5. cseg01:0004DDF4  mov  eax, [eax]
    6. cseg01:0004DDF6  mov  dword ptr [eax], offset sub_4DEA0
    7. cseg01:0004DDFC  mov  eax, [edx]
    8. cseg01:0004DDFE  mov  dword ptr [eax+4], offset sub_4DEC0
    9. cseg01:0004DE05  mov  eax, [edx]
    10. ...
    11. cseg01:0004DE6A  mov  dword ptr [eax+34h], offset sub_4E740
    12. cseg01:0004DE71  mov  eax, [edx]
    13. cseg01:0004DE73  mov  dword ptr [eax+38h], offset sub_4E7B0
    14. cseg01:0004DE7A  xor  eax, eax
    15. cseg01:0004DE7C  lea  eax, [eax+0]
    16. cseg01:0004DE80
    17. cseg01:0004DE80 loc_4DE80:  ; CODE XREF: fillSomeTable+A7j
    18. cseg01:0004DE80  mov  ebx, [edx]
    19. cseg01:0004DE82  mov  byte ptr [ebx+eax+3Ch], 0
    20. cseg01:0004DE87  inc  eax
    21. cseg01:0004DE88  mov  ebx, [edx]
    22. cseg01:0004DE8A  mov  byte ptr [ebx+eax+0BBh], 0
    23. cseg01:0004DE92  cmp  eax, 80h
    24. cseg01:0004DE97  jb  short loc_4DE80
    25. cseg01:0004DE99  pop  edx
    26. cseg01:0004DE9A  pop  ebx
    27. cseg01:0004DE9B  retn
    28. cseg01:0004DE9B fillSomeTable  endp
    Понял, что идёт заполнение массива указателями на функции. Какой конструкции C++ или C это соответствует?

    Те функции в этой таблице, с которыми я пока разобрался, открывают и загружают экзешники с побочными сюжетными линиями.
     
  15. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    1. Наткнулся на такую последовательность:
    Код (Text):
    1. db 0CDh, 0, 0C3h
    2. db 0CDh, 1, 0C3h
    3. ...
    4. db 0CDh, 0FFh, 0C3h
    Она декодируется в:
    Код (Text):
    1. int 0
    2. retn
    3. int 1
    4. retn
    5. ...
    6. int 0FFh
    7. retn
    Для чего она нужна? Для вызова прерываний MS-DOS из защищённого режима?

    2. В 2 функциях, которые обращаются к этой таблице, есть фрагмент:
    db 8Dh, 34h, 76h, 2Eh, 8Dh, 86h, 0E2h, 6Ch, 7, 0
    Код (Text):
    1. cseg01:00076C3C                 lea     esi, [esi+esi*2]
    2. cseg01:00076C3F                 db      2Eh
    3. cseg01:00076C3F                 lea     eax, intTable[esi]
    4.  
    либо то же но с "eax, [eax+eax*2]" в 1-ой строке

    Какова роль "db 2Eh"? Во что этот байт должен был бы декодироваться? Какие настройки в IDA изменить, чтобы декодировался правильно?

    3. db 0CDh, 20h превращается в вызов VxD вместо досовского int 20h. Какие настройки IDA поменять?
     
  16. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    То есть db 2Eh переопределяет сегмент для intTable? Спасибо. Действительно, большинство данных — в отдельном сегменте, но intTable в одном сегменте с кодом.

    Но в статье написано, что с версии 4.17 IDA научился работать с одиночными префиксами. А тут почему-то оставил db 2Eh.
     
  17. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Ожидал, что да. Никаких посторонних db, все переопределения — в строке с lea.
    Понятно.
     
  18. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Помогло отключить "Interpret int 20 as VxDcall" в диалоге "IBM PC specific analyzer options" (доступен по кнопке "Processor Options" при загрузке экзешника или позже через "Options => General... => Analysis => Processor specific analysis options").
     
  19. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Где можно узнать, что даёт функция MS-DOS FF? Имеется фрагмент:
    Код (Text):
    1. mov     dx, 78h
    2. mov     ax, 0FF00h
    3. int     21h            
    4.  
    То есть вызывается int 21h с AH=FFh. В документации такой функции нет. Что она может делать?
    Если эта функция присутствовала только в отдельных OEM версиях, как ведут себя остальные DOS-ы?
     
  20. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.708
    tkzv,
    Р.Браун, Дж.Кайл "Справочник по прерываниям IBM PC" том 1, изд "Мир" 1994, глава 9
    Прерывание 21h функция 0FFh, назначение ― упрощение доступа к некоторым часто используемым функциям MS-DOS из защищенного режима, работают под расширителем DOS GO32 Д.Дж.Делори
     
    CKAP нравится это.