|
|
@@ -1,5 +1,5 @@ |
|
|
|
// snf_HeaderFinder.cpp |
|
|
|
// Copyright (C) 2007 - 2009 ARM Research Labs, LLC. |
|
|
|
// Copyright (C) 2007 - 2020 ARM Research Labs, LLC. |
|
|
|
// See www.armresearch.com for the copyright terms. |
|
|
|
// |
|
|
|
// See snf_HeaderFinder.hpp for details |
|
|
@@ -9,8 +9,59 @@ |
|
|
|
#include "snfLOGmgr.hpp" |
|
|
|
#include "snfCFGmgr.hpp" |
|
|
|
|
|
|
|
namespace cd = codedweller; |
|
|
|
|
|
|
|
const int NumberOfByteValues = 256; // Number of possible byte values. |
|
|
|
|
|
|
|
const bool HeaderFinderPattern::operator<(const HeaderFinderPattern& R) const { // Comparator for set<> living. |
|
|
|
if(Header < R.Header) { // If the Header name is < then true! |
|
|
|
return true; |
|
|
|
} else |
|
|
|
if(Header == R.Header) { // If the Header name is == then |
|
|
|
if(Ordinal < R.Ordinal) { // check the Ordinal. If it's < then |
|
|
|
return true; // true! |
|
|
|
} else |
|
|
|
if(Ordinal == R.Ordinal) { // If the Ordinal == then |
|
|
|
if(Contains < R.Contains) { // check the Contains. If it is < then |
|
|
|
return true; // true! |
|
|
|
} else |
|
|
|
if(Context < R.Context) { |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
return false; // In all other cases this is not < R |
|
|
|
} |
|
|
|
|
|
|
|
HeaderFinderPattern::HeaderFinderPattern(const HeaderFinderPattern& P) { // Copy constructor. |
|
|
|
Header = P.Header; |
|
|
|
Ordinal = P.Ordinal; |
|
|
|
Context = P.Context; |
|
|
|
Directive = P.Directive; |
|
|
|
Contains = P.Contains; |
|
|
|
} |
|
|
|
|
|
|
|
void HeaderFinderPattern::clear() { // Do this to make fresh and clean. |
|
|
|
Header.clear(); |
|
|
|
Ordinal = Context = Directive = 0; |
|
|
|
Contains.clear(); |
|
|
|
} |
|
|
|
|
|
|
|
HeaderFinderPattern& |
|
|
|
HeaderFinderPattern::operator=(const HeaderFinderPattern& R) { // Assignment operator. |
|
|
|
Header = R.Header; |
|
|
|
Ordinal = R.Ordinal; |
|
|
|
Context = R.Context; |
|
|
|
Directive = R.Directive; |
|
|
|
Contains = R.Contains; |
|
|
|
return *this; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const unsigned long int HeaderFinder::operator()() const { // Return the Directives. |
|
|
|
return Directives; |
|
|
|
} |
|
|
|
|
|
|
|
HeaderFinder::HeaderFinder( // To construct one of these: |
|
|
|
snfScanData* EngineScanData, // -- Scanner control data ptr. |
|
|
|
const HeaderDirectiveSet& Patterns, // -- this is the set of patterns. |
|
|
@@ -21,72 +72,72 @@ HeaderFinder::HeaderFinder( |
|
|
|
HeaderDirectives(Patterns), // Grab the Directives and |
|
|
|
Bfr(MessageBuffer), // the message buffer. |
|
|
|
Len(MessageLength), |
|
|
|
ImpossibleBytes(NumberOfByteValues, false), // Clear the impossible bytes cache.
|
|
|
|
ImpossibleBytes(NumberOfByteValues, false), // Clear the impossible bytes cache. |
|
|
|
Directives(0) { // Zero the composite result. |
|
|
|
UnfoldHeaders(); // Unfold the headers. |
|
|
|
} |
|
|
|
|
|
|
|
IP4Address extractIPFromSourceHeader(string& Header) { // Return first IP found in header.
|
|
|
|
const string Digits = "0123456789";
|
|
|
|
unsigned int EndOfName = Header.find_first_of(":");
|
|
|
|
|
|
|
|
unsigned int StartOfIP = Header.find_first_of(Digits, EndOfName);
|
|
|
|
const string IPCharacters = ".0123456789";
|
|
|
|
unsigned int EndOfIP = Header.find_first_not_of(IPCharacters, StartOfIP);
|
|
|
|
bool NoExtraCharactersAfterIP = (string::npos == EndOfIP);
|
|
|
|
if(NoExtraCharactersAfterIP) EndOfIP = Header.length();
|
|
|
|
unsigned int IPLength = EndOfIP - StartOfIP;
|
|
|
|
IP4Address ExtractedIP = Header.substr(StartOfIP, IPLength);
|
|
|
|
|
|
|
|
return ExtractedIP;
|
|
|
|
}
|
|
|
|
|
|
|
|
void HeaderFinder::CheckContent(string& Header, const HeaderFinderPattern& P) { // Check for a match in the header.
|
|
|
|
bool HeaderContainsFinderPattern = (
|
|
|
|
string::npos != Header.find(P.Contains, P.Header.length())
|
|
|
|
|
|
|
|
cd::IP4Address extractIPFromSourceHeader(string& Header) { // Return first IP found in header. |
|
|
|
const string Digits = "0123456789"; |
|
|
|
unsigned int EndOfName = Header.find_first_of(":"); |
|
|
|
|
|
|
|
unsigned int StartOfIP = Header.find_first_of(Digits, EndOfName); |
|
|
|
const string IPCharacters = ".0123456789"; |
|
|
|
unsigned int EndOfIP = Header.find_first_not_of(IPCharacters, StartOfIP); |
|
|
|
bool NoExtraCharactersAfterIP = (string::npos == EndOfIP); |
|
|
|
if(NoExtraCharactersAfterIP) EndOfIP = Header.length(); |
|
|
|
unsigned int IPLength = EndOfIP - StartOfIP; |
|
|
|
cd::IP4Address ExtractedIP = Header.substr(StartOfIP, IPLength); |
|
|
|
|
|
|
|
return ExtractedIP; |
|
|
|
} |
|
|
|
|
|
|
|
void HeaderFinder::CheckContent(string& Header, const HeaderFinderPattern& P) { // Check for a match in the header. |
|
|
|
bool HeaderContainsFinderPattern = ( |
|
|
|
string::npos != Header.find(P.Contains, P.Header.length()) |
|
|
|
); |
|
|
|
|
|
|
|
|
|
|
|
if(HeaderContainsFinderPattern) { |
|
|
|
|
|
|
|
switch(P.Directive) {
|
|
|
|
case HeaderDirectiveBypass:
|
|
|
|
case HeaderDirectiveWhite: {
|
|
|
|
Directives |= P.Directive; // Add the flags to our output.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case HeaderDirectiveDrillDown: {
|
|
|
|
ScanData->drillPastOrdinal(P.Ordinal); // Mark the IP DrillDown flag.
|
|
|
|
Directives |= P.Directive; // Add the flags to our output.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case HeaderDirectiveContext: {
|
|
|
|
ActivatedContexts.insert(P.Context); // Activate the context.
|
|
|
|
Directives |= P.Directive; // Add the flags to our output.
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case HeaderDirectiveSource: {
|
|
|
|
|
|
|
|
bool HeaderDirectiveSourceIPNotSet = (
|
|
|
|
0UL == ScanData->HeaderDirectiveSourceIP()
|
|
|
|
);
|
|
|
|
|
|
|
|
bool SourceContextActive = (
|
|
|
|
ActivatedContexts.end() != ActivatedContexts.find(P.Context)
|
|
|
|
);
|
|
|
|
|
|
|
|
if(HeaderDirectiveSourceIPNotSet && SourceContextActive) {
|
|
|
|
ScanData->HeaderDirectiveSourceIP(
|
|
|
|
extractIPFromSourceHeader(Header)
|
|
|
|
);
|
|
|
|
Directives |= P.Directive; // Add the flags to our output.
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
switch(P.Directive) { |
|
|
|
case HeaderDirectiveBypass: |
|
|
|
case HeaderDirectiveWhite: { |
|
|
|
Directives |= P.Directive; // Add the flags to our output. |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
case HeaderDirectiveDrillDown: { |
|
|
|
ScanData->drillPastOrdinal(P.Ordinal); // Mark the IP DrillDown flag. |
|
|
|
Directives |= P.Directive; // Add the flags to our output. |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
case HeaderDirectiveContext: { |
|
|
|
ActivatedContexts.insert(P.Context); // Activate the context. |
|
|
|
Directives |= P.Directive; // Add the flags to our output. |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
case HeaderDirectiveSource: { |
|
|
|
|
|
|
|
bool HeaderDirectiveSourceIPNotSet = ( |
|
|
|
0UL == ScanData->HeaderDirectiveSourceIP() |
|
|
|
); |
|
|
|
|
|
|
|
bool SourceContextActive = ( |
|
|
|
ActivatedContexts.end() != ActivatedContexts.find(P.Context) |
|
|
|
); |
|
|
|
|
|
|
|
if(HeaderDirectiveSourceIPNotSet && SourceContextActive) { |
|
|
|
ScanData->HeaderDirectiveSourceIP( |
|
|
|
extractIPFromSourceHeader(Header) |
|
|
|
); |
|
|
|
Directives |= P.Directive; // Add the flags to our output. |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|