diff --git a/build/win32/CxbxKrnl.vcxproj b/build/win32/CxbxKrnl.vcxproj index 060787db3..14ba599ec 100644 --- a/build/win32/CxbxKrnl.vcxproj +++ b/build/win32/CxbxKrnl.vcxproj @@ -226,6 +226,7 @@ + @@ -609,6 +610,7 @@ %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) + %(AdditionalIncludeDirectories) %(PreprocessorDefinitions) diff --git a/import/OpenXDK/include/xboxkrnl/xbox.h b/import/OpenXDK/include/xboxkrnl/xbox.h index adccdda33..f06387847 100644 --- a/import/OpenXDK/include/xboxkrnl/xbox.h +++ b/import/OpenXDK/include/xboxkrnl/xbox.h @@ -185,8 +185,19 @@ XBSYSAPI EXPORTNUM(336) VOID NTAPI XcSHAUpdate(UCHAR *pbSHAContext, UCHAR *pbInp // ****************************************************************** XBSYSAPI EXPORTNUM(337) VOID NTAPI XcSHAFinal(UCHAR *pbSHAContext, UCHAR *pbDigest); -XBSYSAPI EXPORTNUM(338) VOID *XcRC4Key; -XBSYSAPI EXPORTNUM(339) VOID *XcRC4Crypt; +XBSYSAPI EXPORTNUM(338) VOID XcRC4Key +( + IN PUCHAR pbKeyStruct, + IN ULONG dwKeyLength, + IN PUCHAR pbKey +); + +XBSYSAPI EXPORTNUM(339) VOID XcRC4Crypt +( + IN PUCHAR pbKeyStruct, + IN ULONG dwInputLength, + IN PUCHAR pbInput +); XBSYSAPI EXPORTNUM(340) VOID NTAPI XcHMAC ( diff --git a/src/CxbxKrnl/EmuKrnl.cpp b/src/CxbxKrnl/EmuKrnl.cpp index 099997c21..464c06b6a 100644 --- a/src/CxbxKrnl/EmuKrnl.cpp +++ b/src/CxbxKrnl/EmuKrnl.cpp @@ -55,6 +55,12 @@ namespace NtDll #include "EmuNtDll.h" }; +// ****************************************************************** +// * Declaring this in a header causes errors with xboxkrnl +// * namespace, so we must declare it within any file that uses it +// ****************************************************************** +xboxkrnl::KPCR* KeGetPcr(); + // ****************************************************************** // * 0x0033 - InterlockedCompareExchange() // ****************************************************************** @@ -200,15 +206,8 @@ XBSYSAPI EXPORTNUM(160) xboxkrnl::UCHAR FASTCALL xboxkrnl::KfRaiseIrql LOG_FUNC_ONE_ARG(NewIrql); UCHAR OldIrql; - KPCR* Pcr = nullptr; - // Fetch KPCR data structure - __asm { - push eax - mov eax, fs:[0x14] - mov Pcr, eax - pop eax - } + KPCR* Pcr = KeGetPcr(); if (NewIrql < Pcr->Irql) { // TODO: Enable this after KeBugCheck is implemented diff --git a/src/CxbxKrnl/EmuKrnlKe.cpp b/src/CxbxKrnl/EmuKrnlKe.cpp index 2e789f66c..2aa96cbfc 100644 --- a/src/CxbxKrnl/EmuKrnlKe.cpp +++ b/src/CxbxKrnl/EmuKrnlKe.cpp @@ -57,6 +57,26 @@ namespace NtDll #include #include +// ****************************************************************** +// * KeGetPcr() +// * NOTE: This is a macro on the Xbox, however we implement it +// * as a function so it can suit our emulated KPCR structure +// ****************************************************************** +xboxkrnl::KPCR* KeGetPcr() +{ + xboxkrnl::KPCR* Pcr = nullptr; + + __asm { + push eax + mov eax, fs:[0x14] + mov Pcr, eax + pop eax + } + + return Pcr; +} + + // ****************************************************************** // * 0x005C - KeAlertResumeThread() // ****************************************************************** @@ -222,12 +242,7 @@ XBSYSAPI EXPORTNUM(103) xboxkrnl::KIRQL NTAPI xboxkrnl::KeGetCurrentIrql(void) KIRQL Irql; - // TODO : Untested : - __asm - { - mov al, byte ptr fs : [24h] - mov Irql, al - } + Irql = KeGetPcr()->Irql; RETURN(Irql); } @@ -439,13 +454,7 @@ XBSYSAPI EXPORTNUM(129) xboxkrnl::UCHAR NTAPI xboxkrnl::KeRaiseIrqlToDpcLevel() CxbxKrnlCleanup("Bugcheck: Caller of KeRaiseIrqlToDpcLevel is higher than DISPATCH_LEVEL!"); KIRQL kRet = NULL; - __asm - { - mov al, byte ptr fs:[24h] - mov kRet, al - mov al, DISPATCH_LEVEL - mov byte ptr fs:[24h], al - } + KeGetPcr()->Irql = DISPATCH_LEVEL; #ifdef _DEBUG_TRACE DbgPrintf("Raised IRQL to DISPATCH_LEVEL (2).\n"); diff --git a/src/CxbxKrnl/EmuKrnlXc.cpp b/src/CxbxKrnl/EmuKrnlXc.cpp index a0b7033aa..6294b9d6b 100644 --- a/src/CxbxKrnl/EmuKrnlXc.cpp +++ b/src/CxbxKrnl/EmuKrnlXc.cpp @@ -44,6 +44,7 @@ namespace xboxkrnl #include "Logging.h" // For LOG_FUNC() #include "EmuKrnlLogging.h" #include "EmuSha.h" // For A_SHAInit, etc. +#include "LibRc4.h" // For RC4 Functions // prevent name collisions namespace NtDll @@ -100,6 +101,44 @@ XBSYSAPI EXPORTNUM(337) xboxkrnl::VOID NTAPI xboxkrnl::XcSHAFinal A_SHAFinal((SHA_CTX*)pbSHAContext, pbDigest); } +// ****************************************************************** +// * 0x0152 - XcRC4Key() +// ****************************************************************** +XBSYSAPI EXPORTNUM(338) xboxkrnl::VOID xboxkrnl::XcRC4Key +( + IN PUCHAR pbKeyStruct, + IN ULONG dwKeyLength, + IN PUCHAR pbKey +) +{ + LOG_FUNC_BEGIN + LOG_FUNC_ARG_OUT(pbKeyStruct) + LOG_FUNC_ARG(dwKeyLength) + LOG_FUNC_ARG_OUT(pbKey) + LOG_FUNC_END; + + Rc4Initialise((Rc4Context*)pbKeyStruct, pbKey, dwKeyLength, 0); +} + +// ****************************************************************** +// * 0x0153 - XcRC4Crypt +// ****************************************************************** +XBSYSAPI EXPORTNUM(339) xboxkrnl::VOID xboxkrnl::XcRC4Crypt +( + IN PUCHAR pbKeyStruct, + IN ULONG dwInputLength, + IN PUCHAR pbInput +) +{ + LOG_FUNC_BEGIN + LOG_FUNC_ARG_OUT(pbKeyStruct) + LOG_FUNC_ARG(dwInputLength) + LOG_FUNC_ARG_OUT(pbInput) + LOG_FUNC_END; + + Rc4Xor((Rc4Context*)pbKeyStruct, pbInput, pbInput, dwInputLength); +} + // ****************************************************************** // * 0x0154 - XcHMAC() // ****************************************************************** diff --git a/src/CxbxKrnl/KernelThunk.cpp b/src/CxbxKrnl/KernelThunk.cpp index aaad5f985..54a075da3 100644 --- a/src/CxbxKrnl/KernelThunk.cpp +++ b/src/CxbxKrnl/KernelThunk.cpp @@ -403,8 +403,8 @@ extern "C" CXBXKRNL_API uint32 CxbxKrnl_KernelThunkTable[379] = (uint32)FUNC(&xboxkrnl::XcSHAInit), // 0x014F (335) (uint32)FUNC(&xboxkrnl::XcSHAUpdate), // 0x0150 (336) (uint32)FUNC(&xboxkrnl::XcSHAFinal), // 0x0151 (337) - (uint32)PANIC(0x0152), // 0x0152 (338) XcRC4Key - (uint32)PANIC(0x0153), // 0x0153 (339) XcRC4Crypt + (uint32)FUNC(&xboxkrnl::XcRC4Key), // 0x0152 (338) + (uint32)FUNC(&xboxkrnl::XcRC4Crypt), // 0x0153 (339) (uint32)FUNC(&xboxkrnl::XcHMAC), // 0x0154 (340) (uint32)PANIC(0x0155), // 0x0155 (341) XcPKEncPublic (uint32)PANIC(0x0156), // 0x0156 (342) XcPKDecPrivate diff --git a/src/CxbxKrnl/LibRc4.cpp b/src/CxbxKrnl/LibRc4.cpp new file mode 100644 index 000000000..6e3c1f53e --- /dev/null +++ b/src/CxbxKrnl/LibRc4.cpp @@ -0,0 +1,129 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// LibRC4 +// +// An implementation of RC4 stream cipher +// +// This is free and unencumbered software released into the public domain - June 2013 waterjuice.org +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// IMPORTS +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include "LibRc4.h" +#include + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// INTERNAL FUNCTIONS +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#define SwapBytes( Value1, Value2 ) \ +{ \ + uint8_t temp = Value1; \ + Value1 = Value2; \ + Value2 = temp; \ +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// PUBLIC FUNCTIONS +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Rc4Initialise +// +// Initialises an RC4 cipher and discards the specified number of first bytes. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void + Rc4Initialise + ( + Rc4Context* Context, + void* Key, + uint32_t KeySize, + uint32_t DropN + ) +{ + uint32_t i; + uint32_t j; + uint32_t n; + + // Setup key schedule + for( i=0; i<256; i++ ) + { + Context->S[i] = (uint8_t)i; + } + + j = 0; + for( i=0; i<256; i++ ) + { + j = ( j + Context->S[i] + ((uint8_t*)Key)[i % KeySize] ) % 256; + SwapBytes( Context->S[i], Context->S[j] ); + } + + i = 0; + j = 0; + + // Drop first bytes (if requested) + for( n=0; nS[i] ) % 256; + SwapBytes( Context->S[i], Context->S[j] ); + } + + Context->i = i; + Context->j = j; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Rc4Output +// +// Outputs the requested number of bytes from the RC4 stream +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void + Rc4Output + ( + Rc4Context* Context, + void* Buffer, + uint32_t Size + ) +{ + uint32_t n; + + for( n=0; ni = ( Context->i + 1 ) % 256; + Context->j = ( Context->j + Context->S[Context->i] ) % 256; + SwapBytes( Context->S[Context->i], Context->S[Context->j] ); + + ((uint8_t*)Buffer)[n] = Context->S[ (Context->S[Context->i] + Context->S[Context->j]) % 256 ]; + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Rc4Xor +// +// XORs the RC4 stream with an input buffer and puts the results in an output buffer. This is used for encrypting +// and decrypting data. InBuffer and OutBuffer can point to the same location for inplace encrypting/decrypting +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void + Rc4Xor + ( + Rc4Context* Context, + void* InBuffer, + void* OutBuffer, + uint32_t Size + ) +{ + uint32_t n; + + for( n=0; ni = ( Context->i + 1 ) % 256; + Context->j = ( Context->j + Context->S[Context->i] ) % 256; + SwapBytes( Context->S[Context->i], Context->S[Context->j] ); + + ((uint8_t*)OutBuffer)[n] = ((uint8_t*)InBuffer)[n] + ^ ( Context->S[ (Context->S[Context->i] + Context->S[Context->j]) % 256 ] ); + } +} + diff --git a/src/CxbxKrnl/LibRc4.h b/src/CxbxKrnl/LibRc4.h new file mode 100644 index 000000000..79f4c22ab --- /dev/null +++ b/src/CxbxKrnl/LibRc4.h @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// LibRC4 +// +// An implementation of RC4 stream cipher +// +// This is free and unencumbered software released into the public domain - June 2013 waterjuice.org +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#ifndef _LibRc4_h_ +#define _LibRc4_h_ + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// IMPORTS +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +#include + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// TYPES +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Rc4Context - This must be initialised using Rc4Initialised. Do not modify the contents of this structure directly. +typedef struct +{ + uint8_t S[256]; + uint32_t i; + uint32_t j; +} Rc4Context; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// PUBLIC FUNCTIONS +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Rc4Initialise +// +// Initialises an RC4 cipher and discards the specified number of first bytes. +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void + Rc4Initialise + ( + Rc4Context* Context, + void* Key, + uint32_t KeySize, + uint32_t DropN + ); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Rc4Output +// +// Outputs the requested number of bytes from the RC4 stream +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void + Rc4Output + ( + Rc4Context* Context, + void* Buffer, + uint32_t Size + ); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Rc4Xor +// +// XORs the RC4 stream with an input buffer and puts the results in an output buffer. This is used for encrypting +// and decrypting data. InBuffer and OutBuffer can point to the same location for inplace encrypting/decrypting +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void + Rc4Xor + ( + Rc4Context* Context, + void* InBuffer, + void* OutBuffer, + uint32_t Size + ); + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +#endif //_LibRc4_h_ +