All pastes #238747 Raw Edit

Anonymous

public text v1 · immutable
·published 2006-11-05 02:59 UTC
rendered paste body
; Program name:	yoda's Crypter
; Version:	1.2
; Author:	C-ripper
; Target:	Yoda's Crypter v.1.2
; Greetings:	yoda, r!sc, bane, Uknown One/TMG, everyone :)

.586p
.model  flat,stdcall
locals
jumps
include win32.inc

EXTRN	GetOpenFileNameA:PROC
EXTRN	MessageBoxA:PROC
EXTRN	GlobalAlloc:PROC
EXTRN	GlobalFree:PROC
EXTRN	VirtualAlloc:PROC
EXTRN	VirtualFree:PROC
EXTRN	ExitProcess:PROC
EXTRN	ReadFile:PROC
EXTRN	WriteFile:PROC
EXTRN	GetFileSize:PROC
EXTRN	CloseHandle:PROC
EXTRN	CreateFileA:PROC

.data
NULL		equ	00h
GMEM_FIXED	equ	0000h

ofn_struc       OPENFILENAME    <>
ofn_struc_size  equ	04ch
ofn_filter      db      'Executable file',00h,'*.exe',00h,00h
ofn_title       db      'Select file to unpack',00h
f_name          db      200h dup(?)
f_handle        dd      ?
f_size          dd      ?
read_len        dd      ?
write_len       dd      ?

out_fhandle	dd	?
outfname        db      'unpacked.exe',00h

buffer          dd      ?
temp_buf	dd	?
tls_table	dd	0,0,0,0

pe_header_ptr   dd      ?
section_start   dd      ?
sections_num	dd	?
image_base      dd      ?
import_start	dd	?
import_rva	dd	?
far_proc	db	?
min_size	dd	?
imp_align	db	?
correct_imp_loc	dd	?
garbage		dd	?	
error_caption   db      'Error!',00h
cant_open_err   db      'Cannot open input file!',00h
no_mem_err      db      'Cannot allocate memory!',00h
not_mz_err      db      'Not valid EXE file (''MZ'' signature does not present)!',00h
not_pe_err      db      'Not valid PE file (''PE'' signature does not present)!',00h
import_err      db      'Cannot rebuild import section (not found)!',00h
success_msg     db      'File successfully unpacked!',00h
success_caption db	'Success',00h

.code

start   proc
; Prepare the OpenFileName structure and get file name
        mov     ofn_struc.lStructSize,ofn_struc_size
        mov     ofn_struc.lpstrFilter,offset ofn_filter
        mov     ofn_struc.lpstrFile,offset f_name
        mov     ofn_struc.lpstrTitle,offset ofn_title
        mov     ofn_struc.nMaxFile,0200h
        mov     ofn_struc.Flags,OFN_FILEMUSTEXIST or \
                                   OFN_PATHMUSTEXIST or OFN_LONGNAMES or\
                                   OFN_EXPLORER or OFN_HIDEREADONLY
        call    GetOpenFileNameA, offset ofn_struc
        or      eax,eax                 ; Nothing selected?
        jz      exit                    ; If so - exit
        call    CreateFileA, offset f_name, GENERIC_READ+GENERIC_WRITE,\
                             NULL,NULL,\
                             OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL
        cmp     eax,-1		; ////Invalid_File_Handle?
        jne     open_ok
        call    MessageBoxA, NULL, offset cant_open_err, offset error_caption, NULL
        jmp     exit
;------ File is opened OK
open_ok:
        mov     f_handle,eax
;------ Load file in memory
        call    GetFileSize, f_handle, 00h
        mov     f_size,eax
        call    GlobalAlloc, GMEM_FIXED, f_size ; Allocate memory
        or      eax,eax
        jnz     mem_alloc_ok
	call	CloseHandle, f_handle
        call    MessageBoxA, NULL, offset no_mem_err, offset error_caption, NULL
        jmp     exit

;------ Memory allocated OK
mem_alloc_ok:
        mov     buffer,eax       	;buffer points to the beginning of the
					;file in memory
        call    ReadFile, f_handle, buffer, f_size, offset read_len, NULL
	call	CloseHandle, f_handle

;------ Check for valid EXE file
check_valid_exe:
        mov     edx,buffer              ; edx points to offset of the file_start
        cmp     word ptr [edx],'ZM'
        jz      exe_ok
        call    MessageBoxA, NULL, offset not_mz_err, offset error_caption, NULL
        jmp     free_mem_exit
exe_ok:
;------ Check for valid PE file
        add     edx,dword ptr [edx+003ch]       ; PE header==>EDX
        cmp     word ptr [edx],'EP'             ; PE file?
        jz      pe_ok
        call    MessageBoxA, NULL, offset not_pe_err, offset error_caption, NULL
        jmp     free_mem_exit
pe_ok:
        mov     pe_header_ptr,edx
	mov     eax,dword ptr [edx+0034h]       ; Get image base and save it for later use
        mov     image_base,eax                  ;
	movzx	eax,word ptr [edx+0006h]	;number of sections
	mov	sections_num,eax
;###### UNPACKING START ##############################################

        mov     eax,dword ptr [edx+0028h]       ; EAX points to entry point of program
        call    rva2fo
	or	eax,eax
	jz	free_mem_exit
	mov	ebp,eax				; EBP is entry point offset
;--------------------Detect   Yoda's v1.2 layer
	cmp	dword ptr [ebp],0000e860h	; pushad
	jne	free_mem_exit
	cmp	dword ptr [ebp+0dh],00097bb9h   ;mov ecx,97Bh
	jne	free_mem_exit
	mov	esi,pe_header_ptr
	mov	edi,dword ptr [esi+10ch]	;get phys_offset of first section
	mov	edx,dword ptr [esi+108h]	;phys_size
	mov 	esi,buffer
	add	esi,edi
	mov	edi,esi				;esi points to start of CODE section
	add	edi,edx			
	Call	VirtualAlloc,NULL,37h,1000h,0004h	;alloc some memory for 1st	
							;decrypt routine
	mov	temp_buf,eax
	mov	esi,pe_header_ptr
	mov	edx,sections_num	
	imul	edx,edx,28h
	sub	edx,14h				;edx=(edx-28h)+14h -->Phys_Offset
	add	edx,esi
	add	edx,0f8h
	mov	ebx,dword ptr [edx]
	mov	edx,buffer
	add	ebx,edx
	mov	section_start,ebx		;fix the beginning off yC section
	mov	edi,ebx	
	add	edi,0078h
	mov	byte ptr [eax+36h],0c3h		;to return after it's done
	mov	ecx,00000036h
copy_:	
	mov	dl,byte ptr [edi]	
	mov	byte ptr [eax],dl
	inc	edi
	inc	eax
	loopnz	copy_

	mov	edi,section_start		
	cmp	dword ptr [edi+0a29h],00	;get first for bytes of needed .rdata(?) section
	jz	no_tls_table
	mov	ecx,dword ptr [edi+0a29h]
	mov	dword ptr tls_table,ecx
	mov	ecx,dword ptr [edi+0a2dh]
	mov	dword ptr tls_table+4,ecx
	mov	ecx,dword ptr [edi+0a31h]
	mov	dword ptr tls_table+8,ecx
	mov	ecx,dword ptr [edi+0a35h]
	mov	dword ptr tls_table+0ch,ecx 
no_tls_table:	
	add	edi,0aeh
	mov	ecx,97bh
	mov	edx,temp_buf
	call	edx
	Call	VirtualFree,temp_buf,0000h,8000h	
	
	mov	edi,section_start
	add	edi,3d2h				;2nd decrypt proc, reading it from
	Call	VirtualAlloc,NULL,37h,1000h,0004h	;the decrypted part of the file
	mov	temp_buf,eax
	mov	edi,section_start
	add	edi,03cfh				
	mov	byte ptr [eax+36h],0c3h		
	mov	ecx,00000036h
copy__:
	mov	dl,byte ptr [edi]			;again copy 3eh bytes to buffer
	mov	byte ptr [eax],dl			;to run decrypt_sections proc
	inc	edi
	inc	eax
	loopnz	copy__

	mov	eax,pe_header_ptr
	mov	edi,eax		
	mov	esi,edi
	add	esi,0f8h
	xor	edx,edx

