TheNaeem / UnrealMappingsDumper

A dumper that generates mappings (.usmap) files for datamining Unreal Engine games.
MIT License
137 stars 18 forks source link

Crash at while(props) #33

Closed UnrealKaraulov closed 3 months ago

UnrealKaraulov commented 3 months ago
auto Props = Struct->ChildProperties();

while (Props)
{
                NameMap.insert_or_assign(Props->GetFName(), 0);
                Props = static_cast<FProperty*>(Props->GetNext());
}

Props invalid address at reading UScriptStruct::StaticClass()

UnrealKaraulov commented 3 months ago

@TheNaeem

Game: Смута Download: https://rutracker.org/forum/viewtopic.php?t=6509904 Aes Key: 0xA6300C9B4E4A5C53F5273B08A6D83BE29BFFA2B693CA77E006B5746485F7E0FF Engine UE 5.3

UnrealKaraulov commented 3 months ago

I added error bypass, but got invalid mapping file. (some data missing)

    UE_LOG("2");
    WritePropertyWrapper = WriteProperty;

    ObjObjects::ForEach([&](UObject*& Object)
        {
            if (Object->Class() == UClass::StaticClass() ||
            Object->Class() == UScriptStruct::StaticClass())
            {
                auto tmp1 = Structs;
                auto tmp2 = NameMap;

                try
                {
                    auto Struct = static_cast<UStruct*>(Object);

                    Structs.push_back(Struct);

                    NameMap.insert_or_assign(Struct->GetFName(), 0);

                    if (Struct->Super() && !NameMap.contains(Struct->Super()->GetFName()))
                        NameMap.insert_or_assign(Struct->Super()->GetFName(), 0);

                    auto Props = Struct->ChildProperties();

                    while (Props)
                    {
                        NameMap.insert_or_assign(Props->GetFName(), 0);
                        Props = static_cast<FProperty*>(Props->GetNext());
                    }
                }
                catch (...)
                {
                    Structs = tmp1;
                    NameMap = tmp2;
                }
            }
            else if (Object->Class() == UEnum::StaticClass())
            {
                auto tmp1 = Enums;
                auto tmp2 = NameMap;

                try
                {
                    auto Enum = static_cast<UEnum*>(Object);
                    Enums.push_back(Enum);

                    NameMap.insert_or_assign(Enum->GetFName(), 0);

                    auto& EnumNames = Enum->Names();

                    for (auto i = 0; i < EnumNames.Num(); i++)
                    {
                        NameMap.insert_or_assign(EnumNames[i].Key.GetNumber(), 0);
                    }
                }
                catch (...)
                {
                    Enums = tmp1;
                    NameMap = tmp2;
                }
            }
        });

    UE_LOG("3");
    Buffer.Write<int>(NameMap.size());

    int CurrentNameIndex = 0;

    for (auto&& N : NameMap)
    {
        auto buf = Buffer.Size();
        try
        {
            NameMap[N.first] = CurrentNameIndex;

            auto Name = N.first.ToString();
            std::string_view NameView = Name;

            auto Find = Name.find("::");
            if (Find != std::string::npos)
            {
                NameView = NameView.substr(Find + 2);
            }

            if (NameView.length() <= 0xFF)
            {
                Buffer.Write<uint8_t>(NameView.length());
                Buffer.WriteString(NameView);
            }
            CurrentNameIndex++;
        }
        catch (...)
        {
            Buffer.Seek(buf, SEEK_SET);
        }
    }

    UE_LOG("4");
    Buffer.Write<uint32_t>(Enums.size());

    for (auto Enum : Enums)
    {
        auto buf = Buffer.Size();
        try
        {
            Buffer.Write(NameMap[Enum->GetFName()]);
            auto& EnumNames = Enum->Names();
            Buffer.Write<uint8_t>(EnumNames.Num());

            for (size_t i = 0; i < EnumNames.Num(); i++)
            {
                Buffer.Write<int>(NameMap[EnumNames[i].Key]);
            }
        }
        catch (...)
        {
            Buffer.Seek(buf, SEEK_SET);
        }
    }

    UE_LOG("5");
    Buffer.Write<uint32_t>(Structs.size());

    for (auto Struct : Structs)
    {
        auto buf = Buffer.Size();
        try
        {
            Buffer.Write(NameMap[Struct->GetFName()]);
            Buffer.Write<int32_t>(Struct->Super() ? NameMap[Struct->Super()->GetFName()] : 0xffffffff);

            std::vector<FPropertyData> Properties;

            auto Props = Struct->ChildProperties();
            uint16_t PropCount = 0;
            uint16_t SerializablePropCount = 0;

            while (Props)
            {
                FPropertyData Data(Props, PropCount);

                Properties.push_back(Data);
                Props = static_cast<FProperty*>(Props->GetNext());

                PropCount += Data.ArrayDim;
                SerializablePropCount++;
            }

            Buffer.Write(PropCount);
            Buffer.Write(SerializablePropCount);

            for (auto P : Properties)
            {
                Buffer.Write<uint16_t>(P.Index);
                Buffer.Write(P.ArrayDim);
                Buffer.Write(NameMap[P.Name]);

                WriteProperty(P.Prop, P.PropertyType);
            }
        }
        catch (...)
        {
            Buffer.Seek(buf, SEEK_SET);
        }
    }

    UE_LOG("6");
    std::vector<uint8_t> UsmapData;

    switch (CompressionMethod)
    {
        case ECompressionMethod::Oodle:
        {
            try
            {
                UsmapData = Oodle::Compress(Buffer.GetBuffer());
            }
            catch (...)
            {

            }
            break;
        }
        default:
        {
            try
            {
                std::string UncompressedStream = Buffer.GetBuffer().str();
                UsmapData.resize(UncompressedStream.size());
                memcpy(UsmapData.data(), UncompressedStream.data(), UsmapData.size());
            }

            catch (...)
            {

            }
        }
    }

    UE_LOG("7");
UnrealKaraulov commented 3 months ago

MappingX.zip

How to check is valid data or not?

Wanja01YT commented 3 months ago

Can you explain how you managed to fix the issues that made you close this as completed?

UnrealKaraulov commented 3 months ago

@Wanja01YT yes I just use another dumper : https://github.com/UE4SS-RE/RE-UE4SS