📄 spp_bo.c
字号:
if ( drop_flags & BO_ALERT_SERVER ) LogMessage(" server"); if ( drop_flags & BO_ALERT_GENERAL ) LogMessage(" general"); if ( drop_flags & BO_ALERT_SNORT_ATTACK ) LogMessage(" snort_attack"); LogMessage("\n"); }}/* * Function: BoRand() * * Purpose: Back Orifice "encryption" algorithm * * Arguments: None. * * Returns: key to XOR with current char to be "encrypted" */static char BoRand(){ holdrand = holdrand * 214013L + 2531011L; return (char) (((holdrand >> 16) & 0x7fff) & 0xFF);}/* * Precalculate the known cyphertext into a prefix and suffix lookup table * to recover the key. Using this in the BoFind() function below is much * faster than the old brute force method */static void PrecalcPrefix(){ u_int8_t cookie_cyphertext[BACKORIFICE_MAGIC_SIZE]; char *cookie_plaintext = "*!*QWTY?"; int key; int cookie_index; char *cp_ptr; /* cookie plaintext indexing pointer */ u_int16_t cyphertext_referent; memset(&lookup1[0], 0, sizeof(lookup1)); memset(&lookup2[0], 0, sizeof(lookup2)); for(key=0;key<65536;key++) { /* setup to generate cyphertext for this key */ holdrand = key; cp_ptr = cookie_plaintext; /* convert the plaintext cookie to cyphertext for this key */ for(cookie_index=0;cookie_index<BACKORIFICE_MAGIC_SIZE;cookie_index++) { cookie_cyphertext[cookie_index] =(u_int8_t)(*cp_ptr^(BoRand())); cp_ptr++; } /* * generate the key lookup mechanism from the first 2 characters of * the cyphertext */ cyphertext_referent = (u_int16_t) (cookie_cyphertext[0] << 8) & 0xFF00; cyphertext_referent |= (u_int16_t) (cookie_cyphertext[1]) & 0x00FF; /* if there are any keyspace collisions that's going to suck */ if(lookup1[cyphertext_referent][0] != 0) { if(lookup1[cyphertext_referent][1] != 0) { lookup1[cyphertext_referent][2] = (u_int16_t)key; } else { lookup1[cyphertext_referent][1] = (u_int16_t)key; } } else { lookup1[cyphertext_referent][0] = (u_int16_t)key; } /* * generate the second lookup from the last two characters of * the cyphertext */ cyphertext_referent = (u_int16_t) (cookie_cyphertext[6] << 8) & 0xFF00; cyphertext_referent |= (u_int16_t) (cookie_cyphertext[7]) & 0x00FF; /* * set the second lookup with the current key */ lookup2[key] = cyphertext_referent; }}/* * Function: BoFind(Packet *) * * Purpose: Look for the magic cookie, squawk if you find it. * * Arguments: p => pointer to the current packet data struct * * Returns: void function * * */void BoFind(Packet *p, void *context){ u_int16_t cyphertext_referent; u_int16_t cyphertext_suffix; u_int16_t key; char *magic_cookie = "*!*QWTY?"; char *pkt_data; char *magic_data; char *end; char plaintext; int i; int bo_direction = 0; PROFILE_VARS; /* make sure it's UDP and that it's at least 19 bytes long */ if(!PacketIsUDP(p)) { DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, " -> spp_bo: Not UDP\n");); return; } if(p->dsize < BACKORIFICE_MIN_SIZE) { return; } PREPROC_PROFILE_START(boPerfStats); /* * take the first two characters of the packet and generate the * first reference that gives us a reference key */ cyphertext_referent = (u_int16_t) (p->data[0] << 8) & 0xFF00; cyphertext_referent |= (u_int16_t) (p->data[1]) & 0x00FF; /* * generate the second referent from the last two characters * of the cyphertext */ cyphertext_suffix = (u_int16_t) (p->data[6] << 8) & 0xFF00; cyphertext_suffix |= (u_int16_t) (p->data[7]) & 0x00FF; for(i=0;i<3;i++) { /* get the key from the cyphertext */ key = lookup1[cyphertext_referent][i]; /* * if the lookup from the proposed key matches the cyphertext reference * then we've probably go the right key and can proceed to full * decryption using the key * * moral of the story: don't use a lame keyspace */ if(lookup2[key] == cyphertext_suffix) { holdrand = key; pkt_data = (char*)p->data; end = (char*)p->data + BACKORIFICE_MAGIC_SIZE; magic_data = magic_cookie; while(pkt_data<end) { plaintext = (char) (*pkt_data ^ BoRand()); if(*magic_data != plaintext) { DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Failed check one on 0x%X : 0x%X\n", *magic_data, plaintext);); PREPROC_PROFILE_END(boPerfStats); return; } magic_data++; pkt_data++; } /* if we fall thru there's a detect */ DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Detected Back Orifice Data!\n"); DebugMessage(DEBUG_PLUGIN, "hash value: %d\n", key);); bo_direction = BoGetDirection(p, pkt_data); if ( bo_direction == BO_FROM_CLIENT ) { if ( !(noalert_flags & BO_ALERT_CLIENT) ) { SnortEventqAdd(GENERATOR_SPP_BO, BO_CLIENT_TRAFFIC_DETECT, 1, 0, 0, BO_CLIENT_TRAFFIC_DETECT_STR, 0); } if ( (drop_flags & BO_ALERT_CLIENT) && InlineMode() ) { InlineDrop(p); } DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Client packet\n");); } else if ( bo_direction == BO_FROM_SERVER ) { if ( !(noalert_flags & BO_ALERT_SERVER) ) { SnortEventqAdd(GENERATOR_SPP_BO, BO_SERVER_TRAFFIC_DETECT, 1, 0, 0, BO_SERVER_TRAFFIC_DETECT_STR, 0); } if ( (drop_flags & BO_ALERT_SERVER) && InlineMode() ) { InlineDrop(p); } DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Server packet\n");); } else { if ( !(noalert_flags & BO_ALERT_GENERAL) ) { SnortEventqAdd(GENERATOR_SPP_BO, BO_TRAFFIC_DETECT, 1, 0, 0, BO_TRAFFIC_DETECT_STR, 0); } if ( (drop_flags & BO_ALERT_GENERAL) && InlineMode() ) { InlineDrop(p); } } } } PREPROC_PROFILE_END(boPerfStats); return;}/* * Function: BoGetDirection(Packet *) * * Purpose: Attempt to guess the direction this packet is going in. * * Arguments: p => pointer to the current packet data struct * pkt_data => pointer to data after magic cookie * * Returns: BO_FROM_UNKNOWN if direction unknown * BO_FROM_CLIENT if direction from client to server * BO_FROM_SERVER if direction from server to client * * Reference: http://www.magnux.org/~flaviovs/boproto.html * BO header structure: * Mnemonic Size in bytes * ------------------------- * MAGIC 8 * LEN 4 * ID 4 * T 1 * DATA variable * CRC 1 * */static int BoGetDirection(Packet *p, char *pkt_data){ u_int32_t len = 0; u_int32_t id = 0; u_int32_t l, i; char type; static char buf1[BO_BUF_SIZE]; char plaintext; /* Check for the default port on either side */ if ( p->dp == BACKORIFICE_DEFAULT_PORT ) { return BO_FROM_CLIENT; } else if ( p->sp == BACKORIFICE_DEFAULT_PORT ) { return BO_FROM_SERVER; } /* Didn't find default port, so look for ping packet */ /* Get length from BO header - 32 bit int */ for ( i = 0; i < 4; i++ ) { plaintext = (char) (*pkt_data ^ BoRand()); l = (u_int32_t) plaintext; len += l << (8*i); pkt_data++; } /* Get ID from BO header - 32 bit int */ for ( i = 0; i < 4; i++ ) { plaintext = (char) (*pkt_data ^ BoRand() ); l = ((u_int32_t) plaintext) & 0x000000FF; id += l << (8*i); pkt_data++; } DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Data length = %lu\n", len);); DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "ID = %lu\n", id);); /* Do more len checking */ if ( len >= BO_BUF_ATTACK_SIZE ) { if ( !(noalert_flags & BO_ALERT_SNORT_ATTACK) ) { SnortEventqAdd(GENERATOR_SPP_BO, BO_SNORT_BUFFER_ATTACK, 1, 0, 0, BO_SNORT_BUFFER_ATTACK_STR, 0); } if ( (drop_flags & BO_ALERT_SNORT_ATTACK) && InlineMode() ) { InlineDrop(p); } return BO_FROM_UNKNOWN; } /* Adjust for BO packet header length */ if (len <= BACKORIFICE_MIN_SIZE) { /* Need some data, or we can't figure out client or server */ return BO_FROM_UNKNOWN; } else { len -= BACKORIFICE_MIN_SIZE; } if( len > 7 ) { len = 7; /* we need no more than 7 variable chars */ } /* Continue parsing BO header */ type = (char) (*pkt_data ^ BoRand()); pkt_data++; /* check to make sure we don't run off end of packet */ if ((u_int32_t)(p->dsize - ((u_int8_t *)pkt_data - p->data)) < len) { /* We don't have enough data to inspect */ return BO_FROM_UNKNOWN; } if ( type & 0x80 ) { DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Partial packet\n");); } if ( type & 0x40 ) { DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Continued packet\n");); } /* Extract type of BO packet */ type = type & 0x3F; DEBUG_WRAP(DebugMessage(DEBUG_PLUGIN, "Type = 0x%x\n", type);); /* Only examine data if this is a ping request or response */ if ( type == BO_TYPE_PING ) { if ( len < 7 ) { return BO_FROM_CLIENT; } for(i=0;i<len;i++ ) /* start at 0 to advance the BoRand() function properly */ { buf1[i] = (char) (pkt_data[i] ^ BoRand()); if ( buf1[i] == 0 ) { return BO_FROM_UNKNOWN; } } if( ( buf1[3] == 'P' || buf1[3] == 'p' ) && ( buf1[4] == 'O' || buf1[4] == 'o' ) && ( buf1[5] == 'N' || buf1[5] == 'n' ) && ( buf1[6] == 'G' || buf1[6] == 'g' ) ) { return BO_FROM_SERVER; } else { return BO_FROM_CLIENT; } } return BO_FROM_UNKNOWN;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -