直接从C中的(共享)-memory执行二进制文件/ elf文件

时间:2017-06-14 11:50:06

标签: c gcc binary executable elf

我们正在尝试将二进制/ elf文件复制到系统的共享内存区域,然后再执行它。我们不想直接调用我们的“客户端”程序,因为我们需要从内存本身为我们的目的执行它。

虽然我们知道我们的方法(下面描述)不会真正起作用,但我们(显然是)试图让它发挥作用。怎么可能复制二进制/精灵/等。直接归档到(共享)-memory并在此后执行?也许我们只是以错误的方式编译它?或其他事情做错了?

我们也不想将其转换为hex / shell-code,我们已经这样做了。我们正在寻找一种更简单,更实用的解决方案。

有人能帮忙吗?非常感谢!

两个程序:

  1. “主机” - 程序(复制和执行共享内存中的客户端程序
  2. “客户端” - 程序(基本上是一个hello-world echo
  3. “客户端” - 程序:

    #include <stdio.h>
    int main()
    {
        printf("Hello, World!\n");
        return 0;
    }
    

    使用gcc -o binfile clientprogram.c -static编译。

    “主机” - 程序:

    #include <string.h>
    #include <sys/mman.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(int argc, char **argv)
    {
      FILE *fp; //filepointer
      size_t size; //filesize
      unsigned char *buffer; //buffer
    
      fp = fopen("binfile","rb"); 
      fseek(fp, 0, SEEK_END); 
      size = ftell(fp);
      fseek(fp, 0, SEEK_SET); 
      buffer = (unsigned char *) malloc(size);
      if (fp == NULL){ //file empty?
          printf("Error: There was an Error reading the file %s \n", "binfile");           
          exit(1);
      }
      else if (fread(buffer, sizeof *buffer, size, fp) != size){ 
          printf("Error: There was an Error reading the file %s\n", "binfile");
          exit(1);
      }else{
        int i;
        // for(i=0; i<size;i++){       
        //    printf("%02x", buffer[i]);
        // }
      }
    
    
      void *mem = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0);
      memcpy(mem, buffer, size);
      mprotect(mem, size, PROT_READ|PROT_WRITE|PROT_EXEC);
    
      void (*func)();
      func = (void (*)()) buffer;
      func();  
    
      munmap(mem, size);
    
      fclose(fp);
      free(buffer);
      return 0;
    }
    

    使用gcc hostprogram.c编译。

2 个答案:

答案 0 :(得分:3)

使用import IdentifierName 1.0 Rectangle { id: nameRectangle width: 999 height: 999 onSomethingChange: { execFunction(); } property NameYourClass nameDesired: nameObject NameYourClass { id: nameObject intProperty1: 999 } function execFunction() { var varExample; varExample = nameDesired.getIntProperty1(); nameDesired.setIntProperty1(varExample); } } 将客户端构建为PIE。然后,您就可以-rdynamic dlopen() dlsym()符号(main dlopen() mmapmprotect对于您,因为您将能够看到您是否strace该程序,之后您将能够在主机的地址空间内运行其main

示例:

#!/bin/sh
cat > client.c <<EOF
#include <stdio.h>
#include <unistd.h>
int main()
{
    printf("Hello, World!: from %ld\n", (long)getpid());
    return 0;
}
EOF

gcc -fpic -c client.c
gcc -pie -rdynamic -o client client.o

cat > host.c <<EOF
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
    printf("Hello, I'm your host: %ld\n", (long)getpid());  ;

    void *client_hndl;
    typedef int main_t(int, char**);
    main_t *client_main;
    client_hndl = dlopen("./client",  RTLD_LAZY);
    if (!client_hndl){
        fprintf(stderr, "%s\n", dlerror());
        exit(1);
    }
    client_main = (main_t*)dlsym(client_hndl, "main");
    if (!client_main){
        fprintf(stderr, "%s\n", dlerror());
        exit(2);
    }
    return client_main(1, (char*[]){"client", 0});
}
EOF
gcc host.c -ldl
./client
echo =============
./a.out

示例输出:

Hello, World!: from 14520
=============
Hello, I'm your host: 14521
Hello, World!: from 14521

答案 1 :(得分:0)

您正在寻找此GLIBC feature request的解决方案。

此功能请求已有7年历史,并且很快就会发生任何事情。

你最好的选择可能是大致完成你正在做的事情(建立一个完全静态的二进制文件)。

您的方法无效,因为您构建的可执行文件需要加载到其链接的地址(在readelf -l binfile中显示为第一个PT_LOAD的地址1}}段。您需要mmap binfile MAP_FIXED Elf{32,64}_Ehdr,其他地址都不会。

您还需要读取并解码在文件开头找到的python -m designer 以找到要跳转到的入口点。您当前正在跳转到ELF标头本身,但该标头不是执行应该开始的位置。