decrypt_sections:
	cmp	dword ptr [esi],63727372h
	jnz	loc_1
	jmp	next_section
loc_1:
	cmp	dword ptr [esi],7273722eh
	jnz	loc_2
	jmp	next_section
loc_2:
	cmp	dword ptr [esi],6f6c6572h
	jnz	loc_3
	jmp	next_section
loc_3:
	cmp	dword ptr [esi],6c65722eh
	jnz	loc_4
	jmp	next_section
loc_4:
	cmp 	dword ptr [esi],00004379h
	jnz	loc_5
	jmp	next_section
loc_5:
	cmp	dword ptr [esi],6164652eh
	jnz	loc_6
	jmp	next_section
loc_6:
	cmp	dword ptr [esi+14h],00h
	jz	next_section
	cmp	dword ptr [esi+10h],00h
	jz	next_section
	pushad
	mov	ecx,[esi+10h]
	mov	edi,[esi+14h]		
	mov	esi,buffer	
	add	esi,edi
	mov	edx,temp_buf
	call	edx	
	popad
next_section:
	add	esi,28h
	inc	edx
	cmp	dx,[edi+06]
	jnz	decrypt_sections
	Call	VirtualFree,temp_buf,0000h,8000h
;^^^^^^^^^^^^^^^^^^^^^^Decrypt import table^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	mov	eax,section_start	;pointer to reserved import 
	add	eax,07efh		;info for later use
	xor	edi,edi
	mov	imp_align,00000001
	cmp	dword ptr [eax+08],00
	jz	pre_calc
	mov	imp_align,00000002
pre_calc:
	mov	edx,dword ptr [eax+10h]	;we may take this thunk for comparison
calc_pointers:				;we'll better calc them
	cmp	dword ptr [eax],00	;to define later their place					;in original .exe
	jnz	continue_
	cmp	dword ptr [eax+04],00
	jz	find_data_section
continue_:
	add	eax,04
	inc	edi
	jmp	calc_pointers
	imul	edi,edi,04

	mov	far_proc,00
find_data_section:
	mov	ecx,sections_num	;looking for section were to put
	mov	bl,01			;important part of import
	mov	esi,pe_header_ptr	
	add	esi,0f8h
find_idata:
	cmp	bl,cl
	jz	proceed_		;if yes then it's last section
	cmp	edx,dword ptr [esi+0ch]
	jg	move_on
	jmp	chk_next_rva
move_on:
	cmp	edx,dword ptr [esi+0ch+28h]
	jg	chk_next_rva
	cmp	edx,[esi+34h]
	jnz	proceed_
	inc	bl
	jmp	proceed_		;if (thunk>rva[i]) && (thunk<rva[i+1]) then
chk_next_rva:				;we found it and bl equ it's index
	add	esi,00000028h
	inc	bl			
	cmp	cl,bl	
	jnz	find_idata
proceed_:
	mov	min_size,edi
	sub	bl,01
	movzx	ebx,bl	
	imul	ebx,ebx,00000028h
	add	ebx,0000000ch
	mov	edi,pe_header_ptr
	add	edi,0f8h
	add	edi,ebx
	mov	esi, dword ptr [edi]	;esi holds pointer to data section
	mov	import_rva,esi		;save Virtual Offset for later use
	mov	esi, dword ptr [edi+8]	;esi is physical offset of .(i)data now
	add	esi,buffer
	mov	import_start,esi
	cmp	far_proc,01
	jz	_end_			;return to the is_in_this_section call
stay_here:	
	mov	edi,section_start
	add	edi,7efh
	xor	edi,edi
not_found:
	push	esi
	xor	edx,edx	
find_space:
	cmp	dword ptr [esi],00	
	jz	chk_farther	
	inc	edx
	cmp	edx,min_size	
	jz	chk_values
	add	esi,04
	jmp	find_space
look_again:
	pop	esi
	add	esi,04
	jmp	not_found	
chk_farther:	
	add	esi,04
	jmp	not_found
