1

我正在参加保险箱比赛,我得到了这个保险箱:

start:
add     ds:0DEDh, ax
xor     cx, cx
loop    start

据我了解,cx 将在循环结束时为 0,并在下一次迭代时变为 FFFF。我也知道 0xCCh 是一条会停止程序的非法指令。我怎样才能破解这个保险箱?

**编辑:这里的目标是停止这个无限循环。循环没有停止项,我需要以某种方式使其停止使用逆向工程。例如:这是一个简单的保险箱

safe:
  mov     ax, ds:4D2h
  cmp     ax, 1000h
  jl      safe 

这是它的关键,使用逆向工程编写:

mov bx, 1000h
mov [4D2h], bx    
l:
    jmp l

这种保险柜钥匙的模拟是在Core Wars 8086 引擎内部完成的。安全钥匙都是战争幸存者的规则如下:

幸存者无法在固定地址上加载,因为游戏引擎每轮都将它们加载到随机地址。生成的程序必须是 COM 而不是 EXE,并且只包含 8086 指令。

每个幸存者都会收到一组自己的完整寄存器(寄存器),其他幸存者无法访问。此外,每个幸存者都有一个 2048 字节的“个人”堆栈,其他幸存者也无法访问。

在运行第一轮游戏之前,游戏引擎将竞技场中的所有字节初始化为值 0CCh(注意:该字节值是“不支持”指令 - 详情如下)。然后引擎将每个幸存者加载到竞技场内存中的随机位置,即 - 完全按原样复制幸存者文件的内容。两个幸存者之间的距离,以及幸存者与竞技场边缘之间的距离,保证至少为 1024 字节。每个幸存者的代码最多有 512 个字节。

在第一轮之前,游戏引擎将(每个幸存者的)寄存器初始化为以下值:

  • BX、CX、DX、SI、DI、BP - 重置。
  • 标志 - 重置。
  • AX, IP - 初始幸存者的位置,游戏引擎加载幸存者的竞技场中的随机偏移量。
  • CS, DS - 所有幸存者共有的竞技场部分。
  • ES - 同一组的幸存者共享的内存段(见高级技术)。
  • SS - 幸存者个人堆栈的开始部分。
  • SP - 偏移 幸存者个人堆栈的开始。

此时游戏以回合开始,每一回合运行游戏引擎运行每个幸存者的下一条指令,直到游戏结束:在 200,000 回合之后,或者当一个幸存者留在竞技场时。幸存者在每一轮中的出场顺序是在游戏开始时随机确定的,在游戏中不会改变。

在以下情况下,幸存者将被取消资格:

  • 运行非法指令(例如:字节 060h,它不会翻译成任何汇编指令)。
  • 游戏引擎运行“不支持”指令(例如:“INT 021h”)。游戏引擎会阻止试图启动与操作系统或计算机硬件的直接通信的运行指令。尝试访问不在竞技场范围内的内存,也不在幸存者的“个人”堆栈范围内。
  • 攻击其他幸存者是通过在竞技场内存中写入有关他们的代码的信息来完成的(为了让他们执行上述三个动作之一),从而取消他们的资格。因此,早些时候,人们必须找到他们藏身的地方:)
4

2 回答 2

5

虽然AX有一个随机值,但它确实有意义。那意思是:

  • AX, IP - 初始幸存者的位置,游戏引擎加载幸存者的竞技场中的随机偏移量。

AX = IP,这是保险箱在内存中加载的指令指针。我们所要做的就是用强制安全退出(死)的东西来更新循环中的第一条指令。这可以通过根据文档将字节值 0x60 1写入该内存地址来完成。由于safe的循环也是程序的开始,我们只需要检索safeAX值并使用它来覆盖该内存地址。

如果他们刚刚将 AX 写入内存地址 0x0DED,那么获得safeAX将是微不足道的,但他们不断将AX添加到内存中的前一个 WORD(16 位值)。这意味着为了弄清楚safeAX值是多少,我们需要读取两次,然后从读取的第二个值中减去读取的第一个值。我们还必须以这样一种方式进行 2 次读取,以使我们知道safe在两次读取之间准确地更新了一次。Core Ware引擎的规则说:

