📄 cryptstuff.asm
字号:
mov edi,offset TlsBackup
mov ecx,sizeof IMAGE_TLS_DIRECTORY32
rep movsb
; fix the TLS DIRECTORY VA
mov eax,CryptSectionVA
add eax,IT_SIZE
add eax,TLS_BACKUP_ADDR
mov esi,pTlsDirAddr
mov [esi],eax
ExitTlsFixProc:
ret
ProcessTlsTable ENDP
; This function encrypts the dll name strings, saves the ImageImportDescriptors to the loader data
; and destroys them.
; return values:
; 1 - success
; 0 - too much IID's !
ProcessOrgIT PROC USES edi esi edx, pFileImage : LPVOID, pITBaseRO : LPVOID
LOCAL dwIIDNum : DWORD
; clear the IIDInfo array
XOR EAX,EAX
MOV EDI, OFFSET IIDInfo
MOV ECX, SIZEOF IIDInfo
ClearArrayLoop:
STOSB
LOOP ClearArrayLoop
; get a random number
INVOKE GetTickCount
XOR EAX, ("yoda")
MOV EDX,EAX ; EDX -> stupid number :)
; start
MOV dwIIDNum, 0
MOV EDI,pITBaseRO
ADD EDI,pFileImage
ASSUME EDI : PTR IMAGE_IMPORT_DESCRIPTOR ; EDI -> IID
MOV ESI,OFFSET IIDInfo
ASSUME ESI : PTR sItInfo ; ESI -> Loder IT data array
.WHILE [EDI].Name1
; too much IID's ?
INC dwIIDNum
.IF dwIIDNum == (MAX_IID_NUM)
XOR EAX, EAX
JMP POIT_Exit
.ENDIF
; save IID Infos
PUPO <[EDI].Name1>, <[ESI].DllNameRVA>
PUPO <[EDI].OriginalFirstThunk>, <[ESI].OrgFirstThunk>
PUPO <[EDI].FirstThunk>, <[ESI].FirstThunk>
;-> get dll pointer
PUSH [EDI].Name1
PUSH pFileImage
CALL RVA2Offset
ADD EAX, pFileImage
;-> crypt string
CALL EnDeCryptString
;--- CRYPT API name strings ---
PUSH ESI
MOV ESI, [EDI].OriginalFirstThunk
.IF !ESI
MOV ESI, [EDI].FirstThunk
.ENDIF
PUSH ESI
PUSH pFileImage
CALL RVA2Offset
MOV ESI, EAX
ADD ESI, pFileImage
.WHILE DWORD PTR [ESI] ; ESI -> Thunk pointer
MOV EAX, [ESI]
; is it an Ordinal Import ?
TEST EAX,IMAGE_ORDINAL_FLAG32
JNZ SkipApiString
PUSH EAX
PUSH pFileImage
CALL RVA2Offset
OR EAX, EAX
JZ SkipApiString
ADD EAX, pFileImage
ADD EAX, 2 ; skip the HINT
CALL EnDeCryptString
SkipApiString:
ADD ESI, 4
.ENDW
POP ESI
; destroy Original IID
MOV [EDI].Name1, EDX
MOV [EDI].OriginalFirstThunk, EDX
MOV [EDI].FirstThunk, EDX
MOV [EDI].TimeDateStamp, EDX
MOV [EDI].ForwarderChain, EDX
; EDI -> point to next IID
ADD EDI,SIZEOF IMAGE_IMPORT_DESCRIPTOR
ADD ESI,SIZEOF sItInfo
.ENDW
ASSUME ESI : NOTHING
ASSUME EDI : NOTHING
XOR EAX, EAX
INC EAX
POIT_Exit:
RET
ProcessOrgIT ENDP
; returns aligned value
PEAlign PROC USES ecx edx, dwTarNum : DWORD, dwAlignTo : DWORD
mov ecx,dwAlignTo
mov eax,dwTarNum
xor edx,edx
div ecx
cmp edx,0
jz AlreadyAligned
inc eax
AlreadyAligned:
mul ecx
ret
PEAlign ENDP
; calulates the Offset from a RVA
; Base - base of the MMF
; dwITRVA - the RVA to calculate
; returns 0 if an error occurred else the calculated Offset will be returned
RVA2Offset PROC USES ebx ecx edx, Base : DWORD,dwITRVA : DWORD
; get the pointer to the NT header
mov eax,Base
add eax,[eax+03Ch]
invoke ImageRvaToSection,eax,Base,dwITRVA
test eax,eax
jz @@ExitProc
xchg eax,ebx
assume ebx : ptr IMAGE_SECTION_HEADER
mov eax,dwITRVA
sub eax,[ebx].VirtualAddress
add eax,[ebx].PointerToRawData
assume ebx : nothing
@@ExitProc:
ret
RVA2Offset ENDP
; ------ START OF THE PE LOADER CODE -----
DepackerCode:
pushad
; get base ebp
call CallMe
CallMe:
pop ebp
sub ebp,offset CallMe
;----- DECRYPT LOADER VARIABLES -----
MOV ECX, CRYPT_LOADER_SIZE_DB
LEA EDI, [EBP+OFFSET LOADER_CRYPT_START]
MOV ESI, EDI
VarDecryptionLoop:
LODSB
VarDecryptBuff DB VAR_PER_SIZE DUP (0)
STOSB
LOOP VarDecryptionLoop
LOADER_CRYPT_START:
;------ DETECT WinNT ------
MOV EAX, [ESP+020h]
INC EAX
JS NoNT
MOV DWORD PTR [EBP+bNT], 1
NoNT:
;------ Get CRC OF LOADER CODE ------
LEA EAX, [EBP+OFFSET DepackerCode]
MOV ECX, LOADER_CRC_CHECK_SIZE
CALL GetChecksum
MOV [EBP+dwLoaderCRC], EAX
;----- SI Check 1 -----
MOV EAX, [ebp+PROTECTION_FLAGS]
AND EAX, CHECK_SI_FLAG
jz SkipSICheck
; install SEH frame
LEA ESI,[EBP+SEH]
ASSUME ESI : PTR sSEH
LEA EAX, [EBP+OFFSET SICheck1_SP]
mov [ESI].SaveEip, EAX
ASSUME ESI : NOTHING
MOV EDI, EBP
LEA EAX, [EBP+OFFSET SehHandler1]
XOR EBX, EBX
push EAX
push FS:[EBX]
mov FS:[EBX], ESP
; 0 - SI not found
; 1 - SI found
mov ebp, 04243484Bh
mov ax, 04h
JMP SM1
DB 0FFh
SM1:
INT 3
SICheck1_SP:
MOV EBP, EDI
; uninstall SEH frame
XOR EBX, EBX
POP FS:[EBX]
ADD ESP, 4
.IF AL != 4
; exit
JMP SM2
DB 0E9h
SM2: popad
ret
.ENDIF
SkipSICheck:
;----- GET BASE API ADDRESSES -----
; find the ImageImportDescriptor and grab dll addresses
mov eax,[ebp+dwImageBase]
add eax,[eax+03Ch]
add eax,080h
mov ecx,[eax] ; ecx contains the VirtualAddress of the IT
add ecx,[ebp+dwImageBase]
add ecx,16 ; ecx points to the FirstThunk address of the IID
mov eax,dword ptr [ecx]
add eax,[ebp+dwImageBase]
mov ebx,dword ptr [eax]
mov [ebp+_LoadLibrary],ebx
add eax,4
mov ebx,dword ptr [eax]
mov [ebp+_GetProcAddress],ebx
;----- GET ALL OTHER API ADDRESSES -----
; get kernel base
lea eax,[ebp+offset szKernel32]
push eax
call [ebp+_LoadLibrary]
mov esi,eax ; esi -> kernel base
MOV [EBP+dwKernelBase], EAX
;-> GetModuleHandle
lea eax,[ebp+szGetModuleHandle]
call DoGetProcAddr
mov [ebp+_GetModuleHandle],eax
;-> VirtualProtect
lea eax,[ebp+szVirtualProtect]
call DoGetProcAddr
mov [ebp+_VirtualProtect],eax
;-> GetModuleFileName
lea eax,[ebp+szGetModuleFileName]
call DoGetProcAddr
mov [ebp+_GetModuleFileName],eax
;-> CreateFile
lea eax,[ebp+szCreateFile]
call DoGetProcAddr
mov [ebp+_CreateFile],eax
;-> GlobalAlloc
lea eax,[ebp+szGlobalAlloc]
call DoGetProcAddr
mov [ebp+_GlobalAlloc],eax
;-> GlobalFree
lea eax,[ebp+szGlobalFree]
call DoGetProcAddr
mov [ebp+_GlobalFree],eax
;-> ReadFile
lea eax,[ebp+szReadFile]
call DoGetProcAddr
mov [ebp+_ReadFile],eax
;-> GetFileSize
lea eax,[ebp+szGetFileSize]
call DoGetProcAddr
mov [ebp+_GetFileSize],eax
;-> CloseHandle
lea eax,[ebp+szCloseHandle]
call DoGetProcAddr
mov [ebp+_CloseHandle],eax
; FUNNY JUMP :)
LEA EAX, [EBP+OFFSET LoaderContinue1]
PUSH EAX
RET
; it's in an own function to keep a the loader code small
; eax = address of API string
; esi = target dll base
DoGetProcAddr:
push eax
push esi
call [ebp+_GetProcAddress]
ret
LoaderContinue1:
;----- ANTI DUMP -----
test [ebp+PROTECTION_FLAGS],ANTI_DUMP_FLAG
jz LetDumpable
push fs:[30h]
pop eax
TEST EAX, EAX
JS fuapfdw_is9x ; detected Win 9x
fuapfdw_isNT:
MOV EAX, [EAX+0Ch]
MOV EAX, [EAX+0Ch]
MOV DWORD PTR [EAX+20h], 1000h ; increase size variable
JMP fuapfdw_finished
fuapfdw_is9x:
PUSH 0
CALL [ebp+_GetModuleHandle]
TEST EDX, EDX
JNS fuapfdw_finished ; Most probably incompatible!!!
CMP DWORD PTR [EDX+8], -1
JNE fuapfdw_finished ; Most probably incompatible!!!
MOV EDX, [EDX+4] ; get address of internaly used
; PE header
MOV DWORD PTR [EDX+50h], 1000h ; increase size variable
fuapfdw_finished:
LetDumpable:
;---- GET HEADER WRITE ACCESS -----
mov edi,[ebp+dwImageBase]
add edi,[edi+03Ch]
assume edi : ptr IMAGE_NT_HEADERS ; edi -> pointer to PE header
mov esi,[ebp+dwImageBase]
mov ecx,[edi].OptionalHeader.SizeOfHeaders
assume edi : nothing
; fix page access
lea eax,[ebp+Buff]
push eax
push PAGE_READWRITE
push ecx
push [ebp+dwImageBase]
call [ebp+_VirtualProtect]
;----- CALCULATE CRC -----
test [ebp+PROTECTION_FLAGS],CHECK_HEADER_CRC
jz DontCheckCRC
; get the calling exe filename
push MAX_PATH
lea edi,[ebp+Buff]
push edi ; edi -> filename
push 0
call [ebp+_GetModuleFileName]
; map it...
push 0
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push NULL
push FILE_SHARE_READ
push GENERIC_READ
push edi
call [ebp+_CreateFile]
.IF eax == INVALID_HANDLE_VALUE
xor eax,eax
jmp SkipChecksumCalc
.ENDIF
mov edi,eax ; edi -> file handle
push NULL
push edi
call [ebp+_GetFileSize]
sub eax,CHECKSUM_SKIP_SIZE
xchg eax,esi ; esi -> filesize
push esi
push GMEM_FIXED+GMEM_ZEROINIT
call [ebp+_GlobalAlloc]
.IF eax == NULL
jmp SkipChecksumCalcAndCleanUp
.ENDIF
xchg eax,ebx ; ebx -> mem base
push NULL
lea eax,[ebp+Buff]
push eax
push esi
push ebx
push edi
call [ebp+_ReadFile]
; get the checksum
mov eax,ebx
mov ecx,esi
PUSH EBX ; [ESP] -> hMem
PUSH EDI ; EDI = hFile
CALL GetChecksum
mov [ebp+dwCalcedCRC],eax
POP EDI
POP EBX
; the calculated CRC will be compared at the start of the InitIT function >:-)
LEA EAX, [EBP+OFFSET AfterCRCCalcContinue]
PUSH EAX
RET
;-> Start of GetChecksum
GetChecksum:
; eax = file image base
; ecx = filesize
mov edi,eax ; edi -> data pointer
xor eax,eax ; eax -> current bytes
xor ebx,ebx ; ebx -> current checksum
xor edx,edx ; edx -> Position (zero based)
; start calculation
CheckSumLoop:
mov al,byte ptr [edi]
mul edx
add ebx,eax
inc edx
inc edi
loop CheckSumLoop
xchg eax,ebx ; eax -> checksum
RET
;-> End of GetChecksum
AfterCRCCalcContinue:
; clean up
PUSH EBX
call [ebp+_GlobalFree]
xchg esi,eax
SkipChecksumCalcAndCleanUp:
push eax
push edi
call [ebp+_CloseHandle]
pop eax
SkipChecksumCalc:
DontCheckCRC:
;----- DECRYPTION -----
mov eax,[ebp+dwImageBase]
mov ebx,1
CALL CryptPE
LEA EAX, [EBP+OFFSET AfterDeCryptionContinue]
PUSH EAX
RET
; eax = pointer to file memory
; ebx: 0 - RawCrypt mode
; 1 - VirtualCrypt mode
CryptPE:
mov edi,eax
add edi,[edi+3Ch]
assume edi : ptr IMAGE_NT_HEADERS ; edi -> PE header
mov esi,edi
add esi,0F8h
assume esi : ptr IMAGE_SECTION_HEADER ; esi -> Section header
xor edx,edx
.REPEAT
; -> skip some special sections !
.IF dword ptr [esi].Name1 == ('crsr')
jmp @@LoopEnd
.ENDIF
.IF dword ptr [esi].Name1 == ('rsr.')
jmp @@LoopEnd
.ENDIF
.IF dword ptr [esi].Name1 == ('oler')
jmp @@LoopEnd
.ENDIF
.IF dword ptr [esi].Name1 == ('ler.')
jmp @@LoopEnd
.ENDIF
.IF dword ptr [esi].Name1 == ('Cy')
jmp @@LoopEnd
.ENDIF
.IF dword ptr [esi].Name1 == ('ade.')
jmp @@LoopEnd
.ENDIF
;-> skip also some other sections
.IF [esi].PointerToRawData == 0 || [esi].SizeOfRawData == 0
jmp @@LoopEnd
.ENDIF
;-> en-/decrypt it
pushad
mov ecx,[esi].SizeOfRawData
.IF ebx == 0 ; (ebx is a parameter)
mov esi,[esi].PointerToRawData
ADD ESI, EAX
CALL EncryptSec
.ELSE
mov esi,[esi].VirtualAddress
add esi,eax
CALL DecryptSec
.ENDIF
JMP SecDecryptContinue1
; esi = CryptStart
; ecx = CryptSize
DecryptSec:
mov edi,esi
SecDecryptLoop:
LODSB
SecDecryptBuff DB SEC_PER_SIZE DUP (0)
STOSB
LOOP SecDecryptLoop
RET
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -