实验目的
选择一个已经标识的隐蔽通道,通过在SecLinux环境中进行实际编程(C语言),完成发送程序、接收程序的编写,并进行收发场景的实际效果演示。
实验内容
- 构建测试环境,选择同步机制
- 发送和接收程序的编写、编译及运行
- 演示存在的隐蔽通道场景
实验准备
- 使用
root
进入系统,执行user_auth
命令获得特权
发现证书过期,使用initcert
命令生成证书
再次执行user_auth
获取特权 使用
root
用户创建用户并设置安全级,设置用户密码并设置用户主目录安全级$ useradd -m -h SYS_ADMIN -v SYS_ADMIN high $ passwd high $ useradd -m -h SYS_PUBLIC -v SYS_PUBLIC low $ passwd low $ setlevel SYS_ADMIN /home/high $ setlevel SYS_PUBLIC /home/low
- 分别从两个不同终端以
high
和low
用户登录
使用两个用户设置各自的主目录自主访问权限为0777 验证 MAC 策略是否正常
说明不可上读
说明可以下读,但不能下写
实验过程、结果
同步机制
采用 sleep
(秒)/usleep
(微秒)制造同步。
当一个进程 sleep
时,就将 cpu
的控制权交给其他进程,直到 sleep
时间已到,重新获得 cpu
的控制权。
实验结果(采用进程标识符信道)
如下面两幅图,左侧为发送端,右侧为接收端,可以看到进程标识符信道较易受到噪声的影响导致接受信息出错。
实验代码(采用进程标识符信道)
发送方代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
pid_t pid[128];
const int sync_time = 3;
void send(char ch){
int i;
printf("sending '%c'\n", ch);
for(i = 0; i < ch; i++){
pid[i]=fork()
if(pid[i]==0){
sleep(1);
exit(0);
}
}
printf("\tcreate %d processes!\n", ch);
}
int main(){
char ch;
FILE* f = fopen("in.txt", "r");
ch = fgetc(f);
while(1){
send(ch);
sleep(sync_time);
if(ch=='!') break;
ch = fgetc(f);
}
printf("Send Done!\n");
fclose(f);
}
接收方代码:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
pid_t firstPid, lastPid;
const int sync_time = 3;
int main(){
int k = 0;
char ch;
FILE *f = fopen('out.txt', 'w');
if ((firstPid=fork())==0){
exit(0);
}
sleep(1);
while(1){
sleep(sync_time);
if((lastPid=fork())==0){
exit(0);
}
printf('firstPid=%d, lastPid=%d\n', firstPid, lastPid);
if(k==0){
ch=lastPid-firstPid-2;
}else{
ch=lastPid-firstPid-1;
}
printf("\tReceive the '%c'\n", ch);
fputc(ch, f);
firstPid = lastPid;
k=1;
if(ch == '!') break;
}
printf("Receive Done!\n");
fclose(f);
}
流程图(采用进程标识符信道)
sequenceDiagram
participant Sender
participant Receiver
Receiver ->> Receiver: start, firstPid, sleep 3
Sender ->> Sender: start
loop send message
Sender ->> Sender: read char, create int(char) processes
Sender ->> Receiver: send the char(char)
Receiver ->> Receiver: lastPid, calc char(char), firstPid=lastPid
end
Sender ->> Sender: end
Receiver ->> Receiver: end
实验结果(采用最近访问时间信道)
如下图,左侧为发送端,右侧为接收端,多次实验发现消息传递十分稳定。
实验代码(采用最近访问时间信道)
发送方代码:
#include <stdio.h>
#include <sys/stat.h>
const int sync_time = 5;
void send(char ch){
int i;
char file_name[50];
printf("sending '%c'\n", ch);
for(i = 0; i < ch; i++){
sprintf(file_name, "/tmp/%d.txt", i);
FILE *fp = fopen(file_name, "r");
fgetc(fp);
fclose(fp);
}
printf("\tvisit %d files!\n", ch);
}
int main(){
char ch;
FILE* f = fopen("in.txt", "r");
ch = fgetc(f);
while(1){
send(ch);
sleep(sync_time);
if(ch=='!') break;
ch = fgetc(f);
}
printf("Send Done!\n");
fclose(f);
}
接收方代码:
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
const int sync_time = 5;
int main(){
int i = 0;
char ch, file_name[50];
FILE *f = fopen('out.txt', 'w');
printf("perpare for files in /tmp\n");
for (i = 0; i < 128; i++){
sprintf(file_name, "/tmp/%d.txt", i);
FILE *fp = fopen(file_name, "w");
fclose(fp);
chmod(file_name, S_IRWXU|S_IRWXG|S_IRWXO);
}
printf("perpare files complete\n");
while(1){
sleep(sync_time);
struct stat buf;
int old_time = -1, new_time;
for(i = 0; i< 128; i++){
sprintf(file_name, "/tmp/%d.txt", i);
stat(file_name, &buf);
new_time = buf.st_atime;
if(old_time != -1 && old_time - new_time > 1){
ch = (char)i;
fputc(ch, f);
printf("\told time: %d, new time: %d\n", old_time, new_time);
printf("\tReceive the '%c'\n", ch);
break;
}
old_time = new_time;
}
if(ch == '!') break;
}
printf("Receive Done!\n");
fclose(f);
}
流程图(采用最近访问时间信道)
sequenceDiagram
participant Sender
participant Receiver
Receiver ->> Receiver: start, create files
Sender ->> Sender: start
loop send message
Sender ->> Sender: read char, visit int(char) files
Sender ->> Receiver: send the char(char)
Receiver ->> Receiver: count visited files
end
Sender ->> Sender: end
Receiver ->> Receiver: end
实验总结
实验收获
对隐蔽通信信道有了更深的了解,进一步熟悉了安胜系统的命令。
实验过程中遇到的问题及解决方法
- 虚拟机无法安装 VMware Tools ,只能用 vim 导致编程困难,没有找到好的解决办法。
- 使用进程标识符通道时,第一个接收到的字符总是不对,后来发现是由于先运行 receiver 后运行 sender 导致第一次接收时应该用 lastPid-firstPid-2.
- 使用最近访问实际通道时,执行发送程序总是提示段错误,原因是接收程序创建的临时文件权限未放开,使用
chmod(file_name, S_IRWXU|S_IRWXG|S_IRWXO)
函数为通信文件设置权限为 777 即可。
总结实验的不足之处,以及进一步的改进措施
- 进程标识符通信信道由于较易受到噪声的影响,消息的传递不够稳定,选用其他的隐蔽通信信道如最近访问时间信道进行试验后发现,消息的传递变得稳定。
- 代码中采取的睡眠同步技术容易实现,适于演示。但是由于进程发送不同字符所用时间不同,而
sleep
时间一旦指定就是固定的,不能在程序运行期间更改,因此这种同步必然造成时间浪费,改进措施就是选用其他的同步机制,例如作业中提到的最近访问时间的方法。