Handle<Value> NovaNode::GetSuspectDetailsString(const Arguments &args) { HandleScope scope; string details; string suspectIp = cvv8::CastFromJS<string>(args[0]); string suspectInterface = cvv8::CastFromJS<string>(args[1]); struct in_addr address; inet_pton(AF_INET, suspectIp.c_str(), &address); SuspectIdentifier id; id.m_ip = htonl(address.s_addr); id.m_interface = suspectInterface; Suspect *suspect = GetSuspectWithData(id); if (suspect != NULL) { details = suspect->ToString(); details += "\n"; details += suspect->GetFeatureSet().toString(); delete suspect; } else { details = "Unable to complete request"; } return scope.Close(cvv8::CastToJS(details)); }
void PrintSuspectData(in_addr_t address, string interface) { Connect(); SuspectIdentifier id(ntohl(address), interface); Suspect *suspect = GetSuspectWithData(id); if (suspect != NULL) { cout << suspect->ToString() << endl; cout << "Details follow" << endl; cout << suspect->GetFeatureSet(MAIN_FEATURES).toString() << endl; } else { cout << "Error: No suspect received" << endl; } delete suspect; CloseNovadConnection(); }
void update(const in_addr_t& key) { in_addr_t foo = key; suspects.ClassifySuspect(foo); //Check that we updated correctly Suspect suspectCopy = suspects.GetSuspect(foo); if(suspects.IsEmptySuspect(&suspectCopy)) { cout << "Got an empty suspect when trying to classify" << endl; return; } //Store in training file if needed trainingFileStream << string(inet_ntoa(suspectCopy.GetInAddr())) << " "; FeatureSet fs = suspectCopy.GetFeatureSet(MAIN_FEATURES); if(fs.m_features[0] != fs.m_features[0] ) { cout << "This can't be good..." << endl; } for(int j = 0; j < DIM; j++) { trainingFileStream << fs.m_features[j] << " "; } trainingFileStream << "\n"; }
// Update our internal suspect list to that of novad void NovaNode::SynchInternalList() { vector<in_addr_t> *suspects; suspects = GetSuspectList(SUSPECTLIST_ALL); if (suspects == NULL) { cout << "Failed to get suspect list" << endl; } for (uint i = 0; i < suspects->size(); i++) { Suspect *suspect = GetSuspect(suspects->at(i)); if (suspect != NULL) { HandleNewSuspect(suspect); if (m_suspects.count(suspect->GetIpAddress()) == 0) { delete m_suspects[suspect->GetIpAddress()]; } m_suspects[suspect->GetIpAddress()] = suspect; } else { cout << "Error: No suspect received" << endl; } } }
void ConvertCaptureToDump(std::string captureFolder) { engine = new ClassificationAggregator(); Database::Inst()->ClearAllSuspects(); if(chdir(Config::Inst()->GetPathHome().c_str()) == -1) { LOG(CRITICAL, "Unable to change folder to " + Config::Inst()->GetPathHome(), ""); } string dumpFile = captureFolder + "/nova.dump"; string pcapFile = captureFolder + "/capture.pcap"; string haystackFile = captureFolder + "/haystackIps.txt"; UpdateHaystackFeatures(haystackFile); trainingFileStream.open(dumpFile); if(!trainingFileStream.is_open()) { LOG(CRITICAL, "Unable to open the training capture file.", "Unable to open training capture file at: "+dumpFile); } FilePacketCapture capture(pcapFile); capture.SetPacketCb(HandleTrainingPacket); capture.Init(); capture.SetFilter(ConstructFilterString()); capture.StartCaptureBlocking(); LOG(DEBUG, "Done processing PCAP file.", ""); suspects.WriteToDatabase(); vector<Suspect> suspects = Database::Inst()->GetSuspects(SUSPECTLIST_ALL); for (int i = 0; i < suspects.size(); i++) { Suspect suspectCopy = suspects[i]; //Store in training file if needed trainingFileStream << suspectCopy.GetIpString() << " "; suspectCopy.GetFeatureSet(); EvidenceAccumulator fs = suspectCopy.GetFeatureSet(MAIN_FEATURES); if(fs.m_features[0] != fs.m_features[0] ) { cout << "This can't be good..." << endl; } for(int j = 0; j < DIM; j++) { trainingFileStream << fs.m_features[j] << " "; } trainingFileStream << "\n"; } trainingFileStream.close(); }
void MonitorCallback() { while (true) { if( ! Nova::ConnectToNovad() ) { LOG(ERROR, "CLI Unable to connect to Novad right now. Trying again in 3 seconds...",""); sleep(3); continue; } CallbackChange cb; CallbackHandler callbackHandler; Suspect s; do { cb = callbackHandler.ProcessCallbackMessage(); switch( cb.m_type ) { case CALLBACK_NEW_SUSPECT: cout << "Got new suspect: " << cb.m_suspect->GetIdString() << + " with classification of " << cb.m_suspect->GetClassification() << endl; // We get a suspect pointer and are responsible for deleting it delete cb.m_suspect; break; case CALLBACK_ERROR: cout << "WARNING: Recieved a callback error message!" << endl; break; case CALLBACK_ALL_SUSPECTS_CLEARED: cout << "Got notice that all suspects were cleared" << endl; break; case CALLBACK_SUSPECT_CLEARED: s.SetIdentifier(cb.m_suspectIP); cout << "Got a notice that suspect was cleared: " + s.GetIdString() << endl; break; case CALLBACK_HUNG_UP: cout << "Got CALLBACK_HUNG_UP" << endl; break; default: cout << "WARNING: Got a callback message we don't know what to do with. Type " << cb.m_type << endl; break; } } while(cb.m_type != CALLBACK_HUNG_UP); cout << "Novad hung up, closing callback processing and trying again in 3 seconds" << endl; sleep(3); } }
int NovaNode::HandleSuspectClearedOnV8Thread(eio_req* req) { HandleScope scope; Suspect* suspect = static_cast<Suspect*>(req->data); if (m_suspects.keyExists(suspect->GetIdentifier())) { delete m_suspects[suspect->GetIdentifier()]; } m_suspects.erase(suspect->GetIdentifier()); v8::Persistent<Value> weak_handle = Persistent<Value>::New(SuspectJs::WrapSuspect(suspect)); weak_handle.MakeWeak(suspect, &DoneWithSuspectCallback); Persistent<Value> argv[1] = { weak_handle }; m_SuspectClearedCallback->Call(m_SuspectClearedCallback, 1, argv); return 0; }
void NovaNode::NovaCallbackHandling(eio_req*) { using namespace Nova; CallbackChange cb; LOG(DEBUG, "Initializing Novad callback processing",""); CallbackHandler callbackHandler; m_callbackRunning = true; do { Suspect *s; cb = callbackHandler.ProcessCallbackMessage(); switch( cb.m_type ) { case CALLBACK_NEW_SUSPECT: HandleNewSuspect(cb.m_suspect); break; case CALLBACK_ERROR: HandleCallbackError(); break; case CALLBACK_ALL_SUSPECTS_CLEARED: HandleAllSuspectsCleared(); break; case CALLBACK_SUSPECT_CLEARED: s = new Suspect(); s->SetIdentifier(cb.m_suspectIP); LOG(DEBUG, "Got a clear callback request for a suspect on interface " + cb.m_suspectIP.m_interface, ""); HandleSuspectCleared(s); break; default: break; } } while(cb.m_type != CALLBACK_HUNG_UP); LOG(DEBUG, "Novad hung up, closing callback processing",""); m_callbackRunning = false; }
int NovaNode::HandleNewSuspectOnV8Thread(eio_req* req) { HandleScope scope; Suspect* suspect = static_cast<Suspect*>(req->data); if (suspect != NULL) { if (m_suspects.keyExists(suspect->GetIdentifier())) { delete m_suspects[suspect->GetIdentifier()]; } m_suspects[suspect->GetIdentifier()] = suspect; SendSuspect(suspect); } else { LOG(DEBUG, "HandleNewSuspectOnV8Thread got a NULL suspect pointer. Ignoring.", ""); } return 0; }
void PrintSuspect(in_addr_t address, string interface) { Connect(); SuspectIdentifier id(ntohl(address), interface); Suspect *suspect = GetSuspect(id); if(suspect != NULL) { cout << suspect->ToString() << endl; } else { cout << "Error: No suspect received" << endl; } delete suspect; CloseNovadConnection(); }
void PrintAllSuspects(enum SuspectListType listType, bool csv) { Connect(); vector<SuspectIdentifier> suspects = GetSuspectList(listType); // Print the CSV header if (csv) { cout << "IP,"; cout << "INTERFACE,"; for(int i = 0; i < DIM; i++) { cout << FeatureSet::m_featureNames[i] << ","; } cout << "CLASSIFICATION" << endl; } for(uint i = 0; i < suspects.size(); i++) { Suspect *suspect = GetSuspect(suspects.at(i)); if(suspect != NULL) { if(!csv) { cout << suspect->ToString() << endl; } else { cout << suspect->GetIpString() << ","; cout << suspect->GetIdentifier().m_interface << ","; for(int i = 0; i < DIM; i++) { cout << suspect->GetFeatureSet().m_features[i] << ","; } cout << suspect->GetClassification() << endl; } delete suspect; } else { cout << "Error: No suspect received" << endl; } } CloseNovadConnection(); }
void NovaNode::NovaCallbackHandling(eio_req*) { LOG(DEBUG, "Initializing Novad callback processing",""); while(true) { Nova::Message *message = DequeueUIMessage(); //If this is a callback for a specific operation if(message->m_contents.has_m_messageid()) { eio_nop(EIO_PRI_DEFAULT, NovaNode::HandleMessageWithIDOnV8Thread, message); continue; } switch(message->m_contents.m_type()) { case UPDATE_SUSPECT: { if(!message->m_suspects.empty()) { HandleNewSuspect(message->m_suspects[0]); } break; } case REQUEST_ALL_SUSPECTS_REPLY: { for(uint i = 0; i < message->m_suspects.size(); i++) { HandleNewSuspect(message->m_suspects[i]); } break; } case REQUEST_SUSPECT_REPLY: { break; } case UPDATE_ALL_SUSPECTS_CLEARED: { HandleAllSuspectsCleared(); break; } case UPDATE_SUSPECT_CLEARED: { Suspect *suspect = new Suspect(); suspect->SetIdentifier(message->m_contents.m_suspectid()); LOG(DEBUG, "Got a clear suspect response for a suspect on interface " + message->m_contents.m_suspectid().m_ifname(), ""); HandleSuspectCleared(suspect); break; } case REQUEST_PONG: { break; } case CONNECTION_SHUTDOWN: { break; } default: { HandleCallbackError(); break; } } delete message; } }
void *SilentAlarmLoop(void *ptr) { MaskKillSignals(); int sockfd; u_char buf[MAX_MSG_SIZE]; struct sockaddr_in sendaddr; if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { LOG(CRITICAL, "Unable to create the silent alarm socket.", "Unable to create the silent alarm socket: "+string(strerror(errno))); close(sockfd); exit(EXIT_FAILURE); } sendaddr.sin_family = AF_INET; sendaddr.sin_port = htons(Config::Inst()->GetSaPort()); sendaddr.sin_addr.s_addr = INADDR_ANY; memset(sendaddr.sin_zero, '\0', sizeof sendaddr.sin_zero); struct sockaddr *sockaddrPtr = (struct sockaddr*) &sendaddr; socklen_t sendaddrSize = sizeof sendaddr; if(::bind(sockfd, sockaddrPtr, sendaddrSize) == -1) { LOG(CRITICAL, "Unable to bind to the silent alarm socket.", "Unable to bind to the silent alarm socket: "+string(strerror(errno))); close(sockfd); exit(EXIT_FAILURE); } stringstream ss; ss << "sudo iptables -A INPUT -p udp --dport " << Config::Inst()->GetSaPort() << " -j REJECT" " --reject-with icmp-port-unreachable"; if(system(ss.str().c_str()) == -1) { LOG(ERROR, "Failed to update iptables.", ""); } ss.str(""); ss << "sudo iptables -A INPUT -p tcp --dport " << Config::Inst()->GetSaPort() << " -j REJECT --reject-with tcp-reset"; if(system(ss.str().c_str()) == -1) { LOG(ERROR, "Failed to update iptables.", ""); } if(listen(sockfd, SOCKET_QUEUE_SIZE) == -1) { LOG(CRITICAL, "Unable to listen on the silent alarm socket.", "Unable to listen on the silent alarm socket.: "+string(strerror(errno))); close(sockfd); exit(EXIT_FAILURE); } int connectionSocket, bytesRead; Suspect suspectCopy; //Accept incoming Silent Alarm TCP Connections while(1) { bzero(buf, MAX_MSG_SIZE); //Blocking call if((connectionSocket = accept(sockfd, sockaddrPtr, &sendaddrSize)) == -1) { LOG(CRITICAL, "Problem while accepting incoming silent alarm connection.", "Problem while accepting incoming silent alarm connection: "+string(strerror(errno))); continue; } if((bytesRead = recv(connectionSocket, buf, MAX_MSG_SIZE, MSG_WAITALL))== -1) { LOG(CRITICAL, "Problem while receiving incoming silent alarm connection.", "Problem while receiving incoming silent alarm connection: "+string(strerror(errno))); close(connectionSocket); continue; } for(uint i = 0; i < hostAddrs.size(); i++) { //If this is from ourselves, then drop it. if(hostAddrs[i].sin_addr.s_addr == sendaddr.sin_addr.s_addr) { close(connectionSocket); continue; } } CryptBuffer(buf, bytesRead, DECRYPT); in_addr_t addr = 0; memcpy(&addr, buf, 4); uint64_t key = addr; Suspect *newSuspect = new Suspect(); if(newSuspect->Deserialize(buf, MAX_MSG_SIZE, MAIN_FEATURE_DATA) == 0) { close(connectionSocket); continue; } //If this suspect exists, update the information if(suspects.IsValidKey(key)) { suspectCopy = suspects.CheckOut(key); suspectCopy.SetFlaggedByAlarm(true); FeatureSet fs = newSuspect->GetFeatureSet(MAIN_FEATURES); suspectCopy.AddFeatureSet(&fs, MAIN_FEATURES); suspects.CheckIn(&suspectCopy); // TODO: This looks like it may be a memory leak of newSuspect } //If this is a new suspect put it in the table else { newSuspect->SetIsHostile(false); newSuspect->SetFlaggedByAlarm(true); //We set isHostile to false so that when we classify the first time // the suspect will go from benign to hostile and be sent to the doppelganger module suspects.AddNewSuspect(newSuspect); } LOG(CRITICAL, string("Got a silent alarm!. Suspect: "+ newSuspect->ToString()), ""); if(!Config::Inst()->GetClassificationTimeout()) { UpdateAndClassify(newSuspect->GetIpAddress()); } close(connectionSocket); } close(sockfd); LOG(CRITICAL, "The code should never get here, something went very wrong.", ""); return NULL; }