致命误操作

Gigabyte BRIX (XM11-3337)在路上飘近一个多月之后,终于到手。遂即安装了Win7及Ubuntu双系统,但Ubuntu不能正常启动。通过U盘启动了Ubuntu Live去查看原因, 在准备chroot环境时,不小心打错了命令:

tar zcvf /dev/sda*

结果,硬盘上的分区及引道记录全被覆盖,好在/dev/sda*只是设备名称,只冲写掉前面几个扇区,数据区域无碍。

通过/proc/partitions里的数据重建分区,前面的主分区正确识别,但扩展分区无法识别,应该是有错位,在新建的扩展分区前后搜索”55 AA”标志,遂找到了正确的扩展分区起始位置。主引导记录的修复只好用Windows 7安装光盘来修复。

后来还要接着搞grub无法启动Ubuntu的问题,grub提示无法找到/boot/grub/normal.mod,此时grub仅支持少量和命令,如ls, set, insmod等,linux及initrd命令必须等linux.mod加载后方能生效,通过set命令查看:

prefix=(hd0,msdos3)/boot/grub

(hd0,msdos3)为/boot分区,并不是root,故需要修改prefix为: (hd0,msdos3)/grub,即

set prefix=(hd0,msdos3)/grub

之后就可以手工启动Linux 了:

insmod linux
linux (hd0,msdos3)/vmlinuz-3.8.0-…-generic ro root=/dev/sdaX
initird (hd0,msdos3)/initrd-3.8.0-…-generic
boot

Ubuntu可以正常启动了,但问题的修复还要费些脑筋,因为我的Ubuntu系统设置了独立的boot分区,早知如此当初就不这么麻烦了,好在还有个比较投机的办法,在/boot目录下建了一个指向上层目录的symbolic link:

ln –s .. ./boot

重启系统并验证grub可以正常启动Ubuntu了。

生命不止,折腾不息!附个BRIX酷照:

Gigabyte Brix

 

用CubieBoard玩转网络共享

将CubieBoard或Raspberry Pi架成Wireless Access Point的办法网上已有很多,但和我的需求正好相反,我是打算让连在CubieBoard的ethernet上的内部子网络可以共享CubieBoard的无线网络端的internet联接,即AP Client方式。

AP client的实现并不复杂,通过dhcpd及NAT即可做到。

第一步:设置有线网口(eth0)为固定ip

~# cat /etc/network/interfaces
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet static
address 192.168.0.1
netmask 255.255.255.0

第二步:安装并配置dhcpd服务

~# apt-get install isc-dhcp-server

添加dhcp网段地址:

~# cat /etc/dhcp.dhcpd.conf
……
subnet 192.168.0.0 netmask 255.255.255.0
{
    range 192.168.0.50 192.168.0.250;
    option routers 192.168.0.1;
    option domain-name-servers 8.8.8.8,4.2.2.2;
}

限定dhcp服务运行于连接在eth0上的子网:

~# vi /etc/default/isc-dhcp-server
……
INTERFACES="eth0"

启动dhcpd服务:

~# service isc-dhcp-server restart
isc-dhcp-server stop/waiting
isc-dhcp-server start/running, process 23686

~# ps -efa | grep dhcpd
root     23686     1  0 15:45 ?        00:00:00 dhcpd -user dhcpd -group dhcpd -f -q -4 -pf /run/dhcp-server/dhcpd.pid -cf /etc/dhcp/dhcpd.conf eth0

此时dhcpd服务架设成功,连在网口eth0子网上的电脑客户端可以自动获取到ip了。

第三步:设置无线上线

用实际的ssid及password替换下面的命令:

~# wpa_passphrase ssid password >> wpa.conf
~# cat wpa.conf
network={
        ssid="ssid"
        #psk="password"
        psk=44116ea881531996d8a23af58b376d70f196057429c258f529577a26e727ec1b
}

连接无线网络:

~# wpa_supplicant -iwlan0 -B -Dwext -c ./wpa.conf
~# dhclient wlan0
~# ifconfig wlan0

wlan0     Link encap:Ethernet  HWaddr 14:xx:xx:xx:xx:xx
          inet addr:10.0.3.93  Bcast:10.0.3.255  Mask:255.255.255.0
          inet6 addr: fe80::16cf:92ff:fe1b:34ef/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:240 errors:0 dropped:0 overruns:0 frame:0
          TX packets:497 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:2299089 (2.2 MB)  TX bytes:1124901 (1.1 MB)
~# ping www.google.com
PING www.google.com (74.125.128.99) 56(84) bytes of data.
64 bytes from hg-in-f99.1e100.net (74.125.128.99): icmp_req=1 ttl=46 time=69.2 ms
64 bytes from hg-in-f99.1e100.net (74.125.128.99): icmp_req=2 ttl=46 time=59.4 ms
^C

第四步:设置网络转发及NAT

编辑/etc/sysctl.conf启用ip forward:

~# cat /etc/sysctl.conf

net.ipv4.ip_forward=1

