On Fri, Apr 22, 2011 at 12:55:32PM -0400, Kragen Javier Sitaker wrote:
> I haven't successfully run it yet.

Okay, now I have run it. It works perfectly. Brilliantly done.

Here is my analysis of how it works, and in particular why certain
things are done the way they are.  This would be spoilery to anyone who
wants the fun of reverse-engineering the code themselves, so those
people shouldn't read the rest of this message.

-- Spoilers below --







































    
    $ cat E.COM
    
    jUX4UPYhUUX5UTP_h@@Z0u1QZJ0u=0uCh//Z!UHhOOZ!UHkUHPG2UHhURX5UP2!hULX2!A
    
    $ xxd < E.COM
    
    0000000: 6a55 5834 5550 5968 5555 5835 5554 505f  jUX4UPYhUUX5UTP_
    0000010: 6840 405a 3075 3151 5a4a 3075 3d30 7543  h@@Z0u1QZJ0u=0uC
    0000020: 682f 2f5a 2155 4868 4f4f 5a21 5548 6b55  h//Z!UHhOOZ!UHkU
    0000030: 4850 4732 5548 6855 5258 3555 5032 2168  HPG2UHhURX5UP2!h
    0000040: 554c 5832 2141 0d0a                      ULX2!A..
    
    $ objdump -D -m i8086 -b binary E.COM
    
    E.COM:     file format binary
    
    
    Disassembly of section .data:
    
    00000000 <.data>:
    (Keep in mind this is actually address 0x0100, not 0000.  Objdump has an 
option --adjust-vma=0x0100
    that avoids this problem, but I didn't know about it until now.)
       0:   6a 55                   push   $0x55
       2:   58                      pop    %ax           ax ← 0x0055
       3:   34 55                   xor    $0x55,%al     ax ← 0 (so jUX4U does 
ax ← 0)
       5:   50                      push   %ax
       6:   59                      pop    %cx           cx ← 0 (so PY copies 
ax to cx.  We can't xor
                                                         directly into cx 
because the instruction
                                                         encoding for that 
would be 83 f1 55, not 34 55,
                                                         and 83 and f1 are both 
non-ASCII bytes.)
       7:   68 55 55                push   $0x5555       (h rather than j to 
push a full 16-bit word)
       a:   58                      pop    %ax           ax ← 0x5555
       b:   35 55 54                xor    $0x5455,%ax   ax ← 0x0100 (start 
address of the program;
                                                         so hUUX5UT does ax ← 
0x0100; presumably
                                                         hoaX5o` and haxX5ay, 
among other combinations,
                                                         would do the same 
thing)
       e:   50                      push   %ax 
       f:   5f                      pop    %di           di ← 0x0100 (so P_ 
copies ax to di. Similar
                                                         ASCII considerations 
apply to xoring directly
                                                         into di: 81 f7 55 54.)
      10:   68 40 40                push   $0x4040
      13:   5a                      pop    %dx           dx ← 0x4040
      14:   30 75 31                xor    %dh,0x31(%di) change multiplier at 
address 0x131 from 0x50 to 0x10
      17:   51                      push   %cx           pushing 0
      18:   5a                      pop    %dx           dx ← 0      (so QZ 
copies cx to dx)
      19:   4a                      dec    %dx           dx ← 0xffff
      1a:   30 75 3d                xor    %dh,0x3d(%di) invert byte at 0x13d 
from 0x32 (xor) to 0xcd
                                                         (interrupt, 
specifically interrupt 21h)
      1d:   30 75 43                xor    %dh,0x43(%di) inverting byte at 0x43 
(another 0x32 that
                                                         becomes interrupt 21h)
      20:   68 2f 2f                push   $0x2f2f       
      23:   5a                      pop    %dx           dx ← 0x2f2f
      24:   21 55 48                and    %dx,0x48(%di) clear top the bits 
xx.x.... on the two bytes
                                                         after the end of the 
program
      27:   68 4f 4f                push   $0x4f4f
      2a:   5a                      pop    %dx
      2b:   21 55 48                and    %dx,0x48(%di) clear the bits 
x.xx.... on the same bytes; now
                                                         only their low-order 
nibbles remain set.
      2e:   6b 55 48 50             imul   $0x50,0x48(%di),%dx
                                                         remember that the 
instruction at 0x14 changed
                                                         the multiplier to 
0x10, so this is putting the
                                                         byte past the end of 
the program into dl, but
                                                         shifted left by four 
bits. (Also, the byte
                                                         after it goes into dh.)
      32:   47                      inc    %di           
      33:   32 55 48                xor    0x48(%di),%dl This snarfs the byte 
at 0x49, whose low-order
                                                         nibble might have set 
bits in it, and combines
                                                         it with the byte from 
0x48 that is already in
                                                         %dl.
      36:   68 55 52                push   $0x5255
      39:   58                      pop    %ax           ax ← 0x5255
      3a:   35 55 50                xor    $0x5055,%ax   ax ← 0x0200, and in 
particular ah ← 0x02, the
                                                         interrupt 21h code to 
output a character to
                                                         standard output.  So 
hURX5UP is ax ← 0x0200.
      3d:   32 21                   xor    (%bx,%di),%ah Really interrupt 21h.
      3f:   68 55 4c                push   $0x4c55
      42:   58                      pop    %ax           ax ← 0x4c55, and in 
particular ah ← 0x4c,
                                                         terminate program.
      43:   32 21                   xor    (%bx,%di),%ah Really interrupt 21h.
      45:   41                      inc    %cx           Unnecessary padding?
      46:   0d                      .byte 0xd            Involuntarily appended 
by ECHO.
      47:   0a                      .byte 0xa
-- 
To unsubscribe: http://lists.canonical.org/mailman/listinfo/kragen-discuss

Reply via email to