云游仙境
跟狗一样的程序
![Rank: 12](static/image/common/star_level3.gif) ![Rank: 12](static/image/common/star_level3.gif) ![Rank: 12](static/image/common/star_level3.gif)
- 贡献度
- 703
- 金元
- 6350
- 积分
- 3467
- 精华
- 2
- 注册时间
- 2008-11-1
|
魔能是个.net游戏,而且贯彻了不加密不混淆的优良作风(不过现在已经够慢了,估计混淆以后速度只能堪比乌龟了)。
因此,这是一个很好玩的玩具(……?),很适合用来做.Net破解的练手,也有足够多的内容用来折腾。
开学以来一直很忙,无暇无地折腾新游戏。
于是在一个月黑风高的夜晚,我溜进学校的某个实验室,由于蛋疼甚矣,不知怎么的想起魔能,觉得鸾霄那帮家伙估计短时间不会填坑了,于是翻出U盘里曾扔进去的魔能的主程序加几个dll并拆了其中一个,做了如下蛋疼的记录。
话说vim真是很好用呢。
PolygonHead.dll 文件
.NET 3.5 引用 XNA 3.1
目标:字体文件格式逆向
使用工具:ILSpy
1. 先是按照当初写提取器时候的记忆,找到了Pipeline模块
2. 由于做的是字体逆向,无视掉AdditiveEddectReader和BiTreeModeReader等等其它Reader,直奔BitmapFontReader。
3. 打开后发现仅有一个Read函数,然而输入的两个参数是ContentReader iInput和BitmapFont existingInstance,猜想还不是调用的最底层,值得商榷。
4. 不管怎么说,按照线索追下去,发现:
if (existingInstance == null)
{
existingInstance = new BitmapFont();
}
existingInstance.Read(iInput);
5. 追入BitmapFont的构造器,发现空无一物。只好继续追踪下面的Read方法。
6. 进入BitmapFont.Read,内容很多
this.mSpacing = 0;
this.mLineHeight = iInput.ReadInt32();
this.mBaseLine = iInput.ReadInt32();
this.mDefaultCharacter = iInput.ReadChar();
这是开始的一点代码,spacing是啥?本来想要预留一段作为备用数据单元么?
先继续看。
先是莫名的mLineHeight,ReadInt32()读取了4个字节
然后是mBaseLine,也是4字节
DefaultCHaracter,读了一个char,这个有点复杂,
观察得知里面检查了char是否占两个byte,所以可能读一个可能读俩。
GraphicsDevice graphicsDevice = null;
do
{
try
{
graphicsDevice = (iInput.ContentManager.ServiceProvider.GetService(typeof(IGraphicsDeviceManager)) as GraphicsDeviceManager).GraphicsDevice;
}
catch
{
Thread.Sleep(1);
}
}
图形设备相关,无视……
while (graphicsDevice == null);
GraphicsDevice obj;
Monitor.Enter(obj = graphicsDevice);
继续无视……
try
{
this.mTexture = iInput.ReadObject<Texture2D>();
}
finally
{
Monitor.Exit(obj);
}
好吧,这个东西……可以看到字体作为Texture2D格式被读出了,这与曾经做过的工作结论相符,当时就是以Texture2D形式成功读出图片的。
7. 追入Texture2D,发现这东西不小……好吧,到时候毫无疑问需要逆向构造一个此类型,那么可以肯定平台又是.NET没跑了。。。这有点看不懂,SetData<T>里面的<T>是什么?泛型吗?这这这……数据是哪个啊……
8. 囧。才发现Texture2D属于XNA模块啊……不用管它了。
9. 回头关心一下iInput.ReadObject,这家伙在Xna.Framework.Content.ContentReader类中,嗯,没准以后能顺藤摸瓜找个Writer之类的。先留个Flag。
10. 回到Read方法。又有新动作。
int num = iInput.ReadInt32();
this.mGlyphs = new Dictionary<char, Glyph>(num);
this.mCharacters = new Dictionary<char, Character>(num);
num读取了4个字符。
话说上面读了一个object怎么知道的有多长啊?莫非用了飘柔就是这么自信?
看来Xna有自己的方式啊。
或者,那个类中只有保存好的相关信息,而不存在数据!
那个Dictionary属于System.Collections.Generic,好吧无视掉。我们继续。
for (int i = 0; i < num; i++)
{
Glyph glyph = Glyph.Read(iInput);
this.mGlyphs.Add(glyph.Character, glyph);
Character value = Character.FromGlyph(glyph, Vector4.One, this.mTexture.Width, (float)this.mTexture.Height);
this.mCharacters.Add(glyph.Character, value);
}
大量的读数据!num注目!
Glyph是一个不长的类,但是读了很多东西,全粘出来好了。
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using System;
namespace PolygonHead
{
public struct Glyph
{
public char Character;
public Point Origin;
public Point Size;
public int AdvanceWidth;
public int LeftSideBearing;
public bool ForceWhite;
public static Glyph Read(ContentReader iInput)
{
Glyph result;
result.Character = iInput.ReadChar();
result.Origin = default(Point);
result.Origin.X = iInput.ReadInt32();
result.Origin.Y = iInput.ReadInt32();
result.Size = default(Point);
result.Size.X = iInput.ReadInt32();
result.Size.Y = iInput.ReadInt32();
result.AdvanceWidth = iInput.ReadInt32();
result.LeftSideBearing = iInput.ReadInt32();
result.ForceWhite = iInput.ReadBoolean();
return result;
}
}
}
懒得算多长了……写的时候再看吧。
int num2 = iInput.ReadInt32();
哦哦,又来了。
this.mKerning = new Dictionary<char, Dictionary<char, int>>();
for (int j = 0; j < num2; j++)
{
char key = iInput.ReadChar();
char key2 = iInput.ReadChar();
int value2 = iInput.ReadInt32();
Dictionary<char, int> dictionary;
if (!this.mKerning.TryGetValue(key, out dictionary))
{
dictionary = new Dictionary<char, int>();
this.mKerning.Add(key, dictionary);
}
dictionary.Add(key2, value2);
}
看来是很简单的数据结构嘛。回头用UE看一下,收工!
11. 最后,整理下流程:
<1> mLineHeight 4 int32
<2> mBaseLine 4 int32
<3> mDefaultCharacter 1 or 2 char
<4> mTexture 不定 object,Texture2D
<5> num 4 int32
<6> Characters num*(26 or 27) struct
<7> num2 4 int32
<8> Kernings num2*(6 or 8) struct
<end>
注:Kerning
n. 1. 【印】(铅字面之)上下的突出部分
vt. 1. 使(铅字面)上下突出 2. 将(铅字上下突出部分)做平
完成
2011.11.16 22:15 |
|