Reverse Engineering for Beginners

(avery) #1

CHAPTER 83. DEMOS CHAPTER 83. DEMOS


; read 16-bit value from port 40h
0000000F: E440 in al,040
00000011: 88C4 mov ah,al
00000013: E440 in al,040
00000015: 9D popf ; enable interrupts by restoring IF flag
00000016: 86C4 xchg ah,al
; here we have 16-bit pseudorandom value
00000018: D1E8 shr ax,1
0000001A: D1E8 shr ax,1
; CF currently have second bit from the value
0000001C: B05C mov al,05C ;'\'
; if CF=1, skip the next instruction
0000001E: 7202 jc 000000022
; if CF=0, reload AL register with another character
00000020: B02F mov al,02F ;'/'
; output character
00000022: B40E mov ah,00E
00000024: CD10 int 010
00000026: E2E1 loop 000000009 ; loop 2000 times
00000028: CD20 int 020 ; exit to DOS


The pseudo-random value here is in fact the time that has passed from the system’s boot, taken from the 8253 time chip,
the value increases by one 18.2 times per second.


By writing zero to port43h, we send the command “select counter 0”, ”counter latch”, ”binary counter” (not aBCD^2 value).


The interrupts are enabled back with thePOPFinstruction, which restores theIFflag as well.


It is not possible to use theINinstruction with registers other thanAL, hence the shuffling.


83.1.2 My attempt to reduce Trixter’s version: 27 bytes.


We can say that since we use the timer not to get a precise time value, but a pseudo-random one, we do not need to spend
time (and code) to disable the interrupts. Another thing we can say is that we need only one bit from the low 8-bit part, so
let’s read only it.


We can reduced the code slightly and we’ve got 27 bytes:


00000000: B9D007 mov cx,007D0 ; limit output to 2000 characters
00000003: 31C0 xor ax,ax ; command to timer chip
00000005: E643 out 043,al
00000007: E440 in al,040 ; read 8-bit of timer
00000009: D1E8 shr ax,1 ; get second bit to CF flag
0000000B: D1E8 shr ax,1
0000000D: B05C mov al,05C ; prepare '\'
0000000F: 7202 jc 000000013
00000011: B02F mov al,02F ; prepare '/'
; output character to screen
00000013: B40E mov ah,00E
00000015: CD10 int 010
00000017: E2EA loop 000000003
; exit to DOS
00000019: CD20 int 020


83.1.3 Taking random memory garbage as a source of randomness.


Since it is MS-DOS, there is no memory protection at all, we can read from whatever address we want. Even more than that:
a simpleLODSBinstruction reads a byte from theDS:SIaddress, but it’s not a problem if the registers’ values are not set
up, let it read 1) random bytes; 2) from a random place in memory!


It is suggested in Trixter’s webpage^3 to useLODSBwithout any setup.


It is also suggested that theSCASBinstruction can be used instead, because it sets a flag according to the byte it reads.


Another idea to minimize the code is to use theINT 29hDOS syscall, which just prints the character stored in theAL
register.


(^2) Binary-coded decimal
(^3) http://go.yurichev.com/17305

Free download pdf