Created
January 4, 2018 02:33
-
-
Save shirriff/e333b99b521bd8dbddbbd40868245011 to your computer and use it in GitHub Desktop.
Use brute force to crack the password on a Xerox Alto disk.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdint.h> | |
#include <stdlib.h> | |
#include <strings.h> | |
#include <stdio.h> | |
int64_t count = 0; | |
// Password vector from sys.boot. Must be big-endian. | |
// Disk 47 | |
uint16_t passvec[] = {0xffff, 0xcfa7, 0x9f3d, 0x669a, 0xf2bb, 0xf193, 0x6d09, 0x4571, 0xe1d1}; | |
// Disk 72 | |
// uint16_t passvec[] = {0xffff, 0x8341, 0x772c, 0x249b, 0x1be2, 0xf71f, 0x5b87, 0x9fce, 0x0581}; | |
void testPasswd(const char *password, uint16_t *passvec) { | |
count += 1; | |
uint16_t x[2]; | |
uint16_t y[2]; | |
x[0] = 0; | |
x[1] = 0; | |
y[0] = 0; | |
y[1] = 0; | |
int length = strlen(password); | |
for (int i = 0; i < length; i++) { | |
char c = password[i]; | |
if (c >= 'a' && c <= 'z') { | |
c = c - 'a' + 'A'; | |
} | |
uint16_t *p; | |
if ((i % 3) == 0) { | |
p = x; | |
} else { | |
p = y; | |
} | |
p[1] = (p[0] << 9) + (p[1] >> 7); | |
p[0] = (c << 9) + (p[0] >> 7); | |
} | |
uint32_t yval = (y[0] << 16) + y[1]; | |
uint32_t a = (passvec[1] << 16) | passvec[2]; | |
uint32_t b = (passvec[3] << 16) | passvec[4]; | |
uint64_t t = (uint32_t)((uint32_t)x[0] * (uint32_t)x[0]); | |
t = t * a; | |
t ^= 0xffffffff00000000; | |
t += 1; | |
uint64_t s = (uint64_t)b * (uint64_t)yval; | |
uint64_t c = t + s; | |
uint64_t wanted = ((uint64_t)passvec[5] << 48) | ((uint64_t)passvec[6] << 32) | ((uint64_t)passvec[7] << 16) | passvec[8]; | |
if (wanted == c) { | |
printf("Password match: %s\n", password); | |
// exit(1); | |
} else { | |
// printf("%llx %llx\n", wanted, c); | |
} | |
} | |
// Try password from stdin. | |
void crack() { | |
// From disk 37 | |
FILE *f = stdin; | |
char pass[80]; | |
while (fgets(pass, 80, f)) { | |
pass[strlen(pass)-1] = '\0'; | |
// printf("Password: %s\n", pass); | |
testPasswd(pass, passvec); | |
} | |
} | |
// char *chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-=_+,.<>?;':"; | |
char *chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; | |
// char *chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; | |
int nchars; | |
// Generate all strings from "chars" recursively. max is the length. | |
void generateString(uint16_t *passvec, char *pass, int idx, int max) { | |
for (int i = 0; i < nchars; i++) { | |
pass[idx] = chars[i]; | |
if (idx >= max-1) { | |
testPasswd(pass, passvec); | |
} else { | |
generateString(passvec, pass, idx + 1, max); | |
} | |
} | |
} | |
// Brute force generate passwords from character set. | |
void crack2() { | |
char pass[80]; | |
for (int max = 1; max < 12; max++) { | |
printf("Len %d\n", max); | |
pass[max] = '\0'; | |
generateString(passvec, pass, 0, max); | |
} | |
} | |
void crack3() { | |
FILE *f = stdin; | |
char pass0[80]; | |
char *pass = pass0 + 1; | |
while (fgets(pass, 80, f)) { | |
int len = strlen(pass); | |
pass[len] = '\0'; | |
for (int i = 0; i < nchars; i++) { | |
pass[len-1] = chars[i]; | |
testPasswd(pass, passvec); | |
pass[len-1] = '\0'; | |
pass[-1] = chars[i]; | |
testPasswd(pass0, passvec); | |
} | |
} | |
} | |
int main(int argc, char **argv) { | |
nchars = strlen(chars); | |
crack2(); | |
printf("Total count: %lld\n", count); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment