Description:

Download the file at https://ggcs-files.allyourbases.co/fe04.zip and find a way to recover the flag from the corrupted file.

Let's see what it thinks it is, first:

file file
file: Apple DiskCopy 4.2 image , 2097408 bytes, 0x40000 tag size, GCR CLV ssdd (400k), 0x54 format

And let's see what strings says:

strings file
/lib/ld-linux.so.2
libc.so.6
_IO_stdin_used
puts
__cxa_finalize
__libc_start_main
__stack_chk_fail
GLIBC_2.0
GLIBC_2.1.3
GLIBC_2.4
...

It's a corrupted ELF. Now, I don't want to many write ELF tables.

We can import it into Ghidra as x86:LE:32:default (2.9) and in all fairness, it does pretty well!

In the functions window, we sort by size to find main (typically the largest function in these things) and go to it, but it looks like some custom crypto madness. I could either manually slave away and reverse it OR I can just call it.

Introducing my friend mmap:

#include <stdio.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

int main() {
  int file = open("file", O_RDONLY);
  void *map = mmap(0x1260000, 7293, PROT_READ | PROT_EXEC, MAP_PRIVATE, file, 0);

  munmap(map, 7293);
  close(file);

  return 0;
}

Now, at that little space between mmap and munmap, I can use GDB to call the main function directly in the map. Make sure to compile it with gcc -m32 solver.c.

Sequence of instructions used:

gdb ./a.out
gef> start
gef> ni 
# continuing until after the mmap executes
# call the function in the memory map (base + offset)
gef> call *(0x1260000+0x566)
gef> jump *(0x1260000+0x566)
gef> quit

Call + jump makes the string pointer in the stack correct as modified by the function (since it remains in the stack) and the stack aligned so I don't have to find it with gef.

0xffffcc2c│+0x0000: 0x012606b9  →  0xb810c483	 ← $esp
0xffffcc30│+0x0004: 0xffffcc50  →  "Flag: DoNTLosEYOURHeAD-1181"

Screw fixing headers, just mmap that bad boy.