# ASISCTF Finals 2015: Fake
----------## Challenge details| Contest        | Challenge     | Category  | Points ||:---------------|:--------------|:----------|-------:|| ASISCTF Finals 2015 | Fake | Reversing |    150 |
**Description:**>*Find the flag in this [file](challenge/fake).*
----------## Write-up
We're dealing with another 64-bit ELF keygen challenge this time consisting of a rather small binary with the following pseudocode:
```c__int64 __fastcall main_routine(signed int a1, __int64 a2){  __int64 v2; // r8@1  __int64 v4; // [sp+0h] [bp-38h]@3  __int64 v5; // [sp+8h] [bp-30h]@3  __int64 v6; // [sp+10h] [bp-28h]@3  __int64 v7; // [sp+18h] [bp-20h]@3  __int64 v8; // [sp+20h] [bp-18h]@3
  v2 = 0LL;  if ( a1 > 1 )    v2 = strtol(*(const char **)(a2 + 8), 0LL, 10);  v4 = 0x3CC6C7B7 * v2;  v5 = 0x981DDEC9AB2D9LL     * ((v2 >> 19)      - 0xB15 * (((signed __int64)((unsigned __int128)(0x5C66DE85BAE10C8BLL * (v2 >> 19)) >> 64) >> 10) - (v2 >> 63)))     * ((v2 >> 19)      - 0x23 * (((signed __int64)((unsigned __int128)(0xEA0EA0EA0EA0EA1LL * (v2 >> 19)) >> 64) >> 1) - (v2 >> 63)))     * ((v2 >> 19)      - 0x21 * (((signed __int64)((unsigned __int128)(0xF83E0F83E0F83E1LL * (v2 >> 19)) >> 64) >> 1) - (v2 >> 63)));  v6 = ((v2 >> 19)      - 0x25AB * (((signed __int64)((unsigned __int128)(0x1B2F55AB6B39F429LL * (v2 >> 19)) >> 64) >> 10) - (v2 >> 63)))     * 0x148E0E2774AE66LL     * ((v2 >> 19)      - 0xA7 * (((signed __int64)((unsigned __int128)(0x621B97C2AEC12653LL * (v2 >> 19)) >> 64) >> 6) - (v2 >> 63)));  v7 = ((v2 >> 19)      - 0x101 * (((signed __int64)((unsigned __int128)(0x7F807F807F807F81LL * (v2 >> 19)) >> 64) >> 7) - (v2 >> 63)))     * 0x25FB3FE64A952LL     * ((v2 >> 19)      - 0x37 * (((signed __int64)((unsigned __int128)(0x4A7904A7904A7905LL * (v2 >> 19)) >> 64) >> 4) - (v2 >> 63)));  v8 = ((v2 >> 19)      - 0xBC8F * (((signed __int64)((unsigned __int128)(0x15B90241024BDECDLL * (v2 >> 19)) >> 64) >> 12) - (v2 >> 63)))     * 0x246DC95E05ELL     * ((v2 >> 19)      - 0x17      * (((signed __int64)((v2 >> 19) + ((unsigned __int128)(0x0B21642C8590B2165LL * (v2 >> 19)) >> 64)) >> 4)       - (v2 >> 63)));  puts((const char *)&v4;;  return 0LL;}```
So we have a 'mystery routine' which converts our numeric input into our flag (it has to since our input can only be numeric and a single `puts` call is all we have for output). The routine, converted to python by hand, does this as follows:
```pythondef mystery(v2):    int64 =  2**64  int128 = 2**128
  v4 = (0x3CC6C7B7 * v2) % int64
  a = ((v2 >> 19) - (0xB15 * (( ((((0x5C66DE85BAE10C8B * (v2 >> 19)) % int128) >> 64) % int64) >> 10) - (v2 >> 63))))  b = ((v2 >> 19) - (0x23 * (( ((((0xEA0EA0EA0EA0EA1 * (v2 >> 19)) % int128) >> 64) % int64) >> 1) - (v2 >> 63))))  c = ((v2 >> 19) - (0x21 * (( ((((0xF83E0F83E0F83E1 * (v2 >> 19)) % int128) >> 64) % int64) >> 1) - (v2 >> 63))))   v5 = (0x981DDEC9AB2D9 * a * b * c) % int64
  a = ((v2 >> 19) - (0x25AB * (( ((((0x1B2F55AB6B39F429 * (v2 >> 19)) % int128) >> 64) % int64) >> 10) - (v2 >> 63))))  b = 0x148E0E2774AE66  c = ((v2 >> 19) - (0xA7 * (( ((((0x621B97C2AEC12653 * (v2 >> 19)) % int128) >> 64) % int64) >> 6) - (v2 >> 63))))
  v6 = (a * b * c) % int64
  a = ((v2 >> 19) - (0x101 * (( ((((0x7F807F807F807F81 * (v2 >> 19)) % int128) >> 64) % int64) >> 7) - (v2 >> 63))))  b = 0x25FB3FE64A952  c = ((v2 >> 19) - (0x37 * (( ((((0x4A7904A7904A7905 * (v2 >> 19)) % int128) >> 64) % int64) >> 4) - (v2 >> 63))))
  v7 = (a * b * c) % int64
  a = ((v2 >> 19) - (0xBC8F * (( ((((0x15B90241024BDECD * (v2 >> 19)) % int128) >> 64) % int64) >> 12) - (v2 >> 63))))  b = 0x246DC95E05E  c = ((v2 >> 19) - (0x17 * (( ((((0x0B21642C8590B2165 * (v2 >> 19)) % int128) >> 64) % int64) >> 4) - (v2 >> 63))))
  v8 = (a * b * c) % int64
  y = [v4, v5, v6, v7, v8]
  z = "".join([pack('