Commit Graph

70 Commits

Author SHA1 Message Date
Romain Thomas be0ee74c14 Fix include 2026-03-19 17:14:29 +01:00
lief-agent 76df01f96a Improve the documentation 2026-03-07 20:32:54 +01:00
Romain Thomas 84f963a716 Initial support for the COFF format
Resolve #1091
2025-06-08 20:01:21 +02:00
Romain Thomas c000b17be0 Enhance PE parser/builder
close #1021
close #1118
close #192
close #276
close #358
close #642
close #746
close #777
resolve #1043
resolve #109
resolve #114
resolve #1167
resolve #124
resolve #137
resolve #140
resolve #277
resolve #472
resolve #473
resolve #517
resolve #523
resolve #528
resolve #530
resolve #546
resolve #69
resolve #876
2025-02-15 05:33:25 +01:00
Emmanuel Ferdman ec233a499f Update authenticode reader reference (#1120)
* Fix memory issues raised by GHSA-xpwf-7qj6-m6r4 & GHSA-c2f3-2xpq-pjj9

* Update authenticode reader reference

Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>

---------

Signed-off-by: Emmanuel Ferdman <emmanuelferdman@gmail.com>
Co-authored-by: Romain Thomas <me@romainthomas.fr>
2024-10-26 06:15:53 +02:00
Romain Thomas b6de8801b2 Improve documentation 2024-10-19 04:39:01 +02:00
Peter Meerwald-Stadler b29613f4e9 Fix some typos in the PE Authenticode tutorial (#1083) 2024-08-02 21:27:00 +02:00
Romain Thomas 3d44a66cf9 Support more PKCS7 attributes for PE Authenticode 2024-07-20 06:04:31 +02:00
Romain Thomas e46074212d Re-scope Mach-O enums 2024-05-09 06:02:00 +02:00
Romain Thomas 6d1a230da2 Rename master branch into main 2024-04-27 06:19:02 +02:00
Romain Thomas 7a62df9b58 Re-scope ELF enums 2024-01-28 22:54:25 +01:00
Romain Thomas c01dc6af49 Update PE's ResourcesManager 2024-01-07 10:11:57 +01:00
Romain Thomas c9c3b79334 Resize images 2023-11-09 09:07:37 +01:00
Romain Thomas 78c3196d67 Refactor the ELF Note support 2023-11-09 06:26:56 +01:00
Georgi Valkov 02ecdd12b3 Use list comprehension instead of map/filter 2023-08-20 10:49:21 +02:00
Romain Thomas 6a90b3457f Refactor and clean LIEF::PE::DataDirectory 2023-07-27 21:14:38 +02:00
Kirill Smelkov a92c3148f6 doc/04_elf_hooking: Fix segmentation fault on systems where libm.so is built with GNU_IFUNC symbols
Hello up there. First of all thanks for LIEF - it looks to be very
handy. I've discovered it recently and started to go through the
tutorial, but quickly hit Segmentation Fault instead of successful
result in 04_elf_hooking, and in https://github.com/lief-project/tutorials/tree/master/04_ELF_hooking

    (1.venv) kirr@deca:~/src/tools/exe/LIEF-tutorials/04_ELF_hooking$ make run
    unset LD_LIBRARY_PATH
    ./do_math.bin 2
    cos(2) = -0.416147
    python insert_hook.py
    Hook inserted at VA: 0x344000
    Change cos!33640 -> cos!3440d0
    LD_LIBRARY_PATH=. ./do_math.bin 2
    make: *** [Makefile:17: run] Segmentation fault (core dumped)

Inspecting with gdb showed that this segmentation fault happens
because cos@got.plt entry is being set with 0x0000000a address even
though everything looks more or less ok in readelf output of updated
libm.so . Further running the example in gdb with setting hardware
watchpoint on cos@got.plt lead to seeing it is being set, expectedly, by
_dl_fixup in ld.so . To investigate I've built glibc with ld.so from
sources, added debugging prints and saw the following:

	...
        219551:     XXX DL_FIXUP 70
        219551:     symbol=cos;  lookup in file=./do_math.bin [0]
        219551:     symbol=cos;  lookup in file=./libm.so.6 [0]
        219551:       -> found it:
        219551:       sym @7f1020de6e88:
        219551:       .st_shndx: 15
        219551:       .st_value: 3440d0
        219551:       .st_size:  4b
        219551:       (weak)
        219551:       (global)
        219551:       map @7f10211260c0:
        219551:       .l_name ./libm.so.6:
        219551:       .l_addr 7f1020de1000:
        219551:       .l_ld:
        219551:         .d_tag 1:
        219551:         .d_val 1:
        219551:         .d_ptr 1:
        219551:     binding file ./do_math.bin [0] to ./libm.so.6 [0]: normal symbol `cos' [GLIBC_2.2.5]
        219551:     .ref @7f1020de6e88:
        219551:     .map @7f10211260c0:
        219551:     (after lookup)
        219551:     value:  7f10211250d0  (= addr)    <-- NOTE
        219551:     value': 7f10211250d0              <-- NOTE
        219551:     ivalue: a                         <-- NOTE
        219551:     (before fixup_plt)
        219551:     (after fixup_plt)
    Segmentation fault (core dumped)

Here we see that address of updated `cos` symbol is first correctly computed,
but after seeing that cos.st_type is GNU_IFUNC, ld.so invokes its code and uses
return value as the address to actually put into got.plt:

    https://sourceware.org/git/?p=glibc.git;a=blob;f=elf/dl-runtime.c;h=d35a725415554337746f562c3f9b16ae8295613c#l123

Since the code we built in hook uses regular FUNC - not GNU_IFUNC - binding
protocol for dynamic linking, this leads to crashes, as `hook.cos` code is used
as ifunc resolver which it did not intended to be.

The fix is simple: explicitly update hooked symbol type to be normal FUNC. Then
ld.so will use regular binding procedure for injected code irregardless of
whether libm.cos was FUNC or GNU_IFUNC.

Fixes:   https://github.com/lief-project/LIEF/issues/380
Updates: https://github.com/lief-project/tutorials/issues/4

Appendix I. ld.so debug print patch
-----------------------------------

```diff
diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
index 05f36a2507..0cb3695bdc 100644
--- a/elf/dl-lookup.c
+++ b/elf/dl-lookup.c
@@ -456,22 +456,34 @@ do_lookup_x (const char *undef_name, unsigned int new_hash,
       if (sym != NULL)
 	{
 	found_it:
+	  _dl_debug_printf("  -> found it:\n");
+	  _dl_debug_printf("  sym @%lx:\n", (unsigned long)sym);
+	  _dl_debug_printf("  .st_shndx: %d\n", sym->st_shndx);
+	  _dl_debug_printf("  .st_value: %lx\n", sym->st_value);
+	  _dl_debug_printf("  .st_size:  %lx\n", sym->st_size);
+
 	  /* Hidden and internal symbols are local, ignore them.  */
-	  if (__glibc_unlikely (dl_symbol_visibility_binds_local_p (sym)))
+	  if (__glibc_unlikely (dl_symbol_visibility_binds_local_p (sym))) {
+	    _dl_debug_printf("  (local -> skip)\n");
 	    goto skip;
+	  }

-	  if (ELFW(ST_VISIBILITY) (sym->st_other) == STV_PROTECTED)
+	  if (ELFW(ST_VISIBILITY) (sym->st_other) == STV_PROTECTED) {
+	    _dl_debug_printf("  (protected)\n");
 	    _dl_check_protected_symbol (undef_name, undef_map, ref, map,
 					type_class);
+          }

 	  switch (ELFW(ST_BIND) (sym->st_info))
 	    {
 	    case STB_WEAK:
+	      _dl_debug_printf("  (weak)\n");
 	      /* Weak definition.  Use this value if we don't find another.  */
 	      if (__glibc_unlikely (GLRO(dl_dynamic_weak)))
 		{
 		  if (! result->s)
 		    {
+	              _dl_debug_printf("  (weak -> already)\n");
 		      result->s = sym;
 		      result->m = (struct link_map *) map;
 		    }
@@ -479,18 +491,30 @@ do_lookup_x (const char *undef_name, unsigned int new_hash,
 		}
 	      /* FALLTHROUGH */
 	    case STB_GLOBAL:
+	      _dl_debug_printf("  (global)\n");
 	      /* Global definition.  Just what we need.  */
 	      result->s = sym;
 	      result->m = (struct link_map *) map;
+
+	      _dl_debug_printf("  map @%lx:\n", (unsigned long)map);
+	      _dl_debug_printf("  .l_name %s:\n", map->l_name);
+	      _dl_debug_printf("  .l_addr %lx:\n", map->l_addr);
+	      _dl_debug_printf("  .l_ld:\n");
+	      _dl_debug_printf("    .d_tag %lx:\n", map->l_ld->d_tag);
+	      _dl_debug_printf("    .d_val %lx:\n", map->l_ld->d_un.d_val);
+	      _dl_debug_printf("    .d_ptr %lx:\n", map->l_ld->d_un.d_ptr);
+
 	      return 1;

 	    case STB_GNU_UNIQUE:;
+	      _dl_debug_printf("  (unique)\n");
 	      do_lookup_unique (undef_name, new_hash, (struct link_map *) map,
 				result, type_class, sym, strtab, ref,
 				undef_map, flags);
 	      return 1;

 	    default:
+	      _dl_debug_printf("  (default)\n");
 	      /* Local symbols are ignored.  */
 	      break;
 	    }
@@ -871,6 +895,9 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
    }

+  _dl_debug_printf(".ref @%lx:\n", (unsigned long)current_value.s);
+  _dl_debug_printf(".map @%lx:\n", (unsigned long)current_value.m);
+
   *ref = current_value.s;
   return LOOKUP_VALUE (current_value.m);
 }
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index d35a725415..3f2771c5de 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -59,6 +59,8 @@ _dl_fixup (
   lookup_t result;
   DL_FIXUP_VALUE_TYPE value;

+  _dl_debug_printf("XXX DL_FIXUP %d\n", sym->st_name);
+
   /* Sanity check that we're really looking at a PLT relocation.  */
   assert (ELFW(R_TYPE)(reloc->r_info) == ELF_MACHINE_JMP_SLOT);

@@ -95,6 +97,8 @@ _dl_fixup (
       result = _dl_lookup_symbol_x (strtab + sym->st_name, l, &sym, l->l_scope,
 				    version, ELF_RTYPE_CLASS_PLT, flags, NULL);

+      _dl_debug_printf("(after lookup)\n");
+
       /* We are done with the global scope.  */
       if (!RTLD_SINGLE_THREAD_P)
 	THREAD_GSCOPE_RESET_FLAG ();
@@ -108,9 +112,11 @@ _dl_fixup (
 	 offset.  */
       value = DL_FIXUP_MAKE_VALUE (result,
 				   SYMBOL_ADDRESS (result, sym, false));
+      _dl_debug_printf("value:  %lx  (= addr)\n", value);
     }
   else
     {
+      _dl_debug_printf("(make value branch 2)\n");
       /* We already found the symbol.  The module (and therefore its load
 	 address) is also known.  */
       value = DL_FIXUP_MAKE_VALUE (l, SYMBOL_ADDRESS (l, sym, true));
@@ -119,10 +125,14 @@ _dl_fixup (

   /* And now perhaps the relocation addend.  */
   value = elf_machine_plt_value (l, reloc, value);
+  _dl_debug_printf("value': %lx\n", value);

+  // XXX here
   if (sym != NULL
-      && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0))
+      && __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)) {
     value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
+    _dl_debug_printf("ivalue: %lx\n", value);
+  }

 #ifdef SHARED
   /* Auditing checkpoint: we have a new binding.  Provide the auditing
@@ -159,7 +169,12 @@ _dl_fixup (
   if (__glibc_unlikely (GLRO(dl_bind_not)))
     return value;

-  return elf_machine_fixup_plt (l, result, refsym, sym, reloc, rel_addr, value);
+  _dl_debug_printf("(before fixup_plt)\n");
+  //return elf_machine_fixup_plt (l, result, refsym, sym, reloc, rel_addr, value);
+  DL_FIXUP_VALUE_TYPE xxx;
+  xxx = elf_machine_fixup_plt (l, result, refsym, sym, reloc, rel_addr, value);
+  _dl_debug_printf("(after fixup_plt)\n");
+  return xxx;
 }

 #ifndef PROF
@@ -175,6 +190,8 @@ _dl_profile_fixup (
 {
   void (*mcount_fct) (ElfW(Addr), ElfW(Addr)) = _dl_mcount;

+  _dl_debug_printf("XXX DL_PROFILE_FIXUP ...\n");
+
   if (l->l_reloc_result == NULL)
     {
       /* BZ #14843: ELF_DYNAMIC_RELOCATE is called before l_reloc_result
```
2023-04-06 16:38:04 +03:00
Romain Thomas 3f3a39168c Update doc 2023-04-02 14:25:18 +02:00
Romain Thomas 23305900c5 Fix link 2023-03-26 11:20:13 +02:00
Romain Thomas 69e9fd39a5 Remove PE hooking 2023-02-11 09:21:21 +01:00
Romain Thomas 47f8e708c6 Reword/fix the tutorial 2023-02-04 10:17:58 +01:00
mgunyho f24df1dfbd Add a connecting sentence 2022-11-06 15:27:51 +02:00
mgunyho 94c5e1ce7e Fix a typo 2022-11-06 15:27:36 +02:00
mgunyho 33b14a50c9 Fix math 2022-11-06 15:26:56 +02:00
mgunyho f60c7521c7 Fix a typo in the shell example 2022-11-06 15:26:56 +02:00
mgunyho 0be18d4a9f Fix typo in link 2022-11-06 15:26:56 +02:00
mgunyho d4d0ff19a2 Make Python example in tutorial stand-alone 2022-11-06 15:26:56 +02:00
Florian Loitsch 84a293950f Fix hasme typos 2022-07-27 14:33:08 +02:00
rthomas a615adbee4 This commit cleans and modernizes the code base of LIEF.
Among the changes:

- It removes the ``and, or, not`` keywords
- It updates the Documentation
- It moves the internal structures in the ``details::`` namespace
2022-01-27 20:18:54 +01:00
Philippe Ombredanne e1ae238087 Fix minor typo
Found while reading this excellent tutorial.

Signed-off-by: Philippe Ombredanne <pombredanne@nexb.com>
2021-08-18 14:02:12 +02:00
Marc Kleine-Budde ee80637030 03_elf_change_symbols.rst: fix typo 2021-06-28 15:22:32 +02:00
Romain Thomas 2737c05837 Fix typo 2021-02-02 17:27:43 +01:00
Romain Thomas fd8af3ac00 Fix typo 2021-01-22 11:19:53 +01:00
Romain Thomas 75846c5ec6 Fix table 2021-01-16 11:45:09 +01:00
Romain Thomas 1587cf5f2d Update un supported oids 2021-01-16 10:02:32 +01:00
Romain Thomas 4b9416731b Update documentation 2021-01-16 09:44:52 +01:00
Romain Thomas bdf1264df9 Update doc & tests 2021-01-16 09:44:51 +01:00
rthomas 634c2fc98e Enhance PE Authenticode 2021-01-16 09:44:51 +01:00
Romain Thomas cd286e1c08 Update doc 2021-01-07 08:43:11 +01:00
Romain Thomas ce58df93d8 Update doc build system
It enables to build documentation out-of-tree. It also introduces the
following build targets:

- lief-doc
- lief-doxygen
- lief-sphinx
- lief-quick-sphinx

See doc/CMakeLists.txt for the details
2020-12-23 07:10:17 +01:00
Romain Thomas c365a533bc Update links 2020-12-20 14:19:04 +01:00
Romain Thomas 576d791f80 Update doc 2020-12-18 18:55:09 +01:00
Adrien Guinet 48f72bd036 Enhance the bin2lib tutorial to support new glic versions
Glibc >= 2.29 versions do not allow the loading of a PIE binary with
dlopen. Explain this and how to workaround it.

An associated PR for https://github.com/lief-project/tutorials/ is
incoming
2020-09-27 11:52:02 +02:00
suletm 7daff3bf9b To fix documentation issue #392
1. Inconsistent function name fix.
2. Compilation fix as discussed in #392
2020-04-10 20:12:25 -07:00
Romain Thomas 088951ddb7 Resolve #329 2019-08-23 07:54:23 +02:00
Chris 2cc22a792f Update 09_frida_lief.rst (#330)
Fix typo
2019-08-23 07:25:32 +02:00
Cédric Tessier 9fc3a8a433 Add coredump support in LIEF 2019-04-18 07:17:46 +02:00
Romain Thomas a6adf242df Fix typo 2019-03-29 13:45:09 +01:00
Chris cb55d7501b Update 11_macho_modification.rst
Typo
2018-12-23 23:39:56 -05:00
Tim Strazzere c6ba2fd8e1 Fix list object to become an iterator 2018-11-13 15:26:30 -08:00