【问题标题】:How do I interpret this disassembled code in IDA?如何在 IDA 中解释这个反汇编代码?
【发布时间】:2022-01-23 18:04:49
【问题描述】:

我正在处理“找出密码”类型的问题,并相信我找到了有问题的功能。我正在努力的是了解他们正在发生的事情。

int __cdecl __noreturn main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rdx
  char *s; // [rsp+18h] [rbp-18h]

  if ( ptrace(PTRACE_TRACEME, 0LL, 1LL, 0LL) < 0 )
    exit(1);
  if ( argc != 2 )
    exit(2);
  s = (char *)argv[1];
  if ( strlen(s) != 8 )
    exit(3);
  if ( checkpw((__int64)s, 0LL, v3, (__int64)s) )
  {
    puts("Invalid Password!");
    exit(4);
  }
  puts("Correct Password!");
  exit(0);
}

我相信上面的主命令,密码参数(函数的第二个参数 - 第一个命令行参数)存储在“s”中。它的长度为 8,因此 checkpw 正在其值上运行。

我在这行中没有真正关注的内容:

  if ( checkpw((__int64)s, 0LL, v3, (__int64)s) )

不确定它实际上传递给 checkpw 的是什么(但我假设在原始程序中,它是 s 本身。

_BOOL8 __fastcall checkpw(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
  unsigned __int8 v5; // cl
  char v6; // cl
  _BOOL8 result; // rax

  result = 1;
  if ( (*(_BYTE *)a4 ^ 0x52) == 17 && *(_BYTE *)(a4 + 7) == 35 )
  {
    v5 = *(_BYTE *)(a4 + 1);
    if ( (v5 ^ *(_BYTE *)(a4 + 2)) == 64 && v5 == 115 )
    {
      v6 = *(_BYTE *)(a4 + 3);
      if ( v6 > 35 && !__OFADD__(91, v6) && (*(_BYTE *)(a4 + 4) ^ 0xF3) == 0xC7 && (*(_WORD *)(a4 + 5) ^ 0x4C47) == 4660 )
        return 0;
    }
  }
  return result;
}

还试图理解这一切在原始字符串的上下文中到底意味着什么:

if ( (*(_BYTE *)a4 ^ 0x52) == 17 && *(_BYTE *)(a4 + 7) == 35 )
  {
    v5 = *(_BYTE *)(a4 + 1);
    if ( (v5 ^ *(_BYTE *)(a4 + 2)) == 64 && v5 == 115 )
    {
      v6 = *(_BYTE *)(a4 + 3);
      if ( v6 > 35 && !__OFADD__(91, v6) && (*(_BYTE *)(a4 + 4) ^ 0xF3) == 0xC7 && (*(_WORD *)(a4 + 5) ^ 0x4C47) == 4660 )
        return 0;
    }

有人可以帮忙吗(可能有一个 s 值的例子?

【问题讨论】:

  • 我在问题中没有看到任何反汇编,只是大概是反编译的结果。您省略了实际的反汇编,以便人们可以看到反编译器正在查看的内容。

标签: c assembly disassembly decompiling ida


【解决方案1】:

看起来您正在查看反编译的输出。由于汇编中没有类型信息,反编译器似乎认为内存地址只是普通整数。

char *s; // [rsp+18h] [rbp-18h] 表明s 是存储字符串的地址。 if ( strlen(s) != 8 ) exit(3); 表示s 中字符串的长度应为8,否则程序将退出并返回错误码3

if ( checkpw((__int64)s, 0LL, v3, (__int64)s) )这里s地址传给checkpw,不是值,不知道为什么传了两次。

checkpw的正文,

_BOOL8 __fastcall checkpw(__int64 a1, __int64 a2, __int64 a3, __int64 a4)
{
  unsigned __int8 v5; // cl
  char v6; // cl
  _BOOL8 result; // rax

  result = 1;
  if ( (*(_BYTE *)a4 ^ 0x52) == 17 && *(_BYTE *)(a4 + 7) == 35 )
  {
    v5 = *(_BYTE *)(a4 + 1);
    if ( (v5 ^ *(_BYTE *)(a4 + 2)) == 64 && v5 == 115 )
    {
      v6 = *(_BYTE *)(a4 + 3);
      if ( v6 > 35 && !__OFADD__(91, v6) && (*(_BYTE *)(a4 + 4) ^ 0xF3) == 0xC7 && (*(_WORD *)(a4 + 5) ^ 0x4C47) == 4660 )
        return 0;
    }
  }
  return result;
}

第一个参数a1 甚至没有被使用,所以你可以忽略第一个s 传递给a1

我无法在checkpw 的正文中为您完成所有反编译的按位逻辑,但是如果您拿起程序员的计算器并在查看十六进制和二进制转储时使用一些可能的输入进行测试,您可能会找到提示。

另外,看看 ASCII 表,它会帮助你理解checkpw 在做什么。它似乎正在将字符串中的每个字符与某个 ASCII 值进行一系列直接比较,以检查密码是否正确。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    • 2022-12-04
    • 2012-06-26
    • 2014-09-30
    • 1970-01-01
    相关资源
    最近更新 更多