此时游戏以回合开始,每一回合运行游戏引擎运行每个幸存者的下一条指令,直到游戏结束:在 200,000 回合之后,或者当一个幸存者留在竞技场时。幸存者在每一轮中的出场顺序是在游戏开始时随机确定的,在游戏中不会改变。

这意味着每一轮指令都由safekey执行。由于safe的循环是 3 条指令:

start:
    add     ds:0DEDh, ax ; Instruction 1
    xor     cx, cx       ; Instruction 2
    loop    start        ; Instruction 3

我们保证[0x0DED]每 4 条指令读取 2 个不同的值。现在我们知道了这一点,它变得相对容易。我们可以通过实现它来简化汇编secondreadAX - firstreadAX代码(-firstreadAX) + secondreadAX。考虑到这一点,执行 2 的解决方案分开读取四个指令并使用 0x60 更新safe代码的开始(及其循环的开始)可能看起来像(在 NASM 语法中):

; Assemble with:
;     nasm -f bin key.asm -o key

start:
    mov bx, [0x0DED] ; Get the WORD from [0x0DED]
    neg bx           ; Negate it. BX=(-firstreadAX)
    nop              ; Need to wait at least one more instruction (3 total)
                     ;     before trying to read 0x0DED again
    add bx, [0x0DED] ; Add the current WORD value at [0x0DED] with BX
                     ;     safeAX = -BX+[0x0DED] = [0x0DED]-BX
                     ;  or safeAX=(-firstreadAX)+secondreadAX = secondreadAX-firstreadAX
    mov byte [bx], 0x60
                     ; Overwrite the first instruction of safe with 0x60
                     ;     to terminate the safe.
    jmp $            ; Infinite loop

在 TASM/MASM(v6.00+)/JWASM 中,代码如下所示:

.model tiny
.code

start:
    mov bx,[ds:0DEDh]; Get the WORD from [0DEDh]
    neg bx           ; Negate it. BX=(-firstreadAX)
    nop              ; Need to wait at least one more instruction (3 total)
                     ;     before trying to read 0DEDh again
    add bx,[ds:0DEDh]; Add the current WORD value at [0DEDh] with BX
                     ;     safeAX=-BX+[0DEDh]=[0DEDh]-BX
                     ;  or safeAX=(-firstreadAX)+secondreadAX = secondreadAX-firstreadAX
    mov byte ptr [bx], 060h
                     ; Overwrite the first instruction of safe with 060h
                     ;     to terminate the safe.
    jmp $            ; Infinite loop

END

脚注

  • 1 8086 不支持的任何操作码都会终止幸存者,这包括 0x60、0x66、0x67 等。INT30xcc ( )、0xce ( INTO) 和 0xf1 ( )等有效的 8086 单字节操作码INT1也会退出,因为它们是 Core Wars 引擎中不受支持的陷阱。调用 Core Wars 引擎(如 DOS)不支持的软件中断INT 21h也会导致幸存者失败。
于 2020-12-11T16:31:39.380 回答
3

这里的目标是停止这个无限循环。循环没有停止项,我需要以某种方式使其停止使用逆向工程

目前还不清楚你能做什么和不能做什么。以下是只需要您更改单个字节的解决方案。

xor cx, cx到无害mov cx, cx将不再重置循环计数器,因此循环将在一段时间后结束(取决于CX我们不知道的初始值)。
操作码为mov cx, cx89h。我们不需要更改 modr/m 字节,因为两条指令的值相同。

mov byte [cs:start+4], 89h

验证汇编器是否不包含其他冗余的DS:段覆盖前缀可能很有用,因为如果是这种情况,您将不得不编写mov byte [cs:start+5], 89h.

于 2020-12-09T20:58:28.177 回答