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