这种算法的核心逻辑是:在对PE进行压缩的时候,如果碰到连续的多个0,比如说0000 0000,会将它变成0 8,0后面的8用来记录0的个数。
下面的代码是对这类压缩的解压缩操作。
.386
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include comdlg32.inc
includelib comdlg32.lib
TOTAL_SIZE equ 162h
.data
szFileSource db 'c:\worm2.exe',0
szFileDest db 'c:\worm2_bak.exe',0
hFileSrc dd 0
hFileDst dd 0
dwTemp dd 0
dwTemp1 dd 0
dwTemp2 dd 0
szBuffer db TOTAL_SIZE dup(0)
szBuffer1 db 0ffffh dup(0)
szText db 'OK!?',0
szCaption db 'Got you',0
.code
start:
invoke CreateFile,addr szFileSource,GENERIC_READ,\
FILE_SHARE_READ,\
0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0
mov hFileSrc,eax
invoke CreateFile,addr szFileDest,GENERIC_WRITE,\
FILE_SHARE_READ,\
0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
mov hFileDst,eax
invoke ReadFile,hFileSrc,addr szBuffer,\
TOTAL_SIZE,addr dwTemp,0
mov esi,offset szBuffer
mov edi,offset szBuffer1
mov ecx,TOTAL_SIZE
mov dwTemp2
@@0:
lodsb ;将SI中的一个字节加载到AL中
mov bl,al
sub bl,0 ;判断字符是否是0
jz @@1 ;如果是0,说明后面跟着的是0的个数,跳转过去处理
;szBuffer中的源文件是被压缩过的,核心思路是:碰到连续的多个0会将它变成1个0,
;然后在0后面跟着1位数字,代表这一串连续的0的个数
stosb
inc dwTemp2
dec ecx
jecxz @F
jmp @@0
@@1:
dec ecx
jecxz @F ;如果ecx为0则跳转
lodsb ;将0的个数取出到al中
push ecx
xor ecx,ecx
mov cl,al
add dwTemp2,ecx
mov al,0
rep stosb ;将al存储到di中,重复多次
pop ecx
dec ecx
jecxz @F
jmp @@0
@@:
;将缓冲区解密之后的数据写入目标文件中
invoke WriteFile,hFileDst,addr szBuffer1,\
dwTemp2,addr dwTemp1,NULL
invoke CloseHandle,hFileDst
invoke CloseHandle,hFileSrc
invoke MessageBox,NULL,offset szText,\
offset szCaption,MB_OK
invoke ExitProcess,NULL
end start