Спасибо, но здесь DOS/4G. Теперь понимаю, что надо было смотреть и его документацию. Спасибо, нашлось! Код (Text): --------E-21FF00DX0078----------------------- INT 21 - Rational Systems DOS/4G - INSTALLATION CHECK AX = FF00h DX = 0078h Return: AL <> 00h if installed GS = segment of kernel if nonzero SeeAlso: INT 15/AX=BF02h
Несколько вопросов по косвенным вызовам: 1. Основной экзешник в процессе работы подгружает несколько MZ-файлов, в которых сразу за MZ-заголовком идёт 16 байт указателей, а собственно код начинается с 10h после заголовка. Правильно ли я понимаю, что инструкции вида call word ptr [bp+si+0Ch] — вызов функции, на которую указывает 2-байтное число по смещению 0Ch после MZ-заголовка? 2. IDA не всегда понимает, что вызываемая таким образом функция сохраняет стек. Нередко при включённом "Display disassembly line parts => Stack pointer" показывает подобное: Код (ASM): fn1+55 034 call word ptr [bp+si+0Ch] fn1+58 000 movzx ax, ax Как объяснить ему, что вызываемая функция сохраняет стек?
В 16-битной программе, написанной на Турбо Паскале, встретился такой вызов функции: Код (ASM): mov di, [bp+block2] shl di, 2 push word ptr [di+7E72h] push word ptr [di+7E70h] mov di, [bp+block2] shl di, 2 push word ptr [di+7F3Eh] push word ptr [di+7F3Ch] mov di, [bp+block2] shl di, 2 push word ptr [di+7E2Eh] push word ptr [di+7E2Ch] mov di, [bp+block2] shl di, 1 mov al, [di+7EB6h] push ax mov di, [bp+block2] shl di, 1 mov al, [di+7F82h] call checkVec Насколько я могу судить, ds:block2, ds:block2*2 и ds:block2*4 указывает куда-то в "кучу". То есть этот код заносит в стек хранимые в "куче" переменные. Можно ли как-то присвоить имена этим переменным? P.S. Можно ли хотя бы присвоить имена всем этим константам: 7E2Ch, 7EB6h и т.д.?
Ещё вопросы по 16-битным борландовским: 1. Есть фрагмент: Код (ASM): push cs 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): seg031:0239 align 2 seg031:023A a456789?u db 2,1Bh,'!#$456789:;<=>?u' seg031:024C aRuntimeError db 'Runtime error ',0 seg031:025B aAt db ' at ',0 seg031:0260 a__0 db '.',0Dh,0Ah,0 seg031:0264 aPortionsCopyri db 'Portions Copyright (c) 1983,92 Borland' seg031:028A seg031:028A ; =============== S U B R O U T I N E ======================================= seg031:028A seg031:028A ; Attributes: bp-based frame seg031:028A seg031:028A getMem1BE7A proc far ; CODE XREF: makeArrays+6P seg031:028A seg031:028A arg_0 = word ptr 6 seg031:028A seg031:028A ; FUNCTION CHUNK AT seg031:010F SIZE 00000004 BYTES seg031:028A seg031:028A 000 push bp seg031:028B 002 mov bp, sp seg031:028D 002 mov ax, [bp+arg_0] seg031:0290 002 call __NewMemory seg031:0293 002 pop bp seg031:0294 000 jb short loc_1BE89 seg031:0296 000 retf 2 seg031:0299 ; --------------------------------------------------------------------------- seg031:0299 seg031:0299 loc_1BE89: seg031:0299 000 mov ax, 0CBh ; '' seg031:029C 000 jmp loc_1BCFF seg031:029C getMem1BE7A endp ; sp-analysis failed
Новый вопрос по 16-битной программе в MS-DOS. Как приписывать имена константам? Некоторые адреса-константы считаются относящимися к текущему сегменту, так как правильный сегмент задан очень опосредованно. Например, такой код: Код (Text): seg008:0197 312 mov dx, seg dseg seg008:019A 312 mov ds, dx seg008:019C 312 mov dx, 6F8h ; modBuf seg008:019F 312 inc dx seg008:01A0 312 mov ah, 3Dh seg008:01A2 312 mov al, 0 seg008:01A4 312 int 21h ; DOS - 2+ - OPEN DISK FILE WITH HANDLE seg008:01A4 ; DS:DX -> ASCIZ filename seg008:01A4 ; AL = access mode seg008:01A4 ; 0 - read Я знаю, что dseg:6F8h — начало массива modBuf. При вызове прерывания данные читаются именно туда. Но IDA считает, что 6F8h относится к текущему сегменту. Я понимаю, что автоматически отследить это сложно. Но можно ли вручную как-то пометить эту константу, что это тоже ссылка на modBuf, чтобы её выводило во всяких таблицах перекрёстных ссылок? И связанный вопрос: можно ли как-то обозначать аргументы и локальные переменные, привязанные не к BP или SP, а к BX? Пример: Код (Text): seg032:0B62 000 mov bx, sp seg032:0B64 000 mov dx, ds seg032:0B66 000 lds si, ss:[bx+0Ah] seg032:0B6A 000 les di, ss:[bx+6] seg032:0B6E 000 mov cx, ss:[bx+4] seg032:0B72 000 cld seg032:0B73 000 rep movsb seg032:0B75 000 mov ds, dx seg032:0B77 000 retf 0Ah Здесь просто, но в некоторых функциях переменных десятки.
Watcom C/С++ использует по умолчанию конвенцию вызово "watcall": первые четыре аргумента передаются в функцию в регистрах: eax, edx, ebx, ecx. Соответственно, для методов классов this передавался в eax.
Спасибо. Передача в регистрах много где описана, но как она применяется к классам — нигде документации не нашёл.
Вопрос по представлению структур данных в IDA: Имеется структура Flic204. 204 байта, несколько десятков полей. bufFlic1 — массив из 8 таких структур. offBufFilc1 — массив из 8 4-байтных ссылок на них. Если не объединять 8 Flic-ов, всё выглядит аккуратно, но длинновато: Код (Text): offBufFlic1 dd offset bufFlic1, offset stru_B0CC8, offset stru_B0D94 dd offset stru_B0E60, offset stru_B0F2C, offset stru_B0FF8 dd offset stru_B10C4, offset stru_B1190 bufFlic1 Flic204 <0> stru_B0CC8 Flic204 <0> stru_B0D94 Flic204 <0> stru_B0E60 Flic204 <0> stru_B0F2C Flic204 <0> stru_B0FF8 Flic204 <0> stru_B10C4 Flic204 <0> stru_B1190 Flic204 <0> Но если объединить все флики в массив, смещения будут указываться относительно полей первого элемента массива, причём выбранных по непонятному принципу (смещения created — 22-23, reserved2 — 42-59, reserved3 — 68-108): Код (Text): offBufFlic1 dd offset bufFlic1, offset bufFlic1.head.reserved2+0A2h dd offset bufFlic1.head.created+182h, offset bufFlic1.head.reserved3+20Ch dd offset bufFlic1.head.reserved2+306h, offset bufFlic1.head.reserved3+3A4h dd offset bufFlic1.head.reserved2+49Eh, offset bufFlic1.head.reserved1+580h bufFlic1 Flic204 8 dup(<0>) dword_B125C dd 0 Вопрос: можно ли заставить показывать что-то вроде Код (Text): offBufFlic1 dd offset bufFlic1, offset bufFlic1[1], offset bufFlic1[2] ... ? Или ещё как-нибудь автоматически привязывать смещения внутри массива bufFlic1 к ближайшим элементам массива, а не к первому.
В подгружаемых оверлеях всегда строго по 4 функции. Эти функции потом используются как методы в каком-то классе. Часто некоторые из них имеют вид: Код (Text): seg073:000001CE sub_1131CE proc near seg073:000001CE seg073:000001CE var_4 = dword ptr -4 seg073:000001CE seg073:000001CE 000 push ebx seg073:000001CF 004 push ecx seg073:000001D0 008 push edx seg073:000001D1 00C push esi seg073:000001D2 010 push edi seg073:000001D3 014 push ebp seg073:000001D4 018 mov ebp, esp seg073:000001D6 018 sub esp, 4 seg073:000001D9 01C mov [ebp+var_4], eax seg073:000001DC 01C leave seg073:000001DD 014 pop edi seg073:000001DE 010 pop esi seg073:000001DF 00C pop edx seg073:000001E0 008 pop ecx seg073:000001E1 004 pop ebx seg073:000001E2 000 retn seg073:000001E2 sub_1131CE endp или Код (Text): seg073:000001E3 sub_1131E3 proc near seg073:000001E3 000 push ebx seg073:000001E4 004 push ecx seg073:000001E5 008 push edx seg073:000001E6 00C push esi seg073:000001E7 010 push edi seg073:000001E8 014 push ebp seg073:000001E9 018 mov ebp, esp seg073:000001EB 018 sub esp, 0 seg073:000001EE 018 pop ebp seg073:000001EF 014 pop edi seg073:000001F0 010 pop esi seg073:000001F1 00C pop edx seg073:000001F2 008 pop ecx seg073:000001F3 004 pop ebx seg073:000001F4 000 retn 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-го. По крайней мере, ясно, почему отличаются, если идентичный результат.