Web – 486 pts (10 solves) – Chall author: Raulet
Easily reversible encryption function behind obfuscation, yuckie.
Challenge

| So somebody hacked the final exam grades to inflate their own… up to 1337, alright. Well in that case it seems our friend ‘nUK<,IDt-.bvKL | ./EO$%;k}@_’ is the culprit. However, his name is encrypted… |
Solution
Within the html file we find some obfuscated javascript
function encrypt(_0x40a681) {
var _0x16b830 = 0x20, _0x561689 = 0x5e, _0x3db275 = 0x0, _0x38a41d = '';
for (var _0x278871 = 0x0; _0x278871 < _0x40a681['length']; _0x278871++) {
_0x38a41d = _0x38a41d + String['fromCharCode']((_0x40a681['charCodeAt'](_0x278871) + _0x3db275) % _0x561689 + _0x16b830), _0x3db275 = _0x3db275 + _0x40a681['charCodeAt'](_0x278871);
}
return _0x38a41d;
We can de-obfuscate this simple function by replacing the nonsense variable names with names that make sense, and by inserting values wherever possible. After this, we find a more readable encrypt function
function encrypt(input) {
var output = '', c0 = 0;
for (var i = 0; i < input['length']; i++) {
output = output + String['fromCharCode']((input['charCodeAt'](i) + c0) % 94 + 32),
c0 = c0 + input['charCodeAt'](i);
}
return output;
Because of the modulo in there, it might be a bit rough to reverse directly, so let’s just brute-force it instead. We can do so by simply trying out a character and seeing if our trial flag matches with the given encrypted flag. I used the following script
#!/usr/bin/env python3
# Encryption function
def encrypt(msg):
out = ''; c0 = 0
# Loop over input message
for i in range(len(msg)):
# Increment character ord value
out += chr(((ord(msg[i]) + c0) % 94) + 32)
# Increment addition variable
c0 += ord(msg[i])
# Return
return out
# Character set
chars = list(r'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_}!?.,')
# Trial flag and given mystery flag
flag = 'NETON{'
mystery = 'nUK<,IDt-.bvKL|./EO$%;k}@_'
i = 0 # iterator
while flag[-1] != '}':
trial = encrypt(flag+chars[i])
# Check if our encrypted trial flag matches the mystery one
if trial == mystery[:len(flag)+1]:
flag += chars[i]
i = 0
else:
i += 1
# If we run out of characters
if i >= len(chars):
print('Expand character list!')
break
print('Gottem!:', flag)
Which neatly returns our desired flag
Gottem!: NETON{Y0u_4r3_0n_th3_t0p!}