Covert Channels in Java: File Locking
A covert channel is a way of secretly transferring information between two policies that are forbidden from communicating. It can be done easily through page faulting, cpu utilization, or file locking. The sender process produces these events which a receiver then tries to poll. Of course, the two are unsynchronized by default so the receiver will be unable to receive with 100% accuracy–it may miss some events, or record too many. And, since the receiver cannot send a message back to the sender without a complex interlock system, it’s hard to build in reliability.
That said, here is some Java 5 code that demonstrates covert channels via file locking:
import java.io.*;
import java.util.*;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException;
public class Receiver {
public static void main(String [] args){
if(args.length < 2) {
System.err.println(“Please invoke with
java Receiver <file> <millis>”);
return;
}
String file = args[0];
Integer millis = Integer.parseInt(args[1]);
LinkedList <Integer> l = new LinkedList<
Integer>();
int conone = 0;
while(true){
int temp = read(file);
if(conone < 8){
if(temp == 1){
conone++;
} else {
conone = 0;
}
} else {
l.add(temp);
if(l.size() == 8){
String c = “”;
while(l.size() > 0){
c += l.getFirst();
l.removeFirst();
}
System.out.print((char) Integer.
parseInt(c, 2));
conone = 0;
}
}
sleep(millis);
}
}
public static void sleep(Integer millis){
try { Thread.sleep(millis); } catch(Exception e){
e.printStackTrace(); }
}
public static int read(String f){
try{
// open a channel
FileChannel channel =
new RandomAccessFile(new File(f), “rw”).getChannel();
FileLock lock = channel.tryLock();
if(lock == null)
return 1;
// give up lock
if(lock != null)
lock.release();
channel.close();
} catch(Exception e){
e.printStackTrace();
}
// no lock
return 0;
}
}
And here is the Sender class:
import java.io.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;
public class Sender {
public static void main(String [] args){
if(args.length < 3) {
System.err.println(“Please invoke with
java Sender <file> <content file name> <millis>”);
return;
}
String file = args[0];
// load some data
String line=“”;
String total=“”;
try {
BufferedReader b =
new BufferedReader(new FileReader(args[1]));
while((line=b.readLine()) != null){
total += line + “\n”;
}
} catch(Exception e){
e.printStackTrace();}
char [] content = total.toCharArray();
Integer millis = Integer.parseInt(args[2]);
// content
for(char temp : content){
// preamble
for(int i = 0; i < 8; i++){
lock(file, millis);
}
String bits = Integer.toBinaryString((int) temp);
while(bits.length() < 8){
bits = “0″ + bits;
}
for(char bit : bits.toCharArray()){
if(bit == ‘1′){
lock(file, millis);
} else {
sleep(millis);
}
System.out.print(bit);
}
}
}
public static void sleep(Integer millis){
try { Thread.sleep(millis); } catch(Exception e){
e.printStackTrace(); }
}
public static void lock(String file, int millis){
try{
// open a channel
FileChannel channel =
new RandomAccessFile(new File(file), “rw”).getChannel();
// get a lock
FileLock lock = null;
while(lock == null){
lock = channel.lock();
}
// Sleep
sleep(millis);
// give up lock
lock.release();
channel.close();
} catch(Exception e){
e.printStackTrace();
}
}
}
When you execute the programs, they produce the following kind of output:
%java Receiver temp.txt 50
Quantitative Information Flow
Lecturer: Michael Clarkson%java Sender temp.txt data.txt 50
0101000101110101011000010110111001110100
0110100101110100011000010111010001101001
0111011001100101001000000100100101101110
0110011001101111011100100110110101100001
0111010001101001011011110110111000100000
0100011001101100011011110111011100001010
0100110001100101011000110111010001110101
0111001001100101011100100011101000100000
0100110101101001011000110110100001100001
0110010101101100001000000100001101101100
01100001011100100110101101110011011011110
110111000001010
The Sender and Receiver take one step to assure that they communicate properly: before each character is sent, a block of 8 1s is transmitted. The Receiver can use these to try and delineate the blocks. This isn’t a robust approach, just a hack to try and prevent frameshift mutations!
This entry was posted on Wednesday, November 9th, 2005 at 7:54 am and is tagged with java nio, string args, lt 2, covert channel, linkedlist, interlock system, randomaccessfile, covert channels, millis, import java, java file, return string, cpu utilization, null return, main string, static int, java util, public static void, reliability, sleep. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback.

Add New Comment
Viewing 1 Comment
Thanks. Your comment is awaiting approval by a moderator.
Do you already have an account? Log in and claim this comment.
Do you already have an account? Log in and claim this comment.
Add New Comment
Trackbacks
(Trackback URL)