Dump e analisi di un binario con soli permessi di esecuzione in Linux

by andreafioraldi

September 23, 2017

#define _GNU_SOURCE
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <libgen.h> //basename

#include <iostream>
#include <string>
#include <fstream>
#include <vector>

using namespace std;

#define BINNAME "noread"


extern "C" int fake_main(int argc, char** argv, char** envp) {

    fstream maps("/proc/self/maps", fstream::in);
    string addrs;
    string nocare;
    string name;

    unsigned long last = (unsigned long)-1;
    vector<string> dumps;
    vector<string> starts;
    vector<string> ends;
    
    while(maps.good()) {
        maps >> addrs;
        maps >> nocare;
        maps >> nocare;
        maps >> nocare;
        maps >> nocare;
        getline(maps, name);

        if(string(basename((char*)name.c_str())) != BINNAME)
            continue;
        
        size_t minus = addrs.find("-");
        string start_str = addrs.substr(0, minus);
        string end_str = addrs.substr(minus +1, addrs.size() - minus -1);
        unsigned long start = stol(start_str, 0, 16);
        unsigned long end = stol(end_str, 0, 16);
        
        if(last == start) {
            dumps.back() += string((char*)start, end - start);
            ends.back() = end_str;
        }
        else {
            dumps.push_back(string((char*)start, end - start));
            starts.push_back(start_str);
            ends.push_back(end_str);
        }
        last = end;
    }
    
    maps.close();
    
    for(size_t i = 0; i < dumps.size(); ++i) {
        string outname = BINNAME "-dump-" + starts[i] + "-" + ends[i] + ".bin";
        fstream out(outname, fstream::binary | fstream::out);
        out << dumps[i];
        out.close();
        
        cout << "dumped: [" << starts[i] << ", " << ends[i] << "]" << endl;
    }

    return 0;
}

//use LD_BIND_NOW LD_PRELOAD

extern "C" int __libc_start_main (int (*main)(int, char**, char**), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end)) {

    auto functor = (int (*)(int (*) (int, char**, char**), int, char**, void (*) (void), void (*) (void), void (*) (void), void (*)))dlsym(RTLD_NEXT, "__libc_start_main");
    
    return functor(&fake_main, argc, ubp_av, init, fini, rtld_fini, stack_end);
}