ettercap-0.7.3源码浅析

最近几天一直在做openwrt下的审计抓包,发现有现成的嗅探工具ettercap,于是就修改了源码拿来用。在这里记录下这几天对这个源码的浅显的理解,不正确的地方还请大虾们多多指点。

0:命令行指行以下命令
    ettercap -i wlan0 -Tq -L 123

1,src/ec_main.c中的两个重要的调用top_half和ui_start
int main(int argc, char *argv[])
{
          ................//各种初始化
           
            ec_thread_new("top_half", "dispatching module", & top_half, NULL);

           
            ec_thread_register(EC_PTHREAD_SELF, GBL_PROGRAM, "the user interface");
            ui_start();

           
            .....................//退出时释放内存及销毁线程
            return 0;
}

2,src/ec_dispatcher.c 中的top_half分析

EC_THREAD_FUNC(top_half)
{
    struct po_queue_entry *e;
    u_int pck_len; 

    LOOP { 
        .................//循环从队列中读数据
        hook_point( HOOK_DISPATCHER, e->po);     //遍历执行 HOOK_DISPATCHER 点的函数
        .........
    }

  return NULL;
}

3, HOOK_DISPATCHER  中的函数log_packet
目录src/ec_log.c

int set_loglevel(int level, char *filename)
{
          。。。。。。。。。
              hook_add(HOOK_DISPATCHER, &log_packet);     //将log_packet函数加入此点
          。。。。。。。。。
}

log_packet函数是用来记录所有捕获到的数据包的。


4, ui_start()    位于src/ec_ui.c中,它调用了 GBL_UI->start 所指向的函数
void ui_start(void)
{
    DEBUG_MSG("ui_start");

    if (GBL_UI->initialized)
      EXECUTE(GBL_UI->start);
    else
      DEBUG_MSG("ui_start called initialized");
}

5, src/ec_ui.c 中ui_register()函数中对其付值
void ui_register(struct ui_ops *ops)
{
         
    BUG_IF(ops->init == NULL);
    GBL_UI->init = ops->init;
   
    BUG_IF(ops->cleanup == NULL);
    GBL_UI->cleanup = ops->cleanup;
   
    BUG_IF(ops->start == NULL);
    GBL_UI->start = ops->start;
         
    BUG_IF(ops->msg == NULL);
    GBL_UI->msg = ops->msg;
   
    BUG_IF(ops->error == NULL);
    GBL_UI->error = ops->error;
   
    BUG_IF(ops->fatal_error == NULL);
    GBL_UI->fatal_error = ops->fatal_error;
   
    BUG_IF(ops->input == NULL);
    GBL_UI->input = ops->input;
   
    BUG_IF(ops->progress == NULL);
    GBL_UI->progress = ops->progress;

    GBL_UI->type = ops->type;
}

6, 有几个调用 ui_register() 函数的地方,最好确定本次执行程序是在此处调用:    src/interfaces/text/ec_text.c
void set_text_interface(void)
{
    struct ui_ops ops;

   
    memset(&ops, 0, sizeof(ops));

   
    ops.init = &text_init;
    ops.start = &text_interface;
    ops.cleanup = &text_cleanup;
    ops.msg = &text_msg;
    ops.error = &text_error;
    ops.fatal_error = &text_fatal_error;
    ops.input = &text_input;
    ops.progress = & text_progress;
    ops.type = UI_TEXT;
   
    ui_register(&ops);
   
   
    hook_add(HOOK_DISPATCHER, text_print_packet);
}

7, 由以上程序确定最终调用了 text_interface()函数

void text_interface(void)
{
    。。。。。。。。。。

   
   EXECUTE(GBL_SNIFF->start);

    。。。。。。
    LOOP {
.../等待用户输入,text交户界面
    }
}

8,  EXECUTE(GBL_SNIFF->start)   这是一个很重要的调用,它的赋值是在src/ec_sniff.c中
void set_sniffing_method(struct sniffing_method *sm)
{
   
    memcpy(GBL_SNIFF, sm, sizeof(struct sniffing_method));
   
    GBL_SNIFF->active = 0;
}

void set_unified_sniff(void)
{
    struct sniffing_method sm;

    DEBUG_MSG("set_unified_sniff");
   
    sm.type = SM_UNIFIED;
    sm.start = & start_unified_sniff;
    sm.cleanup = &stop_unified_sniff;
    sm.check_forwarded = &unified_check_forwarded;
    sm.set_forwardable = &unified_set_forwardable;
   
    sm.forward = &forward_unified_sniff;
    sm.interesting = &set_interesting_flag;

    set_sniffing_method(&sm);
}

9,ui_start中的调用最终是调用了start_unified_sniff()函数(src/ec_sniff_unified.c)
#include
#include
#include
#include
#include
#include
#include
void start_unified_sniff(void)
{
    DEBUG_MSG("start_unified_sniff");
   
    if (GBL_SNIFF->active == 1) {
      USER_MSG("Unified sniffing already started...\n");
      return;
    }
   
    USER_MSG("Starting Unified sniffing...\n\n");
   
   
    if (!GBL_OPTIONS->read) { 
      pthread_t pid;
       
      pid = ec_thread_getpid("timer");
      if (pthread_equal(pid, EC_PTHREAD_NULL))
          ec_thread_new("timer", "conntrack timeouter", & conntrack_timeouter, NULL);
    }

   
    ec_thread_new("capture", "pcap handler and packet decoder", & capture, GBL_OPTIONS->iface);

   
    if (!GBL_OPTIONS->read && !GBL_OPTIONS->unoffensive && !GBL_OPTIONS->only_mitm)
      ec_thread_new("sslwrap", "wrapper for ssl connections", & sslw_start, NULL);

    GBL_SNIFF->active = 1;
}

