Rating:

[original](https://gist.github.com/cwgreene/5253cfa3904871535126b34ebbcb050f)
# Defenit-2020 Mom's Touch
We 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 simple
arithmetic 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 directly
out 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's
deterministic, we will generate the same values. (This also answers the mystery
of 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 using
ghidra'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 calls
to `rand` here, plus an initialization using `srand`. We'll need to add these calls
to our deobfuscator.

```c
int 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.

```c
void 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 then
be 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 invoking
main (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 and
static objects, so this is actually good to know about.

So why did Ghidra botch the function definition for `__libc_start_main`? That's
a story for another time (namely, once I figure it out);