#Memory Address Crashes Program on Write unless Manually Stepped-Over

17 messages · Page 1 of 1 (latest)

median mulch
#

So a bit of context: I am writing a .dll that intends to expand a black 'view bar' that obscures vision past normal ranges in a 2d tile-based game.
The view bar's height is controlled by one value in a packed address, and its horizontal distance (the problem value) is controlled by another value in the same packed address. The game, however, will crash unless stepped-over manually in Visual Studio, or in x32dbg if the program is not paused when the changes occur.

I have checked the address and can confirm its validity. I took some time in x32dbg to look over the memory address in question (img-related) and found that the values cause a crash if:

A) the distance between the horizontal (0x17) and vertical (0x13) values exceeded 4 (only on horizontal value change oddly enough).

B) if the values were changed when the program in question was not paused by a debugger.

C) if the horizontal value is updated after the vertical value is not, even if it fits the aforementioned alignment conditions.

This is the weird part: The vertical value can change to quite-literally any value within reasonable bounds and not cause a crash. It's only the horizontal value that causes issues. On top of that, the address in question sometimes at complete random will write correctly under normal running conditions.

Overall, with all the info considered: this leads me to believe the values are being changed unevenly. One value is changed first in the code before the other while the program is still running, and if the program runs a compare function which ensures the two are aligned properly in the small time window that it is NOT properly aligned, it causes a crash.

My question is: how would I implement my code in a way to ensure the values are equally written, or at-least given time by the program to fully complete?

I will post some of the code in question below:

abstract cairnBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

median mulch
#

int* viewBarMain = reinterpret_cast<int*>(dllAddress + 0x003F55A0); // <---

Memory address in question. Can see it further in image.

void setViewVars() {

*viewBarMain = 0x0016001A; // <---- problematic command (crashes sometimes)

viewWVal = viewWFix + 33554432; 
viewHVal = viewHFix + 256;                  
viewFOVVal = viewFOVFix + 131074;     

            
viewWVal2 = viewWFix + 50331648;     
viewHVal2 = viewHFix + 768;                       
viewFOVVal2 = viewFOVFix + 262148;                   

}

Also apologies if my code looks messy here. The main object of attention is *viewBarMain.
I would really appreciate any help because this has had me stumped for hours.

#

Memory Address Crashes Program on Write unless Manually Stepped-Over

slim needle
#

how is the dllAddress value obtained? What is the nature of the crash? Could be a memory protection, alignment or other fault.

One thing that comes to mind is that if the address represented by viewBarMain is pointing to a .text (code) section of the DLL and memory protection is enabled, it should be read/execute only unless page permissions were modified in advance.

Another thought is that if your code is multi-threaded where read and write accesses are being made without serialization tended to can lead to all sorts of undefined behaviour.

median mulch
#

@slim needle
The dllAddress value is obtained by a simple GetModuleHandle request of this "byondcore.dll"

uintptr_t dllAddress = reinterpret_cast<uintptr_t>(GetModuleHandleA("byondcore.dll"));

As you can see below, it causes an access violation error message at a seemingly random address (I did this a few times and it's been different everytime). Again, only happens when the .dll is injected into the game in question without a breakpoint set at *viewBarMain and manually stepped over, which sets it otherwise.

median mulch
#

Since it works 100% of the time when the program is paused, I was thinking of mimicking that state of pause with a hook that pauses the game code momentarily with a Sleep() command while it updates the value. LMK if you think that could work.

slim needle
#

This behaviour strongly suggests a timing issue or incomplete memory setup. Is it possible that GetModuleHandle might return the base address before the module is entirely loaded and mapped into memory? I think your idea to delay is worth a try though I hate it as a solution. 🙂 You could also do a try/except a few times to see if it resolves without the sleep. Don't like that one much either. I suppose you could also try to validate the memory address beforehand. Don't take my example as gospel as I have never tried this before, but here you go:

MEMORY_BASIC_INFORMATION mbi;
if (VirtualQuery(viewBarMain, &mbi, sizeof(mbi)) && 
    mbi.State == MEM_COMMIT && 
    (mbi.Protect & (PAGE_READWRITE | PAGE_EXECUTE_READWRITE))) {
    *viewBarMain = 0x0016001A;
} else {
    // Decide what to do about the error
}

I am keen to know how you make out.

honest merlin
#

@median mulch if what supercubdude said above doesnt work as in the dll base address u get is always correct and the memory address is always valid, try setting the value of viewBarMain with InterlockedExchange

#

"crashes sometimes" and "it works 100% of the time when the program is paused" sounds like a race condition, if we were to assume the program is normal doesnt modify the memory protections of that region

#

WriteProcessMemory will also handle that for u iirc, memory protections will be changed automatically and it keeps atomicity

#

on the other hand it could be the program itself aswell intentionally crashing OR getting an unexpected value from viewBarMain that takes an unexpected execution route etc.. double check what accesses that address just incase

median mulch
#

@slim needle
Hey mate. Sorry for the long reply time, I've been testing methods all day (to the point of insanity).

I tested your solution and unfortunately it didn't work. Some values do load in incorrectly if the .dll is injected right upon program start. However, I always wait until it is fully loaded before injecting.

I've been trying to write an effective hook to test my method in the meantime, but have been stuck on another very annoying issue where my patch pointer address (which is type uint8_t) keeps retrieving incorrect values somehow when it is supposed to take 0x90 (NOP for padding). Everything was fine except the fact the NOP's wouldn't load in because of this reason. I'm still pretty new to C++ and the more advanced logic with it, so maybe I just messed something up on the way there without realising at this point.

@honest merlin
I also tried this to no avail, as well as WriteProcessMemory. I think it's hard-wired into the game itself for some reason. I traced the address in CE and found that it had a few addresses that were accessing it about 1000+ times a second. Some addresses, particularly mov eax, dword ptr ds: [THE-ADDRESS-IN-QUESTION] would crash the game in a very similar manner if I nop'd them. Another very interesting thing I noted was that the addresses in question would commonly be in a neverending, rapid loop of commands.

Think I might start from the ground up again after learning some more about effective hooking lol. It's been a headache.

frail arrow
honest merlin
#

i agree its indistinguishable, since this is also more about reversing i think the reverse engineering server would be a better place for this thread

median mulch
#

Yeah I see how you think that honestly. Believe it or not I'm mainly doing this for the education and because I find it interesting rather than to cheat. If it's any solace the game I'm working with is an old tile-based RP game, and I'm only trying to find a way to expand FOV.
Regardless, thanks for your time anyway though guys.

median mulch
#

Just an update though I finally got it working using my method of hooking and pausing game logic to change the value.