首页
社区
课程
招聘
[分享]PE程序自免疫技术程序设计一二
发表于: 2009-4-29 08:05 8441

[分享]PE程序自免疫技术程序设计一二

2009-4-29 08:05
8441

学习《Windows信息安全原理与实践》书过程中相关介绍,书中给的VC代码,闲暇将其改成汇编,供汇编初学者参考,大虾们飘过。
PE程序自免疫技术程序设计一:改进程序节表结构
原理:
插入方式的PE文件型病毒利用了每个字节对齐原因,程序实际的代码或数据可能没有占满该节,还有不少空余字节空间,病毒在空白区插入病毒。每节都存在空余字节空间,剩余空间大小由对应节表决定。节表结构中的联合Misc字段VirtualSize为该节的实际大小,该节实际占用空间有节表结构中字段SizeOfRawData得到。
SizeOfRawData减去VirtualSize的大小就是剩余空间的大小。病毒也要计算剩余空间的大小以判断是否可以插入病毒代码,如果空间不够,该种病毒就会放弃感染。这就可以启发我们,如果有意将字段VirtualSize修改的和SizeOfRawData一样大,而且在空白区填上随机数据,就可以欺骗以插入方式感染的病毒了。

代码实现:
(1)        得到节个数
由DOS头结构字段e_lfanew定位PE头结构位置,读取PE头,在其包含的文件头中得到节个数字段NumberOfSections。
(2)        读节表
依据节个数分配节表缓冲区,读取所有节表到缓冲区。
(3)        计算节空白区文件偏移和大小
遍历每个节,空白区的文件偏移等于该节文件偏移(字段PointerToRawData)加上该节大小(字段VirtualSize)。空白区大小为该节实际占用磁盘空间(字段SizeOfRawData)减去该节实际大小(字段VirtualSize)得到。
(4)        生成随机数据填充空白区
(5)        修改节表结构,让缓冲区中每个节表的字段VirtualSize等于字段SizeOfRawData,将缓冲区数据写入原节表位置。

下面是我自己讲《Windows信息安全原理与实践》中书上的VC程序改写成汇编语言的。
.586p
.model flat, stdcall
option casemap :none   ; case sensitive
include c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
includelib c:\masm32\lib\kernel32.lib
include c:\masm32\include\user32.inc
includelib c:\masm32\lib\user32.lib
include        c:\masm32\include\comdlg32.inc
includelib c:\masm32\lib\comdlg32.lib
include c:\masm32\include\masm32.inc   ;这是Alloc函数所需的文件
includelib c:\masm32\lib\masm32.lib    ;这是Alloc函数所需的Lib文件

.data
        stOFAddr        OPENFILENAME  <>
        szTitle         db            "ChangeSection",0
        szFileName        db              MAX_PATH dup (?)
        szExtPe                db              'PE Files',0,'*.exe;*.dll;*.scr;*.fon;*.drv',0
                        db              'All Files(*.*)',0,'*.*',0,0
        hFile           dd            ?
        dos_header      IMAGE_DOS_HEADER <>
        nt_header       IMAGE_NT_HEADERS <>
        section_header  IMAGE_SECTION_HEADER <>
        nBytesRead      dd            ?
        pos             dd            ?
        len             dd            ?
        arrayWrite      dd            ?
        sectionHeaderPos dd           ?
        successTip      db            "    ChangeSection Succeded!   ",0
.code

Start:
        invoke        RtlZeroMemory,offset stOFAddr,sizeof OPENFILENAME
        mov        stOFAddr.lStructSize,sizeof OPENFILENAME
        push        NULL
        pop        stOFAddr.hwndOwner
        mov        stOFAddr.lpstrFilter,offset szExtPe
        mov        stOFAddr.lpstrFile,offset szFileName
        mov        stOFAddr.nMaxFile,MAX_PATH
        mov        stOFAddr.Flags,OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST
        invoke        GetOpenFileName,offset stOFAddr
        .if        ! eax
                jmp        @F
        .endif
        invoke        CreateFile,offset szFileName,GENERIC_ALL ,FILE_SHARE_READ or \
                        FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL
        .if        eax !=        INVALID_HANDLE_VALUE
                        mov        hFile,eax
                        invoke ReadFile, hFile, offset dos_header, sizeof IMAGE_DOS_HEADER, offset nBytesRead, NULL       
                        movzx     eax,  dos_header.e_magic
                        ;检查PE文件是否有效
                        .if     eax == 5a4dh
                               invoke SetFilePointer, hFile, dos_header.e_lfanew, NULL, FILE_BEGIN
                               invoke ReadFile, hFile, offset nt_header, sizeof IMAGE_NT_HEADERS, offset nBytesRead, NULL
                               .if    nt_header.Signature == 4550h
                                      movzx   esi,nt_header.FileHeader.NumberOfSections
                                      cmp     esi,1
                                      jb      NoSection
                                      xor     ebx, ebx
                                LoopSections:
                                      mov     eax, dos_header.e_lfanew
                                      add     eax, sizeof IMAGE_NT_HEADERS
                                      mov     edx, ebx
                                      imul    edx, sizeof IMAGE_SECTION_HEADER
                                      add     eax, edx
                                      mov     sectionHeaderPos, eax
                                      ; 读取节表
                                      invoke SetFilePointer, hFile, sectionHeaderPos, NULL, FILE_BEGIN
                                      invoke ReadFile, hFile, offset section_header, sizeof IMAGE_SECTION_HEADER, offset nBytesRead, NULL
                                      ; 填充节中空白数据
                                      mov  eax, section_header.PointerToRawData
                                      add  eax, section_header.Misc.VirtualSize
                                      mov  pos,eax
                                      mov  eax, section_header.SizeOfRawData
                                      sub  eax, section_header.Misc.VirtualSize
                                      mov  len, eax
                                      invoke  Alloc,len
                                      mov     dword ptr [arrayWrite], eax
                                      xor     ecx,ecx
                                Goon:
                                      mov eax, dword ptr [arrayWrite]
                                      add eax, ecx
                                      mov byte ptr[eax], 41h
                                      inc ecx
                                      cmp ecx, len
                                      jb Goon   
                                      invoke SetFilePointer, hFile, pos, NULL, FILE_BEGIN
                                      invoke WriteFile, hFile, arrayWrite, len, offset nBytesRead, NULL   
                                      ; 修改节表
                                      mov    eax, section_header.SizeOfRawData
                                      mov    section_header.Misc.VirtualSize, eax
                                      invoke SetFilePointer, hFile, sectionHeaderPos, NULL, FILE_BEGIN
                                      invoke WriteFile, hFile, offset section_header, sizeof IMAGE_SECTION_HEADER, offset nBytesRead, NULL                  
                                      invoke Free, dword ptr [arrayWrite]
                                      inc  ebx
                                      dec  esi
                                      cmp  esi,0
                                      ja   LoopSections
                               NoSection:
                                             invoke CloseHandle, hFile
                                             invoke MessageBox, NULL, offset successTip, offset szTitle, MB_OK     
                               .endif
                        .endif
        .endif
@@:
        invoke ExitProcess,0
end Start


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 7
支持
分享
最新回复 (12)
雪    币: 69
活跃值: (342)
能力值: ( LV9,RANK:550 )
在线值:
发帖
回帖
粉丝
2
PE程序自免疫技术程序设计二:禁止插入新节
原理:
以附加方式感染的病毒,要添加新节就必须同时插入一个对应的新节表。能够插入新节表的前提是最后一个节表与第一个节区之间足以放下一个节表结构。而很多情况下编译器生成的可执行文件在上述之间还余有足够放多个节表的空间。
如果把文件头和节表下移,且修改定位文件头位置的指针(DOS头结构字段e_lfanew),那么病毒就无法插入新节了。

代码实现:
(1) 得到节区个数
由DOS头结构字段e_lfanew定位PE头结构位置,读取PE头,在其包含的文件头中得到节个数字段NumberOfSections。
(2)         分配缓冲区,将PE头结构和所有节表读到缓冲区。
(3)         计算移动到的文件偏移,移动数据的长度为PE头结构大小(sizeof(IMAGE_NT_HEADERS))加上所有节表结构的大小为(sizeof(IMAGE_SECTION_HEADER)*nt_header.FileHeader.NumberOfSections)。移动到的位置为第一节区的文件偏移(psection_header[0].PointerToRawData),减去移动数据的长度。将缓冲区数据写入文件该位置。
(4)        修改DOS头结构e_lfanew,并将该结构重新写入原位置。

下面是我自己讲《Windows信息安全原理与实践》中书上的VC程序改写成汇编语言的。
.586p
.model flat, stdcall
option casemap :none   ; case sensitive
include c:\masm32\include\windows.inc
include c:\masm32\include\kernel32.inc
includelib c:\masm32\lib\kernel32.lib
include c:\masm32\include\user32.inc
includelib c:\masm32\lib\user32.lib
include        c:\masm32\include\comdlg32.inc
includelib c:\masm32\lib\comdlg32.lib
include c:\masm32\include\masm32.inc   ;这是Alloc函数所需的文件
includelib c:\masm32\lib\masm32.lib    ;这是Alloc函数所需的Lib文件

.data
        stOFAddr        OPENFILENAME  <>
        szTitle         db            "ChangeSection",0
        szFileName        db              MAX_PATH dup (?)
        szExtPe                db              'PE Files',0,'*.exe;*.dll;*.scr;*.fon;*.drv',0
                        db              'All Files(*.*)',0,'*.*',0,0
        hFile           dd            ?
        dos_header      IMAGE_DOS_HEADER <>
        nt_header       IMAGE_NT_HEADERS <>
        section_header  IMAGE_SECTION_HEADER <>
        nBytesRead      dd            ?
        pos             dd            ?
        len             dd            ?
        endPoint        dd            ?
        arrayWrite      dd            ?
        sectionHeaderPos dd           ?
        successTip      db            "    ProtectSection Succeded!   ",0
.code

Start:
        invoke        RtlZeroMemory,offset stOFAddr,sizeof OPENFILENAME
        mov        stOFAddr.lStructSize,sizeof OPENFILENAME
        push        NULL
        pop        stOFAddr.hwndOwner
        mov        stOFAddr.lpstrFilter,offset szExtPe
        mov        stOFAddr.lpstrFile,offset szFileName
        mov        stOFAddr.nMaxFile,MAX_PATH
        mov        stOFAddr.Flags,OFN_PATHMUSTEXIST or OFN_FILEMUSTEXIST
        invoke        GetOpenFileName,offset stOFAddr
        .if        ! eax
                jmp        @F
        .endif
        invoke        CreateFile,offset szFileName,GENERIC_ALL ,FILE_SHARE_READ or \
                        FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL
        .if        eax !=        INVALID_HANDLE_VALUE
                        mov        hFile,eax
                        invoke ReadFile, hFile, offset dos_header, sizeof IMAGE_DOS_HEADER, offset nBytesRead, NULL       
                        movzx     eax,  dos_header.e_magic
                        ;检查PE文件是否有效
                        .if     eax == 5a4dh
                               invoke SetFilePointer, hFile, dos_header.e_lfanew, NULL, FILE_BEGIN
                               invoke ReadFile, hFile, offset nt_header, sizeof IMAGE_NT_HEADERS, offset nBytesRead, NULL
                               .if    nt_header.Signature == 4550h
                                      movzx   esi,nt_header.FileHeader.NumberOfSections
                                      cmp     esi,1
                                      jb      NoSection
                                      xor     ebx, ebx
                                      ;读取第一个节表
                                      invoke ReadFile, hFile, offset section_header, sizeof IMAGE_SECTION_HEADER, offset nBytesRead, NULL
                                      
                                      mov  eax, section_header.PointerToRawData
                                      mov  endPoint, eax
                                      mov  eax, sizeof IMAGE_NT_HEADERS
                                      mov  ebx, sizeof IMAGE_SECTION_HEADER
                                      imul ebx, esi
                                      add  eax, ebx
                                      mov  len, eax
                                      mov  eax, endPoint
                                      sub  eax, len
                                      mov  pos, eax
                                      invoke  Alloc,len
                                      mov     dword ptr [arrayWrite], eax
                                     
                                      invoke SetFilePointer, hFile, dos_header.e_lfanew, NULL, FILE_BEGIN
                                      invoke ReadFile, hFile, arrayWrite, len, offset nBytesRead, NULL
                                      invoke SetFilePointer, hFile, pos, NULL, FILE_BEGIN
                                      invoke WriteFile, hFile, arrayWrite, len, offset nBytesRead, NULL
                                      mov    eax, pos
                                      mov    dos_header.e_lfanew,eax
                                      invoke SetFilePointer, hFile, 0, NULL, FILE_BEGIN
                                      invoke WriteFile, hFile, offset dos_header, sizeof IMAGE_DOS_HEADER, offset nBytesRead, NULL
                               NoSection:
                                             invoke CloseHandle, hFile
                                             invoke MessageBox, NULL, offset successTip, offset szTitle, MB_OK     
                               .endif
                        .endif
        .endif
