Jun 29, 2011

Shell code 2 (cont.)

After the previous article, I wrote a program which use a shell code to exit normally.
However, there is a more simple way to accomplish this job. We can use the linux system call.

In linux, when you want to use a system call in assembly, just use the int $0x80.
The system call number is store in the %eax, and the parameter of the system call is store in the %ebx and so on.

Ok, it's time to use these information and write them into shell code.

First write a normal program and use inline assembly in the program.

exit.c
int main(){
     __asm__("movw $1, %eax;\
              movw $0, %ebx;\
              int  $0x80;");
     return 0;
}


and now compile it with the following command.
gcc -static -g -o exit.out exit.c
objdump -d exit.out >> dump.txt
dump.txt main function

080482c0 <main>:
 80482c0:       55                      push   %ebp
 80482c1:       89 e5                   mov    %esp,%ebp
 80482c3:       b8 01 00 00 00          mov    $0x1,%eax
 80482c8:       bb 00 00 00 00          mov    $0x0,%ebx
 80482cd:       cd 80                   int    $0x80
 80482cf:       b8 00 00 00 00          mov    $0x0,%eax
 80482d4:       5d                      pop    %ebp
 80482d5:       c3                      ret
the machine code part is what we need.
Let's change them into shell code.

exit_shell.c

char shellcode[]=
"\xb8\x01\x00\x00\x00"
"\xbb\x00\x00\x00\x00"
"\xcd\x80";
int main(){
        int *ptr;
        int i;
        for(i=0;i<10;i++){
                ptr = (int*)&ptr+i;
                *(ptr) = (int)shellcode;
        }
        return 0;
}
P.S The for loop is to overflow the return address and transfer the execution flow to the shellcode.
compile it with the following and remember to use the execstack to enable the executable stack.
gcc -static -g -o exit_shell.out exit_shell.c
execstack -s exit_shell.out


Result:
now use gdb to verify our thoughts.
(gdb) disassem main
Dump of assembler code for function main:
   0x080482c0 <+0>: push   %ebp
   0x080482c1 <+1>: mov    %esp,%ebp
   0x080482c3 <+3>: sub    $0x10,%esp
   0x080482c6 <+6>: movl   $0x0,-0x8(%ebp)
   0x080482cd <+13>: jmp    0x80482eb <main+43>
   0x080482cf <+15>: lea    -0x4(%ebp),%eax
   0x080482d2 <+18>: mov    -0x8(%ebp),%edx
   0x080482d5 <+21>: shl    $0x2,%edx
   0x080482d8 <+24>: add    %edx,%eax
   0x080482da <+26>: mov    %eax,-0x4(%ebp)
   0x080482dd <+29>: mov    -0x4(%ebp),%eax
   0x080482e0 <+32>: mov    $0x80ce028,%edx
   0x080482e5 <+37>: mov    %edx,(%eax)
   0x080482e7 <+39>: addl   $0x1,-0x8(%ebp)
   0x080482eb <+43>: cmpl   $0x9,-0x8(%ebp)
   0x080482ef <+47>: jle    0x80482cf <main+15>
   0x080482f1 <+49>: mov    $0x0,%eax
   0x080482f6 <+54>: leave  
   0x080482f7 <+55>: ret    
End of assembler dump.
(gdb) b *(main+55)
Breakpoint 1 at 0x80482f7: file exit_shell.c, line 12.
(gdb) r
Breakpoint 1, 0x080482f7 in main () at exit_shell.c:12
12 }
(gdb) ni
0x080ce028 in shellcode ()
(gdb) x/4i $eip
=> 0x80ce028 <shellcode>: mov    $0x1,%eax
   0x80ce02d <shellcode+5>: mov    $0x0,%ebx
   0x80ce032 <shellcode+10>: int    $0x80
   0x80ce034 <shellcode+12>: add    %al,(%eax)
(gdb) ni
0x080ce02d in shellcode ()
(gdb) ni
0x080ce032 in shellcode ()
(gdb) ni
Program exited normally.
The result is just what we expected. When main function returned, it will start execute the shellcode.
And exited normally.
video demo is right here (using full screen is better):
http://www.youtube.com/watch?v=I6iYFQl-3kk&feature=player_embedded#at=14





No comments:

Post a Comment

Labels