C
C#6mo ago
elpupper

System.AccessViolationException In windows but not in linux

I come here alas, I could not figure this out for 3 days now I am basically writing a plugin for CS2 dedicated servers using CS# My goal is to access the subtick movements introduced in cs2 to record some movements as keypressed dont call commands till the next game tick so basically I have
public required MemoryFunctionVoid<IntPtr, IntPtr, int, bool, float, IntPtr> ProcessUsercmds;

// access the signatures in Load function
ProcessUsercmds = new(GameData.GetSignature("ProcessUsercmds"));
ProcessUsercmds.Hook(_OnProcessUsercmds, HookMode.Pre);


public HookResult _OnProcessUsercmds(DynamicHook h)
{
Logger.LogInformation("OnProcessUsercmds");
Logger.LogInformation("Param0: {value}", h.GetParam<IntPtr>(0));
nint ptr = h.GetParam<IntPtr>(0);
if (ptr == IntPtr.Zero)
return HookResult.Continue;
Logger.LogInformation("Ptr: {value}", ptr);
unsafe
{
// error happens here i tried CCSPlayerController player = new(ptr) but same error
// Whatever I try to do here to recast the type i just get that same error and ONLY in windows
CCSPlayerController player = ReinterpretCast<IntPtr, CCSPlayerController>(ptr);
Logger.LogInformation("Player: {value}", player);
Logger.LogInformation("Player SteamID: {value}", player.SteamID);
}
//Logger.LogInformation("Param0[CCSPlayerController*]: {value}", h.GetParam<CCSPlayerController>(0));
Logger.LogInformation("Param1[CUserCmd*]: {value}", h.GetParam<IntPtr>(1));
Logger.LogInformation("Param2[cmdCount]: {value}", h.GetParam<int>(2));
Logger.LogInformation("Param3[paused]: {value}", h.GetParam<bool>(3));
Logger.LogInformation("Param4[margin]: {value}", h.GetParam<float>(4));

return HookResult.Continue;
}

public required MemoryFunctionVoid<IntPtr, IntPtr, int, bool, float, IntPtr> ProcessUsercmds;

// access the signatures in Load function
ProcessUsercmds = new(GameData.GetSignature("ProcessUsercmds"));
ProcessUsercmds.Hook(_OnProcessUsercmds, HookMode.Pre);


public HookResult _OnProcessUsercmds(DynamicHook h)
{
Logger.LogInformation("OnProcessUsercmds");
Logger.LogInformation("Param0: {value}", h.GetParam<IntPtr>(0));
nint ptr = h.GetParam<IntPtr>(0);
if (ptr == IntPtr.Zero)
return HookResult.Continue;
Logger.LogInformation("Ptr: {value}", ptr);
unsafe
{
// error happens here i tried CCSPlayerController player = new(ptr) but same error
// Whatever I try to do here to recast the type i just get that same error and ONLY in windows
CCSPlayerController player = ReinterpretCast<IntPtr, CCSPlayerController>(ptr);
Logger.LogInformation("Player: {value}", player);
Logger.LogInformation("Player SteamID: {value}", player.SteamID);
}
//Logger.LogInformation("Param0[CCSPlayerController*]: {value}", h.GetParam<CCSPlayerController>(0));
Logger.LogInformation("Param1[CUserCmd*]: {value}", h.GetParam<IntPtr>(1));
Logger.LogInformation("Param2[cmdCount]: {value}", h.GetParam<int>(2));
Logger.LogInformation("Param3[paused]: {value}", h.GetParam<bool>(3));
Logger.LogInformation("Param4[margin]: {value}", h.GetParam<float>(4));

return HookResult.Continue;
}

