it编程 > App开发 > Windows Phone

UE4逆向篇-1_FNamePool

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来修改游戏。

二、gnames

a.什么是gnames

1.gnames 指的是 alignas(fnamepool) static uint8 namepooldata[sizeof(fnamepool)];

2.也就是namepooldata

3.它是一个数组结构。

b.namepooldata/fnamepool

以下是该结构体原型:


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;
};

c.fnameentryallocator

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中存储的其实就是一堆字符串,而字符串中的内容是什么样的呢?

接下来我们开始查找它。

三、查找namepooldata

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:

(0)
打赏 微信扫一扫 微信扫一扫

您想发表意见!!点此发布评论

推荐阅读

UE4 虚幻4快捷键教程

08-01

如何解决wpcap.dll丢失? 电脑wpcap.dll文件破损的修复方法

08-01

Docker下Open WebUI,Ollama的安装实践

08-01

界面控件DevExpress WPF流程图组件,完美复制Visio UI!(二)

08-01

WPF项目中visual studio 2022 解决方案资源管理器不显示图片,并且将图片添加到button控件中不显示

08-01

WPF异常处理详解

08-02

猜你喜欢

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论