;[c] Chaos Computer Russian eMagazine.
;WRiTER:  D()CT()r  [c] D.i.P.G. Hack Lab's 
;
;     Перед Вами пример простой  само-модифицирующейся  программы.  Эта
;  программа настолько проста, что коментировать я думаю тут  абсолютно
;  нечего. Читайте, пробуйте, модифицируйте на свое усмотрение !
;
;   tasm crypt.asm
;   tlink /t /x crypt.obj
;
.model tiny
.code
org 100h
main     proc
start:
          jmp begin

vec21     dw   21h*4,0        ;указатель на в.п. 21h
old21     dw   ?,?            ;указатель на обработчик 21h

;-------------------- структура табицы взаимозаменяемых команд --------
; длина оманды | первичный код | вторичный код | список адресов | 0ffffh

tabcod    dw offset cmd1_2-offset cmd1_1    ; длина команды 1
cmd1_1:   pushf                             ; первичный код
          call dword ptr old21
cmd1_2:   nop
          int 21h
          nop
          nop
          dw  offset adr1_1                 ; список адресов
          dw  offset adr1_2
          dw  offset adr1_3
          dw  offset adr1_4
          dw  offset adr1_5
          dw  offset adr1_6
          dw  0ffffh                        ; конец списка адресов

          dw  offset cmd2_2-offset cmd2_1   ; длина команды 2
cmd2_1:   inc bx                            ; первичный код
          inc bx
          nop
cmd2_2:   add bx,2                          ; вторичный код
          dw  offset adr2_1                 ; список адресов
          dw  offset adr2_2
          dw  0ffffh                        ; конец списка адресов

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
          dw  0ffffh                        ; конец таблицы TABCOD

begin:
          push cs
          pop  ds
          mov ah,09h                        ; вывод сообщения
          mov dx, offset msg

adr1_1:   nop
          int 21h
          nop
          nop
          call modif                        ; модифицировать код
          mov ax, 3d02h                     ; открыть файл
          mov dx, offset filename

adr1_2:   nop
          int 21h
          nop
          nop
          jc error            ; если баги то надо написть об этом
          mov bx,ax           ; записать в него
          mov ah,40h          ; модифицировать программу
          mov cx, offset fin - offset start
          mov dx, offset start

adr1_3:   nop
          int 21h
          nop
          nop
          jc error

exit:     mov ah,3eh                            ; закрыть файл

adr1_4:   nop
          int 21h
          nop
          nop
          mov ax, 4c00h          ;завершить работу
adr1_5:   nop
          int 21h
          nop
          nop

error:
          mov ah,09h
          mov dx, offset msg_err

adr1_6:
          nop
          int 21h
          nop
          nop
          jmp short exit

main      endp

;--------------------------------------------------------------------------
; подпрограмма модификации исполняемого файла в соответствии с таблицей
; взаимозаменяемых команд
;--------------------------------------------------------------------------

modif     proc near

          cld
          les bx, dword ptr vec21    ; сохранить адрес
          les bx, dword ptr es:[bx]  ; обработчика 21h
          mov old21,bx
          mov old21+2,es
          push cs
          pop  es
          mov si, offset tabcod

rpt1:
          mov cx,[si]                ;длина команды
          add si,2
          mov bx, cx          ; получить в BX адрес списка
          shl bx,1            ; адресов для тек команды
          add bx, si
rpt2:
          cmp [bx],0ffffh     ; конец списка адресов ?
          je nxt_modif        ; да - nxt_modif
          mov di,[bx]         ; нет - переслать первичный код
adr2_1:   add bx,2            ; по адресу [bx]
          push cx
          rep movsb
          pop cx
          sub si,cx           ; перейти к следующему адресу
          jmp short rpt2
nxt_modif:
          mov di,si      ; поменять в таблице местами первичный и
          add di,cx      ; вторичный коды данной команды
rpt3:
          mov al,[si]
          xchg al, [di]
          mov [si], al
          inc si
          inc di
          loop rpt3
adr2_2:   add bx,2            ; перейти к следующей команде
          cmp [bx], 0ffffh    ; конец таблицы ?
          je  end_modif       ; да -- end_modif
          mov si,bx
          jmp short rpt1
end_modif:
          ret


msg       db   'Hello World !',0ah,0dh,'$'
filename  db   'crypt.com',0
msg_err   db   'Error in file',0ah,0dh,'$'

modif     endp

fin:

          end start
