#!/usr/bin/python # -*- coding: utf-8 -*- import datetime import hashlib import random import sys import argparse from CTFd import create_app from CTFd.models import ( Users, Teams, Challenges, Flags, Awards, ChallengeFiles, Fails, Solves, ) parser = argparse.ArgumentParser() parser.add_argument("--mode", help="Set user mode", default="teams") parser.add_argument("--users", help="Amount of users to generate", default=50, type=int) parser.add_argument("--teams", help="Amount of teams to generate", default=10, type=int) parser.add_argument( "--challenges", help="Amount of challenges to generate", default=20, type=int ) parser.add_argument( "--awards", help="Amount of awards to generate", default=5, type=int ) args = parser.parse_args() app = create_app() mode = args.mode USER_AMOUNT = args.users TEAM_AMOUNT = args.teams if args.mode == "teams" else 0 CHAL_AMOUNT = args.challenges AWARDS_AMOUNT = args.awards categories = [ "Exploitation", "Reversing", "Web", "Forensics", "Scripting", "Cryptography", "Networking", ] lorems = [ "Lorem", "ipsum", "dolor", "sit", "amet,", "consectetur", "adipiscing", "elit.", "Proin", "fringilla", "elit", "velit,", "sed", "scelerisque", "tellus", "dapibus", "vel.", "Aenean", "at", "urna", "porta,", "fringilla", "erat", "eget,", "lobortis", "quam.", "Praesent", "luctus,", "quam", "at", "consequat", "luctus,", "mauris", "sem", "pretium", "metus,", "eu", "viverra", "dui", "leo", "in", "tortor.", "Cras", "iaculis", "enim", "erat,", "sed", "gravida", "velit", "consectetur", "a.", "Duis", "eget", "fermentum", "elit.", "Vivamus", "laoreet", "elementum", "massa,", "ut", "sodales", "mi", "gravida", "at.", "Vivamus", "dignissim", "in", "eros", "non", "iaculis.", "Vivamus", "nec", "sem", "fringilla,", "semper", "lectus", "in,", "malesuada", "tellus.", "Vestibulum", "mattis", "commodo", "enim", "sit", "amet", "scelerisque.", "Proin", "at", "condimentum", "nisi,", "nec", "fringilla", "ante.", "Vestibulum", "sit", "amet", "neque", "sit", "amet", "elit", "placerat", "interdum", "egestas", "ac", "malesuada", "quis", "arcu", "ac", "blandit.", "Vivamus", "in", "massa", "a", "purus", "bibendum", "sagittis.", "Nunc", "venenatis", "lacus", "sed", "nulla", "dapibus,", "consequat", "laoreet", "nisi", "faucibus.", "Nam", "consequat", "viverra", "nibh", "a", "cursus.", "Phasellus", "tristique", "justo", "vitae", "rutrum", "pharetra.", "Sed", "sed", "porttitor", "lacus.", "Nam", "ornare", "sit", "amet", "nisi", "imperdiet", "vulputate.", "Maecenas", "hendrerit", "ullamcorper", "elit,", "sed", "pellentesque", "lacus", "bibendum", "sit", "amet.", "Aliquam", "consectetur", "odio", "quis", "tellus", "ornare,", "id", "malesuada", "dui", "rhoncus.", "Quisque", "fringilla", "pellentesque", "nulla", "id", "congue.", "Nulla", "ultricies", "dolor", "tristique", "facilisis", "at", "accumsan", "nisi.", "Praesent", "commodo,", "mauris", "sit", "amet", "placerat", "condimentum,", "nibh", "leo", "pulvinar", "justo,", "vel", "dignissim", "mi", "dolor", "et", "est.", "Nulla", "facilisi.", "Sed", "nunc", "est,", "lobortis", "id", "diam", "nec,", "vulputate", "varius", "orci.", "Maecenas", "iaculis", "vehicula", "eros", "eu", "congue.", "Nam", "tempor", "commodo", "lobortis.", "Donec", "eget", "posuere", "dolor,", "ut", "rhoncus", "tortor.", "Donec", "et", "quam", "quis", "urna", "rhoncus", "fermentum", "et", "ut", "tellus.", "Aliquam", "erat", "volutpat.", "Morbi", "porttitor", "ante", "nec", "porta", "mollis.", "Ut", "sodales", "pellentesque", "rutrum.", "Nullam", "elit", "eros,", "sollicitudin", "ac", "rutrum", "sit", "amet,", "eleifend", "vel", "nulla.", "Morbi", "quis", "lacinia", "nisi.", "Integer", "at", "neque", "vel", "velit", "tincidunt", "elementum", "lobortis", "sit", "amet", "tellus.", "Nunc", "volutpat", "diam", "ac", "diam", "lacinia,", "id", "molestie", "quam", "eu", "ultricies", "ligula.", "Duis", "iaculis", "massa", "massa,", "eget", "venenatis", "dolor", "fermentum", "laoreet.", "Nam", "posuere,", "erat", "quis", "tempor", "consequat,", "purus", "erat", "hendrerit", "arcu,", "nec", "aliquam", "ligula", "augue", "vitae", "felis.", "Vestibulum", "tincidunt", "ipsum", "vel", "pharetra", "lacinia.", "Quisque", "dignissim,", "arcu", "non", "feugiat", "semper,", "felis", "est", "commodo", "lorem,", "malesuada", "elementum", "nibh", "lectus", "porttitor", "nisi.", "Duis", "non", "lacinia", "nisl.", "Etiam", "ante", "nisl,", "mattis", "eget", "convallis", "vel,", "ullamcorper", "ac", "nisl.", "Duis", "eu", "massa", "at", "urna", "laoreet", "convallis.", "Donec", "tincidunt", "sapien", "sit", "amet", "varius", "eu", "dignissim", "tortor,", "elementum", "gravida", "eros.", "Cras", "viverra", "accumsan", "erat,", "et", "euismod", "dui", "placerat", "ac.", "Ut", "tortor", "arcu,", "euismod", "vitae", "aliquam", "in,", "interdum", "vitae", "magna.", "Vestibulum", "leo", "ante,", "posuere", "eget", "est", "non,", "adipiscing", "ultrices", "erat.", "Donec", "suscipit", "felis", "molestie,", "ultricies", "dui", "a,", "facilisis", "magna.", "Cum", "sociis", "natoque", "penatibus", "et", "magnis", "dis", "parturient", "montes,", "nascetur", "ridiculus", "mus.", "Nulla", "quis", "odio", "sit", "amet", "ante", "tristique", "accumsan", "ut", "iaculis", "neque.", "Vivamus", "in", "venenatis", "enim.", "Nunc", "dignissim", "justo", "neque,", "sed", "ultricies", "justo", "dictum", "in.", "Nulla", "eget", "nunc", "ac", "arcu", "vestibulum", "bibendum", "vitae", "quis", "tellus.", "Morbi", "bibendum,", "quam", "ac", "cursus", "posuere,", "purus", "lectus", "tempor", "est,", "eu", "iaculis", "quam", "enim", "a", "nibh.", "Etiam", "consequat", ] hipsters = [ "Ethnic", "narwhal", "pickled", "Odd", "Future", "cliche", "VHS", "whatever", "Etsy", "American", "Apparel", "kitsch", "wolf", "mlkshk", "fashion", "axe", "ethnic", "banh", "mi", "cornhole", "scenester", "Echo", "Park", "Dreamcatcher", "tofu", "selvage", "authentic", "cliche", "High", "Life", "brunch", "pork", "belly", "viral", "XOXO", "drinking", "vinegar", "bitters", "Wayfarers", "gastropub", "dreamcatcher", "chillwave", "Shoreditch", "kale", "chips", "swag", "street", "art", "put", "a", "bird", "on", "it", "Vice", "synth", "cliche", "retro", "Master", "cleanse", "ugh", "Austin", "slow-carb", "small", "batch", "Hashtag", "food", "truck", "deep", "v", "semiotics", "chia", "normcore", "bicycle", "rights", "Austin", "drinking", "vinegar", "hella", "readymade", "farm-to-table", "Wes", "Anderson", "put", "a", "bird", "on", "it", "freegan", "Synth", "lo-fi", "food", "truck", "chambray", "Shoreditch", "cliche", "kogiSynth", "lo-fi", "single-origin", "coffee", "brunch", "butcher", "Pickled", "Etsy", "locavore", "forage", "pug", "stumptown", "occupy", "PBR&B", "actually", "shabby", "chic", "church-key", "disrupt", "lomo", "hoodie", "Tumblr", "biodiesel", "Pinterest", "butcher", "Hella", "Carles", "pour-over", "YOLO", "VHS", "literally", "Selvage", "narwhal", "flexitarian", "wayfarers", "kitsch", "bespoke", "sriracha", "Banh", "mi", "8-bit", "cornhole", "viral", "Tonx", "keytar", "gastropub", "YOLO", "hashtag", "food", "truck", "3", "wolf", "moonFingerstache", "flexitarian", "craft", "beer", "shabby", "chic", "8-bit", "try-hard", "semiotics", "Helvetica", "keytar", "PBR", "four", "loko", "scenester", "keytar", "3", "wolf", "moon", "sriracha", "gluten-free", "literally", "try-hard", "put", "a", "bird", "on", "it", "cornhole", "blog", "fanny", "pack", "Mumblecore", "pickled", "distillery", "butcher", "Ennui", "tote", "bag", "letterpress", "disrupt", "keffiyeh", "art", "party", "aesthetic", "Helvetica", "stumptown", "Wes", "Anderson", "next", "level", "McSweeney's", "cornhole", "Schlitz", "skateboard", "pop-up", "Chillwave", "biodiesel", "semiotics", "seitan", "authentic", "bicycle", "rights", "wolf", "pork", "belly", "letterpress", "locavore", "whatever", "fixie", "viral", "mustache", "beard", "Hashtag", "sustainable", "lomo", "cardigan", "lo-fiWilliamsburg", "craft", "beer", "bitters", "iPhone", "gastropub", "messenger", "bag", "Organic", "post-ironic", "fingerstache", "ennui", "banh", "mi", "Art", "party", "bitters", "twee", "bespoke", "church-key", "Intelligentsia", "sriracha", "Echo", "Park", "Tofu", "locavore", "street", "art", "freegan", "farm-to-table", "distillery", "hoodie", "swag", "ugh", "YOLO", "VHS", "Cred", "hella", "readymade", "distillery", "Banh", "mi", "Echo", "Park", "McSweeney's,", "mlkshk", "photo", "booth", "swag", "Odd", "Future", "squid", "Tonx", "craft", "beer", "High", "Life", "tousled", "PBR", "you", "probably", "haven't", "heard", "of", "them", "locavore", "PBR&B", "street", "art", "pop-up", ] names = [ "James", "John", "Robert", "Michael", "William", "David", "Richard", "Joseph", "Charles", "Thomas", "Christopher", "Daniel", "Matthew", "Donald", "Anthony", "Paul", "Mark", "George", "Steven", "Kenneth", "Andrew", "Edward", "Brian", "Joshua", "Kevin", "Ronald", "Timothy", "Jason", "Jeffrey", "Gary", "Ryan", "Nicholas", "Eric", "Stephen", "Jacob", "Larry", "Frank", "Jonathan", "Scott", "Justin", "Raymond", "Brandon", "Gregory", "Samuel", "Patrick", "Benjamin", "Jack", "Dennis", "Jerry", "Alexander", "Tyler", "Douglas", "Henry", "Peter", "Walter", "Aaron", "Jose", "Adam", "Harold", "Zachary", "Nathan", "Carl", "Kyle", "Arthur", "Gerald", "Lawrence", "Roger", "Albert", "Keith", "Jeremy", "Terry", "Joe", "Sean", "Willie", "Jesse", "Ralph", "Billy", "Austin", "Bruce", "Christian", "Roy", "Bryan", "Eugene", "Louis", "Harry", "Wayne", "Ethan", "Jordan", "Russell", "Alan", "Philip", "Randy", "Juan", "Howard", "Vincent", "Bobby", "Dylan", "Johnny", "Phillip", "Craig", "Mary", "Patricia", "Elizabeth", "Jennifer", "Linda", "Barbara", "Susan", "Margaret", "Jessica", "Dorothy", "Sarah", "Karen", "Nancy", "Betty", "Lisa", "Sandra", "Helen", "Donna", "Ashley", "Kimberly", "Carol", "Michelle", "Amanda", "Emily", "Melissa", "Laura", "Deborah", "Stephanie", "Rebecca", "Sharon", "Cynthia", "Ruth", "Kathleen", "Anna", "Shirley", "Amy", "Angela", "Virginia", "Brenda", "Pamela", "Catherine", "Katherine", "Nicole", "Christine", "Janet", "Debra", "Carolyn", "Samantha", "Rachel", "Heather", "Maria", "Diane", "Frances", "Joyce", "Julie", "Martha", "Joan", "Evelyn", "Kelly", "Christina", "Emma", "Lauren", "Alice", "Judith", "Marie", "Doris", "Ann", "Jean", "Victoria", "Cheryl", "Megan", "Kathryn", "Andrea", "Jacqueline", "Gloria", "Teresa", "Janice", "Sara", "Rose", "Julia", "Hannah", "Theresa", "Judy", "Mildred", "Grace", "Beverly", "Denise", "Marilyn", "Amber", "Danielle", "Brittany", "Diana", "Jane", "Lori", "Olivia", "Tiffany", "Kathy", "Tammy", "Crystal", "Madison", ] emails = [ "@gmail.com", "@yahoo.com", "@outlook.com", "@hotmail.com", "@mailinator.com", "@poly.edu", "@nyu.edu", ] extensions = [ ".doc", ".log", ".msg", ".rtf", ".txt", ".wpd", ".wps", ".123", ".csv", ".dat", ".db", ".dll", ".mdb", ".pps", ".ppt", ".sql", ".wks", ".xls", ".xml", ".mng", ".pct", ".bmp", ".gif", ".jpe", ".jpg", ".png", ".psd", ".psp", ".tif", ".ai", ".drw", ".dxf", ".eps", ".ps", ".svg", ".3dm", ".3dm", ".ind", ".pdf", ".qxd", ".qxp", ".aac", ".aif", ".iff", ".m3u", ".mid", ".mid", ".mp3", ".mpa", ".ra", ".ram", ".wav", ".wma", ".3gp", ".asf", ".asx", ".avi", ".mov", ".mp4", ".mpg", ".qt", ".rm", ".swf", ".wmv", ".asp", ".css", ".htm", ".htm", ".js", ".jsp", ".php", ".xht", ".fnt", ".fon", ".otf", ".ttf", ".8bi", ".plu", ".xll", ".cab", ".cpl", ".cur", ".dmp", ".drv", ".key", ".lnk", ".sys", ".cfg", ".ini", ".reg", ".app", ".bat", ".cgi", ".com", ".exe", ".pif", ".vb", ".ws", ".deb", ".gz", ".pkg", ".rar", ".sea", ".sit", ".sit", ".zip", ".bin", ".hqx", ".0 E", ".mim", ".uue", ".cpp", ".jav", ".pl", ".bak", ".gho", ".old", ".ori", ".tmp", ".dmg", ".iso", ".toa", ".vcd", ".gam", ".nes", ".rom", ".sav", ".msi", ] companies = ["Corp", "Inc.", "Squad", "Team"] icons = [ None, "shield", "bug", "crown", "crosshairs", "ban", "lightning", "code", "cowboy", "angry", ] def gen_sentence(): return " ".join(random.sample(lorems, 50)) def gen_name(): return random.choice(names) def gen_team_name(): return random.choice(hipsters).capitalize() + str(random.randint(1, 1000)) def gen_email(): return random.choice(emails) def gen_category(): return random.choice(categories) def gen_affiliation(): return (random.choice(hipsters) + " " + random.choice(companies)).title() def gen_value(): return random.choice(range(100, 500, 50)) def gen_word(): return random.choice(hipsters) def gen_icon(): return random.choice(icons) def gen_file(): return gen_word() + random.choice(extensions) def random_date(start, end): return start + datetime.timedelta( seconds=random.randint(0, int((end - start).total_seconds())) ) def random_chance(): return random.random() > 0.5 if __name__ == "__main__": with app.app_context(): db = app.db # Generating Challenges print("GENERATING CHALLENGES") for x in range(CHAL_AMOUNT): word = gen_word() chal = Challenges( name=word, description=gen_sentence(), value=gen_value(), category=gen_category(), ) db.session.add(chal) db.session.commit() f = Flags(challenge_id=x + 1, content=word, type="static") db.session.add(f) db.session.commit() # Generating Files print("GENERATING FILES") AMT_CHALS_WITH_FILES = int(CHAL_AMOUNT * (3.0 / 4.0)) for x in range(AMT_CHALS_WITH_FILES): chal = random.randint(1, CHAL_AMOUNT) filename = gen_file() md5hash = hashlib.md5(filename.encode("utf-8")).hexdigest() chal_file = ChallengeFiles( challenge_id=chal, location=md5hash + "/" + filename ) db.session.add(chal_file) db.session.commit() # Generating Teams print("GENERATING TEAMS") used = [] used_oauth_ids = [] count = 0 while count < TEAM_AMOUNT: name = gen_team_name() if name not in used: used.append(name) team = Teams(name=name, password="password") if random_chance(): team.affiliation = gen_affiliation() if random_chance(): oauth_id = random.randint(1, 1000) while oauth_id in used_oauth_ids: oauth_id = random.randint(1, 1000) used_oauth_ids.append(oauth_id) team.oauth_id = oauth_id db.session.add(team) count += 1 db.session.commit() # Generating Users print("GENERATING USERS") used = [] used_oauth_ids = [] count = 0 while count < USER_AMOUNT: name = gen_name() if name not in used: used.append(name) try: user = Users( name=name, email=name + gen_email(), password="password" ) user.verified = True if random_chance(): user.affiliation = gen_affiliation() if random_chance(): oauth_id = random.randint(1, 1000) while oauth_id in used_oauth_ids: oauth_id = random.randint(1, 1000) used_oauth_ids.append(oauth_id) user.oauth_id = oauth_id if mode == "teams": user.team_id = random.randint(1, TEAM_AMOUNT) db.session.add(user) count += 1 except Exception: pass db.session.commit() if mode == "teams": # Assign Team Captains print("GENERATING TEAM CAPTAINS") teams = Teams.query.all() for team in teams: captain = ( Users.query.filter_by(team_id=team.id) .order_by(Users.id) .limit(1) .first() ) if captain: team.captain_id = captain.id db.session.commit() # Generating Solves print("GENERATING SOLVES") if mode == "users": for x in range(USER_AMOUNT): used = [] base_time = datetime.datetime.utcnow() + datetime.timedelta( minutes=-10000 ) for y in range(random.randint(1, CHAL_AMOUNT)): chalid = random.randint(1, CHAL_AMOUNT) if chalid not in used: used.append(chalid) user = Users.query.filter_by(id=x + 1).first() solve = Solves( user_id=user.id, team_id=user.team_id, challenge_id=chalid, ip="127.0.0.1", provided=gen_word(), ) new_base = random_date( base_time, base_time + datetime.timedelta(minutes=random.randint(30, 60)), ) solve.date = new_base base_time = new_base db.session.add(solve) db.session.commit() elif mode == "teams": for x in range(1, TEAM_AMOUNT): used_teams = [] used_users = [] base_time = datetime.datetime.utcnow() + datetime.timedelta( minutes=-10000 ) team = Teams.query.filter_by(id=x).first() members_ids = [member.id for member in team.members] for y in range(random.randint(1, CHAL_AMOUNT)): chalid = random.randint(1, CHAL_AMOUNT) user_id = random.choice(members_ids) if (chalid, team.id) not in used_teams: if (chalid, user_id) not in used_users: solve = Solves( user_id=user_id, team_id=team.id, challenge_id=chalid, ip="127.0.0.1", provided=gen_word(), ) new_base = random_date( base_time, base_time + datetime.timedelta(minutes=random.randint(30, 60)), ) solve.date = new_base base_time = new_base db.session.add(solve) db.session.commit() used_teams.append((chalid, team.id)) used_users.append((chalid, user_id)) db.session.commit() # Generating Awards print("GENERATING AWARDS") for x in range(USER_AMOUNT): base_time = datetime.datetime.utcnow() + datetime.timedelta(minutes=-10000) for _ in range(random.randint(0, AWARDS_AMOUNT)): user = Users.query.filter_by(id=x + 1).first() award = Awards( user_id=user.id, team_id=user.team_id, name=gen_word(), value=random.randint(-10, 10), icon=gen_icon(), ) new_base = random_date( base_time, base_time + datetime.timedelta(minutes=random.randint(30, 60)), ) award.date = new_base base_time = new_base db.session.add(award) db.session.commit() # Generating Wrong Flags print("GENERATING WRONG FLAGS") for x in range(USER_AMOUNT): used = [] base_time = datetime.datetime.utcnow() + datetime.timedelta(minutes=-10000) for y in range(random.randint(1, CHAL_AMOUNT * 20)): chalid = random.randint(1, CHAL_AMOUNT) if chalid not in used: used.append(chalid) user = Users.query.filter_by(id=x + 1).first() wrong = Fails( user_id=user.id, team_id=user.team_id, challenge_id=chalid, ip="127.0.0.1", provided=gen_word(), ) new_base = random_date( base_time, base_time + datetime.timedelta(minutes=random.randint(30, 60)), ) wrong.date = new_base base_time = new_base db.session.add(wrong) db.session.commit() db.session.commit() db.session.close()