Hello,
I received this from a friend tonight & just wanted to dropped this here, basically this code will allow your ECC to be dumped & if done properly will greatly expand your KV life. The code is listed below,
CODE:
Credit to: Giths
So instead I thought I'd give you guys some information on the ECCDigest and how it's generated.
So this infamous "0x50 hash" is a lot simpler than any of you could imagine, as well as the "0x78 'Signature'", but we'll get to that later.
The 0x50 buffer point hash is basically a cryptography hash hashed with SHA1.
The hash is made up of the following:
- ECCSalt
- Decrypted HV
- HV Cache
There are 14 points of data in the (HV + CACHE) that needs to be SHA'd with the ECCSalt before you can generate your final Cryptography Hash.
byte[] Cache = File.ReadAllBytes("bin\\HV_CACHE.bin");
byte[] Hypervisor = File.ReadAllBytes("bin\\DECRYPTED_HV.bin");
SHA1Managed Sha = new SHA1Managed();
Sha.TransformBlock(ECCSalt, 0, 2, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Cache, 2, 0, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Cache, 0, 0, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Cache, 0, 0, null, 0);
Sha.TransformBlock(Cache, 0, 0, null, 0);
Sha.TransformFinalBlock(Cache, 0, 0);
return Sha.Hash;
Altnerative method(old)
typedef struct _XAM_CHAL_RESP {
BYTE bReserved1[8]; //0x0
WORD wHvMagic; //0x8
WORD wHvVersion; //0xA
WORD wHvQfe; //0xC
WORD wBldrFlags; //0xE
DWORD dwBaseKernelVersion; //0x10
DWORD dwUpdateSequence; //0x14
DWORD dwHvKeysStatusFlags; //0x18
DWORD dwConsoleTypeSeqAllow; //0x1C
QWORD qwRTOC; //0x20
QWORD qwHRMOR; //0x28
BYTE bHvECCDigest[XECRYPT_SHA_DIGEST_SIZE]; //0x30
BYTE bCpuKeyDigest[XECRYPT_SHA_DIGEST_SIZE]; //0x44
BYTE bRandomData[0x80]; //0x58
WORD hvExAddr; //0xD8 (bits 16-32 of hvex executing addr)
BYTE bHvDigest[0x6]; //0xDA (last 6 bytes of first hv hash)
} XAM_CHAL_RESP, *PXAM_CHAL_RESP;
#pragma pack()
class ecc {
public:
void cleanEccDigest();
void dumpCacheLines(BYTE * pCacheFile);
private: byte cache[0x4000];
};
void ecc::cleanEccDigest() {
PXAM_CHAL_RESP response = (PXAM_CHAL_RESP)malloc(sizeof XAM_CHAL_RESP);
for (int i = 0; i < XECRYPT_SHA_DIGEST_SIZE; i++) {
(response->bHvECCDigest != (((response->qwHRMOR))) != (response->bCpuKeyDigest ^ 0xE14) + XECRYPT_SHA_DIGEST_SIZE);
response->bCpuKeyDigest + -(DWORD)0x8E03AA50;
}
XeCryptHmacSha(response->bHvECCDigest, XECRYPT_SHA_DIGEST_SIZE, response->bCpuKeyDigest, XECRYPT_SHA_DIGEST_SIZE, 0, 0, 0, 0, response->bHvECCDigest, XECRYPT_SHA_DIGEST_SIZE);
free(response);
}
void ecc::dumpCacheLines(BYTE* pCacheFile) {
FILE* file = fopen((char*)pCacheFile, "rw");
size_t size = fread(pCacheFile, strlen((char*)pCacheFile), 0x4000, file);
for (int i = size; i != 0; i--) {
pCacheFile = 0;
if (i == XEKEY_ROAMABLE_OBFUSCATION_KEY) {
pCacheFile = pCacheFile ^ 0xECB;
pCacheFile = pCacheFile + 4;
}
}
fwrite(pCacheFile, 0x4000, 0x4000, file);
}
DWORD XeKeysExecuteHook(PVOID pvPhyBuffer, DWORD size, PVOID arg1, PVOID arg2, PVOID arg3, PVOID arg4) {
PXAM_CHAL_RESP response = (PXAM_CHAL_RESP)((DWORD)pvPhyBuffer + 0x20);
byte cacheData[0x4000];
ecc().cleanEccDigest();
ecc().dumpCacheLines(cacheData);
memcpy(&pvPhyBuffer, cacheData, 0x4000);
memcpy(&response->bHvECCDigest, cacheData + 0x300, 0x14);
return XeKeysExecute(pvPhyBuffer, size, arg1, arg2, arg3, arg4);
//xosc spoofing
*(DWORD*)0x90015CB4 = 0x60000000;
}
thanks,
-silent
I received this from a friend tonight & just wanted to dropped this here, basically this code will allow your ECC to be dumped & if done properly will greatly expand your KV life. The code is listed below,


