## Comment by the author (0x4d5a)
It turned out that this challenge was harder to solve then i expected. Thats quite unfortunate, since licpwn2 wasn't solved in the consequence. I've learned by lesson and won't do multi stage challenges anymore ;)

Also it turned out that may teams got the correct IV, but didn't craft a valid license object since they missed the fact that the AES key is at the very beginning of the license file. That should've been made more clear.

# licpwn stage1
A simple/medium crypto challenge. The goal is to get the IV of the AES encryption method in order to serialize a forged object. The IV is the flag. Once a valid license object was sent, the WAR file is provided for stage2.

## Description
The site offers a simple bootstrap webpage as shown below. It offers the user to buy some flags, but its actually all about the licensing system.

Using the provided license the user receives the "redeaced" flag. But he got a valid license.

## Solution
First of all the user should see the HTML comment with valid license data:


Using the stacktraces the user can understand the encrypted file format: The key are the first 16 bytes, followed by the binary encrypted data.

Using the scheme for cbc decryption the user can guess the IV using the known plaintext:

The known plaintext is the java object header `0xaced`, Version 5 `0x0005`, as well as the TC_OBJECT and TC_CLASSDESC constants `0x73` and `0x72`, followed by `0x00`. The 8th byte is unknown, but can be brute forced easily. The java serilialized object is followed by the package name, which is also leaked in the stacktrace: `com.licp`. See: https://docs.oracle.com/javase/8/docs/platform/serialization/spec/protocol.html

Using the information the IV can be guessed using the script of localo:

With all those information a valid java license file can be crafted and encrypted. Filling it with the valid license data from the html comment above the user gets the WAR file:

from Crypto.Cipher import AES

data = None
with open('small.lic') as f:
data = f.read()

key = data[:16]
message = data[16:]

fake_iv = message[:16]
fake_message = message[16:]

cipher = AES.new(key, AES.MODE_CBC, fake_iv)
dec = cipher.decrypt(fake_message)

print("decrypted: ")

data = '\xAC\xED\x00\x05\x73\x72\x00'
data+= '\xFF' #This byte needs to be guessed

guess_idx = 7

cipher = AES.new(key, AES.MODE_CBC, '\x00'*16)
dec2 = cipher.decrypt(message)

for i in range(len(data)):
a+= chr(ord(data[i])^ord(dec2[i]))

iv = a

print("partial IV: ")

plain = "A"*16

cipher = AES.new(key, AES.MODE_CBC, fake_iv)
dec2 = cipher.encrypt(plain)
print("Recrypt: ")

new_ciphertext = (fake_iv+dec2)


IV = "ABCDBBCD01230123"
cipher = AES.new(key, AES.MODE_CBC, IV)
new_plain = cipher.decrypt(new_ciphertext)

Flag: `ALLES{a3s_st4g3}`

Done :)

Original writeup (https://github.com/0x4d5a-ctf/Writeups/tree/master/2019/Camp2019/licpwn_1/documentation).