Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Building & patching imports leads to a crash in x64 PE #777

Open
dzervas opened this issue Sep 5, 2022 · 2 comments
Open

Building & patching imports leads to a crash in x64 PE #777

dzervas opened this issue Sep 5, 2022 · 2 comments
Assignees

Comments

@dzervas
Copy link

dzervas commented Sep 5, 2022

Describe the bug
I'm trying to add a single DLL to the import table of a x64 EXE

To Reproduce
Steps to reproduce the behavior:

  • Parse the exe
  • add_library
  • add_entry
  • create a builder with build_imports and patch_imports
  • execute it

Expected behavior
The executable should execute regularly without any new crashes

Environment (please complete the following information):

  • System and Version : Manjaro with kernel 5.15.60-1-MANJARO
  • Target format (PE, ELF, Mach-O): PE
  • LIEF commit version: python -c "import lief;print(lief.__version__)" or the one from LIEF/config.h: 0.12.1-

Additional context
Code used:

def download_libgadget(path=".", bitness="x86"):
	libpath = path + "/libgadget.dll"
	if os.path.isfile(libpath):
		print(f"[+] {libpath} already exists, skipping")
		return None

	latest = requests.get("https://api.github.com/repos/frida/frida/releases/latest").json()

	for a in latest["assets"]:
		if a["name"].startswith("frida-gadget") and a["name"].endswith(f"windows-{bitness}.dll.xz"):
			url = a["browser_download_url"]
			print("[+] Downloading", url)

			r = requests.get(url, allow_redirects=True)
			open(libpath + ".xz", "wb").write(r.content)
			with lzma.open(libpath + ".xz", "rb") as f:
				open(libpath, "wb").write(f.read())

			print("[+] Downloaded", a["name"])

			break

def inject(binary):
	injected = lief.parse(binary)
	bitness = 32

	if injected.header.machine == lief.PE.MACHINE_TYPES.I386:
		print("[+] Detected 32 bit PE")
	elif injected.header.machine == lief.PE.MACHINE_TYPES.AMD64:
		print("[+] Detected 64 bit PE")
		bitness = 64
	else:
		print("[!] Unable to detected binary bitness")
		exit(1)

	download_libgadget(realpath(dirname(binary)), "x86" if bitness == 32 else "x86_64")
	gadget = injected.add_library("libgadget.dll")
	gadget.add_entry("frida_gadget_wait_for_permission_to_resume")

	builder = lief.PE.Builder(injected)
	builder.build_imports(True)
	builder.patch_imports(True)
	builder.build()
	os.rename(binary, binary + ".b-" + str(datetime.now().isoformat()))
	builder.write(binary)

if __name__ == "__main__":
	from sys import argv
	inject(argv[1])

error.txt

Unfortunately I can't freely redistribute the executable so contact me if you need it to send it privately

@romainthomas
Copy link
Member

Yes, actually the modification of the import/export table for PE binary is very (very) limited. I'll have to refactor this part around November.

@dzervas
Copy link
Author

dzervas commented Sep 6, 2022

Are there any other solutions to inject frida into an exe?
I don't get why nobody does it and there's literally nothing out there

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants