- Content
开启日志
0x4068E0
函数是一个空函数,开发阶段应该是输出调试日志的,发布阶段函数体是空的。而它的后续有足够的空间,可以设置一个hook。
004068E0 $ C3 retn
004068E1 90 nop
004068E2 90 nop
004068E3 90 nop
004068E4 90 nop
具体代码如下:
// 打印错误信息
void printLastError(DWORD error, const char* tag = NULL) {
char buffer[1024] = {};
sprintf_s(buffer, sizeof(buffer), "Tag: %s, Error Code: %lu", tag, error);
OutputDebugStringA(buffer);
}
#pragma optimize("", off)
BOOL installHook(LPVOID addr, DWORD newFunc) {
byte buff[5];
DWORD* offset = (DWORD*) & buff[1];
DWORD dwWrittenSize = 0;
DWORD dwOldProtect = 0;
buff[0] = 0xE9; // jmp
*offset = newFunc - (DWORD)addr - 5;
if (VirtualProtect(addr, 5u, PAGE_EXECUTE_READWRITE, &dwOldProtect)) {
WriteProcessMemory(GetCurrentProcess(), addr, &buff, 5u, &dwWrittenSize);
if (!VirtualProtect(addr, 5u, dwOldProtect, &dwOldProtect)) {
printLastError(GetLastError(), "Failed 2!");
}
} else {
printLastError(GetLastError(), "Failed 1!");
}
return true;
}
void __cdecl log(const char* Format, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9) {
if (!strstr(Format, "Theme")) {
char buff1[1024] = {};
char buff2[1024] = {};
DWORD* pArgs = (DWORD*)((DWORD)&Format - 4); //&p是参数栈的地址,&p-4是返回地址
sprintf_s(buff1, Format, a1, a2, a3, a4, a5, a6, a7, a8, a9);
sprintf_s(buff2, "[Ra2] %08X %s", pArgs[0], buff1);
OutputDebugStringA(buff2);
}
}
byte backupCode[5] = {};
bool TrainerFunctions::OpenLog() {
OutputDebugStringA("[Ra2] OpenLog");
void* oldFunc = (byte*)GetModuleHandleA(0) + 0x68E0; // 0x4068E0 是一个空函数,就一个retn
memcpy(&backupCode, oldFunc, 5u);
return installHook(oldFunc, (DWORD)&log);
}
#pragma optimize("", on)
运行并hook后,输出的日志信息:
[Ra2] OpenLog
[Ra2] 00000000 sendto 1.0.0.0 ; 0
[Ra2] 00000000 Frame 272, Receive packet uncompressed into 0 commmands
[Ra2] 00000000 Theme::AI(Next song = 0)
[Ra2] 00000000 Theme::Stop(0)
[Ra2] 00000000 Theme::PlaySong(0) - Repeating
[Ra2] 00000000 Theme::AI(Next song = 0)
[Ra2] 00000000 Theme::Stop(0)
[Ra2] 00000000 Theme::PlaySong(0) - Repeating
[Ra2] 00000000 Crate at 96,53 contains 'reveal'
[Ra2] 00000000 Crate at 71,96 contains money
[Ra2] 00000000 Crate at 139,153 contains firepower
[Ra2] 00000000 Crate at 124,76 contains a unit
[Ra2] 00000000 Crate at 96,53 contains speed
[Ra2] 00000000 Crate at 84,167 contains veterancy(TM)
[Ra2] 00000000 Response time = 2
[Ra2] 00000000 IPX Manager: RetryDelta = 12
[Ra2] 00000000 MaxAhead is 24
[Ra2] 00000000 Send_Packets - created packet with 1 commands on frame 384
[Ra2] 00000000 NumSendAck = 4
[Ra2] 00000000 Received ACK for packet 4
[Ra2] 00000000 Sending ACK for packet 4 to be forwarded to 00
后续可以结合日志进行分析,比较容易聚焦,提高效率。
通信数据
人机对战不会产生通信数据,人人对战才会有通信数据。
结合日志分析:
sendto 1.0.0.0 ; 0
Send_Packets - added total of 1 commands on frame 384
Frame 384, my sent = 5
Frame 384, Receive packet uncompressed into 1 commmands
Received ACK for packet 4
Sending ACK for packet 4 to be forwarded to 00
Send_Packets - created packet with 1 commands on frame 384
Send_Packets - added total of 1 commands on frame 384
找到:
007B3D4F . 68 D0E48400 push 0084E4D0 ; sendto %d.%d.%d.%d ; %d\n
007B3D54 . E8 872BC5FF call 004068E0
007B3D59 . 8B43 10 mov eax, dword ptr [ebx+10]
007B3D5C . 8B7424 50 mov esi, dword ptr [esp+50]
007B3D60 . 83C4 18 add esp, 18
007B3D63 . 8D5424 20 lea edx, dword ptr [esp+20]
007B3D67 . 83C0 04 add eax, 4
007B3D6A . 8D4B 1C lea ecx, dword ptr [ebx+1C]
007B3D6D . 6A 10 push 10 ; /ToLength = 10 (16.)
007B3D6F . 52 push edx ; |pTo
007B3D70 . 6A 00 push 0 ; |Flags = 0
007B3D72 . 50 push eax ; |DataSize
007B3D73 . 51 push ecx ; |Data
007B3D74 . 56 push esi ; |Socket
007B3D75 . E8 364C0100 call <jmp.&WSOCK32.#20> ; \sendto
地图全开
00481F9D |> \0FBF56 26 movsx edx, word ptr [esi+26]
00481FA1 |. 0FBF46 24 movsx eax, word ptr [esi+24]
00481FA5 |. 52 push edx
00481FA6 |. 50 push eax
00481FA7 |. 68 10D08100 push 0081D010 ; ASCII "Crate at %d,%d contains 'reveal'",LF
00481FAC |. E8 2F49F8FF call 004068E0 ; 空函数
00481FB1 |. 8B4D 08 mov ecx, dword ptr [ebp+8]
00481FB4 |. 83C4 0C add esp, 0C
00481FB7 |. 8B91 1C020000 mov edx, dword ptr [ecx+21C]
00481FBD |. B9 E8F78700 mov ecx, 0087F7E8
00481FC2 |. 52 push edx
00481FC3 |. E8 C85D0F00 call 00577D90 ; 地图全开
2024年1月3日:已验证可行性。
// 全地图内联代码
void Map_Assemble() {
_asm {
pushad
mov eax,0x00A83D4C
mov edx,[eax]
mov ecx,0x0087F7E8
push edx
mov eax,0x00577D90
call eax
popad
}
}
雷达开启
以下汇编仅作过程分析的参考:
00508DF0 /$ C681 79570000>mov byte ptr [ecx+5779], 0
00508DF7 |. A1 4C3DA800 mov eax, dword ptr [A83D4C]
00508DFC |. 83EC 0C sub esp, 0C
00508DFF |. 3BC8 cmp ecx, eax
00508E01 |. 0F85 4D010000 jnz 00508F54
00508E07 |. 8B81 B8020000 mov eax, dword ptr [ecx+2B8]
00508E0D |. 53 push ebx
00508E0E |. 55 push ebp
00508E0F |. 56 push esi
00508E10 |. 8BB1 B0020000 mov esi, dword ptr [ecx+2B0]
00508E16 |. 57 push edi
00508E17 |. 83FE FF cmp esi, -1
00508E1A |. C64424 10 00 mov byte ptr [esp+10], 0
00508E1F |. 74 0E je short 00508E2F
00508E21 |. 8B15 84EDA800 mov edx, dword ptr [A8ED84]
00508E27 |. 2BD6 sub edx, esi
00508E29 |. 3BD0 cmp edx, eax
00508E2B |. 7D 0A jge short 00508E37
00508E2D |. 2BC2 sub eax, edx
00508E2F |> 85C0 test eax, eax
00508E31 |. 0F85 F8000000 jnz 00508F2F
00508E37 |> A1 30B2A800 mov eax, dword ptr [A8B230]
00508E3C |. 8A90 A4340000 mov dl, byte ptr [eax+34A4]
00508E42 |. 84D2 test dl, dl ; 雷达开启判断
00508E44 |. 0F85 E0000000 jnz 00508F2A
2024年1月4日:已验证可行性,一键开启全图和雷达,无须修改指令。
//全地图内联代码
#pragma pack(1)
void Map_Assemble() {
_asm {
pushad
mov eax, 0x00A83D4C
mov edx, [eax]
mov ecx, 0x0087F7E8
push edx
mov eax,0x00577D90
call eax
popad
}
}
// 雷达全开 [[0x00A8B230] + 0x34A4] = 1
void RadarOn_Assemble() {
_asm {
pushad
mov eax, 0x00A8B230
mov eax, [eax]
mov byte ptr [eax + 0x34A4], 0x1
popad
}
}
// 判断游戏是否运行
bool isGameRunning() {
bool isRunning = false;
__try {
_asm {
pushad
mov eax, 0x00A83D4C
mov eax, [eax]
mov eax, 0x0087F7E8
mov eax, [eax]
popad
}
isRunning = true;
} __except (EXCEPTION_EXECUTE_HANDLER) {
isRunning = false;
}
return isRunning;
}
#pragma pack()
调用:
//地图全开
void openAllMap() {
if (isGameRunning()) {
Map_Assemble();
RadarOn_Assemble();
} else {
::Beep(523, 400); // do
}
}
其他:
- 对 00577D90 函数下断点,创建雷达后断下来跟踪。
- 找到地址: 0x00A83D4C 0x0087F7E8 0x00A8B230 0x34A4 之间的关系和来源,最好能从一个地址出发找到其他地址。
科技全开
参考:
科技树参考(优先以这个为准):
Aircraft [1]-ORCA-Intruder-入侵者战机
Aircraft [2]-HORNET-Hornet-大黄蜂
Aircraft [7]-BEAG-Black Eagle-黑鹰战机
Building [0]-GAPOWR-Allied Power Plant-盟军发电厂
Building [1]-GAREFN-Allied Ore Refinery-盟军矿厂
Building [2]-GACNST-Allied Construction Yard-盟军建造场
Building [3]-GAPILE-Allied Barracks-盟军兵营
Building [4]-GASAND-Sandbags-沙墙
Building [5]-GADEPT-Allied Service Depot-盟军维修厂
Building [6]-GATECH-Allied Battle Lab-盟军作战实验室
Building [7]-GAWEAP-Allied War Factory-盟军战车工厂
Building [8]-CALAB-Einstein's Lab-爱因斯坦实验室
Building [9]-NAPOWR-Soviet Tesla Reactor-磁能反应炉
Building [10]-NATECH-Soviet Battle Lab-苏军作战实验室
Building [11]-NAHAND-Soviet Barracks-苏军兵营
Building [12]-GAWALL-Allied Wall-盟军围墙
Building [13]-NARADR-Soviet Radar Tower-苏军雷达
Building [14]-NAWEAP-Soviet War Factory-苏军战车工厂
Building [15]-NAREFN-Soviet Ore Refinery-苏军矿厂
Building [16]-NAWALL-Soviet Wall-苏军围墙
Building [18]-NAPSIS-Psychic Sensor-心灵感应器
Building [20]-NALASR-Soviet Sentry Gun-哨戒炮
Building [21]-NASAM-Allied Patriot Missile-爱国者飞弹
Building [22]-CASYDN02-Sydney Kangaroo Burger-悉尼袋鼠堡
Building [23]-GAYARD-Allied Shipyard-盟军船厂
Building [24]-NAIRON-Soviet Iron Curtain Device-铁幕装置
Building [25]-NACNST-Soviet Construction Yard-苏军建造场
Building [26]-NADEPT-Soviet Service Depot-苏军维修厂
Building [27]-GACSPH-Allied Chrono Sphere-超时空传送仪
Building [29]-GAWEAT-Allied Weather Controller-天气控制器
Building [30]-CABHUT-Bridge repair hut-桥梁维修小屋
Building [47]-CAHOSP-Old Civilian Hospital-市民医院
Building [53]-TESLA-Soviet Tesla Coil-磁暴线圈
Building [54]-NAMISL-Soviet Nuclear Missile Silo-核弹发射井
Building [55]-ATESLA-Allied Prism Cannon-光棱塔
Building [56]-CAMACH-Tech Machine Shop-科技机器商店
Building [58]-CASYDN03-Sydney Opera House-悉尼歌剧院
Building [59]-AMMOCRAT-Ammo Crates-弹药箱
Building [61]-NAYARD-Soviet Shipyard-苏军造船厂
Building [62]-GASPYSAT-Allied SpySat Uplink-间谍卫星
Building [63]-GAGAP-Allied Gap Generator-裂缝产生器
Building [64]-GTGCAN-Allied Grand Cannon-巨炮
Building [65]-NANRCT-Soviet Nuclear Reactor-核子反应堆
Building [66]-GAPILL-Allied Pill Box-机枪碉堡
Building [67]-NAFLAK-Soviet Flak Cannon-防空炮
Building [68]-CAOUTP-Tech Outpost-科技前哨站
Building [69]-CATHOSP-Tech Hospital-科技医院
Building [70]-CAAIRP-Tech Airport-科技机场
Building [71]-CAOILD-Tech Oil Derrick-科技钻油厂
Building [72]-NACLON-Cloning Vats-复制中心
Building [73]-GAOREP-Allied Ore Processor-矿石精炼器
Building [79]-CANEWY04-Statue of Liberty-自由女神像
Building [80]-CANEWY05-ZZZ World Trade Center-世贸中心
Building [82]-CATECH01-Communications-通讯中心
Building [85]-CAWASH01-White House-白宫
Building [92]-CAMISC01-Barrels-油桶1
Building [93]-CAMISC02-Barrel-油桶2
Building [104]-CAPARS01-Paris Tower-埃菲尔铁塔
Building [105]-GAAIRC-Allied Airforce Command Headquarters-盟军空指部
Building [107]-CAFRMB-Farm Outhouse-移动式厕所
Building [135]-AMRADR-Allied American Airforce Command Headquarters-美国空指部
Building [137]-CAGARD01-Guard Shack-警卫哨
Building [143]-MAYAN-Mayan Prism Pyramid-玛雅金字塔
Building [147]-CAMEX01-Mayan Prism Pyramid-玛雅金字塔
Building [160]-CARUS03-Russain Kremlin Palace-克里姆林宫
Building [179]-CAPARS11-Paris Arc de Triumphe-巴黎凯旋门
Building [181]-CAFARM06-Lighthouse-灯塔
Building [183]-NAPSYB-Psychic Beacon-心灵信标
Building [184]-NAPSYA-Psychic Amplifier-心灵增幅器
Building [186]-CACOLO01-Air Force Academy Chapel Colorado-空军学院礼拜堂
Building [289]-CAMSC13-Derelict Tank-废弃猛犸坦克
Building [313]-CASLAB-Tech Secret Lab-秘密科技实验室
Building [320]-CATRAN03-TRANS FORTRESS-尤里要塞
Building [369]-CAPOWR-Tech Civilian Power Plant-科技电厂
Building [398]-CABUNK03-Concrete Bunker 03-科技混凝土碉堡
Building [399]-CABUNK04-Concrete Bunker 04-科技混凝土碉堡
Building [402]-YACNST-YACNST-尤里建造场
Building [403]-YAPOWR-YAPOWR-生化反应室
Building [404]-YAREFN-YAREFN-奴隶矿场
Building [405]-YABRCK-YABRCK-尤里兵营
Building [406]-YATECH-YATECH-尤里作战实验室
Building [407]-YAWEAP-YAWEAP-尤里战车工厂
Building [408]-NABNKR-NABNKR-战斗碉堡
Building [409]-YAGGUN-YAGGUN-盖特机炮
Building [410]-YAPSYT-YAPSYT-心灵控制塔
Building [411]-NATBNK-NATBNK-坦克碉堡
Building [412]-GAFWLL-GAFWLL-尤里围墙
Building [413]-YAYARD-YAYARD-尤里船坞
Infantry [0]-E1-GI-美国大兵
Infantry [1]-E2-Conscript-动员兵
Infantry [2]-SHK-Shock Trooper-磁暴步兵
Infantry [3]-ENGINEER-Engineer-工程师
Infantry [4]-JUMPJET-Rocketeer-火箭飞行兵
Infantry [5]-GHOST-SEAL-海豹部队
Infantry [6]-YURI-Yuri-尤里
Infantry [7]-IVAN-Crazy Ivan-疯狂伊文
Infantry [8]-DESO-Desolater-辐射工兵
Infantry [9]-DOG-Attack Dog-苏联警犬
Infantry [13]-CTECH-Technician-技师
Infantry [15]-CLEG-Chrono Legionnaire-超时空军团兵
Infantry [16]-SPY-Spy-间谍
Infantry [17]-CCOMAND-Chrono Commando-超时空突击队
Infantry [18]-PTROOP-Psi-Corp Trooper-尤里复制人
Infantry [19]-CIVAN-Chrono Ivan-超时空伊文
Infantry [20]-YURIPR-Yuri Prime-尤里改
Infantry [21]-SNIPE-Sniper-狙击手
Infantry [22]-COW-Animal Cow-奶牛
Infantry [23]-ALL-Animal Alligator-鳄鱼
Infantry [24]-TANY-Tanya-谭雅
Infantry [25]-FLAKT-Flak Trooper-防空步兵
Infantry [26]-TERROR-Terrorist-恐怖分子
Infantry [27]-SENGINEER-Soviet Engineer-苏军工程师
Infantry [28]-ADOG-Allied Attack Dog-盟军警犬
Infantry [29]-VLADIMIR-Vladimir-弗拉基米尔
Infantry [30]-PENTGEN-General Pentagon-五角大楼将军
Infantry [31]-PRES-President-总统
Infantry [32]-SSRV-Secret Service-秘密保镖
Infantry [43]-POLARB-Animal Polar Bear-北极熊
Infantry [44]-JOSH-Animal Monkey-猴子
Infantry [51]-CLNT-Cowboy-Westwood之星
Infantry [52]-ARND-Hero-终结者
Infantry [53]-STLN-Bodybuilder-兰博
Infantry [54]-CAML-Animal Camel-骆驼
Infantry [55]-EINS-Albert Einstein-爱因斯坦
Infantry [56]-MUMY-Evil Mummy-木乃伊
Infantry [57]-RMNV-Romanov-罗曼诺夫
Infantry [58]-LUNR-Lunar Infantry-登月飞行兵
Infantry [59]-DNOA-Animal T-Rex-暴龙
Infantry [60]-DNOB-Animal Bront-恐龙
Infantry [62]-WWLF-Werewolf-狼人
Infantry [65]-BRUTE-BRUTE-狂兽人
Unit [0]-AMCV-Allied Construction Vehicle-盟军移动基地车
Unit [1]-HARV-War Miner-武装采矿车
Unit [2]-APOC-Apocalypse-灾厄坦克
Unit [3]-HTNK-Rhino Heavy Tank-犀牛坦克
Unit [4]-SAPC-Armored Transport-野牛运输艇
Unit [9]-MTNK-Grizzly Battle Tank-灰熊坦克
Unit [10]-HORV-War Miner-武装采矿车
Unit [13]-CARRIER-Aircraft Carrier-航空母舰
Unit [14]-V3-V3 Launcher-V3导弹车
Unit [15]-ZEP-Kirov Airship-基洛夫空艇
Unit [16]-DRON-Terror Drone-恐怖机器人
Unit [17]-HTK-Flak Track-防空履带车
Unit [18]-DEST-Destroyer-驱逐舰
Unit [19]-SUB-Typhoon Attack Sub-台风攻击潜艇
Unit [20]-AEGIS-Aegis Cruiser-神盾巡洋舰
Unit [21]-LCRF-Landing Craft-旅行者运输艇
Unit [22]-DRED-Dreadnought-无畏级导弹舰
Unit [23]-SHAD-BlackHawk Transport-黑鹰直升机
Unit [24]-SQD-Giant Squid-巨型乌贼
Unit [25]-DLPH-Dolphin-海豚
Unit [26]-SMCV-Soviet Construction Vehicle-苏军移动基地车
Unit [27]-TNKD-Tank Destroyer-坦克杀手
Unit [28]-HOWI-Howitzer-西风火炮
Unit [29]-TTNK-Tesla Tank-磁暴坦克
Unit [30]-HIND-Hind Transport-飞碟
Unit [31]-LTNK-Light Tank-轻坦克
Unit [32]-CMON-Chrono Miner(noback)-超时空采矿车
Unit [33]-CMIN-Chrono Miner-超时空采矿车
Unit [34]-SREF-Prism Tank-光棱坦克
Unit [36]-HYD-Sea Scorpion-海蝎
Unit [37]-MGTK-Mirage Tank-幻影坦克
Unit [38]-FV-IFV-多功能步兵车
Unit [40]-VLAD-Vladimir's Dreadnought-弗拉基米尔指挥舰
Unit [41]-DTRUCK-Demolitions Truck-自爆卡车
Unit [52]-CRUISE-Cruise Ship-游轮
Unit [73]-YDUM-YDUM
Unit [83]-PCV-PCV-尤里移动基地车
网上的资料(不一定准确):
[建筑类]
0=GAPOWR;盟军发电厂
1=GAREFN ;盟军矿厂
2=GAPILE ;盟军兵营
3=GAWEAP ;盟军兵工厂
4=GAAIRC ;盟军空军指挥部
5=AMRADR ;美国空军指挥部--AmericanParaDropSpecial
6=GADEPT ;盟军维修厂
7=GAYARD ;盟军船厂
8=GATECH ;盟军实验室
9=GAROBO; 控制中心 ---
10=GAOREP; 矿石精鍊器
11=GAWALL; 盟军围墙
12=GAPILL; 机枪碉堡---Vulcan2
13=NASAM ;爱国者飞弹 --RedEye2
14=GAGAP ;裂缝产生器
15=ATESLA ;光棱塔----PrismShot / PrismSupport
16=GASPYSAT; 间谍卫星
17=GACNST ;盟军建造场
18=GTGCAN ;法国巨炮 GrandCannonWeapon
19=GACSPH ;超时空传送仪 --- ChronoSphereSpecial
20=GAWEAT ;天气控制器 --- LightningStormSpecial
21=GASAND ;沙袋
22=GAGATE_A; 闸门
23=;===苏军======;
24=NAPOWR; 磁能反应炉
25=NAREFN ;苏军矿厂
26=NAHAND; 苏军兵营
27=NAWEAP; 苏军兵工厂
28=NARADR ;苏军雷达 --- SpyPlaneSpecial
29=NADEPT ;苏军维修厂
30=NAYARD ;苏军造船厂
31=NATECH ;苏军实验室
32=NANRCT ;核子反应堆 --- NukePayload
33=NAINDP ;工业工厂
34=NAWALL ;苏军围墙
35=NABNKR ;战斗碉堡
36=NALASR ;哨戒炮--Vulcan
37=NAFLAK ;防空炮--FlakWeapon
38=TESLA ;磁暴线圈 -- CoilBolt / OPCoilBolt
39=NACNST ;苏军建造厂
40=NAIRON ;铁幕 --- IronCurtainSpecial
41=NAMISL ;核弹发射井 -- NukeSpecial
42=NAPSYB ;心灵信标
43=;===尤里======;
44=YAPOWR ;生化反应炉
45=YAREFN ;奴隶矿厂
46=YABRCK ;尤里兵营
47=YAWEAP ;尤里兵工厂
48=NAPSIS ;心灵感应器 --- PsychicRevealSpecial
49=YAYARD ;尤里船厂
50=YAGRND ;部队回收厂
51=YATECH ;尤里实验室
52=GAFWLL ;尤里围墙
53=NATBNK ;坦克碉堡
54=YAGGUN ;盖特机炮
55=YAPSYT ;心灵控制塔----MultipleMindControlTower
56=NACLON ;复制中心
57=YAGNTC ;基因突变器 --- GeneticConverterSpecial
58=YAPPET ;心灵控制器 --- PsychicDominatorSpecial
59=YACNST ;尤里建造场
60=YAROCK ;不明建筑物
61=YACOMD ;尤里指挥中心
62=;===平======;
63=GASAND;沙墙
64=CAAIRP;科技机场---ParaDropSpecial
65=CAOILD;=科技钻油厂
66=CAPARS01;=艾菲尔铁塔
67=CAEAST02;=尤里雕像----PrismShot
68=CATRAN03;=尤里要塞
69=CAEAST01;=复活岛石像
[步兵类代码]
0=E1;美国大兵
1=E2;苏联动员兵
2=SHK;磁爆步兵
3=ENGINEER;盟军工程师
4=JUMPJET;火箭飞行兵
5=GHOST;海豹部队
6=YURI;尤里
7=IVAN;疯狂伊万
8=DESO;生化步兵
9=DOG;苏联军犬
10=CIV1;平民1
11=CIV2;平民2
12=CIV3;平民3
13=CTECH;技师
14=WEEDGUY;防IE挂载(没用)
15=CLEG;超时空兵团
16=SPY;间谍
17=CCOMAND;超时空突击队
18=PTROOP;伞兵
19=CIVAN;超时空伊万
20=YURIPR;尤里改
21=SNIPE;狙击手
22=COW;奶牛
23=ALL ;鳄鱼
24=TANY;谭雅
25=FLAKT;防空步兵
26=TERROR;恐怖分子
27=SENGINEER;苏联工程师
28=ADOG;盟军军犬
29=VLADIMIR;VLADIMIR
30=PENTGEN;PENTGEN
31=PRES;总统
32=SSRV;终级保镖
33=CIVA;德克萨斯平民A
34=CIVB;德克萨斯平民B
35=CIVC;德克萨斯平民C
36=CIVBBP;棒员运动员
37=CIVBFM;海滩肥男
38=CIVBF;海滩女
39=CIVBTM;海滩瘦男
40=CIVSFM;雪中肥男
41=CIVSF;雪中肥女
42=CIVSTM;雪中瘦男
43=POLARB;北极熊
44=JOSH;猴子
45=YENGINEER;尤里工程师
46=GGI;重装大兵
47=INIT;尤里新兵
48=BORIS;鲍裏斯
49=BRUTE;狂兽人
50=VIRUS;病毒狙击手
51=CLNT;快枪手
52=ARND;终结者
53=STLN;蓝波
54=CAML;骆驼
55=EINS;爱因斯坦
56=MUMY;木乃伊
57=RMNV;洛马诺夫总理
58=LUNR;登月火箭兵
59=DNOA;暴龙
60=DNOB;暴龙
61=SLAV;奴隶矿工
62=WWLF;(木乃伊)
63=YDOG;尤里军犬
64=YADOG;尤里军犬
65=CIVFM;海滩肥女
[战车类代码]
0=AMCV;盟军移动基地车
1=HARV;尤里奴隶采矿车
2=APOC;天启坦克
3=HTNK;犀牛坦克
4=SAPC;装甲运输船
5=CAR;汽车
6=BUS;校车
7=WINI;wini
8=PICK;小货车
9=MTNK;灰熊坦克
10=HORV;武装采矿车
11=TRUCKA;货车A
12=TRUCKB;货车B
13=CARRIER;航空母舰
14=V3;V3火箭车
15=ZEP;基洛夫空艇
16=DRON;恐怖机器人
17=HTK;防空履带车
18=DEST;驱逐舰
19=SUB;飓风级战舰
20=AEGIS;宙斯盾战舰
21=LCRF;盟军运输船
22=DRED;无畏级战舰
23=SHAD;夜鹰直升机
24=SQD;乌贼
25=DLPH;海豚
26=SMCV;苏联移动机基车
27=TNKD;坦克杀手
28=HOWI;榴弹炮
29=TTNK;磁爆坦克
30=LTNK;轻坦克
31=CMON;超时空采矿车(不回)
32=CMIN;超时空采矿车
33=SREF;光棱坦克
34=XCOMET;位置标定器
35=HYD;海蝎
36=MGTK;幻影坦克
37=FV;多功能步兵车
38=VLAD;维拉迪摩指挥舰
39=DTRUCK;自爆卡车
40=PROPA;宣传车
41=CONA;挖掘机
42=COP;cop
43=EUROC;欧洲汽车
44=LIMO;豪华轿车
45=STANG;小轿车
46=SUVB;小汽车A
47=SUVW;小汽车B
48=TAXI;出租车
49=PTRUCK;货车C
50=CRUISE;巡游船
51=TUG;拖船
52=CDEST;海岸巡逻船
53=YHVR;尤里气垫船
54=PCV;尤里机动基地车
55=SMIN;尤里奴隶矿厂
56=SMON;超时空采矿车
57=YCAB;黄色计程车
58=YTNK;盖特炮坦克
59=BFRT;战斗要塞
60=TELE;磁电坦克
61=CAOS;神经突袭车
62=DDBX;巴士
63=BCAB;黑色计程车
64=BSUB;雷鸣潜艇
65=SCHP;武装直升机
66=JEEP;卡车
67=MIND;精神控制车
68=DISK;镭射幽浮
69=UTNK;激光坦克
70=ROBO;遥控坦克
71=SCHD;武装直升机
72=DOLY;摄影车
73=CBLC;电车
74=FTRK;救火车
75=AMBU;救护车
76=CIVP;民航机
77=V3V3;V3火箭车
78=TURCKB;货车B
[飞机类代码]
0=APACHE;阿帕奇
1=ORCA;入侵者战机
2=HORNET;大黄蜂
3=V3ROCKET;V3火箭
4=ASW;舰载反潜机
5=DMISL;无畏级导弹
6=PDPLANE;运输机
7=BEAG;黑鹰战机
8=BPLN;米格战机(鲍里斯的飞机)
9=SPYP;侦察机
10=CMISL;雷鸣导弹
void _openTechOne(int objType, int index) {
_asm {
pushad
mov ecx, 0x0087F7E8
push index
push objType
mov eax, 0x006A6300
call eax
popad
}
}
void _openTechAll(int objType, int count) {
_asm {
pushad
xor esi, esi
label:
push esi
push objType // 0x7是建筑;0x10(也可能是0xF)是步兵;0x28是车船;0x1F=武器
mov ecx, 0x0087F7E8
mov eax, 0x006A6300
call eax
inc esi
cmp esi, count // 可以填一个编号上限值,参考上述ini
jle label
popad
}
}
// 科技全开
void OpenTech() {
//_openTechAll(7, 69); // 建筑全开
//_openTechAll(0x10, 30); // 步兵全开
//_openTechAll(0x28, 40); // 坦克全开
_openTechOne(0x28, 0); // 盟军基地车
_openTechOne(0x28, 26); // 苏军基地车
//_openTechOne(0x28, 54); // 尤里基地车
_openTechOne(0x28, 2); // 天启
_openTechOne(0x28, 14); // V3
//_openTechOne(0x28, 15); // 基洛夫
_openTechOne(0x28, 16); // 恐怖机器人(蜘蛛)
_openTechOne(0x28, 27); // 坦克杀手
_openTechOne(0x28, 34); // 光棱坦克
_openTechOne(0x28, 36); // 幻影
_openTechOne(0x28, 37); // 多功能
}
科技开启后游戏主程序会自动恢复,防止恢复的简单做法是跳过恢复,将如下指令修改为jmp
:
006AA788 |. /0F85 DA020000 |jnz 006AAA68 ;; 测试有效
或者,用CE使用如下注入代码:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(newmem,64)
label(returnhere)
label(originalcode)
label(exit)
newmem: //this is allocated memory, you have read,write,execute access
//place your code here
jmp 004F7B96
originalcode:
mov ecx,[00A8B238]
exit:
jmp returnhere
"{proc}"+F7B6C:
jmp newmem
nop
returnhere:
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"{proc}"+F7B6C:
mov ecx,[00A8B238]
//Alt: db 8B 0D 38 B2 A8 00
写了一个防科技全开恢复的补丁(在项目MatchBin
中编译),这个工具是通用的,需配置patch.ini
文件:
[main]
tag=ra2
path=D:\Ra2Game412\gamemd-spawn.exe
运行后输出如下日志代表成功:
tag: ra2
path: D:\Ra2Game412\gamemd-spawn.exe
Done! time used: 0.132713 ms
补丁的主要功能代码为:
void PEFilePatcher::PatchRa2(const wchar_t* inFilePath) {
PEFilePatcher patcher(inFilePath);
const uint8_t newValue[] = { 0xE9, 0xDB, 0x02, 0x00, 0x00, 0x90 };
patcher.patch(0x006AA788, newValue, sizeof(newValue));
}
心灵探测
判断是否有选中单位(选中的单位数量大于零),然后判断单位是否是建筑物类型(通过对象虚函数表),然后对单位的某个属性字段做修改(具体看代码),心灵探测的字段为一个word类型,因此最大的有符号正数是0x7FFF
。使用时,要选中一下建筑。
这个代码可能会出现内存访问读写异常,须加上异常处理机制。
// 开启心灵探测
void OpenPsychicDetection() {
__try {
_asm {
pushad
mov eax, 0x00A8ECC8
mov eax, [eax] //选中单位的数量
cmp eax, 0 //是否有选中单位
je exit1
mov eax, 0x00A8ECBC
mov eax, [eax]
mov eax, [eax] // +0
mov eax, [eax] // +0
cmp eax, 0x007E3EBC // Building vt
jnz exit1
mov eax, 0x00A8ECBC
mov eax, [eax]
mov eax, [eax] // +0
mov eax, [eax + 0x520] // +0x520
mov word ptr[eax + 0x170C], 0x7FFF // 0x170C PsychicDetectionRadius
exit1:
popad
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
}
}
无限信标
联网对战的时候最多只能放置三个信标,当超过三个时需要把多余的删除掉才能放置新的信标,这样就会造成一个麻烦:战况激烈的时候,想放置信标的时候放置不了,还需要在地图上删除一个信标才能继续放置。
思路2:游戏中删除信标的关键调用:
004FC1C6: sub_431410(dword_89C3B0, *(_DWORD *)(dword_A83D4C + 0x30));
只要模拟调用即可,汇编代码:
// 清除信标:一次批量清除玩家自己的3个信标
// 004FC1C6: sub_431410(dword_89C3B0, *(_DWORD *)(dword_A83D4C + 0x30));
void ClearBeacons() {
_asm {
pushad
mov eax, 0x00A83D4C
mov eax, [eax]
mov eax, [eax + 0x30]
push eax
mov ecx, 0x0089C3B0
mov eax, 0x00431410
call eax
popad
}
}
自动维修
#include "windows.h"
#include "Utils.h"
#include "Config.h"
#include "Ra2Helper.h"
#include <EventClass.h>
#include <HouseClass.h>
#pragma pack(1)
// YRpp 函数重载有问题,这里再写一遍
void MakeEventClass(EventClass* eventClass, int houseIndex, EventType eventType, int id, int rtti) {
int typeId = static_cast<int>(eventType);
__asm {
pushad
push rtti
push id
push typeId
push houseIndex
mov ecx, eventClass
mov eax, 0x004C65E0
call eax
popad
}
}
#pragma pack()
// .text:004AC0D8
void RepairNextBuilding() {
int count = 0;
for (int i = 0; i < HouseClass::CurrentPlayer->Buildings.Count; i++) {
BuildingClass* building = HouseClass::CurrentPlayer->Buildings.GetItem(i);
if (!building->IsBeingRepaired && building->Health < building->GetType()->Strength) {
//if (building->Health / building->GetType()->Strength < 0.7f) {
EventClass repairEvent(0, 0);
MakeEventClass(&repairEvent, HouseClass::CurrentPlayer->ArrayIndex, EventType::Repair,
static_cast<int>(building->UniqueID), static_cast<int>(AbstractType::Abstract));
EventClass::AddEvent(repairEvent);
if ((++count) >= Config::GetAutoRepairCount()) {
break;
}
}
}
}
// 开启自动修理功能
void AutoRepair() {
Utils::Log("Auto Repairing");
RepairNextBuilding();
}
如意宝箱
参考:
分析思路:
OD导入,分析字符串,相关联的字符串释义如下:
veterancy # 老兵 veteran # 老兵 base healing # 加血
找到如下的信息:
00481EA3 push 0081D058 crate at %d,%d contains tiberium\n 00481F77 push 0081D034 crate at %d,%d contains 'shroud'\n 00481FA7 push 0081D010 crate at %d,%d contains 'reveal'\n 0048204B push 0081CFF0 crate at %d,%d contains a unit\n 0048246F push 0081CFD0 crate at %d,%d contains money\n 0048256F push 0081CFAC crate at %d,%d contains explosives\n 00482728 push 0081CF8C crate at %d,%d contains napalm\n 0048284A push 0081CF60 crate at %d,%d contains cloaking device\n 0048297C push 0081CF38 crate at %d,%d contains veterancy(tm)\n 00482B99 push 0081CF10 crate at %d,%d contains base healing\n 00482CAB push 0081CEF0 crate at %d,%d contains icbm\n 00482D60 push 0081CED0 crate at %d,%d contains armor\n 00482EB6 mov ecx, 0081CEB8 eva_unitarmorupgraded 00482F40 push 0081CE98 crate at %d,%d contains speed\n 004830A5 mov ecx, 0081CE80 eva_unitspeedupgraded 0048312F push 0081CE5C crate at %d,%d contains firepower\n
以
veterancy
为例,定位到相关汇编代码:00482972 |> \0FBF46 26 movsx eax, word ptr [esi+26] 00482976 |. 0FBF4E 24 movsx ecx, word ptr [esi+24] 0048297A |. 50 push eax 0048297B |. 51 push ecx 0048297C |. 68 38CF8100 push 0081CF38 ; crate at %d,%d contains veterancy(tm)\n 00482981 |. E8 5A3FF8FF call 004068E0
00482972
表明这个从其他地方跳转过来的,找到跳转源头:00481DE0 |. FF2495 C43348>jmp dword ptr [edx*4+4833C4]
分析地址
4833C4
,是一个跳转表:004833C4 00482463 ; crate at %d,%d contains money\n 004833C8 00482041 ; crate at %d,%d contains a unit\n 004833CC 00482B8F ; crate at %d,%d contains base healing\n 004833D0 00482840 ; crate at %d,%d contains cloaking device\n 004833D4 00482565 ; crate at %d,%d contains explosives\n 004833D8 0048271E ; crate at %d,%d contains napalm\n 004833DC 004832F5 ; ??? 004833E0 00481F6D ; crate at %d,%d contains 'shroud'\n 004833E4 00481F9D ; crate at %d,%d contains 'reveal'\n 004833E8 00482D56 ; crate at %d,%d contains armor\n 004833EC 00482F36 ; crate at %d,%d contains speed\n 004833F0 00483125 ; crate at %d,%d contains firepower\n 004833F4 00482CA1 ; crate at %d,%d contains icbm\n 004833F8 004832F5 ; ??? 004833FC 00482972 ; crate at %d,%d contains veterancy(tm)\n 00483400 004832F5 ; ??? 00483404 00481DE7 ; crate at %d,%d contains poison gas\n 00483408 00481E99 ; crate at %d,%d contains tiberium\n 0048340C 90909090 ; nop
一共有
0x12
个地址((0048340C - 004833C4) / 4
),逐一在反汇编窗口中跟随查看地址,并对应一下功能。
实现思路:
对地址
4833C4
起始的0x12
个四字节内容统一修改为想要的功能地址表。例如想要金钱效果,当按下热键时全部修改为0x00482463
,然后再去捡箱子,则无论是什么箱子都会执行的是捡到金钱的效果。类推,可以设计一个主要的热键功能:
金钱 00482463 加血 00482B8F 经验 00482972 防御 00482D56 火力 00483125 速度 00482F36
实现代码:
// 所有捡箱子效果:金钱
void TrainerFunctions::SetBoxAllMoney() {
const LPVOID MethodTableAddr = (LPVOID)0x004833C4;
const size_t MethodTableCount = 0x12;
const SIZE_T MethodTableSize = MethodTableCount * sizeof(DWORD);
const DWORD JumpToAddr = 0x00482463; // 捡到的是金钱的跳转地址
// 修改代码保护属性
DWORD dwOldProtect = 0;
if (VirtualProtect(MethodTableAddr, MethodTableSize, PAGE_EXECUTE_READWRITE, &dwOldProtect)) {
DWORD* p = (DWORD*)MethodTableAddr;
for (size_t i = 0; i < MethodTableCount; i++) {
*(p + i) = JumpToAddr;
}
// 恢复代码保护属性
if (!VirtualProtect(MethodTableAddr, MethodTableSize, dwOldProtect, &dwOldProtect)) {
printLastError(GetLastError(), "Failed 2!");
}
} else {
printLastError(GetLastError(), "Failed 1!");
}
}
验证效果:
单机玩有效果,但是联网对战不行,会卡,可能是触发了什么机制。
如何使用
编译项目 Ra2Tool ,使用任意注入工具把 Ra2Dll.dll
模块注入到游戏进程即可(RATrainer 用不到)。
如果使用HookLoader工具,可以参考如下使用步骤:
【使用说明】 1、运行exe 2、进入游戏之后按下快捷键【ALT + H】即可,一定要进入游戏,保险起见是在出现基地之后,其他场景没测试过。
【作者有话】 全图功能我认为对级别低的玩家比较有帮助,对级别高的玩家帮助没有那么大。其他影响游戏平衡的变态功能全部删除了,只保留了全图这个功能,不然就没有可玩性了。
内存地址
- 0x00A83D4C :玩家。
[0x00A83D4C] + 0x30
是玩家ID。 - 0x00A8022C :
- 0x00A8ECBC : 选中的单位有关。
[0x00A8ECBC]
是选中单位的数组地址。如果要遍历选择的单位,则结合个数,每次取一个四字节,就是具体单位对象的地址。 - 0x00A8ECC8 : 选中单位的数量,也即:
0x00A8ECBC + 0x0C
。 - 0x6C : 单位血量。
- 0x150 :等级。无星是0,三星是:0x40000000。
- 0x21C :单位归属。
- 0x584 : 疑似速度。
- 0x007E3EBC:建筑物的虚函数表地址,可以通过虚函数表是否是该值来判断对象是否是建筑物。
单机功能
可以参考:AdjWang/RA2YurisRevengeTrainer: 红色警戒2 尤里的复仇v1.001 内存修改器 ,主要是单机版可用的功能,联网对战中很多功能不可用,主要是借鉴参考。
游戏速度:
0x00A8EB60
地址的内容是速度(4字节)。金钱:
[0x00A83D4C] + 0x30C
地址的内容是金钱(4字节)。快速建造:
[0x00A83D4C] + 0x5378
地址起始的连续 5 个四字节内容是速度,修改为15可以实现快速建造。删除选中的单位:
__asm { pushad mov eax,0x00A8ECC8 mov eax,[eax] //选中单位数量 cmp eax,0 //是否选中单位 je exit1 mov eax,0x00A8ECBC mov eax,[eax] mov ecx,[eax] mov eax,[ecx] add eax,0xF8 mov ebx,[eax] call ebx exit1: popad }
选中单位归属为我:
__asm { pushad mov eax,0x00A8ECC8 //选中单位数量 mov eax,[eax] cmp eax,0 //是否选中单位 je exit1 push 0 // mov ebx,0x00A83D4C mov eax,[ebx] push eax mov ebx,0x00A8ECBC mov eax,[ebx] mov ecx,[eax] mov ebx,[ecx] add ebx,0x3D4 mov ebx,[ebx] call ebx exit1: popad }
选中单位升级:
__asm { pushad mov eax,0x00A8ECBC mov ebx,[eax] //选中单位首地址 mov eax,0 process: mov ecx,0x00A8ECC8 cmp eax,[ecx] //选中单位数量为零判断 jge brek //>=跳转 mov ecx,[ebx+eax*4] //当前单位地址 mov edx,0x40000000 //三星的数值 add ecx,0x150 mov [ecx],edx //修改单位经验 add eax,1 jmp process brek: popad }
无限金钱
void GiveMeMoney() {
_asm {
pushad
mov eax, 0x00A83D4C
mov eax, [eax]
mov dword ptr[eax + 0x30C], 0x7FFFFFFF
popad
}
}
高级玩法
- 使用 Phobos-developers/YRpp 作为SDK。例如坦克单位的上述内存地址偏移,可以通过头文件
FootClass
及其父类层层查看对应偏移的字段说明,能对应的上 ,其他属性可以通过源码来判断其偏移地址。在编写工具的时候,开发阶段可以直接使用这些头文件,获取到的地址关联到对应的对象,就可以直接使用了,不需要自己计算地址的硬编码了,很是方便。 - 使用 CnCNet 搭建联网对战平台。这个有兴趣的可以玩玩,也可以参考其源码学习如何打补丁的。
参考
- 红警2共和国之辉开启调试功能
- RA2YurisRevengeTrainer 红色警戒2 尤里的复仇v1.001 内存修改器
- Phobos-developers/Phobos: Ares-compatible C&C Red Alert 2: Yuri’s Revenge engine extension
- CnCNet
- Ra2Tool
文档信息
- 本文作者:zhupite
- 本文链接:https://zhupite.com/sec/red-alert2.html
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)