elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: (TUTORIAL) Aprende a emular Sentinel Dongle By Yapis


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación General
| | |-+  [C++ & Qt][Linux] Crear un builder
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: [C++ & Qt][Linux] Crear un builder  (Leído 1,974 veces)
0xDani


Desconectado Desconectado

Mensajes: 1.077



Ver Perfil
[C++ & Qt][Linux] Crear un builder
« en: 17 Julio 2013, 16:27 pm »

Bueno, tal y como me han pedido, aquí pongo el código de un server builder en Qt para Linux.

Lo primero, el código del server:

Código
  1. #include <iostream>
  2. #include <iomanip>
  3.  
  4. static char ip[30] __asm__("__IP__") = "__IP__ here";
  5. static char port[30] __asm__ ("__PORT__") = "__PORT__ here";
  6.  
  7. int main(int argc, char **argv)
  8. {
  9.  
  10. std::cout << "ip address: " << std::hex << (void*) ip << std::endl;
  11. std::cout << "port address: " << std::hex << (void*) port << std::endl;
  12.  
  13. std::cout << "IP: " << ip << std::endl;
  14. std::cout << "Port: " << port << std::endl;
  15.  
  16.  
  17. /* ... */
  18.  
  19. return 0;
  20. }

Analicemos el código: tiene dos variables globales, para asegurarnos de que esas variables van a ser incluidas en la sección .data del ejecutable como símbolos. También nos aseguramos de que estos símbolos tengan el nombre que queramos ("__IP__" y "__PORT__") con la directiva de ensamblador.

Las cadenas que les asigno son para que se puedan ver en un editor hexadecimal.

Bien, ahora el builder, que se va encargar de que cuando ejecutemos el server, en esas dos variables estén la IP y el puerto.

mainwindow.hpp
Código
  1. #ifndef MAINWINDOW_HPP
  2. #define MAINWINDOW_HPP
  3.  
  4. #include <QMainWindow>
  5. #include <QWidget>
  6. #include <QVBoxLayout>
  7. #include <QLineEdit>
  8. #include <QPushButton>
  9.  
  10. #include <unistd.h>
  11. #include <fcntl.h>
  12. #include <sys/stat.h>
  13. #include <sys/mman.h>
  14. #include <elf.h>
  15. #include <stdint.h>
  16. #include <cstring>
  17.  
  18. #include <iostream>
  19. #include <iomanip>
  20.  
  21. class MainWindow : public QMainWindow
  22. {
  23.    Q_OBJECT
  24.  
  25. public:
  26.    MainWindow(QWidget *parent = 0);
  27.    ~MainWindow();
  28.  
  29. public slots:
  30.    void onButton();
  31.  
  32. private:
  33.    QWidget     *centralWidget; // Central widget
  34.    QVBoxLayout *layout;        // Window's layout
  35.    QLineEdit   *ipEdit;        // Edit for the IP
  36.    QLineEdit   *portEdit;      // Edit for the port
  37.    QPushButton *button;        // Button to build the server
  38. };
  39.  
  40. #endif // MAINWINDOW_HPP

