1

Here is the Ghidra decompiler output for a crackme problem. Specifically, this one:
Code:

undefined8 entry(undefined8 param_1,char *param_2)
{
  int iVar1;
  size_t sVar2;
  char *pcVar3;
  char *pcVar4;
  char local_118 [9];
  char local_10f;
  long local_10;

  local_10 = *(long *)___stdinp;
  _strcspn("Enter the password...\n",param_2);
  _printf(local_118,0x100,*(undefined8 *)_fgets);
  pcVar3 = "\n";
  sVar2 = _strlen(local_118);
  pcVar4 = local_118;
  local_118[sVar2] = '\0';
  iVar1 = dyld_stub_binder();
  if (iVar1 == 10) {
    if (local_118[0] == local_10f) {
      _strcspn("Correct!\nthe password is: %s\n",local_118);
    }
    else {
      _wrong_password(pcVar4,pcVar3);
    }
  }
  else {
    _wrong_password(pcVar4,pcVar3);
  }
  if (*(long *)___stdinp == local_10) {
    return 0;
  }

I'm having some trouble understanding the output.

  1. the printf and strcspn functions seem to be switched?
  2. the local_10f variable is never initialized, and yet is still used to compare to the passcode.
  3. I know from reading the solution, that as long as the first and last characters are the same, and the length is 10, then the passcode will work. How does "dyld_stub_binder" check for length? Where do the first and last characters get compared?

Thanks for any help.

1 Answer 1

2

It seems like your Ghidra decompilation went wrong. Are you using the last version of Ghidra?

The output that I get in the latest version is:

undefined8 entry(void)

{
  size_t sVar1;
  char local_118 [9];
  char local_10f;
  long local_10;

  local_10 = *(long *)___stack_chk_guard;
  _printf("Enter the password...\n");
  _fgets(local_118,0x100,*(FILE **)___stdinp);
  sVar1 = _strcspn(local_118,"\n");
  local_118[sVar1] = '\0';
  sVar1 = _strlen(local_118);
  if ((int)sVar1 == 10) {
    if (local_118[0] == local_10f) {
      _printf("Correct!\nthe password is: %s\n",local_118);
    }
    else {
      _wrong_password();
    }
  }
  else {
    _wrong_password();
  }
  if (*(long *)___stack_chk_guard == local_10) {
    return 0;
  }
                    /* WARNING: Subroutine does not return */
  ___stack_chk_fail();
}

Which makes much more sense. I would guess that your Ghidra version has some problems with parsing the plt/imports. Upgrade to the latest version and check again.

As for your second question: When you don't understand the decompilation, you should always go to the disassembly.

   100000e42        MOVSX      EAX,byte ptr [RBP + local_118]

   100000e49        MOVSX      ECX,byte ptr [RBP + local_10f]

   100000e50        CMP        EAX,ECX

You can see that there is a compersion between two bytes from the stack.

In this case RBP + local_118 is the pointer to the stack location of the user string. 0x118 - 0x10f = 9 => You are looking at the last character (index 9 of the string is the 10th character). So the comparison is between the first and the last char.

3
  • I just installed yesterday, but after reinstalling it worked! Thanks for your help. (I also disabled MacOS's "protection" for opening programs from the internet). How do you know that local_10f is indeed 0x10f?
    – robert
    Dec 29, 2019 at 22:04
  • You can see it in the beginning of the function, just below the signature. Dec 30, 2019 at 8:35
  • It looks like the issue is with Ghidra 9.1.1, actually. I had to downgrade to 9.1 to get the sensible version of this code. I'm so glad I came across this post, I had no idea what I was seeing. Jan 30, 2020 at 4:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.