📄 cryptstuff.asm
字号:
;------ MACROS -----
PUPO MACRO pSrc, pDest
PUSH pSrc
POP pDest
ENDM
;------ DEFINITIONS -------
DEPACKER_CODE_SIZE equ (offset DepackerCodeEnd - offset DepackerCode)
CHECKSUM_SKIP_SIZE equ 5 ; (don't include the saved checksum itself in the checksum calculation)
TLS_BACKUP_ADDR equ (offset TlsBackupLabel - offset DepackerCode)
CHECKSUM_ADDR equ (OFFSET ChecksumLabel - OFFSET DepackerCode)
CRYPT_LOADER_SIZE_DB EQU (OFFSET LOADER_CRYPT_END - OFFSET LOADER_CRYPT_START)
CRYPT_OEP_JUMP_SIZE equ (OFFSET OEP_JUMP_CODE_END - OFFSET OEP_JUMP_CODE_START)
IT_SIZE equ 060h
MAX_SECTION_NUM equ 20
MAX_IID_NUM equ 30
OEP_JUMP_ENCRYPT_NUM equ ('y')
LOADER_CRC_CHECK_SIZE equ (OFFSET OEP_JUMP_CODE_START - OFFSET DepackerCode)
VAR_PER_SIZE EQU 030h
SEC_PER_SIZE EQU 030h
;------- CONST --------
.const
szDone db "File encrypted successfully !",0
szDoneCap db ":)",0
szFileErr db "File access error :(",0
szNoPEErr db "Invalid PE file !",0
szNoMemErr db "Not enough memory :(",0
szFsizeErr db "Files with a filesize of 0 aren't allowed !",0
szNoRoom4SectionErr db "There's no room for a new section :(",0
szSecNumErr db "Too many sections !",0
szIIDErr DB "Too much ImageImportDescriptors !",0
ALIGN_CORRECTION dd 01000h ; this big value is e.g. needed for WATCOM compiled files
DEPACKER_SECTION_NAME dd ('Cy')
szKernel db "KeRnEl32.dLl",0
szLoadLibrary db "LoadLibraryA",0
szGetProcAddress db "GetProcAddress",0
;------- DATA ---------
.data
pMap dd 0
dwBytesRead dd 0
dwBytesWritten dd 0
pMem dd 0
dwFsize dd 0
dwOutPutSize dd 0
dwNewFileEnd dd 0
dwNTHeaderAddr dd 0
dwSectionNum dd 0
dwNewSectionRO dd 0
dwOrgITRVA dd 0
hFile dd 0
;------- CODE ---------
.code
CryptFile PROC szFname : LPSTR, hDlg : HWND,dwProtFlags : DWORD
assume fs : nothing
CALL InitRandom
;----- MAP THE FILE -----
invoke CreateFile,szFname,GENERIC_WRITE + GENERIC_READ,FILE_SHARE_WRITE + FILE_SHARE_READ,\
NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
cmp eax,INVALID_HANDLE_VALUE
jz FileErr
mov hFile,eax
invoke GetFileSize,hFile,0
.IF eax == 0
push hFile
call CloseHandle
jmp FsizeErr
.ENDIF
mov dwFsize,eax
mov eax,dwFsize
add eax,IT_SIZE
add eax,DEPACKER_CODE_SIZE
add eax,ALIGN_CORRECTION
mov dwOutPutSize,eax
push eax
push GMEM_FIXED + GMEM_ZEROINIT
call GlobalAlloc
.IF eax == NULL
push hFile
call CloseHandle
jmp MemErr
.ENDIF
mov pMem,eax
invoke ReadFile,hFile,pMem,dwFsize,offset dwBytesRead,NULL
; ----- check the PE Signature and get some needed values -----
mov edi,pMem
.IF word ptr [edi] != 'ZM'
push pMem
call GlobalFree
push hFile
call CloseHandle
jmp PEErr
.ENDIF
add edi,[edi+3Ch]
.IF word ptr [edi] != 'EP'
push pMem
call GlobalFree
push hFile
call CloseHandle
jmp PEErr
.ENDIF
mov dwNTHeaderAddr,edi
assume edi : ptr IMAGE_NT_HEADERS
push [edi].OptionalHeader.DataDirectory[SIZEOF IMAGE_DATA_DIRECTORY].VirtualAddress
pop dwOrgITRVA
push word ptr [edi].FileHeader.NumberOfSections
pop word ptr dwSectionNum
.IF dwSectionNum > MAX_SECTION_NUM
JMP SecNumErr
.ENDIF
push [edi].OptionalHeader.AddressOfEntryPoint
pop dwOrgEntryPoint
push [edi].OptionalHeader.ImageBase
pop dwImageBase
;----- DELETE Bound Import & IAT DIRECTORIES -----
XOR EAX, EAX
MOV ECX, 4
LEA EDI, [EDI].OptionalHeader.DataDirectory[11 *SIZEOF IMAGE_DATA_DIRECTORY].VirtualAddress
assume edi : nothing
DirDelLoop:
STOSD
LOOP DirDelLoop
;----- ENCRYPT DLL/API NAMES & SAVE IT & DESTROY IID's -----
PUSH dwOrgITRVA
PUSH pMem
CALL RVA2Offset
PUSH EAX
PUSH pMem
CALL ProcessOrgIT
OR EAX, EAX
.IF ZERO?
PUSH pMem
CALL GlobalFree
PUSH hFile
CALL CloseHandle
JMP IIDErr
.ENDIF
;----- ADD THE PACKER SECTION -----
push pMem
call AddSection
.IF eax == 0
push pMem
call GlobalFree
push hFile
call CloseHandle
jmp NoRoom4SectionErr
.ENDIF
;----- CREATE PACKER IMPORT TABLE -----
xchg eax,esi ; esi -> pointer to Section Header of the new section
assume esi : ptr IMAGE_SECTION_HEADER
mov eax,[esi].PointerToRawData
MOV dwNewSectionRO, EAX
add eax,pMem
push [esi].VirtualAddress
push eax
call AssembleIT
;---- REPLACE TLS TABLE -----
push [esi].VirtualAddress
push pMem
call ProcessTlsTable
;------ ENCRYPT THE SECTIONS -----
pushad
; generate PER
PUSH SEC_PER_SIZE
PUSH OFFSET SecDecryptBuff
PUSH OFFSET SecEncryptBuff
CALL MakePER
; encrypt !
mov eax,pMem
mov ebx,0
call CryptPE
popad
; ----- UPDATE PE HEADER -----
mov edi,dwNTHeaderAddr
assume edi : ptr IMAGE_NT_HEADERS ; edi -> pointer to PE header
; ImportTable RVA ...
push [esi].VirtualAddress
pop [edi].OptionalHeader.DataDirectory[SIZEOF IMAGE_DATA_DIRECTORY].VirtualAddress
; EntryPoint...
mov eax,[esi].VirtualAddress
add eax,IT_SIZE
mov [edi].OptionalHeader.AddressOfEntryPoint,eax
; SizeOfImage ...
mov eax,[esi].VirtualAddress
add eax,[esi].Misc.VirtualSize
mov [edi].OptionalHeader.SizeOfImage,eax
; save protection flags...
push dwProtFlags
pop PROTECTION_FLAGS
assume esi : nothing
assume edi : nothing
; ----- CALCULATE THE NEW EOF -----
mov eax,dwNewSectionRO
add eax,IT_SIZE
add eax,DEPACKER_CODE_SIZE
mov dwNewFileEnd,eax
; ----- COPY LOADER CODE TO FILE MEMORY & DO CHECKSUM STUFF ------
mov edi,dwNewSectionRO
add edi,IT_SIZE
add edi,pMem
mov esi,offset DepackerCode
mov ecx,DEPACKER_CODE_SIZE
rep movsb
;----- ENCRYPT OEP JUMP CODE -----
MOV EDI, pMem
ADD EDI, dwNewSectionRO
ADD EDI, IT_SIZE
ADD EDI, (OFFSET OEP_JUMP_CODE_START - OFFSET DepackerCode)
MOV ESI, EDI
MOV ECX, CRYPT_OEP_JUMP_SIZE
XOR EBX, EBX
OepJumpEncryptLoop:
LODSB
ROR AL, 2
ADD AL, BL
XOR AL, OEP_JUMP_ENCRYPT_NUM
STOSB
INC EBX
LOOP OepJumpEncryptLoop
;----- ENCRYPT LOADER -----
; generate PER
PUSH VAR_PER_SIZE
MOV EAX, pMem
ADD EAX, dwNewSectionRO
ADD EAX, IT_SIZE
ADD EAX, (OFFSET VarDecryptBuff - OFFSET DepackerCode)
PUSH EAX
PUSH OFFSET VarEncryptBuff
CALL MakePER
; encryption !
MOV EDI, pMem
ADD EDI, dwNewSectionRO
ADD EDI, IT_SIZE
ADD EDI, (OFFSET LOADER_CRYPT_START - OFFSET DepackerCode)
MOV ECX, CRYPT_LOADER_SIZE_DB
MOV ESI, EDI
@@VarEncryptionLoop:
LODSB
VarEncryptBuff DB VAR_PER_SIZE DUP (0)
STOSB
LOOP @@VarEncryptionLoop
;----- CALCULATE CHECKSUM -----
mov eax,pMem
mov ecx,dwNewFileEnd
sub ecx,CHECKSUM_SKIP_SIZE
call GetChecksum
mov dwOrgChecksum,eax
;----- PASTE CHECKSUM ------
MOV EAX, pMem
ADD EAX, IT_SIZE
ADD EAX, dwNewSectionRO
ADD EAX, CHECKSUM_ADDR
MOV EDX, dwOrgChecksum
MOV DWORD PTR [EAX], EDX
; ----- WRITE FILE MEMORY TO DISK -----
invoke SetFilePointer,hFile,0,NULL,FILE_BEGIN
invoke WriteFile,hFile,pMem,dwOutPutSize,offset dwBytesWritten,NULL
; ------ FORCE CALCULATED FILE SIZE ------
invoke SetFilePointer,hFile,dwNewFileEnd,NULL,FILE_BEGIN
invoke SetEndOfFile,hFile
invoke MessageBox,hDlg,offset szDone,offset szDoneCap,MB_ICONINFORMATION
; ----- CLEAN UP -----
push pMem
call GlobalFree
push hFile
call CloseHandle
@@Exit:
ret
;----- ERROR MESSAGES -----
MemErr:
mov eax,offset szNoMemErr
jmp ShowErr
PEErr:
mov eax,offset szNoPEErr
jmp ShowErr
FileErr:
mov eax,offset szFileErr
jmp ShowErr
NoRoom4SectionErr:
mov eax,offset szNoRoom4SectionErr
jmp ShowErr
FsizeErr:
mov eax,offset szFsizeErr
jmp ShowErr
SecNumErr:
mov eax,offset szSecNumErr
jmp ShowErr
IIDErr:
MOV EAX, OFFSET szIIDErr
JMP ShowErr
ShowErr:
invoke MessageBox,hDlg,eax,offset szErr,MB_ICONERROR
jmp @@Exit
CryptFile ENDP
;--------- functions -----------------
; esi = CryptStart
; ecx = CryptSize
EncryptSec:
mov edi,esi
SecEncryptLoop:
LODSB
SecEncryptBuff DB SEC_PER_SIZE DUP (0)
STOSB
LOOP SecEncryptLoop
RET
; return values:
; 0 - no room for a new section
; 1 - file already encrypted
; else: returns a pointer to the IMAGE_SECTION_HEADER struct of the new section
AddSection PROC USES edi esi ebx ecx edx, pMem_ : LPVOID
LOCAL dwSecNum : DWORD
mov edi,pMem_
add DWORD PTR edi,[edi+03Ch]
assume edi : ptr IMAGE_NT_HEADERS ; edi -> pointer to PE header
; check whether there's room for a new section
xor eax,eax
mov ax,[edi].FileHeader.NumberOfSections
mov dwSecNum,eax
mov ecx,SIZEOF IMAGE_SECTION_HEADER
imul eax,ecx ; eax contains the size of the whole section header
add eax,SIZEOF IMAGE_SECTION_HEADER ; add the size being needed for our new section
mov ecx,edi ; ecx -> address of PE Header
sub ecx,pMem_ ; sub ecx Map Base
add ecx,eax ; ecx + calculated header sizes
add ecx,0F8h ; add the size of the PE header
.IF ecx > [edi].OptionalHeader.SizeOfHeaders
xor eax,eax
jmp @@ExitProc_AS
.ENDIF
; create a new section
mov esi,edi
add esi,0F8h
assume esi : ptr IMAGE_SECTION_HEADER ; esi -> pointer to section headers
; go to the last section
mov edx,dwSecNum
sub edx,1
.REPEAT
; force the writeable flag
mov eax,[esi].Characteristics
or eax,080000000h
mov [esi].Characteristics,eax
add esi,SIZEOF IMAGE_SECTION_HEADER
dec edx
.UNTIL edx == 0
; start to build the new section
mov edx,esi
add edx,SIZEOF IMAGE_SECTION_HEADER ; edx -> pointer to the new section
assume edx : ptr IMAGE_SECTION_HEADER
; VirtualAddress...
mov eax,[esi].VirtualAddress
add eax,[esi].Misc.VirtualSize
push 01000h
push eax
call PEAlign
mov [edx].VirtualAddress,eax
; VirtualSize..
mov [edx].Misc.VirtualSize,02000h
; RawSize..
mov eax,IT_SIZE
add eax,DEPACKER_CODE_SIZE
mov [edx].SizeOfRawData,eax
; Section name
lea eax,[edx].Name1
push DEPACKER_SECTION_NAME
pop [eax]
MOV DWORD PTR [EAX+4],0
; Characteristics
mov [edx].Characteristics,0E00000E0h
; RawOffset
mov eax,[esi].PointerToRawData
add eax,[esi].SizeOfRawData
push 0200h
push eax
call PEAlign
mov [edx].PointerToRawData,eax
mov eax,edx ; eax -> will be returned
; update the PE header
inc [edi].FileHeader.NumberOfSections
assume edx : nothing
assume esi : nothing
assume edi : nothing
@@ExitProc_AS:
ret
AddSection ENDP
AssembleIT PROC USES ebx ecx edx esi edi, pAddress4IT : LPVOID, dwNewSectionVA : DWORD
mov esi,pAddress4IT ; esi -> base of the new IT
; Zero the memory for the new IT
mov eax,pAddress4IT
mov ecx,IT_SIZE
ZeroMem:
mov byte ptr [eax],0
inc eax
loop ZeroMem
; build a new,nice ImportTable :)
mov ebx,esi
mov eax,SIZEOF IMAGE_IMPORT_DESCRIPTOR
xor edx,edx
mov ecx,2
mul ecx
add ebx,eax ; make ebx point after the terminating IID
assume esi:ptr IMAGE_IMPORT_DESCRIPTOR
mov eax,ebx ; process the IID Name
sub eax,esi
add eax,dwNewSectionVA
mov [esi].Name1,eax
push esi
mov esi,offset szKernel
mov edi,ebx
.REPEAT
lodsb
stosb
.UNTIL byte ptr [esi] == 0
pop esi
mov ebx,edi
inc ebx
mov eax,ebx ; process the FirstThunk pointers
sub eax,esi
add eax,dwNewSectionVA
mov [esi].FirstThunk,eax
mov edx,ebx
add edx,10
mov eax,edx
sub eax,esi
add eax,dwNewSectionVA
mov [ebx],eax
add edx,2
push esi
mov esi,offset szLoadLibrary
mov edi,edx
.REPEAT
lodsb
stosb
.UNTIL byte ptr [esi] == 0
pop esi
mov edx,edi
add ebx,4
mov eax,edx
sub eax,esi
add eax,dwNewSectionVA
mov [ebx],eax
add edx,2
mov esi,offset szGetProcAddress
mov edi,edx
.REPEAT
lodsb
stosb
.UNTIL byte ptr [esi] == 0
assume esi : nothing
ret
AssembleIT ENDP
ProcessTlsTable PROC USES edi ebx esi ecx, pFileMem : LPVOID, CryptSectionVA : DWORD
LOCAL pTlsDirAddr : LPVOID
; check whether there's a tls table
mov edi,pFileMem
add edi,[edi+03Ch] ; edi -> pointer to PE header
assume edi : ptr IMAGE_NT_HEADERS
lea ebx,[edi].OptionalHeader.DataDirectory[SIZEOF IMAGE_DATA_DIRECTORY * 9].VirtualAddress
mov pTlsDirAddr,ebx
mov ebx,[ebx]
assume edi : nothing
cmp ebx,0 ; no tls section
jz ExitTlsFixProc
; get a RAW pointer to the tls table
push ebx
push pFileMem
call RVA2Offset
cmp eax,0
jz ExitTlsFixProc
mov esi,pFileMem
add esi,eax ; esi -> pointer to tls tables
; copy the whole TLS table into the loader data part
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -