一、實驗目的
1. 熟悉安勝安全操作系統的運行環境
2. 熟悉隱蔽通道的工作原理
二、實驗內容
1.完成發送和接收程序的編寫、編譯和執行
2.演示存在的隱蔽通道場景:
三、實驗過程、結果
(1)測試準備
1. 啓動到隱蔽通道處理前的安全核SecLinux
2. 創建兩個用戶user_h和user_l,user_h的安全範疇包含user_l的安全範疇,user_h的安全級高於user_l的安全級。此外,設置用戶主目錄安全級與用戶安全級相同;將兩個用戶主目錄自主訪問控制權限放開,即均通過chmod命令將其權限設爲0777,允許u,g,o可讀、寫和執行。
3. 檢驗SecLinux的安全性:
高級用戶可以讀低安全級文件,但是不能創建低安全級文件,也不能通過拷貝等方式向下傳遞信息。低級用戶無法讀高安全級文件。
(2)選用的隱蔽通道:進程描述符信道
信道名稱:
進程標識符信道
信道類型:
持久變量型
中介變量:
last_pid
存在條件:
系統中所有的進程共享同一個進程標識符符列表。無論系統採用何種安全策略,高安全級進程與低安全級進程都要共享這個列表,並且可以通過建立子進程得知當前可用進程標識符信道的值。如果系統的進程標識符信道表是乾淨的,即沒有其它進程消耗進程標識符信道表,高低進程就可以根據進程標識符信道增長的情況瞭解其它進程的工作情況。
發送方動作:
發送方讀取機密文件,然後,根據該文件內容的當前字節的ASIIC碼決定創建的子進程數目,待接收方讀取該信息後,刪除這些子進程。
接受方動作:
創建子進程,得到當前的進程標識符信道,然後與上次創建子進程得到的進程標識符信道對比,可以知道其它進程創建的子進程數目。解釋所得到的信息。
噪音情況:
高噪音。系統中存在的任何其它進程都可能創建子進程,從而導致接收方錯誤解釋所得到的信息。如果再安排在其它用戶不工作的時刻(比如午夜12點)傳遞信息,就可能獲得較大帶寬。
帶寬估計:
最大可以達到160比特/秒。
處理措施:
採用隨機化進程標識符信道或者加入Idle進程,該進程隨機創建子進程。
標記變量:
CC_PID
(3)同步機制
採用sleep(秒)/usleep(微秒)製造同步。
當一個進程sleep時,就將cpu的控制權交給其他進程,直到sleep時間已到,重新獲得cpu的控制權。
這種同步技術容易實現,適於演示。
但是由於進程發送不同字符所用時間不同,而sleep時間一旦指定就是固定的,不能在程序運行期間更改,因此這種同步必然造成時間浪費。
(4)實驗結果
如下圖所示,左側是發送端cc_sender,右側是接收端cc_receiver,發送端從同目錄的sender_text.txt文件獲取發送數據,通過隱蔽通道發送到接收端,接收端接到數據後保存到同目錄的receiver_text.txt文件中,發送端文件中存放的數據是abcdefg。
從下圖可以看到receiver_text.txt的內容,可以看出,7個字符abcdefg都正確傳輸。
(5)發送端源代碼
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void sendChar(char ch);
int main()
{
char ch;
FILE *fp;
int i;
if ((fp = fopen("./sender_text.txt", "r")) == NULL) //打開要發送的文件
{
printf("fopen error.\n");
exit(0);
}
while ((ch = fgetc(fp)) != EOF)
{
sendChar(ch); //每隔2秒發送每一個字符ch
sleep(2);
}
fclose(fp);
return 0;
}
void sendChar(char ch) //字符發送函數,通過創建ch個進程表示發送字符ch,這些進程持續2秒
{
pid_t fpid; //fpid表示fork函數返回的值
int i;
int count = (int) ch;
printf("***************************************************\n");
printf("Sending [%c], new pid count = [%d].\n", ch, count);
for (i = 0; i < count; i++) //父進程連續創建ch個子進程
{
fpid = fork();
if (fpid < 0)
{
printf("fork error.\n");
}
else if (fpid == 0)
{
printf("Sending [%c], last_pid = %d.\n", ch, getpid());
sleep(2); //這些子進程持續2秒就退出
exit(0);
}
}
}
(6)接收端源代碼
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int bStart = 0;
void writeToFile(char ch);
char receiveChar();
int main()
{
char ch;
int i;
remove("./receiver_text.txt"); //先刪除之前接受的文件
while (((ch = receiveChar()) != (char) 0) || bStart == 0)
{ //每隔2秒接受一次字符
if (bStart == 0)
{
printf("Not start.\n"); //bStart爲0表示發送端還沒開始發送
}
else
{
printf("Write [%c] to file.\n", ch); //接收到發送端發送字符ch
writeToFile(ch); //將ch寫入接收文件
}
}
printf("End.\n");
return 0;
}
void writeToFile(char ch) //將ch寫入接收文件
{
FILE *fp;
if ((fp = fopen("./receiver_text.txt", "a")) == NULL)
{
printf("fopen error.\n");
exit(0);
}
fputc(ch, fp);
fclose(fp);
}
char receiveChar() //接收字符函數,用間隔2秒的pid差值表示接收字符
{
pid_t fpid1, fpid2; //fpid1, fpid2表示fork函數返回的值
int iDiff;
char ch;
printf("***************************************************\n");
printf("Receiving round begins.\n");
fpid1 = fork();
if (fpid1 < 0)
{
printf("fork error.\n");
}
else if (fpid1 == 0)
{
exit(0);
}
sleep(2);
fpid2 = fork();
if (fpid2 < 0)
{
printf("fork error.\n");
}
else if (fpid2 == 0)
{
exit(0);
}
iDiff = fpid2 - fpid1 - 1; //由於第一次fork佔用了一個pid,因此做差時需要減1
ch = (char) iDiff;
if (iDiff < 30) //由於可能有別的新開的進程,導致接收端誤以爲發送端在發送,因此需要判斷,在小於30時,我們認爲是誤差
{
printf("Receiving round ends. pid_diff = [%d], data is [%c]\n", iDiff, ch);
return (char) 0;
}
else
{
if (bStart == 0) //第一次接收時,由於發送端本身也是一個進程,也佔用了一個pid,因此需要減1
{
iDiff--;
ch--;
}
printf("Receiving round ends. pid_diff = [%d], data is [%c]\n", iDiff, ch);
bStart = 1; //更新標識,表示以後就不是第一次接收了
return ch;
}
}
四、實驗總結
實驗收穫:
學到了很多隱蔽通道方面的知識,也進一步熟悉了安勝操作系統的命令用法。
總結實驗過程中遇到的問題及解決方法:
在linux中開發C語言程序沒有好用的IDE,編程非常不便。
解決方案:
在linux中用samba共享,將linux中的C語言代碼共享在Windows下,這樣可以在Windows下用Visual Studio等專業IDE對源代碼進行編輯,保證了編碼工作的高效進行。在編碼完成後,用linux的scp工具進行文件傳輸,如下圖所示: