Retro2048

104次阅读
没有评论

Retro2048

得到了一个16位的com程序,直接拖到IDA里面去查看,找到入口

seg000:0100 ;
seg000:0100 ; +-------------------------------------------------------------------------+
seg000:0100 ; |      This file was generated by The Interactive Disassembler (IDA)      |
seg000:0100 ; |           Copyright (c) 2024 Hex-Rays, <support@hex-rays.com>           |
seg000:0100 ; |                      License info: 48-2137-ACAB-99                      |
seg000:0100 ; |                                                                         |
seg000:0100 ; +-------------------------------------------------------------------------+
seg000:0100 ;
seg000:0100 ; Input SHA256 : 20025217C2B3528165426686ADF19C3964AB25378556B46F1F5663B8C5935C9A
seg000:0100 ; Input MD5    : 0399A2EFC19D6062ACD57B18C3D3FCEB
seg000:0100 ; Input CRC32  : 78A1AED7
seg000:0100 ; Compiler     : Visual C++ (guessed)
seg000:0100
seg000:0100 ; ---------------------------------------------------------------------------
seg000:0100 ; File Name   : C:\Users\15589\Desktop\retro2048.com
seg000:0100 ; Format      : MS-DOS COM-file
seg000:0100 ; Base Address: 1000h Range: 10100h-103F6h Loaded length: 2F6h
seg000:0100
seg000:0100                 .8086
seg000:0100                 .model tiny
seg000:0100
seg000:0100 ; ===========================================================================
seg000:0100
seg000:0100 ; Segment type: Pure code
seg000:0100 seg000          segment byte public 'CODE'
seg000:0100                 assume cs:seg000
seg000:0100                 org 100h
seg000:0100                 assume es:nothing, ss:nothing, ds:seg000
seg000:0100
seg000:0100                 public start
seg000:0100 start:
seg000:0100                 mov     ax, 2
seg000:0103                 int     10h             ; - VIDEO - SET VIDEO MODE
seg000:0103                                         ; AL = mode
seg000:0105                 mov     ax, 0B800h
seg000:0108                 mov     es, ax
seg000:010A                 assume es:nothing
seg000:010A                 cld
seg000:010B                 mov     ah, 67h ; 'g'
seg000:010D                 mov     bp, 38Dh
seg000:0110                 mov     cx, 3Eh ; '>'
seg000:0113                 call    sub_10332
seg000:0116                 mov     ah, 8
seg000:0118                 mov     bp, 3A1h
seg000:011B                 mov     cx, 2ACh
seg000:011E                 call    sub_10332
seg000:011E ; ---------------------------------------------------------------------------
seg000:0121                 db 68h, 0, 38h, 68h, 25h, 11h, 6Ah, 2Ch, 68h, 20h, 3, 0E8h
seg000:012D                 db 0D9h, 1, 0C7h, 6, 0BEh, 3, 1, 0, 0C7h, 6, 0BCh, 3, 0E6h
seg000:013A                 db 3, 0E8h, 6Fh, 0, 0C7h, 6, 0BEh, 3, 1, 0, 0C7h, 6, 0BCh
seg000:0147                 db 3, 0E6h, 3, 0E8h, 60h, 0, 0E8h, 20h, 1, 0B4h, 0, 0CDh
seg000:0153                 db 16h, 80h, 0FCh, 48h, 74h, 17h, 80h, 0FCh, 4Bh, 74h
seg000:015D                 db 17h, 80h, 0FCh, 4Dh, 74h, 17h, 80h, 0FCh, 50h, 74h
seg000:0167                 db 17h, 80h, 0FCh, 1, 75h, 0E3h, 0E9h, 1Bh, 2, 0BDh, 0DAh
seg000:0172                 db 3, 0EBh, 0Dh, 0BDh, 0DDh, 3, 0EBh, 8, 0BDh, 0E0h, 3
seg000:017D                 db 0EBh, 3, 0BDh, 0E3h, 3, 8Ah, 46h, 0, 98h, 0A3h, 0BEh
seg000:0188                 db 3, 0B8h, 0E6h, 3, 2, 46h, 1, 31h, 0D2h, 8Ah, 56h, 2
seg000:0194                 db 0E8h, 5Dh, 0, 0E8h, 0D6h, 0, 0E8h, 2, 0, 0EBh, 9Fh
seg000:019F                 db 31h, 0D2h, 0B9h, 5, 0, 0B4h, 86h, 0CDh, 15h, 0B4h, 0Ch
seg000:01AA                 db 0CDh, 21h, 0C3h, 0B9h, 11h, 0, 0BDh, 0E6h, 3, 31h, 0DBh
seg000:01B5                 db 8Ah, 56h, 0, 80h, 0FAh, 0, 75h, 2, 0FEh, 0C3h, 45h
seg000:01C0                 db 0E2h, 0F3h, 80h, 0FBh, 0, 74h, 2Ch, 0B4h, 0, 0CDh, 1Ah
seg000:01CB                 db 89h, 0D0h, 31h, 0D2h, 0F7h, 0F3h, 88h, 0D7h, 0B9h, 10h
seg000:01D5                 db 0, 0BDh, 0E6h, 3, 30h, 0DBh, 8Ah, 56h, 0, 80h, 0FAh
seg000:01E0                 db 0, 75h, 6, 38h, 0FBh, 74h, 5, 0FEh, 0C3h, 45h, 0E2h
seg000:01EB                 db 0EFh, 24h, 1, 0FEh, 0C0h, 88h, 46h, 0, 0C3h, 0B9h, 4
seg000:01F6                 db 0, 0A3h, 0BCh, 3, 60h, 0E8h, 6, 0, 61h, 1, 0D0h, 0E2h
seg000:0202                 db 0F4h, 0C3h, 0B9h, 3, 0, 8Bh, 2Eh, 0BCh, 3, 8Ah, 66h
seg000:020D                 db 0, 80h, 0FCh, 0, 75h, 25h, 89h, 0CBh, 8Bh, 2Eh, 0BCh
seg000:0218                 db 2 dup(3), 2Eh, 0BEh, 3, 8Ah, 56h, 0, 80h, 0FAh, 0, 74h
seg000:0224                 db 0Dh, 0C6h, 46h, 2 dup(0), 8Bh, 2Eh, 0BCh, 3, 88h, 56h
seg000:022F                 db 0, 0EBh, 0D5h, 4Bh, 83h, 0FBh, 0, 75h, 0E1h, 89h, 0CBh
seg000:023A                 db 8Bh, 2Eh, 0BCh, 2 dup(3), 2Eh, 0BEh, 3, 8Ah, 56h, 0
seg000:0245                 db 80h, 0FAh, 0, 74h, 15h, 38h, 0E2h, 75h, 17h, 0C6h, 46h
seg000:0250                 db 2 dup(0), 8Bh, 2Eh, 0BCh, 3, 0FEh, 46h, 2 dup(0), 16h
seg000:025B                 db 0C0h, 3, 0EBh, 6, 4Bh, 83h, 0FBh, 0, 75h, 0D9h, 8Bh
seg000:0266                 db 1Eh, 0BEh, 3, 1, 1Eh, 0BCh, 3, 0E2h, 98h, 0C3h, 0B9h
seg000:0271                 db 11h, 0, 60h, 88h, 0C8h, 0FEh, 0C8h, 0E8h, 1Ah, 0, 61h
seg000:027C                 db 0E2h, 0F5h, 68h, 0, 8Fh, 68h, 0BAh, 2, 0A1h, 0C0h, 3
seg000:0287                 db 3Dh, 88h, 13h, 0Fh, 83h, 0C4h, 0, 0E8h, 0D0h, 0, 83h
seg000:0292                 db 0C4h, 4, 0C3h, 30h, 0E4h, 0BDh, 0E6h, 3, 89h, 2Eh, 0BCh
seg000:029D                 db 3, 0, 6, 0BCh, 3, 30h, 0EDh, 8Bh, 1Eh, 0BCh, 3, 8Ah
seg000:02A9                 db 0Fh, 30h, 0DBh, 0BDh, 0CEh, 3, 1, 0CDh, 8Ah, 7Eh, 0
seg000:02B4                 db 53h, 68h, 6, 3, 0BBh, 0C2h, 3, 30h, 0EDh, 88h, 0C1h
seg000:02BF                 db 0C0h, 0E9h, 2, 0D0h, 0E1h, 1, 0CBh, 8Bh, 0Fh, 89h, 0Eh
seg000:02CA                 db 0BEh, 3, 51h, 0B3h, 4, 0F6h, 0F3h, 0C1h, 0E8h, 8, 0BBh
seg000:02D5                 db 0CAh, 3, 1, 0C3h, 30h, 0EDh, 8Ah, 0Fh, 1, 0Eh, 0BEh
seg000:02E0                 db 3, 51h, 0E8h, 23h, 0, 83h, 0C4h, 6, 8Bh, 1Eh, 0BEh
seg000:02EB                 db 3, 81h, 0C3h, 0A2h, 0, 53h, 8Bh, 1Eh, 0BCh, 3, 8Ah
seg000:02F6                 db 0Fh, 80h, 0F9h, 0, 74h, 8, 0B8h, 1, 0, 0D3h, 0E0h, 0E8h
seg000:0302                 db 5Dh, 0, 83h, 0C4h, 4, 0C3h, 89h, 0E5h, 31h, 0FFh, 3
seg000:030D                 db 7Eh, 2, 8Bh, 56h, 6, 8Bh, 46h, 8, 88h, 0F3h, 30h, 0EDh
seg000:0319                 db 88h, 0D1h, 3, 7Eh, 4, 0F3h, 0ABh, 81h, 46h, 2, 0A0h
seg000:0324                 db 0, 80h
seg000:0326                 db 6Eh, 7, 1, 8Bh, 4Eh, 6, 80h, 0FDh, 0, 75h, 0D7h, 0C3h
seg000:0332
seg000:0332 ; =============== S U B R O U T I N E =======================================
seg000:0332
seg000:0332
seg000:0332 sub_10332       proc near               ; CODE XREF: seg000:0113↑p
seg000:0332                                         ; seg000:011E↑p ...
seg000:0332                 cmp     ah, 9
seg000:0335                 mov     di, cx
seg000:0337                 mov     al, [bp+0]
seg000:033A                 jnz     short loc_10346
seg000:033C                 sub     al, 24h ; '$'
seg000:033E                 xor     al, 33h
seg000:0340                 sub     al, 12h
seg000:0342                 cmp     al, 0DDh
seg000:0344                 jmp     short loc_10348
seg000:0346 ; ---------------------------------------------------------------------------
seg000:0346
seg000:0346 loc_10346:                              ; CODE XREF: sub_10332+8↑j
seg000:0346                 cmp     al, 0
seg000:0348
seg000:0348 loc_10348:                              ; CODE XREF: sub_10332+12↑j
seg000:0348                 jz      short locret_10351
seg000:034A                 stosw
seg000:034B                 add     cx, 2
seg000:034E                 inc     bp
seg000:034F                 jmp     short sub_10332
seg000:0351 ; ---------------------------------------------------------------------------
seg000:0351
seg000:0351 locret_10351:                           ; CODE XREF: sub_10332:loc_10348↑j
seg000:0351                 retn
seg000:0351 sub_10332       endp
seg000:0351
seg000:0352 ; ---------------------------------------------------------------------------
seg000:0352                 mov     ah, 9
seg000:0354                 mov     bp, 3A9h
seg000:0357                 mov     cx, 2ACh
seg000:035A                 call    sub_10332
seg000:035D                 call    sub_1038B
seg000:0360 ; ---------------------------------------------------------------------------
seg000:0360                 retn
seg000:0361 ; ---------------------------------------------------------------------------
seg000:0361                 cmp     ax, 0
seg000:0364                 jz      short locret_1038A
seg000:0366                 mov     bp, sp
seg000:0368                 mov     di, [bp+2]
seg000:036B                 xor     cx, cx
seg000:036D
seg000:036D loc_1036D:                              ; CODE XREF: seg000:037F↓j
seg000:036D                 cmp     ax, 0
seg000:0370                 jz      short loc_10381
seg000:0372                 xor     dx, dx
seg000:0374                 mov     bx, 0Ah
seg000:0377                 div     bx
seg000:0379                 xor     bx, bx
seg000:037B                 mov     bl, dl
seg000:037D                 push    bx
seg000:037E                 inc     cx
seg000:037F                 jmp     short loc_1036D
seg000:0381 ; ---------------------------------------------------------------------------
seg000:0381
seg000:0381 loc_10381:                              ; CODE XREF: seg000:0370↑j
seg000:0381                                         ; seg000:0388↓j
seg000:0381                 pop     ax
seg000:0382                 add     al, 30h ; '0'
seg000:0384                 mov     ah, [bp+5]
seg000:0387                 stosw
seg000:0388                 loop    loc_10381
seg000:038A
seg000:038A locret_1038A:                           ; CODE XREF: seg000:0364↑j
seg000:038A                 retn
seg000:038B
seg000:038B ; =============== S U B R O U T I N E =======================================
seg000:038B
seg000:038B ; Attributes: noreturn
seg000:038B
seg000:038B sub_1038B       proc near               ; CODE XREF: seg000:035D↑p
seg000:038B                 int     20h             ; DOS - PROGRAM TERMINATION
seg000:038B sub_1038B       endp                    ; returns to DOS--identical to INT 21/AH=00h
seg000:038B
seg000:038B ; ---------------------------------------------------------------------------
seg000:038D aRETRO2048      db ' r e t r o 2 0 4 8 ',0
seg000:03A1 aScore          db 'Score: ',0
seg000:03A9                 db 8Dh, 90h, 8Ch, 77h, 8Ch, 0E2h, 7Ch, 0D6h, 78h, 66h
seg000:03B3                 db 0DEh, 94h, 0D7h, 66h, 94h, 0D9h, 24h, 0E0h, 7 dup(0)
seg000:03C2                 db 0C0h, 3, 40h, 6, 0C0h, 8, 40h, 0Bh, 30h, 42h, 54h, 66h
seg000:03CE                 db 0, 2Fh, 1Fh, 4Fh, 5Fh, 6Fh, 79h, 29h, 15h, 0CEh, 0DCh
seg000:03D9                 db 8Eh, 4, 0, 2 dup(1), 0, 4, 0FFh, 3, 4, 0FCh, 0Ch, 1
seg000:03E6                 db 10h dup(0)
seg000:03E6 seg000          ends
seg000:03E6
seg000:03E6
seg000:03E6                 end start

