开心农场外挂破解中。。。

来源:互联网 发布:热血霸业(神奇网络) 编辑:程序博客网 时间:2024/04/27 13:50

      首先声明此文目的在于研究学习,虽然对happyrobot作者的有些做法不赞同,但是对happyrobot作者的劳动成果表示最大的尊重,本文没有侵犯软件作者的核心利益,如果对本文有不同看法请联系pdh013@126.com,我将酌情对本文作出处理。另外请不要随意转载本文,如需转载请注明出处和作者。对本文内容感兴趣的朋友请和我联系,欢迎和我讨论和解决相关问题。

小弟初学C#,有一天玩了玩校内开心农场,就想写一个外挂,无奈不懂网页编程不熟悉网络命令,更不懂加密,但是还是硬着头皮开始写代码,最后只写到自动登录校内成功,至于如何自动收割粮食、自动播种等等功能不会写了,无法突破,于是就从反编译别人用C#写的校内开心农场外挂入手。又无奈,开心农场可用外挂很少,可下载的又很少都是要收费的,好不容易下载到了一个据说是可用的外挂,但是程序作者却煞费苦心进行了加密,他把顾客的id都写成了授权文件(.dat),文件名是用户id+.dat,如3431342.dat,文件里面包含了一些加密的信息,他使用了VS2005提供的加密算法,编译出来的exe文件还使用了字符串混淆和流程混淆技术,用Reflectorfox反编译出来的代码根本就看不成。又是无奈之下我使用了ildasm先把开心农场机器人.exe文件,反汇编成MSIL代码文件,使用VS2005提供的Microsoft CLR调试器,对IL文件进行单步调试直接对它进行删改,试图绕过作者的认证过程,IL代码其实就是一种汇编,看起来特费劲,硬着头皮篡改IL代码,也是有一点点进展,但是最后还是不能正常使用,我现在还不能确认是没破解好程序还是校内更新了Farmkey,所以原来的就不好用了。

 

 

下面是我用ildasm反汇编后得到的IL代码文件里用到的IL语句:

Public field Static     Ldc_I4     将所提供的 int32 类型的值作为 int32 推送到计算堆栈EDI上。

Public field Static     Ldc_I4_0     将整数值 0 作为 int32 推送到计算堆栈上。

Public field Static     Ldc_I4_1     将整数值 1 作为 int32 推送到计算堆栈上。

Public field Static     Ldc_I4_2     将整数值 2 作为 int32 推送到计算堆栈上。

Public field Static     Ldc_I4_3     将整数值 3 作为 int32 推送到计算堆栈上。

Public field Static     Ldc_I4_4     将整数值 4 作为 int32 推送到计算堆栈上。

Public field Static     Ldc_I4_5     将整数值 5 作为 int32 推送到计算堆栈上。

Public field Static     Ldc_I4_6     将整数值 6 作为 int32 推送到计算堆栈上。

Public field Static     Ldc_I4_7     将整数值 7 作为 int32 推送到计算堆栈上。

Public field Static     Ldc_I4_8     将整数值 8 作为 int32 推送到计算堆栈上。

Public field Static     Ldc_I4_M1     将整数值 -1 作为 int32 推送到计算堆栈上。

Public field Static     Ldc_I4_S     将提供的 int8 值作为 int32 推送到计算堆栈上(短格式)。

Public field Static     Ldc_I8     将所提供的 int64 类型的值作为 int64 推送到计算堆栈上。

Public field Static     Ldc_R4     将所提供的 float32 类型的值作为 F (float) 类型推送到计算堆栈上。

Public field Static     Ldc_R8     将所提供的 float64 类型的值作为 F (float) 类型推送到计算堆栈上。

 

Public field Static     Ldlen     将从零开始的、一维数组的元素的数目推送到计算堆栈上。

 

Public field Static     Stloc     从计算堆栈的顶部弹出当前值并将其存储到指定索引处的局部变量列表中。

Public field Static     Stloc_0     从计算堆栈的顶部弹出当前值并将其存储到索引 0 处的局部变量列表中。

 

Public field Static     Rem     将两个值相除并将余数推送到计算堆栈上。

Public field Static     Rem_Un     将两个无符号值相除并将余数推送到计算堆栈上。

 

Public field Static     Bne_Un     当两个无符号整数值或不可排序的浮点型值不相等时,将控制转移到目标指令。

Public field Static     Bne_Un_S     当两个无符号整数值或不可排序的浮点型值不相等时,将控制转移到目标指令(短格式)。

 

Public field Static     Ldloc     将指定索引处的局部变量加载到计算堆栈上。

Public field Static     Ldloc_0     将索引 0 处的局部变量加载到计算堆栈上。

 

Public field Static     Ldarg     将参数(由指定索引值引用)加载到堆栈上。

