Finally an actual reverse engineering challenge. Analysis with `r2` and its Ghidra integration shows the following code: iVar1 = *(int64_t *)(in_FS_OFFSET + 0x28); sym.imp.puts("So you figured out how to provide input and command line arguments."); sym.imp.puts("But can you figure out what input to provide?"); if (argc == 5) { sym.string_to_int(argv[1], (int64_t)&var_ach); sym.string_to_int(argv[2], (int64_t)&var_ach + 4); sym.string_to_int(argv[3], (int64_t)&var_a4h); iVar2 = sym.is_invalid((uint64_t)(uint32_t)var_ach); if (iVar2 == 0) { iVar2 = sym.is_invalid((uint64_t)var_ach._4_4_); if (iVar2 == 0) { iVar2 = sym.is_invalid((uint64_t)var_a4h); if (iVar2 == 0) { if (var_a4h + var_ach._4_4_ * 100 + (uint32_t)var_ach * 10 == 0x3a4) { iVar2 = sym.imp.strcmp(argv[4], "chicken"); if (iVar2 == 0) { sym.imp.puts("Well, you found the arguments, but what\'s the password?"); sym.imp.fgets(&s, 0x80, _reloc.stdin); var_98h = (char *)sym.imp.strchr(&s, 10); if (var_98h != (char *)0x0) { *var_98h = '\0'; } var_9ch = sym.imp.strlen(&s); var_a0h = 0; while (var_a0h <= var_9ch) { if ((*(uint8_t *)((int64_t)&s + (int64_t)var_a0h) ^ 0x2a) != "ZFOKYO\nMC\\O\nLFKM*"[var_a0h]) { sym.imp.puts("I\'m sure it\'s just a typo. Try again."); uVar3 = 1; goto code_r0x00400bc7; } var_a0h = var_a0h + 1; } sym.imp.puts("Good job! You\'re ready to move on to bigger and badder rev!"); sym.print_flag(); uVar3 = 0; goto code_r0x00400bc7; } } } } } sym.imp.puts("Don\'t try to guess the arguments, it won\'t work."); uVar3 = 1; } else { sym.imp.puts("Make sure you have the correct amount of command line arguments!"); uVar3 = 1; } The following checks need to be bypassed: - Four arguments must be passed - The first three must be decimal digits - The last one must be "chicken" - Third digit is used as is - Second digit is multiplied by 100 - First digit is multiplied by 10 - The digits added together must be equal to `0x3a4` (932) The correct invocation is therefore `./taking_off 3 9 2 chicken`. At this stage the executable asks for a password, reads in user input, iterates over every character and compares it with the expected one after XORing with `0x2a`. The correct password can be decoded with `r2` as follows: r2 - [0x00000000]> w 'ZFOKYO\nMC\\O\nLFKM*' [0x00000000]> wox 0x2a [0x00000000]> px 0x20 - offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 0x00000000 0d70 6c65 6173 6520 6769 7665 2066 6c61 .please give fla 0x00000010 6700 0d2a 2a2a 2a2a 2a2a 2a2a 2a2a 2a2a g..************* Call the executable on the shell server with the same input to receive the flag: actf{th3y_gr0w_up_s0_f4st}