CODE:
Credit to: Giths
So instead I thought I'd give you guys some information on the ECCDigest and how it's generated.
So this infamous "0x50 hash" is a lot simpler than any of you could imagine, as well as the "0x78 'Signature'", but we'll get to that later.
The 0x50 buffer point hash is basically a cryptography hash hashed with SHA1.
The hash is made up of the following:
- ECCSalt
- Decrypted HV
- HV Cache
There are 14 points of data in the (HV + CACHE) that needs to be SHA'd with the ECCSalt before you can generate your final Cryptography Hash.
byte[] Cache = File.ReadAllBytes("bin\\HV_CACHE.bin");
byte[] Hypervisor = File.ReadAllBytes("bin\\DECRYPTED_HV.bin");
SHA1Managed Sha = new SHA1Managed();
Sha.TransformBlock(ECCSalt, 0, 2, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Cache, 2, 0, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Cache, 0, 0, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Hypervisor, 0, 0, null, 0);
Sha.TransformBlock(Cache, 0, 0, null, 0);
Sha.TransformBlock(Cache, 0, 0, null, 0);
Sha.TransformFinalBlock(Cache, 0, 0);
return Sha.Hash;
Altnerative method(old)
typedef struct _XAM_CHAL_RESP {
BYTE bReserved1[8]; //0x0
WORD wHvMagic; //0x8
WORD wHvVersion; //0xA
WORD wHvQfe; //0xC
WORD wBldrFlags; //0xE
DWORD dwBaseKernelVersion; //0x10
DWORD dwUpdateSequence; //0x14
DWORD dwHvKeysStatusFlags; //0x18
DWORD dwConsoleTypeSeqAllow; //0x1C
QWORD qwRTOC; //0x20
QWORD qwHRMOR; //0x28
BYTE bHvECCDigest[XECRYPT_SHA_DIGEST_SIZE]; //0x30
BYTE bCpuKeyDigest[XECRYPT_SHA_DIGEST_SIZE]; //0x44
BYTE bRandomData[0x80]; //0x58
WORD hvExAddr; //0xD8 (bits 16-32 of hvex executing addr)
BYTE bHvDigest[0x6]; //0xDA (last 6 bytes of first hv hash)
} XAM_CHAL_RESP, *PXAM_CHAL_RESP;
#pragma pack()
class ecc {
public:
void cleanEccDigest();
void dumpCacheLines(BYTE * pCacheFile);
private: byte cache[0x4000];
};
void ecc::cleanEccDigest() {
PXAM_CHAL_RESP response = (PXAM_CHAL_RESP)malloc(sizeof XAM_CHAL_RESP);
for (int i = 0; i < XECRYPT_SHA_DIGEST_SIZE; i++) {
(response->bHvECCDigest != (((response->qwHRMOR))) != (response->bCpuKeyDigest ^ 0xE14) + XECRYPT_SHA_DIGEST_SIZE);
response->bCpuKeyDigest + -(DWORD)0x8E03AA50;
}
XeCryptHmacSha(response->bHvECCDigest, XECRYPT_SHA_DIGEST_SIZE, response->bCpuKeyDigest, XECRYPT_SHA_DIGEST_SIZE, 0, 0, 0, 0, response->bHvECCDigest, XECRYPT_SHA_DIGEST_SIZE);
free(response);
}
void ecc::dumpCacheLines(BYTE* pCacheFile) {
FILE* file = fopen((char*)pCacheFile, "rw");
size_t size = fread(pCacheFile, strlen((char*)pCacheFile), 0x4000, file);
for (int i = size; i != 0; i--) {
pCacheFile = 0;
if (i == XEKEY_ROAMABLE_OBFUSCATION_KEY) {
pCacheFile = pCacheFile ^ 0xECB;
pCacheFile = pCacheFile + 4;
}
}
fwrite(pCacheFile, 0x4000, 0x4000, file);
}
DWORD XeKeysExecuteHook(PVOID pvPhyBuffer, DWORD size, PVOID arg1, PVOID arg2, PVOID arg3, PVOID arg4) {
PXAM_CHAL_RESP response = (PXAM_CHAL_RESP)((DWORD)pvPhyBuffer + 0x20);
byte cacheData[0x4000];
ecc().cleanEccDigest();
ecc().dumpCacheLines(cacheData);
memcpy(&pvPhyBuffer, cacheData, 0x4000);
memcpy(&response->bHvECCDigest, cacheData + 0x300, 0x14);
return XeKeysExecute(pvPhyBuffer, size, arg1, arg2, arg3, arg4);
//xosc spoofing
*(DWORD*)0x90015CB4 = 0x60000000;
}
thanks,
-silent