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

How to modify the dynamic entries for a ELF in python? #118

Closed
0ca opened this issue Nov 22, 2017 · 11 comments
Closed

How to modify the dynamic entries for a ELF in python? #118

0ca opened this issue Nov 22, 2017 · 11 comments

Comments

@0ca
Copy link

0ca commented Nov 22, 2017

Hello,

I am trying LIEF for the first time, it's an amazing project!

I'm having troubles doing the following.

I want to modify an entry in the dynamic table for an ELF file. I tried this:

  elf = lief.parse("test")
  for entry in elf.dynamic_entries:
    if entry.tag == lief.ELF.DYNAMIC_TAGS.INIT:
      entry.value = 0x88888888
  elf.write("test_modified")

But the value is not written into the file.

I saw the DynamicEntryArray class has a method to insert values:
https://lief.quarkslab.com/doc/api/python/elf.html#dynamic-entry-array

But I don't know how to get that DynamicEntryArray from the parsed file :(

How could I do this?

Thank you!

@romainthomas
Copy link
Member

Hi
For the first point:

$ readelf -d /lib/libm.so.6 |grep INIT
 0x000000000000000c (INIT)               0x7628
 0x0000000000000019 (INIT_ARRAY)         0x34acd0
 0x000000000000001b (INIT_ARRAYSZ)       8 (bytes)

As we can see the value of DT_INIT is 0x7628

Then with LIEF:

>>> lib = lief.parse("/lib/libm.so.6")
>>> lib[lief.ELF.DYNAMIC_TAGS.INIT].value = 0xBADC0DE
>>> lib.write("/tmp/test.so")

And now:

$ readelf -d /tmp/test.so|grep INIT
 0x000000000000000c (INIT)               0xbadc0de
 0x0000000000000019 (INIT_ARRAY)         0x34acd0
 0x000000000000001b (INIT_ARRAYSZ)       8 (bytes)

For the second point you can do:

binary = lief.parse(...)
if lief.ELF.DYNAMIC_TAGS.INIT_ARRAY in binary:
    array = binary[lief.ELF.DYNAMIC_TAGS.INIT_ARRAY]
    print(array)

@0ca
Copy link
Author

0ca commented Nov 22, 2017

Thank you!

@0ca 0ca closed this as completed Nov 22, 2017
@0ca
Copy link
Author

0ca commented Nov 22, 2017

The code you provided works well with the INIT but not with the INIT_ARRAY:

>>> lib = lief.parse("/lib/libm.so.6")
>>> lib[lief.ELF.DYNAMIC_TAGS.INIT_ARRAY].value = 0xBADC0DE
>>> lib.write("/tmp/test.so")

I get this error:

You inserted data (8) in section '' which has SHT_NOBITS type !

Unable to find the section

My idea is to create a new INIT_ARRAY and modify the pointer in the Dynamic Section so I can add an additional start routine to a binary.

@0ca 0ca reopened this Nov 22, 2017
@0ca
Copy link
Author

0ca commented Nov 22, 2017

I only get the error when running the code from a script. Running it from a ipython sessions the error doesn't show up. But the output binary doesn't have the INIT_ARRAY value modified :(

@romainthomas
Copy link
Member

You shouldn't care about the warning You inserted data (8) in section '' which has SHT_NOBITS type ! (It comes from the parser)

Modifying the address of the DT_INIT_ARRAY entry is not a good idea since you won't have relocation for the new address.

@0ca
Copy link
Author

0ca commented Nov 27, 2017

I don't understand :( Do you mean the new address for the INIT_ARRAY? My idea was to create a new segment with the new array and then modify INIT_ARRAY to point there.

Could you explain it more or link a resource where I could learn why it's not a good idea?

Thank you for your hard work!

@romainthomas
Copy link
Member

romainthomas commented Nov 27, 2017

Modifying the address of the DT_INIT_ARRAY entry is not a good idea since you won't have relocation for the new address.

I mean: why not using the existing one and extend it (from the bottom or from the top) ? Usually all Linux shared libraries have such entry

If you really need to create a new one you should take account of the relocation process an create new relocations as well

@0ca
Copy link
Author

0ca commented Nov 27, 2017

I'm worry that there is no space to extend the INIT_ARRAY, maybe there is other tables or sections around.

Could I extend the INIT_ARRAY using LIEF?

PS: I have experience with the PE format, but I feel a bit lost with the ELF. Could you recommend me a good document to understand it? Thank you!

@romainthomas
Copy link
Member

Could I extend the INIT_ARRAY using LIEF?

Yes actually LIEF handle this case: https://github.com/lief-project/LIEF/blob/master/src/ELF/Builder.tcc#L547-L550 ;)

PS: I have experience with the PE format, but I feel a bit lost with the ELF. Could you recommend me a good document to understand it? Thank you!

The better documentation is the loader source code:
https://github.com/lattera/glibc/blob/a2f34833b1042d5d8eeb263b4cf4caaea138c4ad/elf/dl-init.c#L73-L86

@illera88
Copy link
Contributor

illera88 commented Nov 28, 2017

Hi,
There is something I'm missing or I don't understand. Correct me if any of the next statements are wrong:

  1. INIT_ARRAY is a reference in the ELF header
  2. INIT_ARRAY points to an array of pointers. These pointers points to functions that are executed before the library loads
  3. A new segment can be created and the existing pointers in the INIT_ARRAY copied to it and added a new pointer to another brand new segment with the code I want to execute.
  4. The INIT_ARRAY pointer in the ELF header can be modified so now it points to the segment created in 3)

What is the problem with relocations here? I don't understand since I'm not changing more than just pointers not actual code that may need to be aligned (that's what I thought about when reading relocations).

Thanks!!

@romainthomas
Copy link
Member

What is the problem with relocations here?

If the INIT_ARRAY point to 0x123 the address will be at execution time address base + 0x123 thus you need a relocation at the offset of the INIT_ARRAY

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

3 participants