首页 > 解决方案 > x86 装配问题 - 任何人都可以确定下面发生了什么吗?

问题描述

我为我玩的一个 20 多年前的游戏下载了一个修改,它是用汇编代码编写的。它添加了雾效果,然后基于此改变抓地力水平。然而,雾级别似乎是随机选择的。

用受过训练的眼睛很容易看到下面发生的事情吗?我通过反汇编程序运行它,所以不确定它是否真的正确显示......

很容易发现递增的 0x33、0x34、0x35 等,所以我有一种重要的感觉。

0x0000000000000000:  DD 35 00 00 00 00       fnsave dword ptr [0]
0x0000000000000006:  80 3D 00 00 00 00 B8    cmp    byte ptr [0], 0xb8
0x000000000000000d:  75 24                   jne    0x33
0x000000000000000f:  80 3D A8 11 55 00 02    cmp    byte ptr [0x5511a8], 2
0x0000000000000016:  0F 85 E6 00 00 00       jne    0x102
0x000000000000001c:  80 3D 00 00 00 00 00    cmp    byte ptr [0], 0
0x0000000000000023:  75 30                   jne    0x55
0x0000000000000025:  50                      push   eax
0x0000000000000026:  A1 04 B5 6C 00          mov    eax, dword ptr [0x6cb504]
0x000000000000002b:  A3 00 00 00 00          mov    dword ptr [0], eax
0x0000000000000030:  58                      pop    eax
0x0000000000000031:  EB 22                   jmp    0x55

0x0000000000000033:  80 3D B0 11 55 00 02    cmp    byte ptr [0x5511b0], 2
0x000000000000003a:  0F 85 C2 00 00 00       jne    0x102
0x0000000000000040:  80 3D 00 00 00 00 00    cmp    byte ptr [0], 0
0x0000000000000047:  75 0C                   jne    0x55
0x0000000000000049:  50                      push   eax
0x000000000000004a:  A1 0C B5 6C 00          mov    eax, dword ptr [0x6cb50c]
0x000000000000004f:  A3 00 00 00 00          mov    dword ptr [0], eax
0x0000000000000054:  58                      pop    eax
0x0000000000000055:  80 3D 00 00 00 00 33    cmp    byte ptr [0], 0x33
0x000000000000005c:  75 11                   jne    0x6f
0x000000000000005e:  D9 05 00 00 00 00       fld    dword ptr [0]
0x0000000000000064:  D9 1D 00 00 00 00       fstp   dword ptr [0]
0x000000000000006a:  E9 30 00 00 00          jmp    0x9f

0x000000000000006f:  80 3D 00 00 00 00 34    cmp    byte ptr [0], 0x34
0x0000000000000076:  75 11                   jne    0x89
0x0000000000000078:  D9 05 00 00 00 00       fld    dword ptr [0]
0x000000000000007e:  D9 1D 00 00 00 00       fstp   dword ptr [0]
0x0000000000000084:  E9 30 00 00 00          jmp    0xb9

0x0000000000000089:  80 3D 00 00 00 00 35    cmp    byte ptr [0], 0x35
0x0000000000000090:  75 11                   jne    0xa3
0x0000000000000092:  D9 05 00 00 00 00       fld    dword ptr [0]
0x0000000000000098:  D9 1D 00 00 00 00       fstp   dword ptr [0]
0x000000000000009e:  E9 30 00 00 00          jmp    0xd3

0x00000000000000a3:  80 3D 00 00 00 00 36    cmp    byte ptr [0], 0x36
0x00000000000000aa:  75 11                   jne    0xbd
0x00000000000000ac:  D9 05 00 00 00 00       fld    dword ptr [0]
0x00000000000000b2:  D9 1D 00 00 00 00       fstp   dword ptr [0]
0x00000000000000b8:  E9 30 00 00 00          jmp    0xed

0x00000000000000bd:  80 3D 00 00 00 00 37    cmp    byte ptr [0], 0x37
0x00000000000000c4:  75 11                   jne    0xd7
0x00000000000000c6:  D9 05 00 00 00 00       fld    dword ptr [0]
0x00000000000000cc:  D9 1D 00 00 00 00       fstp   dword ptr [0]
0x00000000000000d2:  E9 30 00 00 00          jmp    0x107

0x00000000000000d7:  80 3D 00 00 00 00 38    cmp    byte ptr [0], 0x38
0x00000000000000de:  75 11                   jne    0xf1
0x00000000000000e0:  D9 05 00 00 00 00       fld    dword ptr [0]
0x00000000000000e6:  D9 1D 00 00 00 00       fstp   dword ptr [0]
0x00000000000000ec:  E9 30 00 00 00          jmp    0x121

0x00000000000000f1:  D9 05 00 00 00 00       fld    dword ptr [0]
0x00000000000000f7:  D9 1D 00 00 00 00       fstp   dword ptr [0]
0x00000000000000fd:  E9 1F 00 00 00          jmp    0x121

0x0000000000000102:  E8 00 00 00 00          call   0x107
0x0000000000000107:  D9 05 00 00 00 00       fld    dword ptr [0]
0x000000000000010d:  D8 25 00 00 00 00       fsub   dword ptr [0]
0x0000000000000113:  D8 C9                   fmul   st(1)
0x0000000000000115:  D8 05 00 00 00 00       fadd   dword ptr [0]
0x000000000000011b:  D9 1D 00 00 00 00       fstp   dword ptr [0]
0x0000000000000121:  50                      push   eax
0x0000000000000122:  B8 01 00 00 00          mov    eax, 1
0x0000000000000127:  A3 00 00 00 00          mov    dword ptr [0], eax
0x000000000000012c:  B8 BE 00 00 00          mov    eax, 0xbe
0x0000000000000131:  A3 00 00 00 00          mov    dword ptr [0], eax
0x0000000000000136:  A3 00 00 00 00          mov    dword ptr [0], eax
0x000000000000013b:  A3 00 00 00 00          mov    dword ptr [0], eax
0x0000000000000140:  58                      pop    eax
0x0000000000000141:  E8 00 00 00 00          call   0x146
0x0000000000000146:  83 3D 00 00 00 00 00    cmp    dword ptr [0], 0
0x000000000000014d:  75 20                   jne    0x16f
0x000000000000014f:  50                      push   eax
0x0000000000000150:  A1 00 00 00 00          mov    eax, dword ptr [0]
0x0000000000000155:  A3 00 00 00 00          mov    dword ptr [0], eax
0x000000000000015a:  A1 00 00 00 00          mov    eax, dword ptr [0]
0x000000000000015f:  A3 00 00 00 00          mov    dword ptr [0], eax
0x0000000000000164:  A1 00 00 00 00          mov    eax, dword ptr [0]
0x0000000000000169:  A3 00 00 00 00          mov    dword ptr [0], eax
0x000000000000016e:  58                      pop    eax
0x000000000000016f:  D9 05 00 00 00 00       fld    dword ptr [0]
0x0000000000000175:  D8 35 00 00 00 00       fdiv   dword ptr [0]
0x000000000000017b:  D8 0D 00 00 00 00       fmul   dword ptr [0]
0x0000000000000181:  D9 E0                   fchs   
0x0000000000000183:  D8 05 00 00 00 00       fadd   dword ptr [0]
0x0000000000000189:  D9 1D 00 00 00 00       fstp   dword ptr [0]
0x000000000000018f:  D9 05 00 00 00 00       fld    dword ptr [0]
0x0000000000000195:  D8 35 00 00 00 00       fdiv   dword ptr [0]
0x000000000000019b:  D8 0D 00 00 00 00       fmul   dword ptr [0]
0x00000000000001a1:  D9 E0                   fchs   
0x00000000000001a3:  D8 05 00 00 00 00       fadd   dword ptr [0]
0x00000000000001a9:  D9 1D 00 00 00 00       fstp   dword ptr [0]
0x00000000000001af:  D9 EE                   fldz   
0x00000000000001b1:  D8 1D 00 00 00 00       fcomp  dword ptr [0]
0x00000000000001b7:  9B                      wait   
0x00000000000001b8:  DF E0                   fnstsw ax
0x00000000000001ba:  9E                      sahf   
0x00000000000001bb:  74 1E                   je     0x1db
0x00000000000001bd:  D9 05 00 00 00 00       fld    dword ptr [0]
0x00000000000001c3:  D8 35 00 00 00 00       fdiv   dword ptr [0]
0x00000000000001c9:  D8 0D 00 00 00 00       fmul   dword ptr [0]
0x00000000000001cf:  D8 05 00 00 00 00       fadd   dword ptr [0]
0x00000000000001d5:  D9 1D 00 00 00 00       fstp   dword ptr [0]
0x00000000000001db:  DD 25 00 00 00 00       frstor dword ptr [0]
0x00000000000001e1:  E9 00 00 00 00          jmp    0x1e6
  <Relocation>
      <FromVirtualAddress>004A56B9</FromVirtualAddress>
      <ToVirtualAddress>988700</ToVirtualAddress>
      <Type>0x0014</Type>
   </Relocation>

  <BinaryPatch>
      <VirtualAddress>0x00A0D308</VirtualAddress>
      <Data>
     00000000
      </Data>
   </BinaryPatch>

  <BinaryPatch>
      <VirtualAddress>0x00A0D30C</VirtualAddress>
      <Data>
     0AD7233C
      </Data>
   </BinaryPatch>

  <BinaryPatch>
      <VirtualAddress>0x00A0D314</VirtualAddress>
      <Data>
     CDCC4C3E
      </Data>
   </BinaryPatch>

  <BinaryPatch>
      <VirtualAddress>0x00A0D31C</VirtualAddress>
      <Data>
     CDCC4C3E
      </Data>
   </BinaryPatch>

  <BinaryPatch>
      <VirtualAddress>0x00A0D324</VirtualAddress>
      <Data>
     CDCC4C3E
      </Data>
   </BinaryPatch>

  <BinaryPatch>
      <VirtualAddress>0x00A0D32C</VirtualAddress>
      <Data>
     0000803E
      </Data>
   </BinaryPatch>

  <BinaryPatch>
      <VirtualAddress>0x00A0D330</VirtualAddress>
      <Data>
     00004040
      </Data>
   </BinaryPatch>

  <BinaryPatch>
      <VirtualAddress>0x00A0D334</VirtualAddress>
      <Data>
     00008040
      </Data>
   </BinaryPatch>

  <BinaryPatch>
      <VirtualAddress>0x00A0D338</VirtualAddress>
      <Data>
     0000A040
      </Data>
   </BinaryPatch>

  <BinaryPatch>
      <VirtualAddress>0x00A0D33C</VirtualAddress>
      <Data>
     0000C040
      </Data>
   </BinaryPatch>

  <BinaryPatch>
      <VirtualAddress>0x00A0D340</VirtualAddress>
      <Data>
     0000E040
      </Data>
   </BinaryPatch>

  <BinaryPatch>
      <VirtualAddress>0x00A0D344</VirtualAddress>
      <Data>
     0AD7233C
      </Data>
   </BinaryPatch>

   <Relocation>
      <FromVirtualAddress>988702</FromVirtualAddress>
      <ToVirtualAddress>00A0D0A0</ToVirtualAddress>
      <Type>0006</Type>
   </Relocation>

   <Relocation>
      <FromVirtualAddress>988708</FromVirtualAddress>
      <ToVirtualAddress>0040E9C0</ToVirtualAddress>
      <Type>0006</Type>
   </Relocation>

   <Relocation>
      <FromVirtualAddress>98871E</FromVirtualAddress>
      <ToVirtualAddress>00A0D304</ToVirtualAddress>
      <Type>0006</Type>
   </Relocation>

   <Relocation>
      <FromVirtualAddress>98872C</FromVirtualAddress>
      <ToVirtualAddress>00A0D304</ToVirtualAddress>
      <Type>0006</Type>
   </Relocation>

   <Relocation>
      <FromVirtualAddress>988742</FromVirtualAddress>
      <ToVirtualAddress>00A0D304</ToVirtualAddress>
      <Type>0006</Type>
   </Relocation>

   <Relocation>
      <FromVirtualAddress>988750</FromVirtualAddress>
      <ToVirtualAddress>00A0D304</ToVirtualAddress>
      <Type>0006</Type>
   </Relocation>

   <Relocation>
      <FromVirtualAddress>988757</FromVirtualAddress>
      <ToVirtualAddress>00A0D304</ToVirtualAddress>
      <Type>0006</Type>
   </Relocation>

标签: assemblyx86reverse-engineeringx87

解决方案


使用绝对地址0很奇怪,大概有某种重定位来修复这些地址。但是你的反汇编并没有显示出来。如果它是标准的对象文件格式,您可以使用它objdump -dr -Mintel foo.o来包含重定位元数据。

但无论如何,它用于fnsave转储 x87 FPU 状态。

可能后面的地址具有不同的重定位修复元数据,即使它们都[0]在您转储的代码中。fsave 区域的开头获取,从该位置到/ 4 个字节FPUControlWord是没有意义的。fldfstp

几乎可以肯定fld dword ptr [0]/在其他 2 个位置之间fstp dword ptr [0]复制一个float值,而不是将 FPU 控制和状态字加载/存储到位,作为 4 字节单精度float。(如果数据表示 NaN,可能会修改数据。) 因此我们必须得出结论,每种[0]寻址模式实际上可以是任何地址,无论是否在 fsave 区域内。(fsave 区域中的浮点数将采用 80 位 x87 格式,而不是 32 位(dword)单精度,因此fld dword不太可能对它们进行操作。)

with 0x33 .. 0x38 可能正在查看 x87 状态字的cmp一个字节,也许是为了找出保存区域中的哪个插槽是当前的栈顶?不,状态字位不在字节的底部。但比较结果(C2、C1、C0)位于状态字( http://www.ray.masmcode.com/tutorial/fpuchap1.htm )的高字节的底部,以及异常状态位在低字节的底部。

因此,这条比较/分支链可能正在 fsave 区域中寻找某些东西。 或者更有可能它只是检查游戏数据某个字节的几个可能值之一。 请注意它如何在不等于时跳转到下一个 cmp/jne。 所以这是if/else链,或者是实现switch/ case 0x33:/ case 0x34:/ ... 语句的一种方式。

整个事情周围的fnsave/frstor可能是一条红鲱鱼,它可能根本不在那个数据中。相反,它可能只是保存/恢复 FPU 状态,因此它可以使用 x87 指令本身而不会弄乱主程序。我最初认为它是因为[0]地址而读取了保存区域,但似乎很明显,重定位可能会将该地址指向程序数据的其他部分,而不仅仅是这个补丁自己的私有存储。


推荐阅读