## Golf.so
> Thinking that Bovik’s flags might be hidden in plain sight, you find on your minimap of the Inner Sanctum that there’s a golf course tucked into the northeast corner. Before other people catch on to the idea, you sneak off towards the rolling grassy hills of the golf course.> > As you walk up to the entrance, a small man with pointy ears pops up out of the ground.> > “Would you like to play? Right now almost nobody is here, so it’ll only be a thousand checkers to play a round.“> > You wave your hand and send the man the required amount. It’s not a lot of money, but your balance dwindles to a paltry sum.> > “Thanks! Enjoy your game.“> > A golf club appears in your hand along with a ball that looks suspiciously too large. The start of the first hole beckons, and you stride over to tee off.> > http://golf.so.pwni.ng
On the website we see a scoreboard with team names and file sizes. There is an“Upload” button which shows us the rules of the game:>  Upload a 64-bit ELF shared object of size at most 1024 bytes. It should>  spawn a shell (execute `execve("/bin/sh", ["/bin/sh"], ...)`) when used like> > `LD_PRELOAD=<upload> /bin/true`
Ok, we have to write a tiny ELF file which spawns a shell when `LD_PRELOAD`ed.Unfortunately a simple C program produces a 16kB large .so file, which isclearly too big.
## ELF: Dynamic Shared Objects
First of all we need to know how ELF files work.
Every 64bit ELF file starts with an `Elf64_Ehdr` struct. It contains a magicword, as well as general information about the file like the CPU architecture,entry point, and endianess. It also has pointers to two other structures, theProgram Headers and Section Headers.
Program Headers (`Elf64_Phdr`) describe which *segments* are stored in the ELFfile. There are two important types of segments: `PT_LOAD` segments and`PT_DYNAMIC` segments.  Only `PT_LOAD` segments are loaded into memory. Theyusually contain code, data, and other information that has to be available atruntime. A `PT_DYNAMIC` segment has to overlap with a `PT_LOAD` segment, and itholds information for the dynamic linker.
Section Headers (`Elf64_Shdr`) describe *sections* in the ELF file, like e.g.the `.text` section. They contain additional information about which data isstored where *within* a segment. A single segment can contain multiplesections.
Since we want to create a library, we need both code and a `PT_DYNAMIC`segment. We will see that sections are not important at all.
## ELF: The DYNAMIC SegmentThe DYNAMIC segment consists of a list of `Elf64_Dyn` entries, which contain atag and a value. According to [some webpage](https://docs.oracle.com/cd/E19455-01/816-0559/chapter6-42444/index.html)a few entries are mandatory and all other entries are optional.
One entry is particularly interesting, the `DT_INIT` entry. It has a pointer toan initializer function which is executed after the library is loaded. It issupposed to initialize the library. We will use this function to spawn theshell.
## Writing An ELF File By HandWith this information, we can start to write an ELF file by hand. To start“small”, we write a fully compliant ELF file with all necessary information.
The shellcode is rather simple, it's an off the shelf msfvenom shellcode.
First Attempt: [golf.c](https://www.sigflag.at/assets/posts/golf.so/golf.v1.c)
Running this program produces a `golf.so` which is 821 bytes large. We canupload this to the website, but it tells us that we have to shrink the file inorder to get the flag.
![Troll](https://www.sigflag.at/assets/posts/golf.so/troll.png)
## Making It Smaller
Now let's remove all unnecessary things. First of all the section headers aretotally irrelevant, we can just remove them. With the section headers removed,we can also remove the strings for the string tables, since they were onlyreferenced from section headers.
We can also remove most of the segments and only leave a single `PT_LOAD`segment which holds the code and the DYNAMIC data. And we can remove most ofthe `Elf64_Dyn` entries, since they are not needed.
Now we only have two Program Headers:- `PT_LOAD` which loads the whole file to address 0- `PT_DYNAMIC` which points to the `Elf64_Dyn` list
We still have a few `Elf64_Dyn` entries:- `DT_INIT` for our initializer- `DT_STRTAB`- `DT_SYMTAB`
But this is still too large.
We can start to overlap data. The last Program Header doesn't need a value in`p_memsz` since it is not a `PT_LOAD` segment. We could start our `Elf64_Dyn`list in this field, such that it overlaps with the Program Header.
We can save 6 more bytes by overlapping the first Program Header with the endof the ELF header, since the last 3 fields in the ELF header are not used.
We *cannot* remove any more `Elf64_Dyn` records, since removing any of themmakes the linker crash.
Seccond Attempt: [golf.c](https://www.sigflag.at/assets/posts/golf.so/golf.v2.c)
We now have 229 bytes, but it is still too large.
## Making It Even Smaller
Running `/bin/true` with `golf.so` preloaded in a debugger reveals that ourinitializer is called via `call rax`, so `rax` has a pointer to the shellcode.Now it's time to write some custom shellcode which is smaller. Since we havethe address to our shellcode, we can store the `/bin/sh` string in some unusedELF header field and directly reference it. Since the offset to the SectionHeaders `e_shoff` is not used, we can just store the string in there.
The shellcode now looks like this:
```401000:       48 8d b8 5e ff ff ff    lea    rdi,[rax-0xa2]401007:       31 c0                   xor    eax,eax401009:       50                      push   rax40100a:       57                      push   rdi40100b:       48 89 e6                mov    rsi,rsp40100e:       50                      push   rax40100f:       48 89 e2                mov    rdx,rsp401012:       b0 3b                   mov    al,0x3b401014:       0f 05                   syscall```
Third Attempt: [golf.c](https://www.sigflag.at/assets/posts/golf.so/golf.v3.c)
This generates a 224 byte large golf.so, but that's *still* too big. We have toreach 192 bytes!
## Creating A Tiny But Totally Broken ELF File
Shrinking the file even further is no longer trivial. We now have to overlapeverything, and completely get rid of the shellcode section.
There are a few pointers within the ELF header as well as within ProgramHeaders that are never used. We can overwrite them with arbitrary values andthe linker won't care. We can use this to split the shellcode and embed it inthose pointers.
Unfortunately the first command (`lea rdi,[rax-0xa2]`) not only depends on theaddress of the initializer function, it also consists of 7 bytes, so we cannotadd a jump afterwards. Luckily there are some pointers where the exact value ofthe next field doesn't matter that much, so we can enter something slightly toobig. More specifically, if we put this command into the `p_addr` field of theDYNAMIC segment, we can put the offset for a `jmp` into the `p_filesz` field.The `DT_INIT` has to point to the `p_addr` field. The `lea` is executed, andthen the jump is taken.
The next shellcode fragment can be placed in the `e_entry` field of the ELFheader. We can fit 4 shellcode instructions in there, but then we only have onebyte left for the next jump. This time we *cannot* change the next byte, butsince the ELF header is 0x3A bytes large, we conveniently jump to address 0x90.This is right into the `p_filesz` field of the `PT_LOAD` header. We put anotherjump there, back to the `p_addr` field of the same Program Header. In thisfield we can finally put the remaining commands of the shellcode.
Since we don't need the shellcode at the end of the file anymore, the last`Elf64_Dyn` entry ends with a NULL value. We don't have to store that in ourELF file, since everything past the file end is implicitly zero. We don't evenhave to store the whole `d_tag` of the last `Elf64_Dyn` record, since only thefirst byte is nonzero.
With those optimizations, the final ELF file is only 187 bytes large.
Final Solution: [golf.c](https://www.sigflag.at/assets/posts/golf.so/golf.c)
Interestingly enough, IDA Pro refuses to load this ELF file.
With this `golf.so` file, we finally get our flags:
![Flag](https://www.sigflag.at/assets/posts/golf.so/flag.png)