Not a member yet? Why not Sign up today
Create an account  

Themabewertung:
  • 0 Bewertung(en) - 0 im Durchschnitt
  • 1
  • 2
  • 3
  • 4
  • 5
Euro Truck Simulator 2 1.56 fix nodamage

#1
#include <windows.h>
#include <tlhelp32.h>
#include <psapi.h>
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <thread>
#include <chrono>

using u8 = uint8_t;

// --- simple replacement for optional (tiny)
template<typename T>
struct Optional {
    bool has;
    T val;
    Optional(): has(false) {}
    Optional(const T& v): has(true), val(v) {}
};

// get PID by process name (wide)
DWORD getProcessIdByName(const std::wstring& procName) {
    PROCESSENTRY32W pe{ sizeof(pe) };
    HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (snap == INVALID_HANDLE_VALUE) return 0;
    if (Process32FirstW(snap, &pe)) {
        do {
            if (procName == pe.szExeFile) {
                CloseHandle(snap);
                return pe.th32ProcessID;
            }
        } while (Process32NextW(snap, &pe));
    }
    CloseHandle(snap);
    return 0;
}

Optional<MODULEENTRY32W> getModuleByName(DWORD pid, const std::wstring& moduleName) {
    MODULEENTRY32W me{ sizeof(me) };
    HANDLE snap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, pid);
    if (snap == INVALID_HANDLE_VALUE) return Optional<MODULEENTRY32W>();
    if (Module32FirstW(snap, &me)) {
        do {
            if (moduleName == me.szModule) {
                CloseHandle(snap);
                return Optional<MODULEENTRY32W>(me);
            }
        } while (Module32NextW(snap, &me));
    }
    CloseHandle(snap);
    return Optional<MODULEENTRY32W>();
}

// parse pattern like "40 55 56 57 48 83 EC 70" supporting "??"
bool parsePattern(const std::string& s, std::vector<u8>& bytes, std::string& mask) {
    bytes.clear();
    mask.clear();
    std::istringstream iss(s);
    std::string token;
    while (iss >> token) {
        if (token == "??" || token == "?") {
            bytes.push_back(0);
            mask.push_back('?');
        } else {
            if (token.size() != 2) return false;
            unsigned int val;
            std::istringstream hex(token);
            hex >> std::hex >> val;
            if (hex.fail()) return false;
            bytes.push_back((u8)val);
            mask.push_back('x');
        }
    }
    return true;
}

uintptr_t scanPattern(const u8* data, size_t dataSize, const std::vector<u8>& pat, const std::string& mask, uintptr_t baseAddr) {
    size_t patLen = pat.size();
    if (patLen == 0 || dataSize < patLen) return 0;
    for (size_t i = 0; i <= dataSize - patLen; ++i) {
        bool ok = true;
        for (size_t j = 0; j < patLen; ++j) {
            if (mask[j] == 'x' && data[i + j] != pat[j]) { ok = false; break; }
        }
        if (ok) return baseAddr + i;
    }
    return 0;
}

bool readRemoteMemory(HANDLE hProc, uintptr_t addr, std::vector<u8>& out, SIZE_T size) {
    out.resize(size);
    SIZE_T read = 0;
    if (!ReadProcessMemory(hProc, (LPCVOID)addr, out.data(), size, &read) || read != size) {
        return false;
    }
    return true;
}

bool writeRemoteMemory(HANDLE hProc, uintptr_t addr, const std::vector<u8>& data) {
    SIZE_T written = 0;
    DWORD old = 0;
    if (!VirtualProtectEx(hProc, (LPVOID)addr, data.size(), PAGE_EXECUTE_READWRITE, &old)) {
        std::cerr << "VirtualProtectEx failed: " << GetLastError() << "\n";
        return false;
    }
    if (!WriteProcessMemory(hProc, (LPVOID)addr, data.data(), data.size(), &written) || written != data.size()) {
        std::cerr << "WriteProcessMemory failed: " << GetLastError() << "\n";
        VirtualProtectEx(hProc, (LPVOID)addr, data.size(), old, &old);
        return false;
    }
    VirtualProtectEx(hProc, (LPVOID)addr, data.size(), old, &old);
    return true;
}

