逆向ultraIso制作的MBR, 看到 disk address packet 参数是通过栈传递的.
这样搞,确实省空间, 不过容易看错, 也不好理解.
; =============== S U B R O U T I N E =======================================
; /// @fn fn_read_sectors_into_memory
; /// @brief 读扇区到内存
; /// @param bp 被激活的分区表入口地址
; /// @param cx 要拷贝的扇区数量
; /// @param dx 激活的分区表入口中指定第一个扇区索引的高8位
; /// @param ax 激活的分区表入口中指定第一个扇区索引的低8位
; /// @param bx 扇区读取后,要拷贝到目的内存地址
fn_read_sectors_into_memory:
push di
mov di, 5 ; ///< 读取扇区到内存失败时的重试次数
fn_read_sectors_into_memory_retry:
pusha
; Format of disk address packet:
;Offset Size Description (Table 00272)
;10h QWORD (EDD-3.0, optional) 64-bit flat address of transfer buffer;
; used if DWORD at 04h is FFFFh:FFFFh
;08h QWORD starting absolute block number
; (for non-LBA devices, compute as
; (Cylinder*NumHeads + SelectedHead) * SectorPerTrack +
; SelectedSector - 1
;04h DWORD -> transfer buffer
;02h WORD number of blocks to transfer (max 007Fh for Phoenix EDD)
;01h BYTE reserved (0);
;00h BYTE size of packet (10h or 18h)
; /// 压入 disk address packet, 并将栈顶给si,供 int 13h, ah = 0x42 使用
; /// 这么搞确实省空间,不过很容易填错参数, 分析者也容易看错参数
xor cx, cx
; /// 开始的绝对块号 = 1
; /// 此时 cx == 0, dx:ax = 0000,0001
push cx ;08h QWORD starting absolute block number
push cx
push dx
push ax
; /// 此时, cx:bx = 0000,7e00
push cx ;04h DWORD -> transfer buffer
push bx
; /// 此时 cx = 0
inc cx ; ///< 此时, cx = 1, 说明要传送的块数为1
push cx ;02h WORD number of blocks to transfer (max 007Fh for Phoenix EDD)
push 0010h ;00h BYTE size of packet (10h or 18h)
;01h BYTE reserved (0);
; /// DS:SI -> disk address packet
mov si, sp
; /// 根据分区表是否有效, 选择使用int 13h ah = 42h 扩展读扇区,还是使用int 13h ah = 2 根据CHS来读扇区
test byte[byte_status], BIT_VALID_PARTITION_SET
jz label_read_disk_to_memory_by_chs ; ///< 不是TRUE(分区校验无效), 转 int13h, ah = 2 读扇区
; /// 分区表有效的处理
; /// 使用 int13h, ah = 0x42 读扇区
mov ah, 0x42
mov dl, [byte_udisk_sn] ; DL = drive
; /// DS:SI -> disk address packet, 已经由函数入口处压入了 disk address packet, 压入时,已经填好了参数, 并将 sp => si
jmp label_read_sectors_into_memory
; /// 否则顺序执行下列代码
label_read_disk_to_memory_by_chs:
; /// ax 激活的分区表入口中指定第一个扇区索引的低8位
div word [word_int13h_8_rc_cs]
inc dx
mov cx, dx
xor dx, dx
div word [word_int13h_8_rc_status_code]
mov ch, al ; CH = track
shr ax, 2
and al, 0C0h
or cl, al ; CL = sector
mov dh, dl ; DH = head
mov ax, 201h
label_read_sectors_into_memory:
int 13h ; DISK - READ SECTORS INTO MEMORY
lea sp, [si+10h] ; ///< 堆栈平衡
popa
jnb fn_read_sectors_into_memory_end
dec di
jz fn_read_sectors_into_memory_ok
pusha
xor ah, ah
mov dl, [byte_udisk_sn]
int 13h ; DISK - RESET DISK SYSTEM
; DL = drive (if bit 7 is set both hard disks and floppy disks reset)
popa
jmp fn_read_sectors_into_memory_retry
fn_read_sectors_into_memory_ok:
stc
fn_read_sectors_into_memory_end:
pop di
ret
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
000000200 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 20
000000210 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 21 ! !
000000220 22 00 00 00 00 00 00 00 00 00 00 00 00 00 00 22 " "
000000230 23 00 00 00 00 00 00 00 00 00 00 00 00 00 00 23 # #
000000240 24 00 00 00 00 00 00 00 00 00 00 00 00 00 00 24 $ $
Next at t=0
(0) [0x0000fffffff0] f000:fff0 (unk. ctxt): jmpf 0xf000:e05b ; ea5be000f0
pb 0x7c00
c
(0) Breakpoint 1, 0x0000000000007c00 in ?? ()
Next at t=156816100
(0) [0x000000007c00] 0000:7c00 (unk. ctxt): cli ; fa
s
...
s
Next at t=156825905
(0) [0x000000007ce0] 0000:7ce0 (unk. ctxt): pusha ; 60
s
Next at t=156825906
(0) [0x000000007ce1] 0000:7ce1 (unk. ctxt): xor cx, cx ; 31c9
s
Next at t=156825907
(0) [0x000000007ce3] 0000:7ce3 (unk. ctxt): push cx ; 51
s
Next at t=156825908
(0) [0x000000007ce4] 0000:7ce4 (unk. ctxt): push cx ; 51
s
Next at t=156825909
(0) [0x000000007ce5] 0000:7ce5 (unk. ctxt): push dx ; 52
s
Next at t=156825910
(0) [0x000000007ce6] 0000:7ce6 (unk. ctxt): push ax ; 50
s
Next at t=156825911
(0) [0x000000007ce7] 0000:7ce7 (unk. ctxt): push cx ; 51
s
Next at t=156825912
(0) [0x000000007ce8] 0000:7ce8 (unk. ctxt): push bx ; 53
s
Next at t=156825913
(0) [0x000000007ce9] 0000:7ce9 (unk. ctxt): inc cx ; 41
s
Next at t=156825914
(0) [0x000000007cea] 0000:7cea (unk. ctxt): push cx ; 51
s
Next at t=156825915
(0) [0x000000007ceb] 0000:7ceb (unk. ctxt): push 0x0010 ; 6a10
s
Next at t=156825916
(0) [0x000000007ced] 0000:7ced (unk. ctxt): mov si, sp ; 89e6
s
Next at t=156825917
(0) [0x000000007cef] 0000:7cef (unk. ctxt): test byte ptr ds:0x7d33, 0x01 ; f606337d01
r
rax: 00000000_00000001 rcx: 00000000_00090001
rdx: 00000000_00000000 rbx: 00000000_00007e00
rsp: 00000000_00007bdc rbp: 00000000_00007dbe
rsi: 00000000_000e7bdc rdi: 00000000_00000005
r8 : 00000000_00000000 r9 : 00000000_00000000
r10: 00000000_00000000 r11: 00000000_00000000
r12: 00000000_00000000 r13: 00000000_00000000
r14: 00000000_00000000 r15: 00000000_00000000
rip: 00000000_00007cef
eflags 0x00000202: id vip vif ac vm rf nt IOPL=0 of df IF tf sf zf af pf cf
xp /1bx 0x7d33
[bochs]:
0x0000000000007d33 : 0x01
s
Next at t=156825918
(0) [0x000000007cf4] 0000:7cf4 (unk. ctxt): jz .+8 (0x00007cfe) ; 7408
s
Next at t=156825919
(0) [0x000000007cf6] 0000:7cf6 (unk. ctxt): mov ah, 0x42 ; b442
s
Next at t=156825920
(0) [0x000000007cf8] 0000:7cf8 (unk. ctxt): mov dl, byte ptr ds:0x7d34 ; 8a16347d
s
Next at t=156825921
(0) [0x000000007cfc] 0000:7cfc (unk. ctxt): jmp .+27 (0x00007d19) ; eb1b
r
rax: 00000000_00004201 rcx: 00000000_00090001
rdx: 00000000_00000080 rbx: 00000000_00007e00
rsp: 00000000_00007bdc rbp: 00000000_00007dbe
rsi: 00000000_000e7bdc rdi: 00000000_00000005
r8 : 00000000_00000000 r9 : 00000000_00000000
r10: 00000000_00000000 r11: 00000000_00000000
r12: 00000000_00000000 r13: 00000000_00000000
r14: 00000000_00000000 r15: 00000000_00000000
rip: 00000000_00007cfc
eflags 0x00000202: id vip vif ac vm rf nt IOPL=0 of df IF tf sf zf af pf cf
u
00007cfc: ( ): jmp .+27 ; eb1b
s
Next at t=156825922
(0) [0x000000007d19] 0000:7d19 (unk. ctxt): int 0x13 ; cd13
u 0x7d19 0x7d29
00007d19: ( ): int 0x13 ; cd13
00007d1b: ( ): lea sp, word ptr ds:[si+16] ; 8d6410
00007d1e: ( ): popa ; 61
00007d1f: ( ): jnb .+16 ; 7310
00007d21: ( ): dec di ; 4f
00007d22: ( ): jz .+12 ; 740c
00007d24: ( ): pusha ; 60
00007d25: ( ): xor ah, ah ; 30e4
00007d27: ( ): mov dl, byte ptr ds:0x7d34 ; 8a16347d
pb 0x7d1b
r
rax: 00000000_00004201 rcx: 00000000_00090001
rdx: 00000000_00000080 rbx: 00000000_00007e00
rsp: 00000000_00007bdc rbp: 00000000_00007dbe
rsi: 00000000_000e7bdc rdi: 00000000_00000005
r8 : 00000000_00000000 r9 : 00000000_00000000
r10: 00000000_00000000 r11: 00000000_00000000
r12: 00000000_00000000 r13: 00000000_00000000
r14: 00000000_00000000 r15: 00000000_00000000
rip: 00000000_00007d19
eflags 0x00000202: id vip vif ac vm rf nt IOPL=0 of df IF tf sf zf af pf cf
c
(0) Breakpoint 5, 0x0000000000007d1b in ?? ()
Next at t=156827497
(0) [0x000000007d1b] 0000:7d1b (unk. ctxt): lea sp, word ptr ds:[si+16] ; 8d6410
xp /16bx si
[bochs]:
0x0000000000007bdc : 0x10 0x00 0x01 0x00 0x00 0x7e 0x00 0x00
0x0000000000007be4 : 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
r
rax: 00000000_00000001 rcx: 00000000_00090001
rdx: 00000000_00000080 rbx: 00000000_00007e00
rsp: 00000000_00007bdc rbp: 00000000_00007dbe
rsi: 00000000_000e7bdc rdi: 00000000_00000005
r8 : 00000000_00000000 r9 : 00000000_00000000
r10: 00000000_00000000 r11: 00000000_00000000
r12: 00000000_00000000 r13: 00000000_00000000
r14: 00000000_00000000 r15: 00000000_00000000
rip: 00000000_00007d1b
eflags 0x00000202: id vip vif ac vm rf nt IOPL=0 of df IF tf sf zf af pf cf
xp /32bx 0x7e00
[bochs]:
0x0000000000007e00 : 0x20 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0000000000007e08 : 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x20
0x0000000000007e10 : 0x21 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x0000000000007e18 : 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x21
q
(0).[156827497] [0x000000007d1b] 0000:7d1b (unk. ctxt): lea sp, word ptr ds:[si+16] ; 8d6410
如果还有可用的代码空间,可以考虑将 DS:SI -> disk address packet 指向数据区定义的 disk address packet 结构, 可以提高清晰度.
毕竟用栈传递参数时的参数填写,不是很直观.
逆向的这个MBR编译完, 还有48字节的空间, 可以考虑使用预先定义的结构体来传递disk address packet参数.
看UltraIso制作的MBR, 里面有动态替换代码的实现,更像是手工patch第三方的MBR后产生的成果.