病毒基础系列文档格式.docx
《病毒基础系列文档格式.docx》由会员分享,可在线阅读,更多相关《病毒基础系列文档格式.docx(8页珍藏版)》请在冰豆网上搜索。
![病毒基础系列文档格式.docx](https://file1.bdocx.com/fileroot1/2022-12/13/7eeebe5b-6aab-46de-9a0b-19f38eb7681f/7eeebe5b-6aab-46de-9a0b-19f38eb7681f1.gif)
方法有很多,你可能早就知道了,如果你已经了解了,就此打住,这是为还不了解这一技术而写.另外这也是病毒必用的技巧之一,如果你对病毒技术感兴趣,接着看下去.
这里假设你了解PE的基本结构,如果还不懂,找点资料来看看,到处都是呦.
在几乎每个病毒的开头都用下面的语句:
call
delta
delta:
pop
ebp
sub
ebp,offsetdelta
mov
dwordptr[ebp+offsetappBase],ebp
让我们考虑一下程序的执行情况,如果下面的代码由编译器自动编译连接,那么程序执行的基址一般是400000h,如果是在Nt下执行,那么基址可能不同,比如从100000h开始,不用担心,操作系统的Loader会自动为你重定位.但是这里停下来让我们看一下,如果你想要把这段代码附加到其他程序的后面并想让其正确执行的话,就不是那么简单了,因为你的代码可能要从555588h处开始执行,而在没有得到宿主程序许可的情况下期望操作系统自动为你修正偏移错误是不可能的,既然有非常的目的,就得费点力气,自己搞定重定位.而上面的代码就是首先得到eip指针(保存CPU要执行的下一个指令的地址),也是delta在程序执行时的实际偏移(用popebp,把它存入ebp中)
1)搜寻宿主的引入表获得GetModuleHandleA函数和GetProcAddress的地址,然后通过他返回系统dll的基址.因为很多程序都要使用这两个函数,因此在某些情况下是可行的,如果宿主没有使用GetProcAddress,那你就不得不搜寻Export表了.
2)直接获得kernel32.dll的基址,然后再搜寻Export表获得GetProcAddress和LoadLibraryA的地址,然后我们就能得到任何想调用的函数地址.
3)硬编码调用函数,比如在9X下GetModuleHandleA的地址一般是BFF7****.
第一种和第三种方法存在兼容性的问题,假如宿主没有调用GetModuleHandleA,那么你就不能获得基址,别的就更别想了...硬编码问题更大,操作系统不同则不能运行了,比如9X下可能在有些计算机上正常,但肯定不能在Nt/2K下运行...
第二种方法兼容性比较好,因此作以介绍.
一点背景:
在PELoader装入我们的程序启动后堆栈顶的地址是程序的返回地址,肯定在Kernel中(当然是在没有动堆栈的情况下)!
因此我们可以得到这个地址,然后向低地址缩减验证一直到找到模块的起始地址,验证条件为PE头不能大于4096bytes,PEheader的ImageBase(文件的优先装载地址)值应该和当前指针相等(不是我们的程序,而是那个kernel32.dll),嘿嘿,简单吧,而且兼容性还不错.
要获得Api的地址首先要获得GetModuleHandle,LoadLibraryA,GetProcAddress的地址,这是通过搜索Export表来实现的,具体原理就是PEExport表的结构,如果了解了PE结构就很简单了.下面我加了点注释,没有优化代码,是为了便于理解.
好,这一部分结束了!
这是一个例子,没有用任何预引入函数,加了一条invokeInitCommonControls是为了在2K下也能正常运行,否则不能在2K下不加载!
程序得到MessageBoxA的地址然后显示一个消息框,目的在于演示,重要部分加了注释,很好明白.
注意连接时加入/section:
.text,RWE选项。
.586
.modelflat,stdcall
optioncasemap:
none
;
casesensitive
includec:
\hd\hd.h
\hd\mac.h
;
--------------
GetApiA
proto
:
DWORD,:
DWORD
--------------
.CODE
appBase
dd?
k32Base
lpApiAddrs
label
near
dd
offsetsGetModuleHandle
offsetsGetProcAddress
offsetsExitProcess
offsetsLoadLibrary
0
sGetModuleHandle
db"
GetModuleHandleA"
0
sGetProcAddress
db"
GetProcAddress"
sExitProcess
ExitProcess"
sLoadLibrary
LoadLibraryA"
0
sMessageBoxA
MessageBoxA"
aGetModuleHandle
dd0
aGetProcAddress
dd0
aExitProcess
aLoadLibrary
aMessageBoxA
dd0
u32
User32.dll"
k32
Kernel32.dll"
sztit
ByHume,2002"
szMsg0
Hey,HopeUenjoyit!
"
-----------------------------------------
__Start:
invokeInitCommonControls
得到delta地址
因为在其他程序中基址可能不是默认的所以需要重定位
dwordptr[ebp+offsetappBase],ebp
呵呵仔细想想
mov
ecx,[esp]
返回地址
xor
edx,edx
getK32Base:
dec
ecx
逐字节比较验证
dx,word
ptr[ecx+IMAGE_DOS_HEADER.e_lfanew]
就是ecx+3ch
test
dx,0f000h
DosHeader+stub不可能太大,超过4096byte
jnz
getK32Base
加速检验
cmp
看Image_Base值是否等于ecx即模块起始值,
[ebp+offsetk32Base],ecx
如果是,就认为找到kernel32的Base值
lea
edi,[ebp+offsetaGetModuleHandle]
esi,[ebp+offsetlpApiAddrs]
lop_get:
lodsd
eax,0
jz
End_Get
push
eax
dwordptr[ebp+offsetk32Base]
callGetApiA
获取API地址
stosd
jmp
lop_get
End_Get:
offsetu32
dwordptr[ebp+offsetaLoadLibrary]
在程序空间加载User32.dll
EDX,[EBP+OFFSETsMessageBoxA]
edx
eax,dwordptr[ebp+aGetProcAddress]
用GetProcAddress获得MessageBoxA的地址
eax
调用GetProcAddress
40h+1000h
style
offsetsztit
title
offset
消息内容
一个消息框产生了...嘿嘿
有理由为此高兴吧,因为我们没有预先引入
@@:
这些函数
[ebp+aExitProcess]
-----------------------------------------
K32_api_retrieve
proc
Base:
DWORD,sApi:
edx
保存edx
eax,eax
此时esi=sApi
Next_Api:
edi=AddressOfNames
esi,sApi
edx
Match_Api_name:
bl,byte
ptr[esi]
inc
esi
bl,0
foundit
edx
eax,[edi+eax*4]
AddressOfNames的指针,递增
add
eax,Base
注意是RVA,一定要加Base值
ptr[eax+edx]
逐字符比较
eax
Match_Api_name
继续搜寻
eax
不匹配,下一个api
loop
Next_Api
no_exist
若全部搜完,即未存在
foundit:
edx
edx=AddressOfNameOrdinals
shl
eax,1
*2得到AddressOfNameOrdinals的指针
movzx
eax,word
ptr[edx+eax];
eax返回指向AddressOfFunctions的指针
ret
no_exist:
eax,eax
endp
proc
DWORD,sApi:
DWORD
local
ADDRofFun:
pushad
edi,Base
edi,IMAGE_DOS_HEADER.e_lfanew
edi,[edi]
现在edi=offPE_HEADER
edi,Base
得到IMAGE_NT_HEADERS的偏移
ebx,edi
得到edi=IMAGE_EXPORT_DIRECTORY入口
eax,[edi+1ch]
AddressOfFunctions的地址
eax,Base
ADDRofFun,eax
ecx=NumberOfNames
ecx,[edi+18h]
edx,[edi+24h]
edx,Base
edx=AddressOfNameOrdinals
edi,[edi+20h]
invokeK32_api_retrieve,Base,sApi
ebx,ADDRofFun
eax,2
要*4才得到偏移
eax,ebx
eax,[eax]
加上Base!
[esp+7*4],eax
eax返回api地址
popad
endp
END__Start
------------------------------------------Endall