chk_values:
	mov	edi,min_size	
	imul	edi,edi,04
	sub	esi,edi
	add	esi,04
	mov	eax,dword ptr [esi]
	mov	garbage,eax
	xor	ecx,ecx
chk_the_rest:	
	add	esi,04
	inc	ecx
	cmp	dword ptr [esi],eax
	jnz	look_again
	cmp	ecx,min_size
	jz	restore_import	
	jmp	chk_the_rest
restore_import:
	inc	ecx			;there are usually 2 methods of
	imul	ecx,ecx,04		;locating the grabbed import
	sub	esi,ecx			;info
	add	esi,04
	mov	correct_imp_loc,esi
	mov	edi,section_start
	add	edi,07efh		;here we'll copy the needed data
	cmp	imp_align,1		;and rva of this place should be present
	jnz	locate_method2		;in pe_header at [pe_header_ptr+80h]
	mov	dword ptr [esi],00
	mov	dword ptr [esi+04],00
	mov	dword ptr [esi+08],00
	add	esi,0ch
mov_imp:
	mov	eax,dword ptr [edi]
	cmp	eax,00	
	jz	decrypt_import
	mov	dword ptr [esi],eax
	add	edi,04
	add	esi,04
	mov	eax,dword ptr [edi]	
	cmp	eax,00
	jz	decrypt_import
	mov	dword ptr [esi],eax
	cmp	dword ptr [edi+08],00
	jz	decrypt_import
	mov	dword ptr [esi+04],00
	mov	dword ptr [esi+08],00
	mov	dword ptr [esi+0ch],00
	add	edi,08h
	add	esi,10h
	jmp	mov_imp
locate_method2:
	push	esi
	push	edi
	add	edi,8
c1_:	cmp	dword ptr [edi],00
	jz	c2_
	mov	eax,dword ptr [edi]
	mov	dword ptr [esi],eax
	mov	dword ptr [esi+04],00
	mov	dword ptr [esi+08],00
	add	esi,14h
	add	edi,0ch
	jmp	c1_
c2_:
	mov	dword ptr [esi],00
	mov	dword ptr [esi+04],00
	mov	dword ptr [esi+08],00
	mov	dword ptr [esi+0ch],00
	mov	dword ptr [esi+10h],00
	pop	edi
	pop	esi
	add	esi,0ch
c3_:
	mov	eax,dword ptr [edi]
	mov	dword ptr [esi],eax
	mov	eax, dword ptr [edi+04]
	mov	dword ptr [esi+04],eax
	add	esi,14h
	add	edi,0ch
	cmp	dword ptr [edi],00
	jnz	c3_	
decrypt_import:
	cmp	imp_align,00000001
	jnz	decrypt2_import

;simply perform a "ror al,04" operation over each character of library\WinApi name	
;in case 1 we have the pointer to library and the pointer to thunk pointing to WinApis
;from this library; in case two there are 1 lib_name and 2! thunks	

	mov	ebx,correct_imp_loc				;ajust pointer to thunk pointing to first library
	sub	ebx,04
reverse:	
	add	ebx,10h
	mov	edi,dword ptr [ebx]
	cmp	edi,00
	jz	decr_done
	sub	edi,import_rva
	add	edi,import_start
	mov	esi,edi
	call	imports_back
	add	ebx,04
	mov	edi,dword ptr [ebx]
	sub	edi,import_rva
	add	edi,import_start
pr_thunks:	
	mov	ecx,dword ptr [edi]
	cmp	ecx,00
	jz	reverse
	sub	ecx,import_rva
	add	ecx,import_start
	add	ecx,00000002
	push	edi
	mov	edi,ecx
	mov	esi,edi
	call	imports_back
	pop	edi
	add	edi,04
	jmp	pr_thunks
decrypt2_import:
	Call	VirtualAlloc,NULL,temp_buf,1000h,0004h
	mov	temp_buf,eax
	mov	dword ptr [eax],00000000h		;initialize allocated space
	mov	ebx,correct_imp_loc
reverse_:
	add	ebx,0ch
	mov	edi,dword ptr [ebx]
	cmp	edi,00
	jz	decr_done		
	mov	ecx,edi
	call	is_in_this_section
	mov	edi,eax
	mov	esi,edi
	call	imports_back
	add	ebx,04
	mov	edi,dword ptr [ebx]
	sub	edi,import_rva
	add	edi,import_start
pr1_thunks:
	mov	ecx,dword ptr [edi]
	cmp	ecx,00
	jz	reverse__	
	test	ecx,80000000h
	jnz	rev1_	
	call	repeat_check
	cmp	al,00
	jnz	reverse__
	call	is_in_this_section
	mov	ecx,eax
	add	ecx,00000002
	push	edi
	mov	edi,ecx	
	mov	esi,edi
	call	imports_back
	pop	edi
rev1_:
	add	edi,04
	jmp	pr1_thunks
reverse__:	
	add	ebx,04
	cmp	dword ptr [ebx],00
	jz	decr_done	
	mov	edi,dword ptr [ebx]
	sub	edi,import_rva
	add	edi,import_start
pr2_thunks:
	mov	ecx,dword ptr [edi]
	cmp	ecx,00
	jz	reverse_	
	test	ecx,80000000h
	jnz	rev2_
	call	repeat_check
	cmp	al,00
	jnz	reverse_
	call	is_in_this_section
	mov	ecx,eax
	add	ecx,00000002
	push	edi
	mov	edi,ecx
	mov	esi,edi
	call	imports_back
	pop	edi
rev2_:
	add	edi,04	
	jmp	pr2_thunks
	;decrypt apis pointed by thunk at offset correct_imp_loc+00h
	mov	edi,correct_imp_loc
	jmp	pr2_thunks
	
;###################simple procedure that rotates the bytes##################
imports_back	proc
lp1_:
	lodsb
	ror	al,04
	stosb
	cmp	byte ptr [edi],00
	jnz	lp1_
	ret
imports_back	endp
;############################################################################
;############################################################################
repeat_check	proc
	uses	ebx,ecx
	xor	al,al
	mov	ebx,temp_buf
chk_val:
	cmp	dword ptr [ebx],00
	jz	end__
	cmp	dword ptr [ebx],ecx
	jz	set_flag
	add	ebx,04
	jmp	chk_val
set_flag:
	mov	al,01
	add	ebx,04
	jmp	chk_val
end__:
	mov	dword ptr [ebx],ecx
	ret
repeat_check	endp
;############################################################################
;############################################################################
is_in_this_section	proc
	uses	ecx,ebx,edx,edi,esi,import_rva,import_start
	mov	far_proc,00
	sub	ecx,import_rva
	cmp	ecx,00
	jg	dont_change
	mov	far_proc,01
	add	ecx,import_rva
	mov	edx,ecx
	jmp	find_data_section
_end_:
	mov	eax,edx
	sub	eax,import_rva
	add	eax,import_start
	jmp	_end
dont_change:
	add	ecx,import_start
	mov	eax,ecx
_end:	
	ret
is_in_this_section	endp
;############################################################################

;here we'll define the pointer to "new" import table 
decr_done:
	call	VirtualFree,NULL,temp_buf,0000h,8000h
	mov	eax,correct_imp_loc
	sub	eax,import_start
	add	eax,import_rva
	mov	import_rva,eax
;^^^^^^^^^^^^^^^^^^^^^^^^^Final part: correction of pe header^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
	cmp	dword ptr tls_table,00
	jz	fix_oep
	mov	ecx,sections_num
	mov	esi,pe_header_ptr
	add	esi,0f8h
	xor	eax,eax
local_:
	mov	eax,dword ptr [esi+14h]		;get file offset of each section
	add	eax,buffer			;until we find the proper one
	mov	ebx,dword ptr tls_table
	cmp	[eax],ebx
	jnz	tls_chk
	mov	ebx,dword ptr tls_table+04
	cmp	[eax+04],ebx
	jnz	tls_chk
	mov	ebx,dword ptr tls_table+08
	cmp	[eax+08],ebx
	jnz	tls_chk
	mov	ebx,dword ptr tls_table+0ch
	cmp	[eax+0ch],ebx
	jz	found_it
tls_chk:	
	dec	ecx
	add	esi,28h
	loopnz	local_	
found_it:	
	mov 	edi,pe_header_ptr
chk_4_origin:					;this check is done cause sometimes .tls and
	cmp	dword ptr [esi+10h],00		;.rdata have the same physical offset, but
	jnz	write_it			;in such case raw size of .tls equals to 0000h
	add	esi,28h				;so we'll need to write down the correct
	loopnz	chk_4_origin			;tls table rva
write_it:	
	mov	ebx,dword ptr [esi+0ch]
	mov	dword ptr [edi+0c0h],ebx	
fix_oep:	
	mov	eax,section_start
	add	eax,07dbh			;grab new (real) entry point and fix it
	mov	edi,dword ptr [eax]
	mov	eax,edi
	mov	edi,pe_header_ptr
	mov	dword ptr [edi+28h],eax	
	mov	edx,dword ptr [edi+50h]		;fix image_size:=image_size-2000h
	sub	edx,2000h
	mov	dword ptr [edi+50h],edx
	mov	edx,import_rva
	mov	dword ptr [edi+80h],edx		;set rva to import table we've restored
;delete some shit from pe header
	mov	eax,pe_header_ptr
	mov	edx,sections_num
	mov	ebx,buffer
	add	eax,0f8h
	dec	edx
	imul	edx,edx,28h	
	add	eax,edx				;eax points to .yC 
	xor	ebx,ebx
rem_shit:	
	mov	dword ptr [eax+ebx],00000000h
	add	ebx,4
	cmp	ebx,28h
	jnz	rem_shit
	mov	eax,pe_header_ptr		;correct pe_header
	mov	edx,sections_num		;fix number of objects
	dec	edx
	mov	word ptr [eax+0006h],dx
	add	eax,11ch
	mov	dword ptr [eax],0e0000060h	;make 1st section
						;loadable(for win32dasm)
;*******when finished save file to delamed.exe*****************
	mov	ebx,f_size
	sub	ebx,0a46h		;subtract phys_size of yC section
	mov	f_size,ebx
;###### Write unpacked file to disk ##################################
write_file:
	call    CreateFileA, offset outfname, GENERIC_WRITE,\
                             NULL, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
	push    eax
	call    WriteFile, eax, buffer, f_size, offset write_len, NULL
	call    CloseHandle
	call	MessageBoxA,NULL,offset success_msg,offset success_caption,NULL

;----- Free used memory buffer
free_mem_exit:
        call    GlobalFree,buffer

exit:
        call    ExitProcess, NULL       ; Exit program
start   endp

rva2fo  proc
        uses    ecx,esi,edi

        mov     esi,pe_header_ptr       ; ESI points to PE header in memory
        movzx   ecx,word ptr [esi+0006h]; ECX=sections number

        movzx   edi,word ptr [esi+14h]  ; Get PE Header Size
        add     edi,18h                 ; Add offset of Flags field
        add     edi,esi                 ; Make EDI = Object Table Address
        mov     esi,edi
scan_section:
        cmp     eax,dword ptr [esi+000ch]; Compare RVA with section RVA
        jae     sect_found

go_scan_next_section:
        add     esi,0028h               ; ESI points to next section in memory
        loop    scan_section
	jmp	wrong_rva

sect_found:
	cmp	ecx,0001h
	je	its_last_section
	cmp	eax,dword ptr [esi+000ch+0028h]	; Compare with the start RVA of next section
	jae	go_scan_next_section
        mov     edi,dword ptr [esi+000ch]; EDI is section start RVA
        add     edi,dword ptr [esi+0010h]; EDI is the end RVA of the section in file
	cmp	eax,edi
	jae	wrong_rva

its_last_section:
        sub     eax,dword ptr [esi+000ch]; EAX is offset withing section
        add     eax,dword ptr [esi+0014h]; EAX=physical address of section + offset
        add     eax,buffer               ; EAX is offset in our memory buffer!
        ret

wrong_rva:
	xor	eax,eax
	ret
rva2fo  endp

	end     start