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

Automatic finding one-gadget #932

Open
Isaac0616 opened this issue Mar 24, 2017 · 10 comments
Open

Automatic finding one-gadget #932

Isaac0616 opened this issue Mar 24, 2017 · 10 comments

Comments

@Isaac0616
Copy link
Contributor

There is a tool for finding one-gadget written in ruby. Is it a good idea to have one in pwntools?

@zachriggle
Copy link
Member

Perhaps? It'd be better / easier to use if there were a single endpoint which had all of the offsets in a neutral format like JSON.

I think that the other tool is useful in its own right, I'm not sure that it necessarily fits into the Pwntools workflow currently.

@zachriggle zachriggle self-assigned this Mar 24, 2017
@zachriggle zachriggle added this to the Someday milestone Mar 24, 2017
@zachriggle zachriggle removed their assignment Apr 18, 2017
@ZetaTwo
Copy link
Contributor

ZetaTwo commented Sep 29, 2019

For anyone searching for "one_gadget pwntools" and ending up on this issue: I made the following utility function which calls the one_gadget tool with a path or build id and returns a list of offsets. It requires one_gadget to be installed and in the PATH:

def get_one_gadgets(libc):
	args = ["one_gadget", "-r"]
	if len(libc) == 40 and all(x in string.hexdigits for x in libc.hex()):
		args += ["-b", libc.hex()]
	else:
		args += [libc]
	return [int(offset) for offset in subprocess.check_output(args).decode('ascii').strip().split()]

which can then be called for example with:

print(get_one_gadgets(ELF('libc.so.6').buildid))

or

print(get_one_gadgets(ELF('challenge').libc.path))

@Hellsender01
Copy link

Maybe this fits you -

from one_gadget import generate_one_gadget

path_to_libc = './libc-2.23.so'

for offset in generate_one_gadget(path_to_libc):
    print(offset)
Spoiler! This does not work everytime

@ir0nstone
Copy link

How acceptable would it be for pwntools to have a one_gadget function in the ELF class that simply uses subprocess to call the Ruby one_gadget? An error would have to be thrown in case it's not installed and on the PATH, but I think it could be incredibly helpful.

Not quite sure on the licensing issues this would invoke, though.

@Arusekk
Copy link
Member

Arusekk commented Mar 27, 2024 via email

@ir0nstone
Copy link

It does not appear as if there is an API. The repository itself describes a way to grab the one-gadgets through a subprocess. That ok?

@david942j
Copy link
Contributor

Author of one_gadget here 👋

Feel free to let me know if any support is required from the one_gadget gem. A simple Python wrapper to call subprocess to one_gadget shall be a preferred (at least I prefer it) way to enable it on Pwntools.

Or if there is a common practice for bridging Python-Ruby method exists then I am also fine to add such support on the Ruby side if needed.

@peace-maker
Copy link
Member

Hey!👋 I'd like to see a json output instead of having to parse the text for --near X --raw output, which would make it more robust against cosmetic changes you might want to do. But the basic use case of just grabbing all magic gadgets for a file with a plain one_gadget --raw libc.so.6 execution is good as is. I think shelling out to the one_gadget tool is perfectly fine.

grafik

@ir0nstone How do you envision this function to be used in pwntools scripts? Get all one gadgets and just try them in a loop?
I'm thinking of whether adding some interactive selection while showing the gadget constraints be useful. Similar to libcdb.search_by_symbol_offsets:

grafik

That would allow you to try a few gadgets without touching your script's code.

pwndbg has a onegadget command which parses the tool's output and filters the available gadgets based on whether the constraints can be satisfied in the current execution context which simplifies the process of selecting the right gadget if there is one that doesn't require additional memory/register manipulation.

@david942j
Copy link
Contributor

@peace-maker thanks for the suggestion! I have filed david942j/one_gadget#224 for tracking this support on one_gadget.

@david942j
Copy link
Contributor

one_gadget v1.10.0 was released for supporting output in JSON format.
Example usage:

$ one_gadget -b b417c0ba7cc5cf06d1d1bed6652cedb9253c60d0 -o json -l1
[{"value":324279,"effect":"execve(\"/bin/sh\", rsp+0x40, environ)","constraints":["rsp & 0xf == 0","writable: rsp+0x50","{\"sh\", \"-c\", r12, NULL} is a valid argv"]},{"value":324286,"effect":"execve(\"/bin/sh\", rsp+0x40, environ)","constraints":["rsp & 0xf == 0","writable: rsp+0x50","rcx == NULL || {rcx, \"-c\", r12, NULL} is a valid argv"]},{"value":324293,"effect":"execve(\"/bin/sh\", rsp+0x40, environ)","constraints":["rsp & 0xf == 0","writable: rsp+0x50","rcx == NULL || {rcx, rax, r12, NULL} is a valid argv"]},{"value":324386,"effect":"execve(\"/bin/sh\", rsp+0x40, environ)","constraints":["[rsp+0x40] == NULL || {[rsp+0x40], [rsp+0x48], [rsp+0x50], [rsp+0x58], ...} is a valid argv"]},{"value":939679,"effect":"execve(\"/bin/sh\", r14, r12)","constraints":["[r14] == NULL || r14 == NULL || r14 is a valid argv","[r12] == NULL || r12 == NULL || r12 is a valid envp"]},{"value":940120,"effect":"execve(\"/bin/sh\", [rbp-0x88], [rbp-0x70])","constraints":["[[rbp-0x88]] == NULL || [rbp-0x88] == NULL || [rbp-0x88] is a valid argv","[[rbp-0x70]] == NULL || [rbp-0x70] == NULL || [rbp-0x70] is a valid envp"]},{"value":940127,"effect":"execve(\"/bin/sh\", r10, [rbp-0x70])","constraints":["[r10] == NULL || r10 == NULL || r10 is a valid argv","[[rbp-0x70]] == NULL || [rbp-0x70] == NULL || [rbp-0x70] is a valid envp"]},{"value":940131,"effect":"execve(\"/bin/sh\", r10, rdx)","constraints":["[r10] == NULL || r10 == NULL || r10 is a valid argv","[rdx] == NULL || rdx == NULL || rdx is a valid envp"]},{"value":1090444,"effect":"execve(\"/bin/sh\", rsp+0x70, environ)","constraints":["[rsp+0x70] == NULL || {[rsp+0x70], [rsp+0x78], [rsp+0x80], [rsp+0x88], ...} is a valid argv"]},{"value":1090456,"effect":"execve(\"/bin/sh\", rsi, [rax])","constraints":["[rsi] == NULL || rsi == NULL || rsi is a valid argv","[[rax]] == NULL || [rax] == NULL || [rax] is a valid envp"]}]

More examples in david942j/one_gadget#225

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