在ac编译的二进制文件中查找密码

逆向工程 部件 反编译
2021-06-29 23:05:41

我目前正在学习使用 Cutter 对二进制文件进行一些基本的逆向工程。我正在努力测试作为参数输入的密码是否正确的程序,如果不正确,则返回错误消息。我在组装中有一些严重的差距,我无法弄清楚这个的密码。我已经研究了一段时间,但到了我被卡住的地步..

这是反编译的代码,密码的测试发生在 while/if 迭代期间,所以之前的内容只是为了提供一些上下文。

undefined4 main(int param_1,int param_2){
    undefined4 uVar1;
    size_t sVar2;
    undefined4 local_21;
    undefined4 local_1d;
    undefined local_19;
    char *local_18;
    int local_14;
    undefined4 *local_10;

    local_10 = &param_1;
    local_14 = 0;
    if (param_1 == 2) {
          local_21 = 0x776f7264;
          local_1d = 0x70617373;
          local_19 = 0;
          local_18 = *(char **)(param_2 + 4);
          sVar2 = strlen(local_18);
          if (sVar2 < 8) {
                uVar1 = 0xffffffff;
          }
          else {
                while (local_14 < 8) {
                      if ((int)local_18[local_14] + 1 != (int)*(char                   
                          *)((int)&local_21 + local_14)) {
                              puts("Wrong password.");
                              return 0xffffffff;
                      }
                      local_14 = local_14 + 1;
                }
                puts("Access granted.");
                uVar1 = 0;
                }
          }
    else {
          puts("One and only one argument PLS.");
          uVar1 = 0xffffffff;
    }
    return uVar1;
}

更新 1,我从我的猜测和其他人的帮助中了解到的:

  • 如果给定的密码少于 8 个字符,程序不会返回任何错误消息。(如果 >=8 表示密码不正确)。我确实认为密码必须是 8 个字符。

  • 密码可能是十六进制的。我为什么这么认为?密码验证过程中使用的 var (local_21 = 776f7264 = word) 正好是 8 个字符,我们在验证中迭代了 8 次。

  • 由于我们正在测试 (local_18[local_14] + 1) 我输入的参数 local_18 和在 while 结束时递增的迭代器 local_14 ,因此涉及某种转换。据我所知,它会改变我输入的密码,它需要与 (int)*(char *)((int)&local_21 + local_14)) 相同,但我不知道它是什么.

  • 所以如果我的虽然是正确的,我需要找到一个 8 字符的十六进制,我将从中移动字符(例如用 a 替换 b)以匹配我要翻译的内容 " (int)*(char *)( (int)&local_21 + local_14))"

我试图找出我是否正确..

更新 2,这是程序集树的屏幕放大while 部分

我也在下面评论了它,但正如你所看到的,有一些部分我无法理解发生了什么:

VARS : 
local_21 = 0x776f7264 ; (String) word used in password comparaison
local_1d = 0x70617373 ;(String) pass but unused
local_14 = 0 ;iterator
local_18 = argv[1] (it's the string given as an argument, let's 
           assume i've entered "examples")

- mov edx, dword [local_14] -->  load the value of local_14 into edx 
                                 local_14 = 0

- mov eax, dword[local_18] --> load the function argument into the 
                               register 
                               local_18 = examples


- add eax, edx --> add the value 0 to our password (does it means we 
                   add 0 to the address of our input or directly to 
                   the input ?)

- movzx eax, byte[eax] --> get the first character in eax (is he 
                           taking the hexa character 7 ?

- movsx eax, al --> ?

- lea ecx, [eax + 1] --> load the address of [eax+1] into eax (don't 
                         know what is in eax+1..)

- lea edx, [local_21] --> load the address of local_21 in edx
                          it is 0x776f7264 so what does it stock ? Do 
                          I considerer this as a value or as an 
                          address?

- mov eax, dword[local_14] --> load the value of local_14 (0) into 
                             eax, so 0x0 ?

- add eax, edx -> we add local_14 (0) to eax, so do we have 0x776f7264

- movzx eax, byte[eax] --> exact same thing as before.

- movsx eax, al --> same as before

- cmp ecx, eax --> we compare ecx et eax (eax=?, ecx = [eax+1] = ?)

- add dword [local_14], 1 --> we add 1 to (local_14), it became 1 (our 
                            iterator)

- cmp dword [local-14], 7 --> we compare our iterator with with 7, if 
                              it is lower we continue 

- we start again from the start 

我无法理解 0x776f7264 实际上是地址还是 eax 中的值。所以当我加 1 时,实际发生了什么(2,3 等等)?我是直接将它添加到六边形还是考虑将其添加到字符中?像 77 = w 所以我在 w 上加 1,它给了我 x

如果我没有很好地解释我的问题,我真的很抱歉,我会尽力回答有关我的帖子的任何问题。

非常感谢,祝你有美好的一天!

1个回答

你的一些观察是正确的,有些则不是。

我们来分析一下:

  • local_14确实是一个循环迭代器,所以 while 循环实际上是一个for运行 8 次迭代的循环。您可以尝试将该变量重命名为i以便更清晰。
  • local_18是用户输入,就像您观察到的那样,长度应为 8;否则检查失败。
  • 反编译器无法推断是什么local_21并将其显示为整数。但是,我们可以看到它local_18与它进行了比较(local_14用作该缓冲区的索引),因此它char毕竟可能是一个缓冲区。此外,我们知道的比较local_18local_218个字节长-所以这是怎么回事?反编译有时可能会产生误导,这是一个例子:注意local_21local_1d在堆栈上是连续的(我提醒你,向后增长)所以它们实际上是char一个大小为 8 的缓冲区。编译器将它们都初始化作为整数,因为这是这样做的优化方式。请注意,0x776f72640x70617373是 ASCII 字符串,这是逆向工程经验带来的观察结果。这只是一个大小为 8 的简单“memcmp”;很难看到,因为那里的铸造过多。

顺便说一句,密码不是十六进制的,这就是数据在内存中的存储方式。值的解释取决于上下文。

希望能帮助到你。