微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

为什么编辑.fini_array不会改变程序的过程?

如何解决为什么编辑.fini_array不会改变程序的过程?

我正在尝试查看对.fini_array的编辑将如何导致程序流程的更改,但是似乎更改此条目不会导致任何更改。我的main是:

void cleanup() __attribute__((destructor));
int main() {
    printf("In main\n");
    exit(1);
}
void cleanup(){
    printf("Cleanning Up\n");
}
void fini_exec(){
    printf("FINI\n");
}

运行nm test000000000000119e T fini_exec

cleenup期间:0000000000001187 T cleanup

运行objdump -s -j .fini_array test

Contents of section .fini_array:
 3db0 20110000 00000000 87110000 00000000   ...............

使用十六进制编辑器,移至我从2db0获得的readelf字节,并在运行87110000后将9e110000编辑为objdump(印度语)再次

Contents of section .fini_array:
 3db0 20110000 00000000 9e110000 00000000   ...............

然后保存并重新运行仍然导致cleanup运行,我不知道为什么。不是.fini_array应该向后运行,然后是.fini,但是似乎在cleanup的其他地方有另一个引用,导致fini_exec无法运行。 / p>

解决方法

我分别使用void cleanup() __attribute__((destructor));void fini_exec() __attribute__((destructor));制作了两个独立的可执行文件a.out.1和a.out.2:

#include <stdio.h>
#include <stdlib.h>

void cleanup() __attribute__((destructor));
//void fini_exec() __attribute__((destructor));

int main() {
  printf("In main\n");
  exit(1);
}

void cleanup(){
  printf("Cleanning Up\n");
}

void fini_exec(){
  printf("FINI\n");
}

我使用以下命令生成了十六进制转储:

$ hexdump a.out.1 > a.out.1.hex
$ hexdump a.out.2 > a.out.2.hex

我比较了十六进制转储,发现标记为析构函数的函数的偏移量(0x119e和0x1187)出现在2个位置(偏移量0x580和0x2db8):

$ diff a.out.1.hex a.out.2.hex 
55,56c55,56
< 0000360 0003 0000 4e47 0055 5b7f a631 6798 4fc1
< 0000370 d865 85fc 1cc6 c187 eaab 06ab 0004 0000
---
> 0000360 0003 0000 4e47 0055 4bec d49a 80fc b24e
> 0000370 0d44 2dd5 81c9 82cb fe22 f498 0004 0000
89c89
< 0000580 119e 0000 0000 0000 4008 0000 0000 0000
---
> 0000580 1187 0000 0000 0000 4008 0000 0000 0000
173c173
< 0002db0 1120 0000 0000 0000 119e 0000 0000 0000
---
> 0002db0 1120 0000 0000 0000 1187 0000 0000 0000

因此,我编写了一个简单的修补程序工具,该工具以可执行文件名和一组偏移量作为参数来修补字节(例如,open(可执行文件),lseek(偏移量),write(字节),close(可执行文件)):

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>

int main(int ac,char *av[])
{
int            fd;
char          *fname = av[1];
unsigned char  byte;
int            offset;
int            i;
int            rc;

  if (!fname) {
    fprintf(stderr,"Usage: %s {offseth byteh...}\n",av[0]);
    return 1;
  }

  fd = open(fname,O_RDWR);
  if (fd < 0) {
    fprintf(stderr,"open(%s): '%m' (%d)\n",fname,errno);
    return 1;
  }

  i = 2;
  while (av[i] && av[i + 1]) {

    offset = strtol(av[i],NULL,0);
    byte = strtol(av[i + 1],0);

    printf("Patching @0x%x: 0x%02x\n",offset,byte);
    rc = lseek(fd,SEEK_SET);
    if (rc != offset) {
      fprintf(stderr,"lseek(%s): '%m' (%d)\n",errno);
      return 1;
    }

    rc = write(fd,&byte,1);
    if (rc != 1) {
      fprintf(stderr,"write(%s): '%m' (%d)\n",errno);
      return 1;
    }

    i += 2;

  } // End while

  close(fd);

  return 0;

} // main

当我用它修补两个地方时,析构函数将更改并按预期工作:

$ gcc patch.c -o patch
$ patch ./a.out.1 0x580 0x87 0x2db8 0x87 # cleanup()'s offset (0x1187)
Patching @0x580: 0x87
Patching @0x2db8: 0x87
$ ./a.out.1
In main
Cleanning Up
$ ./patch ./a.out.1 0x580 0x9e 0x2db8 0x9e # fini_exec()'s offset (0x119e)
Patching @0x580: 0x9e
Patching @0x2db8: 0x9e
$ ./a.out.1
In main
FINI

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。