// helper: convert wide string to utf8 (avoids wstring_convert)
std::string wideToUtf8(const std::wstring& w) {
    if (w.empty()) return {};
    int sizeNeeded = WideCharToMultiByte(CP_UTF8, 0, w.data(), (int)w.size(), nullptr, 0, nullptr, nullptr);
    std::string strTo(sizeNeeded, 0);
    WideCharToMultiByte(CP_UTF8, 0, w.data(), (int)w.size(), &strTo[0], sizeNeeded, nullptr, nullptr);
    return strTo;
}

int main() {
    std::cout << "ETS2 Patcher - aplica/restaura patches (singleplayer only)\n";
    std::cout << "Procurando eurotrucks2.exe e aplicando patches...\n\n";

    const std::wstring targetProc = L"eurotrucks2.exe";
    const std::wstring moduleName = L"eurotrucks2.exe";

    // patterns (originais + trailer)
    const std::string pat1_str = "40 55 56 57 48 83 EC 70 48 8B B1 48 01 00 00 0F 57 E4"; // NoWearTruck
    const std::string pat2_str = "48 83 EC 18 4C 8B 81 48 01 00 00";                        // NoDamageTruck
    const std::string pat3_str = "40 55 41 56 41 57 48 81 EC 80 00 00 00 48 8B A9 48 01 00 00"; // NoTrailerWear
    const std::string pat4_str = "48 8B 81 48 01 00 00 0F 57 ED";                              // NoTrailerDamage

    std::vector<u8> pat1, pat2, pat3, pat4;
    std::string mask1, mask2, mask3, mask4;
    if (!parsePattern(pat1_str, pat1, mask1) || !parsePattern(pat2_str, pat2, mask2)
        || !parsePattern(pat3_str, pat3, mask3) || !parsePattern(pat4_str, pat4, mask4)) {
        std::cerr << "Erro ao parsear pattern\n";
        return 1;
    }

    DWORD pid = 0;
    std::cout << "Procurando processo '" << wideToUtf8(targetProc) << "'...\n";
    for (int attempts = 0; attempts < 10 && pid == 0; ++attempts) {
        pid = getProcessIdByName(targetProc);
        if (pid == 0) {
            std::cout << "Processo não encontrado. Tentando novamente em 1s...\n";
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
    }
    if (pid == 0) {
        std::cerr << "Processo não encontrado. Execute o Euro Truck Simulator 2 primeiro.\n";
        return 1;
    }
    std::cout << "PID: " << pid << "\n";

    auto modOpt = getModuleByName(pid, moduleName);
    if (!modOpt.has) {
        std::cerr << "Módulo " << wideToUtf8(moduleName) << " não encontrado no processo.\n";
        return 1;
    }
    MODULEENTRY32W me = modOpt.val;
    uintptr_t base = (uintptr_t)me.modBaseAddr;
    SIZE_T modSize = me.modBaseSize;

    std::cout << "Module base: 0x" << std::hex << base << " size: 0x" << modSize << std::dec << "\n";

    HANDLE hProc = OpenProcess(PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION, FALSE, pid);
    if (!hProc) {
        std::cerr << "OpenProcess falhou: " << GetLastError() << "\n";
        return 1;
    }

    // read module
    std::vector<u8> moduleData;
    moduleData.resize(modSize);
    SIZE_T actuallyRead = 0;
    if (!ReadProcessMemory(hProc, (LPCVOID)base, moduleData.data(), modSize, &actuallyRead) || actuallyRead != modSize) {
        std::cerr << "Leitura do modulo falhou: " << GetLastError() << "\n";
        CloseHandle(hProc);
        return 1;
    }

    uintptr_t addr1 = scanPattern(moduleData.data(), moduleData.size(), pat1, mask1, base);
    uintptr_t addr2 = scanPattern(moduleData.data(), moduleData.size(), pat2, mask2, base);
    uintptr_t addr3 = scanPattern(moduleData.data(), moduleData.size(), pat3, mask3, base);
    uintptr_t addr4 = scanPattern(moduleData.data(), moduleData.size(), pat4, mask4, base);

    if (!addr1) std::cout << "Pattern 1 (NoWearTruck) não encontrado.\n"; else std::cout << "Pattern 1 encontrado em 0x" << std::hex << addr1 << std::dec << "\n";
    if (!addr2) std::cout << "Pattern 2 (NoDamageTruck) não encontrado.\n"; else std::cout << "Pattern 2 encontrado em 0x" << std::hex << addr2 << std::dec << "\n";
    if (!addr3) std::cout << "Pattern 3 (NoTrailerWear) não encontrado.\n"; else std::cout << "Pattern 3 encontrado em 0x" << std::hex << addr3 << std::dec << "\n";
    if (!addr4) std::cout << "Pattern 4 (NoTrailerDamage) não encontrado.\n"; else std::cout << "Pattern 4 encontrado em 0x" << std::hex << addr4 << std::dec << "\n";

    struct Patch {
        uintptr_t addr;
        std::vector<u8> original;
        std::vector<u8> patchBytes;
        std::string desc;
    };
    std::vector<Patch> patches;

    auto preparePatch = [&](uintptr_t addr, const std::vector<u8>& pat, const std::string& desc) -> bool {
        if (!addr) return false;
        Patch p;
        p.addr = addr;
        size_t len = pat.size();
        if (!readRemoteMemory(hProc, addr, p.original, len)) {
            std::cerr << "Erro ao ler bytes originais (" << desc << ")\n";
            return false;
        }
        p.patchBytes.assign(len, 0xC3); // 0xC3 = ret
        p.desc = desc;
        patches.push_back(std::move(p));
        return true;
    };

    bool anyPrepared = false;
    anyPrepared |= preparePatch(addr1, pat1, "NoWearTruck");
    anyPrepared |= preparePatch(addr2, pat2, "NoDamageTruck");
    anyPrepared |= preparePatch(addr3, pat3, "NoTrailerWear");
    anyPrepared |= preparePatch(addr4, pat4, "NoTrailerDamage");

    if (!anyPrepared) {
        std::cerr << "Nenhum pattern foi localizado/preparado. Saindo.\n";
        CloseHandle(hProc);
        return 1;
    }

    // apply patches
    bool okAll = true;
    for (auto &p : patches) {
        std::cout << "Aplicando patch (" << p.desc << ") em 0x" << std::hex << p.addr << std::dec << " (len=" << p.patchBytes.size() << ")\n";
        if (!writeRemoteMemory(hProc, p.addr, p.patchBytes)) {
            std::cerr << "Falha ao aplicar patch (" << p.desc << ") em 0x" << std::hex << p.addr << std::dec << "\n";
            okAll = false;
        } else {
            std::cout << "Patch aplicado: " << p.desc << "\n";
        }
    }

    if (!okAll) {
        std::cerr << "Alguns patches falharam. Tente executar como Administrador.\n";
    } else {
        std::cout << "Todos patches aplicados com sucesso (se localizados).\n";
    }

    std::cout << "\nPressione Enter para restaurar os bytes originais e sair...\n";
    std::cin.get();

    for (auto &p : patches) {
        std::cout << "Restaurando (" << p.desc << ") em 0x" << std::hex << p.addr << std::dec << " ... ";
        if (!writeRemoteMemory(hProc, p.addr, p.original)) {
            std::cerr << "Falha ao restaurar (" << p.desc << ") em 0x" << std::hex << p.addr << std::dec << "\n";
        } else {
            std::cout << "OK\n";
        }
    }

    CloseHandle(hProc);
    std::cout << "Concluído. Saindo.\n";
    return 0;
}
Zitieren



Gehe zu:


Benutzer, die gerade dieses Thema anschauen: