Assembly safes and keys- why it won't work?

谁说我不能喝 提交于 2021-02-11 08:41:44

问题


So we have like this safes challenge in assembly, you need to create safes and keys that will break them and end the infinite loop. Here's an example for a safe:

loopy:
mov ax, [1900]
cmp ax,1234
jne loopy

and a key:

loopy2:
mov ax, 1234
mov [1900],ax
jmp loopy2

So I have a safe and a key, and I don't understand why it doesn't work:

here's my safe:

org 100h
mySafe:  
mov dx,5
mov ax, [5768h] 
mov bx,7 
mov word [180h],2
mul word [180h]
mov [180h],bx
push ax
dec bx
mov cx,dx
mov ax,dx
loopy1:
add bx,ax
loop loopy1
dec bx
pop ax
add ax,bx
mul word [180h]
cmp ax,350
jne mySafe

And here's my key:


org 100h
loopy:
mov word [5768h],10
jmp loopy


ret

The right answer to break the loop should be 10 and it works when I put in on the safe, somehow with the key it doesn't work and I can't figure out why.. (the "word" is needed for nasm)


回答1:


The value in dx used as the counter for the loop instruction comes from the first mul instruction.

This multiplication is just doubling the key, so dx is either 0 or 1 (an easy way to see this is to think of the multiplication as a left shift by one or by remembering that the sum of two n-bit numbers has at most n+1 bits)


If dx is zero, the whole loopy1 block does nothing (as dx also sets ax) and the value in ax at the end of the safe is 7*(5 +2k) where k is the key (see the commented code below).

It is then easy to see that 350 = 7*(5+2k) => 2k = 45 has no solution. Therefore no key for which dx is zero can unlock the safe.
A key has dx 0 iif its value is less than 32768 (again, this is easy to see when thinking of the multiplication as a left shift by one).

Corollary: 10 cannot be a solution.

safe:
  mov dx,5
  mov ax, [k]               ;ax = k (key)
  mov bx,7 
  mov word [aux],2    
  mul word [aux]            ;dx = 0 ax = 2k
  mov [aux],bx              ;aux = 7
  push ax                   ;ax = 2k
  dec bx                    ;bx = 6 
  dec bx                    ;bx =    5
  pop ax                    ;ax = 2k
  add ax,bx                 ;ax = 5 + 2k
  mul word [aux]            ;ax = 7*(5 +2k)

  cmp ax,350
  ret 

If there is a key that unlocks the safe then it must be greater or equal to 32768 so that dx is 1 after the first multiplication. With this condition, the value in ax at the end of the safe can be written as 7*(6 + (2k & 0xffff)) => k & 0x7fff = 22.
Adding the condition stated at the very beginning of this section, the final value for k is 32768 + 22 = 32790 or 0x8016 in hex. I've leaped quite a few logical steps in manipulating the equation and forming the result but, again, thinking of 2k as a shift may help visualize them.

Corollary: Due to the algebraic structure involved, this is the only solution.

safe:
  mov dx,5
  mov ax, [k]           ;ax = k
  mov bx,7 
  mov word [aux],2    
  mul word [aux]            ;dx:ax = 2k
  mov [aux],bx              ;[aux] = 7
  push ax                   ;dx = 1 ax = 2k & 0xffff
  dec bx                    ;bx = 6 
  mov cx,dx                 ;cx = 1
  mov ax,dx                 ;ax = 1
loopy1:
  add bx,ax                 ;bx = 6 + 1
  dec cx
jnz loopy1
  dec bx                    ;bx = 6 
  pop ax                    ;ax = 2k & 0xffff
  add ax,bx                 ;ax = 6 + (2k & 0xffff)
  mul word [aux]            ;ax = 7*(6 + (2k & 0xffff))

  cmp ax,350
  ret 

Considering that you have a mov dx, 5 before the first multiplication, did you (or the author of the safe) forget that mul affects dx?
If you wrap the first mul in push dx / pop dx (or just move mov dx, 5 after it), you would get, at the end of the safe, a value in ax equals to 7*(30 +2k) which implies k = 10 indeed.



来源:https://stackoverflow.com/questions/59512527/assembly-safes-and-keys-why-it-wont-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!