在start_unified_sniff 函数里启用了三个线程,分别是 conntrack_timeouter   capture、 sslw_start,其中 capture是用来捕捉数据包的。

10, src/ec_capture.c 中capture()函数
EC_THREAD_FUNC(capture)
{
    int ret;
   
   
    ec_thread_init();
   
    DEBUG_MSG("neverending loop (capture)");

   
    stats_wipe();
   
   
   ret = pcap_loop(GBL_PCAP->pcap, -1, ec_decode, EC_THREAD_PARAM);
    ON_ERROR(ret, -1, "Error while capturing: %s", pcap_geterr(GBL_PCAP->pcap));
   
    return NULL;
}

pcap_loop函数见百度百科(用于捕捉数据包)。ec_decode()函数用于当捕捉到数据包时处理数据包。

11, src/ec_decode.c中ec_decode函数
void ec_decode(u_char *param, const struct pcap_pkthdr *pkthdr, const u_char *pkt)
{

   
..................
   
    stats_half_start(&GBL_STATS->bh);

..................
   
   packet_create_object(&po, data, datalen);

............
     
    hook_point( HOOK_RECEIVED, &po);
   
.............
    packet_decoder = get_decoder( LINK_LAYER, GBL_PCAP->dlt);
    BUG_IF(packet_decoder == NULL);
    packet_decoder(data, datalen, &len, &po);
    ..........
    if ( (po.flags & PO_FORWARDABLE) && !(po.flags & PO_FORWARDED) ) {
       
      hook_point(HOOK_PRE_FORWARD, &po);
      EXECUTE(GBL_SNIFF->forward, &po);
    }
    .............
   
    if (GBL_OPTIONS->read && GBL_PCAP->dump_size == GBL_PCAP->dump_off) {
      po.flags |= PO_EOF;
      top_half_queue_add(&po);
    }
    ...........
    return;
}

上述2中所说的从队列中读取数据,数据是在哪里写入队列的呢,对,就是这里: top_half_queue_add(&po);

    packet_decoder = get_decoder( LINK_LAYER, GBL_PCAP->dlt);
    BUG_IF(packet_decoder == NULL);
    packet_decoder(data, datalen, &len, &po);   这三行代码是将捕捉到的数据包交给了链路层进行处理,经测试发现是交给了src/protocols/ec_eth.c文件中的decode_eth函数进行处理。

12, src/protocols/ec_eth.c文件(链路层)中:
void __init eth_init(void)
{
   add_decoder(LINK_LAYER, IL_TYPE_ETH, decode_eth);
    add_builder(IL_TYPE_ETH, build_eth);
    add_aligner(IL_TYPE_ETH, align_eth);
}

FUNC_DECODER(decode_eth)
{
    FUNC_DECODER_PTR(next_decoder);
    struct eth_header *eth;

    DECODED_LEN = sizeof(struct eth_header);
   
    eth = (struct eth_header *)DECODE_DATA;

   
    PACKET->L2.header = (u_char *)DECODE_DATA;
    PACKET->L2.proto = IL_TYPE_ETH;
    PACKET->L2.len = DECODED_LEN;
   
    memcpy(PACKET->L2.src, eth->sha, ETH_ADDR_LEN);
    memcpy(PACKET->L2.dst, eth->dha, ETH_ADDR_LEN);

   
    hook_point(HOOK_PACKET_ETH, po);
   
       
    next_decoder = get_decoder(NET_LAYER, ntohs(eth->proto));

    EXECUTE_DECODER(next_decoder);
       
   
   
    return NULL;
}

这个函数又将数据包交给了网络层

13,src/protocols/ec_ip.c   (网络层)
void __init ip_init(void)
{
    add_decoder(NET_LAYER, LL_TYPE_IP, decode_ip);
    add_injector(CHAIN_LINKED, IP_MAGIC, inject_ip);
    add_injector(CHAIN_LINKED, STATELESS_IP_MAGIC, stateless_ip);
}

FUNC_DECODER(decode_ip)
{
  。。。。。。。
   
    next_decoder = get_decoder(PROTO_LAYER, ip->protocol);
    EXECUTE_DECODER(next_decoder);
  。。。。。。。
}

这个函数又将数据包交给了协议层,ip->protocol这个参数会区分tcp协议还是udp协议

14,src/protocols/ec_udp.c   src/protocols/ec_tcp.c(协议层)
void __init udp_init(void)
{
    add_decoder(PROTO_LAYER, NL_TYPE_UDP, decode_udp);
    add_injector(CHAIN_ENTRY, NL_TYPE_UDP, inject_udp);
}

FUNC_DECODER(decode_udp)
{
  。。。。。。
     
    next_decoder =  get_decoder(APP_LAYER, PL_DEFAULT);
    EXECUTE_DECODER(next_decoder);
  。。。。。。
}



void __init tcp_init(void)
{
    add_decoder(PROTO_LAYER, NL_TYPE_TCP, decode_tcp);
    add_injector(CHAIN_ENTRY, NL_TYPE_TCP, inject_tcp);
}


FUNC_DECODER(decode_tcp)
{
  。。。。。。
   
   next_decoder =  get_decoder(APP_LAYER, PL_DEFAULT);
    EXECUTE_DECODER(next_decoder);
  。。。。。。
}
数据包由协议层最终都交给了应用层








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值