Сборка x86 Core Wars Safe Challenge (вычесть ядро)

Я участвую в соревнованиях по сейфам, и мне достался вот такой сейф:

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» , тогда мне просто нужно сделать neg ax и поместить в адрес 0A2h значение ax после neg. Тогда ax-ax = 0. Вот код, который я построил:

nop
nop
nop
nop
nop
nop
nop
mov ax, [0x00A2]
neg ax
key:
    mov [0x00A2], ax
    jmp key

Код работает, но только в половине случаев:


Эта симуляция сейфа и ключа выполнена внутри движка Core Wars 8086 . Правила таковы, когда и сейфом, и ключом являются выжившие на войне:

Выжившие не могут размещать нагрузку на фиксированные адреса, потому что игра движок загружает их каждый ход по случайному адресу. Программы, которые должны быть COM, а не EXE и содержать только 8086 инструкций.

Каждый выживший получает набор собственных полных регистров. (регистры), который не доступен для других выживших. В Кроме того, у каждого выжившего есть «личный» стек размером 2048 байт, что составляет также недоступны для других выживших.

Перед запуском первого раунда игры движок игры инициализирует все байты на арене значением 0CCh (примечание: это значение байта является «неподдерживаемой» инструкцией — подробности ниже). Затем двигатель загружает каждого выжившего в случайное место в памяти арены, т.е. копирует содержимое файла оставшегося в живых точно так, как оно есть. расстояние между двумя выжившими, а также расстояние между выживший и край арены, гарантировано не менее 1024 байт. Код для каждого выжившего имеет максимум 512 байт.

Перед первым раундом игровой движок инициализирует регистры (из каждого выжившего) до следующих значений:

  • BX, CX, DX, SI, DI, BP - сброс.
  • Флаги - Сбросить.
  • AX, IP - Позиция начального выжившего, случайное смещение на арене, в которое выживший загружается движком игры.
  • CS, DS - Сегмент арены общий для всех выживших.
  • ES — Сегмент (сегмент) для памяти, разделяемой выжившими из одной группы (см. Advanced Techniques).
  • СС - Начальный раздел личного стека выжившего.
  • SP - Offset Начало личного стека выжившего.

С этого момента игра начинается в раундах, в каждом раунде игровой движок запускает следующую инструкцию для каждого выжившего до конца. игры: после 200 000 раундов или когда остался хоть один выживший на арене. Порядок, в котором выжившие будут играть в каждом раунде определяется в начале игры случайным образом, а не меняться во время него.

Оставшийся в живых дисквалифицируется в следующих случаях:

  • Запуск недопустимой инструкции (пример: байт 060h, который не транслируется ни в какую ассемблерную инструкцию).
  • Запуск «неподдерживаемой» инструкции игровым движком (пример: «INT 021h»). Игровой движок предотвращает запуск инструкций, которые пытаются инициировать прямая связь с операционной системой или компьютерным оборудованием. Попытка получить доступ к памяти, которая находится за пределами области арены, и не входит в сферу «личного» стека выжившего.
  • Атака других выживших осуществляется путем записи информации об их коде в память арены (чтобы заставить их выполнить одно из действий). выше трех действий), и, следовательно, их дисквалификацию. Ранее, значит надо найти где они прячутся :)

Ваш key кажется не на своем месте. Я думаю, что вы хотите, чтобы заново сделать расчет каждый раз.

Jester 17.12.2020 13:11

После второго цикла значение регистра оси не меняется... В любом случае, если мне нужно каждый раз вычислять, как я получил 50 50?

Osher Berger 17.12.2020 18:08
stackoverflow.com/questions/40438971/assembly-safe-competiti‌​на здесь есть ответ.
Osher Malka 17.12.2020 18:50
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
731
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

l: 
   mov bx, 0a2h 
   mov dx, 0xffff            
   mov word [bx], dx
   nop
   nop
   mov ax, word [bx]
   sub dx, ax 
   mov word [bx], dx 
   mov dx, 0xffff 
   jmp l  

попробуй это.

Ответ принят как подходящий

Я думаю, вы на правильном пути. Вы заметили, что все вычисления до входа сейфа в цикл можно игнорировать (это отвлекающий маневр). Важно понимать, что после того, как цикл в сейфе будет выполнен один раз, все последующие циклы всегда будут вычитать одно и то же значение. Что вам нужно сделать, так это убедиться, что мы игнорируем первое значение, которое сейф записывает в [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

Другие вопросы по теме