Public field Static     Ldarg_0     将索引为 0 的参数加载到计算堆栈上。

 

Public field Static     Ldfld     查找对象中其引用当前位于计算堆栈的字段的值。

Public field Static     Ldflda     查找对象中其引用当前位于计算堆栈的字段的地址。

 

Public field Static     Ldnull     将空引用(O 类型)推送到计算堆栈上。

Public field Static     Ceq     比较两个值。如果这两个值相等,则将整数值 1 (int32) 推送到计算堆栈上;否则,将 0 (int32) 推送到计算堆栈上。

 

Public field Static     Box     将值类转换为对象引用(O 类型)。

 

Public field Static     Conv_I4     将位于计算堆栈顶部的值转换为 int32

 

Public field Static     Newarr     将对新的从零开始的一维数组(其元素属于特定类型)的对象引用推送到计算堆栈上。

 

Public field Static     Ldc_I4_M1     将整数值 -1 作为 int32 推送到计算堆栈上。

 

Public field Static     Conv_U4     将位于计算堆栈顶部的值转换为 unsigned int32,然后将其扩展为 int32

 

Public field Static     Cgt     比较两个值。如果第一个值大于第二个值,则将整数值 1 (int32) 推送到计算堆栈上;反之,将 0 (int32) 推送到计算堆栈上。

Public field Static     Cgt_Un     比较两个无符号的或不可排序的值。如果第一个值大于第二个值,则将整数值 1 (int32) 推送到计算堆栈上;反之,将 0 (int32) 推送到计算堆栈上。

 

Public field Static     Clt     比较两个值。如果第一个值小于第二个值,则将整数值 1 (int32) 推送到计算堆栈上;反之,将 0 (int32) 推送到计算堆栈上。

Public field Static     Clt_Un     比较无符号的或不可排序的值 value1 value2。如果 value1 小于 value2,则将整数值 1 (int32 ) 推送到计算堆栈上;反之,将 0 ( int32 ) 推送到计算堆栈上。

最后我说说如何修改了其中的IL代码。首先我使用了VS2005提供的Microsoft CLR调试器,对IL文件进行单步调试,首先就是如何修改程序能绕过作者的身份验证过程的问题。我的办法是这样的,IL代码里面有特别多的brbrfalsebrtrue的跳转语句,利用单步调试可以一步一步试,知道如何跳转才能导引程序想正确方向运行而不往“授权文件已损坏”或者“当前使用者未授权”程序块跳转,比如下面代码:

      IL_0160:  ldloc.3   //V_3临时变量的值载入到计算堆栈

      IL_0161:  brtrue     IL_0086 //如果值为真则跳转到IL_0086程序段

但是一旦不跳转到IL_0086程序段,程序就报错:“授权文件已损坏”,于是我就把代码改成:

      IL_0160:  ldc.i4.1 // 1载入到计算堆栈

      IL_0161:  brtrue     IL_0086//如果值为真则跳转到IL_0086程序段

我把1载入到计算堆栈,那么程序运行到这里肯定会跳转到IL_0086程序段。

 

另外,未破解的程序打开的时候开心农场tab下面的所有按钮的enable=false,按钮全部是灰色的,不能使用,如何让所有按钮enable=true呢?方法如下:首先作者是使用的[DevComponents.DotNetBar2]DevComponents.DotNetBar C#控件,所以我们先查找所有的ButtonItem关键字于是找到了多个如下的程序段:

IL_0000:  nop

    IL_0001:  ldarg.0

    IL_0002:ldfld class [DevComponents.DotNetBar2]DevComponents.DotNetBar.ButtonItem HappyRobot.xf8cd58877bcccfa0::x2e92c7c071be839a

    IL_0007:  ldc.i4.0   //// 0载入到计算堆栈

IL_0008:callvirt instance void [DevComponents.DotNetBar2]DevComponents.DotNetBar.BaseItem

::set_Enabled(bool) //执行set_Enabled函数,那个bool的参数肯定就是预先载入计算堆栈的0

    IL_000d:  br         IL_0117

我们看到这段代码先把0载入到计算堆栈然后执行set_Enabled函数,那个bool的参数肯定就是预先载入计算堆栈的0了,把ldc.i4.0改写成ldc.i4.1于是这个ButtonItem控件就被enable了,界面里面的按钮可用了。

    最后,总结一下程序不能正常使用的原因,一个有可能是授权文件.dat可能有一些必要信息没有被破解,所以导致以后的程序使用了value不正确的变量;另外有肯能是开心农场farmkey计算方法更新了,旧的算法算出来的key已经不可用了。欢迎对此感兴趣的朋友给我提宝贵的意见和建议,我的邮箱是:pdh013@126.com