Assembly 汇编x86核心战争安全挑战(减去核心)

Assembly 汇编x86核心战争安全挑战(减去核心),assembly,x86,nasm,x86-16,corewars,Assembly,X86,Nasm,X86 16,Corewars,我正在参加保险箱比赛,我得到了这个保险箱: and al, 0FEh push ax clc mul ax xor ax, dx or al, 1 loc_A: sub ds:0A2h, ax pop ax push ax jnz loc_A ends 据我所知,为了进入保险箱,我需要在子操作后获得零,以便保险箱停止运行 所以我想做的解决方案是,在子运算之后,取地址0A2h处的值,然后把它放到ax寄存器中,然后我在ax寄存器中有保险库的ax的负值,即“

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

and al, 0FEh
push ax
clc
mul ax
xor ax, dx
or al, 1

loc_A:
    sub ds:0A2h, ax
    pop ax
    push ax
    jnz loc_A
    ends
据我所知,为了进入保险箱,我需要在子操作后获得零,以便保险箱停止运行

所以我想做的解决方案是,在子运算之后,取地址0A2h处的值,然后把它放到ax寄存器中,然后我在ax寄存器中有保险库的ax的负值,即“-ax”,然后我只需要做neg ax,然后把地址0A2h处的值放到neg后面。那么ax=0。这就是我构建的代码:

nop
nop
nop
nop
nop
nop
nop
mov ax, [0x00A2]
neg ax
key:
    mov [0x00A2], ax
    jmp key
代码正在运行,但只有一半的时间:


保险箱和钥匙的模拟是在内部完成的。保险箱和钥匙都是战争幸存者的情况如下:

幸存者不能在固定地址上加载,因为游戏 引擎每转一圈将它们加载到一个随机地址。那些节目 生成的必须是COM而不是EXE,并且只包含8086指令

每个幸存者都会收到一套自己的完整寄存器 (登记册),其他幸存者无法访问。在里面 此外,每个幸存者都有一个2048字节的“个人”堆栈,即 其他幸存者也无法进入

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

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

  • BX、CX、DX、SI、DI、BP-重置
  • 标志-重置
  • AX,IP-初始幸存者的位置,由游戏引擎加载幸存者的竞技场中的随机偏移量
  • CS,DS-竞技场中所有幸存者共有的部分
  • ES-同一组幸存者共享的记忆片段(见高级技术)
  • SS-幸存者个人堆栈的开始部分
  • SP-偏移幸存者个人堆栈的开始
在这一点上,游戏开始轮,每轮运行游戏引擎运行每个幸存者的下一条指令,直到结束 游戏规则:20万回合后,或者只有一个幸存者 在竞技场上。幸存者在每轮比赛中的顺序 是在游戏开始时随机确定的,而不是 在这期间改变

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

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


试试看。

我认为你的思路是对的。您已经注意到,在保险箱进入循环之前的所有计算都可以忽略(它们是一种误导)。需要了解的重要一点是,在保险柜中的循环完成一次后,所有后续循环将始终减去相同的值。您需要做的是确保忽略安全写入[0A2h]的第一个值,然后一旦知道它已写入[0A2h],我们将[0A2h]归零,然后等待它再次写入[0A2h],然后在内存中对该值求反。一旦否定,保险柜将退出循环,因为保险柜中的减法结果将为0,循环条件将退出。应该工作的NASM代码是:

start:
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    ; At this point the safe is guaranteed to have written to [0A2h] exactly once
    ; Zero out the value at [0A2h]
    mov word [0A2h], 0
    nop
    nop
    nop
    ; At this point the safe is guaranteed to have written to [0A2h] exactly twice
    ; Negate the value at [0A2h] so that safe will exit (SUB will result in value 0)
    neg word [0a2h]

    ; End in an infinite loop
    jmp $
MASM(6.x+)/TASM/JWASM版本应为:

.model tiny
.code

start:
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    ; At this point the safe is guaranteed to have written to [0A2h] exactly once
    ; Zero out the value at [0A2h]
    mov word ptr [ds:0A2h], 0
    nop
    nop
    nop
    ; At this point the safe is guaranteed to have written to [0A2h] exactly twice
    ; Negate the value at [0A2h] so that safe will exit (SUB will result in value 0)
    neg word ptr [ds:0a2h]

    ; End in an infinite loop
    jmp $

end

我认为你在正确的轨道上。您已经注意到,在保险箱进入循环之前的所有计算都可以忽略(它们是一种误导)。需要了解的重要一点是,在保险柜中的循环完成一次后,所有后续循环将始终减去相同的值。您需要做的是确保忽略安全写入[0A2h]的第一个值,然后一旦知道它已写入[0A2h],我们将[0A2h]归零,然后等待它再次写入[0A2h],然后在内存中对该值求反。一旦否定,保险柜将退出循环,因为保险柜中的减法结果将为0,循环条件将退出。应该工作的NASM代码是:

start:
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    ; At this point the safe is guaranteed to have written to [0A2h] exactly once
    ; Zero out the value at [0A2h]
    mov word [0A2h], 0
    nop
    nop
    nop
    ; At this point the safe is guaranteed to have written to [0A2h] exactly twice
    ; Negate the value at [0A2h] so that safe will exit (SUB will result in value 0)
    neg word [0a2h]

    ; End in an infinite loop
    jmp $
MASM(6.x+)/TASM/JWASM版本应为:

.model tiny
.code

start:
    nop
    nop
    nop
    nop
    nop
    nop
    nop
    ; At this point the safe is guaranteed to have written to [0A2h] exactly once
    ; Zero out the value at [0A2h]
    mov word ptr [ds:0A2h], 0
    nop
    nop
    nop
    ; At this point the safe is guaranteed to have written to [0A2h] exactly twice
    ; Negate the value at [0A2h] so that safe will exit (SUB will result in value 0)
    neg word ptr [ds:0a2h]

    ; End in an infinite loop
    jmp $

end

您的
键似乎放错了位置。我想你每次都想重新计算。在第二次循环后,ax寄存器值不会改变。。。不管怎样,如果我每次都要计算我是怎么得到50的?这里有答案。你的
键似乎放错地方了。我想你每次都想重新计算。在第二次循环后,ax寄存器值不会改变。。。不管怎样,如果我每次都要计算我是怎么得到50的?这里有答案。哇,非常感谢!!哇,非常感谢!!