BepInEx / Il2CppInterop

A tool interoperate between CoreCLR and Il2Cpp at runtime
GNU Lesser General Public License v3.0
195 stars 61 forks source link

Fix OOB read crash in Pass16ScanMethodRefs #83

Open khang06 opened 1 year ago

khang06 commented 1 year ago

I was running into a crash where Iced tried to disassemble past the end of the file, so here's a pretty straightforward fix for it.

Kasuromi commented 1 year ago

What is the game you got the out of bounds exception on? I've been unable to reproduce this on several games.

khang06 commented 1 year ago

I ran into this on Rec Room. IIRC it also required modifying Cpp2IL to make it find CodeRegistration properly, which I did by porting this.

internal ulong FindCodeRegistrationKhangSearch(ulong expectedMetadataRegistration)
{
    // custom search
    // searching .text for the following pattern:
    // lea r8,  [rip+0x????????]
    // lea rdx, [rip+0x????????]
    // lea rcx, [rip+0x????????]
    // jmp [rip+0x????????]
    // or...
    // 4c 8d 05 ?? ?? ?? ??
    // 48 8d 15 ?? ?? ?? ??
    // 48 8d 0d ?? ?? ?? ??
    // e9
    // 22 bytes long

    // functions are always aligned to 16 bytes
    const int patternLength = 22;
    byte[] d = new byte[patternLength];
    ulong address = 0;
    for (int ptr = 0; ptr < _binaryBytes.Length - patternLength; ptr += 0x10)
    {
        Buffer.BlockCopy(_binaryBytes, ptr, d, 0, patternLength);
        if (
            d[0] == 0x4C && d[1] == 0x8D && d[2] == 0x05 &&
            d[7] == 0x48 && d[8] == 0x8D && d[9] == 0x15 &&
            d[14] == 0x48 && d[15] == 0x8D && d[16] == 0x0D &&
            d[21] == 0xE9
        )
        {
            var virtualPtr = _binary.MapRawAddressToVirtual((uint)ptr);
            address = virtualPtr + 21 + BitConverter.ToUInt32(d, 14 + 3);
            var metadataRegistration = virtualPtr + 14 + BitConverter.ToUInt32(d, 7 + 3);
            if (metadataRegistration == expectedMetadataRegistration)
            {
                LibLogger.VerboseNewline($"Found the offsets at 0x{virtualPtr.ToString("X2")}! codeRegistration: 0x{address.ToString("X2")}, metadataRegistration: 0x{metadataRegistration.ToString("X2")}");
                break;
            }
            break;
        }
    }

    var codeReg = LibCpp2IlMain.Binary!.ReadReadableAtVirtualAddress<Il2CppCodeRegistration>(address);

    var fields = typeof(Il2CppCodeRegistration).GetFields();
    var fieldsByName = fields.ToDictionary(f => f.Name);
    var success = ValidateCodeRegistration(codeReg, fieldsByName);

    if (success)
    {
        LibLogger.VerboseNewline("Looks good!");
        return address;
    }

    return 0;
}