# unknown
Let's take a look at the binary:
```$	file unknown unknown: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=53ec94bd1406ec6b9a28f5308a92e4d906444edb, stripped$	./unknown Try again.$	./unknown gimme_flagStill nope.```
So this is a 64 bit elf, that appears to take input as an argument. Let's look at the code:
```signed __int64 __fastcall main(int argc, char **argv, char **a3){  signed __int64 result; // rax@2  unsigned int i; // [sp+14h] [bp-Ch]@5  char *argument; // [sp+18h] [bp-8h]@5
  if ( argc == 2 )  {    if ( strlen(argv[1]) == 56 )    {      argument = argv[1];      for ( i = 0; i < 0x38; ++i )      {        if ( (unsigned int)first_layer((__int64)argument, i) )          check = 1;      }      if ( check )        puts("Nope.");      else        printf("Congraz the flag is: %s\n", argument, argv);      result = 0LL;    }    else    {      puts("Still nope.");      result = 0xFFFFFFFELL;    }  }  else  {    puts("Try again.");    result = 0xFFFFFFFFLL;  }  return result;}```
So we can see here, it checks to see that the length of the first argument is 56 bytes. It then runs a for loop 56 (0x38) times in which it runs the function `first_layer` with the arguments being our input, and the iteration count. We see that it is ran in an if then statement, and if it is true `check` is set equal to one. We can see that if `check` is set equal to one, then we don't have the flag. So we need to make sure `first_layer` always outputs false. Let's take a look at `first_layer`:
```__int64 __fastcall first_layer(__int64 argument, __int64 i){  char *v2; // r15@1  __int64 v3; // rdx@1  int v4; // ebx@1  signed __int64 v5; // rcx@1  __int64 v6; // rax@3  int v7; // eax@3  char v9; // [sp+0h] [bp-8h]@1
  v2 = &v9 - 6004;  v3 = 0LL;  v4 = 0;  v5 = 0LL;  do  {    ++v5;    v4 += 666;  }  while ( v5 < 0x2F );  LOBYTE(v3) = *(_BYTE *)(argument + i);  *((_QWORD *)v2 + 1) = v3;  v6 = sub_400A1C((__int64)(v2 + 8), 1u);  v7 = __ROL4__((v4 + 35) * (unsigned __int64)sub_401BDD((const char *)(v6 + 24), 16), 21);  return v7 != (unsigned int)*(_QWORD *)((char *)&desired_output + 4 * i);}```
We can see there is a good bit going on here. However at the end of the day, that return value is all that matters. Let's set a breakpoint for that compare instruction in gdb (0x401f20) and see what the values are:
```gdb-peda$ b *0x401f20Breakpoint 1 at 0x401f20gdb-peda$ r 00000000000000000000000000000000000000000000000000000000Starting program: /Hackery/tuctf/unkown/unknown 00000000000000000000000000000000000000000000000000000000
[----------------------------------registers-----------------------------------]RAX: 0x63e13f5f RBX: 0x7a69 ('iz')RCX: 0x32449a7fdfab57a RDX: 0x0 RSI: 0x0 RDI: 0x7ffff7b85860 --> 0x2000200020002 RBP: 0x7fffffffdf30 --> 0x401ce0 (push   r15)RSP: 0x7fffffffdf00 --> 0x7fffffffdf30 --> 0x401ce0 (push   r15)RIP: 0x401f20 --> 0x1b80a74c839 R8 : 0x0 R9 : 0x0 R10: 0x7ffff7b84f60 --> 0x100000000 R11: 0x7ffff7b85860 --> 0x2000200020002 R12: 0x0 R13: 0x7fffffffe010 --> 0x2 R14: 0x7fffffffdf00 --> 0x7fffffffdf30 --> 0x401ce0 (push   r15)R15: 0x7fffffffc78c --> 0x0EFLAGS: 0x203 (CARRY parity adjust zero sign trap INTERRUPT direction overflow)[-------------------------------------code-------------------------------------]   0x401f0f:	rol    eax,0x15   0x401f12:	movabs rcx,0x401dac   0x401f1c:	mov    rcx,QWORD PTR [rcx+rsi*4]=> 0x401f20:	cmp    eax,ecx   0x401f22:	je     0x401f2e   0x401f24:	mov    eax,0x1   0x401f29:	mov    rsp,r14   0x401f2c:	pop    rbp[------------------------------------stack-------------------------------------]0000| 0x7fffffffdf00 --> 0x7fffffffdf30 --> 0x401ce0 (push   r15)0008| 0x7fffffffdf08 --> 0x401c82 (test   eax,eax)0016| 0x7fffffffdf10 --> 0x7fffffffe018 --> 0x7fffffffe345 ("/Hackery/tuctf/unkown/unknown")0024| 0x7fffffffdf18 --> 0x200400600 0032| 0x7fffffffdf20 --> 0xffffe010 0040| 0x7fffffffdf28 --> 0x7fffffffe363 ('0' <repeats 56 times>)0048| 0x7fffffffdf30 --> 0x401ce0 (push   r15)0056| 0x7fffffffdf38 --> 0x7ffff7a303f1 (<__libc_start_main+241>:	mov    edi,eax)[------------------------------------------------------------------------------]Legend: code, data, rodata, value
Breakpoint 1, 0x0000000000401f20 in ?? ()gdb-peda$ p $eax$1 = 0x63e13f5fgdb-peda$ p $ecx$2 = 0xfdfab57agdb-peda$ ```So the `eax` register hold the result of our input, and the `ecx` register holds the value that it is being compared against. We can tell this by the fact that `ecx` holds hex characters that are in `desired_output` when we check the data in it. In addition to that, when we go the next check, we see that the value in `ecx` changes while `eax` does not (all 56 bytes of our input were the same). This also tells us that the position of a specific character in our input doesn't change it's value.
Remember we need the function to output false, and the check is if the two values are not equal, so we need the two values to be equal.
So instead of going through and reversing this challenge, we can just skip that, look at  at if the values it is comparing it against, and the result of  what the output of characters we give it and use that to figure out what characters we need to in order to pass the checks.
Looking at the format of previous flags, we would probably have the eight characters `TUCTF{_}`, undercase characters and digits in the flag. It holds true with this. This is the output of all of those characters:
```alphabet:!:	0xba165ea7_:	0xff20bdef{:	0x59e2eb0d}:	0xef1b84cdq:	0x2c6485d5w:	0x5ed756d7e:	0xb623c6c1r:	0xcd78354et:	0xc863df45y:	0x12a92a61u:	0xb59d1071i:	0x67258d77o:	0x408a2c4bp:	0xf2184419l:	0x9239bdf3c:	0xf62c7f9bm:	0xd6338e84f:	0x388d98700:	0x63e13f5f1:	0x3ca8bfdc2:	0xdd0e6ec03:	0x5cfff0234:	0xceecc5ba5:	0xcc1be3176:	0x2ff351447:	0xc51f928e8:	0xb67059109:	0x26552da4T:  0xfdfab57aU:	0x032449a7C:  0x5f383821F:  0x25435e02```
here is the list of the 56 checks it does:
```checks:0xfdfab57a	TUCFT{0x032449a70x5f3838210xfdfab57a0x25435e020x59e2eb0d
0x5ed756d7 w3lc0m3_0x5cfff0230x9239bdf30xf62c7f9b0x63e13f5f0xd6338e840x5cfff0230xff20bdef
0xc51f928e 70_0x63e13f5f0xff20bdef
0xc51f928e 7uc7f_0xb59d10710xf62c7f9b0xc51f928e0x388d98700xff20bdef
0xceecc5ba 4nd_0xa952136b0x967108410xff20bdef
0xc51f928e 7th4nk_ check 70xf536dffd0xceecc5ba0xa952136b0xc5d7dac40xff20bdef
0x12a92a61 y0u_0x63e13f5f0xb59d10710xff20bdef
0x388d9870 f0r_0x63e13f5f0xcd78354e0xff20bdef
0xf2184419	p4r71c1p4y1n6!}0xceecc5ba0xcd78354e0xc51f928e0x3ca8bfdc0xf62c7f9b0x3ca8bfdc0xf21844190xceecc5ba0xc51f928e0x3ca8bfdc0xa952136b0x2ff351440xba165ea70xef1b84cd```
and putting all together (and skipping a lot of the reversing work):
```$	./unknown TUCTF{w3lc0m3_70_7uc7f_4nd_7h4nk_y0u_f0r_p4r71c1p471n6\!}Congraz the flag is: TUCTF{w3lc0m3_70_7uc7f_4nd_7h4nk_y0u_f0r_p4r71c1p471n6!}```
We had to add a backslack in order to escape the `!`. Just like that, we captured the flag!