@ Pohon BBS
tripex tripcode finding software (8 replies)
■ 🕑 1. tripex tripcode finding software │ releasing version 1.0 of my tripcode finding program, 'tripex' │ │ compile the program as follows: │ gcc tripex.c -o tripex -O3 -lcrypt │ │ example #1; find tripcodes containing 'nice' (case insensitive): │ ./tripex -n $(nproc) -i nice │ │ example #2; find tripcodes starting with either 'giko' or 'mona': │ ./tripex -n $(nproc) ^giko ^mona │ │ example #3; find fully lowercase tripcodes with quads: │ ./tripex -s -n $(nproc) "^[a-z]*$" "\(.\)\1\{3,\}" │ │ untested on anything but GNU/Linux with glibc, but it would probably work on FreeBSD too. │ don't trust any update posts unless they have my tripcode or you can audit them yourself! │ │ -----BEGIN FILE tripex.c----- │ /* CC0-1.0 */ │ │ #include <err.h> │ #include <crypt.h> │ #include <regex.h> │ #include <stdio.h> │ #include <stdlib.h> │ #include <string.h> │ #include <unistd.h> │ │ #include <sys/random.h> │ │ #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) │ │ static unsigned char saltFilter[256]; │ static unsigned char rngFilter[256]; │ char *tripcode(const char *key); │ │ void usage(void) │ { │ fprintf(stderr, "usage: tripex [-Ehilnmsv] expressions\n" │ " -E\tuse extended regular expressions\n" │ " -h\tshow usage\n" │ " -i\tignore case\n" │ " -l\tkey length\n" │ " -n\tnumber of threads\n" │ " -m\tmax number of tries (per thread!)\n" │ " -s\tstack expressions (logical AND)\n"); │ } │ │ int main(int argc, char *argv[]) │ { │ int re_flags = 0; │ int sflag = 0; │ size_t n_procs = 1; │ size_t key_len = 8; │ size_t max_tries = 0; │ │ int opt; │ while ((opt = getopt(argc, argv, "E:hil:m:n:sv")) != -1) { │ switch(opt) { │ case 'E': │ re_flags |= REG_EXTENDED; │ break; │ case 'i': │ re_flags |= REG_ICASE; │ break; │ case 'l': │ key_len = atol(optarg); │ if (key_len < 1) │ errx(EXIT_FAILURE, "key length must be at least 1"); │ break; │ case 'n': │ n_procs = atol(optarg); │ if (n_procs < 1) │ errx(EXIT_FAILURE, "need at least one process"); │ break; │ case 'm': /* ! PER THREAD ! */ │ max_tries = atol(optarg); │ if (max_tries < 1) │ errx(EXIT_FAILURE, "need at least one try"); │ break; │ case 's': │ sflag = 1; │ break; │ case 'v': │ printf("tripex 1.0 by taocana\n"); │ return EXIT_SUCCESS; │ case 'h': │ /* FALLTHROUGH */ │ default: │ usage(); │ │ return EXIT_FAILURE; │ } │ } │ │ argc -= optind; │ argv += optind; │ │ if (argc < 1) { │ usage(); │ errx(EXIT_FAILURE, "need at least one expression"); │ } │ │ size_t n_exps = argc; │ regex_t *exps = malloc(sizeof(regex_t) * n_exps); │ for (size_t i = 0; i < n_exps; i++) │ if (regcomp(&exps[i], argv[i], re_flags)) │ errx(EXIT_FAILURE, "failed to compile regex"); │ │ for (int i = 1; i < n_procs; i++) │ if (!fork()) │ break; │ │ regmatch_t pmatch[1]; │ unsigned char key[key_len + 1]; /* dynamic array, bad form but i'm lazy */ │ key[key_len] = 0; │ │ for (size_t n = 0; !max_tries || n < max_tries ; n++) { │ if (getrandom(key, key_len, 0) < 0) │ err(EXIT_FAILURE, "failed to get random key"); │ │ for (int i = 0; i < key_len; i++) │ key[i] = rngFilter[key[i]]; │ │ char *trip = tripcode(key); │ if (!trip) │ err(EXIT_FAILURE, "failed to generate tripcode"); │ │ for (size_t i = 0; i < n_exps; i++) │ if (regexec(&exps[i], trip, ARRAY_SIZE(pmatch), pmatch, 0)) │ if (sflag) │ break; │ else │ continue; │ else if (!sflag || i >= n_exps - 1) │ printf("%s %s\n", trip, key); │ │ free(trip); │ } │ │ for (size_t i = 0; i < n_exps; i++) │ regfree(&exps[i]); │ free(exps); │ return EXIT_SUCCESS; │ } │ │ char *tripcode(const char *key) │ { │ /* we don't do any sjis conversion, but who cares anyway? */ │ if (strlen(key) == 0) │ return NULL; │ │ unsigned char *tempKey = malloc(strlen(key) + 2); │ if (!tempKey) │ return NULL; │ strcpy(tempKey, key); │ strcat(tempKey, "H."); │ │ unsigned char salt[3]; │ for (int i = 0; i < 3; i++) │ salt[i] = saltFilter[tempKey[i+1]]; │ salt[2] = 0; │ free(tempKey); │ │ struct crypt_data data; │ bzero(&data, sizeof(struct crypt_data)); │ │ char *tempCode = crypt_r(key, salt, &data); │ unsigned char *code = malloc(strlen(tempCode) - 3); │ if (!code) │ return NULL; │ strcpy(code, tempCode + 3); │ return code; │ } │ │ static unsigned char saltFilter[256] = │ "................................" │ ".............../0123456789......" │ ".ABCDEFGHIJKLMNOPQRSTUVWXYZ....." │ ".abcdefghijklmnopqrstuvwxyz....." │ "................................" │ "................................" │ "................................" │ "................................"; │ │ static unsigned char rngFilter[256] = │ "{dDOFByx8Jdo=C.{hFw:'p%m+]E-*}~4" │ "O)YiM99y?%A)tldRIN4!fat`J|(iI+}h" │ "]59P#T_Qx#h0q8w+F,$}Vo5Gq;<rw]Y~" │ "k6>O~Ge,.DW9`hqhaSf#A.vrnhy`[2Ct" │ "Bb6|7Mr+iJZG5.&7>?K@{D~6*Vs'H_*>" │ "$Mh3R-F$Sp^.E5R-W1DnQzXC@Tf']xxt" │ "o`GLO'Ui`S/v,aegU2HkE3Y6y!WZm%?k" │ "aD/H=yH4vQg7dC*(Gx$vV[<vV?jw8s^d"; │ │ ├─■ 🕑 2. tripex 1.1 │ │ version 1.1, cryptography patch. │ │ i forgot to audit the cryptography; i made a huge boneheaded mistake │ │ with the key filter (thing that turns pure random bytes into printable │ │ ascii) where it was skewing a lot. now it uses an 85 character subset │ │ (256 % 85 = 1) which has a very tiny amount of skew but doesn't lose │ │ as much entropy as an unskewed 64 character subset of ascii would. │ │ the default key length is also increased to 10, so that it would be │ │ ~64 shannons of entropy total (a tripcode has 60 shannons.) │ │ │ │ here is the patch file, apply it to the original as follows: │ │ patch tripex.c tripex-1.1.patch │ │ │ │ then recompile the program as follows: │ │ gcc tripex.c -o tripex -O3 -lcrypt │ │ │ │ -----BEGIN FILE tripex-1.1.patch----- │ │ 36c36 │ │ < size_t key_len = 8; │ │ --- │ │ > size_t key_len = 10; │ │ 67c67 │ │ < printf("tripex 1.0 by taocana\n"); │ │ --- │ │ > printf("tripex 1.1 by taocana\n"); │ │ 167a168,175 │ │ > /* we must get printable ascii from a random byte, │ │ > * but 256 % 94 = 68 which leaves too much skew. │ │ > * quantizing into 64 chars won't skew at all, but │ │ > * it only has 6 shannons of entropy per character. │ │ > * an 85 character quantization only skews by a │ │ > * remainder of one, which is miniscule enough and │ │ > * we average 6.41 shannons per character. │ │ > */ │ │ 169,176c177,192 │ │ < "{dDOFByx8Jdo=C.{hFw:'p%m+]E-*}~4" │ │ < "O)YiM99y?%A)tldRIN4!fat`J|(iI+}h" │ │ < "]59P#T_Qx#h0q8w+F,$}Vo5Gq;<rw]Y~" │ │ < "k6>O~Ge,.DW9`hqhaSf#A.vrnhy`[2Ct" │ │ < "Bb6|7Mr+iJZG5.&7>?K@{D~6*Vs'H_*>" │ │ < "$Mh3R-F$Sp^.E5R-W1DnQzXC@Tf']xxt" │ │ < "o`GLO'Ui`S/v,aegU2HkE3Y6y!WZm%?k" │ │ < "aD/H=yH4vQg7dC*(Gx$vV[<vV?jw8s^d"; │ │ --- │ │ > "!#$%&'()*+,-./012" │ │ > "3456789:;<=>?@ABC" │ │ > "DEFGHIJKLMNOPQRST" │ │ > "UVWXYZ^abcdefghij" │ │ > "klmnopqrstuvwxyz~" │ │ > "!#$%&'()*+,-./012" │ │ > "3456789:;<=>?@ABC" │ │ > "DEFGHIJKLMNOPQRST" │ │ > "UVWXYZ^abcdefghij" │ │ > "klmnopqrstuvwxyz~" │ │ > "!#$%&'()*+,-./012" │ │ > "3456789:;<=>?@ABC" │ │ > "DEFGHIJKLMNOPQRST" │ │ > "UVWXYZ^abcdefghij" │ │ > "klmnopqrstuvwxyz~" │ │ > "~"; │ │ │ │ │ └─■ 🕑 3. tripex 1.2 │ tripex 1.2 release notes │ + -f flag to read a list of expressions from a file │ * -s flag now takes an argument for when to begin/end stacking. negative values mean to stop stacking after the absolute value of the index. │ │ apply the patch as follows (make sure to apply the previous patch first:) │ patch tripex.c tripex-1.2.patch │ │ then recompile the software as follows: │ gcc tripex.c -o tripex -O3 -lcrypt │ │ here's an example of the new features combined for efficient dictionary searches. │ because expressions from argv are parsed after files, we have to put our first expression in it's own file :(. │ '-s -1' means to stop stacking after the first expression, so it will first check if it is even possible to match with any of the dictionary expressions. │ │ aspell -d en dump master | grep "^[a-z]\{5,5\}$" > len5dict.txt │ echo "[a-z]\{5,5\}" > 5a-z.txt │ ./tripex -n $(nproc) -s -1 -f 5a-z.txt -f len5dict.txt │ │ -----BEGIN FILE tripex-1.2.patch----- │ 13a14 │ > #define MAX_EXPRS 262144 │ 18a20,23 │ > /* if i put this garbage on the stack instead of bss, it will segfault. */ │ > size_t n_exprs = 0; │ > regex_t exprs[MAX_EXPRS]; │ > │ 21c26 │ < fprintf(stderr, "usage: tripex [-Ehilnmsv] expressions\n" │ --- │ > fprintf(stderr, "usage: tripex [-Ef:hil:n:m:s:v] expressions\n" │ 22a28 │ > " -f\tread expressions from file (use '-' for stdin)\n" │ 28c34,46 │ < " -s\tstack expressions (logical AND)\n"); │ --- │ > " -s\tstack (logical AND) expressions before/after expr #n (negative for before)\n"); │ > } │ > │ > void appendExpr(regex_t exprs[], size_t *i, char *str, int re_flags) │ > { │ > /* avoiding malloc like the plague, simple and fast shitware! │ > * if you somehow need more than MAX_EXPRS, change it & recompile. │ > */ │ > if (*i >= MAX_EXPRS) │ > errx(EXIT_FAILURE, "no %s-kun! it's too many exprs, it wont fit!", getlogin()); │ > if (regcomp(&exprs[*i], str, re_flags)) │ > errx(EXIT_FAILURE, "failed to compile regex '%s'", str); │ > (*i)++; │ 34a53 │ > long stack_after = 0; │ 40c59 │ < while ((opt = getopt(argc, argv, "E:hil:m:n:sv")) != -1) { │ --- │ > while ((opt = getopt(argc, argv, "E:f:hil:m:M:n:s:v")) != -1) { │ 44a64,81 │ > case 'f': │ > FILE *fp = stdin; │ > if (strcmp(optarg, "-") != 0) │ > fp = fopen(optarg, "r"); │ > if (!fp) │ > err(EXIT_FAILURE, "couldn't open regex file '%s'", optarg); │ > │ > char *line = NULL; │ > size_t len = 0; │ > ssize_t nread; │ > while ((nread = getline(&line, &len, fp)) != -1) { │ > *strchr(line, '\n') = '\0'; │ > appendExpr(exprs, &n_exprs, line, re_flags); │ > } │ > │ > free(line); │ > fclose(fp); │ > break; │ 64a102 │ > stack_after = atol(optarg); │ 67c105 │ < printf("tripex 1.1 by taocana\n"); │ --- │ > printf("tripex 1.2 by taocana\n"); │ 73d110 │ < │ 81c118,121 │ < if (argc < 1) { │ --- │ > for (size_t i = 0; i < argc; i++) │ > appendExpr(exprs, &n_exprs, argv[i], re_flags); │ > │ > if (n_exprs < 1) { │ 86,91d125 │ < size_t n_exps = argc; │ < regex_t *exps = malloc(sizeof(regex_t) * n_exps); │ < for (size_t i = 0; i < n_exps; i++) │ < if (regcomp(&exps[i], argv[i], re_flags)) │ < errx(EXIT_FAILURE, "failed to compile regex"); │ < │ 97c131 │ < unsigned char key[key_len + 1]; /* dynamic array, bad form but i'm lazy */ │ --- │ > unsigned char key[key_len + 1]; │ 100c134 │ < for (size_t n = 0; !max_tries || n < max_tries ; n++) { │ --- │ > for (size_t n = 0; !max_tries || n < max_tries; n++) { │ 111,113c145,151 │ < for (size_t i = 0; i < n_exps; i++) │ < if (regexec(&exps[i], trip, ARRAY_SIZE(pmatch), pmatch, 0)) │ < if (sflag) │ --- │ > for (size_t i = 0; i < n_exprs; i++) { │ > int stacking = (sflag │ > && ((stack_after >= 0 && i >= stack_after) │ > || (stack_after < 0 && i < -stack_after))); │ > │ > if (regexec(&exprs[i], trip, ARRAY_SIZE(pmatch), pmatch, 0)) │ > if (stacking) │ 117c155 │ < else if (!sflag || i >= n_exps - 1) │ --- │ > else if (!stacking || i >= n_exprs - 1) { │ 118a157,159 │ > break; │ > } │ > } │ 123,125c164,165 │ < for (size_t i = 0; i < n_exps; i++) │ < regfree(&exps[i]); │ < free(exps); │ --- │ > for (size_t i = 0; i < n_exprs; i++) │ > regfree(&exprs[i]); │ 134a175 │ > /* unsigned for array lookups by character */ │ 152c193 │ < if (!code) │ --- │ > if (!code) /* doesn't fully handle crypt_r(3) errors yet */ │ │ ├─■ 🕑 4. │ │ What does this do │ │ │ ├─■ 🕑 5. │ │ A program to search for 2ch style tripcodes via regular expressions. │ │ │ └─■ 🕑 6. │ >>4 │ it makes you 1337 in exchange for CPU cycles │ ├─■ 🕑 7. │ i remember ones that used GPU. │ how long do things take? │ └─■ 🕑 8. fully patched up2date src for convenience :^) ----BEGIN FILE tripex.c---- /* CC0-1.0 */ #include <err.h> #include <crypt.h> #include <regex.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/random.h> #define ARRAY_SIZE(x) (sizeof((x)) / sizeof((x)[0])) #define MAX_EXPRS 262144 static unsigned char saltFilter[256]; static unsigned char rngFilter[256]; char *tripcode(const char *key); /* if i put this garbage on the stack instead of bss, it will segfault. */ size_t n_exprs = 0; regex_t exprs[MAX_EXPRS]; void usage(void) { fprintf(stderr, "usage: tripex [-Ef:hil:n:m:s:v] expressions\n" " -E\tuse extended regular expressions\n" " -f\tread expressions from file (use '-' for stdin)\n" " -h\tshow usage\n" " -i\tignore case\n" " -l\tkey length\n" " -n\tnumber of threads\n" " -m\tmax number of tries (per thread!)\n" " -s\tstack (logical AND) expressions before/after expr #n (negative for before)\n"); } void appendExpr(regex_t exprs[], size_t *i, char *str, int re_flags) { /* avoiding malloc like the plague, simple and fast shitware! * if you somehow need more than MAX_EXPRS, change it & recompile. */ if (*i >= MAX_EXPRS) errx(EXIT_FAILURE, "no %s-kun! it's too many exprs, it wont fit!", getlogin()); if (regcomp(&exprs[*i], str, re_flags)) errx(EXIT_FAILURE, "failed to compile regex '%s'", str); (*i)++; } int main(int argc, char *argv[]) { int re_flags = 0; int sflag = 0; long stack_after = 0; size_t n_procs = 1; size_t key_len = 10; size_t max_tries = 0; int opt; while ((opt = getopt(argc, argv, "E:f:hil:m:M:n:s:v")) != -1) { switch(opt) { case 'E': re_flags |= REG_EXTENDED; break; case 'f': FILE *fp = stdin; if (strcmp(optarg, "-") != 0) fp = fopen(optarg, "r"); if (!fp) err(EXIT_FAILURE, "couldn't open regex file '%s'", optarg); char *line = NULL; size_t len = 0; ssize_t nread; while ((nread = getline(&line, &len, fp)) != -1) { *strchr(line, '\n') = '\0'; appendExpr(exprs, &n_exprs, line, re_flags); } free(line); fclose(fp); break; case 'i': re_flags |= REG_ICASE; break; case 'l': key_len = atol(optarg); if (key_len < 1) errx(EXIT_FAILURE, "key length must be at least 1"); break; case 'n': n_procs = atol(optarg); if (n_procs < 1) errx(EXIT_FAILURE, "need at least one process"); break; case 'm': /* ! PER THREAD ! */ max_tries = atol(optarg); if (max_tries < 1) errx(EXIT_FAILURE, "need at least one try"); break; case 's': sflag = 1; stack_after = atol(optarg); break; case 'v': printf("tripex 1.2 by taocana\n"); return EXIT_SUCCESS; case 'h': /* FALLTHROUGH */ default: usage(); return EXIT_FAILURE; } } argc -= optind; argv += optind; for (size_t i = 0; i < argc; i++) appendExpr(exprs, &n_exprs, argv[i], re_flags); if (n_exprs < 1) { usage(); errx(EXIT_FAILURE, "need at least one expression"); } for (int i = 1; i < n_procs; i++) if (!fork()) break; regmatch_t pmatch[1]; unsigned char key[key_len + 1]; key[key_len] = 0; for (size_t n = 0; !max_tries || n < max_tries; n++) { if (getrandom(key, key_len, 0) < 0) err(EXIT_FAILURE, "failed to get random key"); for (int i = 0; i < key_len; i++) key[i] = rngFilter[key[i]]; char *trip = tripcode(key); if (!trip) err(EXIT_FAILURE, "failed to generate tripcode"); for (size_t i = 0; i < n_exprs; i++) { int stacking = (sflag && ((stack_after >= 0 && i >= stack_after) || (stack_after < 0 && i < -stack_after))); if (regexec(&exprs[i], trip, ARRAY_SIZE(pmatch), pmatch, 0)) if (stacking) break; else continue; else if (!stacking || i >= n_exprs - 1) { printf("%s %s\n", trip, key); break; } } free(trip); } for (size_t i = 0; i < n_exprs; i++) regfree(&exprs[i]); return EXIT_SUCCESS; } char *tripcode(const char *key) { /* we don't do any sjis conversion, but who cares anyway? */ if (strlen(key) == 0) return NULL; /* unsigned for array lookups by character */ unsigned char *tempKey = malloc(strlen(key) + 2); if (!tempKey) return NULL; strcpy(tempKey, key); strcat(tempKey, "H."); unsigned char salt[3]; for (int i = 0; i < 3; i++) salt[i] = saltFilter[tempKey[i+1]]; salt[2] = 0; free(tempKey); struct crypt_data data; bzero(&data, sizeof(struct crypt_data)); char *tempCode = crypt_r(key, salt, &data); unsigned char *code = malloc(strlen(tempCode) - 3); if (!code) /* doesn't fully handle crypt_r(3) errors yet */ return NULL; strcpy(code, tempCode + 3); return code; } static unsigned char saltFilter[256] = "................................" ".............../0123456789......" ".ABCDEFGHIJKLMNOPQRSTUVWXYZ....." ".abcdefghijklmnopqrstuvwxyz....." "................................" "................................" "................................" "................................"; /* we must get printable ascii from a random byte, * but 256 % 94 = 68 which leaves too much skew. * quantizing into 64 chars won't skew at all, but * it only has 6 shannons of entropy per character. * an 85 character quantization only skews by a * remainder of one, which is miniscule enough and * we average 6.41 shannons per character. */ static unsigned char rngFilter[256] = "!#$%&'()*+,-./012" "3456789:;<=>?@ABC" "DEFGHIJKLMNOPQRST" "UVWXYZ^abcdefghij" "klmnopqrstuvwxyz~" "!#$%&'()*+,-./012" "3456789:;<=>?@ABC" "DEFGHIJKLMNOPQRST" "UVWXYZ^abcdefghij" "klmnopqrstuvwxyz~" "!#$%&'()*+,-./012" "3456789:;<=>?@ABC" "DEFGHIJKLMNOPQRST" "UVWXYZ^abcdefghij" "klmnopqrstuvwxyz~" "~";
Pohon BBS