HackTheBox Nothing Without A Cost Writeup
Explore the basics of cybersecurity in the Nothing Without A Cost 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.
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
#!/usr/bin/env python3
from pwn import *
def get_process():
try:
host, port = sys.argv[1].split(':')
return remote(host, int(port))
except IndexError:
print(f'Usage: python {sys.argv[0]} <ip:port>')
exit(1)
def get_values(test_n):
global a
io.recvuntil(f'Test {test_n + 1}/100\n'.encode())
n, k = list(map(int, io.recvline().rstrip().decode().split()))
a = [0] + list(map(int, io.recvline().rstrip().decode().split()))
return n, k
def divide_and_conquer(i, l, r, optl, optr):
if l > r:
return
mid = (l + r) // 2
best_k = -1
dp[i][mid] = float('inf')
global cl, cr, cost, count
for k in range(optl, min(mid, optr) + 1):
while cr < mid:
cr += 1
add(cr)
while cr > mid:
remove(cr)
cr -= 1
while cl < k + 1:
remove(cl)
cl += 1
while cl > k + 1:
cl -= 1
add(cl)
tmp = dp[i - 1][k] + cost
if tmp < dp[i][mid]:
dp[i][mid] = tmp
best_k = k
divide_and_conquer(i, l, mid - 1, optl, best_k)
divide_and_conquer(i, mid + 1, r, best_k, optr)
def find_minimum_cost(n, k):
global dp, cl, cr, cost, count
maxA = max(a)
dp = [[float('inf')] * (n + 1) for _ in range(k + 1)]
dp[0][0] = 0
for i in range(1, k + 1):
cl, cr = 1, 0
cost = 0
count = [0] * (maxA + 1)
divide_and_conquer(i, i, n, i - 1, n - 1)
return dp[k][n]
def add(pos):
global cost
x = a[pos]
cost += count[x]
count[x] += 1
def remove(pos):
global cost
x = a[pos]
count[x] -= 1
cost -= count[x]
def send_solution(min_cost):
io.sendline(f'{int(min_cost)}'.encode())
def get_flag():
io.recvuntil(b'HTB{')
return b'HTB{' + io.recvline().rstrip()
def pwn():
for t in range(100):
print('Test', t + 1)
n, k = get_values(t)
min_cost = find_minimum_cost(n, k)
send_solution(min_cost)
flag = get_flag()
print(flag)
if __name__ == '__main__':
a = []
dp = []
cost = 0
count = []
cl = 0
cr = 0
io = get_process()
pwn()
Summary
Nothing Without A Cost requires solving 100 test cases using dynamic programming with divide-and-conquer optimization. The script connects to the remote service, retrieves inputs, calculates minimum costs for array partitions, and sends solutions iteratively. Each test involves computing costs efficiently by updating states dynamically. Successfully solving all cases reveals the flag, but the process is time-intensive.
This post is licensed under CC BY 4.0 by the author.