1. 病毒程序:1)宿主:被病毒感染的程序。例如:exe dll office文档
2)重定位:在病毒体中使用绝对位置规定的变量或入口地址,病毒体被插入到宿主程序时,这些规定的绝对位置可以已经被宿主程序使用,从而病毒体无法使用。为保证病毒体在宿主中正常执行,需要在病毒代码中使用重定位的技术。
3)重定位的实现:
病毒代码重定位:
call @@1
@@1:pop edx
……….
mov eax,[edx+(offset sum-offset @@1)];
……….
sum dd ? ;绝对地址
说明:
使用call指令,将@@1处地址放入堆栈,使用pop指令,取出地址到edx中,使用offset sum-offset @@1表示sum相对于@@1的RVA,加上edx,就得到sum变量在宿主中的绝对地址。
4)动态获取API:病毒代码实现要搜索文件、读写文件、进行进程枚举等操作,需要大量的API函数。病毒体代码在宿主进程空间中如何获取病毒体所调用的API函数在宿主进程空间中的地址.
动态获取API实现:首先需要获得kernel32.dll基地址,kernel32.dll几乎在所有的Win32 进程中都要被加载。
使用Kernel32.DLL中的LoadLibrary 和GetProcAddress 两个API可以获取任意DLL中导出的任意函数在进程空间中的位置。
三种获取kernel32.dll基地址的技术:
暴力搜索法: 通过线程初始化时, 获得esp堆栈指针中的ExitThread函数的地址,然后通过搜索获得kernel32.dll的基地址。
异常处理链表搜索法:遍历seh异常链,然后获得EXCEPTION_REGISTRATION结构prev为-1的异常处理过程地址,这个异常处理过程地址是位于kernel32.dll,通过它搜索得到kernel32.dll的基地址。
PEB法: 通过TEB获得PEB结构地址,然后再获得PEB_LDR_DATA结构地址,然后遍历模块列表,查找kernel32.dll模块的基地址。
暴力搜索法
线程在被初始化的时,其堆栈指针指向ExitThread函数的地址,windows这样做是为了退出线程时通过ret来调用ExitThread函数。
则:在主线程的起始位置(程序入口点)通过获得当前堆栈指针,从而得到ExitThread函数地址。
例如:mov edx, [esp]
获得堆栈指针中ExitThread地址到edx寄存器。
因为ExitThread函数是kernel32.dll的输出函数,获取的地址在kernel32.dll空间中,可以通过它往上搜索来获得kernel32.dll基地址。
kernel32.dll中块对齐值是00001000h, pe文件被装入内存时按64k对齐 ,所以可以通过1000h (64K) 作为跨度进行搜索,加快搜索速度。
如何确定搜索到的地址是基地址呢?
1)如果这个地址的前两个字节是否是"MZ“
2)使用该地址定位到PE头结构,然后判断是否是“PE”
如果这两个都符合,则表示这个地址就是基地址。
暴力搜索是有缺陷
代码必须运行在进程起始地址中
如果搜索的内存为不可读时,电脑就会蓝屏
暴力搜索法
mov edx, [esp]
.Next:
dec edx ;
xor dx, dx ; 减去跨度,edx的底16位置零
cmp word [edx], “ZM”
jz .IsPe
jmp .Next
.IsPe:
mov eax, [edx+3ch]
cmp word [eax+edx], ‘EP’
jnz .Next
xchg eax, edx ; eax = kernel32 基地址
异常处理链表搜索法
UNhandledExceptionFilter地址保存在结构_EXCEPTION_REGISTRATION 中。当异常发生时,操作系统将调用这个结构中的hanlder所指向的回调函数。
遍历seh异常链,获得EXCEPTION_REGISTRATION结构,如果成员prev为-1,则这个异常处理过程地址是位于kernel32.dll,通过它搜索得到kernel32.dll的基地址。
遍历的方法: [fs:0]定位的ExceptionList 指向EXCEPTION_REGISTRATION结构,通过[fs:0]获得EXCEPTION_REGISTRATION结构后,判断prev成员是否是-1,如果是则取异常处理过程地址handler,然后进行搜索。
PEB法
原理:在NT内核系统中fs寄存器指向TEB结构,TEB+0x30处指向PEB结构,PEB+0x0c处指向PEB_LDR_DATA结构,PEB_LDR_DATA+0x1c处是一个叫InInitialzationOrderModuleList的成员,指向LDR_MODULE双向链表结构,存放一些动态链接库地址:
第一个指向ntdl.dll
第二个就是kernel32.dll
PEB法
;find kernel32.dll
find_kernel32:
push esi
xor eax, eax
mov eax, [fs:eax+0x30]
test eax, eax
js find_kernel32_9x ;win9x or nt
find_kernel32_nt:
mov eax, [eax + 0x0c]
mov esi, [eax + 0x1c]
lodsd
mov eax, [eax + 0x8]
jmp find_kernel32_finished
find_kernel32_9x:
mov eax, [eax + 0x34]
lea eax, [eax + 0x7c]
mov eax, [eax + 0x3c]
find_kernel32_finished:
pop esi
ret
得到了kernel32的基地址,下一步就是定位到引出表找到GetProcAddress的地址。对于给定的API,搜索其地址可以直接通过Kernel32.dll的输出表信息搜索,PE头+120处就是引出表的文件地址。
一般是先搜索出GetProcAddress和LoadLibrary两个API函数的地址,然后利用这两个API函数得到其他所需要的API函数地址。
需要的字段:
AddressOfFunction字段:指向模块中所有函数地址的数组
AddressOfNames字段:指向模块中所有函数名称的数组
AddressOfNameOrdinals字段:指向AddressOfNames数组中函数对应序数的数组
2.病毒:
狭义:计算机病毒是指编制或者在计算机程序中插入的破坏计算机功能或者破坏数据,影响计算机使用并且能够自我复制的一组计算机指令或者程序代码
广义:
是一种人为制造的、能够进行自我复制的、具有对计算机资源进行破坏作用的一组程序或指令集合。
3.钩子是Windows系统中非常重要的系统接口,它可以截获并处理送给其他应用程序的消息,来完成普通应用程序难以实现的功能。
钩子可以监控系统或进程中的各种事件消息,截获发往目标窗口的消息并进行处理。
本质:处理message的一段程序