最近几天一直在做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);
。。。。。。
}
数据包由协议层最终都交给了应用层