From d930e400f1949577c6bfb494cd8525f27ef4f32d Mon Sep 17 00:00:00 2001 From: Vincent Berg Date: Tue, 24 Oct 2023 02:52:28 +0200 Subject: [PATCH] rsecssfs key decrypt fix (see #70) (#71) * rsecssfs key decrypt fix (see #70) * adding unit test --- pysap/SAPSSFS.py | 22 +++++++++++++++++++++- pysap/utils/crypto/__init__.py | 29 +++++++++++++++++++++++++++++ tests/data/ssfs_npl_dat | Bin 0 -> 794 bytes tests/data/ssfs_npl_key | Bin 0 -> 187 bytes tests/sapssfs_test.py | 26 +++++++++++++++++++++++++- 5 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 tests/data/ssfs_npl_dat create mode 100644 tests/data/ssfs_npl_key diff --git a/pysap/SAPSSFS.py b/pysap/SAPSSFS.py index f131266..d91be5c 100644 --- a/pysap/SAPSSFS.py +++ b/pysap/SAPSSFS.py @@ -26,7 +26,7 @@ from cryptography.hazmat.primitives.hashes import Hash, SHA1 from cryptography.hazmat.backends import default_backend # Custom imports -from pysap.utils.crypto import rsec_decrypt +from pysap.utils.crypto import rsec_decrypt, rsec_decrypt_key from pysap.utils.fields import PacketNoPadded, StrFixedLenPaddedField, TimestampField @@ -78,6 +78,26 @@ class SAPSSFSKey(Packet): StrFixedLenPaddedField("host", None, 24, padd=" "), ] +class SAPSSFSKeyE(Packet): + """SAP SSFS Key (encrypted) file format packet. + + Key file length is 0xbb + """ + name = "SAP SSFS Encrypted Key" + fields_desc = [ + StrFixedLenField("preamble", "RSecSSFsKey", 11), + ByteField("type", None), + TimestampField("timestamp", None), + StrFixedLenPaddedField("user", None, 24, padd=" "), + StrFixedLenPaddedField("host", None, 24, padd=" "), + # probably kind of check sum or just noise + StrFixedLenField("unknown", None, 62), + StrFixedLenField("key_enc", None, 57), + ] + + @property + def key(self): + return rsec_decrypt_key(self.key_enc) class SAPSSFSDecryptedPayload(PacketNoPadded): """SAP SSFS Decrypted Payload. diff --git a/pysap/utils/crypto/__init__.py b/pysap/utils/crypto/__init__.py index fbd1dff..4bd951f 100644 --- a/pysap/utils/crypto/__init__.py +++ b/pysap/utils/crypto/__init__.py @@ -367,3 +367,32 @@ def rsec_decrypt(blob, key): round_3 = cipher.crypt(RSECCipher.MODE_DECODE, round_2, key1, len(round_2)) return ''.join([chr(i) for i in round_3]) + +def rsec_decrypt_key(key_enc): + kek = "\x9F\x60\xA6\xDD\x7E\x15\x7D\x07\x0C\xC3\x57\x90\x9A\xA2\x90\xE9\x36\x0E\xEE\x47\x2F\xDA\x47\x72" + kek = [ord(i) for i in kek] + kek1 = kek[0:8] + kek2 = kek[8:16] + kek3 = kek[16:24] + """ Default Key Encryption Key embedded in rsecssfx/kernel binaries """ + + blob = [ord(i) for i in key_enc[:56]] + last_key_byte = bytearray(key_enc[56:]) + """ Last key byte is computed outside DES decryption """ + + cipher = RSECCipher() + round_1 = cipher.crypt(RSECCipher.MODE_DECODE, blob, kek3, len(blob)) + round_2 = cipher.crypt(RSECCipher.MODE_ENCODE, round_1, kek2, len(round_1)) + round_3 = cipher.crypt(RSECCipher.MODE_DECODE, round_2, kek1, len(round_2)) + + t1 = [ord(i) for i in key_enc[48:56]] + tmp = cipher.crypt(RSECCipher.MODE_ENCODE, t1, kek3, 8) + last_key_byte = last_key_byte[0] ^ tmp[0] + + tmp = cipher.crypt(RSECCipher.MODE_ENCODE, round_2[48:56], kek2, 8) + last_key_byte = last_key_byte ^ tmp[0] + + tmp = cipher.crypt(RSECCipher.MODE_ENCODE, round_2[48:56], kek1, 8) + last_key_byte = last_key_byte ^ tmp[0] + + return [chr(c) for c in round_3[33:] + [last_key_byte]] diff --git a/tests/data/ssfs_npl_dat b/tests/data/ssfs_npl_dat new file mode 100644 index 0000000000000000000000000000000000000000..ea5c733ce7eacc2651214a8c46961dfabd3a5af9 GIT binary patch literal 794 zcmWFvPE8IDb}M#CEJ-X&M;`?e0mzh8v#m~f1v!Z+ zxtN;EGLjQ>fRf3XsB$p-LHd{QI^AWS%N)cmu+KFsQv2k@MUNKQ8t&xt?r=Dh;C!Rd zUi!@0w*qaqRZeT$=!ta``?8R8h7K9RB47*_NrBZlJAT_)gU=9F=*RM~aYxchO%v*NnbZLTk z5KCqGOYe--oSgh}gQA=iRF|W~w6kY`hied-Q4NYIU`)>@+2tUOP~gw{yl!ot;QyF_ z)tAM#=;qf=G%{h&dzBE(eq@*Rk&MZ0rbfJLZIZs;Qd{{%<uL~#de{_v`IOpcOEAyS^-Ua{#Gwdk< literal 0 HcmV?d00001 diff --git a/tests/data/ssfs_npl_key b/tests/data/ssfs_npl_key new file mode 100644 index 0000000000000000000000000000000000000000..2884682e7a58f97f990e15b8c41c162763b6f9c3 GIT binary patch literal 187 zcmWFvPE8IDb}RNytz=>Vf>g6DxAF>d5>s*&FhE&Ga$*ipGC31f3Z#!9u>8C1S=d@F z@!aeqB1&J11Z`Nw@=yFN;+