summaryrefslogtreecommitdiff
path: root/random.cpp
blob: afdf4c70997137e02fed93ea7ab7d3f4212a89e3 (plain)
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
// let's try to make it very simple

#include <fcntl.h>
#include <signal.h>
#include <sys/mman.h>
#include <unistd.h>

// 1. write a function to randomly put data in a buffer
// 		[apparently one loaded from a file]

#define MAPFNAME "random.bin"

pid_t child = 0;
bool child_terminated = false;
void handleSigChld(int)
{
	child_terminated = true;
}

static unsigned long long * count;

void random(int mapfd, int randfd, void *addr)
{
	pid_t pid = getpid();

	// *count is shared and stored
	for (*count = 0; ; ++ *count) {
		unsigned long long old_count = *count;

		// if successful child, update & kill parent
		if (getpid() != pid) {
			msync(addr + pos, size, MS_SYNC | MS_INVALIDATE);

			kill(pid, SIGTERM);
			pid = getpid();

			// add data to git.
			system("git add " MAPFNAME);
			system("git commit -m selfmod");
		}
		
		// handle crashes with fork()
		child = fork();
		if (child == 0) {
			// we are new child process
			// self-modify by 1-8 bytes
			uint16_t pos;
			uint8_t size;
			read(randfd, &pos, sizeof(pos));
			read(randfd, &size, sizeof(size));
			size = (size & 0x7) + 1; // self-modify by 1-8 bytes
			read(randfd, addr + pos, size);
			// loop
		} else {
			// old process: make sure new process succeeds within 1s
			time_t then = time(0);
			for (;;) {
				if (child_terminated || time(0) > then) {
					// child did not succeed
					kill(child, SIGTERM);
					child_terminated = false;
					// try again
					break;
				}
				if (old_count < *count + 1) {
					// incremented count by 1: success; hand off to child
					return;
				}
			}
		}
	}
}

void random_tail() {
}

void main()
{
	// handle SIGCHLD by setting a global flag
	struct sigaction sigchld;
	sigchld.sa_handler = handleSigChld;
	sigchld.sa_flags = SA_NOCLDWAIT;
	sigaction(SIGCHLD, &sigchld, NULL);

	int fd = open(MAPFNAME, O_RDWR);
	if (fd == -1 && errno == ENOENT) {
		// does not exist yet
		fd = open("random.bin", O_RDWR | O_CREAT);
		// 2. seed the buffer with the function that puts random data in it
		count = 0;
		write(fd, &count, sizeof(count));
		write(fd, &random, &random_tail - &random);
	}

	int randfd = open("/dev/random", O_RDONLY);

	// a buffer of 1 gig working space; random data will fill it
	void *buf = mmap(NULL,
	                 0x40000000,
	                 PROT_EXEC | PROT_READ | PROT_WRITE,
	                 MAP_SHARED | MAP_32BIT,
	                 fd,
	                 0;

	// 3. execute the buffer
	void (*buf_as_func)(void*) = (void*)((uint8_t*)buf + count);
	buf_as_func(mapfname, mapfd, randfd, buf);
}