1. Если вы только начинаете программировать на ассемблере и не знаете с чего начать, тогда попробуйте среду разработки ASM Visual IDE
    (c) на правах рекламы
    Скрыть объявление

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

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

Метки:
  1. njeen

    njeen Member

    Публикаций:
    0
    Регистрация:
    26 мар 2017
    Сообщения:
    76
    Адрес:
    Ташлинск
  2. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Спасибо, но здесь DOS/4G. Теперь понимаю, что надо было смотреть и его документацию.
    Спасибо, нашлось!
    Код (Text):
    1. --------E-21FF00DX0078-----------------------
    2. INT 21 - Rational Systems DOS/4G - INSTALLATION CHECK
    3.         AX = FF00h
    4.         DX = 0078h
    5. Return: AL <> 00h if installed
    6.             GS = segment of kernel if nonzero
    7. SeeAlso: INT 15/AX=BF02h
     
  3. tkzv

    tkzv Member

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

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

    Вложения:

    • r24.7z
      Размер файла:
      1,5 КБ
      Просмотров:
      72
  4. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Имею в виду, как обойтись без ручного вызова "Change Stack Pointer" на каждом call-е?
     
  5. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Даже если все вызовы — одной функции?
     
  6. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    В 16-битной программе, написанной на Турбо Паскале, встретился такой вызов функции:
    Код (ASM):
    1.  
    2. mov     di, [bp+block2]
    3. shl     di, 2
    4. push    word ptr [di+7E72h]
    5. push    word ptr [di+7E70h]
    6. mov     di, [bp+block2]
    7. shl     di, 2
    8. push    word ptr [di+7F3Eh]
    9. push    word ptr [di+7F3Ch]
    10. mov     di, [bp+block2]
    11. shl     di, 2
    12. push    word ptr [di+7E2Eh]
    13. push    word ptr [di+7E2Ch]
    14. mov     di, [bp+block2]
    15. shl     di, 1
    16. mov     al, [di+7EB6h]
    17. push    ax
    18. mov     di, [bp+block2]
    19. shl     di, 1
    20. mov     al, [di+7F82h]
    21. call  checkVec
    22.  
    Насколько я могу судить, ds:block2, ds:block2*2 и ds:block2*4 указывает куда-то в "кучу". То есть этот код заносит в стек хранимые в "куче" переменные. Можно ли как-то присвоить имена этим переменным?
    P.S. Можно ли хотя бы присвоить имена всем этим константам: 7E2Ch, 7EB6h и т.д.?
     
    Последнее редактирование: 9 июн 2018
  7. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Ещё вопросы по 16-битным борландовским:
    1. Есть фрагмент:
    Код (ASM):
    1. push    cs
    2. call    near ptr DecodeFrame
    Но это — дальний вызов, выход из DecodeFrame — по retf, а не ret. Как заставить IDA заменить call near на call far?

    2. Попробовал поменять местами вызовы нескольких функций через "Edit => Patch Program => Change Byte..." Просто сменил адреса. Получил предупреждение, что там релокейшены, и результат не соответствовал ожиданиям — при дизассемблировании патченого файла на этих местах были совсем другие вызовы. Вопрос: можно ли в
    IDA добиться нужного результата? Она умеет редактировать relocation table? Или что там лучше делать? (Пока обошёлся последовательностью JMP.)

    3. Одна библиотечная функция автоматически не распозналась. Я её распознал вручную, и она сразу же опозналась как библиотечная (что-то связанное с резервированием памяти), подставились соответствующие комментарии и т.д. Затем IDA упала. Я повторно распознал эту функцию, но в этот раз она не опозналась как библиотечная. Как понять, в чём проблема?
    Код (ASM):
    1. seg031:0239  align 2
    2. seg031:023A  a456789?u  db 2,1Bh,'!#$456789:;<=>?u'
    3. seg031:024C  aRuntimeError  db 'Runtime error ',0
    4. seg031:025B  aAt  db ' at ',0
    5. seg031:0260  a__0  db '.',0Dh,0Ah,0
    6. seg031:0264  aPortionsCopyri db 'Portions Copyright (c) 1983,92 Borland'
    7. seg031:028A
    8. seg031:028A  ; =============== S U B R O U T I N E =======================================
    9. seg031:028A
    10. seg031:028A  ; Attributes: bp-based frame
    11. seg031:028A
    12. seg031:028A     getMem1BE7A     proc far  ; CODE XREF: makeArrays+6P
    13. seg031:028A
    14. seg031:028A     arg_0           = word ptr  6
    15. seg031:028A
    16. seg031:028A     ; FUNCTION CHUNK AT seg031:010F SIZE 00000004 BYTES
    17. seg031:028A
    18. seg031:028A 000                 push    bp
    19. seg031:028B 002                 mov     bp, sp
    20. seg031:028D 002                 mov     ax, [bp+arg_0]
    21. seg031:0290 002                 call    __NewMemory
    22. seg031:0293 002                 pop     bp
    23. seg031:0294 000                 jb      short loc_1BE89
    24. seg031:0296 000                 retf    2
    25. seg031:0299     ; ---------------------------------------------------------------------------
    26. seg031:0299
    27. seg031:0299     loc_1BE89:
    28. seg031:0299 000                 mov     ax, 0CBh ; ''
    29. seg031:029C 000                 jmp     loc_1BCFF
    30. seg031:029C     getMem1BE7A     endp ; sp-analysis failed
     
  8. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Новый вопрос по 16-битной программе в MS-DOS. Как приписывать имена константам?

    Некоторые адреса-константы считаются относящимися к текущему сегменту, так как правильный сегмент задан очень опосредованно. Например, такой код:
    Код (Text):
    1. seg008:0197 312                 mov     dx, seg dseg
    2. seg008:019A 312                 mov     ds, dx
    3. seg008:019C 312                 mov     dx, 6F8h        ; modBuf
    4. seg008:019F 312                 inc     dx
    5. seg008:01A0 312                 mov     ah, 3Dh
    6. seg008:01A2 312                 mov     al, 0
    7. seg008:01A4 312                 int     21h             ; DOS - 2+ - OPEN DISK FILE WITH HANDLE
    8. seg008:01A4                                             ; DS:DX -> ASCIZ filename
    9. seg008:01A4                                             ; AL = access mode
    10. seg008:01A4                                             ; 0 - read
    Я знаю, что dseg:6F8h — начало массива modBuf. При вызове прерывания данные читаются именно туда. Но IDA считает, что 6F8h относится к текущему сегменту. Я понимаю, что автоматически отследить это сложно. Но можно ли вручную как-то пометить эту константу, что это тоже ссылка на modBuf, чтобы её выводило во всяких таблицах перекрёстных ссылок?

    И связанный вопрос: можно ли как-то обозначать аргументы и локальные переменные, привязанные не к BP или SP, а к BX? Пример:
    Код (Text):
    1. seg032:0B62 000                 mov     bx, sp
    2. seg032:0B64 000                 mov     dx, ds
    3. seg032:0B66 000                 lds     si, ss:[bx+0Ah]
    4. seg032:0B6A 000                 les     di, ss:[bx+6]
    5. seg032:0B6E 000                 mov     cx, ss:[bx+4]
    6. seg032:0B72 000                 cld
    7. seg032:0B73 000                 rep movsb
    8. seg032:0B75 000                 mov     ds, dx
    9. seg032:0B77 000                 retf    0Ah
    Здесь просто, но в некоторых функциях переменных десятки.
     
  9. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Каким образом 32-разрядный досовский Watcom C++ передавал в методы классов указатель на this? В EAX?
     
  10. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.553
    Адрес:
    г. Санкт-Петербург
    Watcom C/С++ использует по умолчанию конвенцию вызово "watcall": первые четыре аргумента передаются в функцию в регистрах: eax, edx, ebx, ecx. Соответственно, для методов классов this передавался в eax.
     
  11. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Спасибо. Передача в регистрах много где описана, но как она применяется к классам — нигде документации не нашёл.
     
  12. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.553
    Адрес:
    г. Санкт-Петербург
    this всегда передаётся как первый аргумент метода, независимо от конвенции вызова.
     
  13. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Спасибо, буду знать.
     
  14. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    Вопрос по представлению структур данных в IDA:

    Имеется структура Flic204. 204 байта, несколько десятков полей. bufFlic1 — массив из 8 таких структур. offBufFilc1 — массив из 8 4-байтных ссылок на них.
    Если не объединять 8 Flic-ов, всё выглядит аккуратно, но длинновато:
    Код (Text):
    1.  
    2. offBufFlic1     dd offset bufFlic1, offset stru_B0CC8, offset stru_B0D94
    3.                 dd offset stru_B0E60, offset stru_B0F2C, offset stru_B0FF8
    4.                 dd offset stru_B10C4, offset stru_B1190
    5. bufFlic1        Flic204 <0>
    6. stru_B0CC8      Flic204 <0>
    7. stru_B0D94      Flic204 <0>
    8. stru_B0E60      Flic204 <0>
    9. stru_B0F2C      Flic204 <0>
    10. stru_B0FF8      Flic204 <0>
    11. stru_B10C4      Flic204 <0>
    12. stru_B1190      Flic204 <0>
    13.  
    Но если объединить все флики в массив, смещения будут указываться относительно полей первого элемента массива, причём выбранных по непонятному принципу (смещения created — 22-23, reserved2 — 42-59, reserved3 — 68-108):
    Код (Text):
    1.  
    2. offBufFlic1  dd offset bufFlic1, offset bufFlic1.head.reserved2+0A2h
    3.              dd offset bufFlic1.head.created+182h, offset bufFlic1.head.reserved3+20Ch
    4.              dd offset bufFlic1.head.reserved2+306h, offset bufFlic1.head.reserved3+3A4h
    5.              dd offset bufFlic1.head.reserved2+49Eh, offset bufFlic1.head.reserved1+580h
    6. bufFlic1     Flic204 8 dup(<0>)
    7. dword_B125C  dd 0
    8.  
    Вопрос: можно ли заставить показывать что-то вроде
    Код (Text):
    1. offBufFlic1  dd offset bufFlic1, offset bufFlic1[1], offset bufFlic1[2] ...
    ? Или ещё как-нибудь автоматически привязывать смещения внутри массива bufFlic1 к ближайшим элементам массива, а не к первому.
     
    Последнее редактирование: 13 апр 2019
  15. f13nd

    f13nd Active Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    882
    Скорей всего только скриптом через SetManualInsn() полностью заменить.
     
  16. tkzv

    tkzv Member

    Публикаций:
    0
    Регистрация:
    20 апр 2018
    Сообщения:
    31
    В подгружаемых оверлеях всегда строго по 4 функции. Эти функции потом используются как методы в каком-то классе. Часто некоторые из них имеют вид:
    Код (Text):
    1. seg073:000001CE  sub_1131CE  proc near
    2. seg073:000001CE
    3. seg073:000001CE  var_4  = dword ptr -4
    4. seg073:000001CE
    5. seg073:000001CE 000  push  ebx
    6. seg073:000001CF 004  push  ecx
    7. seg073:000001D0 008  push  edx
    8. seg073:000001D1 00C  push  esi
    9. seg073:000001D2 010  push  edi
    10. seg073:000001D3 014  push  ebp
    11. seg073:000001D4 018  mov  ebp, esp
    12. seg073:000001D6 018  sub  esp, 4
    13. seg073:000001D9 01C  mov  [ebp+var_4], eax
    14. seg073:000001DC 01C  leave
    15. seg073:000001DD 014  pop  edi
    16. seg073:000001DE 010  pop  esi
    17. seg073:000001DF 00C  pop  edx
    18. seg073:000001E0 008  pop  ecx
    19. seg073:000001E1 004  pop  ebx
    20. seg073:000001E2 000  retn
    21. seg073:000001E2  sub_1131CE  endp
    или
    Код (Text):
    1. seg073:000001E3  sub_1131E3  proc near
    2. seg073:000001E3 000  push  ebx
    3. seg073:000001E4 004  push  ecx
    4. seg073:000001E5 008  push  edx
    5. seg073:000001E6 00C  push  esi
    6. seg073:000001E7 010  push  edi
    7. seg073:000001E8 014  push  ebp
    8. seg073:000001E9 018  mov  ebp, esp
    9. seg073:000001EB 018  sub  esp, 0
    10. seg073:000001EE 018  pop  ebp
    11. seg073:000001EF 014  pop  edi
    12. seg073:000001F0 010  pop  esi
    13. seg073:000001F1 00C  pop  edx
    14. seg073:000001F2 008  pop  ecx
    15. seg073:000001F3 004  pop  ebx
    16. seg073:000001F4 000  retn
    17. seg073:000001F4  sub_1131E3  endp
    Единственный передаваемый параметр — EAX, ссылка на объект.

    Вопрос: есть ли какая-нибудь разница между этими функциями? Или они обе не оставляют никаких результатов, а записанный в стек EAX использовать далее нереально?
    --- Сообщение объединено, 3 май 2019 ---
    Поправка: вариант с "sub esp, 4 — mov [ebp+var_4], eax — leave" встречается только для методов 1, 2, 3, вариант с sub esp, 0 — только для 4-го. По крайней мере, ясно, почему отличаются, если идентичный результат.
     
    Последнее редактирование: 3 май 2019