[original](https://gist.github.com/cwgreene/5253cfa3904871535126b34ebbcb050f)# Defenit-2020 Mom's TouchWe download the binary and open it in ghidra.
```c
void entry(void)
{  __libc_start_main(FUN_08048840);  do {                    /* WARNING: Do nothing block with infinite loop */  } while( true );}```
This is actually not quite right; but we'll come back to that later.Proceeding to main we have
```c
undefined4 FUN_08048840(void)
{  char cVar1;  ssize_t sVar2;  size_t len;  char *local_1c;  char *__s;   FUN_080486b0();  puts("Mom Give Me The FLAG!");  __s = (char *)malloc(100);  if (__s == (char *)0x0) {    __s = "[*]Error : malloc()";  }  else {    sVar2 = read(0,__s,100);    if (-1 < sVar2) {      if (__s[sVar2 + -1] == '\n') {        __s[sVar2 + -1] = '\0';      }      len = strlen(__s);      if (len == 0x49) {        cVar1 = mainfunc(__s);        if (cVar1 == '\0') {          local_1c = "Try Again..";        }        else {          local_1c = "Correct! Mom! Input is FLAG!";        }        puts(local_1c);        free(__s);        return 0;      }      puts("Mom, Check the legnth..");                    /* WARNING: Subroutine does not return */      exit(0);    }    __s = "[*]Error : read()";  }  perror(__s);                    /* WARNING: Subroutine does not return */  exit(-1);}```
So we read the input, which should be 0x49 characters long,and then pass it against our verifier function `mainfunc`.
```c
undefined4 mainfunc(char *param_1)
{  uint uVar1;  int iVar2;  uint uVar3;  int iVar4;   iVar4 = 0;  do {    uVar1 = (&DAT_080492ac)[iVar4];    iVar2 = rand();    uVar3 = iVar2 + ((iVar2 / 0xff + (iVar2 >> 0x1f)) - (int)((longlong)iVar2 * 0x80808081 >> 0x3f))                    * -0xff;    if (((int)param_1[iVar4] ^ (&DAT_080492ac)[(uVar1 >> 4 | uVar1 << 4) & 0xff] ^        (&DAT_080492ac)[(uVar3 >> 2 | uVar3 * 4) & 0xff]) != (&DAT_08049144)[iVar4]) {      return 0;    }    iVar4 = iVar4 + 1;  } while (iVar4 < 0x49);  return 1;}```
So, we have two arrays, one, DAT_080492ac, which gets transformed with rand() and then xor'd with the input, and then gets comapred to the second array DAT_08049144. By simplearithmetic this means
```X = (&DAT_080492ac)[(uVar1 >> 4 | uVar1 << 4) & 0xff] ^        (&DAT_080492ac)[(uVar3 >> 2 | uVar3 * 4) & 0xff])param_1[i] = (&DAT_08049144)[iVar4]) ^ X ```
Visiting those array locations in Ghidra, however, reveals zero arrays. Strange,but no matter, we can break point in this function and read the values directlyout from memory using `gdb`. So something like this
```    for(int i = 0; i < 73;i++) {        int chr = array1[i];        int rnd =rand();        int uVar1 = rnd + ((rnd / 0xff + (rnd >> 0x1f)) - (int)((long long)rnd * 0x80808081 >> 0x3f)) * -0xff;        int d = array1[(chr >> 4 | chr << 4) & 0xff] ^ array1[(uVar1 >> 2 | uVar1 * 4) & 0xff] ^array2[i];        printf("%c",d);    }```
Since `srand()` isn't being called, we can just call `rand()` directly and, since it'sdeterministic, we will generate the same values. (This also answers the mysteryof how this is guaranteed to work, and not just sometimes).
However, this doesn't work. `srand()` is in fact being called. And we can find it usingghidra's XREFS. Which reveals this function.
```c
/* WARNING: Globals starting with '_' overlap smaller symbols at the same address */
void _INIT_1(void)
{  int iVar1;  int iVar2;   srand(0xff);  _DAT_080492a4 = rand();  _DAT_080492a4 =       _DAT_080492a4 +       ((_DAT_080492a4 / 0xff + (_DAT_080492a4 >> 0x1f)) -       (int)((longlong)_DAT_080492a4 * 0x80808081 >> 0x3f)) * -0xff;  iVar2 = -0x400;  do {    iVar1 = rand();    *(int *)(iVar2 + 0x80496ac) =         iVar1 + ((iVar1 / 0xff + (iVar1 >> 0x1f)) - (int)((longlong)iVar1 * 0x80808081 >> 0x3f)) *                 -0xff;    iVar2 = iVar2 + 4;  } while (iVar2 != 0);  return;}```
Ah! So **that's** how the arrays are getting populated! So we have additional callsto `rand` here, plus an initialization using `srand`. We'll need to add these callsto our deobfuscator.
```cint main() {    srand(0xff);    rand();    for(int j = 0; j < 256; j++) {        rand();     }    for(int i = 0; i < 73;i++) {        int chr = array1[i];        int rnd =rand();        int uVar1 = rnd + ((rnd / 0xff + (rnd >> 0x1f)) - (int)((long long)rnd * 0x80808081 >> 0x3f)) * -0xff;        int d = array1[(chr >> 4 | chr << 4) & 0xff] ^ array1[(uVar1 >> 2 | uVar1 * 4) & 0xff] ^array2[i];        printf("%c",d);    }}```
This spits out
```Defenit{ea40d42bfaf7d1f599abf284a35c535c607ccadbff38f7c39d6d57e238c4425e}```
Huzzah! But wait... where did INIT_1 get called?
## The Land Before `main`
Let's revisit the entry point.
```cvoid entry(void)
{  __libc_start_main(FUN_08048840);  do {                    /* WARNING: Do nothing block with infinite loop */  } while( true );}```
`__libc_start_main` signature is wrong! It should be
```int __libc_start_main(int *(main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end));```
The first argument should be main, followed by argc, and then argv! That should thenbe followed by a function pointer, followed by another function pointer.
Looking at the disassembly we sometimes
```        0804859b 68 70 89        PUSH       FUN_08048970                 04 08        080485a0 68 10 89        PUSH       FUN_08048910                 04 08        080485a5 51              PUSH       ECX        080485a6 56              PUSH       ESI        080485a7 68 40 88        PUSH       FUN_08048840                 04 08        080485ac e8 9f ff        CALL       __libc_start_main                                undefined __libc_start_main()                 ff ff```We find the `init` function is this:
```void FUN_08048910(undefined4 param_1,undefined4 param_2,undefined4 param_3)
{  int iVar1;   _DT_INIT();  iVar1 = 0;  do {    (*(code *)(&__DT_INIT_ARRAY)[iVar1])(param_1,param_2,param_3);    iVar1 = iVar1 + 1;  } while (iVar1 != 2);  return;}```
This is actually the `libc_csu_init` function. It gets called prior to invokingmain (we can prove this using `gdb`, just set a breakpoint).
Visiting the `__DT_INIT_ARRAY` we find
```                             //                             // .init_array                              // SHT_INIT_ARRAY  [0x8049000 - 0x8049007]                             // ram: 08049000-08049007                             //                             __DT_INIT_ARRAY                                 XREF[5]:     0804809c(*),                                                                                           FUN_08048910:08048931(*),                                                                                           FUN_08048910:08048954(R),                                                                                           0804902c(*),                                                                                           _elfSectionHeaders::000002dc(*)          08049000 60 86 04 08     ddw        _INIT_0                             DWORD_08049004                                  XREF[1]:     FUN_08048910:08048954(R)          08049004 30 87 04 08     ddw        _INIT_1```
And there's the init function! So libc_csu_init is calling everything in the array,in particular, it calls `_INIT_1` (`INIT_0` btw, is boring and does nothing,I'm not sure why it's there).
In C++, one of these functions will call all the static initializers for global andstatic objects, so this is actually good to know about.
So why did Ghidra botch the function definition for `__libc_start_main`? That'sa story for another time (namely, once I figure it out);