Skip to content

Commit

Permalink
Update 2.2.0
Browse files Browse the repository at this point in the history
- Added Black Clover
  • Loading branch information
MJx0 committed Jan 2, 2024
1 parent 60faf54 commit 9cc436b
Show file tree
Hide file tree
Showing 7 changed files with 198 additions and 8 deletions.
3 changes: 2 additions & 1 deletion Tweak/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ PESmobile \
XGame \
MKMobile \
UE_game \
UAGame
UAGame \
ProjectVic

#THEOS_DEVICE_IP =
ARCHS = arm64 arm64e
Expand Down
4 changes: 3 additions & 1 deletion Tweak/UE4Dumper.plist
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,13 @@
"com.pubg.imobile",
"com.pubg.krmobile",
"com.vng.pubgmobile",
"com.tencent.tmgp.pubgmhd",
"jp.konami.pesactionmobile",
"com.lilithgames.xgame.ios.global",
"com.wb.MK.Brawler2015",
"com.xd.TLglobal",
"com.proximabeta.mf.uamo"
"com.proximabeta.mf.uamo",
"com.garena.game.bc"
);
};
}
2 changes: 1 addition & 1 deletion Tweak/control
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: com.kitty.ue4dumper
Name: UE4Dumper
Version: 2.1.0
Version: 2.2.0
Architecture: iphoneos-arm
Description: An awesome MobileSubstrate tweak!
Maintainer: CyberCat
Expand Down
6 changes: 3 additions & 3 deletions Tweak/src/Core/Dumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,11 @@ namespace Dumper

if (!Profile::isUsingFNamePool)
{
fmt::print(logfile, "GNames: {:#08x}\n", Profile::GNamesPtr);
fmt::print(logfile, "GNames: [Base + {:#08x}] = {:#08x}\n", Profile::GNamesPtr-Profile::BaseAddress, Profile::GNamesPtr);
}
else
{
fmt::print(logfile, "FNamePool: {:#08x}\n", Profile::NamePoolDataPtr);
fmt::print(logfile, "FNamePool: [Base + {:#08x}] = {:#08x}\n", Profile::NamePoolDataPtr-Profile::BaseAddress, Profile::NamePoolDataPtr);
}
fmt::print(logfile, "Test Dumping First 5 Name Enteries\n");
for (int i = 0; i < 5; i++)
Expand All @@ -123,7 +123,7 @@ namespace Dumper
}
fmt::print(logfile, "==========================\n");

fmt::print(logfile, "ObjObjects: {:#08x}\n", Profile::ObjObjectsPtr);
fmt::print(logfile, "ObjObjects: [Base + {:#08x}] = {:#08x}\n", Profile::ObjObjectsPtr-Profile::BaseAddress, Profile::ObjObjectsPtr);
fmt::print(logfile, "ObjObjects Num: {}\n", Profile::ObjObjects.GetNumElements());
fmt::print(logfile, "ObjObjects Max: {}\n", Profile::ObjObjects.GetMaxElements());
fmt::print(logfile, "==========================\n");
Expand Down
184 changes: 184 additions & 0 deletions Tweak/src/Core/GameProfiles/BlackClover.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
#pragma once

#include "GameProfile.hpp"

// BlackClover M
// UE 4.27

class BlackCloverProfile : public IGameProfile
{
public:
BlackCloverProfile() = default;

std::vector<std::string> GetAppIDs() const override
{
return { "com.garena.game.bc" };
}

MemoryFileInfo GetExecutableInfo() const override
{
return KittyMemory::getMemoryFileInfo("ProjectVic");
}

bool IsUsingFNamePool() const override
{
return true;
}

uintptr_t GetGUObjectArrayPtr() const override
{
std::string ida_pattern = "FF 9F 52 ? ? ? ? ? ? ? 91 ? 03 80 52";
const int step = 3;

auto text_seg = GetExecutableInfo().getSegment("__TEXT");

uintptr_t insn_address = KittyScanner::findIdaPatternFirst(text_seg.start, text_seg.end, ida_pattern);
if (insn_address == 0)
return 0;

insn_address += step;

int64 adrp_pc_rel = 0;
int32 add_imm12 = 0;

const int page_size = 4096;
const uintptr_t page_off = (insn_address & ~(page_size - 1));

uint32 adrp_insn = vm_rpm_ptr<uint32>((void *)(insn_address));
uint32 add_insn = vm_rpm_ptr<uint32>((void *)(insn_address + 4));
if (adrp_insn == 0 || add_insn == 0)
return 0;

if (!KittyArm64::decode_adr_imm(adrp_insn, &adrp_pc_rel) || adrp_pc_rel == 0)
return 0;

add_imm12 = KittyArm64::decode_addsub_imm(add_insn);

return (page_off + adrp_pc_rel + add_imm12);
}

uintptr_t GetNamesPtr() const override
{
std::string ida_pattern = "C8 00 00 37 ? ? ? ? ? ? ? 91 ? ? FF 97";
const int step = 4;

auto text_seg = GetExecutableInfo().getSegment("__TEXT");

uintptr_t insn_address = KittyScanner::findIdaPatternFirst(text_seg.start, text_seg.end, ida_pattern);
if (insn_address == 0)
return 0;

insn_address += step;

int64 adrp_pc_rel = 0;
int32 add_imm12 = 0;

const int page_size = 4096;
const uintptr_t page_off = (insn_address & ~(page_size - 1));

uint32 adrp_insn = vm_rpm_ptr<uint32>((void *)(insn_address));
uint32 add_insn = vm_rpm_ptr<uint32>((void *)(insn_address + 4));
if (adrp_insn == 0 || add_insn == 0)
return 0;

if (!KittyArm64::decode_adr_imm(adrp_insn, &adrp_pc_rel) || adrp_pc_rel == 0)
return 0;

add_imm12 = KittyArm64::decode_addsub_imm(add_insn);

return (page_off + adrp_pc_rel + add_imm12);
}

UE_Offsets *GetOffsets() const override
{
struct
{
uint16 Stride = 2; // alignof(FNameEntry)
uint16 FNamePoolBlocks = 0xD0; // usually ios at 0xD0 and android at 0x40
uint16 FNameMaxSize = 0xff;
struct
{
uint16 Number = 4;
} FName;
struct
{ // not needed in UE4.23+
uint16 Name = 0;
} FNameEntry;
struct
{
uint16 Info = 0; // Offset to Memory filled with info about type and size of string
uint16 WideBit = 0; // Offset to bit which shows if string uses wide characters
uint16 LenBit = 6; // Offset to bit which has lenght of string
uint16 HeaderSize = 2; // Size of FNameEntry header (offset where a string begins)
} FNameEntry23;
struct
{
uint16 ObjObjects = 0x10;
} FUObjectArray;
struct
{
uint16 NumElements = 0x14;
} TUObjectArray;
struct
{
uint16 Size = 0x18;
} FUObjectItem;
struct
{
uint16 ObjectFlags = 0x8;
uint16 InternalIndex = 0xC;
uint16 ClassPrivate = 0x10;
uint16 NamePrivate = 0x18;
uint16 OuterPrivate = 0x20;
} UObject;
struct
{
uint16 Next = 0x28; // sizeof(UObject)
} UField;
struct
{
uint16 SuperStruct = 0x40; // sizeof(UField) + 2 pointers?
uint16 Children = 0x48; // UField*
uint16 ChildProperties = 0x50; // FField*
uint16 PropertiesSize = 0x58;
} UStruct;
struct
{
uint16 Names = 0x40; // usually at sizeof(UField) + sizeof(FString)
} UEnum;
struct
{
uint16 EFunctionFlags = 0xB0; // sizeof(UStruct)
uint16 NumParams = EFunctionFlags + 0x4;
uint16 ParamSize = NumParams + 0x2;
uint16 Func = EFunctionFlags + 0x28; // ue3-ue4, always +0x28 from flags location.
} UFunction;
struct
{
uint16 ClassPrivate = 0x8;
uint16 Next = 0x20;
uint16 NamePrivate = 0x28;
uint16 FlagsPrivate = 0x30;
} FField;
struct
{
uint16 ArrayDim = 0x34; // sizeof(FField)
uint16 ElementSize = 0x38;
uint16 PropertyFlags = 0x40;
uint16 Offset_Internal = 0x4C;
uint16 Size = 0x78; // sizeof(FProperty)
} FProperty;
struct
{ // not needed in UE4.25+
uint16 ArrayDim = 0;
uint16 ElementSize = 0;
uint16 PropertyFlags = 0;
uint16 Offset_Internal = 0;
uint16 Size = 0;
} UProperty;
} static profile;
static_assert(sizeof(profile) == sizeof(UE_Offsets));

return (UE_Offsets *)&profile;
}
};
3 changes: 2 additions & 1 deletion Tweak/src/Core/GameProfiles/PUBGM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ class PUBGMProfile : public IGameProfile
"com.rekoo.pubgm",
"com.pubg.imobile",
"com.pubg.krmobile",
"com.vng.pubgmobile"
"com.vng.pubgmobile",
"com.tencent.tmgp.pubgmhd"
};
}

Expand Down
4 changes: 3 additions & 1 deletion Tweak/src/Tweak.mm
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "Core/GameProfiles/Torchlight.hpp"
#include "Core/GameProfiles/MortalKombat.hpp"
#include "Core/GameProfiles/ArenaBreakout.hpp"
#include "Core/GameProfiles/BlackClover.hpp"


static IGameProfile *UE_Games[] =
Expand All @@ -40,7 +41,8 @@ new PESProfile(),
new DistyleProfile(),
new TorchlightProfile(),
new MortalKombatProfile(),
new ArenaBreakoutProfile()
new ArenaBreakoutProfile(),
new BlackCloverProfile()
};

void dump_thread();
Expand Down

0 comments on commit 9cc436b

Please sign in to comment.