第1关:基于BF算法的网络入侵检测
任务描述
随着互联网的飞速发展,网络安全问题日益严重。入侵检测技术是一种积极主动防御的安全保障技术,而Snort是其中基于规则匹配的一种入侵检测技术。Snort自1998年被发明以来,历经数年的迭代更新,Snort已成为一个具有多平台(Multi-Platform)、实时(Real-Time)流量分析、网络IP数据包(Pocket)记录等特性的强大的网络入侵检测/防御系统(Network Intrusion Detection/Prevention System),即NIDS/NIPS。
Snort首先需要使用者根据入侵行为的特征,按照一定的规范将这些特征编写成规则,最后通过检测网络数据与规则数据库中的规则是否匹配来判断入侵与否。在Snort入侵检测系统中,规则的匹配效率是影响Snort检测效率的关键。而规则匹配的核心技术是模式匹配算法。
请实现一个基于BF算法的模式匹配算法,用于网络入侵行为的检测。若检在网络日志中检测到任何一条检测规则中的ip地址,则输出“Intrusion.”,反之输出“No Intrusion.”
编程要求
输入
输入共n + m + 1行,第1行两个整数n, m(n, m ≤ 100) 2 ~ n + 1行每行为一条检测规则。规则的格式为:
protocol:网络协议 ip:ip地址 msg:"附加信息"
n + 2 ~ n + m + 1行共m行,为网络日志内容。
输出
输出一行,若检在网络日志中检测到任何一条检测规则中的ip地址,则输出“Intrusion.”,反之输出“No Intrusion.”。
测试说明
平台会对你编写的代码进行测试:
测试输入:
3 3
protocol:tcp ip:225.93.118.39 msg:"Network intrusion detected."
protocol:tcp ip:152.213.218.150 msg:"Network intrusion detected."
protocol:tcp ip:181.164.101.231 msg:"Network intrusion detected."
Proto Recv-Q Send-Q Local-Address Foreign-Address State
tcp 0 0 36.51.200.67:95403 40.56.49.213:29716 LAST_ACK
tcp 0 0 215.142.133.153:49323 106.54.135.230:18487 CLOSED
预期输出:
No Intrusion.
测试输入:
1 6
protocol:tcp ip:44.207.25.205 msg:"Network intrusion detected."
Proto Recv-Q Send-Q Local-Address Foreign-Address State
tcp 0 0 63.228.177.122:83999 115.120.78.164:25267 ESTABLISHED
tcp 0 0 91.62.129.226:75977 77.138.44.135:71910 ESTABLISHED
tcp 0 0 12.70.45.198:24940 44.207.25.205:7927 CLOSE_WAIT
tcp 0 0 155.212.113.157:94592 147.138.105.205:64521 LAST_ACK
tcp 0 0 148.0.118.155:33854 128.61.218.176:83248 LISTEN
预期输出:
Intrusion.
上答案:
#include<iostream>
#include<cstring>
#include<sstream>
using namespace std;
int BF(string s,string t)
{//简单模式匹配算法,S为主串(目标串),T为子串(模式串)。
//匹配成功返回主串中所含子串第一次出现的位置,否则返回-1。
/**************begin************/
int i=0,j=0;
while(i<s.length()&&j<t.length())
{
if(s[i]==t[j]){
++i;
++j;
}
else{
i=i-j+2;
j=0;
}
}
if(j==t.length()){
return i-t.length();
}
else{
return -1;
}
/**************end************/
}
int main()
{
int n,m;
while (cin>>n>>m)//输入n条规则,并将其中的n个ip地址存放到ip数组,输入m条日志,并合并存放到log
{
cin.get();
string *rule=new string[n];
string log="";
for(int i=0;i<n;i++)
{
string t;
getline(cin,t);
stringstream sss(t);
string pot,ip,msg;
sss>>pot>>ip;
rule[i]=ip.substr(3, ip.length() - 3);
}
for(int i=0;i<m;i++)
{
string t;
getline(cin,t);
log += t;
}
for(int i=0;i<n;i++)
{
if(BF(log,rule[i])!=-1)
{
cout<<"Intrusion."<<endl;
return 0;
}
}
cout<<"No Intrusion."<<endl;
delete[] rule;
return 0;
}
}
第2关:基于KMP算法的网络入侵检测
任务描述
随着互联网的飞速发展,网络安全问题日益严重。入侵检测技术是一种积极主动防御的安全保障技术,而Snort是其中基于规则匹配的一种入侵检测技术。Snort自1998年被发明以来,历经数年的迭代更新,Snort已成为一个具有多平台(Multi-Platform)、实时(Real-Time)流量分析、网络IP数据包(Pocket)记录等特性的强大的网络入侵检测/防御系统(Network Intrusion Detection/Prevention System),即NIDS/NIPS。
Snort首先需要使用者根据入侵行为的特征,按照一定的规范将这些特征编写成规则,最后通过检测网络数据与规则数据库中的规则是否匹配来判断入侵与否。在Snort入侵检测系统中,规则的匹配效率是影响Snort检测效率的关键。而规则匹配的核心技术是模式匹配算法。
请实现一个基于KMP算法的模式匹配算法,用于网络入侵行为的检测。若检在网络日志中检测到任何一条检测规则中的ip地址,则输出“Intrusion.”,反之输出“No Intrusion.”
编程要求
输入
输入共n + m + 1行,第1行两个整数n, m(n, m ≤ 100) 2 ~ n + 1行每行为一条检测规则。规则的格式为:
protocol:网络协议 ip:ip地址 msg:"附加信息"
n + 2 ~ n + m + 1行共m行,为网络日志内容。
输出
输出一行,若检在网络日志中检测到任何一条检测规则中的ip地址,则输出“Intrusion.”,反之输出“No Intrusion.”。
测试说明
平台会对你编写的代码进行测试:
测试输入:
3 3
protocol:tcp ip:225.93.118.39 msg:"Network intrusion detected."
protocol:tcp ip:152.213.218.150 msg:"Network intrusion detected."
protocol:tcp ip:181.164.101.231 msg:"Network intrusion detected."
Proto Recv-Q Send-Q Local-Address Foreign-Address State
tcp 0 0 36.51.200.67:95403 40.56.49.213:29716 LAST_ACK
tcp 0 0 215.142.133.153:49323 106.54.135.230:18487 CLOSED
预期输出:
No Intrusion.
测试输入:
1 6
protocol:tcp ip:44.207.25.205 msg:"Network intrusion detected."
Proto Recv-Q Send-Q Local-Address Foreign-Address State
tcp 0 0 63.228.177.122:83999 115.120.78.164:25267 ESTABLISHED
tcp 0 0 91.62.129.226:75977 77.138.44.135:71910 ESTABLISHED
tcp 0 0 12.70.45.198:24940 44.207.25.205:7927 CLOSE_WAIT
tcp 0 0 155.212.113.157:94592 147.138.105.205:64521 LAST_ACK
tcp 0 0 148.0.118.155:33854 128.61.218.176:83248 LISTEN
预期输出:
Intrusion.
上答案:
#include<iostream>
#include<cstring>
#include<sstream>
using namespace std;
void GetNext(string pattern,int* next)
{//每个模式的下一个输出值 和 下一个输入数字组
int j=0, k=-1;
next[j]=k;
while (j<(int)pattern.length()-1){
if(k==-1||pattern[j]==pattern[k]){
j++;
k++;
next[j]=k;
}
else{
k=next[k];
}
}
}
int KMP(string target,string pattern,int* next)
{//KMP匹配算法,target为主串,pattern为子串。
//匹配成功返回主串中所含子串第一次出现的位置,否则返回-1。
//调用GetNext函数获取模式串的next数组
/**************begin************/
int a=0,b=0;
GetNext(pattern,next);
while(a<target.length()&&b<pattern.length())
{
if(b==0||target[a]==pattern[b]){
a++;
b++;
}
else b=next[b];
}
if(b>=pattern.length()){return a-pattern.length();}
else return -1;
/**************end************/
}
int main()
{
int n,m;
while (cin>>n>>m)
{
cin.get(); //将接收第一个返回,并阻止对netline()的输入
string *rule=new string[n]; //规则编号组存储ip地址
string log="";
for(int i=0;i<n;i++)
{
string t;
getline(cin,t);
stringstream sss(t); //根据规范将字段左侧分成一个字符
string pot,ip,msg;
sss>>pot>>ip;
rule[i]=ip.substr(3, ip.length() - 3);
}
for(int i=0;i<m;i++)
{
string t;
getline(cin,t);
log += t;
}
for(int i=0;i<n;i++)
{
int *next=new int[rule[i].length()];
if(KMP(log,rule[i],next)!=-1)
{
cout<<"Intrusion."<<endl;
return 0;
}
delete[] next; //删除组指针空间
}
cout<<"No Intrusion."<<endl;
delete[] rule;
return 0;
}
}
第3关:统计字符出现的频度
任务描述
写一个算法统计在输入字符串中各个不同字符出现的频度,并将结果输出(字符串中的合法字符为A-Z之间的26个字母和0-9之间的10个数字)。
编程要求
输入
多组数据,每组数据有一行,为待统计字符频度的字符串。当字符串为“0”时,输入结束。
输出
对于每组数据输出n行,每一行为一个字符出现的频度(只输出存在的字符,格式为:字符:频度),字符排列顺序按照ASCII码从小到大的顺序。
测试说明
平台会对你编写的代码进行测试:
测试输入:
LITTLE5ILOVEYOU
AREYOUOKNUMB90077
0
预期输出:
5:1
E:2
I:2
L:3
O:2
T:2
U:1
V:1
Y:1
0:2
7:2
9:1
A:1
B:1
E:1
K:1
M:1
N:1
O:2
R:1
U:2
Y:1
上答案:
#include<iostream>
#include<cstring>
using namespace std;
void Count(string c,int b[])
{//统计字符出现的频度
/**************begin************/
for(int i=0;i<c.length();i++)
{
if(c[i]>=48&&c[i]<=57){
int t=c[i]-48;
b[t]++;
}
else {
int t=c[i]-55;
b[t]++;
}
}
for(int j=0;j<36;j++)
{
if(b[j])
{
if(j>=0&&j<=9)
{
cout<<j<<":"<<b[j]<<endl;
}
else{
printf("%c",j+55);
cout<<":"<<b[j]<<endl;
}
}
}
}
int main()
{
string c; //存储输入的字符串
while(cin>>c)
{
if(c=="0") break;
int *b=new int[36]{0}; //存储对应字符的个数
Count(c,b);
}
return 0;
}
第4关:字符串的插入
任务描述
编写算法,实现下面函数的功能。函数void insert(char * s,char * t,int pos)将字符串t插入到字符串s中,插入位置为pos(插在第pos个字符前)。假设分配给字符串s的空间足够让字符串t插入。(说明:不得使用任何库函数)
编程要求
输入
多组数据,每组数据有三行,第一行为插入的位置pos,第二行为要被插入的字符串s,第三行为待插入的字符串t。当pos为“0”时输入结束。
输出
对于每组数据输出一行,为t插入s后的字符串。
测试说明
平台会对你编写的代码进行测试:
测试输入:
1
abc
de
abc
2
acd
baaaa
0
预期输出:
abcabcde
abaaaacd
上答案:
#include<iostream>
#define MAXSIZE 100
using namespace std;
void Insert(char s[],char t[],int pos,int LenS,int LenT)
{//字符串的插入
/**************begin************/
int i;
while(s[LenS]!='\0')
LenS++;
while(t[LenT]!='\0')
LenT++;
for(i=LenS-1;i>=pos-1;i--)
s[i+LenT]=s[i];
for(i=pos-1;i<pos-1+LenT;i++)
s[i]=t[i-pos+1];
LenS+=LenT;
s[LenS]='\0';
for(i=0;i<LenS;i++)
cout<<s[i];
cout<<endl;
/**************end************/
}
int main()
{
int pos;
while(cin>>pos) //输入插入位置pos
{
if(pos<=0) break;
char s[MAXSIZE],t[MAXSIZE];
cin>>s>>t; //输入字符串s和t
int LenS=0,LenT=0;
while(s[LenS]!='\0') LenS++; //求字符串s的长度LenS
while(t[LenT]!='\0') LenT++; //求字符串t的长度LenT
if(pos>LenS) break; //插入位置非法
Insert(s,t,pos,LenS,LenT);
}
return 0;
}