this code works completely fine in linux but not on windows
61 Replies
Gamma_Draconis
Gamma_Draconis6mo ago
Could you define the idea behind the code? What's it's intended purpose? And could we get the implementation of To ReinterpretCast<From, To>(From value) please?
elpupper
elpupperOP6mo ago
ah yes sorry
static unsafe TDest ReinterpretCast<TSource, TDest>(TSource source)
{
var sourceRef = __makeref(source);
var dest = default(TDest);
var destRef = __makeref(dest);
*(IntPtr*)&destRef = *(IntPtr*)&sourceRef;
return __refvalue(destRef, TDest);
}
static unsafe TDest ReinterpretCast<TSource, TDest>(TSource source)
{
var sourceRef = __makeref(source);
var dest = default(TDest);
var destRef = __makeref(dest);
*(IntPtr*)&destRef = *(IntPtr*)&sourceRef;
return __refvalue(destRef, TDest);
}
the idea rn atleast is to be able t get the steamid from the player
CCSPlayerController player = ReinterpretCast<IntPtr, CCSPlayerController>(ptr);
Logger.LogInformation("Player: {value}", player);
Logger.LogInformation("Player SteamID: {value}", player.SteamID);
CCSPlayerController player = ReinterpretCast<IntPtr, CCSPlayerController>(ptr);
Logger.LogInformation("Player: {value}", player);
Logger.LogInformation("Player SteamID: {value}", player.SteamID);
this gives us the playercontroller and we can do a lot of things with it but for now just something basic like printing the user's steamid but the end goal is to be able to access the subtick params
Gamma_Draconis
Gamma_Draconis6mo ago
Generally speaking, it's not desireable to use a hidden/undocumented C# operator like __makeref(). The desired behavior can be written as return Unsafe.As<TSource, TDest>(ref source); The Unsafe helper class is exposed from System.Runtime.CompilerServices. This is of course assuming both types are the same size, and are both value types. Something tells me the IntPtr aka nint is actually a CCSPlayerController* or similar, in which case the desired code should be something like this:
CCSPlayerController player = *(CCSPlayerController*)ptr;
CCSPlayerController player = *(CCSPlayerController*)ptr;
Is my assumption correct?
elpupper
elpupperOP6mo ago
yes i tried that as well CCSPlayerController does take a pointer
Gamma_Draconis
Gamma_Draconis6mo ago
Could we get a definition of the type in question?
Gamma_Draconis
Gamma_Draconis6mo ago
Is it just a wrapper around a pointer? Oh god that's a class... In which case, new CCSPlayerController(ptr) should be used.
elpupper
elpupperOP6mo ago
thats what i did and i still get that error
Gamma_Draconis
Gamma_Draconis6mo ago
Do you know if the pointer is valid? It could be non-null and yet still not be valid.
elpupper
elpupperOP6mo ago
yes it is valid it is from a sig from the modding community
Gamma_Draconis
Gamma_Draconis6mo ago
What's the stack trace of the exception?
elpupper
elpupperOP6mo ago
let me try to get it again server crashes so fast without logs here i will try it with CCSPlayerController player = *(CCSPlayerController*)ptr;
Gamma_Draconis
Gamma_Draconis6mo ago
Won't work if CCSPlayerController is a class At least it won't work as intended If the pointer to object reference feature is implemented yet. In any case, the exception tells me that some pointer or another isn't being interpretted correctly.
elpupper
elpupperOP6mo ago
Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at System.Runtime.CompilerServices.CastHelpers.StelemRef(System.Array, IntPtr, System.Object)
at HelloWorldPlugin.HelloWorldPlugin._OnProcessUsercmds(CounterStrikeSharp.API.Modules.Memory.DynamicFunctions.DynamicHook)
at System.RuntimeMethodHandle.InvokeMethod(System.Object, Void**, System.Signature, Boolean)
at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(System.Object, System.Span`1<System.Object>, System.Reflection.BindingFlags)
at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)
at System.Delegate.DynamicInvokeImpl(System.Object[])
at CounterStrikeSharp.API.Core.FunctionReference.<CreateWrappedCallback>b__18_0(CounterStrikeSharp.API.Core.fxScriptContext*)
Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at System.Runtime.CompilerServices.CastHelpers.StelemRef(System.Array, IntPtr, System.Object)
at HelloWorldPlugin.HelloWorldPlugin._OnProcessUsercmds(CounterStrikeSharp.API.Modules.Memory.DynamicFunctions.DynamicHook)
at System.RuntimeMethodHandle.InvokeMethod(System.Object, Void**, System.Signature, Boolean)
at System.Reflection.MethodBaseInvoker.InvokeDirectByRefWithFewArgs(System.Object, System.Span`1<System.Object>, System.Reflection.BindingFlags)
at System.Reflection.MethodBaseInvoker.InvokeWithOneArg(System.Object, System.Reflection.BindingFlags, System.Reflection.Binder, System.Object[], System.Globalization.CultureInfo)
at System.Delegate.DynamicInvokeImpl(System.Object[])
at CounterStrikeSharp.API.Core.FunctionReference.<CreateWrappedCallback>b__18_0(CounterStrikeSharp.API.Core.fxScriptContext*)
@Gamma_Draconis here it is
Gamma_Draconis
Gamma_Draconis6mo ago
at System.Runtime.CompilerServices.CastHelpers.StelemRef(System.Array, IntPtr, System.Object) This right here...
elpupper
elpupperOP6mo ago
i dont understand this
Gamma_Draconis
Gamma_Draconis6mo ago
I don't understand it either because you're not accessing an array...
elpupper
elpupperOP6mo ago
ill try iwth CCSPlayerController player = ReinterpretCast<IntPtr, CCSPlayerController>(ptr); and get the full thing owe i got a big error 1 sec
Gamma_Draconis
Gamma_Draconis6mo ago
Yeah no, I expected that to fail.
Gamma_Draconis
Gamma_Draconis6mo ago
Can I get the implementation of DynamicHook?
Gamma_Draconis
Gamma_Draconis6mo ago
GitHub
CounterStrikeSharp/managed/CounterStrikeSharp.API/Modules/Memory/Dy...
CounterStrikeSharp allows you to write server plugins in C# for Counter-Strike 2/Source2/CS2 - roflmuffin/CounterStrikeSharp
Gamma_Draconis
Gamma_Draconis6mo ago
...something about their native interop doesn't sit right with me...
elpupper
elpupperOP6mo ago
tell me about it
Gamma_Draconis
Gamma_Draconis6mo ago
I'd expect a function pointer to be here... but instead I get... whatever the heck that is. That does not help me or anyone else debug an access violation.
elpupper
elpupperOP6mo ago
what do you suggest i do
Gamma_Draconis
Gamma_Draconis6mo ago
Talk to a maintainer of the codebase about it. If that should fail, I haven't a clue.
elpupper
elpupperOP6mo ago
ok
Gamma_Draconis
Gamma_Draconis6mo ago
The maintainers of CounterStrikeSharp specifically, in case that wasn't clear. ^_^
elpupper
elpupperOP6mo ago
yes i get it im not that incompentent
Gamma_Draconis
Gamma_Draconis6mo ago
I can never be sure with some people lol
elpupper
elpupperOP6mo ago
i just dont understand c# that much dont blame ya
Gamma_Draconis
Gamma_Draconis6mo ago
I'm certain this is just a lack of understanding of what to do here, but I am not the source of this knowledge.
elpupper
elpupperOP6mo ago
thought i mighta said something that made me seem crazy
Gamma_Draconis
Gamma_Draconis6mo ago
Nah, you're good. lol Wait..
elpupper
elpupperOP6mo ago
uhoh
Gamma_Draconis
Gamma_Draconis6mo ago
Could it be that it needs to be written out as h.GetParam<CCSPlayerController>(0)? Or does that not work?
elpupper
elpupperOP6mo ago
no because of memoryfunctionvoid even if i had public required MemoryFunctionVoid<CCSPlayerController, IntPtr, int, bool, float, IntPtr> ProcessUsercmds;
Gamma_Draconis
Gamma_Draconis6mo ago
Why wouldn't that work? Do you know?
elpupper
elpupperOP6mo ago
let me try again i forgot the error
Gamma_Draconis
Gamma_Draconis6mo ago
It looks like, according to the stack trace, the general setup is supported, but something's not being looked at right. Talk to a maintainer, see what they think. Do you control what's passed as the first argument at all? Or is the caller in Native?
elpupper
elpupperOP6mo ago
wel uy usee its all really based on metamod i32 FASTCALL movement::Detour_ProcessUsercmds(CCSPlayerController *controller, void *cmds, int numcmds, bool paused, float margin)
Gamma_Draconis
Gamma_Draconis6mo ago
If new CCSPlayerController(ptr); doesn't work, I imagine it's a bug in the framework's code somewhere. So I don't think this is on you at all, given that definition.
elpupper
elpupperOP6mo ago
but why does this work in linux
Gamma_Draconis
Gamma_Draconis6mo ago
Memory layout can change between windows and linux. If they're using constant field offsets, that could screw things up.
elpupper
elpupperOP6mo ago
thats why we have signatures
"ProcessUsercmds": {
"signatures": {
"library": "server",
"windows": "\\x48\\x8B\\xC4\\x44\\x88\\x48\\x20\\x44\\x89\\x40\\x18\\x48\\x89\\x50\\x10\\x56",
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x89\\xD6\\x41\\x55\\x41\\x54\\x49\\x89\\xFC\\x53\\x48\\x83\\xEC\\x38"
}
}
"ProcessUsercmds": {
"signatures": {
"library": "server",
"windows": "\\x48\\x8B\\xC4\\x44\\x88\\x48\\x20\\x44\\x89\\x40\\x18\\x48\\x89\\x50\\x10\\x56",
"linux": "\\x55\\x48\\x89\\xE5\\x41\\x57\\x41\\x56\\x41\\x89\\xD6\\x41\\x55\\x41\\x54\\x49\\x89\\xFC\\x53\\x48\\x83\\xEC\\x38"
}
}
Gamma_Draconis
Gamma_Draconis6mo ago
Signatures affect method calls only, memory layout affects objects and data structures in memory
elpupper
elpupperOP6mo ago
yes but its consistent
Gamma_Draconis
Gamma_Draconis6mo ago
Padding and so forth add into that
elpupper
elpupperOP6mo ago
btw it doesnt even let me try catch these things
Gamma_Draconis
Gamma_Draconis6mo ago
This is a runtime level exception, it wouldn't let anyone try to catch them. Something about this isn't right, in this particular circumstance. That's as far as I can go.
elpupper
elpupperOP6mo ago
why
Gamma_Draconis
Gamma_Draconis6mo ago
Wait, no, not that... This According to the exception stack trace get_Raw being the Raw property's getter
elpupper
elpupperOP6mo ago
im sicka this i giveup fuck cs2
Want results from more Discord servers?
Add your server