14 серпня 1984 року вийшла DOS 3.00. Вона, по великому рахунку, була останньою радикально переписаною версією DOS. Додано основу для підтримки мереж. Створено підтримку “Network redirector”, при чому, майже повну. Хоча підтримку мережі не встигли закінчити, в результаті чого ніхто ним не користувався, але було додано критичні для роботи мережі механізми: перенаправлення та блокування файлів. З'явилася можливість створювати "користувацькі" файлові системи (installable filesystems), за допомогою яких потім, зокрема, було реалізовано підтримку CD-дисків. Із більш приземлених речей, додано підтримку п'ятидюймових 1.2Мб дискет, FAT16 (правда, такі диски ставали несумісними із DOS 2.10, крім того, диски розміром більше 15Мб, форматовані з-під DOS2, стали несумісними із DOS3+), давно очікувану підтримку годинника реального часу, (тепер не було потреби вводити час і дату кожного запуску наново), додано утиліту ATTRIB.EXE для роботи із атрибутами файлів --- першу системну програму DOS, написану на С, покращено підтримку не-англомовних користувачів.
Детальніше можна почитати тут: "DOS 3.0, 3.1, and 3.2" і тут: "Timeline of DOS operating systems", а я повернуся до SYS.COM.
Дизасемблювавши, побачив щось, абсолютно не схоже на звичний SYS.COM. Перша думка була про не-мікрософтівську OEM-версію (таке вже траплялося), але прожила та думка недовго. Виявилося, що файл хитро "закодований". Спочатку він розкодовується, точніше --- перекодовується, і ми бачимо, що COM-файл, насправді, є таким собі псевдо-EXE, із вбудованим завантажувачем. Образ цього EXE в пам'яті вже є менш-більш звичним SYS. За одним важливим винятком. Друк більшості повідомлень реалізований через функцію, яка дуже нагадує printf, правда --- жорстоко урізаний. При чому, ця функція викликається дальнім (far) викликом, і, можливо саме заради неї над SYS.COM так познущалися.
Дизасемблювавши, побачив щось, абсолютно не схоже на звичний SYS.COM. Перша думка була про не-мікрософтівську OEM-версію (таке вже траплялося), але прожила та думка недовго. Виявилося, що файл хитро "закодований". Спочатку він розкодовується, точніше --- перекодовується, і ми бачимо, що COM-файл, насправді, є таким собі псевдо-EXE, із вбудованим завантажувачем. Образ цього EXE в пам'яті вже є менш-більш звичним SYS. За одним важливим винятком. Друк більшості повідомлень реалізований через функцію, яка дуже нагадує printf, правда --- жорстоко урізаний. При чому, ця функція викликається дальнім (far) викликом, і, можливо саме заради неї над SYS.COM так познущалися.
Тобто, історія подій видається наступною:
- В коді SYS друк більшості повідомлень (крім повідомлення про невірну версію --- якщо його треба виводити, ми не можемо очікувати "просунутих" сервісів INT 21h), замінено на дальній виклик printf.
- Ймовірно, printf взявся із Microsoft/Lattice C, ймовірно дуже ранніх версій, так як printf дуже урізаний (детальніше --- нижче).
- Код SYS лінкується із printf, даючи щось типу SYS.EXE --- повноцінний MZ-EXE.
- Якимось конвертером він перетворюється в псевдо-COM, який "вручну" робить 6 релокацій (по кількості викликів printf), переміщає завантажений "буквально" --- як .COM, файл, створюючи в пам'яті готовий до виконання образ EXE-файла, близький до вихідного, та передає йому керування.
- Що найцікавіше, всі ці збочення --- заради шести викликів printf, із яких лише один (!) використовує можливість printf, а саме --- можливість вивести одну літеру --- літеру диску, один char (!!!), у вказаному місці стрічки.
Через цю всю (якщо я не впустив чогось важливого --- абсолютно зайву, хіба що так експериментували на не дуже критичній утиліті) магію, "розкопки" затягнулися надовго. Тому опишу їх в декількох постах. Почнемо із аналізу "псевдозавантажувача", та про те, як виколупати вихідний файл. Іншим постом розкажу про цікаву, але побічну, тему реалізації printf, і останнім --- що ж змінилося в SYS.COM із приходом PC-DOS 3.00.
Отож, поїхали.
Так як рекомпілювабельний ASM-файл робити особливого сенсу немає, то наводжу лістинг -- в ньому легше орієнтуватися. Зрозуміло, що синтаксис при цьому буде менш послідовним -- fasm допомагав коректно порозставляти всілякі там дужки і конкретизації розміру операндів. Але сприйняттю це заважати не повинно.
На початку псевдо-COM -- перехід майже в сам кінець.
Після переходу -- область із службовими даними. Кидається в очі текст "'Converted',0,0,0,0,'MZ'". Після нього всілякі хитрі поля. Частину розглянемо в міру їх використання "декодером", а про всіх них загалом -- нижче. В лістингу саме тіло програми залишив у вигляді масиву -- його дизасемблюватимемо потім.
seg000:0100 ; This file is generated by The Interactive Disassembler (IDA) seg000:0100 ; Copyright (c) 2010 by Hex-Rays SA, <support@hex-rays.com> seg000:0100 ; Licensed to: Freeware version seg000:0100 ; seg000:0100 ; Input MD5 : DAFCFFB7F8CE8DA1332E59AB39ED107A seg000:0100 seg000:0100 ; Сommented by Indrekis, indrekis2.blogspot.com seg000:0100 seg000:0100 ; File Name : PC-DOS_3.00\SYS.COM seg000:0100 ; Format : MS-DOS COM-file seg000:0100 ; Base Address: 0h Range: 100h-F2Dh Loaded length: E2Dh seg000:0100 seg000:0100 ; .8086 seg000:0100 seg000:0100 start: seg000:0100 jmp EntryPoint1 seg000:0100 ; --------------------------------------------------------------------------- seg000:0103 aConvertedmz db 'Converted',0,0,0,0 seg000:0110 ; ========================================== seg000:0110 ; EXE file header! seg000:0110 ; seg000:0110 ; Info about EXE format taken from seg000:0110 ; http://www.delorie.com/djgpp/doc/exe/ seg000:0110 ; and seg000:0110 ; http://wiki.osdev.org/MZ seg000:0110 aMz db 'MZ' seg000:0112 dw 1A2h ; Number of bytes in the last block seg000:0112 ; 0 --entire block is used. Block size -- 512b seg000:0114 dw 7 ; Number of whole and partial blocks. seg000:0116 RelocationsNumber seg000:0116 dw 6 ; Number of entries in the relocation table. seg000:0118 HeaderSize_Pars: ; seg000:0118 ; seg000:0118 dw 20h ; The number of paragraphs taken up by the header. seg000:0118 ; The program's data begins just after the header, seg000:0118 ; and this field can be used to calculate the appropriate seg000:0118 ; file offset. The header includes the relocation entries. seg000:011A dw 0 ; Number of paragraphs of additional memory that seg000:011A ; the program will need. ("BSS") seg000:011C dw 0FFFFh ; Maximum number of paragraphs of additional memory. seg000:011E StackSeg_displ: ; seg000:011E dw 7Bh ; Relative value of the stack segment. This value seg000:011E ; is added to the segment the program was loaded at, seg000:011E ; and the result is used to initialize the SS register. seg000:0120 StackTop: ; seg000:0120 dw 80h ; Initial value of the SP register. seg000:0122 dw 309Bh ; EXE file Word checksum. seg000:0124 StartingIP: ; seg000:0124 dw 0 seg000:0126 CodeSeg_displ: ; seg000:0126 dw 27h ; Initial value of the CS register, relative to seg000:0126 ; the segment the program was loaded at. seg000:0128 RelocTblBeginAddr: ; seg000:0128 dw 1Eh ; The offset to the relocation table. seg000:012A dw 0 ; Overlay number. Normally zero, seg000:012A ; meaning that it's the main program. seg000:012C dw 1 ; Field for overlay information seg000:012E CurRelocTbl dw 67h ; Displ -- reloc 0 seg000:0130 dw 27h ; DS seg000:0132 dw 7Dh ; Displ -- reloc 1 seg000:0134 dw 27h ; DS seg000:0136 dw 276h ; Displ -- reloc 2 seg000:0138 dw 27h ; DS seg000:013A dw 280h ; Displ -- reloc 3 seg000:013C dw 27h ; DS seg000:013E dw 289h ; Displ -- reloc 4 seg000:0140 dw 27h ; DS seg000:0142 dw 403h ; Displ -- reloc 5 seg000:0144 dw 27h ; DS seg000:0146 ; ===================================================================================================================== seg000:0146 db 1CAh dup(0), 1, 0Ah dup(0), 20h, 30h, 31h, 32h, 33h, 34h, 35h, 36h, 37h, 38h, 39h, 41h, 42h; 0 seg000:0146 db 43h, 44h, 45h, 46h, 61h, 62h, 63h, 64h, 65h, 66h, 19h dup(0), 15h, 0, 55h, 52h, 51h; 482 seg000:0146 db 53h, 50h, 57h, 56h, 6, 1Eh, 8Bh, 0ECh, 0Eh, 7, 0BFh, 26h, 0, 8Bh, 6Eh, 16h; 522 seg000:0146 db 3Eh, 8Bh, 76h, 0, 33h, 0DBh, 0E8h, 0FAh, 1, 0ACh, 3Ch, 25h, 74h, 30h, 0Ah, 0C0h; 538 seg000:0146 db 74h, 5, 0E8h, 0BDh, 1, 0EBh, 0F2h, 0E8h, 0D9h, 1, 1Fh, 7, 5Eh, 5Fh, 58h, 5Bh; 554 seg000:0146 db 59h, 5Ah, 5Dh, 2Eh, 8Fh, 6, 22h, 0, 2Eh, 8Fh, 6, 24h, 0, 58h, 2Eh, 0FFh; 570 seg000:0146 db 36h, 24h, 0, 2Eh, 0FFh, 36h, 22h, 0, 0CBh, 0E8h, 96h, 1, 0EBh, 0CBh, 0ACh, 3Ch; 586 seg000:0146 db 25h, 74h, 0F6h, 3Ch, 2Dh, 74h, 3Fh, 3Ch, 2Bh, 74h, 47h, 3Ch, 4Ch, 74h, 3Eh, 3Ch; 602 seg000:0146 db 6Ch, 74h, 3Ah, 3Ch, 30h, 72h, 3Dh, 3Ch, 39h, 77h, 39h, 3Ch, 30h, 75h, 0Eh, 2Eh; 618 seg000:0146 db 83h, 3Eh, 7, 2 dup(0), 75h, 6, 2Eh, 0C6h, 6, 0Bh, 0, 30h, 50h, 0B8h, 0Ah, 0; 634 seg000:0146 db 2Eh, 0F7h, 26h, 7, 0, 2Eh, 0A3h, 7, 0, 58h, 32h, 0E4h, 2Ch, 30h, 2Eh, 1; 651 seg000:0146 db 6, 7, 0, 0EBh, 0Ch, 2Eh, 0FEh, 6, 2, 0, 0EBh, 5, 2Eh, 0FEh, 6, 3; 667 seg000:0146 db 0, 0EBh, 0AAh, 3Ch, 58h, 74h, 26h, 3Ch, 61h, 72h, 6, 3Ch, 7Ah, 7Fh, 2, 24h; 683 seg000:0146 db 0DFh, 3Ch, 58h, 74h, 12h, 3Ch, 44h, 74h, 1Eh, 3Ch, 43h, 74h, 29h, 3Ch, 53h, 74h; 699 seg000:0146 db 20h, 0E8h, 4Eh, 1, 0E9h, 51h, 0FFh, 2Eh, 0C6h, 6, 5, 0, 6, 2Eh, 0C7h, 6; 715 seg000:0146 db 9, 0, 10h, 0, 0EBh, 7Bh, 90h, 2Eh, 0C7h, 6, 9, 0, 0Ah, 0, 0EBh, 71h; 731 seg000:0146 db 90h, 2Eh, 0FEh, 2 dup(6), 0, 56h, 8Bh, 0F3h, 83h, 0C3h, 2, 3Eh, 8Bh, 72h, 2, 2Eh; 747 seg000:0146 db 80h, 3Eh, 6, 2 dup(0), 75h, 0Ah, 0ACh, 3Ch, 0, 74h, 3Bh, 0E8h, 0E1h, 0, 0EBh, 36h; 764 seg000:0146 db 2Eh, 8Bh, 0Eh, 7, 0, 0Bh, 0C9h, 74h, 0Dh, 2Eh, 80h, 3Eh, 2, 2 dup(0), 75h, 5; 781 seg000:0146 db 56h, 0E8h, 28h, 0, 5Eh, 56h, 0ACh, 3Ch, 0, 74h, 5, 0E8h, 0C0h, 0, 0EBh, 0F6h; 798 seg000:0146 db 5Eh, 2Eh, 80h, 3Eh, 2, 2 dup(0), 74h, 0Ch, 2Eh, 8Bh, 0Eh, 7, 0, 0Bh, 0C9h, 74h; 814 seg000:0146 db 3, 0E8h, 7, 0, 0E8h, 0D7h, 0, 5Eh, 0E9h, 0D9h, 0FEh, 33h, 0D2h, 0ACh, 0Ah, 0C0h; 831 seg000:0146 db 74h, 3, 42h, 0EBh, 0F8h, 2Bh, 0CAh, 76h, 3, 0E8h, 81h, 0, 0C3h, 56h, 8Bh, 0F3h; 847 seg000:0146 db 83h, 0C3h, 2, 3Eh, 8Bh, 42h, 2, 2Eh, 80h, 3Eh, 3, 2 dup(0), 74h, 0Bh, 8Bh, 0F3h; 863 seg000:0146 db 83h, 0C3h, 2, 3Eh, 8Bh, 52h, 2, 0EBh, 2, 33h, 0D2h, 53h, 2Eh, 8Bh, 36h, 9; 880 seg000:0146 db 0, 2Eh, 8Bh, 0Eh, 7, 0, 0E8h, 0Bh, 0, 0E8h, 50h, 0, 0E8h, 8Eh, 0, 5Bh; 896 seg000:0146 db 5Eh, 0E9h, 8Fh, 0FEh, 49h, 50h, 8Bh, 0C2h, 33h, 0D2h, 0F7h, 0F6h, 8Bh, 0D8h, 58h, 0F7h; 912 seg000:0146 db 0F6h, 87h, 0DAh, 50h, 0Bh, 0C2h, 58h, 74h, 7, 53h, 0E8h, 0E7h, 0FFh, 5Bh, 0EBh, 0Bh; 928 seg000:0146 db 2Eh, 80h, 3Eh, 2, 2 dup(0), 75h, 3, 0E8h, 21h, 0, 8Bh, 0C3h, 3Ch, 0Ah, 72h, 0Dh; 944 seg000:0146 db 2Eh, 80h, 3Eh, 4, 2 dup(0), 75h, 5, 2Eh, 2, 6, 5, 0, 0BBh, 0Ch, 0, 1Eh; 961 seg000:0146 db 0Eh, 1Fh, 0D7h, 1Fh, 51h, 0E8h, 12h, 0, 59h, 0C3h, 0Bh, 0C9h, 7Eh, 0Bh, 2Eh, 0A0h; 978 seg000:0146 db 0Bh, 0, 51h, 0E8h, 4, 0, 59h, 0E2h, 0F9h, 0C3h, 0AAh, 81h, 0FFh, 3Ah, 0, 74h; 994 seg000:0146 db 1, 0C3h, 0B9h, 14h, 0, 53h, 2Eh, 8Bh, 1Eh, 2 dup(0), 1Eh, 0Eh, 1Fh, 0BAh, 26h, 0; 1010 seg000:0146 db 0B4h, 40h, 0CDh, 21h, 1Fh, 5Bh, 0BFh, 26h, 0, 0C3h, 81h, 0FFh, 26h, 0, 74h, 0E0h; 1027 seg000:0146 db 81h, 0EFh, 26h, 0, 8Bh, 0CFh, 0E8h, 0DBh, 0FFh, 0C3h, 33h, 0C0h, 2Eh, 0A2h, 2, 0; 1043 seg000:0146 db 2Eh, 0A2h, 3, 0, 2Eh, 0A2h, 5, 0, 2Eh, 0A3h, 7, 0, 2Eh, 0C6h, 6, 0Bh; 1059 seg000:0146 db 0, 20h, 2Eh, 0A2h, 6, 0, 0C3h, 0EBh, 0Ah, 0C8h, 6, 53h, 59h, 53h, 20h, 31h; 1075 seg000:0146 db 2Eh, 38h, 36h, 50h, 0B4h, 30h, 0CDh, 21h, 86h, 0E0h, 3Dh, 0, 3, 72h, 1Ah, 58h; 1091 seg000:0146 db 0Eh, 7, 0BEh, 5Ch, 0, 0BFh, 8, 6, 0B9h, 20h, 0, 0F3h, 0A4h, 0Eh, 1Fh, 0BAh; 1107 seg000:0146 db 3Eh, 6, 0B4h, 1Ah, 0CDh, 21h, 0EBh, 53h, 90h, 0Eh, 1Fh, 0BAh, 26h, 4, 0B4h, 9; 1123 seg000:0146 db 0CDh, 21h, 6, 33h, 0C0h, 50h, 0CBh, 0BAh, 6Eh, 4, 0E9h, 36h, 2, 0BAh, 5Ah, 4; 1139 seg000:0146 db 0E9h, 30h, 2, 0B4h, 19h, 0CDh, 21h, 8Ah, 0D8h, 0FEh, 0C3h, 0B8h, 8, 44h, 0CDh, 21h; 1155 seg000:0146 db 72h, 13h, 3Dh, 2 dup(0), 74h, 0Eh, 0BAh, 0E8h, 4, 52h, 9Ah, 3Dh, 3 dup(0), 0B8h, 1, 4Ch; 1171 seg000:0146 db 0CDh, 21h, 0A0h, 0C0h, 5, 4, 40h, 0A2h, 2Ch, 5, 0BAh, 28h, 5, 52h, 9Ah, 3Dh; 1190 seg000:0146 db 3 dup(0), 0E8h, 70h, 3, 32h, 0C0h, 80h, 3Eh, 9, 6, 20h, 75h, 0B5h, 3Ch, 0FFh, 74h; 1206 seg000:0146 db 0B7h, 80h, 3Eh, 8, 6, 0, 74h, 0B0h, 0B4h, 19h, 0CDh, 21h, 0FEh, 0C0h, 0A2h, 0C0h; 1224 seg000:0146 db 5, 38h, 6, 8, 6, 74h, 0A1h, 50h, 8Ah, 1Eh, 8, 6, 0B8h, 9, 44h, 0CDh; 1240 seg000:0146 db 21h, 72h, 0Ch, 0F7h, 0C2h, 0, 10h, 74h, 6, 0BAh, 24h, 4, 0E9h, 0BFh, 1, 58h; 1256 seg000:0146 db 50h, 0A0h, 8, 6, 0FEh, 0C8h, 0BBh, 32h, 9, 0BAh, 1, 0, 8Bh, 0CAh, 0CDh, 25h; 1272 seg000:0146 db 2 dup(58h), 72h, 0Ah, 80h, 3Eh, 32h, 9, 0F8h, 73h, 6, 0E9h, 4Dh, 2, 0E9h, 8Ah, 0; 1288 seg000:0146 db 50h, 0A0h, 8, 6, 4, 40h, 0A2h, 0C1h, 5, 0A2h, 0CFh, 5, 0B4h, 4Eh, 0BAh, 0C1h; 1305 seg000:0146 db 5, 0B9h, 6, 0, 0CDh, 21h, 72h, 4, 0FEh, 6, 0DEh, 5, 0B4h, 4Eh, 0BAh, 0CFh; 1321 seg000:0146 db 5, 0CDh, 21h, 72h, 4, 0FEh, 6, 0DDh, 5, 8Ah, 16h, 8, 6, 0B4h, 32h, 1Eh; 1337 seg000:0146 db 0CDh, 21h, 8Bh, 57h, 10h, 1Fh, 0A0h, 8, 6, 0FEh, 0C8h, 0BBh, 32h, 9, 0B9h, 1; 1353 seg000:0146 db 0, 0CDh, 25h, 58h, 73h, 3, 0EBh, 41h, 90h, 0BEh, 32h, 9, 80h, 3Ch, 0, 74h; 1369 seg000:0146 db 2Fh, 0FCh, 80h, 3Ch, 0E5h, 74h, 0Eh, 0BFh, 33h, 6, 0B9h, 0Bh, 0, 0F3h, 0A6h, 75h; 1385 seg000:0146 db 19h, 0FEh, 0Eh, 0E0h, 5, 0BEh, 52h, 9, 80h, 3Ch, 0, 74h, 13h, 80h, 3Ch, 0E5h; 1401 seg000:0146 db 74h, 0Eh, 0BFh, 28h, 6, 0B9h, 0Bh, 0, 0F3h, 0A6h, 75h, 74h, 0FEh, 0Eh, 0DFh, 5; 1417 seg000:0146 db 0A1h, 0DDh, 5, 23h, 6, 0DFh, 5, 75h, 67h, 58h, 4, 40h, 0A2h, 0C1h, 5, 0A2h; 1433 seg000:0146 db 0CFh, 5, 0FCh, 0BAh, 0C1h, 5, 0BFh, 0E1h, 5, 0E8h, 82h, 1, 73h, 3, 0E9h, 0CCh; 1449 seg000:0146 db 0FEh, 0BAh, 0CFh, 5, 0BFh, 0F1h, 5, 0E8h, 74h, 1, 72h, 0F2h, 8Bh, 0CCh, 81h, 0E9h; 1465 seg000:0146 db 32h, 0Bh, 89h, 0Eh, 0BEh, 6, 0E8h, 0FCh, 0, 72h, 0E3h, 0A0h, 8, 6, 4, 40h; 1481 seg000:0146 db 0A2h, 0C1h, 5, 0A2h, 0CFh, 5, 0A2h, 1, 6, 0B4h, 4Eh, 0BAh, 1, 6, 0B9h, 16h; 1497 seg000:0146 db 0, 0CDh, 21h, 73h, 0Fh, 0B4h, 4Eh, 0BAh, 1, 6, 0B9h, 8, 0, 0CDh, 21h, 72h; 1513 seg000:0146 db 1Bh, 0E9h, 66h, 1, 0BAh, 0C1h, 5, 0B9h, 7, 0, 0B4h, 4Eh, 0CDh, 21h, 73h, 3; 1529 seg000:0146 db 0E9h, 57h, 1, 0BAh, 0CFh, 5, 0B4h, 4Eh, 0CDh, 21h, 72h, 0F4h, 0BAh, 0C1h, 5, 0B9h; 1545 seg000:0146 db 2 dup(0), 0B8h, 1, 43h, 0CDh, 21h, 0BAh, 0CFh, 5, 0B9h, 2 dup(0), 0B8h, 1, 43h, 0CDh, 21h; 1561 seg000:0146 db 0BAh, 0C1h, 5, 0B9h, 7, 0, 0B4h, 3Ch, 0CDh, 21h, 72h, 3Ch, 0A3h, 0EFh, 5, 0BAh; 1579 seg000:0146 db 0CFh, 5, 0B4h, 3Ch, 0CDh, 21h, 72h, 30h, 0A3h, 0FFh, 5, 1Eh, 0B4h, 32h, 8Ah, 16h; 1595 seg000:0146 db 8, 6, 0CDh, 21h, 0C7h, 47h, 1Ch, 2 dup(0), 1Fh, 0E8h, 11h, 1, 72h, 19h, 0A1h, 0F7h; 1611 seg000:0146 db 5, 0Bh, 6, 0F3h, 5, 0Bh, 6, 0E7h, 5, 0Bh, 6, 0E3h, 5, 74h, 11h, 0E8h; 1628 seg000:0146 db 60h, 0, 73h, 0E5h, 0E9h, 13h, 0FEh, 0E9h, 0EDh, 0, 0BAh, 0B2h, 4, 0EBh, 3Bh, 90h; 1644 seg000:0146 db 8Bh, 0Eh, 0EBh, 5, 8Bh, 16h, 0EDh, 5, 8Bh, 1Eh, 0EFh, 5, 0B8h, 1, 57h, 0CDh; 1660 seg000:0146 db 21h, 0B4h, 3Eh, 0CDh, 21h, 8Bh, 0Eh, 0FBh, 5, 8Bh, 16h, 0FDh, 5, 8Bh, 1Eh, 0FFh; 1676 seg000:0146 db 5, 0B8h, 1, 57h, 0CDh, 21h, 0B4h, 3Eh, 0CDh, 21h, 0E8h, 0F5h, 0, 0BAh, 0C9h, 4; 1692 seg000:0146 db 52h, 9Ah, 3Dh, 3 dup(0), 32h, 0C0h, 0EBh, 11h, 52h, 9Ah, 3Dh, 3 dup(0), 0BAh, 31h, 5, 52h; 1708 seg000:0146 db 9Ah, 3Dh, 3 dup(0), 0B0h, 0FFh, 0B4h, 4Ch, 0CDh, 21h, 59h, 0F9h, 0C3h, 8Bh, 0Eh, 0BEh, 6; 1728 seg000:0146 db 8Bh, 1Eh, 0E1h, 5, 0BAh, 32h, 9, 51h, 83h, 3Eh, 0E7h, 5, 0, 77h, 0Ah, 39h; 1746 seg000:0146 db 0Eh, 0E3h, 5, 77h, 4, 8Bh, 0Eh, 0E3h, 5, 0B4h, 3Fh, 0CDh, 21h, 72h, 0DAh, 3Bh; 1762 seg000:0146 db 0C1h, 75h, 0D6h, 3, 0D0h, 89h, 16h, 0C0h, 6, 29h, 6, 0E3h, 5, 83h, 1Eh, 0E7h; 1778 seg000:0146 db 5, 0, 59h, 2Bh, 0C8h, 8Bh, 1Eh, 0F1h, 5, 83h, 3Eh, 0F7h, 5, 0, 77h, 0Ah; 1794 seg000:0146 db 39h, 0Eh, 0F3h, 5, 77h, 4, 8Bh, 0Eh, 0F3h, 5, 0B4h, 3Fh, 0CDh, 21h, 72h, 0ABh; 1810 seg000:0146 db 3Bh, 0C1h, 75h, 0A6h, 3, 0D0h, 89h, 16h, 0C2h, 6, 29h, 6, 0F3h, 5, 83h, 1Eh; 1826 seg000:0146 db 0F7h, 5, 0, 0F8h, 0C3h, 0B8h, 0, 3Dh, 0CDh, 21h, 72h, 0F8h, 0ABh, 8Bh, 0D8h, 0B8h; 1842 seg000:0146 db 2, 42h, 33h, 0C9h, 33h, 0D2h, 0CDh, 21h, 2 dup(0ABh), 8Bh, 0C2h, 2 dup(0ABh), 33h, 0D2h, 0B8h, 0; 1858 seg000:0146 db 42h, 0CDh, 21h, 0B8h, 0, 57h, 0CDh, 21h, 8Bh, 0C1h, 0ABh, 8Bh, 0C2h, 0ABh, 0C3h, 0BAh; 1876 seg000:0146 db 97h, 4, 0E9h, 4Dh, 0FFh, 0BAh, 32h, 9, 8Bh, 0Eh, 0C0h, 6, 2Bh, 0CAh, 74h, 0Eh; 1892 seg000:0146 db 8Bh, 1Eh, 0EFh, 5, 0B4h, 40h, 0CDh, 21h, 72h, 0E4h, 3Bh, 0C1h, 75h, 1Ah, 8Bh, 16h; 1908 seg000:0146 db 0C0h, 6, 8Bh, 0Eh, 0C2h, 6, 2Bh, 0CAh, 74h, 0D4h, 8Bh, 1Eh, 0FFh, 5, 0B4h, 40h; 1924 seg000:0146 db 0CDh, 21h, 72h, 0CAh, 3Bh, 0C1h, 74h, 0C6h, 0F9h, 0C3h, 0B4h, 32h, 8Ah, 16h, 8, 6; 1940 seg000:0146 db 0CDh, 21h, 8Ah, 47h, 16h, 0Eh, 1Fh, 2Ch, 0F8h, 98h, 8Bh, 0D8h, 0D1h, 0E3h, 8Bh, 0B7h; 1956 seg000:0146 db 0C8h, 8, 0Bh, 0F6h, 75h, 51h, 0C6h, 6, 0DDh, 6, 0F8h, 33h, 0DBh, 89h, 1Eh, 0C4h; 1972 seg000:0146 db 6, 1Eh, 0C5h, 1Eh, 0C4h, 6, 8Bh, 1Fh, 8Ah, 7, 43h, 1Fh, 89h, 1Eh, 0C4h, 6; 1988 seg000:0146 db 0A2h, 0E6h, 6, 0CDh, 11h, 0D0h, 0C0h, 0D0h, 0C0h, 24h, 3, 75h, 2, 0FEh, 0C0h, 0FEh; 2004 seg000:0146 db 0C0h, 8Ah, 16h, 8, 6, 2Ah, 0D0h, 0FEh, 0CAh, 74h, 9, 83h, 6, 0C4h, 6, 13h; 2020 seg000:0146 db 0FEh, 6, 0E6h, 6, 0C5h, 36h, 0C4h, 6, 0Eh, 7, 0BFh, 0D3h, 6, 0B9h, 13h, 0; 2036 seg000:0146 db 0FCh, 0F3h, 0A4h, 0Eh, 1Fh, 0EBh, 10h, 83h, 0FEh, 0FFh, 74h, 1Bh, 1Eh, 7, 0BFh, 0D5h; 2052 seg000:0146 db 6, 0B9h, 12h, 0, 0FCh, 0F3h, 0A4h, 0A0h, 8, 6, 0FEh, 0C8h, 0BBh, 0C8h, 6, 33h; 2068 seg000:0146 db 0D2h, 8Bh, 0CAh, 41h, 0CDh, 26h, 58h, 0C3h, 0B8h, 8, 0Ch, 0CDh, 21h, 0B8h, 0, 0Ch; 2084 seg000:0146 db 0CDh, 21h, 0BAh, 31h, 5, 52h, 9Ah, 3Dh, 3 dup(0), 0C3h, 43h, 61h, 2 dup(6Eh), 6Fh, 74h, 20h; 2100 seg000:0146 db 53h, 59h, 53h, 20h, 74h, 6Fh, 20h, 61h, 20h, 4Eh, 65h, 74h, 77h, 6Fh, 72h, 6Bh; 2119 seg000:0146 db 20h, 64h, 72h, 69h, 76h, 65h, 0, 6, 4, 49h, 6Eh, 63h, 6Fh, 2 dup(72h), 65h, 63h; 2135 seg000:0146 db 74h, 20h, 44h, 4Fh, 53h, 20h, 76h, 65h, 72h, 73h, 69h, 6Fh, 6Eh, 0Dh, 0Ah, 24h; 2152 seg000:0146 db 49h, 6Eh, 76h, 61h, 6Ch, 69h, 64h, 20h, 64h, 72h, 69h, 76h, 65h, 20h, 73h, 70h; 2168 seg000:0146 db 65h, 63h, 69h, 66h, 69h, 63h, 61h, 74h, 69h, 6Fh, 6Eh, 0, 3Eh, 4, 49h, 6Eh; 2184 seg000:0146 db 76h, 61h, 6Ch, 69h, 64h, 20h, 70h, 61h, 72h, 61h, 6Dh, 65h, 74h, 65h, 72h, 0; 2200 seg000:0146 db 5Ch, 4, 4Eh, 6Fh, 20h, 72h, 2 dup(6Fh), 6Dh, 20h, 66h, 6Fh, 72h, 20h, 73h, 79h, 73h; 2216 seg000:0146 db 74h, 65h, 6Dh, 20h, 6Fh, 6Eh, 20h, 64h, 65h, 73h, 74h, 69h, 6Eh, 61h, 74h, 69h; 2233 seg000:0146 db 6Fh, 6Eh, 20h, 64h, 69h, 73h, 6Bh, 0, 70h, 4, 49h, 6Eh, 63h, 6Fh, 6Dh, 70h; 2249 seg000:0146 db 61h, 74h, 69h, 62h, 6Ch, 65h, 20h, 73h, 79h, 73h, 74h, 65h, 6Dh, 20h, 73h, 69h; 2265 seg000:0146 db 7Ah, 65h, 0, 99h, 4, 53h, 79h, 73h, 74h, 65h, 6Dh, 20h, 74h, 72h, 61h, 6Eh; 2281 seg000:0146 db 73h, 66h, 65h, 2 dup(72h), 65h, 64h, 0Dh, 0Ah, 0, 0B4h, 4, 4Eh, 6Fh, 20h, 73h, 79h; 2297 seg000:0146 db 73h, 74h, 65h, 6Dh, 20h, 6Fh, 6Eh, 20h, 64h, 65h, 66h, 61h, 75h, 6Ch, 74h, 20h; 2314 seg000:0146 db 64h, 72h, 69h, 76h, 65h, 0Dh, 0Ah, 0, 0CBh, 4, 49h, 6Eh, 73h, 65h, 72h, 74h; 2330 seg000:0146 db 20h, 73h, 79h, 73h, 74h, 65h, 6Dh, 20h, 64h, 69h, 73h, 6Bh, 20h, 69h, 6Eh, 20h; 2346 seg000:0146 db 64h, 72h, 69h, 76h, 65h, 20h, 25h, 63h, 0Dh, 0Ah, 61h, 6Eh, 64h, 20h, 73h, 74h; 2362 seg000:0146 db 72h, 69h, 6Bh, 65h, 20h, 61h, 6Eh, 79h, 20h, 6Bh, 65h, 79h, 20h, 77h, 68h, 65h; 2378 seg000:0146 db 6Eh, 20h, 72h, 65h, 61h, 64h, 79h, 0, 0EAh, 4, 2Ch, 5, 41h, 0, 0Dh, 0Ah; 2394 seg000:0146 db 0, 2Eh, 5, 8Eh dup(0), 41h, 3Ah, 5Ch, 49h, 42h, 4Dh, 42h, 49h, 4Fh, 2Eh, 43h, 4Fh; 2410 seg000:0146 db 4Dh, 0, 41h, 3Ah, 5Ch, 49h, 42h, 4Dh, 44h, 4Fh, 53h, 2Eh, 43h, 4Fh, 4Dh, 3 dup(0); 2567 seg000:0146 db 2 dup(1), 20h dup(0), 41h, 3Ah, 5Ch, 2Ah, 2Eh, 2Ah, 21h dup(0), 49h, 42h, 4Dh, 44h, 4Fh, 53h, 2 dup(20h); 2585 seg000:0146 db 43h, 4Fh, 4Dh, 49h, 42h, 4Dh, 42h, 49h, 4Fh, 2 dup(20h), 43h, 4Fh, 4Dh, 88h dup(0), 70h, 0; 2666 seg000:0146 db 0EBh, 29h, 90h, 49h, 42h, 4Dh, 2 dup(20h), 33h, 2Eh, 30h, 0, 2, 8, 1, 0, 2; 2818 seg000:0146 db 0, 2, 3, 51h, 0F8h, 8, 0, 11h, 0, 4, 0, 1, 0, 80h, 5 dup(0), 0Fh; 2835 seg000:0146 db 4 dup(0), 1, 0, 0FAh, 33h, 0C0h, 8Eh, 0D0h, 0BCh, 0, 7Ch, 16h, 7, 0BBh, 78h, 0; 2855 seg000:0146 db 36h, 0C5h, 37h, 1Eh, 56h, 16h, 53h, 0BFh, 20h, 7Ch, 0B9h, 0Bh, 0, 0FCh, 0ACh, 26h; 2874 seg000:0146 db 80h, 3Dh, 0, 74h, 3, 26h, 8Ah, 5, 0AAh, 8Ah, 0C4h, 0E2h, 0F1h, 6, 1Fh, 89h; 2890 seg000:0146 db 47h, 2, 0C7h, 7, 20h, 7Ch, 0FBh, 0CDh, 13h, 72h, 67h, 0A0h, 10h, 7Ch, 98h, 0F7h; 2906 seg000:0146 db 26h, 16h, 7Ch, 3, 6, 1Ch, 7Ch, 3, 6, 0Eh, 7Ch, 0A3h, 34h, 7Ch, 0A3h, 2Ch; 2922 seg000:0146 db 7Ch, 0B8h, 20h, 0, 0F7h, 26h, 11h, 7Ch, 8Bh, 1Eh, 0Bh, 7Ch, 3, 0C3h, 48h, 0F7h; 2938 seg000:0146 db 0F3h, 1, 6, 2Ch, 7Ch, 0BBh, 0, 5, 0A1h, 34h, 7Ch, 0E8h, 96h, 0, 0B8h, 1; 2954 seg000:0146 db 2, 0E8h, 0AAh, 0, 72h, 19h, 8Bh, 0FBh, 0B9h, 0Bh, 0, 2 dup(0BEh), 7Dh, 0F3h, 0A6h, 75h; 2970 seg000:0146 db 0Dh, 8Dh, 7Fh, 20h, 0BEh, 0C9h, 7Dh, 0B9h, 0Bh, 0, 0F3h, 0A6h, 74h, 18h, 0BEh, 5Fh; 2987 seg000:0146 db 7Dh, 0E8h, 61h, 0, 32h, 0E4h, 0CDh, 16h, 5Eh, 1Fh, 8Fh, 4, 8Fh, 44h, 2, 0CDh; 3003 seg000:0146 db 19h, 0BEh, 0A8h, 7Dh, 2 dup(0EBh), 0A1h, 1Ch, 5, 33h, 0D2h, 0F7h, 36h, 0Bh, 7Ch, 0FEh, 0C0h; 3019 seg000:0146 db 0A2h, 31h, 7Ch, 0A1h, 2Ch, 7Ch, 0A3h, 32h, 7Ch, 0BBh, 0, 7, 0A1h, 2Ch, 7Ch, 0E8h; 3036 seg000:0146 db 40h, 0, 0A1h, 18h, 7Ch, 2Ah, 6, 30h, 7Ch, 40h, 50h, 0E8h, 4Eh, 0, 58h, 72h; 3052 seg000:0146 db 0CFh, 28h, 6, 31h, 7Ch, 76h, 0Ch, 1, 6, 2Ch, 7Ch, 0F7h, 26h, 0Bh, 7Ch, 3; 3068 seg000:0146 db 0D8h, 0EBh, 0D9h, 8Ah, 2Eh, 15h, 7Ch, 8Ah, 16h, 1Eh, 7Ch, 8Bh, 1Eh, 32h, 7Ch, 0EAh; 3084 seg000:0146 db 2 dup(0), 70h, 0, 0ACh, 0Ah, 0C0h, 74h, 22h, 0B4h, 0Eh, 0BBh, 7, 0, 0CDh, 10h, 0EBh; 3100 seg000:0146 db 0F2h, 33h, 0D2h, 0F7h, 36h, 18h, 7Ch, 0FEh, 0C2h, 88h, 16h, 30h, 7Ch, 33h, 0D2h, 0F7h; 3117 seg000:0146 db 36h, 1Ah, 7Ch, 88h, 16h, 1Fh, 7Ch, 0A3h, 2Eh, 7Ch, 0C3h, 0B4h, 2, 8Bh, 16h, 2Eh; 3133 seg000:0146 db 7Ch, 0B1h, 6, 0D2h, 0E6h, 0Ah, 36h, 30h, 7Ch, 8Bh, 0CAh, 86h, 0E9h, 8Bh, 16h, 1Eh; 3149 seg000:0146 db 7Ch, 0CDh, 13h, 0C3h, 0Dh, 0Ah, 4Eh, 6Fh, 6Eh, 2Dh, 53h, 79h, 73h, 74h, 65h, 6Dh; 3165 seg000:0146 db 20h, 64h, 69h, 73h, 6Bh, 20h, 6Fh, 72h, 20h, 64h, 69h, 73h, 6Bh, 20h, 65h, 2 dup(72h); 3181 seg000:0146 db 6Fh, 72h, 0Dh, 0Ah, 52h, 65h, 70h, 6Ch, 61h, 63h, 65h, 20h, 61h, 6Eh, 64h, 20h; 3198 seg000:0146 db 73h, 74h, 72h, 69h, 6Bh, 65h, 20h, 61h, 6Eh, 79h, 20h, 6Bh, 65h, 79h, 20h, 77h; 3214 seg000:0146 db 68h, 65h, 6Eh, 20h, 72h, 65h, 61h, 64h, 79h, 0Dh, 0Ah, 0, 0Dh, 0Ah, 44h, 69h; 3230 seg000:0146 db 73h, 6Bh, 20h, 42h, 2 dup(6Fh), 74h, 20h, 66h, 61h, 69h, 6Ch, 75h, 72h, 65h, 0Dh, 0Ah; 3246 seg000:0146 db 0, 49h, 42h, 4Dh, 42h, 49h, 4Fh, 2 dup(20h), 43h, 4Fh, 4Dh, 49h, 42h, 4Dh, 44h, 4Fh; 3263 seg000:0146 db 53h, 2 dup(20h), 43h, 4Fh, 4Dh, 2Ah dup(0), 55h, 0AAh, 2 dup(0), 20h, 9, 4 dup(0FFh), 0FCh, 8, 0Eh, 9; 3280 seg000:0146 db 0D8h, 8, 0EAh, 8, 2 dup(1), 0, 2, 40h, 0, 40h, 1, 0FEh, 1, 0, 8, 0; 3342 seg000:0146 db 1, 4 dup(0), 2, 1, 0, 2, 70h, 0, 80h, 2, 0FFh, 1, 0, 8, 0, 2; 3359 seg000:0146 db 4 dup(0), 2 dup(1), 0, 2, 40h, 0, 68h, 1, 0FCh, 2, 0, 9, 0, 1, 4 dup(0), 2; 3378 seg000:0146 db 1, 0, 2, 70h, 0, 0D0h, 2, 0FDh, 2, 0, 9, 0, 2, 4 dup(0), 2 dup(1), 0; 3401 seg000:0146 db 2, 0E0h, 0, 60h, 9, 0F9h, 7, 0, 0Fh, 0, 2, 4 dup(0); 3421 seg000:0EB2 ; ===================================================================================================================== seg000:0EB2 NewIP dw 0 seg000:0EB4 CodeSeg_addr dw 0 seg000:0EB6 StackTop_addr dw 0 seg000:0EB8 StackSeg_addr dw 0 seg000:0EBA ; --------------------------------------------------------------------------- seg000:0EBA seg000:0EBA EntryPoint1: seg000:0EBA call $+3 seg000:0EBD pop bx ; BX contains EBD --- adress of "pop bx" command beginning seg000:0EBE push ax ; Save AX (disks status) seg000:0EBF mov ax, es ; ES points to COM-file code segment seg000:0EC1 add ax, 10h ; ES+10h --- start of code, just after the PSP seg000:0EC4 mov cx, [StackSeg_displ] seg000:0EC8 add cx, ax seg000:0ECA mov [bx-5], cx ; BX=0EBDh, BX-5=0EB8h, StackSeg_addr seg000:0ECD mov cx, word ptr [CodeSeg_displ] seg000:0ED1 add cx, ax seg000:0ED3 mov [bx-9], cx ; CodeSeg_addr = 27h + PSP + 10h = PSP + 37h seg000:0ED6 mov cx, [StackTop] seg000:0EDA mov [bx-7], cx ; 0EB6, StackTop_addr seg000:0EDD mov cx, word ptr [StartingIP] seg000:0EE1 mov [bx-0Bh], cx ; NewIP = 0 seg000:0EE4 mov di, [RelocTblBeginAddr] seg000:0EE8 mov dx, [HeaderSize_Pars] ; Offset of program image in paragraphs seg000:0EEC mov cl, 4 ; And in bytes: seg000:0EEE shl dx, cl ; DX was 20h, multiply by 16=10h, now 200h seg000:0EF0 mov cx, word ptr [RelocationsNumber] seg000:0EF4 jcxz short NoReloc seg000:0EF6 seg000:0EF6 NextReloc: seg000:0EF6 lds si, es:[di+110h] ; DI starts from 1Eh seg000:0EF6 ; SI --- relocation address seg000:0EF6 ; DS --- new code segment! All equal to 27h seg000:0EFB add di, 4 seg000:0EFE mov bp, ds seg000:0F00 add bp, [es:HeaderSize_Pars] ; Some size in paragraphs seg000:0F05 add bp, 1 seg000:0F08 add bp, ax ; AX=ES+10h seg000:0F0A mov ds, bp ; Now DS contains new code seg seg000:0F0C add [si], ax ; Relocate. seg000:0F0E loop NextReloc seg000:0F10 seg000:0F10 NoReloc: seg000:0F10 push cs seg000:0F11 pop ds ; Restore DS seg000:0F12 mov di, 100h seg000:0F15 mov si, dx ; DX=200h seg000:0F17 add si, 110h ; SI=310h seg000:0F1B mov cx, bx ; BX=0EBDh seg000:0F1D sub cx, si ; CX=BAD :-) seg000:0F1F rep movsb ; Move 0xBAD bytes from 310h to 100h, UP seg000:0F21 pop ax ; Restore AX -- disks state seg000:0F22 cli seg000:0F23 mov ss, word ptr [bx-5] ; 0EB8h --- StackSeg_addr seg000:0F26 mov sp, [bx-7] ; StackTop_addr seg000:0F29 sti seg000:0F2A jmp dword ptr [bx-0Bh] ; CodeSeg_addr:NewIP = PSP + 37h:0 seg000:0F2A ; start endp
Код декодера починається із зміщення 0EBAh, (умовно -- мітка EntryPoint1). Першим його кроком є: викликати самого себе за допомогою "call $+3" і дістати збережений в стеку адрес повернення у BX. Це -- популярний трюк взнати зміщення коду відносно кодового сегмента, CS. Далі зберігається AX --- він містить інформацію про те, чи коректні диски вказано в першому та другому FCB із PSP (див. попередні публікації), ця інформація буде потрібна основному коду.
Далі, з ES береться початок сегменту COM-файла (він єдиний для даних та коду), до нього додається 10h -- пропускається 100h-байтовий PSP (пам'ятаємо, що в реальному режимі адреса це є сегментний регістр * 10h + зміщення) і отримується адреса початку тіла програми.
У змінну, умовно названу StackSeg_addr, кладеться сума адреси початку тіла і зміщення в ньому до сегмента стеку, яке зберігається у полі StackSeg_displ, що знаходиться після "Converted MZ". Адресація змінної відбувається відносно вмісту BX, тобто відносно початку коду декодера-завантажувача. Аналогічно, в CodeSeg_addr кладеться адреса початку кодового сегменту, яка розраховується як сума адреси початку образу та зміщення з CodeSeg_displ (PSP + 10h + 27h = PSP + 37h). У поле StackTop_addr кладеться StackTop --- вершина стеку, майбутній вміст SP на початку виконання декодованої програми. Початковий IP (Instruction Pointer :) береться з StartingIP (рівне 0) і зберігається в NewIP. Зауважте, всі чотири поля, NewIP, CodeSeg_addr, StackTop_addr, StackSeg_addr, знаходяться зразу над декодером, після тіла програми.
Наступний крок цікавіший. В DI кладеться адреса таблиці релокацій, взята за адресою RelocTblBeginAddr (при чому, відраховується вона від сегмента PSP+110h), в CX -- їх кількість із RelocationsNumber (6 штук). Далі, для кожної релокації, в циклі, SI присвоюється адреса, в BP збирається поточний DS --- той же сегмент, що і PSP, до нього додається розмір заголовку EXE-файлу (див. нижче), одиниця та зміщення початку тіла програми відносно початку PSP. Ця сума зберігається в пам'ять за адресою в SI.
Що це за хитрі маневри такі? Насправді, все просто. Якщо згадати формат EXE-файла, він містить таблицю релокацій, формат кожного запису якої --- два байти зміщення, два байти сегмента. (За посиланням на OSDev там помилка, див. "EXE format" від DJ Delorie). Значення в сегменті додаватиметься до того, що вказане в коді, даючи можливість "зсунути" всі посилання --- програма не знає наперед, в якому сегменті опиниться, і без цього трюку неможливими були б дальні, міжсегментні, виклики. А так, для кожного такого дальнього виклику, за кожного запуску, здійснюється налаштування під реальний сегмент. Так ось. Якщо ще раз придивимося до полів після "Converted", то це --- звичайний заголовок EXE-файлу. Після якого йде таблиця релокацій. Тобто, наш декодер просто виконує релокації, як би це зробив завантажувач EXE!
Завершивши із релокаціями, відновалюємо DS (DS = CS), переміщаємо початок реального образу програми --- того, що під заголовком MZ EXE, таблицею релокацій і т.д. (його зміщення, в параграфах, в HeaderSize_Pars), зразу після PSP (цікаво, що переміщається рівно 0xBAD байт :), встановлюємо стек (SS:SP) згідно збереженого раніше у змінних StackSeg_addr:StackTop_addr (до речі, cli-sti там зайві, зміна SS автоматично забороняє переривання для наступної команди) та передаємо керування у вибрані CodeSeg_addr:NewIP.
Цікаве зауваження: Переміщати так високо, аж на 210h байт можна, тому що заголовок EXE-файлу чомусь займає 200h байт (+10h -- "Converted\0\0\0\0"), з яких більшість --- нулі, зайнято лише порядку 30h...
Подальший аналіз
Каюся, спершу, я пішов обхідною дорогою. Прогледів, що на початку, після MZ --- повноцінний MZ-EXE заголовок. Тому, щоб отримати реальний код, завантажив програму у відладчику, дав відпрацювати "декодеру", зберіг образ та дизасемблював вже його. При тому довго вовтузячись із ручним налаштуванням сегментів у IDA Free. Потім усвідомив -- є багато коротша дорога. Якщо від файла відкинути перших 16 байт (можна також відкинути код декодера + 8 байт перед ним, але це необов'язково) --- отримується повноцінний SYS.EXE, який можна нормально запускати чи дизасемблювати.Продовження --- у наступній частині.
Немає коментарів:
Дописати коментар