记一次UE逆向--三角洲行动
huarui记一次UE逆向–三角洲行动
关于
本文章仅供学习交流,请勿用于非法用途
信息获取
通往罗马的路不止一条。
三角洲行动这个游戏可以说是市面上反作弊部署最为完善的游戏,上到服务器端,下到内存cr3都有严苛的反作弊措施。严密的检测下几乎不可能直接上手调试。如果只会公式化逆向或者喜欢单刷ACE,只能说死路一条
但是哥们有社会工程学
只要我能获取我想要的信息,那我就可以绕过调试阶段,直接写脚本了
Offset
BV1EigWzGEaj
大佬的dll直接注入即可GetOffset(

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| /* Create by ShaHen */ /* QQ:750144893 */ inline static const uint64_t OwningGameInstance = 0x00000000000001B0 inline static const uint64_t LocalPlayers = 0x0000000000000048 inline static const uint64_t PlayerController = 0x0000000000000038 inline static const uint64_t ControlRotation = 0x00000000000003E8 inline static const uint64_t AcknowledgedPawn = 0x0000000000000410 inline static const uint64_t PlayerCameraManager = 0x0000000000000430 inline static const uint64_t CameraCachePrivate = 0x000000000002F300 inline static const uint64_t POV = 0x0000000000000010 inline static const uint64_t RootComponent = 0x0000000000000188 inline static const uint64_t RelativeLocation = 0x000000000000016C inline static const uint64_t RelativeRotation = 0x0000000000000178 inline static const uint64_t Mesh = 0x00000000000003E8 inline static const uint64_t MasterPoseComponent = 0x0000000000000718 inline static const uint64_t PlayerState = 0x00000000000003A0 inline static const uint64_t PlayerNamePrivate = 0x0000000000000488 inline static const uint64_t bFinishGame = 0x00000000000004D8 inline static const uint64_t TeamId = 0x000000000000067C inline static const uint64_t CampID = 0x0000000000000680 inline static const uint64_t LoginInfo = 0x0000000000000690 inline static const uint64_t LoginNumber = 0x0000000000000008 inline static const uint64_t CacheCurWeapon = 0x0000000000001560 inline static const uint64_t WeaponID = 0x0000000000000828 inline static const uint64_t HealthComp = 0x0000000000000F00 inline static const uint64_t HealthSet = 0x0000000000000250 inline static const uint64_t Health = 0x0000000000000048 inline static const uint64_t MaxHealth = 0x0000000000000068 inline static const uint64_t CharacterEquipComponentCache = 0x0000000000001F50 inline static const uint64_t EquipmentInfoArray = 0x00000000000001E0 inline static const uint64_t PoolChosenName = 0x0000000000002620 inline static const uint64_t RepItemArray = 0x00000000000017C8 inline static const uint64_t Items = 0x0000000000000108 inline static const uint64_t MarkingItemType = 0x000000000000072A inline static const uint64_t bLooted = 0x0000000000001E60 inline static const uint64_t bHasOpened = 0x0000000000001C54 inline static const uint64_t TipsText = 0x0000000000001D00 inline static const uint64_t Password = 0x0000000000000D44 inline static const uint64_t PwdSum = 0x0000000000000DA0 inline static const uint64_t GWorld = 0x000000015264C588 inline static const uint64_t Gname = 0x0000000152F50400 inline static const uint64_t Matrix = 0x000000015263C520 inline static const uint64_t Object = 0x0000000152F69D88
|
值得一提的是,三角洲行动的基址固定为5368709120 (0x140000000)
以Gname举例,实际上它的偏移是0x0000000152F50400 - 0x0000000140000000 = 0x12F50400
我在测试的时候被这个问题搞晕乎了,我一直以为是我的偏移算错了,但是实际上不是。
在cpp中可以直接简化这一步骤,即用inline static const uint64_t Gname = 0x0000000152F50400直接表示Gname。这个现象令我十分困惑,我毕竟逆向水平不高如果有大佬能为我解释请联系我。
gname算法
三角洲的gname算法在b站也是烂大街了,这里不做过多叙述,直接上算法
E:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| .版本 2
ChunkOffset = Uchar (右移 (key, 18)) NameOffset = 位与 (key, 262143) GNameTable = g_模块 + #GetName
NamePoolChunk = 读长整数 (GNameTable + ChunkOffset × 8 + 8) + 到整数 (2 × NameOffset)
NameEntry = 读短整数 (NamePoolChunk) NameLength = 到整数 (右移 (NameEntry, 6))
.如果真 (NameLength > 256 或 NameLength ≤ 0)
返回 (“NULL”) .如果真结束 EncText = 驱动.读写_读字节集 (PID, NamePoolChunk + 2, 1024)
.如果 (位与 (NameEntry, 1) ≠ 0) ' 调试输出 (“宽字符”) .否则 .如果真 (EncText [1] ≠ 0) Index = 0
.循环判断首 ()
EncText [Index + 1] = 位异或 (EncText [Index + 1], GetXorKey (NameLength)) Index = Index + 1 .循环判断尾 (Index < NameLength) EncText [NameLength + 1] = 0 .如果真结束
返回 (到文本 (EncText))
|
Cpp:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| #include <windows.h> #include <cstdint> #include <string> #include <vector>
uintptr_t g_module; DWORD PID;
std::vector<BYTE> ReadMemory(uintptr_t address, size_t size) {
std::vector<BYTE> buffer(size);
return buffer; }
uint64_t ReadUInt64(uintptr_t address) { auto data = ReadMemory(address, 8); return *reinterpret_cast<uint64_t*>(data.data()); }
uint16_t ReadUInt16(uintptr_t address) { auto data = ReadMemory(address, 2); return *reinterpret_cast<uint16_t*>(data.data()); }
BYTE GetXorKey(int nameLength) {
return 0; }
std::string GetNameFromKey(uint64_t key) { BYTE ChunkOffset = static_cast<BYTE>(key >> 18);
uint32_t NameOffset = key & 262143; const uintptr_t GetNameOffset = 0x12345678; uintptr_t GNameTable = g_module + GetNameOffset;
uintptr_t NamePoolChunk = ReadUInt64(GNameTable + ChunkOffset * 8 + 8) + static_cast<uintptr_t>(2 * NameOffset);
uint16_t NameEntry = ReadUInt16(NamePoolChunk);
int NameLength = static_cast<int>(NameEntry >> 6); if (NameLength > 256 || NameLength <= 0) { return "NULL"; }
std::vector<BYTE> EncText = ReadMemory(NamePoolChunk + 2, 1024); if ((NameEntry & 1) != 0) {
return "WIDE_CHAR_NOT_IMPLEMENTED"; } else { if (EncText.size() > 0 && EncText[0] != 0) { int Index = 0; do { EncText[Index] = EncText[Index] ^ GetXorKey(NameLength); Index++; } while (Index < NameLength); EncText[NameLength] = 0; return std::string(reinterpret_cast<char*>(EncText.data())); } } return "NULL"; }
|
绘制过滤
gname对象
这里也没什么好讲的。如果是小兵和真人,成员对象名字都有Character关键词,直接过滤即可
读取坐标
这里的坐标和正常的ue有一些不同,偏移大概是读RootComponent 的值+0x220
其他相对偏移
OwningGameInstance=0x1B0
LocalPlayers=0x50
ULevels = =0x108
其他譬如世界转屏幕,矩阵这里不多叙述,都是直接用上一篇文章远光84的代码
效果

线程这块可以优化一下,多次测试表明三个线程:绘制,刷新gname,刷新矩阵
其中刷新gname设置延时为600000
如上安排效果好,不会出现拖框的情况
后记
84那篇文章里我尝试在进程保护加载器dump内存成功了,我突发奇想能不能用这个方法dump三角洲的内存
然后不出意料的失败了,dump出来180mb的内存,ida分析了一个晚上,字符串都有700万个,很明显,这些都是被混淆的数据。
我在查阅资料的时候发现,至少在2025年3月26日的时候,三角洲行动这个游戏是可以正常dump内存而不会报错的。说明这几个赛季里三角洲行动做了很多反外挂的举措。
后记的后记
过了一天之后我重新上号发现被封了十年。。。好在调试的时候我用的云电脑和小号,也算是免于机器码封禁了。
这篇文章完成于2025/8/20,然而在8/21号这天三角洲做了一个小更新,把ulevel加密了,所以本文的源码和方法应该不适用了(笑)
最后还是希望国产游戏的反作弊能越做越好吧
(本文完)