当前位置 > 首页 > Asp.net

用Cecil任意修改.Net程序集+源码

2012-12-7 23:11:00来源:Asp.net

      之前写过一篇文章《欺骗你的地理坐标+源码》,简单的讲述了使用Cecil修改WP版微信程序的方法。本文再次以破解WP的XBL(Xbox LIVE)游戏为例讲解如何使用Cecil这把尚方宝剑,让ILDasm修改IL的方法彻底成为历史。

 

      最近在Windows Phone Store的Nokia collection里面发现了《Parking Mania(疯狂停车场)》这款游戏。试玩了一下觉得非常有趣,但只能试玩前面少数几关。手痒痒的就开始了“盗版”部署。由于Parking Manin是XBL游戏,其调用GamerServicesComponent组件。但直接部署的XAP的应用无法使用此组件,从而会在使用了组件的地方会直接终止应用(DFT成就版ROM除外)。所以我们要做的就是在整个游戏中找到所有调用了XBL服务的地方并将其去除或跳过。但这样有个明显的缺点:XBL最重要的成就和排名功能被阉割掉了。DFT成就版就是为了解决这一问题而产生的。

 

      Cecil、WP7应用、IL等背景知识已经在上一篇博文中讲述了,有兴趣的请移步到《欺骗你的地理坐标+源码》。

 

      为了破解,当然是要先找到所有调用了XBL服务的地方。直接在IL中搜索GamerServicesComponent,只有ParkingMania.ParkingManiaGame中枪。然后在Initialize方法中前两句指令给删掉,清空HandleGameUpdateRequired、Update方法。即下图中红框中的代码要干掉。

image

image

      找到其对应的IL代码:

image

 

      对应用C#代码操作的代码如下 if (type.FullName == "ParkingMania.ParkingManiaGame")
{
var field = type.Fields.FirstOrDefault(s => s.Name == "GamerServiceInstance");
type.Fields.Remove(field);

foreach (var method in type.Methods)
{
if (method.Body == null)
continue;

var worker = method.Body.GetILProcessor();
if (method.Name == "Initialize")
{
var list = method.Body.Instructions.Skip(1).Take(9).ToList();
list.ForEach(i => { worker.Remove(i); });
}
if (method.Name == "HandleGameUpdateRequired")
{
var list = method.Body.Instructions.Skip(3).Take(4).ToList();
list.ForEach(i => { worker.Remove(i); });
}
if (method.Name == "Update")
{
var list = method.Body.Instructions.Skip(8).Take(8).ToList();
list.ForEach(i => { worker.Remove(i); });
}
}
}

 

      再进一步阅读分析源码可以发现有ParkingMania.Services.Data.Achievments.XBLAService这个类。这里面要把Event、LoadMoneyLeaderboard、LoadStarsLeaderboard、GetAchievmentsForMenu方法统统干掉。具体方法也类似,就不重复贴代码的。

 

      需要注意的是:离开try…catch…模块的时候需要leave.s指令、离开一个方法的时候需要ret指令。删除的时候记得保留这些指令。

 

       最后贴出完整的代码 using Mono.Cecil;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CecilParkingMania
{
class Program
{
static void Main(string[] args)
{
var bas = @"D:\Til\Parking_0\";
var src = bas + @"ParkingMania.org.dll";
var dst = bas + @"0\ParkingMania.dll";

var resolver = new DefaultAssemblyResolver();
resolver.AddSearchDirectory(bas + @"0");

var parameters = new ReaderParameters
{
AssemblyResolver = resolver,
ReadSymbols = false,
};
var assembly = AssemblyDefinition.ReadAssembly(src, parameters);

foreach (var module in assembly.Modules)
{
foreach (var type in module.Types)
{
if (type.FullName == "ParkingMania.ParkingManiaGame")
{
var field = type.Fiel