private void _buildAsmArrays() { if (OriginalLocalCode == null) { OriginalLocalCode = RBytes(OriginalLocalCodeStartOffset.ToInt64(), OriginalLocalCodeLength); } using (var _customRemoteCodeMemoryStream = new MemoryStream(OriginalLocalCodeLength)) { //Start building wrapped user code at the location immediately after the copy of the original //code ends (unless OriginalCodeAtEnd is defined, in which case, it's at the beginning of CustomRemoteCodeHandle) : var customRemoteCodeCodeBuilder = new X86Writer(_customRemoteCodeMemoryStream, (IntPtr)(CustomRemoteCodeHandle.GetHandle().ToInt64())); //If OriginalCodeAtEnd is not defined, write the original code at the start of the custom remote code: if (!OriginalCodeAtEnd) { _customRemoteCodeMemoryStream.Write(OriginalLocalCode, 0, OriginalLocalCodeLength); } BuildCustomRemoteCode(customRemoteCodeCodeBuilder, _customRemoteCodeMemoryStream); //If OriginalCodeAtEnd is defined, write the original code at the end of the custom remote code: if (OriginalCodeAtEnd) { _customRemoteCodeMemoryStream.Write(OriginalLocalCode, 0, OriginalLocalCodeLength); } //Jump to return offset at end of wrapped function: customRemoteCodeCodeBuilder.Jmp(CustomRemoteCodeReturnDestinationOffset); //Copy the bytes of the ASM to our array before exiting the "using" statement and disposing the MemoryStream: CustomRemoteCode = _customRemoteCodeMemoryStream.ToArray(); } using (var _customLocalCodeMemoryStream = new MemoryStream(OriginalLocalCodeLength)) { var customLocalCodeCodeBuilder = new X86Writer(_customLocalCodeMemoryStream, OriginalLocalCodeStartOffset); // Jump to our wrapped code instead of doing the original code: customLocalCodeCodeBuilder.Jmp(CustomRemoteCodeHandle.GetHandle()); // Fill in the rest of the original instructions with NOP's: while (_customLocalCodeMemoryStream.Position < OriginalLocalCodeLength) { customLocalCodeCodeBuilder.Nop(); } CustomLocalCode = _customLocalCodeMemoryStream.ToArray(); } }
public void PatchCode(bool force = false) { if (IsPatched && !force) { return; } //Write the wrapped code to the allocated memory region: var wrappedCodeHandle = CustomRemoteCodeHandle.GetHandle(); WBytes((wrappedCodeHandle, wrappedCodeHandle), CustomRemoteCode); //Flush instruction cache for wrapped code: Kernel.FlushInstructionCache(DARKSOULS.GetHandle(), CustomRemoteCodeHandle.GetHandle(), (UIntPtr)CustomLocalCodeAllocSize); /* * * >> The rest of this method: << * * Patch original local code while Dark Souls is suspended so that there will be a 0.0% chance of the * game trying to execute only-partially-overridden code instead of the usual 0.00000001% chance ;) * */ //Suspend execution of Dark Souls process: DARKSOULS.Suspend(); //Overwrite the original local code with the custom local code: WBytes((OriginalLocalCodeStartOffset, OriginalLocalCodeStartOffset), CustomLocalCode); //Flush the instruction cache over the span of the local code: Kernel.FlushInstructionCache(DARKSOULS.GetHandle(), OriginalLocalCodeStartOffset, (UIntPtr)OriginalLocalCodeLength); //Resume execution of Dark Souls process: DARKSOULS.Resume(); IsPatched = true; }