# Grip (rev)

{% file src="/files/66aSHFjL21KlRV6UdBsg" %}
Grippy binary file
{% endfile %}

This binary has an initialisation routine which involves printing `:3` followed by calling `exit()`. We can bypass the `exit()` call and allow the program to continue running by patching the call to `exit()` with some other instruction such as a `jmp`. This allows the program to continue executing the `main` function.

<figure><img src="/files/CVS9qTWiPCzc6VXBSdR2" alt="" width="557"><figcaption><p>Unpatched binary code</p></figcaption></figure>

<figure><img src="/files/daB50tvwcnyEC3O3Cgi1" alt="" width="563"><figcaption><p>Patched binary file</p></figcaption></figure>

The decompiled main code looks as follows:

```c
undefined8 main(void)

{
  undefined8 *puVar1;
  long in_FS_OFFSET;
  ulong local_d0;
  undefined8 local_b8;
  undefined8 local_b0;
  undefined8 local_a8;
  undefined8 local_a0;
  undefined8 local_98;
  undefined8 local_90;
  undefined8 local_88;
  undefined8 local_80;
  undefined8 local_78;
  undefined8 local_70;
  undefined8 local_68;
  undefined8 local_60;
  undefined8 local_58;
  undefined8 local_50;
  undefined8 local_48;
  undefined5 local_40;
  undefined3 uStack_3b;
  undefined5 uStack_38;
  undefined8 local_33;
  long local_20;
  
  local_20 = *(long *)(in_FS_OFFSET + 0x28);
  local_b8 = 0xb21e71ba177bbaa7;
  local_b0 = 0xf2f2dad7f679ba96;
  local_a8 = 0xba32c30ab77bbaf2;
  local_a0 = 0xcbd3d5c3d1dbd14a;
  local_98 = 0xc9c4c481d848bac3;
  local_90 = 0xba22b77bba84c0ef;
  local_88 = 0xc0efc94aba2aa77b;
  local_80 = 0xef48bad483dbd384;
  local_78 = 0xbacdc9c284de81d2;
  local_70 = 0x3516a77bba2eb77b;
  local_68 = 0xea19f2f2f2f23eb7;
  local_60 = 0x22f7b644fd3eb779;
  local_58 = 0x3eb779307bb00271;
  local_50 = 0xf33eb77122f7a67a;
  local_48 = 0xba621084e93e8f71;
  local_40 = 0xba960ab779;
  uStack_3b = 0xd7f6d9;
  uStack_38 = 0x86f2f2f2da;
  local_33 = 0x313bf2f2f2f21af7;
  for (local_d0 = 0; local_d0 < 0x8d; local_d0 = local_d0 + 1) {
    *(byte *)((long)&local_b8 + local_d0) = *(byte *)((long)&local_b8 + local_d0) ^ 0xf2;
  }
  puVar1 = (undefined8 *)mmap((void *)0x0,0x8d,6,0x22,-1,0);
  *puVar1 = local_b8;
  puVar1[1] = local_b0;
  puVar1[2] = local_a8;
  puVar1[3] = local_a0;
  puVar1[4] = local_98;
  puVar1[5] = local_90;
  puVar1[6] = local_88;
  puVar1[7] = local_80;
  puVar1[8] = local_78;
  puVar1[9] = local_70;
  puVar1[10] = local_68;
  puVar1[0xb] = local_60;
  puVar1[0xc] = local_58;
  puVar1[0xd] = local_50;
  puVar1[0xe] = local_48;
  puVar1[0xf] = CONCAT35(uStack_3b,local_40);
  *(ulong *)((long)puVar1 + 0x7d) = CONCAT53(uStack_38,uStack_3b);
  *(undefined8 *)((long)puVar1 + 0x85) = local_33;
  (*(code *)puVar1)();
  puts(":3");
  if (local_20 != *(long *)(in_FS_OFFSET + 0x28)) {
                    /* WARNING: Subroutine does not return */
    __stack_chk_fail();
  }
  return 0;
}
```

Essentially, the local variables represent the bytecode to be executed. The bytecode first undergoes an XOR decryption operation, then the bytecode is loaded into the memory at the address `puVar1` and executed.

I then set a breakpoint at the line where the bytecode is executed to see what the bytecode does. The bytecode basically writes characters into the stack then slowly decrypts them, giving us the flag: `akasec{sh1tty_p4ck3d_b1n4ry}`


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://elijahchia.gitbook.io/ctf-blog/akasec-ctf-24/grip-rev.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
