;DEBUG_T = TRUE
建议用 edit plus for masm 观看
loaderstuff.inc
crypt.asm: .686P ; -> Polymorphic En-/Decryption routine generator for per byte encryption <-
@Loader_Start:
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 伪装为 DBPE 2.x -> Ding Boy
jmp $+2+20h
dd 400000h,400000h,0,0,0,0,0,0
pushfd
push ebp
push edi
push esi
push edx
push ecx
push ebx
pushfd
call $+5
pop ebp
db 81h, 0EDh ,0,0,0,0 ; sub ebp, 00000000
popfd
add esp, 14h
pop ebp
popfd
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
_svkp1 0CDh
pushad
_svkp3 44h
; 取起始地址
call @Delta
@Delta:
pop ebp
_svkp2 0CCh
sub ebp, offset @Delta
_svkp3 0E8h
push ebp ; 保存 ebp
_svkp1 0E9h
add ebp, offset @Decrypt_Loader_Code
_svkp2 99h
push ebp
_svkp2 33h
ret ; -> @Decrypt_Loader_Code
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; Banner :D
db ' Sword-Protector (c) by LiNSoN[DFCG] release ',CR,LF
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
@Decoder:
; 重点防护 & anti-disasmer
_vxd
enter 0, 0
_junk 0E9h
pushad
_vxd
mov eax, [ebp+10h] ; eax -> pContext
assume eax : ptr CONTEXT
_vxd
mov ebx, [ebp+8] ; ebx -> pExcept
_mmx 0E9h
mov ebx, [ebx]
_trash 0E8h
.if ebx == 0C000001Dh
_vxd
; mov seg?, dx 产生的第一个异常
xor ebx, ebx
_vxd
and [eax].iDr0, ebx
_trash 0E8h
and [eax].iDr1, ebx
_mmx 0CDh
and [eax].iDr2, ebx
_trash 0E8h
and [eax].iDr3, ebx
_vxd
and [eax].iDr6, 0FFFF0FF0h
_trash 0E8h
and [eax].iDr7, 0DC00h ; 禁止掉所有断点
; 修复 regEip 指针
_jmper 0FFh
add [eax].regEip, 2
_vxd
jmp @@ExceptProcessed
.elseif ebx == 0C000001Eh
_vxd
cld ; 正方向进行
_jmper 0BEh
xchg esi, [eax].regEsi
_vxd
xor esi, [eax].iDr0 ; 防止 DRx 断点, 若设置 DRx 会造成解码错误, 下同
_vxd
xchg edi, [eax].regEdi
_jmper 0FFh
xor edi, [eax].iDr1
_junk 0E9h
xchg ecx, [eax].regEcx
_trash 0E8h
xor ecx, [eax].iDr2
_jmper 0CCh
push eax
_jmper 0CCh
lodsb
_trash 0E8h
VarDecryptBuff db VAR_PER_SIZE dup (0) ; 解码
_trash 0E8h
stosb
_vxd
pop eax
_mmx 0CDh
xor eax, [eax].iDr3
_trash 0E8h
xchg esi, [eax].regEsi
_mmx 0E9h
xchg edi, [eax].regEdi
_mmx 0E8h
xchg ecx, [eax].regEcx
_vxd
dec [eax].regEcx
.endif
_vxd
.if zero?
_trash 0E8h
; 恢复原始 SEH Handler
mov ecx, [eax].regEsp
_mmx 0CDh
push [ecx]
_jmper 0CCh
xor ecx, ecx
_jmper 0CDh
pop fs:[ecx]
_trash 0E8h
; 卸载 SEH 链
add [eax].regEsp, 8
_mmx 0CDh
; 修复异常
add [eax].regEip, 4
_vxd
; 初始化 DRx
and [eax].iDr0, ecx
_trash 0E8h
and [eax].iDr1, ecx
_mmx 0CDh
and [eax].iDr2, ecx
_trash 0E8h
and [eax].iDr3, ecx
_vxd
and [eax].iDr6, 0FFFF0FF0h
_trash 0E8h
and [eax].iDr7, 0DC00h ; 禁止掉所有断点
.endif
_mmx 0E8h
@@ExceptProcessed:
popad
assume eax : nothing
_mmx 0E9h
xor eax, eax
_vxd
leave
_trash 0E8h
ret
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
@Decrypt_Loader_Code:
_jmper 0C7h
pop ebp ; 恢复 ebp
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 首层 Loader 代码解码
_jmper 0CDh
lea eax, @Decoder[ebp]
_vxd
push eax
_trash 0E8h
xor eax, eax
_mmx 0E9h
push fs:[eax]
_junk 0E9h
mov fs:[eax], esp
db 8Eh, 0FAh ;mov seg?, dx 产生异常初始化 DRx 防止解码错误
mov ecx, @Loader_Crypt_Size ; 解码长度
_vxd
lea edi, @Loader_Crypt_Start[ebp] ; 首地址
_jmper 0CCh
mov esi, edi
_vxd
dd 0C8C70FF0h ; lock cmpxchg8b (e)ax 产生非法指令异常调用解码器, 解码完成会自行卸载
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
@Loader_Crypt_Start:
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 使用段选择子检测操作系统类别
mov ax, ds
and ax, 4
.if zero?
inc eax
mov bNT[ebp], eax
.endif
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 取 Loader 校验和
lea eax, @Loader_Start[ebp]
mov ecx, LOADER_CRC_CHECK_SIZE
call GetChecksum
mov dwLoaderCRC[ebp], eax
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 检测 SoftICE
test PROTECTION_FLAGS[ebp], CHECK_SI_FLAG
.if !zero?
lea esi, SEH[ebp]
assume esi : ptr sSEH
lea eax, SICheck1_SP[ebp]
mov [esi].SaveEip, eax
assume esi : nothing
mov EDI, EBP
lea eax, @SehHandler1[ebp]
xor ebx, ebx
push eax
push fs:[ebx]
mov fs:[ebx], esp
; 0 - 未检测到 SoftICE
; 1 - 检测到 SoftICE
mov ebp, 04243484Bh
mov ax, 04h
_vxd
int 3
SICheck1_SP:
mov EBP, EDI
; 恢复 SEH 链
xor ebx, ebx
pop fs:[ebx]
add esp, 4h
.if AL != 4
_junk 0E9h
popad
ret
.endif
.endif
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 取外部函数地址
lea eax, LoaderContinue1[ebp]
push eax
ret
@DoGetProcAddr:
; eax = 函数名称
; esi = DLL模块句柄
push eax
push esi
call _GetProcAddress[ebp]
cmp byte ptr [eax], 0CCh
.if zero?
add esp, 24h
.endif
ret
LoaderContinue1:
; 从 ImageImportDescriptor 中读取输入函数地址
mov eax, dwImageBase[ebp]
add eax, [eax+03Ch]
add eax,080h
mov ecx, [eax] ; ecx contains the VirtualAddress of the IT
add ecx, dwImageBase[ebp]
add ecx,16 ; ecx points to the FirstThunk address of the IID
mov eax,dword ptr [ecx]
add eax, dwImageBase[ebp]
mov ebx,dword ptr [eax]
mov [ebp+_LoadLibrary],ebx
add eax,4
mov ebx,dword ptr [eax]
mov _GetProcAddress[ebp],ebx
; 取 Kernel.DLL 之函数
lea eax,szKernel32[ebp]
push eax
call _LoadLibrary[ebp]
mov esi, eax ; esi -> Kernel 模块句柄
mov dwKernelBase[ebp], eax
lea edi, @DoGetProcAddr[ebp]
;-> GetModuleHandle
lea eax, [ebp+szGetModuleHandle]
call edi
mov [ebp+_GetModuleHandle],eax
;-> VirtualProtect
lea eax, [ebp+szVirtualProtect]
call edi
mov [ebp+_VirtualProtect],eax
;-> GetModuleFileName
lea eax, [ebp+szGetModuleFileName]
call edi
mov [ebp+_GetModuleFileName],eax
;-> CreateFile
lea eax, [ebp+szCreateFile]
call edi
mov [ebp+_CreateFile],eax
;-> GlobalAlloc
lea eax, [ebp+szGlobalAlloc]
call edi
mov [ebp+_GlobalAlloc],eax
;-> GlobalFree
lea eax, [ebp+szGlobalFree]
call edi
mov [ebp+_GlobalFree],eax
;-> ReadFile
lea eax, [ebp+szReadFile]
call edi
mov [ebp+_ReadFile],eax
;-> WriteFile
lea eax, [ebp+szWriteFile]
call edi
mov [ebp+_WriteFile],eax
;-> GetFileSize
lea eax, [ebp+szGetFileSize]
call edi
mov [ebp+_GetFileSize],eax
;-> CloseHandle
lea eax, [ebp+szCloseHandle]
call edi
mov _CloseHandle[ebp],eax
;-> CreateEvent
lea eax, [ebp+szCreateEvent]
call edi
mov [ebp+_CreateEvent],eax
;-> GetCurrentProcessId
lea eax,szGetCurrentProcessId[ebp]
call edi
mov [ebp+_GetCurrentProcessId], eax
;-> GetCurrentProcess
lea eax,szGetCurrentProcess[ebp]
call edi
mov [ebp+_GetCurrentProcess], eax
;-> GetStdHandle
lea eax, szGetStdHandle[ebp]
call edi
mov _GetStdHandle[ebp], eax
;-> OpenProcess
lea eax, szOpenProcess[ebp]
call edi
mov _OpenProcess[ebp], eax
;-> ReadProcessMemory
lea eax, szReadProcessMemory[ebp]
call edi
mov _ReadProcessMemory[ebp], eax
;-> VirtualAlloc
lea eax, szVirtualAlloc[ebp]
call edi
mov _VirtualAlloc[ebp], eax
;-> VirtualFree
lea eax, szVirtualFree[ebp]
call edi
mov _VirtualFree[ebp], eax
;-> GetWindowsDirectory
lea eax, szGetWindowsDirectory[ebp]
call edi
mov _GetWindowsDirectory[ebp], eax
;-> lstrcat
lea eax, szlstrcat[ebp]
call edi
mov _lstrcat[ebp], eax
;-> lstrcmpi
lea eax, szlstrcmpi[ebp]
call edi
mov _lstrcmpi[ebp], eax
; 取 NtDLL.DLL 之函数
lea eax, szNTDLL[ebp]
push eax
call [_GetModuleHandle+ebp]
test eax, eax
.if !zero?
mov esi, eax ; esi -> NtDLL.DLL
;-> ZwQueryInformationProcess
lea eax, szZwQueryInformationProcess[ebp]
call edi
mov _ZwQueryInformationProcess[ebp], eax
.endif
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 检测 SoftICE , 不支持 NT
test PROTECTION_FLAGS[ebp], CHECK_SI_FLAG
.if !zero?
lea ESI, [EBP+SEH]
ASSUME ESI : PTR sSEH
lea EAX, [EBP+OFFSET SICheck2_SP]
mov [ESI].SaveEip, EAX
ASSUME ESI : NOTHING
xor EBX, EBX
lea EAX, [EBP+OFFSET @SehHandler2]
push EAX
push FS:[EBX]
mov FS:[EBX], ESP
mov EDI, EBP
mov EAX, 4400h
_jmper 0C7h
INT 68h
SICheck2_SP:
xor EBX, EBX
POP FS:[EBX]
add ESP, 4
.if DI == 01297h || DI == 01277h || DI == 01330h
_mmx 0FFh
popad
_junk 0E8h
ret
.endif
.endif
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; NT's Native API 检测 Ring 3 级调试器
pushad
mov edi, _ZwQueryInformationProcess[ebp]
test edi, edi
.if !zero?
push 0
push 0
push 4
lea eax, [esp+8]
push eax
push 7
call _GetCurrentProcess[ebp]
push eax
call edi
pop eax
test eax, eax
.if !zero?
add esp, 20h*2
ret
.endif
.endif
popad
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
; 检测父进程名 ( by kongfoo )
;...
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 修改 ImageSize 防止进程转储
test PROTECTION_FLAGS[ebp],ANTI_DUMP_FLAG
.if !zero?
mov eax, 30h
push fs:[eax]
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:
.endif
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 取文件头写权限
mov edi, dwImageBase[ebp]
add edi, [edi+03Ch]
assume edi : ptr IMAGE_NT_HEADERS ; edi -> 指向 PE Header
mov esi, dwImageBase[ebp]
mov ecx, [edi].OptionalHeader.SizeOfHeaders
assume edi : nothing
; 修正页面访问权限
lea eax, Buff[ebp]
push eax
push PAGE_READWRITE
push ecx
push dwImageBase[ebp]
call _VirtualProtect[ebp]
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 计算校验和
test PROTECTION_FLAGS[ebp],CHECK_HEADER_CRC
.if !zero?
; 取执行文件名
push MAX_PATH
lea edi, Buff[ebp]
push edi ; edi -> 文件名
push 0
call _GetModuleFileName[ebp]
; 映射文件
push 0
push FILE_ATTRIBUTE_NORMAL
push OPEN_EXISTING
push NULL
push FILE_SHARE_READ
push GENERIC_READ
push edi
call _CreateFile[ebp]
inc eax
; INVALID_HANDLE_VALUE ?
jz SkipChecksumCalc
dec eax
mov edi, eax ; edi -> 文件句柄
push NULL
push edi
call _GetFileSize[ebp]
sub eax, CHECKSUM_SKIP_SIZE
xchg eax, esi ; esi -> 文件长度
push esi
push GMEM_FIXED+GMEM_ZEROINIT
call _GlobalAlloc[ebp]
test eax, eax
jz SkipChecksumCalcAndCleanUp
xchg eax, ebx ; ebx -> mem base
push NULL
lea eax, Buff[ebp]
push eax
push esi
push ebx
push edi
call _ReadFile[ebp]
; 计算校验和
mov eax,ebx
mov ecx,esi
; EBX -> hMem
; EDI = hFile
pushad
call GetChecksum
mov dwCalcedCRC[ebp], eax
popad
; 计算所得校验和将在初始化输入表后比较 >:-)
lea eax, AfterCRCCalcContinue[ebp]
push eax
ret
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 校验和计算函数
; eax = file image base
; ecx = 数据长度
GetChecksum:
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)
CheckSumLoop:
mov al, [edi]
mul edx
add ebx,eax
inc edx
inc edi
loop CheckSumLoop
xchg eax,ebx ; eax -> 校验和
ret
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
AfterCRCCalcContinue:
; 打扫战场
push ebx
call _GlobalFree[ebp]
xchg esi,eax
SkipChecksumCalcAndCleanUp:
push eax
push edi
call _CloseHandle[ebp]
pop eax
SkipChecksumCalc:
.endif
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
; 调用 IsDebuggerPresent 函数检测调试器
ifndef DEBUG_T
lea EAX, [EBP+OFFSET szIsDebuggerPresent]
push EAX
push dwKernelBase[ebp]
call _GetProcAddress[ebp]
test EAX, EAX ; Windows 95 不支持此函数
.if !zero?
call EAX
OR EAX, EAX
.IF !ZERO?
popad
RET
.ENDIF
.ENDIF
endif
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 区段解码
test PROTECTION_FLAGS[ebp], NO_CRYPT_SECTION_FLAG
.if zero?
mov eax, dwImageBase[ebp]
xor ebx, ebx
inc ebx
call CryptPE
.endif
lea eax, AfterDeCryptionContinue[ebp]
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
; -> 跳过特殊段名的段 !
.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 == ('ade.')
jmp @@LoopEnd
.ENDIF
.IF dword ptr [esi].Name1 == 0
jmp @@LoopEnd
.ENDIF
;-> skip also some other sections
.IF [esi].PointerToRawData == 0 || [esi].SizeOfRawData == 0
jmp @@LoopEnd
.ENDIF
SECTION_NAME_ENCRYPT_NUM = 19890813h
; 用来加密段名的常数
xor dword ptr [esi].Name1, SECTION_NAME_ENCRYPT_NUM
xor dword ptr [esi+4].Name1, SECTION_NAME_ENCRYPT_NUM
;-> 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
SecDecryptContinue1:
popad
@@LoopEnd:
add esi,SIZEOF IMAGE_SECTION_HEADER
inc edx
.UNTIL dx == [edi].FileHeader.NumberOfSections
assume esi : nothing
assume edi : nothing
ret
AfterDeCryptionContinue:
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; SET Index Variable of TLS table to 0
; 是否有 Tls 表
mov edi, dwImageBase[ebp]
add edi, dword ptr [edi+03Ch] ; edi -> 指向 PE Header
assume edi : ptr IMAGE_NT_HEADERS
mov ebx, [edi].OptionalHeader.DataDirectory[SIZEOF IMAGE_DATA_DIRECTORY * 9].VirtualAddress
assume edi : nothing
test ebx, ebx
.if !zero?; tls section
add ebx, dwImageBase[ebp] ; ebx -> pointer to tls table
assume ebx : ptr IMAGE_TLS_DIRECTORY32
mov eax, [ebx].AddressOfIndex
mov dword ptr [eax],0
.endif
assume ebx : nothing
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 比较 Loader 校验和
mov eax, dwCalcedCRC[ebp]
test eax, eax
.if !zero?
cmp dwOrgChecksum[ebp], eax
jnz SkipInitIt
.endif
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 初始化输入表
; 0 - 发生错误
; 1 - 输入表成功初始化
lea ESI, IIDInfo[ebp] ; ESI -> 指向当前 IID 数组
ASSUME ESI : PTR sItInfo
; 准备函数重定向
test PROTECTION_FLAGS[ebp], API_REDIRECT_FLAG
.if !zero?
pushad
lea edi, Buff[ebp]
assume edi : ptr sReThunkInfo
xor ecx, ecx
.while [ESI].FirstThunk
mov EDX, [ESI].FirstThunk
add EDX, dwImageBase[ebp]
.while dword ptr [edx]
inc ecx
add edx, 4
.endw
add esi, sizeof sItInfo
.endw
; 为 IAT 分配内存
sub edx, edx
mov eax, sizeof sApiStub
mul ecx
push PAGE_READWRITE ; access type
push MEM_RESERVE or MEM_COMMIT ; flags
push eax ; memory size to allocate
push 7FF60000h
call _VirtualAlloc[ebp] ; allocate memory
.IF !EAX ; 异常退出
pop eax
popad
ret
.ENDIF
mov [edi].ApiStubMemAddr, eax
mov [edi].pNextStub, eax
assume edi : nothing
popad
.endif
; start with the real routine
.while [esi].FirstThunk != 0
; 载入动态链接库
mov ebx, [esi].DllNameRVA
add ebx, dwImageBase[ebp]
; decrypt dll string
mov EAX,EBX
call @EnDeCryptString
lea EAX, InitITContinue1[ebp] ; goto InitITContinue1
push EAX
ret
; eax = VA of target string
@EnDeCryptString:
push ESI
push EDI
mov ESI,EAX
mov EDI,EAX
@DllCryptLoop:
LODSB
ROR AL,4
STOSB
CMP BYTE PTR [EDI],0
JNZ @DllCryptLoop
POP EDI
POP ESI
ret
InitITContinue1:
push ebx
call [ebp+_LoadLibrary]
test eax,eax
jz SkipInitIt
; zero dll name
push eax ; save dll base
test PROTECTION_FLAGS[ebp],DESTROY_IMPORT_FLAG
.if !zero?
mov eax, ebx
lea ebx, @KillString[ebp]
call ebx
.endif
POP EBX ; EBX -> library handle
; 处理 (Original-)FirstThunk 成员
mov ecx, [esi].OrgFirstThunk
.if ecx == 0
mov ecx, [esi].FirstThunk
.endif
add ecx, dwImageBase[ebp] ; ecx -> pointer to current thunk
mov edx, [esi].FirstThunk
add edx, dwImageBase[ebp] ; edx -> pointer to current thunk (always the non-original one)
.WHILE dword ptr [ecx] != 0
test dword ptr [ecx], IMAGE_ORDINAL_FLAG32 ; is it an ordinal import ?
.if zero?
; 处理 name import
mov dword ptr eax, [ecx]
add eax,2
add eax, dwImageBase[ebp] ; eax points now to the Name of the Import
push eax
call @EnDeCryptString
pop eax
mov edi,eax ; 保存 API name 指针, 之后要清空
push edx
push ecx ; save the Thunk pointers
push eax
push ebx
call _GetProcAddress[ebp]
test eax, eax
.if zero?
pop ecx
pop edx
jmp SkipInitIt
.endif
pop ecx
pop edx
; 清零 API 名称
test PROTECTION_FLAGS[ebp], DESTROY_IMPORT_FLAG
.if !zero?
pushad
mov eax, edi
lea edi, @KillString[ebp]
call edi
popad
.endif
; 填充 API 地址
.else
; 处理 ordinal import
push edx
push ecx ; 保存 Thunk 指针
mov dword ptr eax, [ecx]
sub eax,080000000h
push eax
push ebx
call _GetProcAddress[ebp]
test eax,eax
jz SkipInitIt
pop ecx
pop edx
.endif
mov dword ptr [edx], eax
; 加密输入表
; eax = 当前函数地址
; ebx = dll base
; edx = non-org thunk pointer
test PROTECTION_FLAGS[ebp], API_REDIRECT_FLAG
_jmper 0CCh
.if !zero?
_junk 0e8h
;.IF [EBP+bNT]
_junk 0E8h
; .IF EBX < 070000000h || EBX > 077FFFFFFh; ; 非系统函数
_junk 0e8h
; JMP SkipThunkRed
; .ENDIF
;.ELSE
_vxd
; .IF EBX < 080000000h ; 非系统函数
_vxd
; JMP SkipThunkRed
; .ENDIF
;.ENDIF
pushad
lea edi, Buff[ebp]
assume edi : ptr sReThunkInfo
mov esi, [edi].pNextStub
mov [edx], esi ; 使 Thunk 指向 Stub Mem
pushad
xor ebx, esi
ror ebx, 7 ; ebx == Key
xor eax, ebx
mov byte ptr [esi], 68h ; push NOT_REAL_ADDRESS
inc esi
mov [esi], eax
add esi, 4
_vxd
mov word ptr [esi], 3481h ; xor dword ptr [esp], KEY
inc esi
inc esi
mov byte ptr [esi], 24h
inc esi
mov [esi], ebx
_junk 0E9h
add esi, 4
mov byte ptr [esi], 0C3h ; ret
popad
add [edi].pNextStub, sizeof sApiStub
assume edi : nothing
popad
.endif
add ecx,4
add edx,4
.ENDW
add esi, sizeof sItInfo ; 使 esi 指向下一个 IID
.ENDW
assume esi:nothing
xor eax,eax
inc eax
SkipInitIt:
dec eax
.if !zero?
popad
ret
.endif
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 把区段数改为天文数字防止转储
test PROTECTION_FLAGS[ebp], ANTI_DUMP_FLAG
.if !zero?
mov eax, dwImageBase[ebp]
add eax, [eax+3Ch]
or [eax+06h], sp ; tELock 之代码
.endif
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 初始化 OEP
lea eax, [esp+_eax]
push dwImageBase[ebp]
pop [eax]
mov ebx, dwOrgEntryPoint[ebp]
add [eax], ebx
ror dword ptr [eax], 7
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 清零 PE Header
test PROTECTION_FLAGS[ebp], ERASE_HEADER_FLAG
.if !zero?
pushad
mov eax, dwImageBase[ebp]
add eax, [eax+03Ch]
assume eax:ptr IMAGE_NT_HEADERS ; -> PE Header
mov ecx, [eax].OptionalHeader.SizeOfHeaders
mov edi, dwImageBase[ebp]
xor al, al
assume eax:nothing
@ZeroPEHeaderLoop:
stosb
loop @ZeroPEHeaderLoop
popad
.endif
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 检测调试器
ifndef DEBUG_T
pushad
.if bNT[ebp]
push fs:[30h]
pop eax ; eax -> PEB
movzx ebx, byte ptr [eax+2]
test bl, bl ; 检测用户模式调试器
jz @@CheckDebuggerEnd
popad
popad
ret
.else
push eax
sidt [esp-2]
pop ebx
add ebx, 18h
mov ecx, [ebx+4] ; int 3
mov cx, [ebx]
mov edx, [ebx+0Ch] ; int 4
mov dx, [ebx+8]
mov eax, [ebx+14h] ; int 5
mov ax, [ebx+10h]
sub eax, edx
sub edx, ecx
sub eax, edx
; 系统初始化的 int 3 、int 4、int 5 之中断向量
; 应在同一模块内,正常应有相同的高位字
; 一般调试器修改 int 3,可能不改 int 4 & int 5
; 检测 int 3 中断向量是否被改过
jz @@CheckDebuggerEnd
popad
popad
ret
.endif
@@CheckDebuggerEnd:
popad
endif
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 再次计算 Loader 校验和并比较
lea eax, @Loader_Start[ebp]
mov ecx, LOADER_CRC_CHECK_SIZE
_vxd
call GetChecksum
_mmx 0C7h
mov ebx, dwLoaderCRC[ebp]
xor eax, ebx
.if !zero?
_junk 02Ch
popad
_jmper 0E8h
ret
.endif
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
; 跳转层代码解码
lea edi, @Loader_OEP_Jump_Code_Start[ebp]
mov esi, edi
mov ecx, @Loader_Crypt_OEP_Jump_Code_Size
xor ebx, ebx
@OepJumpDecryptLoop:
lodsb
xor al, OEP_JUMP_ENCRYPT_NUM
sub al, bl
rol al, 2
stosb
inc ebx
_jmper 0E9h
loop @OepJumpDecryptLoop
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@Loader_OEP_Jump_Code_Start:
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
; 处理跳转表
_junk 0EBh
test PROTECTION_FLAGS[ebp], API_REDIRECT_FLAG
pushad
_mmx 0E8h
jz label_14_
mov eax, [esp+20h+_eax]
rol eax, 7
mov esi, eax
; ESI == OEP
; >>>>>>>> 搜索跳转表
label_0_: ;push eax,ecx,edx,ebx,esp,ebp,esi,edi ;1字节
mov ax,word ptr [esi]
cmp al,50h
jb label_1_
cmp al,57h
ja label_1_
inc esi
jmp label_0_
label_1_: ;push xx ;2字节
cmp al,6ah
jnz label_2_
inc esi
inc esi
jmp label_0_
label_2_: ;push xxxxxxxx ;5字节
cmp al,68h
jnz label_3_
add esi, 5
jmp label_0_
label_3_: ;mov eax,dword ptr [xxxxxxxx] ;5字节
cmp al,0a1h
jnz label_4_
add esi, 5
jmp label_0_
label_4_: ;sub edx,edx ;2字节
cmp ax,0d22bh
jnz label_5_
inc esi
inc esi
jmp label_0_
label_5_: ;push [esp+xx] ;4字节
cmp ax,74ffh
jnz label_6_
add esi, 4
jmp label_0_
label_6_: ;mov ebp,esp ;2字节
cmp ax,0ec8bh
jnz label_7_
inc esi
inc esi
jmp label_0_
label_7_: ;call xxxxxxx ;5字节
cmp al,0e8h
jnz label_8_
add esi, 5
jmp label_0_
label_8_:
cmp ax,0ff64h
jnz label_9_
.if byte ptr [esi+2] == 32h ;push dword ptr fs:[edx] ;3字节
add esi, 3
.elseif byte ptr [esi+2] == 35h ;push dword ptr fs:[???] ;7字节
add esi, 7
.else
jmp label_12_
.endif
jmp label_0_
label_9_:
cmp ax,8964h
jnz label_10_
.if byte ptr [esi+2] == 22h ;mov dword ptr fs:[edx],esp ;3字节
add esi, 3
.elseif byte ptr [esi+2] == 25h ;mov dword ptr fs:[???],esp ;7字节
add esi, 7
.else
jmp label_12_
.endif
jmp label_0_
label_10_: ;sub esp,xx ; 3字节
cmp ax,0ec83h
jnz label_11_
add esi, 3
jmp label_0_
label_11_:
cmp al,0A3h; mov dword ptr [xxxxxxxx],eax 5字节
jnz label_12_
add esi, 5
jmp label_0_
label_12_:
cmp al,0CCh;int 3 1byte
jnz label_13_
inc esi
jmp label_0_
label_13_: ;跳转表!!!
cmp ax, 25ffh
jnz label_14_
.while WORD ptr [esi] == 25ffh
mov eax, dword ptr [esi+2]
mov BYTE ptr [esi],68h
inc esi
mov eax, dword ptr [eax]
mov [esi],eax
add esi, 4
mov byte ptr [esi],0c3h
inc esi
.endw
label_14_:; Game Over
popad
OepJumpCodeCont:
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 清零附加代码
xor al, al
dec al ; al = 0FFh
lea edi, @Loader_Start[ebp]
mov ecx, (offset OepJumpCodeCont - offset @Loader_Start)
@LoaderZeroLoop:
stosb
loop @LoaderZeroLoop
lea EDI, [EBP+OFFSET @Loader_OEP_Jump_Code_End]
mov ECX, (OFFSET @Loader_Crypt_End - OFFSET @Loader_OEP_Jump_Code_End)
@LoaderVarZeroLoop:
stosb
loop @LoaderVarZeroLoop
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 飞 向 光 明 之 巅
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
mov eax, [esp+_eax]
mov [esp-10h], eax
rol dword ptr [esp-10h], 7
popad ; 恢复起始寄存器
; EAX - OEP
_jmper 0E9h
jmp dword ptr [esp-30h]
; 留言
db 'I am LiNSoN,you have got the OEP,Good job! QQ:150099182',0
@Loader_OEP_Jump_Code_End:
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 清零 ASCII 字符串
; EAX = ASCII 字符串首地址
@KillString:
.while byte ptr [eax] != 0
mov byte ptr [eax],0
inc eax
.ENDW
ret
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
@SehHandler1 PROC C pExcept:DWORD,pFrame:DWORD,pContext:DWORD,pDispatch:DWORD
push EDI
mov EAX,pContext
ASSUME EAX : PTR CONTEXT
mov EDI, [EAX].regEdi
push [EDI+SEH.SaveEip]
pop [eax].regEip
mov [eax].regEbp, EDI
mov [EAX].regEax, 4 ; SI NOT detected !
mov EAX,ExceptionContinueExecution
ASSUME EAX : NOTHING
POP EDI
RET
@SehHandler1 ENDP
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
@SehHandler2 PROC C pExcept:DWORD,pFrame:DWORD,pContext:DWORD,pDispatch:DWORD
push EDI
mov EAX,pContext
ASSUME EAX : PTR CONTEXT
mov EDI, [EAX].regEdi
push [EDI+SEH.SaveEip]
pop [eax].regEip
mov [eax].regEbp, EDI
mov [EAX].regEdi, 0 ; SI NOT detected !
mov EAX,ExceptionContinueExecution
ASSUME EAX : NOTHING
POP EDI
RET
@SehHandler2 ENDP
; ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━?
; 结构定义
sItInfo STRUCT
DllNameRVA dd ?
FirstThunk dd ?
OrgFirstThunk dd ?
sItInfo ENDS
sSEH STRUCT
OrgEsp dd ?
OrgEbp dd ?
SaveEip dd ?
sSEH ENDS
sReThunkInfo STRUCT
ApiStubMemAddr DD ?
pNextStub DD ?
sReThunkInfo ENDS
sApiStub struct ; 未使用此结构, 仅用来控制指针
PushOpcode DB ?;68h -> push xxxxxxxx
PushDword DD ?;the address of api (xored)
XorOpcode DB 3 dup(?);81h,34h,24h -> xor dword ptr [esp],xxxxxxxx
XorKey DD ?;Key for xoring to get the true address
RetOpcode DB ?;C3h -> ret
sApiStub ends
;----- LOADER VARIABLES -----
dwImageBase dd 0
dwOrgEntryPoint dd 0
PROTECTION_FLAGS dd 0
dwCalcedCRC dd 0
dwLoaderCRC dd 0
bNT dd 0
IIDInfo db (SIZEOF sItInfo * MAX_IID_NUM) dup (0)
SEH sSEH <0>
_LoadLibrary dd 0
_GetProcAddress dd 0
szKernel32 db "Kernel32.dll",0
dwKernelBase dd 0
szGetModuleHandle db "GetModuleHandleA",0
_GetModuleHandle dd 0
szVirtualProtect db "VirtualProtect",0
_VirtualProtect dd 0
szGetModuleFileName db "GetModuleFileNameA",0
_GetModuleFileName dd 0
szCreateFile db "CreateFileA",0
_CreateFile dd 0
szGlobalAlloc db "GlobalAlloc",0
_GlobalAlloc dd 0
szGlobalFree db "GlobalFree",0
_GlobalFree dd 0
szReadFile db "ReadFile",0
_ReadFile dd 0
szWriteFile db 'WriteFile',0
_WriteFile dd 0
szGetFileSize db "GetFileSize",0
_GetFileSize dd 0
szCloseHandle db "CloseHandle",0
_CloseHandle dd 0
szCreateEvent db "CreateEventA",0
_CreateEvent dd 0
szIsDebuggerPresent db "IsDebuggerPresent",0
_IsDebuggerPresent dd 0
szGetCurrentProcessId db 'GetCurrentProcessId', 0
_GetCurrentProcessId dd 0
szGetCurrentProcess db 'GetCurrentProcess', 0
_GetCurrentProcess dd 0
szGetStdHandle db 'GetStdHandle',0
_GetStdHandle dd 0
szOpenProcess db 'OpenProcess', 0
_OpenProcess dd 0
szReadProcessMemory db 'ReadProcessMemory',0
_ReadProcessMemory dd 0
szGetWindowsDirectory db 'GetWindowsDirectoryA', 0
_GetWindowsDirectory dd 0
szlstrcat db 'lstrcatA', 0
_lstrcat dd 0
szlstrcmpi db 'lstrcmpiA', 0
_lstrcmpi dd 0
szVirtualAlloc db 'VirtualAlloc', 0
_VirtualAlloc dd 0
szVirtualFree db 'VirtualFree', 0
_VirtualFree dd 0
szNTDLL db 'NTDLL.DLL', 0
dwNTDLLBase dd 0
szZwQueryInformationProcess db 'ZwQueryInformationProcess', 0
_ZwQueryInformationProcess dd 0
szExplorer db 'Explorer.eXe', 0
@Loader_Crypt_End:
; 未被加密的变量:
TlsBackupLabel:
TlsBackup IMAGE_TLS_DIRECTORY32 <0>
ChecksumLabel:
dwOrgChecksum dd 0
Buff db 0 ; 缓冲区,大小: 2000h(VS) - @Loader_Code_Size
@Loader_End:
顺送junkxx宏...呵呵
_junk macro prefix
IFDEF DEBUG_T
; db 4 dup(90h)
ELSE
jmp $+5
; db prefix
; db NOT prefix+1
db 0C7h
db 084h
db prefix
ENDIF
endm
; 9 bytes macro
_trash macro some_byte
IFDEF DEBUG_T
; db 10 dup(90h)
ELSE
call $+6 ; you
must step into(F8) if you want to continue
db some_byte ; tracing
add esp,4 ; fix stack(dont change any! register)
; add esp,4=3bytes instruction
ENDIF
endm
_jmper macro shit
IFDEF DEBUG_T
; db 7 dup(90h)
ELSE
jl $+5
jmp $+5
db shit
jz $-3
ENDIF
endm
_vxd macro
IFDEF DEBUG_T
; db 5 dup(90h)
ELSE
jmp $+4
db 0CDh,20h
ENDIF
endm
_mmx macro shit
IFDEF DEBUG_T
; db 4 dup(90h)
ELSE
jmp $+4
db 0Fh
db shit
ENDIF
endm
_svkp1 macro junkcode
; call loc_1
; _ONE_BYTE_JUNKCODE_
;loc_1: call loc_2
; _TWO_BYTE_JUNKCODE_
;loc_2: add dword ptr [esp], 0Bh
; add dword ptr [esp+04h], 13h
; ret
; _ONE_BYTE_JUNKCODE_
ifndef DEBUG_T
db 0E8h,01h,00h,00h,00h,junkcode,0E8h,02h,00h,00h,00h,junkcode,junkcode,83h,04h,24h,0Bh,83h,44h,24h,04h,13h,0C3h,junkcode
endif
endm
_svkp2 macro junkcode
; call loc_1
; _TWO_BYTE_JUNKCODE_
;loc_1: add dword ptr [esp]h, 08h
; ret
; _ONE_BYTE_JUNKCODE_
ifndef DEBUG_T
db 0E8h,02h,00h,00h,00h,junkcode,junkcode,83h,04h,24h,08h,0C3h,junkcode
endif
endm
_svkp3 macro junkcode
; pushad
; call loc_1
; _ONE_BYTE_JUNKCODE_
; jmp loc_4
;loc_1: pop eax
; jmp loc_2
; _ONE_BYTE_JUNKCODE_
;loc_2: inc eax
; jmp loc_3
; _ONE_BYTE_JUNKCODE_
;loc_3: jmp eax
;loc_4: popad
ifndef DEBUG_T
db 60h,0E8h,03h,00h,00h,00h,junkcode,0EBh,0Ah,58h,0EBh,01h,junkcode,40h,0EBh,01h,junkcode,0FFh,0E0h,61h
endif
endm
_dbpe1 macro junkcode
; pushf
; push 0Ah
;loc_1: jnb loc_3
; jmp loc_2
; _TWO_BYTE_JUNKCODE_
;loc_2: call loc_4
; _TWO_BYTE_JUNKCODE_
;loc_3: jnb loc_2
; _TWO_BYTE_JUNKCODE_
;loc_4: add esp,4
; jmp loc_5
; _TWO_BYTE_JUNKCODE_
;loc_5: dec dword ptr [esp]
; jno loc_6
; _ONE_BYTE_JUNKCODE_
;loc_6: jns loc_1
; jp loc_7
; _ONE_BYTE_JUNKCODE_
;loc_7: add esp,4
; popf
; jmp loc_8
; _ONE_BYTE_JUNKCODE_
;loc_8: ......
ifndef DEBUG_T
db 9Ch,6Ah,junkcode,73h,0Bh,0EBh,02h,junkcode,junkcode,0E8h,06h,00h,00h,00h,junkcode,junkcode,73h,0F7h,junkcode,junkcode,83h,0C4h,04h,0EBh,02h,junkcode,junkcode,0FFh,0Ch,24h,71h,01h,junkcode,79h,0E0h,7Ah,01h,junkcode,83h,0C4h,04h,9Dh,0EBh,01h,junkcode
endif
endm
;
; pe header structure
;
signature equ 0 ; PE,0,0
cputype equ 4 ; i386,i486 etc...
numObj equ 6 ; count of sections
timestamp equ 8
symboltable equ 12
symbolnum equ 16
NtHeaderSize equ 20
DllFlags equ 22 ; file is DLL or PE?
reserved3 equ 24
lmajor equ 26 ; linker major
lminor equ 27 ; linker minor
codesize equ 28
initdatasize equ 32
uninitdatasize equ 36
entrypointRVA equ 40 ; starting address
baseofcode equ 44
baseofdata equ 48
imagebase equ 52
objalign equ 56 ; align between objects in file
filealign equ 60 ; align between objects in memory
imagesize equ 80
headersize equ 84
checksum equ 88 ; checksum
dllflags equ 94
loaderflags equ 112 ; not used at all
edatadir equ 120
import equ 128 ; import table RVA
importsize equ 132 ; imports size
resource equ 136
ressize equ 140
reloc equ 160 ; relocation table RVA
relocsize equ 164 ; relocation table size
debug equ 168
debugsize equ 172
tls equ 192
tlssize equ 196
entryiat equ 216
entryiatsize equ 224
dimport equ 224
dimportsize equ 232
;
; object structure
;
objname equ 0 ; section name 2DWORD
objvsize equ 8 ; virtual size DWORD
objrva equ 12 ; rva of section DWORD
objpsize equ 16 ; raw size DWORD
objpoff equ 20 ; raw offset DWORD
objrle equ 24 ; relocations DWORD
objline equ 28 ; linenumbers DWORD
objrlenum equ 32 ; no of relocations WORD
objlinenum equ 34 ; no of linenumbers WORD
objflags equ 36 ; object flags DWORD
objlen equ 40 ; total object length
;
; SetFilePointer stuff
;
FILE_BEGIN equ 0
FILE_CURRENT equ 1
FILE_END equ 2
;
; mapping stuff
;
PAGE_READONLY equ 2
PAGE_READWRITE equ 4
PAGE_WRITECOPY equ 8
SECTION_QUERY equ 1
SECTION_MAP_WRITE equ 2
SECTION_MAP_READ equ 4
SECTION_MAP_EXECUTE equ 8
SECTION_MAP_EXTEND_SIZE equ 10
FILE_MAP_COPY equ SECTION_QUERY
FILE_MAP_WRITE equ SECTION_MAP_WRITE
FILE_MAP_READ equ SECTION_MAP_READ
MEM_COMMIT equ 00001000h
MEM_RESERVE equ 00002000h
MEM_DECOMMIT equ 00004000h
MEM_RELEASE equ 00008000h
MEM_FREE equ 00010000h
MEM_PRIVATE equ 00020000h
MEM_MAPPED equ 00040000h
MEM_TOP_DOWN equ 00100000h
OF_READ equ 0h ;open file only for read
OF_WRITE equ 1h ;open file only for write
OF_READWRITE equ 2h ;open file only for read+write
OFN_HIDEREADONLY equ 4
OFN_OVERWRITEPROMPT equ 2
FILE_ATTRIBUTE_NORMAL equ 080h
OPEN_EXISTING equ 3
GENERIC_READ equ 80000000h
GENERIC_WRITE equ 40000000h
FILE_SHARE_READ equ 0001h
FILE_ATTRIBUTE_ARCHIVE equ 00000020h
CREATE_NEW equ 1
CREATE_ALWAYS equ 2
OPEN_EXISTING equ 3
OPEN_ALWAYS equ 4
TRUNCATE_EXISTING equ 5
CR equ 0Dh
LF equ 0Ah
NORMAL_PRIORITY_CLASS equ 00000020h
IDLE_PRIORITY_CLASS equ 00000040h
HIGH_PRIORITY_CLASS equ 00000080h
REALTIME_PRIORITY_CLASS equ 00000100h
ERROR_ALREADY_EXISTS equ 183
PC_WRITEABLE equ 00020000H
PC_USER equ 00040000H
PC_STATIC equ 20000000H
PC_LOCKED equ 00000080H
VMM equ 00001h
_cf equ 0000000000000001b ; carry flag
_pf equ 0000000000000100b ; parity flag
_af equ 0000000000010000b ; auxilary flag
_zf equ 0000000001000000b ; zero flag
_sf equ 0000000010000000b ; sign flag
_tf equ 0000000100000000b ; trap flag
_if equ 0000001000000000b ; interrupt flag
_df equ 0000010000000000b ; direction flag
_of equ 0000100000000000b ; overflow flag
;
; pushad
; usage:
; pushad
; ...
; ...
; mov [esp+_eax],eax
; popad
;
_edi equ 0
_esi equ 4
_ebp equ 8
_esp equ 12
_ebx equ 16
_edx equ 20
_ecx equ 24
_eax equ 28
VxDCall macro Service
db 0CDh
db 020h
dd Service
endm
VMMCall macro ServiceVMM
db 0CDh,20h
dw ServiceVMM
dw VMM
endm
MEMF struct
mem_ptr dd ?
mem_handle dd ?
file_handle dd ?
file_size dd ?
MEMF ends
MEMF_ equ 4*4
CONSOLESCREENBUFFERINFO struct
c_width dw ?
c_height dw ?
c_X dw ?
c_Y dw ?
c_attribs dw ?
c_smallrect dd 2 dup(?)
c_maxwidth dw ?
c_maxheight dw ?
CONSOLESCREENBUFFERINFO ends
CONSOLESCREENBUFFERINFO_ equ 2+2+2+2+2+8+2+2
STD_OUTPUT_HANDLE equ -11
STD_INPUT_HANDLE equ -10
STD_ERROR_HANDLE equ -12
callW macro api_func
IFDEF USE_TASM
extrn api_func:proc
ENDIF
call api_func
endm
pushb macro bytevalue
db 6Ah,bytevalue
endm
fcall macro popreg,junxx
IFDEF DEBUG_T
ELSE
call $+6
db junxx
pop popreg
ENDIF
endm
ud2_1 macro
db 0Fh,0Bh ; undocumented opcode to invoke exception,this one UD2
endm
ud2_2 macro
db 0Fh,0B9h ; this is also UD2 but in disasembler it's showed as ???? unknown opcode
endm
salc macro
db D6h ; set AL on carry flag
endm
_sal macro byte ; !real! sal eax instruction,undocumented,sal eax,16 is translated
; by asembler like tasm&masm as shl eax,16
db 0C1h,0F0h,byte
endm
@Loader_Code_Size = (offset @Loader_End - offset @Loader_Start)
@Loader_Crypt_Size = (OFFSET @Loader_Crypt_End - OFFSET @Loader_Crypt_Start)
@Loader_Crypt_OEP_Jump_Code_Size = (OFFSET @Loader_OEP_Jump_Code_End - OFFSET @Loader_OEP_Jump_Code_Start)
CHECKSUM_SKIP_SIZE = 5 ; (don't include the saved checksum itself in the checksum calculation)
TLS_BACKUP_ADDR = (offset TlsBackupLabel - offset @Loader_Start)
CHECKSUM_ADDR = (OFFSET ChecksumLabel - OFFSET @Loader_Start)
IT_SIZE = 060h
MAX_SECTION_NUM = 20
MAX_IID_NUM = 30
OEP_JUMP_ENCRYPT_NUM = ('X')
LOADER_CRC_CHECK_SIZE = (OFFSET @Loader_OEP_Jump_Code_Start - OFFSET @Loader_Start)
VAR_PER_SIZE = 030h
SEC_PER_SIZE = 030h
.Const
szDone db "文件加密成功 !",0
szDoneCap db ":)",0
szFileErr db "无法访问文件 :D",0
szNoPEErr db "无效的 PE 文件 :(",0
szNoMemErr db "内存不足 -_-;",0
szFsizeErr db "奇怪的文件 !",0
szNoRoom4SectionErr db "空间不足以加入新区段 :(",0
szSecNumErr db "区段太多 !",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 0
szKernel db "KeRnEl32.dLl",0
szLoadLibrary db "LoadLibraryA",0
szGetProcAddress db "GetProcAddress",0
.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
Protect 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,@Loader_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
; 备份文件
pushad
invoke IsDlgButtonChecked,hDlg,IDC_BACKUP
.IF eax == BST_CHECKED
push offset cFname ; find file name length
call lstrlen
xchg eax,ecx
push ecx
push ecx ; save used regs
push edx
push PAGE_READWRITE ; access type
push MEM_RESERVE or MEM_COMMIT ; flags
push ecx ; size
push 0
call VirtualAlloc
pop edx
pop ecx
add eax, 5
; allocate memory page
xchg eax,edi ; edi --> memory
mov esi,offset cFname ; original file name
pop ecx ; pop size
push ecx ; save size
push edi ; save pointer to memory
push 0 ; fail if exist
push edi ; new file name
push esi ; file name
push edi ; pointer to backup file name ptr
rep movsb ; copy original file name
mov eax,'KAB.' ; add .BAK suffix
stosd ; store it
call DeleteFile ; delete backup file if exists
call CopyFile ; make backup
pop eax ; pop memory ptr
pop ecx ; pop memory size
push MEM_DECOMMIT
push ecx ; memory size
push eax ; memory pointer
call VirtualFree
.endif
popad
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
;----- 删除 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
;------ 加密块 -----
pushad
; 生成 PER
PUSH SEC_PER_SIZE
PUSH OFFSET SecDecryptBuff
PUSH OFFSET SecEncryptBuff
CALL MakePER
; 加密数据!
test dwProtFlags, NO_CRYPT_SECTION_FLAG
.if zero?
mov eax, pMem
xor ebx, ebx
call CryptPE
.endif
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
add eax,[esi].Misc.VirtualSize
; 连接器版本号
mov [edi].OptionalHeader.MajorLinkerVersion,88;主版本号
mov [edi].OptionalHeader.MinorLinkerVersion,88;次版本号
; 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, @Loader_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 @Loader_Start
mov ecx,@Loader_Code_Size
rep movsb
;----- ENCRYPT OEP JUMP CODE -----
MOV EDI, pMem
ADD EDI, dwNewSectionRO
ADD EDI, IT_SIZE
ADD EDI, (OFFSET @Loader_OEP_Jump_Code_Start - OFFSET @Loader_Start)
MOV ESI, EDI
MOV ECX, @Loader_Crypt_OEP_Jump_Code_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 @Loader_Start)
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 @Loader_Start)
MOV ECX, @Loader_Crypt_Size
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
Protect 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,@Loader_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
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
M2M <[EDI].Name1>, <[ESI].DllNameRVA>
M2M <[EDI].OriginalFirstThunk>, <[ESI].OrgFirstThunk>
M2M <[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 指针
MOV EAX, [ESI]
; is it an Ordinal Import ?
TEST EAX,IMAGE_ORDINAL_FLAG32
JNZ SkipApiString
PUSH EAX
PUSH pFileImage
CALL RVA2Offset
test eax, eax
jz SkipApiString
add eax, pFileImage
inc eax
inc eax ; 跳过 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 -> 指向下一个 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
include loaderstuff.inc
include LOADER.ASM
.MMX
.Model Flat,StdCall
Option CaseMap:None
include masm32includekernel32.inc
include masm32includeuser32.inc
include masm32includecomdlg32.inc
include masm32includeshell32.inc
include masm32includeimagehlp.inc
includelib masm32libkernel32.lib
includelib masm32libuser32.lib
includelib masm32libcomdlg32.lib
includelib masm32libshell32.lib
includelib masm32libimagehlp.lib
include masm32includewindows.inc
include resource.inc
include MACROS.ASM
include JUNKXX.INC
.CONST
CHECK_SI_FLAG equ 1
ERASE_HEADER_FLAG equ 2
DESTROY_IMPORT_FLAG equ 4
CHECK_HEADER_CRC equ 8
ANTI_DUMP_FLAG equ 16
API_REDIRECT_FLAG equ 32
NO_CRYPT_SECTION_FLAG equ 64
szFilter db "可执行文件",0,"*.eXe",0,"所有文件",0,"*.*",0,0
szCurDir db ".",0
szNoFile db "未选择文件 !",0
szErr db "错误",0
.Data
hInst dd 0
hDLG dd 0
ofn OPENFILENAME <>
cFname db MAX_PATH dup (0)
szCaption db '『 仙剑 - 宿命 』',0
szAboutInfo db ' 仙剑保护器 - linson/forgot',CR,LF,
' 致意:',CR,LF,
' y0da hying fly fxyang shinegood kongfoo jeff jwh51 goodmorning ',CR,LF,
' ...... and you ',0
.Code
include CryptStuff.ASM
include PER.ASM
DlgProc Proc hDlg:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
Local hDrop:HANDLE
pushad
.IF uMsg == WM_INITDIALOG
invoke LoadIcon,hInst,IDI_ICON
invoke SendMessage,hDlg,WM_SETICON,TRUE,eax
push hDlg
pop hDLG
; 是否已经运行?
invoke FindWindow, NULL, offset szCaption
test eax, eax
jz runchkOK
invoke FlashWindow, eax, 1; 闪动窗口
invoke SendMessage,hDlg,WM_CLOSE,NULL,NULL; 退出
runchkOK:
; 设置窗口标题
invoke SetWindowText, hDlg, offset szCaption
; 设置默认复选框
invoke CheckDlgButton,hDlg, IDC_SICHECK , TRUE
invoke CheckDlgButton,hDlg,IDC_CHECKHEADERCRC, TRUE
invoke CheckDlgButton,hDlg,IDC_DESTROYIMPORT, TRUE
invoke CheckDlgButton,hDlg,IDC_ANTIDUMP, TRUE
invoke CheckDlgButton,hDlg,IDC_APIREDIRECT, TRUE
invoke DragAcceptFiles,hDlg,TRUE
.ELSEIF uMsg == WM_DROPFILES
push wParam
pop hDrop
invoke DragQueryFile,hDrop,0,offset cFname,sizeof cFname
invoke DragFinish,hDrop
invoke SetDlgItemText,hDlg,IDC_TARGETFILE,offset cFname
.ELSEIF uMsg == WM_COMMAND
mov eax,wParam
.IF ax == IDC_CLOSE
invoke SendMessage,hDlg,WM_CLOSE,NULL,NULL
.ELSEIF eax == IDC_ABOUT
invoke MessageBox, hDlg, offset szAboutInfo, offset szCaption, 64
.ELSEIF ax == IDC_CHOOSEFILE
; get a file path
mov ofn.lStructSize,SIZEOF ofn
mov ofn.lpstrFilter,offset szFilter
push hDlg
pop ofn.hwndOwner
mov ofn.lpstrFile, offset cFname
mov ofn.nMaxFile,SIZEOF cFname
mov ofn.lpstrInitialDir,offset szCurDir
mov ofn.Flags, OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST or OFN_LONGNAMES or OFN_HIDEREADONLY
push offset ofn
call GetOpenFileName
test eax,eax
jz @@ExitDlgProc
invoke SetDlgItemText,hDlg,IDC_TARGETFILE,offset cFname
.ELSEIF ax == IDC_CRYPT
; ----- was a file selected ? -----
mov eax,offset cFname
.IF byte ptr [eax] == 0
invoke MessageBox,hDlg,offset szNoFile,offset szErr,MB_ICONERROR
jmp @@ExitDlgProc
.ENDIF
; ---- 生成保护选项 -----
xor edi,edi
invoke IsDlgButtonChecked,hDlg,IDC_SICHECK
.IF eax == BST_CHECKED
or edi,CHECK_SI_FLAG
.ENDIF
invoke IsDlgButtonChecked,hDlg,IDC_ERASEPEHEADER
.IF eax == BST_CHECKED
or edi,ERASE_HEADER_FLAG
.ENDIF
invoke IsDlgButtonChecked,hDlg,IDC_DESTROYIMPORT
.IF eax == BST_CHECKED
or edi,DESTROY_IMPORT_FLAG
.ENDIF
invoke IsDlgButtonChecked,hDlg,IDC_CHECKHEADERCRC
.IF eax == BST_CHECKED
or edi,CHECK_HEADER_CRC
.ENDIF
invoke IsDlgButtonChecked,hDlg,IDC_ANTIDUMP
.IF eax == BST_CHECKED
or edi,ANTI_DUMP_FLAG
.ENDIF
INVOKE IsDlgButtonChecked,hDlg,IDC_APIREDIRECT
.IF EAX == BST_CHECKED
OR EDI, API_REDIRECT_FLAG
.ENDIF
INVOKE IsDlgButtonChecked,hDlg,IDC_NOCRYPTSECTION
.IF EAX == BST_CHECKED
OR EDI, NO_CRYPT_SECTION_FLAG
.ENDIF
push edi
push hDlg
push offset cFname
call Protect
.ENDIF
.ELSEIF uMsg == WM_CLOSE
invoke EndDialog,hDlg,0
.ENDIF
popad
@@ExitDlgProc:
xor eax,eax
ret
DlgProc endp
Main:
invoke GetModuleHandle, NULL
mov hInst, eax
invoke DialogBoxParam, eax, IDD_MAINDLG, 0, offset DlgProc, 0
invoke ExitProcess, 0
End Main
; by yoda
;---- STRUCTs ----
sPERTable STRUCT
dwSize DD ?
dwEncrypt DD ?
dwDecrypt DD ?
RandNumType DD ?
sPERTable ENDS
; RandNumType:
; 0 - no random num needed
; 1 - 3th byte must be a random number
; 2 - 2nd byte must be a random number
;----- EQUs -----
PERItems EQU 14
;----- CONST ----
.CONST
; all opcodes are in reverse order
PERTable DD 1
DD 090h ; NOP
DD 090h ; NOP
DD 0
DD 1
DD 0F9h ; STC
DD 0F9h ; STC
DD 0
DD 1
DD 0F8h ; CLC
DD 0F8h ; CLC
DD 0
DD 2
DD 0C0FEh ; INC AL
DD 0C8FEh ; DEC AL
DD 0
DD 2
DD 00004 ; ADD AL, 0
DD 0002Ch ; SUB AL, 0
DD 2
DD 2
DD 0002Ch ; SUB AL, 0
DD 00004 ; ADD AL, 0
DD 2
DD 2
DD 0C102h ; ADD AL, CL
DD 0C12Ah ; SUB AL, CL
DD 0
DD 2
DD 0C12Ah ; SUB AL, CL
DD 0C102h ; ADD AL, CL
DD 0
DD 2
DD 00034h ; XOR AL, 0
DD 00034h ; XOR AL, 0
DD 2
DD 3
DD 000C8C0h ; ROR AL, 0
DD 000C0C0h ; ROL AL, 0
DD 1
DD 3
DD 000C0C0h ; ROL AL, 0
DD 000C8C0h ; ROR AL, 0
DD 1
DD 3
DD 0E801EBh ; Self modifing
DD 0E801EBh ; Self modifing
DD 0
DD 3
DD 0E901EBh ; Self modifing
DD 0E901EBh ; Self modifing
DD 0
DD 3
DD 0C201EBh ; Self modifing
DD 0C201EBh ; Self modifing
DD 0
.DATA
dwRandVal DD 0
.CODE
; srand should only called one time !!!
InitRandom PROC
; manage the random generator
CALL GetTickCount
PUSH EAX
CALL srand
RET
InitRandom ENDP
MakePER PROC pEncryptBuff : LPVOID, pDecryptBuff : LPVOID, dwSize : DWORD
LOCAL dwCurRandNum : DWORD
; prepare some things
MOV EDI, pEncryptBuff ; EDI -> EncryptBuffer
MOV ESI, pDecryptBuff ; ESI -> DecryptBuffer
ADD ESI, dwSize ; ESI will be filled from down to top
; generate !
.REPEAT
; get a random PER Item
PUSH PERItems
CALL rand
MOV EBX, SIZEOF sPERTable
XOR EDX, EDX
MUL EBX
ADD EAX, OFFSET PERTable
XCHG EAX, EDX ; EDX -> PER Table Item
ASSUME EDX : PTR sPERTable
; is this item too big
MOV EBX, [EDX].dwSize
CMP EBX, dwSize
JG Retry
;---- past the Opcode ----
;-> encryption buffer
MOV ECX, [EDX].dwSize
MOV EAX, [EDX].dwEncrypt
MOV ECX, [EDX].dwSize
.WHILE ECX != 0
MOV BYTE PTR [EDI], AL
ADD EDI, 1
ROR EAX, 8
DEC ECX
.ENDW
; generate the random num
MOV EAX, [EDX].RandNumType
.IF EAX == 1 || EAX == 2
MOV EBX, EDI
SUB EBX, 1
PUSH 0F8h
CALL rand
INC EAX ; avoid 0 !
MOV dwCurRandNum, EAX
MOV BYTE PTR [EBX], AL
.ENDIF
; update variables/pointers
MOV EAX, [EDX].dwSize
SUB dwSize, EAX
;-> decryption buffer
MOV ECX, [EDX].dwSize
MOV EAX, [EDX].dwDecrypt
SUB ECX, 1
.WHILE ECX != 0
ROR EAX, 8
DEC ECX
.ENDW
MOV ECX, [EDX].dwSize
.WHILE ECX != 0
SUB ESI, 1
MOV BYTE PTR [ESI], AL
ROL EAX, 8
DEC ECX
.ENDW
; generate the random num
MOV EAX, [EDX].RandNumType
.IF EAX == 1
MOV EBX, ESI
ADD EBX, 2
MOV EAX, dwCurRandNum
MOV BYTE PTR [EBX], AL
.ELSEIF EAX == 2
MOV EBX, ESI
ADD EBX, 1
MOV EAX, dwCurRandNum
MOV BYTE PTR [EBX], AL
.ENDIF
ASSUME EDX : NOTHING
Retry:
.UNTIL dwSize == 0
RET
MakePER ENDP
rand PROC USES edx ebx, dwRange : DWORD
MOV EAX, dwRandVal
; save new random number
ADD EAX, 0567h
ROL EAX, 1
MOV dwRandVal, EAX
; get new random number
XOR EDX, EDX
MOV ECX, 32
BitLoop:
SHR EAX, 1
.IF CARRY?
XOR EAX, 013245769h
.ENDIF
LOOP BitLoop
; force dwRange
XOR EDX, EDX
MOV EBX, dwRange
DIV EBX
XCHG EAX, EDX
RET
rand ENDP
srand PROC dwRandNum : DWORD
MOV EAX, dwRandNum
MOV dwRandVal, EAX
RET
srand ENDP