-
Notifications
You must be signed in to change notification settings - Fork 0
/
exploit.js
106 lines (85 loc) · 2.39 KB
/
exploit.js
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
// Example usage:
// node exploit.js encode < input.txt | node exploit.js decode
//
// To solve:
// cat instructions.txt | node exploit.js decode
const fs = require('fs');
function _encode(input) {
let a = [];
for (let i = 0; i < input.length; i++) {
let t = input.charCodeAt(i);
for (let j = 0; j < 8; j++) {
// if t >> j is odd
if ((t >> j) & 1) {
a.push(1 + j + (input.length - 1 - i) * 8);
}
}
}
let b = [];
while (a.length) {
const rand = Math.random();
let t = (rand * a.length) | 0; // round down
b.push(a[t]);
a = a.slice(0, t).concat(a.slice(t + 1)); // remove a[t] from a
}
let r = '';
while (b.length) {
let t = b.pop();
r = r + '-'.repeat(t) + '.';
}
return r;
}
function generateLookup() {
const lookup = {};
for (var i = 32; i < 127; ++i) {
const char = String.fromCharCode(i);
const a = [];
for (let j = 0; j < 8; j++) {
if ((i >> j) & 1) a.push(j);
}
lookup[a] = char;
}
return lookup;
}
function _decode(input) {
const lookup = generateLookup();
// Reverse encoded string into b[].
const b = input
.split('.')
.map(x => x.length)
.reverse();
// Resultant b[] is in random order.
// Sorting it always gives rise to the same array regardless of random() above.
b.sort((a, b) => a - b);
// Input length can be determined from the maximal value.
const len = (b[b.length - 1] / 8) | (0 + 1);
// Find the binary set bits and character index from each encoded value.
const byIdx = {};
b.forEach(x => {
// Represents the binary bit (0 to 7).
const j = (x - 1) % 8;
// Represents the character index (0 to 161).
const i = ((x - j - 1) / 8 - len) * -1;
// Append the binary bit value for a specific character index.
if (!byIdx[i]) byIdx[i] = [];
byIdx[i].push(j);
});
// Fix last character (for some reason)
byIdx[len].shift();
// Decode all characters lookup table
const chars = Object.values(byIdx).map(j => lookup[j]);
return chars.join('');
}
if (process.argv.length !== 3) {
console.error('Usage: node exploit.js [encode|decode]');
return;
}
// Read from stdin
const file = fs.readFileSync(0, 'utf-8').toString();
if (process.argv[2] === 'encode') {
console.log(_encode(file));
} else if (process.argv[2] === 'decode') {
console.log(_decode(file));
} else {
console.error('Usage: node exploit.js [encode|decode]');
}