Contiki-NG黑洞攻击实现中memcpy无法更新MAC输入指针的问题
问题原因
- 只读内存段保护:tsch.c里的
tsch_mac_driver被声明为const,编译后会被放到只读数据段(.rodata)。Z1节点这类嵌入式系统会阻止对只读段的写入操作,你用memcpy修改的操作实际上没生效,所以NETSTACK_MAC.input地址看起来没变,自定义函数也不会触发。 - 结构体指针指向只读区域:
NETSTACK_MAC是指向这个const结构体的指针,直接修改结构体成员的操作在内存保护下会被静默忽略,不会真正替换函数指针。
修复方案
方案1:移除TSCH驱动的const修饰(最直接)
- 找到tsch.c里的
tsch_mac_driver定义,删掉const:// 原代码 const struct mac_driver tsch_mac_driver = { ... }; // 修改后 struct mac_driver tsch_mac_driver = { ... }; - 之后直接用赋值替换函数指针,比memcpy更简洁:
NETSTACK_MAC->input = malicious_packet_input;
方案2:替换NETSTACK_MAC指针(不修改核心驱动)
- 定义一个非const的MAC驱动结构体,复制原驱动的所有成员,再替换input函数:
struct mac_driver malicious_tsch_driver; // 在初始化阶段(比如main里的setup部分)执行 memcpy(&malicious_tsch_driver, &tsch_mac_driver, sizeof(struct mac_driver)); malicious_tsch_driver.input = malicious_packet_input; // 替换全局的NETSTACK_MAC指针 NETSTACK_MAC = &malicious_tsch_driver; - 这种方法不用改Contiki-NG核心代码,适合不想动底层的场景。
方案3:扩展驱动添加钩子(更规范)
- 如果不想直接替换input函数,可以给TSCH驱动加钩子逻辑:
- 在tsch.c的
tsch_mac_driver结构体里加一个钩子成员:void (*input_hook)(struct mac_driver *d, struct packetbuf *p, uint16_t linkaddr); - 修改原
tsch_input函数,先检查钩子是否存在,存在就调用:static void tsch_input(struct mac_driver *d, struct packetbuf *p, uint16_t linkaddr) { if(tsch_mac_driver.input_hook != NULL) { // 钩子返回非0就丢弃数据包 if(tsch_mac_driver.input_hook(d, p, linkaddr)) { return; } } // 原有的数据包处理逻辑 ... } - 在恶意节点代码里设置钩子:
tsch_mac_driver.input_hook = malicious_packet_input;
- 在tsch.c的
验证方法
- 在
malicious_packet_input里加打印:static void malicious_packet_input(struct mac_driver *d, struct packetbuf *p, uint16_t linkaddr) { printf("Blackhole: Dropping packet from %04x\n", linkaddr); // 直接返回,不处理数据包 } - 启动Cooja仿真,让其他节点向恶意节点发数据包,看终端是否有打印,确认攻击生效。
内容的提问来源于stack exchange,提问作者Haithem Dixon
相关产品推荐
相关产品推荐

