88
#define countof(x) (sizeof(x)/sizeof(*(x)))
90
static int matrix_encoding[] = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
91
192, 193, 194, 195, 196, 197, 198, 199,
92
200, 201, 202, 203, 204, 205, 206, 207 };
93
static int decimal_encoding[] = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25 };
94
static int hex_encoding[] = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
95
33, 34, 35, 36, 37, 38 };
96
static int binary_encoding[] = { 16, 17 };
97
static int dna_encoding[] = { 33, 35, 39, 52 };
98
static unsigned char char_map[256] = {
99
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 0 */
100
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 16 */
101
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 32 */
102
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, /* 48 */
103
32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, /* 64 */
104
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 80 */
105
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 96 */
106
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 112 */
107
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 128 */
108
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 144 */
109
96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 160 */
110
112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 176 */
111
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 192 */
112
144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, /* 208 */
113
160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, /* 224 */
114
176,177,178,195,180,181,182,183,184,185,186,187,188,189,190,191 /* 240 */
117
#define CURSOR_GLYPH 97
119
typedef enum { TRACEA1, TRACEA2,
120
TRACEB1, TRACEB2, SYSTEMFAILURE,
121
KNOCK, NMAP, MATRIX, DNA, BINARY, DEC, HEX } m_mode;
98
126
XWindowAttributes xgwa;
127
GC draw_gc, erase_gc, scratch_gc;
100
128
int grid_width, grid_height;
101
129
int char_width, char_height;
103
132
m_feeder *feeders;
106
136
Bool insert_top_p, insert_bottom_p;
108
138
signed char *tracing;
141
Pixmap images[CHAR_MAPS];
112
142
int image_width, image_height;
147
unsigned long colors[5];
119
load_images (m_state *state)
152
load_images_1 (m_state *state, int which)
154
#if defined(HAVE_GDK_PIXBUF) || defined(HAVE_XPM)
122
155
if (!get_boolean_resource ("mono", "Boolean") &&
123
156
state->xgwa.depth > 1)
125
XpmAttributes xpmattrs;
127
xpmattrs.valuemask = 0;
130
xpmattrs.valuemask |= XpmCloseness;
131
xpmattrs.closeness = 40000;
134
xpmattrs.valuemask |= XpmVisual;
135
xpmattrs.visual = state->xgwa.visual;
138
xpmattrs.valuemask |= XpmDepth;
139
xpmattrs.depth = state->xgwa.depth;
142
xpmattrs.valuemask |= XpmColormap;
143
xpmattrs.colormap = state->xgwa.colormap;
146
result = XpmCreatePixmapFromData (state->dpy, state->window,
150
&state->images, 0 /* mask */,
152
if (!state->images || (result != XpmSuccess && result != XpmColorError))
155
state->image_width = xpmattrs.width;
156
state->image_height = xpmattrs.height;
157
state->nglyphs = CHAR_ROWS;
159
(which == 1 ? (state->small_p ? matrix1b_xpm : matrix1_xpm) :
160
(state->small_p ? matrix2b_xpm : matrix2_xpm));
162
state->images[which] =
163
xpm_data_to_pixmap (state->dpy, state->window, bits,
164
&state->image_width, &state->image_height, 0);
160
#endif /* !HAVE_XPM */
167
#endif /* !HAVE_XPM && !HAVE_GDK_PIXBUF */
162
169
unsigned long fg, bg;
163
state->image_width = (state->small_p ? matrix2_width : matrix_width);
164
state->image_height = (state->small_p ? matrix2_height : matrix_height);
165
state->nglyphs = CHAR_ROWS;
170
state->image_width = (state->small_p ? matrix1b_width :matrix1_width);
171
state->image_height = (state->small_p ? matrix1b_height:matrix1_height);
167
172
fg = get_pixel_resource("foreground", "Foreground",
168
173
state->dpy, state->xgwa.colormap);
169
174
bg = get_pixel_resource("background", "Background",
170
175
state->dpy, state->xgwa.colormap);
172
XCreatePixmapFromBitmapData (state->dpy, state->window,
174
? (char *) matrix2_bits
175
: (char *) matrix_bits),
176
state->images[which] =
177
XCreatePixmapFromBitmapData (state->dpy, state->window, (char *)
178
(which == 1 ? (state->small_p ? matrix1b_bits :matrix1_bits) :
179
(state->small_p ? matrix2b_bits :matrix2_bits)),
176
180
state->image_width, state->image_height,
177
181
bg, fg, state->xgwa.depth);
649
static void drain_matrix (m_state *);
652
handle_events (m_state *state)
654
XSync (state->dpy, False);
655
while (XPending (state->dpy))
658
XNextEvent (state->dpy, &event);
660
if (event.xany.type == ConfigureNotify)
662
int ow = state->grid_width;
663
int oh = state->grid_height;
664
XGetWindowAttributes (state->dpy, state->window, &state->xgwa);
665
state->grid_width = state->xgwa.width / state->char_width;
666
state->grid_height = state->xgwa.height / state->char_height;
668
state->grid_height++;
669
if (state->grid_width < 5) state->grid_width = 5;
670
if (state->grid_height < 5) state->grid_height = 5;
672
if (ow != state->grid_width ||
673
oh != state->grid_height)
675
m_cell *ncells = (m_cell *)
676
calloc (sizeof(m_cell),
677
state->grid_width * state->grid_height);
678
m_feeder *nfeeders = (m_feeder *)
679
calloc (sizeof(m_feeder), state->grid_width);
682
/* fprintf(stderr, "resize: %d x %d ==> %d x %d\n",
683
ow, oh, state->grid_width, state->grid_height); */
685
for (y = 0; y < oh; y++)
686
for (x = 0; x < ow; x++)
687
if (x < ow && x < state->grid_width &&
688
y < oh && y < state->grid_height)
689
ncells[y * state->grid_width + x] =
690
state->cells[y * ow + x];
692
state->cells = ncells;
694
x = (ow < state->grid_width ? ow : state->grid_width);
695
for (i = 0; i < x; i++)
696
nfeeders[i] = state->feeders[i];
697
free (state->feeders);
698
state->feeders = nfeeders;
701
else if (event.xany.type == KeyPress)
705
XLookupString (&event.xkey, &c, 1, &keysym, 0);
706
if (c == '0' && !state->tracing)
708
drain_matrix (state);
711
else if (c == '+' || c == '=' || c == '>' || c == '.')
713
state->density += 10;
714
if (state->density > 100)
715
state->density = 100;
719
else if (c == '-' || c == '_' || c == '<' || c == ',')
721
state->density -= 10;
722
if (state->density < 0)
727
else if (c == '[' || c == '(' || c == '{')
729
state->insert_top_p = True;
730
state->insert_bottom_p = False;
733
else if (c == ']' || c == ')' || c == '}')
735
state->insert_top_p = False;
736
state->insert_bottom_p = True;
739
else if (c == '\\' || c == '|')
741
state->insert_top_p = True;
742
state->insert_bottom_p = True;
745
else if ((c == 't' || c == 'T') && state->mode == MATRIX)
747
state->mode = (c == 't' ? TRACEA1 : TRACEB1);
752
else if ((c == 'c' || c == 'k') && state->mode == MATRIX)
754
drain_matrix (state);
755
state->mode = (c == 'c' ? NMAP : KNOCK);
761
screenhack_handle_event (state->dpy, &event);
767
matrix_usleep (m_state *state, unsigned long delay)
773
int blink_delay = 333000;
775
m_cell *cursor = state->cursor;
776
while (tot_delay < delay)
780
usleep (blink_delay * 2);
781
tot_delay += (2 * blink_delay);
782
state->cursor = NULL;
786
usleep (blink_delay);
787
tot_delay += blink_delay;
788
state->cursor = cursor;
791
redraw_cells (state, False);
792
XSync (state->dpy, False);
793
handle_events (state);
798
XSync (state->dpy, False);
799
handle_events (state);
806
hack_text_1 (m_state *state,
817
int i = state->grid_width * y + x;
819
int long_delay_usecs = 1000000;
821
if (long_delay == -1)
822
long_delay = 0, long_delay_usecs /= 6;
824
if (y >= state->grid_height-1) return;
829
Bool done_p = s[1] == '\000';
833
if (*s == '\n' || x >= state->grid_width - 1)
839
i = state->grid_width * y + x;
844
for (yy = 0; yy < state->grid_height-1; yy++)
845
for (xx = 0; xx < state->grid_width; xx++)
847
int ii = yy * state->grid_width + xx;
848
int jj = (yy+1) * state->grid_width + xx;
849
state->cells[ii] = state->cells[jj];
850
state->cells[ii].changed = 1;
852
/* clear bottom row */
853
for (xx = 0; xx < state->grid_width; xx++)
855
int ii = yy * state->grid_width + xx;
856
state->cells[ii].glyph = 0;
857
state->cells[ii].changed = 1;
859
y--; /* move it back */
860
i = state->grid_width * y + x;
863
if (y >= state->grid_height) return;
865
cell = &state->cells[i];
869
state->cursor = cell;
872
else if (*s == '\010')
874
else if (*s == '\002')
878
cell = &state->cells[i];
879
if (x < state->grid_width-1)
881
cell->glyph = char_map[(unsigned char) *s] + 1;
882
if (*s == ' ' || *s == '\t') cell->glyph = 0;
884
cell->glow = (glow_p ? 100 : 0);
887
m_cell *next = &state->cells[i + 1];
889
state->cursor = next;
896
if (typing_delay || transmit_delay || long_delay)
898
redraw_cells (state, False);
899
XSync (state->dpy, False);
900
handle_events (state);
904
if (typing_delay && 0 == random() % 3)
905
usleep (0xFFFFFF & ((random() % 250000) + 1));
909
matrix_usleep (state, long_delay_usecs);
921
zero_cells (m_state *state)
924
for (i = 0; i < state->grid_height * state->grid_width; i++)
926
m_cell *cell = &state->cells[i];
927
cell->changed = (cell->glyph != 0);
936
hack_text (m_state *state)
938
Bool typing_delay = False;
939
Bool transmit_delay = False;
940
Bool long_delay = False;
941
Bool visible_cursor = False;
947
const char *blocks[] = {
949
"The Matrix has you...",
950
"Follow the white rabbit.",
954
int nblocks = countof(blocks);
957
transmit_delay = False;
959
visible_cursor = True;
960
for (j = 0; j < nblocks; j++)
964
const char *s = blocks[j];
965
if (!s[0] || !s[1]) typing_delay = False;
967
hack_text_1 (state, &x, &y, s,
968
typing_delay, transmit_delay, -1,
969
visible_cursor, True);
970
matrix_usleep (state, 2000000);
975
case TRACEA1: case TRACEB1:
977
const char *blocks[10];
980
if (state->mode == TRACEA1)
982
(state->grid_width >= 52
983
? "Call trans opt: received. 2-19-98 13:24:18 REC:Log>"
984
: "Call trans opt: received.\n2-19-98 13:24:18 REC:Log>");
987
(state->grid_width >= 52
988
? "Call trans opt: received. 9-18-99 14:32:21 REC:Log>"
989
: "Call trans opt: received.\n9-18-99 14:32:21 REC:Log>");
991
if (state->mode == TRACEB1)
992
blocks[n++] = "WARNING: carrier anomaly";
993
blocks[n++] = "Trace program: running";
995
typing_delay = False;
996
transmit_delay = True;
998
visible_cursor = True;
999
for (j = 0; j < n; j++)
1001
const char *s = blocks[j];
1005
hack_text_1 (state, &x, &y, s,
1006
typing_delay, transmit_delay, long_delay,
1007
visible_cursor, True);
1009
matrix_usleep (state, 1000000);
1015
const char *s = "SYSTEM FAILURE";
1017
float cx = ((int)state->grid_width - (int)strlen(s)) / 2 - 0.5;
1018
float cy = (state->grid_height / 2) - 1.3;
1024
XFillRectangle (state->dpy, state->window, state->erase_gc,
1025
cx * state->char_width,
1026
cy * state->char_height,
1027
(strlen(s) + 1) * state->char_width,
1028
state->char_height * 1.6);
1030
for (i = -2; i < 3; i++)
1033
gcv.foreground = state->colors[i + 2];
1034
XChangeGC (state->dpy, state->scratch_gc, GCForeground, &gcv);
1035
XDrawRectangle (state->dpy, state->window, state->scratch_gc,
1036
cx * state->char_width - i,
1037
cy * state->char_height - i,
1038
(strlen(s) + 1) * state->char_width + (2 * i),
1039
(state->char_height * 1.6) + (2 * i));
1042
/* If we don't clear these out, part of the box may get overwritten */
1043
for (i = 0; i < state->grid_height * state->grid_width; i++)
1045
m_cell *cell = &state->cells[i];
1049
x = ((int)state->grid_width - (int)strlen(s)) / 2;
1050
y = (state->grid_height / 2) - 1;
1053
hack_text_1 (state, &x, &y, s,
1054
typing_delay, transmit_delay, long_delay,
1055
visible_cursor, False);
1061
/* Note that what Trinity is using here is moderately accurate:
1062
She runs nmap (http://www.insecure.org/nmap/) then breaks in
1063
with a (hypothetical) program called "sshnuke" that exploits
1064
the (very real) SSHv1 CRC32 compensation attack detector bug
1065
(http://staff.washington.edu/dittrich/misc/ssh-analysis.txt).
1067
The command syntax of the power grid control software looks a
1068
lot like Cisco IOS to me. (IOS is a descendant of VMS.)
1070
const char *blocks[] = {
1073
"\001nmap 10.2.2.2\n",
1074
"Starting nmap V. 2.54BETA25\n"
1076
"\010", "\010", "\010",
1078
"Insufficient responses for TCP sequencing (3), OS detection "
1079
"may be less accurate\n"
1080
"Interesting ports on 10.2.2.2:\n"
1081
"(The 1538 ports scanned but not shown below are in state: "
1083
"Port state service\n"
1086
"No exact OS matches for host\n"
1088
"Nmap run completed -- 1 IP address (1 host up) scanned\n"
1091
"\001sshnuke 10.2.2.2 -rootpw=\"Z1ON0101\"\n",
1093
"Connecting to 10.2.2.2:ssh ... ",
1096
"Attempting to exploit SSHv1 CRC32 ... ",
1099
"Resetting root password to \"Z1ON0101\".\n",
1101
"System open: Access Level <9>\n"
1104
"\001ssh 10.2.2.2 -l root\n",
1106
"root@10.2.2.2's password: ",
1108
"\001\010\010\010\010\010\010\010\010\n",
1113
"\001disable grid nodes 21 - 48\n",
1115
"\002Warning: Disabling nodes 21-48 will disconnect sector 11 "
1118
"\002 ARE YOU SURE? (y/n) ",
1124
int nblocks = countof(blocks);
1125
int y = state->grid_height - 2;
1128
visible_cursor = True;
1131
for (j = 0; j < nblocks; j++)
1133
const char *s = blocks[j];
1134
typing_delay = (*s == '\001');
1135
if (typing_delay) s++;
1138
hack_text_1 (state, &x, &y, s,
1139
typing_delay, transmit_delay, long_delay,
1140
visible_cursor, True);
1143
typing_delay = False;
1145
for (j = 21; j <= 48; j++)
1148
sprintf (buf, "\002Grid Node %d offline...\n", j);
1149
hack_text_1 (state, &x, &y, buf,
1150
typing_delay, transmit_delay, -1,
1151
visible_cursor, True);
1155
hack_text_1 (state, &x, &y, "\nRRF-CONTROL> ",
1156
typing_delay, transmit_delay, long_delay,
1157
visible_cursor, True);
1159
/* De-glow all cells before draining them... */
1160
for (j = 0; j < state->grid_height * state->grid_width; j++)
1162
m_cell *cell = &state->cells[j];
1163
cell->changed = (cell->glow != 0);
1177
drain_matrix (m_state *state)
1179
int delay = get_integer_resource ("delay", "Integer");
1182
/* Fill the top row with empty top-feeders, to clear the screen. */
1183
for (i = 0; i < state->grid_width; i++)
1185
m_feeder *f = &state->feeders[i];
1191
/* Turn off all the spinners, else they never go away. */
1192
for (i = 0; i < state->grid_width * state->grid_height; i++)
1193
if (state->cells[i].spinner)
1195
state->cells[i].spinner = 0;
1196
state->cells[i].changed = 1;
1199
/* Run the machine until there are no live cells left. */
1202
Bool any_cells_p = False;
1203
for (i = 0; i < state->grid_width * state->grid_height; i++)
1204
if (state->cells[i].glyph)
1213
feed_matrix (state);
1214
redraw_cells (state, True);
1215
XSync (state->dpy, False);
1216
handle_events (state);
1217
if (delay) usleep (delay);
1223
roll_state (m_state *state)
1226
switch (state->mode)
1229
state->mode = TRACEA2;
1232
state->mode = TRACEB2;
1239
for (i = 0; i < strlen((char *) state->tracing); i++)
1240
if (state->tracing[i] < 0) any = True;
1244
XSync (state->dpy, False);
1245
matrix_usleep (state, 3000000);
1246
state->mode = MATRIX;
1247
state->glyph_map = matrix_encoding;
1248
state->nglyphs = countof(matrix_encoding);
1249
flip_images (state);
1250
free (state->tracing);
1253
else if ((random() % 20) == 0) /* how fast numbers are discovered */
1255
int x = random() % strlen((char *) state->tracing);
1256
if (state->tracing[x] < 0)
1257
state->tracing[x] = -state->tracing[x];
1264
/* reversed logic from TRACEA2 */
1267
for (i = 0; i < strlen((char *) state->tracing); i++)
1268
if (state->tracing[i] > 0) any = True;
1270
if ((random() % 15) == 0) {
1272
state->mode = SYSTEMFAILURE;
1275
int x = random() % strlen((char *) state->tracing);
1276
if (state->tracing[x] < 0)
1277
state->tracing[x] = -state->tracing[x];
1284
XSync (state->dpy, False);
1285
matrix_usleep (state, 6000000);
1286
state->mode = MATRIX;
1287
state->glyph_map = matrix_encoding;
1288
state->nglyphs = countof(matrix_encoding);
1289
flip_images (state);
1290
drain_matrix (state);
1291
matrix_usleep (state, 2000000);
1292
if (state->tracing) {
1293
free (state->tracing);
1300
state->mode = MATRIX;
1301
state->glyph_map = matrix_encoding;
1302
state->nglyphs = countof(matrix_encoding);
1303
flip_images (state);
1307
if (state->knock_knock_p && (! (random() % 3500)))
1309
drain_matrix (state);
1310
if (! (random() % 5))
1313
state->mode = KNOCK;
1315
flip_images (state);
1319
case DNA: case BINARY: case DEC: case HEX:
1327
matrix_usleep (state, delay * 1000000);
1328
state->cursor = NULL;
446
1333
hack_matrix (m_state *state)
1337
switch (state->mode)
1339
case TRACEA1: case TRACEB1: case SYSTEMFAILURE:
1340
case KNOCK: case NMAP:
1343
case TRACEA2: case TRACEB2:
1344
case MATRIX: case DNA: case BINARY: case DEC: case HEX:
450
1350
/* Glow some characters. */
451
1351
if (!state->insert_bottom_p)
453
1353
int i = random() % (state->grid_width / 2);
456
int x = random() % state->grid_width;
457
int y = random() % state->grid_height;
458
m_cell *cell = &state->cells[state->grid_width * y + x];
1356
int yy = random() % state->grid_height;
1357
int xx = random() % state->grid_width;
1358
m_cell *cell = &state->cells[state->grid_width * yy + xx];
459
1359
if (cell->glyph && cell->glow == 0)
461
1361
cell->glow = random() % 10;