flash 游戏分析 - 1

游戏

我们就以《猎人的生存日记》(Orion Sandbox)这款游戏来分析。

下载链接

FlashStart打开Orion Sandbox 1.swf

我们需要反复进入游戏,可以先打开一次游戏,以此进行:文件 \(\rightarrow\)游戏路径\Orion Sandbox 1.swf

工具

  • 可以看16进制的软件(我用的是HxD

数字

因为这是个本地游戏,所以在本地要有个储存的位置。

这个位置一般在C:\Users\UserName\AppData\Roaming\Macromedia\Flash Player#SharedObjects\一串英文#localWithNet\游戏文件夹名

在这里面有\(3\)个文件:

  • player.sol 玩家数据
  • world.sol 地图数据(世界数据)
  • settings.sol 一些设置

我们主要看 player.sol 这个文件。

修改血量

从 player.sol 里找到health这串字符。为什么修改血量要找这字符,因为\(health\)是血量的意思。

68 65 61 6C 74 68 04 64
h  e  a  l  t  h

如果你的血量是\(100\)的话就可以找到以上数据。

\(5\)个是health的ASCII码。

04是什么知不道,只能猜,它是字符串的结束,或是整型数字的开始。

64很明显,就是血量。(\(64_{(16)}=100_{(10)}\)

我们将64改成63,然后保存一下。

我建议更改的时候备份一下。

重进游戏:血量变成\(99\)。修改成功。

修改经验值

还是从 player.sol 里找,找experience这串字符。experience n. 经验 vt. 体验。

65 78 70 65 72 69 65 6E 63 65 04 00
e  x  p  e  r  i  e  n  c  e  UK

UK 表示未知。(unknow)

00 表示经验是\(0\)

经验达到\(127\)时,数据中表示7F

exp = 127
65 78 70 65 72 69 65 6E 63 65 04 7F
e  x  p  e  r  i  e  n  c  e  UK 127

但经验达到\(128\)时,数据中表示81 00

exp = 128:
65 78 70 65 72 69 65 6E 63 65 04 81 00
e  x  p  e  r  i  e  n  c  e  UK 128

81改为82后经验变为\(256\)

所以\(2\)位数字的范围为\([0, 16383]\)\([00\space00, FF\space7F]\)

\[(FFh-80h)\times80h+7Fh=3FFFh=16383_{(10)} \]

\(3\)位数字:\(16384\)表示81 80 00

所以,公式就是:

\[a_0+\sum^{l-1}_{i=1}{2^{7i}(a_i-80h)} \]

\(l\)\(a\)的长度。
\(a_0\)是最低位。
C++ 代码:

template<class intT>
intT flashint_to(unsigned char* fints) {
    intT res = 0;
    size_t l = 0;
    intT expr = 1;
	while(fints[l++] >= 0x80);
	for(size_t i = l - 2;; i--)
    {
        res += (fints[i] - 0x80) * (expr *= 128);
        if(i == 0)
            break;
    }
    res += fints[l - 1];
    return res;
}

// test
void test() {
    ::std::cout << flashint_to<int>("\x81\x01"); // 输出 129
}

根据上面的规律,我们也可以逆回去:

\[x\to a_i=\cases{ x\mod 128 & ,i=1 \\ \lfloor x \div2^{7i} \rfloor+80h &,i>1 } \]

C++ 代码:

template<class intT>
size_t to_flashint(intT x, unsigned char* fints) {
    size_t l = 0;
    while(x)
    {
        fints[l++] = x % 128 + 0x80;
        x /= 128;
    }
    for(int i = 0; i < l / 2; i++)
    {
        fints[i] ^= fints[l - i - 1];
        fints[l - i - 1] ^= fints[i];
        fints[i] ^= fints[l - i - 1];
    }
    fints[l - 1] -= 0x80;
    return l;
}

// test
void test() {
    unsigned char buf[10];
    int x = 129;
    int l = to_flashint(x, buf);
    for(int i = 0; i < l; i++)
        printf("%x ", buf[i]);
    // 输出 81 01
}

有了这两个函数就好办了

posted @ 2022-12-14 13:16  kuailedetongnian  阅读(190)  评论(0编辑  收藏  举报