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