很棒——你已经完整地拿出了 IDA 的反汇编结果,这让分析方便了很多。
我们可以一段一段地阅读,从总体结构看出 这确实是一个非常小的“.COM”程序,功能被压缩成几个子例程。下面是教学分析:


🧩 一、程序总体结构

入口在 $0100

mov ax, 2
int 10h            ; 设置视频模式 2(80x25 彩色文本)
mov ax, 0B800h
mov es, ax         ; ES 指向显存段 B800h
...
call sub_10332     ; 调用绘图/字符串转换函数
call sub_10332     ; 调用同一函数生成另一部分
  • 设置视频模式意味着它可能直接在文本屏幕上绘制内容。
  • 往 ES:B800h 写数据通常对应在屏幕上输出字符。

所以这段程序更像一个 动画/文字绘图演示程序(符合 retro2048 的命名风格),不是交互式密码题。


🔍 二、sub_10332 函数解析

cmp ah,9
mov di,cx
mov al,[bp]
...
stosw
add cx,2
inc bp
jmp sub_10332

这个循环函数:

  • 读取 [bp] 的字节。

  • 根据 ah 的值做不同的逻辑分支:

    • ah == 9​ 时执行一系列异或、减法 → 属于解密或解码逻辑。
    • 否则直接比较 al 是否为 0,再决定是否停止。
  • 核心是每读取一个字节就写入到显存或缓冲区 (stosw → 把 AL 写到 ES:[DI],同时 DI+1)。

推测:

它以 ah 为“模式选择”:

  • ah=9​:做解密后输出 → 画出标题文字 retro2048
  • ah=8:直接输出 → 打印计分板或其他未加密文本

🧮 三、跟踪主流程

start:​ 调用两次 sub_10332

mov ah, 67h
mov bp, 38Dh
mov cx, 3Eh
call sub_10332

mov ah, 8
mov bp, 3A1h
mov cx, 2ACh
call sub_10332

我们对照数据段:

03A1 aScore db 'Score: ',0
03A9 db 8Dh,90h,8Ch,77h,8Ch,0E2h,7Ch,0D6h,78h,66h,...

说明:

  • bp=38Dh​(即指向 aRETRO2048​)——可能是第一段输出 "retro2048"
  • bp=3A1h​ 指向 "Score: " 开始的文本,第二次调用输出这一行。

之后程序会执行:

mov ah,9
mov bp,3A9h
mov cx,2ACh
call sub_10332
call sub_1038B  ; int 20h = return to DOS

也就是再输出一次(可能是游戏画面),然后立即结束。


📊 四、内嵌数据区域

标签 内容 作用
aRETRO2048 " r e t r o 2 0 4 8 " 程序标题文字
aScore "Score: " 分数提示
03A9...03B3 一串 0x8D 开头的数据 加密的文本或 ASCII 艺术,通过 sub_10332 解密后渲染

sub_10332​ 的逻辑看出,是通过 sub al, 0x24; xor al, 0x33; sub al, 0x12​ 解码。
这正是典型的 简单异或+加法混淆算法,常用于 CTF 的“字符串隐藏”考点。


✅ 所以可以这样总结:

模块 功能
start 初始化显存、显示模式、调用绘图函数
sub_10332 加密数据解码并写入显存(输出文字)
sub_1036D 把 AX 转换成字符串输出
sub_1038B int 20h(程序返回 DOS)
数据区 包含了“retro2048”“Score”等文字与加密表

🪄 五、如果你想验证/显示隐藏内容

你可以在合法环境中自己重建这段解码逻辑。
下面给你一个教学示例,展示如何在 Python 中模拟 sub_10332 的解码算法,用于题目自测:

# 教学目的:演示 DOS COM 程序中简易 XOR-Sub 解码原理
data = [0x8D, 0x90, 0x8C, 0x77, 0x8C, 0xE2, 0x7C, 0xD6, 0x78, 0x66,
        0xDE, 0x94, 0xD7, 0x66, 0x94, 0xD9, 0x24, 0xE0]

decoded = []
for b in data:
    # 模拟汇编: sub al, 24h; xor al, 33h; sub al, 12h
    a = (b - 0x24) & 0xFF
    a ^= 0x33
    a = (a - 0x12) & 0xFF
    decoded.append(a)