mainwindow.cpp
Código
  1. #include "mainwindow.hpp"
  2.  
  3. MainWindow::MainWindow(QWidget *parent)
  4.    : QMainWindow(parent)
  5. {
  6.    /* Constructor to build the GUI */
  7.  
  8.    centralWidget = new QWidget();
  9.    layout = new QVBoxLayout();
  10.  
  11.    ipEdit = new QLineEdit();
  12.    portEdit = new QLineEdit();
  13.  
  14.    button = new QPushButton("Build!");
  15.  
  16.    layout->addWidget(ipEdit);
  17.    layout->addWidget(portEdit);
  18.    layout->addWidget(button);
  19.  
  20.    centralWidget->setLayout(layout);
  21.    setCentralWidget(centralWidget);
  22.  
  23.    connect(button, SIGNAL(clicked()), this, SLOT(onButton()));
  24. }
  25.  
  26. MainWindow::~MainWindow()
  27. {
  28.    /* Delete reserved objects */
  29.  
  30.    delete ipEdit;
  31.    delete portEdit;
  32.    delete button;
  33.    delete layout;
  34.    delete centralWidget;
  35. }
  36.  
  37. void MainWindow::onButton()
  38. {
  39.    int fdIn, fdOut; // Input and output files
  40.  
  41.    fdIn = open("server", O_RDONLY); // Open input file
  42.  
  43.    struct stat st;
  44.    fstat(fdIn, &st); // Get input file size
  45.  
  46.    /* Map input file into memory */
  47.    void *map = mmap(0, st.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fdIn, 0);
  48.  
  49.    Elf32_Ehdr *hdr = (Elf32_Ehdr*) map; /* Get the ELF header,
  50.                                             that's at the start of the file*/
  51.  
  52.    /* Get pointer to the ELF sections */
  53.    Elf32_Shdr *sections = (Elf32_Shdr*) ((char*) map + hdr->e_shoff);
  54.  
  55.    /* Get pointer to the .shstrtab section content */
  56.    char *shStrTabData = (char*) map+sections[hdr->e_shstrndx].sh_offset;
  57.  
  58.    Elf32_Shdr tabs[2]; // First symtab, second strtab
  59.  
  60.  
  61.    /* Find and save .symtab and .strtab sections */
  62.    const char *sectionNames[] = {".symtab", ".strtab"};
  63.    for(int i=0; i<2; i++)
  64.    {
  65.        for(int j=0; j<hdr->e_shnum; j++)
  66.        {
  67.            if(!strcmp(shStrTabData+sections[j].sh_name, sectionNames[i]))
  68.            {
  69.                tabs[i] = sections[j];
  70.                break;
  71.            }
  72.        }
  73.    }
  74.  
  75.    //std::cout << ".symtab at offset " << std::hex << tabs[0].sh_offset << std::endl;
  76.    //std::cout << ".strtab at offset " << std::hex << tabs[1].sh_offset << std::endl;
  77.  
  78.    /* Get pointer to the .strtab section content */
  79.    char *strTabData = (char*) map + tabs[1].sh_offset;
  80.  
  81.    /* Get pointer to the symbols in the .symtab section */
  82.    Elf32_Sym *syms = (Elf32_Sym*) ((char*) map + tabs[0].sh_offset);
  83.  
  84.    Elf32_Sym toModify[2]; // First __IP__, second __PORT__
  85.  
  86.    const char *symbolNames[] = {"__IP__", "__PORT__"};
  87.  
  88.  
  89.    // Find and save the symbols we want to modify
  90.    for(int i=0; i<2; i++)
  91.    {
  92.        for(unsigned int j=0; j<(tabs[0].sh_size/sizeof(Elf32_Sym)); j++)
  93.        {
  94.            if(!strcmp(strTabData+syms[j].st_name, symbolNames[i]))
  95.            {
  96.                toModify[i] = syms[j];
  97.            }
  98.        }
  99.    }
  100.  
  101.    //std::cout << "__IP__ value: " << std::hex << toModify[0].st_value << std::endl;
  102.    //std::cout << "__PORT__ value: " << std::hex << toModify[1].st_value << std::endl;
  103.  
  104.    Elf32_Off ipOff, portOff;
  105.  
  106.  
  107.    /* Find symbols offsets: get symbol offset into the section that
  108.        contains the symbol: symbol_address - section_base_address; and then
  109.        add the offset of the section into the file                       */
  110.    ipOff = toModify[0].st_value - sections[toModify[0].st_shndx].sh_addr +
  111.            sections[toModify[0].st_shndx].sh_offset;
  112.  
  113.    portOff = toModify[1].st_value - sections[toModify[1].st_shndx].sh_addr +
  114.            sections[toModify[1].st_shndx].sh_offset;
  115.  
  116.    //std::cout << "__IP__ section: " << shStrTabData+sections[toModify[0].st_shndx].sh_name << std::endl;
  117.    //std::cout << "__PORT__ section: " << shStrTabData+sections[toModify[1].st_shndx].sh_name << std::endl;
  118.  
  119.  
  120.    //std::cout << "__IP__ offset: " << std::hex << ipOff << std::endl;
  121.    //std::cout << "__PORT__ offset: " << std::hex << portOff << std::endl;
  122.  
  123.    // Put the text in the edit in the file at the offsets
  124.    strcpy((char*) map+ipOff, ipEdit->text().toStdString().c_str());
  125.    strcpy((char*) map+portOff, portEdit->text().toStdString().c_str());
  126.  
  127.  
  128.    /* Open output file and write the memory map to it */
  129.    fdOut = open("server-built", O_TRUNC|O_CREAT|O_WRONLY, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IROTH);
  130.  
  131.    write(fdOut, map, st.st_size);
  132.  
  133.    ::close(fdOut);
  134.  
  135.  
  136.    munmap(map, st.st_size);
  137.  
  138.    ::close(fdIn);
  139. }
  140.  

