225人参与 • 2024-08-01 • Windows Phone
1.ue4.23以下与4.23以上版本是有所区别的,笔者所使用的ue源码为4.27。
2.ue4为开源的github项目,但你想下载其源码需要将epic账号与github账号绑定,其次会收到一封邮件以加入github组织。
1.由于c++没有反射,而ue自行实现的反射导致其暴露出了非常多的接口,所以我们可以利用这些暴露出来的接口。
2.gnames是unicode字符串的数组。
3.gobject是类指针的数组。
拥有gobjects以后,可以访问游戏中大部分对象,而gname则对应其对象的名称?
拥有这些信息以后,可以生成出一个sdk来修改游戏。
1.gnames 指的是 alignas(fnamepool) static uint8 namepooldata[sizeof(fnamepool)];
2.也就是namepooldata。
3.它是一个数组结构。
以下是该结构体原型:
class fnamepool
{
public:
fnamepool();
void reserve(uint32 numblocks, uint32 numentries);
fnameentryid store(fnamestringview view);
fnameentryid find(fnamestringview view) const;
fnameentryid find(ename ename) const;
const ename* findename(fnameentryid id) const;
/** @pre !!handle */
fnameentry& resolve(fnameentryhandle handle) const { return entries.resolve(handle); }
bool isvalid(fnameentryhandle handle) const;
fnameentryid storevalue(const fnamecomparisonvalue& value);
void storebatch(uint32 shardidx, tarrayview<fnamecomparisonload> batch) { comparisonshards[shardidx].insertbatch(batch); }
#if with_case_preserving_name
fnameentryid storevalue(const fnamedisplayvalue& value, bool breusecomparisonid);
void storebatch(uint32 shardidx, tarrayview<fnamedisplayload> batch) { displayshards[shardidx].insertbatch(batch); }
bool reusecomparisonentry(bool baddedcomparisonentry, const fnamedisplayvalue& displayvalue);
#endif
/// stats and debug related functions ///
uint32 numentries() const;
uint32 numansientries() const;
uint32 numwideentries() const;
uint32 numblocks() const { return entries.numblocks(); }
uint32 numslots() const;
void logstats(foutputdevice& ar) const;
uint8** getblocksfordebugvisualizer() { return entries.getblocksfordebugvisualizer(); }
tarray<const fnameentry*> debugdump() const;
private:
enum { maxenames = 512 };
fnameentryallocator entries;
#if with_case_preserving_name
fnamepoolshard<enamecase::casesensitive> displayshards[fnamepoolshards];
#endif
fnamepoolshard<enamecase::ignorecase> comparisonshards[fnamepoolshards];
// put constant lookup on separate cache line to avoid it being constantly invalidated by insertion
alignas(platform_cache_line_size) fnameentryid enametoentry[name_maxhardcodednameindex] = {};
uint32 largestenameunstableid;
tmap<fnameentryid, ename, tinlinesetallocator<maxenames>> entrytoename;
};
1.fnamepool结构体之中的大部分我们都可以忽略。
2.更需要重点关注其中的:fnameentryallocator entries;
class fnamepool
{
private:
fnameentryallocator entries;
};
需要注意 fnameentryallocator 并不是一个指针,而是完整的结构体。
同样的,该结构体中的大部分都可以忽略,重点关注以下内容:
static constexpr uint32 fnamemaxblocks = 1 << fnamemaxblockbits;
class fnameentryallocator
{
mutable frwlock lock; //0x0000
uint32 currentblock = 0; //0x0008
uint32 currentbytecursor = 0; //0x000c
uint8* blocks[fnamemaxblocks] = {}; //0x0010
};
fname中存储的其实就是一堆字符串,而字符串中的内容是什么样的呢?
接下来我们开始查找它。
1.想要查找namepooldata其实非常简单,只需要打开游戏并使用ce附加游戏。
2.搜索字符串:multicastdelegateproperty,注意不要勾选utf-16(宽字符)。
3.搜索字符串后浏览内存相关区域,快捷键ctrl+b,并向上翻:
看到内存区域类似.none.....byteproperty.....intproperty即可。
4.此时从none往前推6个字节,即:......none,并将该地址记录下来:
记录下该地址,回到ce中进行新的扫描,勾选hex扫描8字节:
如果扫描不到可以尝试调整ce的可写选项
5.现在,只需要使用扫描出的地址减去 blocks(uint8* blocks[fnamemaxblocks] = {};) 的偏移0x10,即可得出fnamepool,使用reclass验证一下:
至此,查找namepooldata的工作就完成了,通过修改unrealdumper 的源码即可导出names:
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论