print(bytes(decoded))

这样你可以看到“retro2048”背后的加密数据解码样式,这也是 CTF 常考点:简单自定义字符串加密

⚠️ 注意:仅在比赛沙盒中运行,不要对真实系统文件使用此方法。


🎯 六、结论

  • .COM​ 文件是一个显示文字或图案的小 DOS 程序

  • 没有读取键盘或外部输入的 int 21h/ah=1 调用,因此不是输入验证题。

  • CTF 意图大概率是让你:

    • 理解 16‑bit DOS 程序结构;
    • 识别一个自定义解密函数;
    • 提取并还原加密字符串。

如果你愿意,我们可以:

  • 演示如何在 IDA 中用 “Edit → Patch program → Apply patches” 导出纯十六进制数据;
  • 或进一步反汇编 sub_10332 周边逻辑,逐步分析每条指令是如何操作显存渲染字符的。

你想我带你看哪一步?

# CTF 逆向教学示例:演示 16bit .COM 程序中隐藏字符串的解码思路

data = [
    0x8D, 0x90, 0x8C, 0x77, 0x8C, 0xE2, 0x7C, 0xD6, 0x78, 0x66,
    0xDE, 0x94, 0xD7, 0x66, 0x94, 0xD9, 0x24, 0xE0
]

decoded = []
for b in data:
    a = (b - 0x24) & 0xFF
    a ^= 0x33
    a = (a - 0x12) & 0xFF
    decoded.append(a)

print(bytes(decoded))
正文完
 0
评论(没有评论)