Skip to content

Commit 47dfc57

Browse files
ValekoZpeace-makerArusekk
authored
Add a flatten argument to ssh.libs (#2268)
* Add a `flatten` argument to `ssh.libs` This option makes us able to avoid getting the file tree of the remote server and just downloads the desired files in the output folder * Update changelog * Add a warning in ssh.libs for duplicate filenames * Add documentation in ssh.libs for duplicate filenames fallback * [ssh.libs] Fix flatten's duplicate check Fix this: #2268 (comment) * [ssh.libs] Add better warning for flatten's duplicates Fix this: #2268 (comment) * [ssh.libs] Add doctests This commit adds: - The `no_duplicate` binary that depends on - `a/lib.so` - `b/lib2.so` - The `duplicate` binary that depends on - `a/lib.so` - `b/lib.so` Then, the doctest tries to pull the libs from both binaries with different `flatten` values. * [ssh.libs] Add `remote` arg to documentation * [ssh.libs] Remove fallback to unflattened when flatten fails * [ssh.libs] Fix doctests * [ssh.libs] Import pwnlib.data.elf.ssh_libs in pwnlib.data.elf * [ssh.libs] Fix corrupted binaries * [ssh.libs] We actually need to set the cwd since libs paths are relative * [ssh.libs] Fix permission issues for CI * [ssh.libs] Fix doctest * Remove doctest attempts --------- Co-authored-by: peace-maker <[email protected]> Co-authored-by: Arusekk <[email protected]> Co-authored-by: Peace-Maker <[email protected]>
1 parent f5a119f commit 47dfc57

File tree

2 files changed

+28
-3
lines changed

2 files changed

+28
-3
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ The table below shows which release corresponds to each branch, and what date th
9595
- [#2345][2345] Fix pwn constgrep when it matches a non-constant type
9696
- [#2338][2338] Fix: follow symlink for libs on ssh connection
9797
- [#2341][2341] Launch GDB correctly in iTerm on Mac
98+
- [#2268][2268] Add a `flatten` argument to `ssh.libs`
9899

99100
[2242]: https://github.com/Gallopsled/pwntools/pull/2242
100101
[2277]: https://github.com/Gallopsled/pwntools/pull/2277
@@ -118,6 +119,7 @@ The table below shows which release corresponds to each branch, and what date th
118119
[2345]: https://github.com/Gallopsled/pwntools/pull/2345
119120
[2338]: https://github.com/Gallopsled/pwntools/pull/2338
120121
[2341]: https://github.com/Gallopsled/pwntools/pull/2341
122+
[2268]: https://github.com/Gallopsled/pwntools/pull/2268
121123

122124
## 4.12.0 (`beta`)
123125

pwnlib/tubes/ssh.py

+26-3
Original file line numberDiff line numberDiff line change
@@ -1810,20 +1810,42 @@ def unlink(self, file):
18101810

18111811
return self.sftp.unlink(file)
18121812

1813-
def libs(self, remote, directory = None):
1813+
def libs(self, remote, directory = None, flatten = False):
18141814
"""Downloads the libraries referred to by a file.
18151815
18161816
This is done by running ldd on the remote server, parsing the output
18171817
and downloading the relevant files.
18181818
18191819
The directory argument specified where to download the files. This defaults
1820-
to './$HOSTNAME' where $HOSTNAME is the hostname of the remote server."""
1820+
to './$HOSTNAME' where $HOSTNAME is the hostname of the remote server.
1821+
1822+
Arguments:
1823+
remote(str): Remote file path
1824+
directory(str): Output directory
1825+
flatten(bool): Flatten the file tree if True (defaults to False) and
1826+
ignore the remote directory structure. If there are duplicate
1827+
filenames, an error will be raised.
1828+
"""
18211829

18221830
libs = self._libs_remote(remote)
18231831

18241832
remote = packing._decode(self.readlink('-f',remote).strip())
18251833
libs[remote] = 0
18261834

1835+
if flatten:
1836+
basenames = dict()
1837+
1838+
# If there is a duplicate switch to unflattened download
1839+
for lib in libs:
1840+
name = os.path.basename(lib)
1841+
1842+
if name in basenames.values():
1843+
duplicate = [key for key, value in basenames.items() if
1844+
value == name][0]
1845+
self.error('Duplicate lib name: %r / %4r' % (lib, duplicate))
1846+
1847+
basenames[lib] = name
1848+
18271849
if directory is None:
18281850
directory = self.host
18291851

@@ -1834,7 +1856,8 @@ def libs(self, remote, directory = None):
18341856
seen = set()
18351857

18361858
for lib, addr in libs.items():
1837-
local = os.path.realpath(os.path.join(directory, '.' + os.path.sep + lib))
1859+
local = os.path.realpath(os.path.join(directory, '.' + os.path.sep \
1860+
+ (basenames[lib] if flatten else lib)))
18381861
if not local.startswith(directory):
18391862
self.warning('This seems fishy: %r' % lib)
18401863
continue

0 commit comments

Comments
 (0)