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

Add functionality for computing locations of PLT stubs in ELF binaries #318

Closed
RyanGlScott opened this issue Feb 16, 2023 · 0 comments · Fixed by #320
Closed

Add functionality for computing locations of PLT stubs in ELF binaries #318

RyanGlScott opened this issue Feb 16, 2023 · 0 comments · Fixed by #320

Comments

@RyanGlScott
Copy link
Contributor

In order to properly handle binaries that dynamically link against shared libraries, one important step is figuring out which functions correspond to procedure linkage table (PLT) stubs. PLT stubs are small pieces of code that allow a binary to call into shared library functions by consulting the global offset table (GOT). For instance, here is a PLT stub in a binary that I have lying around:

$ objdump -d so.exe

so.exe:     file format elf64-x86-64


Disassembly of section .plt:

0000000000001000 <.plt>:
    1000:       ff 35 02 30 00 00       pushq  0x3002(%rip)        # 4008 <_GLOBAL_OFFSET_TABLE_+0x8>
    1006:       ff 25 04 30 00 00       jmpq   *0x3004(%rip)        # 4010 <_GLOBAL_OFFSET_TABLE_+0x10>
    100c:       0f 1f 40 00             nopl   0x0(%rax)

0000000000001010 <fib@plt>:
    1010:       ff 25 02 30 00 00       jmpq   *0x3002(%rip)        # 4018 <fib>
    1016:       68 00 00 00 00          pushq  $0x0
    101b:       e9 e0 ff ff ff          jmpq   1000 <.plt>

The fib@plt PLT stub is what the binary invokes when it wants to call fib, which is defined elsewhere in a shared library. In order to symbolically execute binaries that link against shared libraries, macaw-symbolic needs to have some level of knowledge about PLT stubs.

We have implemented functionality for detecting PLT stubs in a downstream project, and since this would likely be useful for many different projects, we would like to upstream it to macaw. Much of the details of locating PLT stubs are a matter of using the relevant functions from elf-edit to dig into the appropriate parts of an ELF binary. There are a couple of reasons why I think we should put this PLT detection code in macaw rather than elf-edit, however:

  1. We use heuristics to infer how much space there is in between PLT stubs in the .plt section. These heuristics are done on an architecture-by-architecture basis, which requires some knowledge of types in macaw.
  2. It is worth emphasizing that these heuristics are not perfect, and there are scenarios where the heuristics fail. If we want to make the heuristics more accurate, we will likely need to do what the angr tool does and perform direct comparisons against the machine code in the .plt section. This is another reason for putting this code in macaw, as Doing It Right™ would require knowledge of machine code that elf-edit doesn't have.

Once we have functionality for detecting PLT stubs, we can demonstrate it by extending Data.Macaw.Symbolic.Testing to work with shared libraries. This can then serve as a template for other projects that want to use macaw on dynamically linked binaries.

RyanGlScott added a commit that referenced this issue Feb 20, 2023
This extends `Data.Macaw.Symbolic.Testing` in `macaw-symbolic` to be able to
handle binaries that depend on shared libraries. This is fully functional for
the x86-64 and AArch32 symbolic backends, and I have added test cases to the
respective repos demonstrating that it works. (The PowerPC backend is not yet
supported. At a minimum, this is blocked on GaloisInc/elf-edit#35.)

To implement this, I also needed to add some additional infrastructure to
`macaw-base` (I put this infrastructure here as it doesn't depend on any
Crucible-specific functionality):

* `Data.Macaw.Memory.ElfLoader.DynamicDependencies`: a basic ELF dynamic
  loader that performs a breadth-first search over all `DT_NEEDED` entries
  that an ELF binary depends on (both directly and indirectly).
* `Data.Macaw.Memory.ElfLoader.PLTStubs`: a collection of heuristics for
  detecting the addresses of PLT stubs in a dynamically linked binary.

It is worth noting that shared libraries are rife with nuance and subtlety,
and the way `macaw` models shared libraries is not 100% accurate. I have
written a length `Note [Shared libraries]` in `Data.Macaw.Symbolic.Testing`
to describe where corners had to be cut.

Fixes #318.
RyanGlScott added a commit that referenced this issue Feb 23, 2023
This extends `Data.Macaw.Symbolic.Testing` in `macaw-symbolic` to be able to
handle binaries that depend on shared libraries. This is fully functional for
the x86-64 and AArch32 symbolic backends, and I have added test cases to the
respective repos demonstrating that it works. (The PowerPC backend is not yet
supported. At a minimum, this is blocked on GaloisInc/elf-edit#35.)

To implement this, I also needed to add some additional infrastructure to
`macaw-base` (I put this infrastructure here as it doesn't depend on any
Crucible-specific functionality):

* `Data.Macaw.Memory.ElfLoader.DynamicDependencies`: a basic ELF dynamic
  loader that performs a breadth-first search over all `DT_NEEDED` entries
  that an ELF binary depends on (both directly and indirectly).
* `Data.Macaw.Memory.ElfLoader.PLTStubs`: a collection of heuristics for
  detecting the addresses of PLT stubs in a dynamically linked binary.

It is worth noting that shared libraries are rife with nuance and subtlety,
and the way `macaw` models shared libraries is not 100% accurate. I have
written a length `Note [Shared libraries]` in `Data.Macaw.Symbolic.Testing`
to describe where corners had to be cut.

Fixes #318.
RyanGlScott added a commit that referenced this issue Feb 23, 2023
This extends `Data.Macaw.Symbolic.Testing` in `macaw-symbolic` to be able to
handle binaries that depend on shared libraries. This is fully functional for
the x86-64 and AArch32 symbolic backends, and I have added test cases to the
respective repos demonstrating that it works. (The PowerPC backend is not yet
supported. At a minimum, this is blocked on GaloisInc/elf-edit#35.)

To implement this, I also needed to add some additional infrastructure to
`macaw-base` (I put this infrastructure here as it doesn't depend on any
Crucible-specific functionality):

* `Data.Macaw.Memory.ElfLoader.DynamicDependencies`: a basic ELF dynamic
  loader that performs a breadth-first search over all `DT_NEEDED` entries
  that an ELF binary depends on (both directly and indirectly).
* `Data.Macaw.Memory.ElfLoader.PLTStubs`: a collection of heuristics for
  detecting the addresses of PLT stubs in a dynamically linked binary.

It is worth noting that shared libraries are rife with nuance and subtlety,
and the way `macaw` models shared libraries is not 100% accurate. I have
written a length `Note [Shared libraries]` in `Data.Macaw.Symbolic.Testing`
to describe where corners had to be cut.

Fixes #318.
RyanGlScott added a commit to GaloisInc/stubs that referenced this issue Jun 21, 2024
The PLT stub detection mechanism that `stubs-loader` used was upstreamed in
`macaw` in GaloisInc/macaw#318. This deletes
`stubs-loader`'s copy in favor of the upstream (and more up-to-date) version in
`macaw`.

Fixes #32.
RyanGlScott added a commit to GaloisInc/stubs that referenced this issue Jun 21, 2024
The PLT stub detection mechanism that `stubs-loader` used was upstreamed in
`macaw` in GaloisInc/macaw#318. This deletes
`stubs-loader`'s copy in favor of the upstream (and more up-to-date) version in
`macaw`.

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

Successfully merging a pull request may close this issue.

1 participant