main.cpp
Código
  1. #include "mainwindow.hpp"
  2. #include <QApplication>
  3.  
  4. int main(int argc, char *argv[])
  5. {
  6.    QApplication a(argc, argv);
  7.    MainWindow w;
  8.    w.show();
  9.  
  10.    return a.exec();
  11. }

Lo primero, este último código funciona sólo para ejecutables de 32 bits, pero se puede portar fácilmente.

¿Cómo funciona?

Pues los ejecutables ELF suelen tener una tabla de strings con los nombres de todas las secciones (la sección .shstrtab). Con esa tabla, encontramos las secciones .symtab (la tabla de símbolos) y la .strtab (la tabla de strings de símbolos).

Comparando los nombres de cada símbolo con los que hay en la tabla, encotramos los dos que queremos modificar. No tenemos el offset de estos símbolos directamente, así que tenemos que hallarlo. Tenemos la dirección del símbolo una vez cargado en memoria, la sección en la que se encuentra este símbolo (y por tanto la dirección de esta sección en memoria y el offset de esta sección en el archivo); así que hacemos la siguiente cuenta:

        Dirección del símbolo - Dirección base de la sección + Offset de la sección en el archivo

Eso corresponde a esta parte del código:

Código
  1. ipOff = toModify[0].st_value - sections[toModify[0].st_shndx].sh_addr +
  2.           sections[toModify[0].st_shndx].sh_offset;
  3.  
  4.   portOff = toModify[1].st_value - sections[toModify[1].st_shndx].sh_addr +
  5.           sections[toModify[1].st_shndx].sh_offset;

Luego escribimos el texto de los edits en el mapa de memoria en el offset de cada símbolo, de forma que cuando se carguen en memoria contengan esos datos, y nuestro server pueda conectar a la IP y por el puerto indicado.

Bueno, hace falta conocimiento del formato ELF para entender esto totalmente, así que más información aquí y también se pueden preguntar dudas.

Saludos!


En línea

I keep searching for something that I never seem to find, but maybe I won't, because I left it all behind!

I code for $$$
Hago trabajos en C/C++
Contactar por PM
OmarHack


Desconectado Desconectado

Mensajes: 1.268


Ver Perfil
Re: [C++ & Qt][Linux] Crear un builder
« Respuesta #1 en: 17 Julio 2013, 17:06 pm »

Muy bueno el aporte.
Tengo una duda, ¿los datos de ips se actualizan automáticamente? Es decir:
Si el objetivo ejecuta el server y tiene una ip dinámica el programa actualiza la ip del objetivo automáticamente? ¿O tendría que volver a ejecutar el server para que se tome su nueva ip?


En línea

I like to test things.
0xDani


Desconectado Desconectado

Mensajes: 1.077



Ver Perfil
Re: [C++ & Qt][Linux] Crear un builder
« Respuesta #2 en: 17 Julio 2013, 17:24 pm »

Muy bueno el aporte.
Tengo una duda, ¿los datos de ips se actualizan automáticamente? Es decir:
Si el objetivo ejecuta el server y tiene una ip dinámica el programa actualiza la ip del objetivo automáticamente? ¿O tendría que volver a ejecutar el server para que se tome su nueva ip?

Bueno, eso es flipar mucho y no depende del builder. La verdad no creo que haya ningún server que haga eso. Lo que se suele hacer es conseguirse un dominio de no-ip.

Yo nunca he encontrado como hacer esto en Linux y lo tuve que implementar mirando la man page, a ver si ahora alguien se anima a hacer alguna criatura para Linux.
En línea

I keep searching for something that I never seem to find, but maybe I won't, because I left it all behind!

I code for $$$
Hago trabajos en C/C++
Contactar por PM
OmarHack


Desconectado Desconectado

Mensajes: 1.268


Ver Perfil
Re: [C++ & Qt][Linux] Crear un builder
« Respuesta #3 en: 17 Julio 2013, 17:38 pm »

Ahh claro claro, estupidez mía.
En línea

I like to test things.
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
crear un jar que se ejecute en linux, o un como exec en linux « 1 2 »
Java
moyo18 13 10,266 Último mensaje 3 Mayo 2010, 18:38 pm
por moyo18
Como crear Builder en C#? « 1 2 »
.NET (C#, VB.NET, ASP)
Edu 12 7,064 Último mensaje 23 Febrero 2011, 16:57 pm
por Edu
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines