Skip to content

Jenny From The Block

from hashlib import sha256
from Crypto.Util.Padding import pad, unpad
import signal
import subprocess
import socketserver
import os

allowed_commands = [b'whoami', b'ls', b'cat secret.txt', b'pwd']
BLOCK_SIZE = 32


def encrypt_block(block, secret):
    enc_block = b''
    for i in range(BLOCK_SIZE):
        val = (block[i]+secret[i]) % 256
        enc_block += bytes([val])
    return enc_block


def encrypt(msg, password):
    h = sha256(password).digest()
    if len(msg) % BLOCK_SIZE != 0:
        msg = pad(msg, BLOCK_SIZE)
    blocks = [msg[i:i+BLOCK_SIZE] for i in range(0, len(msg), BLOCK_SIZE)]
    ct = b''
    for block in blocks:
        enc_block = encrypt_block(block, h)
        h = sha256(enc_block + block).digest()
        ct += enc_block

    return ct.hex()


def run_command(cmd):
    if cmd in allowed_commands:
        try:
            resp = subprocess.run(
                cmd.decode().split(' '),  capture_output=True)
            output = resp.stdout
            return output
        except:
            return b'Something went wrong!\n'
    else:
        return b'Invalid command!\n'


def challenge(req):
    req.sendall(b'This is Jenny! I am the heart and soul of this spaceship.\n' +
                b'Welcome to the debug terminal. For security purposes I will encrypt any responses.')
    while True:
        req.sendall(b'\n> ')
        command = req.recv(4096).strip()
        output = run_command(command)
        response = b'Command executed: ' + command + b'\n' + output
        password = os.urandom(32)
        ct = encrypt(response, password)
        req.sendall(ct.encode())


class incoming(socketserver.BaseRequestHandler):
    def handle(self):
        signal.alarm(30)
        req = self.request
        challenge(req)


class ReusableTCPServer(socketserver.ForkingMixIn, socketserver.TCPServer):
    pass


def main():
    socketserver.TCPServer.allow_reuse_address = True
    server = ReusableTCPServer(("0.0.0.0", 1337), incoming)
    server.serve_forever()


if __name__ == "__main__":
    main()
flag.py
from Crypto.Util.Padding import pad, unpad
from hashlib import sha256

BLOCK_SIZE = 32

def decrypt(enc_block, secret):
    dec_block = b''
    for i in range(BLOCK_SIZE):
        val = (enc_block[i]-secret[i]) % 256
        dec_block += bytes([val])
    return dec_block

# setelah percobaan, diketahui blocks[0] pas dengan= Command executed: cat secret.txt
output_cat_secret = 'a2a78c0b6964d8d4ce5d2cab44662a167a8be2dd3ba043ef1d75d63d3e1a06a5d7e3b61d118c2bee845a89c264f00e93d77d2bb3ed07f864a7e6c02489f4cff37bc62ef8be58dc12a083e51def424eea3d7f0599ef305e25b6dce2e51504a33df2eb3cbdd1785ebc7e6ee5cfd014d5285035bfa685d088233f96c27a1a53dbf24e3fbe64e82d1ac7e5aff88eb9abdca2e9981e5aab3a9de8e22001e425b9fdd8d1b468482fed1b3221395575eee91f757e69a2049697fd585a19034df03c348ab28fbc76260c51dfea9482fe3b967131ebd7c80f45aa72bb2663ea0523962a74b8ab3378f3d4bc30f65a74971bdd07c4d337fba947e21007c9ef5fceb8f38d09'
# nilai output bebas, sama saja
enc = bytes.fromhex(output_cat_secret)
enc_blocks = [enc[i:i+BLOCK_SIZE] for i in range(0, len(enc), BLOCK_SIZE)]

block = b'Command executed: cat secret.txt'

pt = b''
for i in range(len(enc_blocks)-1):
    h = sha256(enc_blocks[i] + block).digest()
    p = decrypt(enc_blocks[i+1], h)
    block = p
    pt += p

print(pt)

flag HTB{b451c_b10ck_c1ph3r_15_w34k!!!}