组装 - 二元炸弹混淆

逆向工程 部件 x86 二进制
2021-07-04 13:03:27

我有一个对二进制文件进行逆向工程的作业。我要使用的函数接受一个字符串输入并一次读取一个字符。如下(删除了push/pop寄存器):


 8048b6e: mov    $0x8049ee9,%esi 
 8048b73: movzbl (%esi),%edx ; (%esi) = 0x654A6167
 8048b76: test   %dl,%dl
 8048b78: je     8048bb2 
 8048b7a: mov    0x8(%ebp),%ebx
 8048b7d: mov    $0x16,%edi
 8048b82: movzbl (%ebx),%eax
 8048b85: sub    $0x61,%eax
 8048b88: cmp    $0x19,%al
 8048b8a: ja     8048b97 
 8048b8c: mov    %edi,%ecx
 8048b8e: sub    %al,%cl
 8048b90: mov    %ecx,%eax
 8048b92: jns    8048b97 
 8048b94: add    $0x1a,%eax
 8048b97: add    $0x61,%eax
 8048b9a: cmp    %al,%dl
 8048b9c: je     8048ba3 
 8048b9e: call   8048e18 
 8048ba3: add    $0x1,%esi
 8048ba6: movzbl (%esi),%edx
 8048ba9: test   %dl,%dl
 8048bab: je     8048bb2 
 8048bad: add    $0x1,%ebx
 8048bb0: jmp    8048b82 

我在理解一部分(8048b85 以后)的逻辑时遇到了一些麻烦,所以我将其转换为 C


eax = *ebx;                                 // movzbl (%ebx),%eax
eax -= 97;                                  // sub    $0x61,%eax

// cmp    $0x19,%al
// ja     8048b97 <phase_3+0x32>
if((unsigned)(eax & 0xFF) < 25)
{
  ecx = edi;                                // mov    %edi,%ecx
  int cl = (eax & 0xFF) - (ecx & 0xFF);     // sub    %al,%cl
  ecx &= cl;
  eax = ecx;                                // mov    %ecx,%eax

  if(cl >= -127 && cl < 128)                // jns    8048b97
  {
    eax += 0x1A;                              // add    $0x1a,%eax
  }
}
eax += 97;                                  // add    $0x61,%eax
if((eax & 0xFF) != (edx & 0xFF))            // cmp    %al,%dl
{
  trigger_bomb();                           //  call   8048e18 <trigger_bomb>
}

我不确定我转换的内容是否正确。比较的第一个值是 0x67,它是 ascii 中的 g,它不会将 ja 的标志设置为 0x19 > 0x67 - 0x61。如果我尝试 0x67 - 0x1A 作为输入,因为它是无符号比较,它永远不会 < 25,因为它会溢出回 236。我想我需要使用一个负数,以便如果它溢出,它会变成 0x67 但是由于输入是 ascii,我不确定是否可以输入负值。

所以我的问题是我的逻辑哪里出了问题?我不希望得到答案,因为我需要弄清楚其他 3 个值,但我正在尝试的似乎并不正确。任何指针/建议将不胜感激。

谢谢

2个回答

可悲的是,问题是我自己的愚蠢.. 第一个问题,

int cl = (eax & 0xFF) - (ecx & 0xFF);

有围绕错误方式的论点(dest = dest - source not dest = source - dest)

其次是我对 JNS 指令的困惑。我将它误解为有符号字节而不是符号标志,因此,

if(cl >= -127 && cl < 128)

应该写成

if(cl < 0)

经过一周的尝试解决这个问题后,答案很烦人:)

0x61是在ASCII表的公知的值它所对应的a字符。而且,事实上,当您遇到:

8048b85: sub    $0x61,%eax

这通常意味着您将字符从通常的可打印字符间隔向下移动到不可打印字符值。

我没有深入研究你的代码,但我真的怀疑这里所做的是将 ASCII 文本编码为一组不可打印的字符。

但是,这只是一个疯狂的猜测(不到 5 分钟)。所以,如果我错了就打我!:-)