Created
June 25, 2024 18:18
-
-
Save nuvious/b216145bcbba0f4199c14d66ba6a66e8 to your computer and use it in GitHub Desktop.
Cloak Covert Channel TCP Flow Sequence Encoder/Decoder
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
An implementation of the encoding used by Clock [1], a timing based covert | |
channel which converts a binary string into a sequence of N packets to be sent | |
over X flows. It is assumed that the values N, X, and the number of bits per | |
message are agreed upon ahead of time. The bit string is converted to an | |
unsigned integer value, which is used as the rank [2] for the reverse-sorted | |
distribution. The distribution is then computed from this rank and each of X | |
tcp flows has N packets sent with each flow waiting for N acknowledgements | |
before attempting to receive the next message. On the receiving end, the number | |
of TCP handshakes is counted and the number of packets sent are also counted to | |
reproduce the distribution. The rank is then computed and converted back to | |
binary. | |
The below implements the encoding and decoding logic to the best of my | |
understanding from the paper. | |
Expected Output: | |
(base) nuvious@rpiterm:~/JHU/EN.695.722.81.SU24-CoverChannels$ python3 rank.py | |
(3, 4, 2, 5, 1) Rank: 55 | |
55 Distribution: (3, 4, 2, 5, 1) | |
Lbits: 010100100110011100 | |
84380 | |
(16, 15, 14, 13, 12, 11, 10, 7, 9, 2, 6, 8, 1, 4, 3, 5) | |
Encoded TCP Info (tcp_flow_index, num_packets): | |
((0, 16), (1, 15), (2, 14), (3, 13), (4, 12), (5, 11), (6, 10), (7, 7), | |
(8, 9), (9, 2), (10, 6), (11, 8), (12, 1), (13, 4), (14, 3), (15, 5)) | |
Decoded Lbits: 010100100110011100 | |
(base) nuvious@rpiterm:~/JHU/EN.695.722.81.SU24-CoverChannels$ | |
[1] X. Luo, E. Chan, and R. Chang, Cloak: A TenFold Way for Reliable Covert | |
Communications, vol. 4734. 2007, pp. 283–298. | |
doi: https://doi.org/10.1007/9783540748359_19 | |
[2] Wikipedia Contributors, “Ranking (statistics),” Wikipedia, Dec. 05, 2023. | |
Available: https://en.wikipedia.org/wiki/Ranking_(statistics). | |
[Accessed: Jun. 25, 2024] | |
""" | |
import itertools | |
def rank(values: tuple): | |
"""Returns the reverse-orderd statistical rank of an ordered set of values | |
Parameters | |
---------- | |
values : tuple | |
An ordered set of values which are in the range of [1..N] | |
Returns | |
------- | |
int | |
The reverse-order statistical rank | |
""" | |
sorted_values = sorted(list(values), reverse=True) | |
for i, permutation in enumerate(itertools.permutations(sorted_values)): | |
if permutation == values: | |
return i - 1 | |
def unrank(rank: int, value_count: int): | |
"""Returns the sequence of values given a reverse-ordered rank | |
Parameters | |
---------- | |
rank : int | |
The rank of the set | |
value_count : int | |
The number of values expected in the set | |
Returns | |
------- | |
tuple | |
The ordered values of the set | |
""" | |
sorted_values = list(range(value_count, 0, -1)) | |
for i, permutation in enumerate(itertools.permutations(sorted_values)): | |
if i == rank + 1: | |
return permutation | |
def cloak_encode(N: int, X: int, lbits: str): | |
"""Encodes an l-bit string into a distribution of TCP flows and packet | |
counts. | |
Parameters | |
---------- | |
N : int | |
Maximum number of packets per flow. | |
X : int | |
Number of flows | |
lbits : str | |
A binary string of 1's and 0's | |
Returns | |
------- | |
tuple | |
Tuple of (tcp_flow_index, num_packets) | |
""" | |
# Convert to unsigned int | |
lbits_rank = int(lbits, 2) | |
print(lbits_rank) | |
distribution = unrank(rank=lbits_rank, value_count=X) | |
print(distribution) | |
return tuple((i, distribution[i]) for i in range(X)) | |
def cloak_decode(N: int, X: int, tcp_flow_data: tuple, lbit_len: int): | |
"""Decodes a tuple of (tcp_flow_index, num_packets) into an lbit string | |
Parameters | |
---------- | |
N : int | |
Maximum number of packets per flow. | |
X : int | |
Number of flows | |
tcp_flow_data : tuple | |
Tuple of (tcp_flow_index, num_packets) | |
lbit_len : int | |
Length of bitstring expected | |
Returns | |
------- | |
str | |
The decoded bitstring | |
""" | |
distribution = tuple( | |
num_packets for tcp_packet_index, num_packets in tcp_flow_data | |
) | |
lbits_rank = rank(distribution) | |
return bin(lbits_rank)[2:].zfill(lbit_len) | |
if __name__ == "__main__": | |
N = 16 | |
X = 16 | |
values = (3, 4, 2, 5, 1) | |
lbits = '010100100110011100' | |
lbit_len = len(lbits) | |
values_rank = rank(values) | |
print(f"{values} Rank:", values_rank) | |
unranked_distribution = unrank(values_rank, len(values)) | |
print(f"{values_rank} Distribution:", unranked_distribution) | |
print("Lbits:", lbits) | |
encoded = cloak_encode(N, X, lbits) | |
print("Encoded TCP Info (tcp_flow_index, num_packets):\n", encoded) | |
decoded = cloak_decode(N, X, encoded, lbit_len) | |
print("Decoded Lbits:", decoded) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment