@ Pohon BBS
tripex tripcode finding software (5 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.
       

Pohon BBS