对于一个PE文件病毒来说,没有引入函数节的支撑,同时,也不应该全部使用静态库(这样做,不仅会大大增加程序代码,很容易被用户或者杀毒软件发现,同时也不具有通用性,对于不同的计算机平台,甚至不同的主机,都可能得到不同的结果,显然,这不是我们不希望的),所有,制作一个PE文件病毒的首要步骤就是寻找kernel32.dll基地址,根据模块地址,查找到LoadLibraryA和GetProcAddress函数的地址,通过这两个函数,我们就可以使用所有Windows的库函数了。同时,由于不清楚病毒代码会被加载到什么地方,病毒代码的重定位也是必须的。
1、代码重定位
2、寻找kernel32.dll模块基地址(提供了两种解决方案)
3、通过kernel32.dll查找到LoadLibraryA和GetProcAddress函数加载地址
4、通过LoadLibraryA和GetProcAddress两个函数加载我们需要的函数
操作系统:windows10家庭版1903
汇编器:masm32 6.14.8444
注:link的时候可能会出错,把lib.asm里面的函数放到mycode.asm里,进行相应修改就可以了。
win32.inc
.686
.model flat,stdcall
assume fs:nothing
option casemap:none;case sensetive
;include E:\masm32\include\windows.inc
;include E:\masm32\include\kernel32.inc
;include E:\masm32\include\user32.inc
;include E:\masm32\include\msvcrt.inc
;includelib E:\masm32\lib\kernel32.lib
;includelib E:\masm32\lib\user32.lib
;includelib E:\masm32\lib\msvcrt.lib
__kernel32Unicode Macro
forc char,kernel32.dll
byte '&char&'
byte 0
endm
word 0
endm
lib.asm
include win32.inc
public fun_GetKernel32Addr_f
public fun_GetKernel32Addr_t
public fun_GetFunA
public fun_strcmp
public fun_strcmp_nocase
public fun_strcmp_nocaseU
.code
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;get kernel32.dll address
;para1: one address in kernel32.dll
;ret: kernel32Address
fun_GetKernel32Addr_f proc
push ebp
mov ebp,esp
mov eax,[ebp+8h]
and eax,0ffff0000h
fun_GetKernel32Addr_f_l1:
cmp word ptr [eax],'ZM'
je fun_GetKernel32Addr_f_l2
sub eax,010000h
jmp fun_GetKernel32Addr_f_l1
fun_GetKernel32Addr_f_l2:
leave
ret 4h
fun_GetKernel32Addr_f endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;para1 kernel32NameString
;ret: kernel32Address
fun_GetKernel32Addr_t:
push ebp
mov ebp,esp
push edi
mov edi,fs:[30h]
mov edi,[edi + 0ch]
mov edi,[edi + 01ch]
fun_GetKernel32Addr_t_l1:
push [edi + 20h]
push [ebp + 08h]
call fun_strcmp_nocaseU
cmp eax,1h
je fun_GetKernel32Addr_t_l2
mov edi,[edi]
jmp fun_GetKernel32Addr_t_l1
fun_GetKernel32Addr_t_l2:
mov eax,[edi + 08h]
pop edi
leave
ret 4h
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;get funtion address in kernel32.dll
;para1 export directory table virtual address
;para2: search function name string
;para3: kernel32.dll address
;ret: function virtual address
fun_GetFunA:
push ebp
mov ebp,esp
sub esp,010h
;export address table
mov eax,[ebp+8h]
mov eax,[eax + 1ch]
add eax,[ebp + 010h]
mov [ebp-4h],eax
;export name table
mov eax,[ebp+8h]
mov eax,[eax + 20h]
add eax,[ebp + 010h]
mov [ebp-8h],eax
;export ordinal table
mov eax,[ebp+8h]
mov eax,[eax + 24h]
add eax,[ebp + 010h]
mov [ebp-0ch],eax
;i
mov dword ptr [ebp-010h],0h
fun_GetFunA_loop:
mov eax,[ebp-8h]
mov edx,[ebp-010h]
mov ecx,[eax + edx * 4]
add ecx,[ebp + 010h]
push ecx
push [ebp+0ch]
call fun_strcmp_nocase
cmp eax,1h
je fun_GetFunA_ret
inc dword ptr [ebp-010h]
jmp fun_GetFunA_loop
fun_GetFunA_ret:
mov eax,[ebp-0ch]
mov edx,[ebp-010h]
xor ecx,ecx
mov cx,[eax + edx * 2]
mov eax,[ebp-4h]
mov eax,[eax + ecx * 4]
add eax,[ebp + 010h]
leave
ret 0ch
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;campare string
;para1:string1
;para2:string2
;ret: equal=1,not equal=0
fun_strcmp proc
push ebp
mov ebp,esp
mov eax,[ebp+0ch]
mov ecx,[ebp+8h]
fun_strcmp_loop:
mov dl,[eax]
cmp dl,[ecx]
jne fun_strcmp_ret0
cmp dl,0
je fun_strcmp_ret1
inc eax
inc ecx
jmp fun_strcmp_loop
fun_strcmp_ret0:
mov eax,0
jmp fun_strcmp_ret
fun_strcmp_ret1:
mov eax,1
fun_strcmp_ret:
leave
ret 8h
fun_strcmp endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;campare string nocase
;para1:string1
;para2:string2
;ret: equal=1,not equal=0
fun_strcmp_nocase proc
push ebp
mov ebp,esp
mov eax,[ebp+0ch]
mov ecx,[ebp+8h]
fun_strcmp_nocase_loop:
mov dl,[eax]
sub dl,[ecx]
jz fun_strcmp_nocase_zero
cmp dl,20h
je fun_strcmp_nocase_final
cmp dl,-20h
je fun_strcmp_nocase_final
jmp fun_strcmp_nocase_ret0
fun_strcmp_nocase_zero:
cmp byte ptr [ecx],0
je fun_strcmp_nocase_ret1
fun_strcmp_nocase_final:
inc eax
inc ecx
jmp fun_strcmp_nocase_loop
fun_strcmp_nocase_ret0:
mov eax,0
jmp fun_strcmp_nocase_ret
fun_strcmp_nocase_ret1:
mov eax,1
fun_strcmp_nocase_ret:
leave
ret 8h
fun_strcmp_nocase endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;campare string nocase unicode
;para1:string1
;para2:string2
;ret: equal=1,not equal=0
fun_strcmp_nocaseU proc
push ebp
mov ebp,esp
mov eax,[ebp+0ch]
mov ecx,[ebp+8h]
fun_strcmp_nocaseU_loop:
mov dx,[eax]
sub dx,[ecx]
jz fun_strcmp_nocaseU_zero
cmp dx,20h
je fun_strcmp_nocaseU_final
cmp dx,-20h
je fun_strcmp_nocaseU_final
jmp fun_strcmp_nocaseU_ret0
fun_strcmp_nocaseU_zero:
cmp word ptr [ecx],0
je fun_strcmp_nocaseU_ret1
fun_strcmp_nocaseU_final:
add eax,2
add ecx,2
jmp fun_strcmp_nocaseU_loop
fun_strcmp_nocaseU_ret0:
mov eax,0
jmp fun_strcmp_nocaseU_ret
fun_strcmp_nocaseU_ret1:
mov eax,1
fun_strcmp_nocaseU_ret:
leave
ret 8h
fun_strcmp_nocaseU endp
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
end
mycode.asm
include win32.inc
extern fun_GetKernel32Addr_t:near
extern fun_GetFunA:near
.code
start:
;获取imageBase偏移
call getOffset
getOffset:
pop ebx
sub ebx,offset getOffset
;查找&&存储kernel32.dll基地址
lea eax,[ebx + offset kernel32NameString]
push eax
call fun_GetKernel32Addr_t
mov [ebx + offset kernel32Addr],eax
;查找&&存储引出目录表地址
mov eax,[eax + 3ch]
add eax,78h
add eax,[ebx + offset kernel32Addr]
mov eax,[eax]
add eax,[ebx + offset kernel32Addr]
mov [ebx + offset exportDirTAddr],eax
;查找LoadLibraryA,GetProcAddress函数地址&&存储
push [ebx + offset kernel32Addr]
lea ecx,[ebx + offset LoadLNameString]
push ecx
push dword ptr [ebx + offset exportDirTAddr]
call fun_GetFunA
mov [ebx + offset LoadLibraryAddr],eax
push [ebx + offset kernel32Addr]
lea ecx,[ebx + offset GetPANameString]
push ecx
push dword ptr [ebx + offset exportDirTAddr]
call fun_GetFunA
mov [ebx + offset GetProcAddressAddr],eax
;加载user32.dll
lea eax,[ebx + offset user32NameString]
push eax
mov eax,[ebx + offset LoadLibraryAddr]
call eax
mov [ebx + offset user32Addr],eax
;查找FindFirstFile,FindNextFile,ExitProcess, MessageBoxA函数地址&&存储
lea eax,[ebx + offset FindFFNameString]
push eax
push [ebx + offset kernel32Addr]
mov eax,[ebx + offset GetProcAddressAddr]
call eax
mov [ebx + offset FindFirstFileAddr],eax
lea eax,[ebx + offset FindNFNameString]
push eax
push [ebx + offset kernel32Addr]
mov eax,[ebx + offset GetProcAddressAddr]
call eax
mov [ebx + offset FindNextFileAddr],eax
lea eax,[ebx + offset ExitPNameString]
push eax
push [ebx + offset kernel32Addr]
mov eax,[ebx + offset GetProcAddressAddr]
call eax
mov [ebx + offset ExitProcessAddr],eax
lea eax,[ebx + offset MessageBNameString]
push eax
push [ebx + offset user32Addr]
mov eax,[ebx + offset GetProcAddressAddr]
call eax
mov [ebx + offset MessageBoxAddr],eax
;执行操作
push 40h+1000h
lea eax,[ebx + offset msgtitle]
push eax
lea eax, [ebx + offset content]
push eax
push 0
mov eax,[ebx + offset MessageBoxAddr]
call eax
;mov eax,00401000h
;jmp eax
push 0
mov eax,[ebx + offset ExitProcessAddr]
call eax
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;data in section code
kernel32Addr dword 0
user32Addr dword 0
exportDirTAddr dword 0
LoadLibraryAddr dword 0
GetProcAddressAddr dword 0
FindFirstFileAddr dword 0
FindNextFileAddr dword 0
MessageBoxAddr dword 0
ExitProcessAddr dword 0
LoadLNameString byte "LoadLibraryA",0
GetPANameString byte "GetProcAddress",0
FindFFNameString byte "FindFirstFileA",0
FindNFNameString byte "FindNextFileA",0
MessageBNameString byte "MessageBoxA",0
ExitPNameString byte "ExitProcess",0
user32NameString byte "user32.dll",0
kernel32NameString: __kernel32Unicode
msgtitle byte "MessageBox program",0
content byte "My name is hs, and I like computer, and this is a MessageBox program",0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
end start
make.bat
@echo off
@set project=E:\masm32
@echo on
%project%\BIN\ML /c /coff /Zi /Fl %1.asm
@echo off
if errorlevel 1 goto terminate
@echo on
%project%\BIN\LINK %1.obj lib.obj /subsystem:windows /release /section:.text,rw
@echo off
if errorlevel 1 goto terminate
@echo on
:terminate
@echo on