最近在复习考试,面对砖头一样的《数据库原理》,真的很想把它像砖头一样扔出去。
往往复习的时候,效率爆低,因为我无法明白,离开了程序,还要什么好学的、好背的。真的很佩服那些在图书馆看书看一整天的人,莫非他们的脑子里内置了一个编译器?
这几天屡屡dota,感觉比较浪费时间,还是上来写点blog为好。
这学期我们还开了《计算机网络》,相比其他科,这科还显得有用点,也没那么理论。这几天补了一下基础知识,觉得还是先在rootkit里实现tcp/ip传输。这世道真是tcp的天下啊,少了它干嘛嘛不成。
实现的意思呢,就是脱离内核,自己实现一个简易的tcpip协议栈。
这样做的好处是不经过netfilter,完全脱离内核的限制。
有人说“这太疯狂了,我们还是有办法搞定netfilter的吧,没必要这样做来绕过它啊”
你知道鄙视的最高境界是什么吗?是蔑视。就是压根不把它当回事。当你对一个东西失去了信心的时候,就会蔑视它,比如说中国足球或者应试教育。
看了lwip(一个开源的小型tcpip协议栈)的源码后,觉得自己实现一个也不是那么遥不可及。吗的,程序员就应该疯狂点。
千里之行,始于足下。首先,我们要找到以太网设备。
- int register_netdevice(struct net_device *dev)
- {
- ...
- list_add_tail(&dev->dev_list, &dev_base_head);
- ...
首先,网络设备的注册,必然会把dev加入到dev_base_head中。
- #define for_each_netdev(d) /
- list_for_each_entry(d, &dev_base_head, dev_list)
- struct net_device *dev_getbyhwaddr(unsigned short type, char *ha)
- {
- struct net_device *dev;
- ASSERT_RTNL();
- for_each_netdev(dev)
- if (dev->type == type &
- !memcmp(dev->dev_addr, ha, dev->addr_len))
- return dev;
- return NULL;
- }
我们顺藤摸瓜,找到了这个函数。都是老套路了,反汇编一下。
- 0: 55 push %ebp
- 1: 0f b7 c0 movzwl %ax,%eax
- 4: 57 push %edi
- 5: 56 push %esi
- 6: 53 push %ebx
- 7: 83 ec 18 sub $0x18,%esp
- a: 89 54 24 10 mov %edx,0x10(%esp)
- e: 89 44 24 14 mov %eax,0x14(%esp)
- 12: e8 e9 71 00 00 call 0x7200
- 17: 85 c0 test %eax,%eax
- 19: 75 72 jne 0x8d
- 1b: 8b 1d fc c4 35 c0 mov 0xc035c4fc,%ebx
- 21: 83 eb 30 sub $0x30,%ebx
- 24: 8b 6b 30 mov 0x30(%ebx),%ebp
- 27: 0f 18 45 00 prefetchnta 0x0(%ebp)
- 2b: 81 3d fc c4 35 c0 fc cmpl $0xc035c4fc,0xc035c4fc
- 32: c4 35 c0
- 35: 75 1b jne 0x52
- 37: eb 48 jmp 0x81
看到没,16行就是我们要找的了,判断list_head是否为空。我不说你也知道该咋办了吧。
- dev_base_head: .fill 4
- net_device.dev_list: .long 0x30
- EXPORT_LABEL(netdev_mod_init)
- PUSH_ALL
- GET_VAL32(dev_getbyhwaddr, %eax)
- movl %eax, (%esp)
- movl $0x50, 0x4(%esp)
- call 1f
- .byte 0x00; .long 0x0000ffff; .long 0x00003d81;
- .byte 's'; .byte 0x02; .long 0xffffffff;
- .byte 'e'
- 1: popl %eax
- movl %eax, 0x8(%esp)
- GET_ADDR(dev_base_head, %eax)
- movl %eax, 0xc(%esp)
- call xde_find
- testl %eax, %eax
- jz netdev_mod_init_out
- #ifdef _DEBUG_
- GET_VAL32(dev_base_head, %edx)
- movl %edx, 4(%esp)
- DPRINT("<3>dev_base_head %lx/n")
- #endif
- // for_each_netdev ..
- GET_VAL32(dev_base_head, %edi)
- movl %edi, %esi
- movl (%esi), %esi
- 1: cmpl %edi, %esi
- jz 2f
- #ifdef _DEBUG_
- CONTAINER_OF(%esi, net_device.dev_list, %ebp)
- movl %ebp, 4(%esp)
- DPRINT("<3>netdev: %s/n")
- #endif
- // strncmp(dev->name, "eth", 3);
- // name is always the first member of net_device ~~!
- CONTAINER_OF(%esi, net_device.dev_list, %ebp)
- movl (%ebp), %eax
- andl $0x00ffffff, %eax
- cmpl $0x00687465, %eax
- jz 3f
- movl (%esi), %esi
- jmp 1b
- 2:
- #ifdef _DEBUG_
- DPRINT("<3>eth dev not found/n")
- #endif
- jmp netdev_mod_init_out
- 3:
- #ifdef _DEBUG_
- DPRINT("<3>eth dev found/n")
- #endif
- netdev_mod_init_out:
- xorl %eax, %eax
- POP_ALL
- ret
这样,我们就找到了eth设备。至于tcp ip的实现,考完试先吧。
这篇文章没有什么技术含量,因为最重要的东西还没说。
先讲个笑话吧:
一次逛街时突然觉得肚子很痛
于是走进街角的199吃到饱的火锅店
想说借个厕所用用
偏偏找遍了一楼就是找不到
于是我跑到二楼去
二楼是还在装修空荡荡的没有任何东西
但是却发现有一间厕所贴著“故障待修,请勿使用“
我实在是忍不住了
管他三七二十一,反正四下无人
脱了裤子就朝马桶蹲下去
霹雳啪啦……好爽! !
结束后
我走下楼去却发现空无一人
奇怪了,正值晚餐时间 刚才楼下还高朋满座
怎么一下子就人去楼空呢?连服务生和接待都不见了……
於是我走近吧台,
并且问到:有人在吗?怎么都没人了?
此时,只见一个男服务生从吧台下钻出来,
并且开口说:
我操!……刚才大便从天花板掉下来
打到电风扇的时候你不在吗?算你运气好......
今天看到这笑话,彻底笑翻了,所以心情特好,就写了这篇文章。