@@:
        invoke ExitProcess,0
end Start
2009-4-29 08:06
0
雪    币: 69
活跃值: (342)
能力值: ( LV9,RANK:550 )
在线值:
发帖
回帖
粉丝
3
呵呵,好久没出来了,工作后忙起来了,偶有空闲看到这个程序,担心自己被繁琐事情搞得技术全无了,学习了下,就当做熟悉汇编了,我希望给初学者一点点帮助。高手飘啊飘,不要笑话了。
2009-4-29 08:09
0
雪    币: 69
活跃值: (342)
能力值: ( LV9,RANK:550 )
在线值:
发帖
回帖
粉丝
4
前段时间因为单位需要,破解了一个网络教室的软件,该软件采用狗加密,我觉得打狗过程还是挺有意思的,对于初学者还是挺有帮助的。但是是国产软件,我想不注明是什么软件,只讲打狗过程,老大们觉得可行吗?
2009-4-29 08:13
0
雪    币: 91
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
欢迎打狗的 ;)

文章不错, 就是没有看懂;(
2009-4-29 08:22
0
雪    币: 1373
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
好呀,最好是屏幕录像。
2009-4-29 13:55
0
雪    币: 270
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
“插入方式的PE文件型病毒利用了每个字节对齐原因,程序实际的代码或数据可能没有占满该节,还有不少空余字节空间,病毒在空白区插入病毒”
有搞头...
  学习了!
2009-4-29 17:38
0
雪    币: 279
活跃值: (160)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
8
好文顶一下..
学习之..
2009-4-29 18:21
0
雪    币: 30
活跃值: (750)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
SizeOfRawData减去VirtualSize的大小就是剩余空间的大小
    我可以通过判断是否是IAT 的末尾, 来找到剩余空间开始位置。。。。。。。
2009-4-29 19:12
0
雪    币: 474
活跃值: (96)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
期待楼主的打狗教程!
2009-4-30 09:20
0
雪    币: 1450
活跃值: (35)
能力值: (RANK:680 )
在线值:
发帖
回帖
粉丝
11
第一种填充随机数据的方法,对于经典空隙感染的确是很有效的。
第二种将各节上移防止增加节的做法则比较一般,你能移动节表,病毒也能移动。

其实如果为了达到防止病毒“轻松的”增加节的目的,你还得擦掉exe的重定位节及其节表。
2009-4-30 13:45
0
雪    币: 69
活跃值: (342)
能力值: ( LV9,RANK:550 )
在线值:
发帖
回帖
粉丝
12
道高一尺,魔高一丈,我只是介绍点皮毛知识了。防病毒路很长,我想过段时间会推出一片简单的修改EXE文件,给EXE文件添加节。
鉴于大家对打狗热情这样强,我会写一篇简单的打狗文章,当然水平有限,不要期望太高。
2009-4-30 14:28
0
雪    币: 1450
活跃值: (35)
能力值: (RANK:680 )
在线值:
发帖
回帖
粉丝
13
呵呵,支持LZ的打狗文章。这方面文章很少的。
期待ing...
2009-4-30 16:21
0
游客
登录 | 注册 方可回帖
返回
//