-
-
Save halmartin/28e013a9034be04777073bccc918cb95 to your computer and use it in GitHub Desktop.
Fujitsu iRMC S4 PoC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# https://watchmysys.com/blog/2023/01/fujitsu-irmc-s4-license/ | |
import argparse | |
import base64 | |
import binascii | |
import zlib | |
import hmac | |
import hashlib | |
import struct | |
from Crypto.Cipher import AES | |
# obtain values from /usr/local/lib/libfts_license.so.1.12.1 | |
# Note that in python, you enter binary hex values as b"\x0d\x0e..." | |
HMAC_KEY = b"" | |
HMAC_MSG = b"" * 4 | |
AES_IV = b"" | |
def init_lookup_table(): | |
out = [] | |
for i in range(0x100): | |
lookup_table_entry = i << 0x18 | |
for k in range(8): | |
if lookup_table_entry >> 31: | |
inlr = lookup_table_entry << 1 | |
if lookup_table_entry >> 31: | |
lookup_table_entry = inlr ^ 0x4c11db7 | |
else: | |
lookup_table_entry = lookup_table_entry << 1 | |
lookup_table_entry &= 0xffffffff | |
out.append(lookup_table_entry) | |
return out | |
def spd_crc32(param_1, x): | |
tbl = init_lookup_table() | |
for pbVar1 in param_1: | |
x = (tbl[(pbVar1 ^ x >> 0x18) & 0xff] ^ x << 8) & 0xffffffff | |
return x | |
def simple_generator(ext_features, type, serial): | |
if ext_features.lower() == "kvm": | |
features = b"\x01\x00\x00\x00" | |
elif ext_features.lower() == "kvm_media": | |
features = b"\x03\x00\x00\x00" | |
elif ext_features.lower() == "kvm_media_elcm": | |
# this license type doesn't validate on my TX chassis | |
# but apparently works on RX chassis | |
if type.lower() == "tx": | |
print("License may not be valid for TX chassis with eLCM enabled") | |
features = b"\x0f\x00\x00\x00" | |
return license_generator(serial, features, type.lower()) | |
def license_generator(serial, features, type): | |
# chassis type TX | |
struct_data = 0xffffff00 | |
if type == "rx": | |
# chassis type RX | |
struct_data = 0xffffff05 | |
DATA = b'iRMC' \ | |
+ features \ | |
+ struct.pack('>I', struct_data) + \ | |
struct.pack('<I', spd_crc32(serial.encode("ASCII"), 1)) | |
print(binascii.hexlify(DATA).decode('utf-8')) | |
aes_key = hmac.new(HMAC_KEY, HMAC_MSG, hashlib.sha1).digest() | |
# this is AES-128, so only take the first 16 bytes of the aes_key | |
cipher = AES.new(aes_key[:16], AES.MODE_CBC, iv=AES_IV) | |
encrypted_license = cipher.encrypt(DATA) | |
encoded_license = base64.b32encode(encrypted_license) | |
license = encoded_license.decode("UTF-8").replace("=","") | |
return '-'.join(license[i:i+4] for i in range(0, len(license), 4)) | |
if __name__ == "__main__": | |
parser = argparse.ArgumentParser() | |
parser.add_argument("-t", "--type", type=str, default="tx", help="License type, valid values are 'TX' or 'RX'") | |
parser.add_argument("-f", "--features", type=str, default="kvm_media", help="License type, valid values are 'KVM', 'KVM_Media', or 'KVM_Media_eLCM'") | |
parser.add_argument("serial") | |
args = parser.parse_args() | |
if len(HMAC_KEY) != 16 or len(HMAC_MSG) != 16*4 or len(AES_IV) != 16: | |
print("You are missing the HMAC and AES values") | |
else: | |
print(simple_generator(args.features, args.type, args.serial)) |
I am trying to recover the values from the firmware file and I manage to get the libfts_license.so.1.12.1 most of the file is just @ and not really readable. The only thing that makes "sense" is:
^K^N^N^O^@^A^B^C ^H^G^FH!^@^@^A^@^@^@�!^@^@^B^@^@^@�!^@^@^H^@^@^@^@^@^@^@^@^@^@^@^A^B^C^D^A^B^C^D^A^B^C^D^A^B^C^DFujitsu!^A^A�(^@^@��AES CBC 128 Decrypt Fail
^@^@^@AES CBC 128 Decrypt final Fail
^@AES CBC 128 Encrypt updated in Confidentiality Trailer Fail
^@^@^@^@Confidentiality Trailer AES CBC 128 Encryption Fail
^@^@^@^@/conf/fts/license_key^@^@^@rb^@^@wb^@^@KVM^@2015-01-01 00:00:00^@%F %H:%M:%S^@Rejecting valid volume license due to cutoff date '%s'
^@sh /etc/init.d/licenseapp.sh manual &^@^@^@Could not decode license '%s' len=%d
^@^@^@MEDIA^@^@^@eLCM^@^@^@^@^@^@^@^@X^Q^@^@�^P^@^@^@^@^@^@^A^@^@^@8^C^@^@^A^@^@^@B^C^@^@^A^@^@^@R^C^@^@^A^@^@^@e^C^@^@^N^@^@^@�^C^@^@^O^@^@^@�^C^@^@^L^@^@^@�
I guess I have missed something on the way here? I am trying to open the file with nano after extracted the firmware with binwalk -e.
I guess I have missed something on the way here? I am trying to open the file with nano after extracted the firmware with binwalk -e.
libfts_license in Ghidra, showing decompiled function and hexdump
@Alotire432 Please do not post personal information in a public comment on GitHub. My contact information is available on my profile.
Your values for HMAC_KEY
, HMAC_MSG
, and AES_IV
are incorrect.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
If you want to investigate the exported license (using “iRMC S4” -> “Save Configuration” -> “Include License Information”), here is a validation script: