def _check_elf_cache(cache_type, hex_encoded_id, hash_type): """ Check if there already is an ELF file for this hash in the cache. >>> cache, _ = _check_elf_cache('libcdb', '2d1c5e0b85cb06ff47fa6fa088ec22cb6e06074e', 'build_id') >>> os.unlink(cache) if os.path.exists(cache) >>> filename = search_by_hash('2d1c5e0b85cb06ff47fa6fa088ec22cb6e06074e', 'build_id', unstrip=False) >>> hex(ELF(filename).symbols.read) '0xe56c0' >>> filename == cache True """ # Ensure that the cache directory exists cache_dir = os.path.join(context.cache_dir, cache_type, hash_type) if not os.path.isdir(cache_dir): os.makedirs(cache_dir) # If we already downloaded the file, and it looks even passingly like # a valid ELF file, return it. cache = os.path.join(cache_dir, hex_encoded_id) if not os.path.exists(cache): return cache, False log.debug("Found existing cached ELF at %r", cache) data = read(cache) if not data.startswith(b'\x7FELF'): log.info_once("Skipping unavailable ELF %s", hex_encoded_id) return cache, False log.info_once("Using cached data from %r", cache) return cache, True
def push(local_path, remote_path): """Upload a file to the device. Arguments: local_path(str): Path to the local file to push. remote_path(str): Path or directory to store the file on the device. Returns: Remote path of the file. Example: .. doctest:: :skipif: skip_android >>> write('./filename', 'contents') >>> adb.push('./filename', '/data/local/tmp') '/data/local/tmp/filename' >>> adb.read('/data/local/tmp/filename') b'contents' >>> adb.push('./filename', '/does/not/exist') Traceback (most recent call last): ... PwnlibException: Could not stat '/does/not/exist' """ msg = "Pushing %r to %r" % (local_path, remote_path) remote_filename = os.path.basename(local_path) if log.isEnabledFor(logging.DEBUG): msg += ' (%s)' % context.device with log.waitfor(msg) as w: with AdbClient() as c: # We need to discover whether remote_path is a directory or not. # If we cannot stat the full path, assume it's a path-plus-filename, # where the filename does not exist. stat_ = c.stat(remote_path) if not stat_: remote_filename = os.path.basename(remote_path) remote_path = os.path.dirname(remote_path) stat_ = c.stat(remote_path) # If we can't find the exact path, or its parent directory, bail! if not stat_: log.error('Could not stat %r' % remote_path) # If we found the parent directory, append the filename mode = stat_['mode'] if stat.S_ISDIR(mode): remote_path = os.path.join(remote_path, remote_filename) c.write(remote_path, misc.read(local_path), callback=_create_adb_push_pull_callback(w)) return remote_path
def should_check(): """Return True if we should check for an update""" filename = cache_file() if not filename: return False if disabled or read(filename).strip() == b'never': return False return time.time() > (last_check() + update_freq)
def should_check(): """Return True if we should check for an update""" filename = cache_file() if not filename: return False if read(filename).strip() == 'never': return False return time.time() > (last_check() + update_freq)
def push(local_path, remote_path): """Upload a file to the device. Arguments: local_path(str): Path to the local file to push. remote_path(str): Path or directory to store the file on the device. Returns: Remote path of the file. Example: >>> write('./filename', 'contents') >>> adb.push('./filename', '/data/local/tmp') '/data/local/tmp/filename' >>> adb.read('/data/local/tmp/filename') 'contents' >>> adb.push('./filename', '/does/not/exist') Traceback (most recent call last): ... PwnlibException: Could not stat '/does/not/exist' """ msg = "Pushing %r to %r" % (local_path, remote_path) remote_filename = os.path.basename(local_path) if log.isEnabledFor(logging.DEBUG): msg += ' (%s)' % context.device with log.waitfor(msg) as w: with AdbClient() as c: # We need to discover whether remote_path is a directory or not. # If we cannot stat the full path, assume it's a path-plus-filename, # where the filename does not exist. stat_ = c.stat(remote_path) if not stat_: remote_filename = os.path.basename(remote_path) remote_path = os.path.dirname(remote_path) stat_ = c.stat(remote_path) # If we can't find the exact path, or its parent directory, bail! if not stat_: log.error('Could not stat %r' % remote_path) # If we found the parent directory, append the filename mode = stat_['mode'] if stat.S_ISDIR(mode): remote_path = os.path.join(remote_path, remote_filename) c.write(remote_path, misc.read(local_path), callback=_create_adb_push_pull_callback(w)) return remote_path
def search_by_hash(hex_encoded_id, hash_type='build_id'): assert hash_type in HASHES, hash_type # Ensure that the libcdb cache directory exists cache_dir = os.path.join(context.cache_dir, 'libcdb', hash_type) if not os.path.isdir(cache_dir): os.makedirs(cache_dir) # If we already downloaded the file, and it looks even passingly like # a valid ELF file, return it. cache = os.path.join(cache_dir, hex_encoded_id) if os.path.exists(cache): log.debug("Found existing cached libc at %r", cache) data = read(cache) if data.startswith(b'\x7FELF'): log.info_once("Using cached data from %r", cache) return cache else: log.info_once("Skipping unavialable libc %s", hex_encoded_id) return None # Build the URL using the requested hash type url_base = "https://gitlab.com/libcdb/libcdb/raw/master/hashes/%s/" % hash_type url = urllib.parse.urljoin(url_base, hex_encoded_id) data = b"" while not data.startswith(b'\x7fELF'): log.debug("Downloading data from LibcDB: %s", url) data = wget(url) if not data: log.warn_once("Could not fetch libc for build_id %s", hex_encoded_id) break # GitLab serves up symlinks with if data.startswith(b'..'): url = os.path.dirname(url) + '/' url = urllib.parse.urljoin(url.encode('utf-8'), data) # Save whatever we got to the cache write(cache, data or b'') # Return ``None`` if we did not get a valid ELF file if not data or not data.startswith(b'\x7FELF'): return None return cache
def search_by_hash(hex_encoded_id, hash_type='build_id'): assert hash_type in HASHES, hash_type # Ensure that the libcdb cache directory exists cache_dir = os.path.join(context.cache_dir, 'libcdb', hash_type) if not os.path.isdir(cache_dir): os.makedirs(cache_dir) # If we already downloaded the file, and it looks even passingly like # a valid ELF file, return it. cache = os.path.join(cache_dir, hex_encoded_id) if os.path.exists(cache): log.debug("Found existing cached libc at %r", cache) data = read(cache) if data.startswith(b'\x7FELF'): log.info_once("Using cached data from %r", cache) return cache else: log.info_once("Skipping unavailable libc %s", hex_encoded_id) return None # Run through all available libc database providers to see if we have a match. for provider in PROVIDERS: data = provider(hex_encoded_id, hash_type) if data and data.startswith(b'\x7FELF'): break if not data: log.warn_once("Could not find libc for %s %s anywhere", hash_type, hex_encoded_id) # Save whatever we got to the cache write(cache, data or b'') # Return ``None`` if we did not get a valid ELF file if not data or not data.startswith(b'\x7FELF'): return None return cache
def search_by_build_id(hex_encoded_id): """ Given a hex-encoded Build ID, return the path to an ELF with that Build ID only the local system. If it can't be found, return None. Arguments: hex_encoded_id(str): Hex-encoded Build ID (e.g. 'ABCDEF...') of the library Returns: Path to the downloaded library on disk, or :const:`None`. """ cache = cache_dir + '-libc.so.' + hex_encoded_id if os.path.exists(cache) and read(cache).startswith('\x7FELF'): log.info_once("Using cached data from %r" % cache) return cache log.info("Downloading data from GitHub") url_base = "https://gitlab.com/libcdb/libcdb/raw/master/hashes/build_id/" url = urlparse.urljoin(url_base, hex_encoded_id) data = "" while not data.startswith('\x7fELF'): data = wget(url) if not data: return None if data.startswith('..'): url = os.path.dirname(url) + '/' url = urlparse.urljoin(url, data) write(cache, data) return cache
def is_wsl() -> bool: return b'Microsoft' in read('/proc/sys/kernel/osrelease')
def is_wsl() -> bool: return b'Microsoft' in read('/proc/sys/kernel/osrelease') class AddrChecker():