PLT command - search all .plt.* sections (#2945)

* PLT command now also searches .plt.sec section

* Add search for .plt.got vs .plt.bnd

* Refactor

* lint

* Remove comment

* Update test

* Add comment and order from low to high address

* Correct section names

* Update pwndbg/commands/elf.py

Co-authored-by: k4lizen <124312252+k4lizen@users.noreply.github.com>

* Update plt command comment, fix tests to reflect new spacing

* Comment

* Run generate docs script

* Generate docs manual fix

---------

Co-authored-by: Disconnect3d <dominik.b.czarnota@gmail.com>
Co-authored-by: k4lizen <124312252+k4lizen@users.noreply.github.com>
pull/2966/head
OBarronCS 7 months ago committed by GitHub
parent 0195f3a077
commit 205b0fd791
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -103,7 +103,7 @@
- [linkmap](linux_libc_elf/linkmap.md) - Show the state of the Link Map
- [onegadget](linux_libc_elf/onegadget.md) - Find gadgets which single-handedly give code execution.
- [piebase](linux_libc_elf/piebase.md) - Calculate VA of RVA from PIE base.
- [plt](linux_libc_elf/plt.md) - Prints any symbols found in the .plt section if it exists.
- [plt](linux_libc_elf/plt.md) - Prints any symbols found in Procedure Linkage Table sections if any exist.
- [strings](linux_libc_elf/strings.md) - Extracts and displays ASCII strings from readable memory pages of the debugged process.
- [threads](linux_libc_elf/threads.md) - List all threads belonging to the selected inferior.
- [tls](linux_libc_elf/tls.md) - Print out base address of the current Thread Local Storage (TLS).

@ -11,7 +11,7 @@ usage: plt [-h]
```
Prints any symbols found in the .plt section if it exists.
Prints any symbols found in Procedure Linkage Table sections if any exist.
### Optional arguments
|Short|Long|Help|

@ -1,5 +1,8 @@
from __future__ import annotations
from typing import List
from typing import Tuple
from elftools.elf.elffile import ELFFile
import pwndbg.commands
@ -42,15 +45,72 @@ def gotplt() -> None:
print_symbols_in_section(".got.plt", "@got.plt")
# These are all the section names associated with PLTs.
# .plt.sec and .plt.bnd are associated with control flow transfer integrity.
# These are derived from this list that GDB recognizes: https://github.com/bminor/binutils-gdb/blob/38d726a24c1a85abdb606e7ab6cefad17872aad7/bfd/elf64-x86-64.c#L5775-L5780
PLT_SECTION_NAMES = (".plt", ".plt.sec", ".plt.got", ".plt.bnd")
@pwndbg.commands.Command(
"Prints any symbols found in the .plt section if it exists.", category=CommandCategory.LINUX
"Prints any symbols found in Procedure Linkage Table sections if any exist.",
category=CommandCategory.LINUX,
)
@pwndbg.commands.OnlyWithFile
def plt() -> None:
print_symbols_in_section(".plt", "@plt")
local_path = pwndbg.aglib.file.get_proc_exe_file()
bin_base_addr = 0
# If we started the binary and it has PIE, rebase it
if pwndbg.aglib.proc.alive:
bin_base_addr = pwndbg.aglib.proc.binary_base_addr
# List of (Section name, start_addr, end_addr)
sections_found: List[Tuple[str, int, int]] = []
with open(local_path, "rb") as f:
elffile = ELFFile(f)
for section_name in PLT_SECTION_NAMES:
section = elffile.get_section_by_name(section_name)
if section:
start: int = section["sh_addr"]
size: int = section["sh_size"]
if start is None:
continue
end = start + size
# Rebase the start and end addresses if needed
if start < bin_base_addr:
start += bin_base_addr
end += bin_base_addr
sections_found.append((section_name, start, end))
# Sort by the start address so we print from lowest to highest
sections_found.sort(key=lambda x: x[1])
for section_name, start, end in sections_found:
symbols = get_symbols_in_region(start, end, "@plt")
print(message.notice(f"Section {section_name} {start:#x} - {end:#x}:"))
if not symbols:
print(message.error(f"No symbols found in section {section_name}"))
stuff: List[Tuple[int, str]] = []
for symbol, addr in symbols:
stuff.append((addr, symbol))
print(hex(int(addr)) + ": " + symbol)
if len(sections_found) == 0:
print(message.error("No .plt.* sections found"))
def get_section_bounds(section_name):
def get_section_bounds(section_name: str):
local_path = pwndbg.aglib.file.get_proc_exe_file()
with open(local_path, "rb") as f:
@ -93,8 +153,8 @@ def print_symbols_in_section(section_name, filter_text="") -> None:
print(hex(int(addr)) + ": " + symbol)
def get_symbols_in_region(start, end, filter_text=""):
symbols = []
def get_symbols_in_region(start: int, end: int, filter_text="") -> List[Tuple[str, int]]:
symbols: List[Tuple[str, int]] = []
ptr_size = pwndbg.aglib.typeinfo.pvoid.sizeof
addr = start
while addr < end:

@ -18,7 +18,7 @@ def test_commands_plt_gotplt_got_when_no_sections(start_binary):
start_binary(NO_SECTS_BINARY)
# elf.py commands
assert gdb.execute("plt", to_string=True) == "Could not find section .plt\n"
assert gdb.execute("plt", to_string=True) == "No .plt.* sections found\n"
assert gdb.execute("gotplt", to_string=True) == "Could not find section .got.plt\n"
# got.py command
@ -40,7 +40,7 @@ def test_command_plt(binary_name, is_pie):
out = gdb.execute("plt", to_string=True).splitlines()
assert len(out) == 2
assert re.match(r"Section \.plt 0x[0-9a-f]+-0x[0-9a-f]+:", out[0])
assert re.match(r"Section \.plt 0x[0-9a-f]+ - 0x[0-9a-f]+:", out[0])
assert re.match(r"0x[0-9a-f]+: puts@plt", out[1])
gdb.execute("starti")
@ -53,7 +53,7 @@ def test_command_plt(binary_name, is_pie):
assert out == out2
assert len(out2) == 2
assert re.match(r"Section \.plt 0x[0-9a-f]+-0x[0-9a-f]+:", out2[0])
assert re.match(r"Section \.plt 0x[0-9a-f]+ - 0x[0-9a-f]+:", out2[0])
assert re.match(r"0x[0-9a-f]+: puts@plt", out2[1])

Loading…
Cancel
Save