понеділок, 28 жовтня 2013 р.

Аналіз SYS.COM з PC-DOS 3.00 -- частина перша

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 так познущалися. 

Тобто, історія подій видається наступною:
  1. В коді SYS друк більшості повідомлень (крім повідомлення про невірну версію --- якщо його треба виводити, ми не можемо очікувати "просунутих" сервісів INT 21h), замінено на дальній виклик printf. 
  2. Ймовірно, printf взявся із Microsoft/Lattice C, ймовірно дуже ранніх версій, так як printf дуже урізаний (детальніше --- нижче).
  3. Код SYS лінкується із printf, даючи щось типу SYS.EXE --- повноцінний MZ-EXE.
  4. Якимось конвертером він перетворюється в псевдо-COM, який "вручну" робить 6 релокацій (по кількості викликів printf), переміщає завантажений "буквально" --- як .COM, файл, створюючи в пам'яті готовий до виконання образ EXE-файла, близький до вихідного, та передає йому керування.
  5. Що найцікавіше, всі ці збочення --- заради шести викликів 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, який можна нормально запускати чи дизасемблювати.

Продовження --- у наступній частині.

Немає коментарів:

Дописати коментар