■ 🕑 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~"
"~";