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 · 10 comments
Open

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

dzervas opened this issue Sep 5, 2022 · 10 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

@receiver1
Copy link

it looks like the refactoring never happened, the crashes are still going on

@jclab-joseph
Copy link

+1

1 similar comment
@Grivus
Copy link

Grivus commented Jul 29, 2024

+1

@babaee404
Copy link

this code generate exe file but after run it crash
filePath= r"PE64_x86-64_binary_mfc-application.exe"
outFile= r"out-1.exe"
peFile = lief.parse(filePath)

kernel32_lhs = peFile.add_library("user32.dll")
kernel32_lhs.add_entry("UnregisterClassW")

builder = lief.PE.Builder(peFile)

builder.build_imports(True).patch_imports(True)
builder.build()

builder.write(outFile)

@receiver1
Copy link

this code generate exe file but after run it crash filePath= r"PE64_x86-64_binary_mfc-application.exe" outFile= r"out-1.exe" peFile = lief.parse(filePath)

kernel32_lhs = peFile.add_library("user32.dll") kernel32_lhs.add_entry("UnregisterClassW")

builder = lief.PE.Builder(peFile)

builder.build_imports(True).patch_imports(True) builder.build()

builder.write(outFile)

Import rebuild is broken for X64.

@Redbeanw44602
Copy link

Two years have passed and the crash continues :(

@jclab-joseph
Copy link

jclab-joseph commented Oct 18, 2024

We also needed to add the dll to the import table of the exe.

https://github.com/Snshadow/debug
It was a difficult work, but he succeeded! It was made in Go and works well.
With this as a reference, someone might be able to fix LIEF too.

@m0rphine1
Copy link

any updates? i really need this feature. at least any suggestion what is the actual problem and how can i fix it myself?

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

8 participants