I have found two if statements in an application that I want to alter. I've made the two changes and saved the patch file using x32dgb and the application boots up successfully, however; the change doesn't seem to be taking affect nor is it there when I debug the saved patch .exe file.

In short, my patches don't seem to be saved into the new exe!

With my breakpoints saved, I looked the two locations that I need to change, and on initial application load I noticed the addresses contain totally different instructions and not all memory addresses are shown in the left most column.

Here is how x32dgb looked when I successfully loaded the application:

enter image description here

And when application loads:

enter image description here

Any ideas why the patches are not working? Do I need to take a different approach?

  • 1
    It's simple. 1. double click JE 2. edit JE to JNE 3. Press Ctrl+P to pen patch menu 4. Select patch file 5. Enter the new executable name different than the use one 6. press 'Save'. – Biswapriyo Jul 16 '18 at 18:26
  • I've done that, but the program I'm trying to change closes when I run directly. I've also opened up the "patched" version in x32dbg and it contains the original je statements, so it looks like the patch didn't apply. – Noobie3001 Jul 16 '18 at 18:57
  • Could be a TLS callback/dll that does integrity checks on the code and corrupts it when it finds a difference. Does it look like this if you navigate to the address from the system breakpoint (both for patched and unpatched)? – mrexodia Jul 17 '18 at 22:24
  • If I open the patched version in the debugger, the addresses show the original instructions, as if it didn't patch it. It's strange because the exe file's modilfy date updates – Noobie3001 Jul 17 '18 at 23:22
  • And I tried an older version of x32dbg with no success – Noobie3001 Jul 17 '18 at 23:24

At first glance, those two screenshots appear to show completely different instructions within the same memory region, almost as if it's an application that JITs during runtime. (Actually, in the second screen shot, that looks like a region of memory not meant to be disassembled.)

Anyway, you could attempt to patch via a hex editor like HxD. Since you've found the offsets of those instructions, simply open the .exe in HxD (or whatever other hex editor of choice), head to offsets 34EC8 and 34F02, then change each of those bytes according to the appropriate JNE you need for the opcodes you see:

  • 34EC8: Change 84 to 85
  • 34F02: Change 74 to 75

If you don't see your original bytes of 84 and 74 when you go to those offsets, then something's amiss. If you did and you changed them, then save your patched version, run the executable, and see what happens. If you have the same behavior, then it seems highly likely that there's an integrity check of some sort going on. That will require more effort on your behalf to then solve.

| improve this answer | |
  • 1
    I understand that, but I'm thinking this is less about x32dbg and more about the application itself that OP is trying to patch. If he/she has the same behavior happen by attempting to patch via another program, then the issue isn't x32dbg. Finally, from the bottom of OP's post: "Any ideas why the patches are not working? Do I need to take a different approach?" Perhaps, with that approach being to try a different program. – dsasmblr Jul 20 '18 at 2:21
  • 1
    Thanks for the answer. HxD was far better for editing the values. The original values at the addresses were untouched by x32dgb. HxD did edit them correctly, however; the application still closes. Also, the values at the addresses weren't what I expected (84 and 74). I'm currently writing a C++ application to boot it on the fly and hopefully bypass. – Noobie3001 Jul 20 '18 at 7:36
  • 1
    Glad you found it useful. Good luck with the bypass app you're coding! Now, to anyone else who happens by, my other comment was in response to someone who criticized me for not making the answer x32dbg-related. They've since deleted the comment, so now my comment appears out of context. I'm leaving mine intact, though. – dsasmblr Jul 21 '18 at 0:18

Good news! I've built an application in C++ that forces the instruction change until the end of the splash screen. The code is NOT great, but the application is very stubborn and I had to time the loop just right otherwise the application just closes.

Here is the code in case it helps anyone else.

    #include "stdafx.h"
    #include "iostream";
    #include "atlstr.h";
    #include <windows.h>
    #include <TlHelp32.h>
    #include <stdio.h>
    #include <psapi.h>
    using namespace std;

    #pragma comment(lib, "Psapi.lib")

    void TryToCrack(PROCESS_INFORMATION processInfo);

    // 85 c0 0f 84 9e 00 00 00
    // 85 c0 0f 85 9e 00 00 00
    // First offset 34EC7, do 34EC8
    // second offset 34F03
    // 74 2E
    // EB 2E

    int main()
        cout << "Launching Application" << endl;
        PROCESS_INFORMATION processInfo = CreateVProcess();
        cout << "Trying to crack..." << endl;
        return 0;

        LPCTSTR path = L"NameOfAppHere.exe";

        // additional information
        STARTUPINFO si;

        // set the size of the structures
        ZeroMemory(&si, sizeof(si));
        si.cb = sizeof(si);
        ZeroMemory(&pi, sizeof(pi));

            NULL,        // Command line
            NULL,           // Process handle not inheritable
            NULL,           // Thread handle not inheritable
            FALSE,          // Set handle inheritance to FALSE
            0,              // No creation flags
            NULL,           // Use parent's environment block
            NULL,           // Use parent's starting directory 
            &si,            // Pointer to STARTUPINFO structure
            &pi             // Pointer to PROCESS_INFORMATION structure (removed extra parentheses)
        return pi;

    void TryToCrack(PROCESS_INFORMATION processInfo)

        HANDLE targetProcess = OpenProcess(STANDARD_RIGHTS_WRITE, 0, processInfo.dwProcessId);
        void* hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, processInfo.dwProcessId);
        MODULEENTRY32 mod32;
        mod32.dwSize = sizeof(MODULEENTRY32);
        Module32Next(hSnap, &mod32);

        DWORD modHandle = (DWORD)mod32.modBaseAddr;

        unsigned char mem1 = 0x85;
        unsigned char mem2 = 0x75;

        for (int i = 0; i < 100000; i++)
            WriteProcessMemory(processInfo.hProcess, (LPVOID)(modHandle + 0x034EC8), &mem1, 1, NULL);
            WriteProcessMemory(processInfo.hProcess, (LPVOID)(modHandle + 0x034F02), &mem2, 1, NULL);
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.