[2019Ciscn初赛] Strange int

  • file Image.bin查看文件类型,发现是DOS/MBR boot sector

  • 下面简单记录一下DOS分区体系的主引导记录扇区-MBR

  • 使用 DOS 分区体系时,磁盘的第一个扇区――也就是 0 号扇区被称为主引导记录扇区,也称为 MBR( 主引导记录, Master Boot Recorder -- MBR) 。当计算机启动并完成自检后,首先会寻找磁盘的 MBR 扇区并读取其中的引导记录,然后将系统控制权交给它。

  • MBR 由 446 个字节的引导代码、 64 个字节的主分区表及 2 个字节的签名值“ 55AA ”组成。

  • ***引导代码:***MBR 接管系统的控制权后,引导代码负责对其他代码信息进行检查(比如查看是否有“ 55AA ”有效标记)并进一步引导系统。

  • 分区表:分区表负责描述磁盘内的分区情况。

  • “ 55AA ”有效标志。“ 55AA ”标志做为有效标志以通知系统该 MBR 扇区是否有效,如果该标志丢失或损坏,磁盘将会显示为“未初始化”。

  • 放入010中找到此签名,那么前面的就是主引导扇区的代码

  • IDA将0-0x200的数据转换成汇编代码

  • seg000:0000 EA 05 00 C0 07                jmp     far ptr 7C0h:5
    seg000:0000
    seg000:0005                               ; ---------------------------------------------------------------------------
    seg000:0005 8C C8                         mov     ax, cs
    seg000:0007 8E D8                         mov     ds, ax
    seg000:0009 8E D0                         mov     ss, ax
    seg000:000B BC 00 04                      mov     sp, 400h
    seg000:000E FC                            cld
    seg000:000F B8 03 00                      mov     ax, 3
    seg000:0012 CD 10                         int     10h                             ; - VIDEO - SET VIDEO MODE
    seg000:0012                                                                       ; AL = mode
    seg000:0012
    seg000:0014 BA 00 00                      mov     dx, 0
    seg000:0017 B9 02 00                      mov     cx, 2
    seg000:001A B8 00 10                      mov     ax, 1000h
    seg000:001D 8E C0                         mov     es, ax
    seg000:001F                               assume es:nothing
    seg000:001F 31 DB                         xor     bx, bx
    seg000:0021 B8 28 02                      mov     ax, 228h
    seg000:0024 CD 13                         int     13h                             ; DISK - READ SECTORS INTO MEMORY
    seg000:0024                                                                       ; AL = number of sectors to read, CH = track, CL = sector
    seg000:0024                                                                       ; DH = head, DL = drive, ES:BX -> buffer to fill
    seg000:0024                                                                       ; Return: CF set on error, AH = status, AL = number of sectors read
    seg000:0024
    seg000:0026 73 02                         jnb     short loc_2A
    seg000:0026
    seg000:0028
    seg000:0028                               loc_28:                                 ; CODE XREF: seg000:loc_28↓j
    seg000:0028 EB FE                         jmp     short loc_28
    seg000:0028
    seg000:002A                               ; ---------------------------------------------------------------------------
    seg000:002A
    seg000:002A                               loc_2A:                                 ; CODE XREF: seg000:0026↑j
    seg000:002A FA                            cli
    seg000:002B B8 00 10                      mov     ax, 1000h
    seg000:002E 8E D8                         mov     ds, ax
    seg000:0030                               assume ds:nothing
    seg000:0030 31 C0                         xor     ax, ax
    seg000:0032 8E C0                         mov     es, ax
    seg000:0034                               assume es:nothing
    seg000:0034 B9 00 20                      mov     cx, 2000h
    seg000:0037 29 F6                         sub     si, si
    seg000:0039 29 FF                         sub     di, di
    seg000:003B F3 A4                         rep movsb
    seg000:003D B8 C0 07                      mov     ax, 7C0h
    seg000:003D
    seg000:0040
    seg000:0040                               loc_40:                                 ; DATA XREF: seg000:0012↑r
    seg000:0040 8E D8                         mov     ds, ax
    seg000:0042                               assume ds:nothing
    seg000:0042 0F 01 1E 6F 00                lidt    fword ptr ds:6Fh
    seg000:0047 0F 01 16 75 00                lgdt    fword ptr ds:75h
    seg000:0047
    seg000:004C
    seg000:004C                               loc_4C:                                 ; DATA XREF: seg000:0024↑r
    seg000:004C B8 01 00                      mov     ax, 1
    seg000:004F 0F 01 F0                      lmsw    ax
    seg000:0052 EA 00 00 08 00                jmp     far ptr byte_80
    seg000:0052
    seg000:0052                               ; ---------------------------------------------------------------------------
    seg000:0057 00 00 00 00 00 00 00 00 FF 07+db 8 dup(0), 0FFh, 7, 3 dup(0), 9Ah, 0C0h, 0, 0FFh, 7, 3 dup(0), 92h, 0C0h, 7 dup(0), 0FFh, 7, 57h, 7Ch
    seg000:0057 00 00 00 9A C0 00 FF 07 00 00+db 7 dup(0)
    seg000:0080 00 00 00 00 00 00 00 00 00 00+byte_80 db 17Eh dup(0), 55h, 0AAh       ; CODE XREF: seg000:0052↑J
    seg000:0080 00 00 00 00 00 00 00 00 00 00+seg000 ends
    seg000:0080 00 00 00 00 00 00 00 00 00 00+
    
  • 下面分析上述汇编:

  • 首先主引导扇区的地址被加载到0x7c00,跳转到0x7c05

  • 然后初始化段寄存器和栈指针,然后用int 10h 是bios中断设置显示模式,字符和字符串输出等

  • int 13h就是直接磁盘服务,下面是一些用法:

  • 1、功能 00H
    
    功能描述:磁盘系统复位
    入口参数:AH=00H
    DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
    出口参数:CF=0——操作成功,AH=00H,否则,AH=状态代码,参见功能号01H中的说明
    
    2、功能 01H
    
    功能描述:读取磁盘系统状态
    入口参数:AH=01H
    DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
    出口参数:AH=00H,AL=状态代码,其定义如下:
    00H — 无错 01H — 非法命令
    02H — 地址目标未发现 03H — 磁盘写保护(软盘)
    04H — 扇区未发现 05H — 复位失败(硬盘)
    06H — 软盘取出(软盘) 07H — 错误的参数表(硬盘)
    08H — DMA越界(软盘) 09H — DMA超过64K界限
    0AH — 错误的扇区标志(硬盘) 0BH — 错误的磁道标志(硬盘)
    0CH — 介质类型未发现(软盘) 0DH — 格式化时非法扇区号(硬盘)
    0EH — 控制数据地址目标被发现(硬盘) 0FH — DMA仲裁越界(硬盘)
    10H — 不正确的CRC或ECC编码 11H — ECC校正数据错(硬盘)
     CRC:Cyclic Redundancy Check code
     ECC:Error Checking & Correcting code
    20H — 控制器失败 40H — 查找失败
    80H — 磁盘超时(未响应) AAH — 驱动器未准备好(硬盘)
    BBH — 未定义的错误(硬盘) CCH — 写错误(硬盘)
    E0H — 状态寄存器错(硬盘) FFH — 检测操作失败(硬盘)
    
    3、功能 02H
    
    功能描述:读扇区
    入口参数:AH=02H
    AL=扇区数
    CH=柱面
    CL=扇区
    DH=磁头
    DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
    ES:BX=缓冲区的地址
    出口参数:CF=0——操作成功,AH=00H,AL=传输的扇区数,否则,AH=状态代码,参见功能号01H中的说明
    
    4、功能 03H
    
    功能描述:写扇区
    入口参数:AH=03H
    AL=扇区数
    CH=柱面
    CL=扇区
    DH=磁头
    DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
    ES:BX=缓冲区的地址
    出口参数:CF=0——操作成功,AH=00H,AL=传输的扇区数,否则,AH=状态代码,参见功能号01H中的说明
    
    5、功能 04H
    
    功能描述:检验扇区
    入口参数:AH=04H
    AL=扇区数
    CH=柱面
    CL=扇区
    DH=磁头
    DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
    ES:BX=缓冲区的地址
    出口参数:CF=0——操作成功,AH=00H,AL=被检验的扇区数,否则,AH=状态代码,参见功能号01H中的说明。
    
    6、功能 05H
    
    功能描述:格式化磁道
    入口参数:AH=05H
    AL=交替(Interleave)
    CH=柱面
    DH=磁头
    DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
    ES:BX=地址域列表的地址
    出口参数:CF=0——操作成功,AH=00H,否则,AH=状态代码,参见功能号01H中的说明。
    
    7、功能 06H
    
    功能描述:格式化坏磁道
    入口参数:AH=06H
    AL=交替
    CH=柱面
    DH=磁头
    DL=80H~0FFH:硬盘
    ES:BX=地址域列表的地址
    出口参数:CF=0——操作成功,AH=00H,否则,AH=状态代码,参见功能号01H中的说明
    
    8、功能 07H
    
    功能描述:格式化驱动器
    入口参数:AH=07H
    AL=交替
    CH=柱面
    DL=80H~0FFH:硬盘
    出口参数:CF=0——操作成功,AH=00H,否则,AH=状态代码,参见功能号01H中的说明
    
    9、功能 08H
    
    功能描述:读取驱动器参数
    入口参数:AH=08H
    DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
    出口参数:CF=1——操作失败,AH=状态代码,参见功能号01H中的说明,否则,
    BL=
    01H — 360K
    =02H — 1.2M
    =03H — 720K
    =04H — 1.44M
    CH=柱面数的低8位
    CL的位7-6=柱面数的该2位
    CL的位5-0=扇区数
    DH=磁头数
    DL=驱动器数
    ES:DI=磁盘驱动器参数表地址
    
    10、功能 09H
    
    功能描述:初始化硬盘参数
    入口参数:AH=09H
    DL=80H~0FFH:硬盘(还有有关参数表问题,在此从略)
    出口参数:CF=0——操作成功,AH=00H,否则,AH=状态代码,参见功能号01H中的说明
    
    11、功能 0AH
    
    功能描述:读长扇区,每个扇区随带四个字节的ECC编码
    入口参数:AH=0AH
    AL=扇区数
    CH=柱面
    CL=扇区
    DH=磁头
    DL=80H~0FFH:硬盘
    ES:BX=缓冲区的地址
    出口参数:CF=0——操作成功,AH=00H,AL=传输的扇区数,否则,AH=状态代码,参见功能号01H中的说明
    
    12、功能 0BH
    
    功能描述:写长扇区,每个扇区随带四个字节的ECC编码
    入口参数:AH=0BH
    AL=扇区数
    CH=柱面
    CL=扇区
    DH=磁头
    DL=80H~0FFH:硬盘
    ES:BX=缓冲区的地址
    出口参数:CF=0——操作成功,AH=00H,AL=传输的扇区数,否则,AH=状态代码,参见功能号01H中的说明
    
    13、功能 0CH
    
    功能描述:查寻
    入口参数:AH=0CH
    CH=柱面的低8位
    CL(7-6位)=柱面的高2位
    DH=磁头
    DL=80H~0FFH:硬盘
    出口参数:CF=0——操作成功,AH=00H,否则,AH=状态代码,参见功能号01H中的说明
    
    14、功能 0DH
    
    功能描述:硬盘系统复位
    入口参数:AH=0DH
    DL=80H~0FFH:硬盘
    出口参数:CF=0——操作成功,AH=00H,否则,AH=状态代码,参见功能号01H中的说明
    
    15、功能 0EH
    
    功能描述:读扇区缓冲区
    入口参数:AH=0EH
    ES:BX=缓冲区的地址
    出口参数:CF=0——操作成功,否则,AH=状态代码,参见功能号01H中的说明
    
    16、功能 0FH
    
    功能描述:写扇区缓冲区
    入口参数:AH=0FH
    ES:BX=缓冲区的地址
    出口参数:CF=0——操作成功,否则,AH=状态代码,参见功能号01H中的说明
    
    17、功能 10H
    
    功能描述:读取驱动器状态
    入口参数:AH=10H
    DL=80H~0FFH:硬盘
    出口参数:CF=0——操作成功,AH=00H,否则,AH=状态代码,参见功能号01H中的说明
    
    18、功能 11H
    
    功能描述:校准驱动器
    入口参数:AH=11H
    DL=80H~0FFH:硬盘
    出口参数:CF=0——操作成功,AH=00H,否则,AH=状态代码,参见功能号01H中的说明
    
    19、功能 12H
    
    功能描述:控制器RAM诊断
    入口参数:AH=12H
    出口参数:CF=0——操作成功,否则,AH=状态代码,参见功能号01H中的说明
    
    20、功能 13H
    
    功能描述:控制器驱动诊断
    入口参数:AH=13H
    出口参数:CF=0——操作成功,否则,AH=状态代码,参见功能号01H中的说明
    
    21、功能 14H
    
    功能描述:控制器内部诊断
    入口参数:AH=14H
    出口参数:CF=0——操作成功,否则,AH=状态代码,参见功能号01H中的说明
    
    22、功能 15H
    
    功能描述:读取磁盘类型
    入口参数:AH=15H
    DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘
    出口参数:CF=1——操作失败,AH=状态代码,参见功能号01H中的说明, 否则,AH=00H — 未安装驱动器
    =01H — 无改变线支持的软盘驱动器
    =02H — 带有改变线支持的软盘驱动器
    =03H — 硬盘,CX:DX=512字节的扇区数
    
    23、功能 16H
    
    功能描述:读取磁盘变化状态
    入口参数:AH=16H
    DL=00H~7FH:软盘
    出口参数:CF=0——磁盘未改变,AH=00H,否则,AH=06H,参见功能号01H中的说明
    
    24、功能 17H
    
    功能描述:设置磁盘类型
    入口参数:AH=17H
    DL=00H~7FH:软盘 AL=00H — 未用
    =01H — 360K在360K驱动器中
    =02H — 360K在1.2M驱动器中
    =03H — 1.2M在1.2M驱动器中
    =04H — 720K在720K驱动器中
    出口参数:CF=0——操作成功,AH=00H,否则,AH=状态编码,参见功能号01H中的说明
    
    25、功能 18H
    
    功能描述:设置格式化媒体类型
    入口参数:AH=18H
    CH=柱面数
    CL=每磁道的扇区数
    DL=00H~7FH:软盘
    出口参数:CF=0——操作成功,AH=00H,ES:DI=介质类型参数表地址,否则,AH=状态编码,参见功能号01H中的说明
    
    26、功能 19H
    
    功能描述:磁头保护,仅在PS/2中有效,在此从略
    
    27、功能 1AH
    
    功能描述:格式化ESDI驱动器,仅在PS/2中有效,在此从略
    
    
  • 找到汇编代码中AH的值为02h,对应用法:软盘(DL=0H) 上的0磁道(DH=0H)0柱面(CH=0H)2扇区(CL=2H)开始的28个扇区(AL=28H)读取(AH=02H)到内存的1000:0000h处(ES:BX=1000:0),然后跳到loc_2A处,这部分代码再将刚才读入的扇区数据移动到内存的0x00000000处

  • 初始化IDT和GDT(lidt,lgdt)之后开启保护模式(Imsw)并且跳转至32位代码段 从0x200开始
    继续转换成汇编代码,关于IDT与GDT:操作系统之GDT和IDT(三)_gdt idt-CSDN博客

  • 这里切到保护,跳到32位

  • 接着分析汇编:

  • seg000:00000200                               sub_200 proc near
    seg000:00000200 B8 10 00 00 00                mov     eax, 10h
    seg000:00000205 8E D8                         mov     ds, eax
    seg000:00000207                               assume ds:nothing
    seg000:00000207 0F B2 25 5C 0B 00 00          lss     esp, fword ptr ds:byte_C5C
    seg000:0000020E E8 78 00 00 00                call    sub_28B
    seg000:0000020E
    seg000:00000213
    seg000:00000213                               loc_213:                                ; DATA XREF: sub_2BA+A↓r
    seg000:00000213                                                                       ; sub_2BA:loc_2E0↓w
    seg000:00000213 E8 6B 00 00 00                call    sub_283
    seg000:00000213
    seg000:00000218
    seg000:00000218                               loc_218:                                ; DATA XREF: sub_28B+27↓r
    seg000:00000218 B8 10 00 00 00                mov     eax, 10h
    seg000:0000021D 8E D8                         mov     ds, eax
    seg000:0000021F 8E C0                         mov     es, eax
    seg000:00000221                               assume es:nothing
    seg000:00000221
    seg000:00000221                               loc_221:                                ; DATA XREF: sub_283↓r
    seg000:00000221 8E E0                         mov     fs, eax
    seg000:00000223                               assume fs:nothing
    seg000:00000223 8E E8                         mov     gs, eax
    seg000:00000225                               assume gs:nothing
    seg000:00000225
    seg000:00000225                               loc_225:                                ; DATA XREF: sub_28B+11↓o
    seg000:00000225 0F B2 25 5C 0B 00 00          lss     esp, fword ptr ds:byte_C5C
    seg000:0000022C 31 DB                         xor     ebx, ebx
    seg000:0000022C
    seg000:0000022E
    seg000:0000022E                               loc_22E:                                ; CODE XREF: sub_200+5D↓j
    seg000:0000022E 90                            nop
    seg000:0000022F 83 FB 10                      cmp     ebx, 10h
    seg000:00000232 7D 2B                         jge     short loc_25F
    seg000:00000232
    seg000:00000234 B8 00 00 08 00                mov     eax, 80000h
    seg000:00000239 8D 14 9D 08 0D 00 00          lea     edx, ds:0D08h[ebx*4]
    seg000:00000240 8B 12                         mov     edx, [edx]
    seg000:00000242 66 89 D0                      mov     ax, dx
    seg000:00000245 66 BA 00 8E                   mov     dx, 8E00h
    seg000:00000249 B9 21 00 00 00                mov     ecx, 21h ; '!'
    seg000:0000024E 01 D9                         add     ecx, ebx
    seg000:00000250 8D 34 CD 28 01 00 00          lea     esi, ds:128h[ecx*8]
    seg000:00000257 89 06                         mov     [esi], eax
    seg000:00000259 89 56 04                      mov     [esi+4], edx
    seg000:0000025C 43                            inc     ebx
    seg000:0000025D EB CF                         jmp     short loc_22E
    seg000:0000025D
    seg000:0000025F                               ; ---------------------------------------------------------------------------
    seg000:0000025F
    seg000:0000025F                               loc_25F:                                ; CODE XREF: sub_200+32↑j
    seg000:0000025F                                                                       ; sub_200+66↓j
    seg000:0000025F E8 04 00 00 00                call    sub_268
    seg000:0000025F
    seg000:00000264 CD 21                         int     21h                             ; DOS -
    seg000:00000264
    seg000:00000266 EB F7                         jmp     short loc_25F
    seg000:00000266
    seg000:00000266                               sub_200 endp
    
  • 挨个分析:

  • seg000:0000028B                               sub_28B proc near                       ; CODE XREF: sub_200+E↑p
    seg000:0000028B BA FC 00 00 00                mov     edx, 0FCh
    seg000:00000290 B8 00 00 08 00                mov     eax, 80000h
    seg000:00000295 66 89 D0                      mov     ax, dx
    seg000:00000298 66 BA 00 8E                   mov     dx, 8E00h
    seg000:0000029C 8D 3D 28 01 00 00             lea     edi, loc_225+3 - (dword_74+8Ch)//地址是128h
    seg000:000002A2 B9 00 01 00 00                mov     ecx, 100h
    seg000:000002A2
    seg000:000002A7
    seg000:000002A7                               loc_2A7:                                ; CODE XREF: sub_28B+25↓j
    seg000:000002A7 89 07                         mov     [edi], eax
    seg000:000002A9 89 57 04                      mov     [edi+4], edx
    seg000:000002AC 83 C7 08                      add     edi, 8
    seg000:000002AF 49                            dec     ecx
    seg000:000002B0 75 F5                         jnz     short loc_2A7
    seg000:000002B0
    seg000:000002B2 0F 01 1D 1C 01 00 00          lidt    fword ptr ds:loc_218+4
    seg000:000002B9 C3                            retn
    seg000:000002B9
    seg000:000002B9                               sub_28B endp
    seg000:000002B9
    
  • seg000:00000283                               sub_283 proc near                       ; CODE XREF: sub_200:loc_213↑p
    seg000:00000283 0F 01 15 22 01 00 00          lgdt    fword ptr ds:loc_221+1
    seg000:0000028A C3                            retn
    seg000:0000028A
    seg000:0000028A                               sub_283 endp
    seg000:0000028A
    seg000:0000028B
    
  • 上面两个就是将IDT和GDT的入口地址装入IDTR(GDTR)寄存器

  • 再往下看:

  • 给ds,es,fs,gs赋值,循环16次,loc_22E是将ds:0xD08开始的数据填充到ds:0x128,0x128是IDT表基地址,执行后中断21h到30h的的入口地址全部改变

  • sub_268:

  • seg000:00000268                               sub_268 proc near                       ; CODE XREF: sub_200:loc_25F↑p
    seg000:00000268 8B 3D 78 0B 00 00             mov     edi, dword ptr ds:unk_C78
    seg000:0000026E 8D 3C BD 48 0D 00 00          lea     edi, ds:0D48h[edi*4]
    seg000:00000275 8B 07                         mov     eax, [edi]
    seg000:00000277 A2 65 00 00 00                mov     byte ptr ds:unk_165, al
    seg000:0000027C 8B 4F 04                      mov     ecx, [edi+4]
    seg000:0000027F 8B 47 08                      mov     eax, [edi+8]
    seg000:00000282 C3                            retn
    seg000:00000282
    seg000:00000282                               sub_268 endp
    
  • 这里的ds:unk_165就是 000264处的 int 21h

  • 该段代码就是存储了虚拟机的指令,每条指令的长度为12字节,前四个字节为opcode,后面八个字节就是两个操作数,作为两个参数传入中断,中断作用相当于call,调用子程序就是handler

  • 中断指令 的21h会一直改变,每次调用完子程序都会跳到EF8处,0B78处的值加3,从而执行0d48[edi*4]处的下一个中断

  • 注:中断调用子程序地址按中断编号线性排列

  • seg000:00000EF8 8D 0D 78 0B 00 00             lea     ecx, unk_B78
    seg000:00000EFE 8B 01                         mov     eax, [ecx]
    seg000:00000F00 83 C0 03                      add     eax, 3
    seg000:00000F03 89 01                         mov     [ecx], eax
    seg000:00000F05 CF                            iret
    seg000:00000F05
    seg000:00000F05                               ; -----------------------
    
  • 下面逐个分析16个中断的意义:设0B64数组为buf,eax为a,ecx为c,0D48为code数组

  • seg000:00000D7C 8D 0C 8D 64 0B 00 00          lea     ecx, ds:0B64h[ecx*4]
    seg000:00000D83 89 01                         mov     [ecx], eax
    seg000:00000D85 E9 6E 01 00 00                jmp     loc_EF8   ; buf[c]=a;
    seg000:00000D85
    seg000:00000D8A                               ; ---------------------------------------------------------------------------
    seg000:00000D8A 8D 04 85 64 0B 00 00          lea     eax, ds:0B64h[eax*4]
    seg000:00000D91 8B 00                         mov     eax, [eax]
    seg000:00000D93 8D 0C 8D 64 0B 00 00          lea     ecx, ds:0B64h[ecx*4]
    seg000:00000D9A 89 01                         mov     [ecx], eax
    seg000:00000D9C E9 57 01 00 00                jmp     loc_EF8  ;buf[c]=buf[a]
    seg000:00000D9C
    seg000:00000DA1                               ; ---------------------------------------------------------------------------
    seg000:00000DA1 8D 04 85 64 0B 00 00          lea     eax, ds:0B64h[eax*4]
    seg000:00000DA8 8B 00                         mov     eax, [eax]
    seg000:00000DAA 8D 0C 8D 64 0B 00 00          lea     ecx, ds:0B64h[ecx*4]
    seg000:00000DB1 8D 04 85 48 0D 00 00          lea     eax, ds:0D48h[eax*4]
    seg000:00000DB8 8B 00                         mov     eax, [eax]
    seg000:00000DBA 89 01                         mov     [ecx], eax;buf[c]=code[buf[a]]
    seg000:00000DBC E9 37 01 00 00                jmp     loc_EF8
    seg000:00000DBC
    seg000:00000DC1                               ; ---------------------------------------------------------------------------
    seg000:00000DC1 8D 04 85 64 0B 00 00          lea     eax, ds:0B64h[eax*4]
    seg000:00000DC8 8B 00                         mov     eax, [eax]
    seg000:00000DCA 8D 0C 8D 64 0B 00 00          lea     ecx, ds:0B64h[ecx*4]
    seg000:00000DD1 8B 09                         mov     ecx, [ecx]
    seg000:00000DD3 8D 0C 8D 48 0D 00 00          lea     ecx, ds:0D48h[ecx*4]
    seg000:00000DDA 89 01                         mov     [ecx], eax
    seg000:00000DDC E9 17 01 00 00                jmp     loc_EF8;code[buf[c]]=buf[a];
    seg000:00000DDC
    seg000:00000DE1                               ; ---------------------------------------------------------------------------
    seg000:00000DE1 8D 04 85 64 0B 00 00          lea     eax, ds:0B64h[eax*4]
    seg000:00000DE8 8B 10                         mov     edx, [eax]
    seg000:00000DEA 8D 0C 8D 64 0B 00 00          lea     ecx, ds:0B64h[ecx*4]
    seg000:00000DF1 8B 01                         mov     eax, [ecx]
    seg000:00000DF3 01 D0                         add     eax, edx
    seg000:00000DF5 89 01                         mov     [ecx], eax
    seg000:00000DF7 E9 FC 00 00 00                jmp     loc_EF8;code[buf[c]]=buf[a];
    seg000:00000DF7
    seg000:00000DFC                               ; ---------------------------------------------------------------------------
    seg000:00000DFC 8D 04 85 64 0B 00 00          lea     eax, ds:0B64h[eax*4]
    seg000:00000E03 8B 10                         mov     edx, [eax]
    seg000:00000E05 8D 0C 8D 64 0B 00 00          lea     ecx, ds:0B64h[ecx*4]
    seg000:00000E0C 8B 01                         mov     eax, [ecx]
    seg000:00000E0E 29 D0                         sub     eax, edx
    seg000:00000E10 89 01                         mov     [ecx], eax
    seg000:00000E12 E9 E1 00 00 00                jmp     loc_EF8
    seg000:00000E12;buf[c]=buf[c]-buf[a];
    seg000:00000E17                               ; ---------------------------------------------------------------------------
    seg000:00000E17 8D 04 85 64 0B 00 00          lea     eax, ds:0B64h[eax*4]
    seg000:00000E1E 8B 10                         mov     edx, [eax]
    seg000:00000E20 8D 0C 8D 64 0B 00 00          lea     ecx, ds:0B64h[ecx*4]
    seg000:00000E27 8B 01                         mov     eax, [ecx]
    seg000:00000E29 31 D0                         xor     eax, edx
    seg000:00000E2B 89 01                         mov     [ecx], eax
    seg000:00000E2D E9 C6 00 00 00                jmp     loc_EF8
    seg000:00000E2D;buf[c]=buf[c]^buf[a];
    seg000:00000E32                               ; ---------------------------------------------------------------------------
    seg000:00000E32 8D 04 85 64 0B 00 00          lea     eax, ds:0B64h[eax*4]
    seg000:00000E39 8B 00                         mov     eax, [eax]
    seg000:00000E3B 8D 14 8D 64 0B 00 00          lea     edx, ds:0B64h[ecx*4]
    seg000:00000E42 88 C1                         mov     cl, al
    seg000:00000E44 8B 02                         mov     eax, [edx]
    seg000:00000E46 D3 E0                         shl     eax, cl
    seg000:00000E48
    seg000:00000E48                               loc_E48:
    seg000:00000E48 89 02                         mov     [edx], eax
    seg000:00000E4A E9 A9 00 00 00                jmp     loc_EF8
    seg000:00000E4A;buf[c]=buf[c]<<(buf[a]&0xFF);
    seg000:00000E4F                               ; ---------------------------------------------------------------------------
    seg000:00000E4F
    seg000:00000E4F                               loc_E4F:
    seg000:00000E4F 8D 04 85 64 0B 00 00          lea     eax, ds:0B64h[eax*4]
    seg000:00000E56 8B 00                         mov     eax, [eax]
    seg000:00000E58 8D 14 8D 64 0B 00 00          lea     edx, ds:0B64h[ecx*4]
    seg000:00000E5F 88 C1                         mov     cl, al
    seg000:00000E61 8B 02                         mov     eax, [edx]
    seg000:00000E63 D3 E8                         shr     eax, cl
    seg000:00000E65 89 02                         mov     [edx], eax
    seg000:00000E67 E9 8C 00 00 00                jmp     loc_EF8
    seg000:00000E67;buf[c]=buf[c]>>(buf[a]&0xFF);
    seg000:00000E6C                               ; ---------------------------------------------------------------------------
    seg000:00000E6C 8D 04 85 64 0B 00 00          lea     eax, ds:0B64h[eax*4]
    seg000:00000E73 8B 00                         mov     eax, [eax]
    seg000:00000E75 8D 0C 8D 64 0B 00 00          lea     ecx, ds:0B64h[ecx*4]
    seg000:00000E7C 8B 11                         mov     edx, [ecx]
    seg000:00000E7E 21 D0                         and     eax, edx
    seg000:00000E80 89 01                         mov     [ecx], eax
    seg000:00000E82 EB 74                         jmp     short loc_EF8
    seg000:00000E82;buf[c]=buf[c]>>(buf[a]&0xFF);
    seg000:00000E84                               ; ---------------------------------------------------------------------------
    seg000:00000E84 8D 04 8D 64 0B 00 00          lea     eax, ds:0B64h[ecx*4]
    seg000:00000E8B 8B 00                         mov     eax, [eax]
    seg000:00000E8D 8D 0D 78 0B 00 00             lea     ecx, unk_B78
    seg000:00000E93 89 01                         mov     [ecx], eax
    seg000:00000E95 CF                            iret
    seg000:00000E95;ds:0x0b78=buf[c];
    seg000:00000E96                               ; ---------------------------------------------------------------------------
    seg000:00000E96 8D 04 85 64 0B 00 00          lea     eax, ds:0B64h[eax*4]
    seg000:00000E9D 8B 00                         mov     eax, [eax]
    seg000:00000E9F 85 C0                         test    eax, eax
    seg000:00000EA1 75 55                         jnz     short loc_EF8
    seg000:00000EA1
    seg000:00000EA3 8D 04 8D 64 0B 00 00          lea     eax, ds:0B64h[ecx*4]
    seg000:00000EAA 8B 00                         mov     eax, [eax]
    seg000:00000EAC 8D 0D 78 0B 00 00             lea     ecx, unk_B78
    seg000:00000EB2 89 01                         mov     [ecx], eax
    seg000:00000EB4 CF                            iret
    seg000:00000EB4;if {buf[a]==0} ds:0x0b78=buf[c];
    seg000:00000EB5                               ; ---------------------------------------------------------------------------
    seg000:00000EB5 8D 04 85 64 0B 00 00          lea     eax, ds:0B64h[eax*4]
    seg000:00000EBC 8B 00                         mov     eax, [eax]
    seg000:00000EBE 85 C0                         test    eax, eax
    seg000:00000EC0 74 36                         jz      short loc_EF8
    seg000:00000EC0
    seg000:00000EC2 8D 04 8D 64 0B 00 00          lea     eax, ds:0B64h[ecx*4]
    seg000:00000EC9 8B 00                         mov     eax, [eax]
    seg000:00000ECB 8D 0D 78 0B 00 00             lea     ecx, unk_B78
    seg000:00000ED1 89 01                         mov     [ecx], eax
    seg000:00000ED3 CF                            iret
    seg000:00000ED3;if{buf[a]!=0} ds:0x0b78=buf[c];
    seg000:00000ED4                               ; ---------------------------------------------------------------------------
    seg000:00000ED4 8D 05 94 0F 00 00             lea     eax, unk_F94
    seg000:00000EDA E8 0B F4 FF FF                call    sub_2EA
    seg000:00000EDA
    seg000:00000EDF F4                            hlt;暂停;
    seg000:00000EE0 8D 05 A0 0F 00 00             lea     eax, unk_FA0
    seg000:00000EE6 E8 FF F3 FF FF                call    sub_2EA;正确
    seg000:00000EE6
    seg000:00000EEB 8D 05 AE 0F 00 00             lea     eax, word_FAE
    seg000:00000EF1 E8 F4 F3 FF FF                call    sub_2EA;错误
    seg000:00000EF1
    seg000:00000EF6 F4                            hlt
    
  • 后面把数据dump出来(注意是DWORD类型数组)写脚本模拟虚拟机

  • data = [
            0x00000021, 0x00000000, 0x00000081, 0x00000027, 0x00000001, 0x00000001, 0x00000024, 0x00000001, 0x00000001,
            0x00000023, 0x00000002, 0x00000000, 0x00000022, 0x00000003, 0x00000002, 0x00000021, 0x00000004, 0x00000008,
            0x00000028, 0x00000003, 0x00000004, 0x00000027, 0x00000002, 0x00000003, 0x00000028, 0x00000003, 0x00000004,
            0x00000027, 0x00000002, 0x00000003,  0x00000028, 0x00000003, 0x00000004, 0x00000027, 0x00000002, 0x00000003,
            0x00000027, 0x00000003, 0x00000003, 0x00000023, 0x00000004, 0x00000003, 0x00000024, 0x00000003, 0x00000002,
            0x00000027, 0x00000002, 0x00000004, 0x00000024, 0x00000000, 0x00000002, 0x00000021, 0x00000001, 0x00000001,
            0x00000025, 0x00000000, 0x00000001, 0x00000022, 0x00000001, 0x00000000, 0x00000021, 0x00000002, 0x00000081,
            0x00000026, 0x00000001, 0x00000002, 0x00000021, 0x00000002, 0x00000009, 0x00000026, 0x00000001, 0x00000002,
            0x00000021, 0x00000002, 0x00000009, 0x0000002D, 0x00000002, 0x00000001, 0x00000021, 0x00000000, 0x00000081,
            0x00000022, 0x00000001, 0x00000000, 0x00000021, 0x00000002, 0x00000009, 0x00000025, 0x00000001, 0x00000002,
            0x00000023, 0x00000003, 0x00000000, 0x00000023, 0x00000004, 0x00000001, 0x00000026, 0x00000003, 0x00000004,
            0x00000021, 0x00000004, 0x0000007E, 0x0000002D, 0x00000004, 0x00000003, 0x00000021, 0x00000003, 0x00000001,
            0x00000025, 0x00000000, 0x00000003, 0x00000025, 0x00000001, 0x00000003, 0x00000026, 0x00000002, 0x00000003,
            0x00000021, 0x00000004, 0x0000005A, 0x0000002D, 0x00000004, 0x00000002, 0x0000002F, 0x00000000, 0x00000000,
            0x00000030, 0x00000000, 0x00000000
          ]
    i = 0
    while (i<=126):
        if data[i] == 0x21:
            print ("buf[%d]=%d" % (data[i+1], data[i+2]))
        if data[i] == 0x22:
            print ("buf[%d]=buf[%d]" % (data[i+1], data[i+2]))
        if data[i] == 0x23:
            print ("buf[%d]=code[buf[%d]]" % (data[i+1], data[i+2]))
        if data[i] == 0x24:
            print ("code[buf[%d]]=buf[%d]" % (data[i+1], data[i+2]))
        if data[i] == 0x25:
            print ("buf[%d]+=buf[%d]" % (data[i+1], data[i+2]))
        if data[i] == 0x26:
            print ("buf[%d]-=buf[%d]" % (data[i+1], data[i+2]))
        if data[i] == 0x27:
            print ("buf[%d]^=buf[%d]" % (data[i+1], data[i+2]))
        if data[i] == 0x28:
            print ("buf[%d]<<=buf[%d]" % (data[i+1], data[i+2]))
        if data[i] == 0x29:
            print ("buf[%d]>>=buf[%d]" % (data[i+1], data[i+2]))
        if data[i] == 0x2A:
            print ("buf[%d]&=buf[%d]" % (data[i+1], data[i+2]))
        if data[i] == 0x2B:
            print ("i =buf[%d]" % (data[i+1]))
        if data[i] == 0x2c:
            print ("if buf[%d]==0  i=buf[%d]" % (data[i+2], data[i+1]))
        if data[i] == 0x2d:
            print ("if buf[%d]!=0 i=buf[%d]" % (data[i+2], data[i+1]))
        if data[i] == 0x2e:
            print ("pause")
        if data[i] == 0x2f:
            print ("correct")
        if data[i] == 0x30:
            print ("wrong")
        i+=3
    
  • 输出:

  • buf[0]=129
    buf[1]^=buf[1]
    code[buf[1]]=buf[1]
    buf[2]=code[buf[0]]
    buf[3]=buf[2]
    buf[4]=8
    buf[3]<<=buf[4]
    buf[2]^=buf[3]
    buf[3]<<=buf[4]
    buf[2]^=buf[3]
    buf[3]<<=buf[4]
    buf[2]^=buf[3]
    buf[3]^=buf[3]
    buf[4]=code[buf[3]]
    code[buf[3]]=buf[2]
    buf[2]^=buf[4]
    code[buf[0]]=buf[2]
    buf[1]=1
    buf[0]+=buf[1]
    buf[1]=buf[0]
    buf[2]=129
    buf[1]-=buf[2]
    buf[2]=9
    buf[1]-=buf[2]
    buf[2]=9
    if buf[1]!=0 i=buf[2]
    buf[0]=129
    buf[1]=buf[0]
    buf[2]=9
    buf[1]+=buf[2]
    buf[3]=code[buf[0]]
    buf[4]=code[buf[1]]
    buf[3]-=buf[4]
    buf[4]=126
    if buf[3]!=0 i=buf[4]
    buf[3]=1
    buf[0]+=buf[3]
    buf[1]+=buf[3]
    buf[2]-=buf[3]
    buf[4]=90
    if buf[2]!=0 i=buf[4]
    correct
    wrong
    
  • 代码一共循环9次执行指令code[i]=code[i] ^(code[i]<<8) ^ (code[i]<<16) ^(code[i]<<24) ^ code[i-1];之后再执行9次比较;buf[i]与buf[i+9]进行9次比较。

  • a=[0x57635565, 0x06530401, 0x1F494949, 0x5157071F, 0x575F4357, 0x57435E57, 0x4357020A, 0x575E035E,0x0f590000,0x0]
    for x in range (0,9):
    
        m4=a[x]&0xff
        m3=(a[x]&0xff00)>>8
        m2=(a[x]&0xff0000)>>16
        m1=(a[x]&0xff000000)>>24
    
        p1=m4
        p2=p1^m3
        p3=p1^m2^p2
        p4=p1^p2^p3^m1
    
        flag=p1+(p2<<8)+(p3<<16)+(p4<<24)
        print(long_to_bytes(flag))
        a[x+1]=a[x]^a[x+1]
    
  • 我直接用longtobytes了

  • b'460e'
    b'aa5d'
    b'7a5-'
    b'11-2'
    b'9-9e'
    b'-002'
    b'9e88'
    b'08ef'
    b'faef'
    
  • 调整顺序,这就是flag

  • 后来发现:

  • 0x61646238, 0x36353465, 0x6361352D, 0x31312D38, 0x612D3965, 0x2D316331, 0x39653838, 0x30386566, 0x66616566, 0x57635565, 0x06530401, 0x1F494949, 0x5157071F, 0x575F4357, 0x57435E57, 0x4357020A, 0x575E035E, 0x0F590000,
    
  • flag就是数据段中已经有的,算非预期嘛?(不过也还是要找到这个循环比较

  • 总结:软盘分析,中断向量表,vm混淆