使ip forward更改生效:

~# sysctl –p

设置NAT转发:

~# iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE

设置好NAT后,子网客户端就可以上网了。

注1:dhcpd server可以用udhcpd来替代
注2:无线网络的设置也可以通过/etc/network/interfaces来做
注3:ip forward的设置(/etc/sysctl.conf方式)重启仍然有效
注4:有关iptables的设置及防火墙配置请参阅相关资料

“曾经沧海”正是我们的梦

 
我所见过的事情 你们人类绝对无法置信
我目睹了战舰 在猎户星座的边缘中弹 燃起熊熊火光
我见过C射线 划过了‘唐怀瑟之门’ 那幽暗的宇宙空间
然而所有的这些片段
那所有的瞬间
都将湮没于时间的洪流
就像泪水消逝在雨中
                          ----《银翼杀手》对白。

活法

1, Living a Life Well Lived

甩下包袱,大踏步前行吧。世界有太多的未知等你去探索,前面有太多的体验等你去尝试。每一次冒险也最终将会成就你自己!

Jim Whittaker,first America to top of Mt. Everest.
http://www.adventure-journal.com/2013/06/living-a-life-well-lived/

2,活出我们的精彩

把握住你的时间,有想法便全情去做,努力做好!

Aaron Swartz在26岁的年纪以自杀的方式结束了自己的生命,但26岁的他活得却异常精彩。 RSS1.0标准的制定者之一,社交新闻网站Reddit的合作创始人,为了一个单纯的资源共享让全社会受益的理想,最终迫于压力而自杀,令人惋惜。

Aaron Swartz: http://en.wikipedia.org/wiki/Aaron_Swartz

3,活出我们的良心

以自由和平等为信念的美国却以反恐的名义收集着全世界人的隐私,侵犯了全世界人的权益!Edward Snowden站出来了,在明知道自己将会面对怎么的后果的情况下,他还是站出来了,并将NSA的这个不光彩的勾当告之以全天下。

反恐的底线在哪里?为了反恐我们人类真得要承受如此的代价吗?

珠峰是面照妖镜

轰轰烈烈的2013年珠峰登山季结束了,其结果也是同样的烈烈轰轰。今年的登山季太不平静,南坡有80岁日本老人三浦雄一郎登顶的好消息,北坡更有高海拔救援身价3亿的夏老板的壮举,只是因着救援消耗太大的关系,B组10人与近在咫尺的登顶擦肩而过,朋友老杨就是B组10人之一!

当前的珠峰已成为中国房产商们的后花园,时髦大亨们追逐炫耀的新战场。从对最高的渴望,上升至国家荣誉,再沦落至个人得失之地,前后刚刚60年。话说回来,从1949年到现在也刚过去60多年。

十一郎的《登山就像谈恋爱,珠峰是面照妖镜》有更多关于珠峰攀登的故事,不妨看看。版权原因,不作转载。

由Hook引起的XP Explorer崩溃

有用户反应XP系统上一拖动桌面上的图标即会导致桌面重启,验证后,证实和360安全的升级有关,360安全9.0及后续版本和我们的软件有冲突。

360安全本身太激进,作为一款安全及防毒软件来说,激进并不是什么好事,这也是我不喜欢用360安全软件的原因之一。但是在事情未查出原因之前,不能随便怪罪360,毕竟在二者不共存时,均不会有桌面崩溃的事情发生。

先通过排除法,发现冲突发生在Hook上,而且是在特定的响应拖拽事件的API的Hook上:

    ole32.dll: DoDragDrop

问题定位之后照理应该很直接了,但分析新的DoDragDrop的实现及相关代码,并没有发现明显问题。

我们的代码在一个DLL文件中,并根据需要注入被Hook的进程,此案中便是Explorer.exe。调试起来稍有些周折,但也不算太麻烦。对此类的应用层调试问题,用VS (Visual Studio)远程调试最方便。远程attach到目标XP系统上的explorer.exe进程,然后触发崩溃事件,VS直接响应,显示问题出在一条很正常的压栈(push)操作上,再查看堆栈指针,果然已经耗尽,esp所指内存为非法地址(空页)。

初步揣测可能是堆栈不够所致,explorer.exe默认的size of stack reserve是0x400000,即4M字节。为了验证是不是堆栈的问题,直接将修改explorer.exe的PE文件头,将reserved stack size改成了64M(0x4000000)。

再测试时,explorer.exe在拖动桌面图标时还是会崩溃,只是会等上一会,不像之前一拖动便立即崩溃,看来问题并不是堆叠不够所致。

通过VS中断,发现Call stack中全是iNetSafe.dll (360安全的一个模块),由此断定出现了嵌套调用,死循环。

后面继续跟踪代码的调用过程发现了这样一个有趣的事,先将相关代码列出来:

ole32.dll地址空间 【774E0000 - 7761E000】:
_DoDragDrop@16:
775D0DC0 E9 0B DA 13 EE       jmp         6570E7D0
775D0DC5 83 EC 4C                sub         esp,4Ch
。。。。。。

iNetSafe.dll的地址空间 【65700000 - 65737000】:
6570E7D0 E9 AB 3A 1E 9B       jmp         CDragDropObj::NewDoDrapDrop (8F2280h) 
6570E7D5 57                           push        edi 
。。。。。。
6570E7F5 8B 4C 24 18          mov         ecx,dword ptr [esp+18h] 
6570E7F9 8B 54 24 14          mov         edx,dword ptr [esp+14h] 
6570E7FD 51                         push        ecx 
6570E7FE 8B 4C 24 14          mov         ecx,dword ptr [esp+14h] 
6570E802 52                   push        edx 
6570E803 51                   push        ecx 
6570E804 56                   push        esi 
6570E805 FF D0                call        eax                     [eax: 6FFE00A0]
6570E807 5F                   pop         edi 
6570E808 5E                   pop         esi 
6570E809 C2 10 00             ret         10h 
6570E80C 8B C7                mov         eax,edi 
6570E80E 5F                   pop         edi 
6570E80F 5E                   pop         esi 
6570E810 C2 10 00             ret         10h

360 iNetSafe.dll 所维护的Hook地址信息:
6FFE00A0 E9 DB 21 91 90       jmp         CDragDropObj::NewDoDrapDrop (8F2280h) 
6FFE00A5 E9 1B 0D 5F 07       jmp         _DoDragDrop@16+5 (775D0DC5h) 

MyHook32.dll地址空间 【008F0000 - 00C5F000】:
CDragDropObj::NewDoDrapDrop:
008F2280 55                   push        ebp 
008F2281 8B EC                mov         ebp,esp 
008F2283 8B 0D 38 70 C1 00    mov         ecx,dword ptr […::m_OldDoDragDrop 0C17038h] 
                                                                  0C17038h:0EC9002C  ECX = 0EC9002C 
008F2289 33 C0                xor         eax,eax 
008F228B 85 C9                test        ecx,ecx 
008F228D 74 03                je          CDragDropObj::NewDoDrapDrop+12h (8F2292h) 
008F228F 5D                   pop         ebp 
008F2290 FF E1                jmp         ecx                              [ecx = 0EC9002C]
008F2292 5D                   pop         ebp 
008F2293 C2 10 00             ret         10h 

MyHook32.dll: 原地址及代码
0EC9002C 56                         push        esi 
0EC9002D 8B 74 24 08          mov         esi,dword ptr [esp+8] 
0EC90031 E9 9F E7 A7 56      jmp         6570E7D5 

流程分析:

当Explorer调用_DoDragDrop()函数时,将跳转到iNetSafe的DoDragDrop实现,地址为6570E7D0。iNetSafe的DoDragDrop函数又被MyHook32 Hook了,所以还要继续跳至地址008F2280。MyHook32执行完还会跳转至被Hook前的_DoDragDrop函数,地址存放于0EC90032处,跳转地址为:6570E7D5,即iNetSafe的DoDragDrop函数入口加上5个字节的偏移。同理,iNetSafe的DoDragDrop函数也要调用它所Hook的原DoDragDrop地址,此地址的跳转指令存放于6FFE00A0处。但奇怪的是,位置6FFE00A0所存放的地址竟指向MyHoo32的
NewDoDrapDrop(即8F2280),所以任何对_DoDragDrop的调用,将会陷入一个嵌套的死循环里再也出不来了,直到堆栈被耗尽。

从上面代码上来看,iNetSafe在前,MyHook32在后,所以iNetSafe于6FFE00A0中所保存的原_DoDragDrop地址不应该是MyHook32的,而应该是ole32的_DoDragDrop才是。

但根据Explorer.exe进程的加载模块表,MyHook32.dll的加载order为40,而iNetSafe则为103,明显是MyHook32.dll先被加载,所以Hook的顺序明显违背上面的分析。

至此,方想到问题可能出在MyHook32的Anti-UnHook检查机制上。MyHook32在一个线程里面会实时检测被Hook的函数入口代码,如果不是MyHook32自己的,则会再次尝试Hook,因为360的Hook,便导致了MyHook32的再Hook,所以结果便导致了嵌套Hook的乌龙。

问题已经明确,并不是360的问题,而是出在我们自己的程序上,实在不应该先入为主的怪罪360,尽管其中还是有不少感情因素。

调试终于结束,剩下的的事情便是思考出一个万全的Anti-UnHook机制了。

下图为Explorer.exe所加载的模块(截屏自VS2010):

HookModules-01HookModules-02HookModules-03

注:有几个DLL的图标上均有红叹号,表示是此DLL被加载到的虚拟地址空间并不是此DLL所指定的地址空间。如MyHook32.dll(此版本为DEBUG版本,故体积及占用的地址范围也比较大)其默认的虚拟地址为10000000 - 1036EFFF,而实际上却被加载至008F0000 - 00C5F000。对于DLL文件的加载及从Vista之后所支持的ASLR(Address Space Layout Randomization),以后有机会再单独介绍。