CyberStudents Wordmark

ElfTV

Category

Points

Author

Reverse engineering

55

q

qvipin

Solves (147)

1Profile Picture for .awesomeguy..awesomeguy.12/03 3:08 pm
2Profile Picture for boomanten10boomanten1012/03 3:30 pm
3Profile Picture for booklover997booklover99712/03 3:39 pm
4Profile Picture for _avyra_avyra12/03 3:49 pm
5Profile Picture for benishot.benishot.12/03 4:01 pm
6Profile Picture for krississykrississy12/03 4:10 pm
7Profile Picture for uvuvueuvuvue12/03 4:35 pm
8Profile Picture for eth007eth00712/03 4:39 pm
9Profile Picture for wavefire_wavefire_12/03 4:43 pm
10Profile Picture for mr_mphmr_mph12/03 4:47 pm
11Profile Picture for foodreaperfoodreaper12/03 5:21 pm
12Profile Picture for ryuun1cornryuun1corn12/03 5:56 pm
13Profile Picture for pranavnpranavn12/03 6:17 pm
14Profile Picture for Ricker WilkesRicker Wilkes12/03 6:43 pm
15Profile Picture for dharneesh5555dharneesh555512/03 7:20 pm
16Profile Picture for org_benerorg_bener12/03 9:05 pm
17Profile Picture for nouxianouxia12/03 11:14 pm
18Profile Picture for amsour._.amsour._.12/04 12:27 am
19Profile Picture for dailybee13.dailybee13.12/04 5:26 am
20Profile Picture for midnightfammidnightfam12/04 7:48 am
21Profile Picture for batterseabattersea12/04 8:48 am
22Profile Picture for peterw18peterw1812/04 9:22 am
23Profile Picture for __j03__j0312/04 9:24 am
24Profile Picture for ShrelicShrelic12/04 10:40 am
25Profile Picture for _vow__vow_12/04 10:55 am
26Profile Picture for dawiddymdawiddym12/04 11:34 am
27Profile Picture for saturn9saturn912/04 11:53 am
28Profile Picture for callmesaviourcallmesaviour12/04 1:00 pm
29Profile Picture for aa2a9c53cbb80416d3b47d85538d9971aa2a9c53cbb80416d3b47d85538d997112/04 1:06 pm
30Profile Picture for p.s.yp.s.y12/04 3:22 pm
31Profile Picture for unpwnblunpwnbl12/04 3:29 pm
32Profile Picture for f.a.u.c.e.tf.a.u.c.e.t12/04 3:36 pm
33Profile Picture for _4n3s_4n3s12/04 6:54 pm
34Profile Picture for monstermanyana_47633monstermanyana_4763312/04 7:21 pm
35Profile Picture for theapprocrastinatortheapprocrastinator12/04 9:24 pm
36Profile Picture for godlyavengergodlyavenger12/04 9:59 pm
37Profile Picture for minipifminipif12/05 5:42 am
38Profile Picture for ._e4gl3_.._e4gl3_.12/05 7:04 am
39Profile Picture for sleuth123sleuth12312/05 9:54 am
40Profile Picture for pligonsteinpligonstein12/05 9:54 am
41Profile Picture for sonicskibidisonicskibidi12/05 10:02 am
42Profile Picture for tudortudor12/05 10:49 am
43Profile Picture for amir213.amir213.12/05 10:58 am
44Profile Picture for raul_26raul_2612/05 6:51 pm
45Profile Picture for lydxnlydxn12/05 10:52 pm
46Profile Picture for silence_silence_12/06 10:34 am
47Profile Picture for theb4tmitetheb4tmite12/06 11:34 am
48Profile Picture for h3ri0sh3ri0s12/06 12:36 pm
49Profile Picture for kr4z31nkr4z31n12/07 6:27 am
50Profile Picture for zarnex__zarnex__12/07 2:10 pm
51Profile Picture for zzunaidd023zzunaidd02312/08 9:24 pm
52Profile Picture for whofulwhoful12/10 4:34 am
53Profile Picture for heartstollerheartstoller12/11 11:12 am
54Profile Picture for vuxnx_91621vuxnx_9162112/18 1:52 am
55Profile Picture for .hackboredzz.hackboredzz12/18 2:01 am
56Profile Picture for kush001607kush00160712/18 2:47 am
57Profile Picture for test123450604test12345060412/18 3:41 am
58Profile Picture for benny_46903_75418benny_46903_7541812/18 5:08 am
59Profile Picture for andreicatandreicat12/18 6:05 am
60Profile Picture for trixaitrixai12/18 7:26 am
61Profile Picture for puwanai.spuwanai.s12/18 9:09 am
62Profile Picture for m0ns7erm0ns7er12/18 9:22 am
63Profile Picture for georgechkhaidzegeorgechkhaidze12/18 9:58 am
64Profile Picture for sanskariwolfsanskariwolf12/18 10:15 am
65Profile Picture for damian.28damian.2812/18 10:16 am
66Profile Picture for __landon__landon12/18 12:34 pm
67Profile Picture for masquerade8077masquerade807712/18 3:07 pm
68Profile Picture for hash0xchash0xc12/18 5:50 pm
69Profile Picture for andreww4364andreww436412/18 6:37 pm
70Profile Picture for athawathaw12/18 7:04 pm
71Profile Picture for fzhshzh_163fzhshzh_16312/18 7:55 pm
72Profile Picture for mostyx_56545mostyx_5654512/18 10:05 pm
73Profile Picture for magic_kaito1412magic_kaito141212/18 10:05 pm
74Profile Picture for f00varf00var12/19 1:51 am
75Profile Picture for awdyan_awdyan_12/19 7:03 am
76Profile Picture for mini_waremini_ware12/19 7:59 am
77Profile Picture for elijah5399elijah539912/19 8:07 am
78Profile Picture for saik9415saik941512/19 11:03 am
79Profile Picture for infernosalexinfernosalex12/19 2:26 pm
80Profile Picture for rotzkokowskirotzkokowski12/19 3:51 pm
81Profile Picture for akz_loidakz_loid12/20 2:34 am
82Profile Picture for yo8836yo883612/20 7:06 am
83Profile Picture for mage9298mage929812/20 9:27 am
84Profile Picture for nnhung37nnhung3712/20 9:32 am
85Profile Picture for mtwiss_32447mtwiss_3244712/20 4:22 pm
86Profile Picture for hqky.2kruoihqky.2kruoi12/21 7:01 am
87Profile Picture for rex_i_arex_i_a12/21 8:04 am
88Profile Picture for installman.installman.12/21 8:13 am
89Profile Picture for mitotototomitotototo12/21 9:26 am
90Profile Picture for kaizowekaizowe12/21 12:05 pm
91Profile Picture for mobyduckmobyduck12/21 1:42 pm
92Profile Picture for manu7738manu773812/21 5:36 pm
93Profile Picture for kar_bkar_b12/21 6:22 pm
94Profile Picture for skizzers13skizzers1312/21 11:00 pm
95Profile Picture for persononline247persononline24712/21 11:17 pm
96Profile Picture for h45himh45him12/22 12:49 am
97Profile Picture for spectre06872spectre0687212/22 5:39 am
98Profile Picture for .mindsystem.mindsystem12/22 11:05 am
99Profile Picture for leslatoleslato12/22 7:31 pm
100Profile Picture for srik714srik71412/22 9:20 pm
101Profile Picture for captainblcaptainbl12/23 2:48 am
102Profile Picture for obetobet12/23 6:03 am
103Profile Picture for aarondewesaarondewes12/23 11:19 am
104Profile Picture for aquarheadaquarhead12/23 11:19 am
105Profile Picture for re_tiredre_tired12/23 2:01 pm
106Profile Picture for iam_the_tea_guyiam_the_tea_guy12/23 3:25 pm
107Profile Picture for znatiiznatii12/23 4:40 pm
108Profile Picture for astharot15astharot1512/23 4:46 pm
109Profile Picture for tomatoedtomatoed12/23 7:03 pm
110Profile Picture for awwliveyetawwliveyet12/24 3:25 pm
111Profile Picture for concealbearconcealbear12/24 9:44 pm
112Profile Picture for genseilni9593genseilni959312/24 9:50 pm
113Profile Picture for papa9995papa999512/25 12:25 am
114Profile Picture for kineticallyunstablekineticallyunstable12/25 2:09 am
115Profile Picture for anyzy.anyzy.12/25 2:56 am
116Profile Picture for busy_parrot_29341busy_parrot_2934112/25 8:08 am
117Profile Picture for mattewastakenmattewastaken12/25 8:13 am
118Profile Picture for isee9917isee991712/25 8:32 am
119Profile Picture for darkitydarkity12/25 10:27 am
120Profile Picture for leyo7leyo712/25 1:01 pm
121Profile Picture for 6oq.6oq.12/25 1:59 pm
122Profile Picture for hanks2151hanks215112/25 2:15 pm
123Profile Picture for chappy_jethrochappy_jethro12/25 2:17 pm
124Profile Picture for predatormonarchpredatormonarch12/25 5:09 pm
125Profile Picture for m4422m442212/25 5:53 pm
126Profile Picture for tildenjacksontildenjackson12/25 5:59 pm
127Profile Picture for yugi200yugi20012/25 6:27 pm
128Profile Picture for wilsonwei_cswilsonwei_cs12/25 11:44 pm
129Profile Picture for grwnagrwna12/26 12:36 am
130Profile Picture for sadfr0g.sadfr0g.12/26 2:13 am
131Profile Picture for .brothersofdestruction.brothersofdestruction12/26 5:05 am
132Profile Picture for _vga__vga_12/26 6:35 am
133Profile Picture for dudalpdudalp12/26 9:41 am
134Profile Picture for darkimoo.darkimoo.12/26 11:28 am
135Profile Picture for 0x0ffset0x0ffset12/26 12:02 pm
136Profile Picture for .jstr_.jstr_12/26 9:25 pm
137Profile Picture for tyx2019tyx201912/27 1:22 am
138Profile Picture for fakeaviationistfakeaviationist12/27 2:55 am
139Profile Picture for vifsh_01692vifsh_0169212/27 5:30 am
140Profile Picture for qwerty2119581qwerty211958112/27 6:31 am
141Profile Picture for baribal02baribal0212/28 6:03 pm
142Profile Picture for siddhartha_hdksiddhartha_hdk12/29 4:32 am
143Profile Picture for fazectfazect12/29 6:18 am
144Profile Picture for riki_sriki_s12/29 5:58 pm
145Profile Picture for jumbotron.__38029jumbotron.__3802912/31 12:01 am
146Profile Picture for mahendra3279mahendra327912/31 1:36 am
147Profile Picture for daynight253daynight25312/31 4:07 am

Description

Santa’s ElfTV license key checker got leaked! Finally, a break for a broke elf like you, starving for that sweet, sweet elf dopamine. The catch? You’ve got to reverse-engineer Santa’s “state-of-the-art” security to unlock it. Think you’re smarter than the guy who still uses reindeer for transportation? Prove it and claim your ElfTV fix!!!!

Connect using nc ctf.csd.lol 1001

Attachments

Hint

There are no penalties for viewing hints. Hints are released 12 hours and 24 hours after the challenge releases.

Submit flag

Discuss this challenge with others in #🎄丨advent-of-ctf on our Discord server.

Write-up

zarnex's write-up was selected as the best write-up submitted for this challenge.

View this write-up on GitHub

Let's take a look at the source!

use std::fs::File;
use std::io::{self, BufRead, Write};
use std::path::Path;

fn supasecurefibberdachicheckerthing(n: usize) -> Vec<u64> {
    let mut fib: Vec<u64> = vec![0, 1];
    for i in 2..n {
        let next = fib[i - 1].checked_add(fib[i - 2]).unwrap_or(0);
        fib.push(next);
    }
    fib
}

fn validate_license_key(key: &str) -> bool {
    if !key.starts_with("XMAS") {
        return false;
    }

    if key.len() != 12 {
        return false;
    }

    let ascii_sum: u32 = key.chars().skip(4).take(5).map(|c| c as u32).sum();
    if ascii_sum != 610 {
        return false;
    }

    let fib_482 = supasecurefibberdachicheckerthing(483)[482];
    let fib_last_3 = fib_482 % 1000;

    let key_last_3: u16 = match key[9..12].parse() {
        Ok(num) => num,
        Err(_) => return false,
    };

    if key_last_3 != fib_last_3 as u16 {
        return false;
    }

    true
}

fn win() {
    let flag_path = Path::new("flag.txt");

    if let Ok(file) = File::open(flag_path) {
        let mut buf_reader = io::BufReader::new(file);
        let mut flag = String::new();
        if buf_reader.read_line(&mut flag).is_ok() {
            println!("🎄 Ho Ho Ho!, go watch some ELFTV!: {}", flag.trim());
        } else {
            println!("smth went wrong contact vip3r with error (flag-file-1)");
        }
    } else {
        println!("smth went wrong contact vip3r with error (flag-file-2)");
    }
}


fn main() {
    println!("🎄 Welcome to the ElfTV XMAS-license key checker!");
    println!("Please enter your license key:");

    let stdin = io::stdin();
    let mut input = String::new();
    let mut stdout = io::stdout();

    if stdin.read_line(&mut input).is_ok() {
        let key = input.trim();
        if validate_license_key(key) {
            win();
        } else {
            writeln!(stdout, "Ho ho ho! Try again.").unwrap();
        }
    } else {
        writeln!(stdout, "Failed to read the input!").unwrap();
    }
}

So the goal of this challenge is to piece together a license key to get the flag. Let's start by analyzing each function used to check for the license key.


fn validate_license_key(key: &str) -> bool {
    if !key.starts_with("XMAS") {
        return false;
    }

    if key.len() != 12 {
        return false;
    }

    let ascii_sum: u32 = key.chars().skip(4).take(5).map(|c| c as u32).sum();
    if ascii_sum != 610 {
        return false;
    }

    let fib_482 = supasecurefibberdachicheckerthing(483)[482];
    let fib_last_3 = fib_482 % 1000;

    let key_last_3: u16 = match key[9..12].parse() {
        Ok(num) => num,
        Err(_) => return false,
    };

    if key_last_3 != fib_last_3 as u16 {
        return false;
    }

    true
}

This function in the source is what checks if the license key is correct or not.

if !key.starts_with("XMAS") {
        return false;
    }

This first check is pretty straight forward, it checks if the string starts with XMAS

if key.len() != 12 {
        return false;
    }

The next check above is looking at if the key is 12 characters, so now we have general idea on how the license key should look like. XMAS********

let ascii_sum: u32 = key.chars().skip(4).take(5).map(|c| c as u32).sum();
if ascii_sum != 610 {
    return

Now it is starting to get tricky to understand, lets go over it!

  1. key.chars(): Turns the string into a iterator of is characters
  2. .skip(4): Skips the first 4 chars
  3. .take(5): Takes the next 5 characters after skipping the first 4.
  4. .map(|c| c as u32): Maps each character in this slice to its ASCII value (as a u32 integer).
  5. .sum(): Takes the sum of these ASCII values.
  6. let ascii_sum: u32 = ...;: Saves the sum in a variable ascii_sum.
  7. if ascii_sum != 610 {: Checks if the sum of these ASCII values is not equal to 610.

So at this point we need to find 5 characters that add up to 610 which is nice since it is even. So I wrote a Python one liner print(chr(int(610 / 5)) * 5) which outputs zzzzz. So our license key should look like XMASzzzzz*** so far.

let fib_482 = supasecurefibberdachicheckerthing(483)[482];
let fib_last_3 = fib_482 % 1000;

let key_last_3: u16 = match key[9..12].parse() {
    Ok(num) => num,
    Err(_) => return false,
};

if key_last_3 != fib_last_3 as u16 {
    return false;
}

Now the final check had me confused, I was looking very surface level and thought the key was just the last 3 digits of the Fibonacci sequence for the 482 number (which is 041) but it didn't work. As I look in deeper, it seems as the codes implementation of the Fibonacci check is faulty because of this

  • The Function is computing the digits using u64 integers
  • u64 can hold up to 2^64−1≈1.84×10^19
  • And by the 94th number is overflows that limit changing f'ing up the rest of the numbers.

So to get the correct number, I modified the code to just print out the last 3 digits.

fn main() {
    fn supasecurefibberdachicheckerthing(n: usize) -> Vec<u64> {
        let mut fib: Vec<u64> = vec![0, 1];
        for i in 2..n {
            let next = fib[i - 1].checked_add(fib[i - 2]).unwrap_or(0);
            fib.push(next);
        }
        fib
    }

    let fib_482 = supasecurefibberdachicheckerthing(483)[482];
    let fib_last_3 = fib_482 % 1000;

    println!("last 3 digits: {}", fib_last_3);
}

And running it...

$ rustc test.rs
$ ./test
last 3 digits: 738

So now we have our full license key: XMASzzzzz738. Lets try it!

$ nc ctf.csd.lol 1001
🎄 Welcome to the ElfTV XMAS-license key checker!
Please enter your license key:
XMASzzzzz738
🎄 Ho Ho Ho!, go watch some ELFTV!: csd{Ru57y_L1c3N53_k3Y_CH3Ck3r}

Flag: csd{Ru57y_L1c3N53_k3Y_CH3Ck3r}

Need help with a challenge? Is a challenge broken? DM @ModMail in our Discord server.