?? spp_rpc_decode.c
字號:
} /* check the port list */ if(!(RpcDecodePorts[(p->dp/8)] & (1<<(p->dp%8)))) { return; } PREPROC_PROFILE_START(rpcdecodePerfStats); ret = ConvertRPC(p); DEBUG_WRAP(DebugMessage(DEBUG_RPC,"Got ret: %d from ConvertRPC\n", ret);); if(ret != 0) { switch(ret) { case RPC_FRAG_TRAFFIC: if(rpcpreprocdata.alert_fragments) { SnortEventqAdd(GENERATOR_SPP_RPC_DECODE, RPC_FRAG_TRAFFIC, 1, RPC_CLASS, 3, RPC_FRAG_TRAFFIC_STR, 0); } break; case RPC_MULTIPLE_RECORD: if(rpcpreprocdata.alert_multi) { SnortEventqAdd(GENERATOR_SPP_RPC_DECODE, RPC_MULTIPLE_RECORD, 1, RPC_CLASS, 3, RPC_MULTIPLE_RECORD_STR, 0); } break; case RPC_LARGE_FRAGSIZE: if(rpcpreprocdata.alert_large) { SnortEventqAdd(GENERATOR_SPP_RPC_DECODE, RPC_LARGE_FRAGSIZE, 1, RPC_CLASS, 3, RPC_LARGE_FRAGSIZE_STR, 0); } break; case RPC_INCOMPLETE_SEGMENT: if(rpcpreprocdata.alert_incomplete) { SnortEventqAdd(GENERATOR_SPP_RPC_DECODE, RPC_INCOMPLETE_SEGMENT, 1, RPC_CLASS, 3, RPC_INCOMPLETE_SEGMENT_STR, 0); } break; case RPC_ZERO_LENGTH_FRAGMENT: if(rpcpreprocdata.alert_multi) { SnortEventqAdd(GENERATOR_SPP_RPC_DECODE, RPC_ZERO_LENGTH_FRAGMENT, 1, RPC_CLASS, 3, RPC_ZERO_LENGTH_FRAGMENT_STR, 0); } break; } } PREPROC_PROFILE_END(rpcdecodePerfStats); return; }/* most significant bit */#define MSB 0x80000000/* * For proto ref, see rfc1831 section 10 and page 445 UNP vol2 * * check to make sure we've got enough data to process a record * * Where did the original 16 come from? It seems that it could be * a last frag of 0 length according to spec. * * The minimum "valid" packet for us is 8 fields * 4 bytes * * This decoder is ignorant of TCP state so we'll have to assume * that reassembled TCP stuff is reinjected to the preprocessor * chain * * This decoder is also ignorant of multiple RPC requests in a * single stream. To compensate, we can configure alerts * * Additionally, we don't do anything to verify that this is * really an RPC service port so we don't decode anything that * happens as a result * * From rfc1831: * * Fragment Header ( 1 flag bit, 31 bit uint ) * RPC Body * * unsigned int xid * struct call_body { * unsigned int rpcvers; // must be equal to two (2) * unsigned int prog; * unsigned int vers; * unsigned int proc; * opaque_auth cred; * opaque_auth verf; * } */int ConvertRPC(Packet *p){ const u_int8_t *data = p->data; /* packet data */ u_int8_t *norm_index; u_int8_t *data_index; /* this is the index pointer to walk thru the data */ u_int8_t *data_end; /* points to the end of the payload for loop control */ u_int16_t psize = p->dsize; /* payload size */ int length; /* length of current fragment */ int last_fragment = 0; /* have we seen the last fragment sign? */ int decoded_len; /* our decoded length is always atleast a 0 byte header */ u_int32_t fraghdr; /* Used to store the RPC fragment header data */ int fragcount = 0; /* How many fragment counters have we seen? */ int ret; u_int8_t *decode_buf_start = &DecodeBuffer[0]; u_int8_t *decode_buf_end = decode_buf_start + DECODE_BLEN; if(psize < 32) { DEBUG_WRAP(DebugMessage(DEBUG_RPC, "Returning due to" " small packet size: %d\n ", psize);); return 0; } /* on match, normalize the data */ DEBUG_WRAP(DebugMessage(DEBUG_RPC, "Got RPC traffic (%d bytes)!\n", psize);); /* cheesy alignment safe fraghdr = *(uint32_t *) data*/ *((u_int8_t *) &fraghdr) = data[0]; *(((u_int8_t *) &fraghdr) + 1) = data[1]; *(((u_int8_t *) &fraghdr) + 2) = data[2]; *(((u_int8_t *) &fraghdr) + 3) = data[3]; /* The fragment header is 4 bytes in network byte order */ fraghdr = ntohl(fraghdr); length = fraghdr & 0x7FFFFFFF; /* Check to see if we are on the last fragment */ if(fraghdr & MSB) { /* on match, normalize the data */ DEBUG_WRAP(DebugMessage(DEBUG_RPC, "Found Last Fragment: %u!\n",fraghdr);); if((length + 4 != psize) && !(p->packet_flags & PKT_REBUILT_STREAM)) { DEBUG_WRAP(DebugMessage(DEBUG_RPC, "It's not the only thing in this buffer!" " length: %d psize: %d!\n", length, psize);); return RPC_MULTIPLE_RECORD; } else if ( length == 0 ) { DEBUG_WRAP(DebugMessage(DEBUG_RPC, "Zero-length RPC fragment detected." " length: %d psize: %d.\n", length, psize);); return RPC_ZERO_LENGTH_FRAGMENT; } return 0; } else if(rpcpreprocdata.alert_fragments) { return RPC_FRAG_TRAFFIC; } norm_index = &DecodeBuffer[0]; data_index = (u_int8_t *)data; data_end = (u_int8_t *)data + psize; /* now we know it's in fragmented records, 4 bytes of * header(of which the most sig bit fragment (0=yes 1=no). * The header is followed by the value move pointer up 4 * bytes, we need to stuff header in first 4 bytes. * But the header has the total length...we don't know * until the end */ /* This is where decoded data will be written */ norm_index += 4; decoded_len = 4; /* always make sure that we have enough data to process atleast * the header and that we only process at most, one fragment */ while(((data_end - data_index) >= 4) && (last_fragment == 0)) { /* get the fragment length (31 bits) and move the pointer to the start of the actual data */ *((u_int8_t *) &fraghdr) = data_index[0]; *(((u_int8_t *) &fraghdr) + 1) = data_index[1]; *(((u_int8_t *) &fraghdr) + 2) = data_index[2]; *(((u_int8_t *) &fraghdr) + 3) = data_index[3]; fraghdr = ntohl(fraghdr); length = fraghdr & 0x7FFFFFFF; /* move the current index into the packet past the fragment header */ data_index += 4; if(fraghdr & MSB) { DEBUG_WRAP(DebugMessage(DEBUG_RPC, "Last Fragment detected\n");); last_fragment = 1; } if((length + decoded_len) < decoded_len) { /* don't allow integer overflow to confuse us. Should be * caught by length > psize but who knows when weird * psize's might be allowed */ DEBUG_WRAP(DebugMessage(DEBUG_RPC, "Integer Overflow" " field(%d) exceeds packet size(%d)\n", length, psize);); return RPC_LARGE_FRAGSIZE; } decoded_len += length; if(length > psize) { DEBUG_WRAP(DebugMessage(DEBUG_RPC, "Length of" " field(%d) exceeds packet size(%d)\n", length, psize);); return RPC_INCOMPLETE_SEGMENT; } else if(decoded_len > psize) { /* The entire request is larger than our current packet * size */ DEBUG_WRAP(DebugMessage(DEBUG_RPC, " Decoded Length (%d)" "exceeds packet size(%d)\n", decoded_len, psize);); return RPC_LARGE_FRAGSIZE; } else if((data_index + length) > data_end) { DEBUG_WRAP(DebugMessage(DEBUG_RPC, "returning LARGE_FRAGSIZE" "since we'd read past our end\n");); return RPC_LARGE_FRAGSIZE; } else { fragcount++; DEBUG_WRAP(DebugMessage(DEBUG_RPC, "length: %d size: %d decoded_len: %d\n", length, psize, decoded_len);); ret = SafeMemcpy(norm_index, data_index, length, decode_buf_start, decode_buf_end); if (ret != SAFEMEM_SUCCESS) { return 0; } norm_index += length; data_index += length; } } /* rewrite the header on the request packet */ /* move the fragment header back onto the data */ fraghdr = ntohl(decoded_len); /* size */ DecodeBuffer[0] = *((u_int8_t *) &fraghdr); DecodeBuffer[1] = *(((u_int8_t *) &fraghdr) + 1); DecodeBuffer[2] = *(((u_int8_t *) &fraghdr) + 2); DecodeBuffer[3] = *(((u_int8_t *) &fraghdr) + 3); DecodeBuffer[0] |= 0x80; /* Mark as unfragmented */ /* is there another request encoded that is trying to evade us by doing * * frag last frag [ more data ]? */ if(decoded_len + ((fragcount - 1) * 4) != psize) { DEBUG_WRAP(DebugMessage(DEBUG_RPC, "decoded len does not compute: %d\n", decoded_len);); return RPC_MULTIPLE_RECORD; } DEBUG_WRAP(DebugMessage(DEBUG_RPC, "New size: %d\n", decoded_len); DebugMessage(DEBUG_RPC, "converted data:\n"); //PrintNetData(stdout, data, decoded_len); ); p->alt_dsize = decoded_len; p->packet_flags |= PKT_ALT_DECODE; return 0;}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -