Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/126.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 用libelf注入所需的dtu条目_C++_C_Linux_64 Bit_Elf - Fatal编程技术网

C++ 用libelf注入所需的dtu条目

C++ 用libelf注入所需的dtu条目,c++,c,linux,64-bit,elf,C++,C,Linux,64 Bit,Elf,我正在尝试向任意elf可执行文件中注入一个新的DT_所需的条目 到目前为止,我只编辑了现有的DT_NEEDED条目,其中的字符串已经存在于.dynstr部分中。这是我的密码: #define _GNU_SOURCE #include <assert.h> #include <err.h> #include <fcntl.h> #include <gelf.h> #include <limits.h> #include <stdio

我正在尝试向任意elf可执行文件中注入一个新的
DT_所需的
条目

到目前为止,我只编辑了现有的
DT_NEEDED
条目,其中的字符串已经存在于
.dynstr
部分中。这是我的密码:

#define _GNU_SOURCE
#include <assert.h>
#include <err.h>
#include <fcntl.h>
#include <gelf.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

char g_target_path[] = "/tmp/new_elf";

void copy_elf(const char *arg_path) {
  char source_path[PATH_MAX];
  realpath(arg_path, source_path);

  FILE *source, *target;

  source = fopen(source_path, "rb");
  assert(source != NULL);
  target = fopen(g_target_path, "wb");
  assert(target != NULL);

  size_t n, m;
  unsigned char buff[8192];
  do {
    n = fread(buff, 1, sizeof buff, source);
    if (n != 0)
      m = fwrite(buff, 1, n, target);
    else
      m = 0;
  } while ((n > 0) && (n == m));
  assert(m == 0);

  assert(fclose(target) == 0);
  assert(fclose(source) == 0);
}

void inject_dt_needed(const char *elf_path) {
  assert(elf_version(EV_CURRENT) != EV_NONE);

  int fd = open(elf_path, O_RDWR, 0);
  assert(fd >= 0);

  Elf *elf = elf_begin(fd, ELF_C_RDWR, NULL);
  assert(elf != NULL);
  assert(elf_kind(elf) == ELF_K_ELF);

  elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT);

  Elf_Scn *scn = NULL;
  while ((scn = elf_nextscn(elf, scn)) != NULL) {
    GElf_Shdr shdr = {0};
    assert(gelf_getshdr(scn, &shdr) == &shdr);

    if (shdr.sh_type == SHT_DYNAMIC) {
      Elf_Data *data = NULL;
      data = elf_getdata(scn, data);
      assert(data != NULL);

      size_t sh_entsize = gelf_fsize(elf, ELF_T_DYN, 1, EV_CURRENT);

      for (size_t i = 0; i < shdr.sh_size / sh_entsize; i++) {
        GElf_Dyn dyn = {0};
        assert(gelf_getdyn(data, (int)i, &dyn) == &dyn);

        if (dyn.d_tag == DT_NEEDED) {
          printf("DT_NEEDED detected: %s string offset: %ld\n",
                 elf_strptr(elf, shdr.sh_link, dyn.d_un.d_val), dyn.d_un.d_val);

          // Update a DT_NEEDED inplace.
          dyn.d_un.d_val = 1;
          assert(gelf_update_dyn(data, (int)i, &dyn) != 0);
        }
      }
    }
  }

  assert(elf_update(elf, ELF_C_WRITE) >= 0);

  assert(elf_end(elf) == 0);
  assert(close(fd) == 0);
}

int main(int argc, char const *argv[]) {
  if (argc != 2)
    errx(EXIT_FAILURE, "Please give a path to an elf.");

  copy_elf(argv[1]);
  inject_dt_needed(g_target_path);
  return 0;
}

如何添加所需的任意额外
dtu
条目

我试图创建一个新的
.dynamic
部分,如下所示:

void inject_dt_needed(const char *elf_path) {
  assert(elf_version(EV_CURRENT) != EV_NONE);

  int fd = open(elf_path, O_RDWR, 0);
  assert(fd >= 0);

  Elf *elf = elf_begin(fd, ELF_C_RDWR, NULL);
  assert(elf != NULL);
  assert(elf_kind(elf) == ELF_K_ELF);

  elf_flagelf(elf, ELF_C_SET, ELF_F_LAYOUT);

  Elf_Scn *scn = NULL;
  while ((scn = elf_nextscn(elf, scn)) != NULL) {
    GElf_Shdr shdr = {};
    assert(gelf_getshdr(scn, &shdr) == &shdr);

    if (shdr.sh_type == SHT_DYNAMIC) {
      Elf_Data *data = NULL;
      data = elf_getdata(scn, data);
      assert(data != NULL);

      Elf_Scn *n_scn = elf_newscn(elf);
      assert(n_scn != NULL);

      Elf_Data *n_data = elf_newdata(n_scn);
      assert(n_data != NULL);

      *n_data = *data;

      GElf_Shdr n_shdr = {};
      assert(gelf_getshdr(n_scn, &n_shdr) == &n_shdr);

      n_shdr = shdr;

      assert(gelf_update_shdr(n_scn, &n_shdr) != 0);

      shdr.sh_name = 0;
      assert(gelf_update_shdr(scn, &shdr) != 0);

      elf_flagscn(n_scn, ELF_C_SET, ELF_F_DIRTY);
      elf_flagshdr(n_scn, ELF_C_SET, ELF_F_DIRTY);
      elf_flagdata(n_data, ELF_C_SET, ELF_F_DIRTY);
      assert(elf_update(elf, ELF_C_NULL) >= 0);
      break;
    }
  }

  assert(elf_update(elf, ELF_C_WRITE) >= 0);

  assert(elf_end(elf) == 0);
  assert(close(fd) == 0);
}
但由于某种原因,当我将原始elf与新生成的elf进行比较时,额外的部分没有标题信息,而我看到旧的
。dynamic
部分已被删除:

$ diff <(readelf -a /tmp/new_elf) <(readelf -a ./elftarget)
readelf: Error: no .dynamic section in the dynamic segment
19c19
<   Number of section headers:         36
---
>   Number of section headers:         35
69c69
<   [22]                   DYNAMIC          0000000000200d78  00000d78
---
>   [22] .dynamic          DYNAMIC          0000000000200d78  00000d78
95,96d94
<   [35]                   NULL             0000001400000001  00000000
<        000000000160c260  0000000000000000 WSIx       2     1     544
133,134c131,132
<    03     .preinit_array .init_array .fini_array  .got .data .bss
<    04
---
>    03     .preinit_array .init_array .fini_array .dynamic .got .data .bss
>    04     .dynamic
138c136
<    08     .preinit_array .init_array .fini_array  .got
---
>    08     .preinit_array .init_array .fini_array .dynamic .got
$diff[22]。动态0000000000 200D78 00000d78
95,96d94
<[35]空000000 140000001 00000000
<000000000 160C260 0000000000000000 WSIx 2 1 544
133134C131132
<03.preinit_数组.init_数组.fini_数组.got.data.bss
<    04
---
>03.preinit_数组.init_数组.fini_数组.dynamic.got.data.bss
>04.动态
138c136
<08.preinit\u数组。init\u数组。fini\u数组。获取
---
>08.preinit_数组.init_数组.fini_数组.dynamic.get

关于<代码>GElf_Shdr Shdr={}通过
gcc
编译器运行会导致:untitled1.c:65:24:警告:ISO c禁止使用空的初始值设定项大括号[-Wpedantic]。还有很多其他的编译问题。编译时,始终启用警告,然后修复这些警告。(对于
gcc
,至少使用:
-Wall-Wextra-Wconversion-pedantic-std=gnu11
)注意:其他编译器使用不同的选项来产生相同的结果
$ diff <(readelf -a /tmp/new_elf) <(readelf -a ./elftarget)
readelf: Error: no .dynamic section in the dynamic segment
19c19
<   Number of section headers:         36
---
>   Number of section headers:         35
69c69
<   [22]                   DYNAMIC          0000000000200d78  00000d78
---
>   [22] .dynamic          DYNAMIC          0000000000200d78  00000d78
95,96d94
<   [35]                   NULL             0000001400000001  00000000
<        000000000160c260  0000000000000000 WSIx       2     1     544
133,134c131,132
<    03     .preinit_array .init_array .fini_array  .got .data .bss
<    04
---
>    03     .preinit_array .init_array .fini_array .dynamic .got .data .bss
>    04     .dynamic
138c136
<    08     .preinit_array .init_array .fini_array  .got
---
>    08     .preinit_array .init_array .fini_array .dynamic .got