Rise的自留地

记录生活中的点滴,分享编程技术和游戏开发经验。

0%

头文件,
处理憔悴,
编译器,
报错如风雪。
是谁混淆基本类,
惹变量是非。
虚基类,
构造轮回,
动态堆,
字符串唤不回。
纵然代码已经成灰,
内存不灭。
循环如三千东流水,
我嵌套一瓢爱了解,
只恋函数的递归。
你发如雪,
定义了离别,
我指针指向了谁,
邀明月,
让地址皎洁,
爱在数组里倾颓。
你发如雪,
初始化眼泪,
我联编继承了谁,
数据醉,
编程的岁月,
我用后悔,
刻电脑崩溃的碑。
啦儿啦 啦儿啦 啦儿啦儿啦
啦儿啦 啦儿啦 啦儿啦儿啦
去约会她斜扎儿马尾只因为学C++学到了崩溃

上周,“番茄花园”作者洪磊被警方带走,传出的罪名是涉嫌侵犯微软著作权,也就是俗称的“盗版”。(8月24日北京晨报)


  从番茄花园的站长被拘捕、番茄花园网站改版开始,“番茄门”开始成为网络间仅次于奥运会的热门话题。与当初人们对“珊瑚虫事件”的反应有些类似,有一部分网民开始为番茄花园叫屈,“支持番茄花园”式的呼吁此起彼伏。

很多人都说,现在社会风气败坏了,都是年轻人的错。这实在是一个很离谱的理论,至少从我的观察来看,比如拿坐公交车这件事情来说,最不道德就是老年人(不是所有的老年人),从公交车到站,他们就挤成一团,谁都恨不得自己第一上车;只见过年轻人给老年人让座,但是基本没有见过老年人给孕妇或者抱小孩的让座;给老年人让座位,能得到“谢谢”的次数也不多;在无锡,我至少看到三次老年人之间为了一个座位吵架甚至要出手。就拿近期发生的一件事情来看,南京的“彭宇案”来看,是那个老年人还是彭宇不够道德呢?
  其实我不是在抨击老年人,也不是在为年轻人做辩解,社会不好大家都有责任。但是就从社会风气不好的源头来看,至少这笔帐不应该,也不能够算到年轻人身上。一个社会,其权力基本是掌控在中老年人手里,最简单,看看我们的政治局常委就应该清楚,里面没有80后吧。
目前中国的社会问题在于老百姓生活艰难,没有保障,社会没有正义,没有诚信,缺少关爱。这一切都是什么造成的呢?老百姓的保障,从国企改革,员工下岗,医疗改革,教育改革,住房改革,一层层的被剥落下来,这过程中,做决策,执行的都是哪个年龄段的人?从这个角度来说,作为一个80生人,被扔到这样一个烂摊子的社会里面,是有权力责怪我们的长辈的。由于失去了保障,而在保障失去的过程中,其实都是国家的违约。国家的步步违约造成老百姓对国家不信任,原先的道德体系崩盘。人失去的多了,就开始拼命的想获得,而大部分的社会资源掌控在少部分的人手里,剩下的人就相互践踏,你抢我夺。就连重庆家乐福搞促销那么点蝇头小利都会导致3人遭挤压致死,在现实的社会中可想而知,人会用尽各种手段,尔虞我诈,无所不用其极的想办法生存。有能力的就贪污受贿,有专职的就收受红包,有权力的就搞灰色交易,剩下的老百姓就想办法出去偷,出去骗,出去抢。还有一些许三多同志,他们就老老实实的当民工,当没有什么保障的工人。
  社会道德的沦丧,不能责怪某些人,同样是人,为什么在唐代的品质和清朝的就不一样的,就是清朝的人,为什么清初和清末的社会风气也不一样呢?非人异也,社会制度使然也。
但是,就是这样,我相信现在的年轻人还是有资格指责一下中老年人的,他们更多的时候只是这个社会现状的承受者,而那些年富力强和已经行将就木的人,才是当前社会的缔造者和执行者。举个最简单的道理,经历过大跃进年代的人,就不要和我讨论什么诚信了,经历了文革的人,也不要和我讨论什么正直。诚信的人已经被打压了,而正直的人,就如同老舍。除了那些被打压的,受压迫的,剩下的顶多在当时是一个苟活者。
  我倒是认为中国的希望在80后,他们比他们的前辈看到的更多,听到的更多,学到的更多。随着大学教育的普及,虽然我并不苟同杨振宁教授关于中国的大学教育是最成功的观点,但是大学的教育还是为中国培养了大量的有一定知识的年轻人。更重要的是,在他们这一代人里面,他们很少有人再靠依赖国家的组织、部门来混饭吃了,他们可以通过自己的努力找到一份养活自己的工作,哪怕是洗脚工。从这一点来说,他们的行为更自由了,自由身体可以带来自由的思想,自由的思想可以带来独立的意识。中国之希望,或许就在80 以后。

村民石章云3年前患了食道癌,现病重不起

刘长月老人在发臭的黑水河上,吃力的挪动着渡船

王子清已记不清自己主持过多少次葬礼了。

自打他48岁那年起,癌症患者便在村子里多了起来,死亡接踵而至。每遇死亡,王子清必会到场,或主持,或与亡魂告别。多数情况下,他是主持者。

本来,作为子字辈的他,是没有资格主持这种仪式的。子字辈之上,还有祖父辈的玉字辈和父辈的德字辈。在村里,这种告别亡魂的庄严仪式,通常是由年岁较大且德高望重的老人主持。但如今村子里玉子辈的人已所存无几,而德字辈的人,或因癌症相继去世,或已“逃离”了这个村子。因此他这个小子辈,就责无旁贷地担当起了这个任务。岁岁月月,“送走一茬又一茬”。

“每死一个人,我的心就像刀割一样。”现年65岁的王子清步履蹒跚地走在村中,神情黯淡。有时,他还会停住脚步,摆摆手,不去追忆往事,“都是大好的年龄,死的太可惜了。真不知道啥时才是个头啊!”


死人就像家常便饭一样

位于河南省沈丘县城东约10公里处的东孙楼村,共有1200多人。原先孙姓为望族,后王姓成了大姓。现全村王姓约有800多人。

自上世纪90年代以来,村里的人出现了密集的反常现象:有些人腹泻不止,有些人内脏出现了各种不适。此外,偏瘫、智障、畸形和妇科疾病也频频出现。患者相继死去,少则一年内五六人,多则达20多人。死者经诊断多为食道癌、肝癌、胃癌、直肠癌、子宫癌、乳腺癌等等。

死亡像个挥之不去的幽灵,笼罩着这个村子。新起的坟茔、白对联、哀乐,一年四季绵延不绝。

王子清的族人便是这个不幸村庄的不幸家族。

1991年,小他5岁的弟弟食道出现问题,吞咽困难。次年,大他两岁的哥哥也出现同样病症。俩人的病后来都转化为食道癌。2004年6月,王子清的哥哥病逝。28天后,他的弟弟也撒手人寰。这边丧事还没料理完,3天后,他的一位叔叔也死于食道癌。短短一个月,王子清相继失去3位亲人。

而这仅仅是幽灵掀开的序幕一角。事实是,这些年,仅王姓德字辈的族人中,25对夫妇,便有19人死于癌症。而子字辈中不到80人,便有16人死于癌症。死者大都正值壮年,最大的70岁出头,最小的只有30岁。

“死人就像家常便饭一样。”王子清抽泣着,任由眼泪淌满褶皱的脸上,“我不知道村里到底死了多少人,只知道一个接一个地死。”

王子清本人虽然没有患上癌症,但胃穿孔也让他遭了不少罪。2004年,他花了5000元做了胃部手术,至今天气转凉,伤口就会隐隐作痛。为“转移痛苦”,他染上了抽烟的毛病,一支接一支,一会儿功夫,一包烟就空了。

在大多数地区,通常每个村里有一名医师就不错了,但在沈丘县东孙楼村却增加到了4名医师。刘德亮是村里最老资格的医师。他记得最忙碌时自己每天要跑三四家,“抗生素药供不应求”。村里的人口一度竟出现了负增长。

一位正在病床上输液的腹泻患者挣扎着坐了起来,插话说,就是现在,村里患腹泻的病人至少也不下100人。

不仅是东孙楼村,自上世纪90年代以来,沈丘县的黄孟营村、孟寨村、孙营村等,癌症患者的比例均大幅度上升。据该县政协常委、民间环保组织“淮河卫士”会长霍岱珊提供的资料显示:1990年~2005年间,2470人的黄孟营村,有116人死于癌症;2366人的孟寨村,有103人死于癌症;1697人的孙营村,有37人死于癌症;1300人的陈口村,有116人死于癌症;2015人的大衤者庄,有145人死于癌症;1687人的杜营村,有187人死于癌症。而据沈丘县医院记载,1972年当地120万人中,只发现癌症患者12人,发病率仅为十万分之一。

由于癌症爆发的密度大、频率高,故上述村庄被当地人称作“癌症村”。3年前,河南省周口市有关部门,曾联手在沈丘县的“癌症村”做过一次癌症患者的入户统计,但该数据一直没有公开,沈丘县卫生局的一位副局长表示,不能向记者提供。

谁得病谁家就败

在王子清隔壁的一条小巷子里,原先住着16户人家,现在只剩下3户了。其中,有两户全家死于癌症,其余的因害怕也搬走了。

恰逢雨后,巷子里一片泥泞。在这条约100米深的小巷子里,已有很长时间没人出入了,显得分外寂静。有一户人家的房子是两层预制板楼,在这个人均年收入不到1000元的村子里,这栋小楼显得十分气派。但如今铁门上的锁头已经生锈,门口杂草丛生。显然,这里早已人去楼空了。

“死的死,走的走。”王子清趿着拖鞋,在泥水中“啪嗒啪嗒”地走着,不时发出重重的叹息,“以前这里可热闹了,现在一点生气都没啦。”

这个东西长约1公里、南北宽约半公里的村子,上世纪90年代以前,曾和许多村一样,过着自给自足的闲适生活。农忙时,男人女人热火朝天地干活,换取一年的口粮。收成好的时候,兴许还会落些余钱,添几件衣服,买两件电器,乐呵一番。不忙的时候,男人们出外找些活计,或在本地打打零工。空闲时,招呼几个人喝上几盅,或搓一阵麻将。

可眼下,疾病和死亡像恶魔一样几乎缠扰着村里的每一户人家。街上偶尔遇到几个人,脸上也大都带着悲伤、无奈或茫然。有时能看到三五个人聚在一起,谈论的话题往往都和癌症有关。

一位癌症患者盖着一床厚被子躺在床上呻吟。经过化疗和放疗,她的头发已经稀稀疏疏,头皮清晰可见。裸露在外的胳膊和腿,瘦得皮包骨头。她紧闭双眼,嘴里不时嘟囔着什么。守在她身边的丈夫,愁眉不展,目光呆滞,偶尔下意识地给妻子掖掖被子。“家里有多少钱,也让病折腾穷了。”他说。

在这三间预制板结构的楼房里,大理石地板、雪白的墙壁、宽大明亮的窗户、墙上四大名楼的挂图,以及一台21英口寸的彩色电视机,多少彰显出主人的能干和富足。如果不是癌症拖垮了这个家庭,在这个举目都是低矮房屋的村子里,楼房主人的生活一定会让邻居羡慕。可现在,这间屋子里死气沉沉。

“谁得病谁家就败。”王子清说,有钱的人家,病人能多活两天,没钱的,就只能等死了。他一再表示,村子里钱都不好借,有钱也不敢借出去。“我们东孙楼穷,不是因为人懒,没能力,而是因为癌症。只要家里有病人,都得花上三两万块。”

王子清的一位叔叔患了胃癌,家里拿不出钱为他填这个无底洞,于是,在一个夜深人静的晚上,他上吊自杀了。“因没钱看病上吊自杀的,村里已有好几个。”他说。

人死了,葬礼照样得办。火化1000元,棺材1500元,孝服500~800元,灵车灵棚各100元,唢呐100元。各种费用算下来,至少需要5000元。因外出和死亡的青壮年多,棺材都没人抬,以至于吊车下葬,成了当地一个“热门”行当。

由于贫穷,村里如今盗窃成风。王子清家原来的围墙不高,人很容易翻墙进去。现在,他已把原有的围墙拆掉,准备加高。“我怕小偷。”他说。

村头墙壁上,到处是触目惊心的治疗腹泻、癌症的广告。有些患者无奈只能找江湖游医寻求安慰;有些患者则只能求助“神”的力量。

黄孟营村33岁的孔鹤琴,19岁嫁到此地,26岁得了直肠癌,4次手术,12次化疗,花了7 万多元,如今家徒四壁,外债高筑。两年前,“感到无望”的孔鹤琴皈依了基督。每周五,骨关节变形的她,都要坐在轮椅上,让丈夫推着,到两公里外的王寨村做礼拜。王寨村基督教堂的信徒芦美英则表示,七八十名教友中,基本都是身体有病的人。

孙营村的村民孙振雨,不忍看着自己的乡亲们忍受癌症的折磨,于1999年,筹钱2500元,修复了村里的华佗庙,“初一十五,香火很旺”。但华佗庙重修后4年,孙的爱人得了偏瘫,至今卧病在床。可叹的是,连塑华佗像的匠人也因癌症而去世了。

与周边“癌症村”一样,东孙楼村能参军的人很少。有几年,竟没有一个体检合格的。

“人活得都没有希望了。”王子清说,“村里的人总担心,下一个死的会不会是自己。”


又黑又臭的卫河在村口流过

都是污染造的孽

王子清家正对着一个大水塘,塘边有几棵树,几只白色的鸭子在水塘内戏水。如果不与癌症发生联系,塘边树下,静坐垂钓,本该是件惬意的事。

像这样的水塘,几乎每个村子都有几处,只是有些已经变成了倾倒生活垃圾的地方。在这个西北高、东南低的县域内,因河流冲刷,坑塘较多。加之,上世纪50年代后期,当地人鼓足干劲,大修水利。干渠、支渠、斗渠、毛渠,通向每一个角落。四通八达的灌溉系统,造就了这个曾经的鱼米之乡。

东孙楼村也有一个发达的灌溉系统。东南西北四条水渠,将村南两公里外的沙颍河水,输送到地里田间。这个处于沈丘县“锅底”的村子,即使在非灌溉季节,沟渠里也会积下不少的水。因此,这里几乎一年四季浸淫在水中。

在王子清的记忆中,沙颍河和渠塘里的水曾经清澈透明。上世纪50年代,这里的人上地,“从来不带水”。渴了,随便在渠塘中掬一捧水就喝。“甜着呢,比现在的自来水都好喝”。

可是,随着上世纪80年代末、90年代初,沿河一些污染工业项目纷纷上马,沙颍河水逐年开始变坏变臭,致使源自沙颍河的灌溉沟渠的水也变得腐臭难闻。在王子清的带领下,记者沿着村里的沟渠水塘走了一遍。水面上覆盖着一层绿油油的浮萍,树叶、秸秆散落其中,蚊虫猖獗,臭不可闻。

据沈丘县水文站站长李斌提供的一份资料:沙颍河槐店(沈丘县城所在地)段,1990年、 1994年、2000年均属劣V类水质,已失去各种水体功能。中国环境监测总站公布的水质监测周报显示:2005年和2006年,此段水质分别有两次是Ⅳ 类水,其余时间皆为V类或劣V类;2007年第20周和21周的水质也均为劣V类。水体中高锰酸钾和氨氮含量均超Ⅲ类水标准的数倍。

1994年7月中旬,淮河发生特大污染事故,在黑色污染团过后,水质有所好转的情况下,安徽省蚌埠市自来水公司取3000公升淮河水送到上海化验,结果对比美国环境保护机构公布的129种“首要控制污染物”,蚌埠三水厂和一水厂的源水分别查出90种和95种,其中,致癌物高达67种。

淮河60%的来水量源自沙颍河,而沙颍河贯穿沈丘全境。今年4月,中国环境监测总站对沙颍河的监测报告显示,其水质全部为劣V类。

“作为淮河最大支流,沙颍河的水质污染可想而知。”淮河卫士会长霍岱珊痛心地说。

有研究显示,这些高污染、富含各种致癌物的水,通过发达的沟渠逐渐渗透到地下水系统,破坏了当地的地下水水质。据当地人反映,自1990年代以来,压水井里压出的水混浊不清,能看到明显的杂质;有些地方的水,粘性特别大,能像油一样流成细线状;水烧开后,水壶上会留有厚厚的一层水垢;即使开水也苦涩难咽,喝下去后喉咙会发麻。有媒体称,“地下50米以上的浅层地下水已不能饮用”。而在沈丘,农户自家的压水井一般都在20米以上。

据阜阳市疾病预防控制中心2004年7月13日做出的一份水质检测报告显示:沈丘县黄孟营村一家的压井水送检样本中,有10多项指标超标,其中锰、硝酸盐氮严重超标。科学实验证明,过量摄入高硝酸盐氮的水或食物会引发消化道癌症或者肝癌,而高锰的暴露会对大脑产生危害,使一些大脑皮层坏死,对人的智力发育甚至大脑神经活动产生危害。

“都是污染造的孽。”王子清说,虽然他本人不能从科学上证明沙颍河水污染和癌症之间的因果关系,但生活经验和直觉告诉他,严重污染的沙颍河是癌症高发的直接元凶。

2005年,国家疾控中心曾对淮河流域癌症高发地进行全面普查,其中包括沈丘县全境,最终结论是:一、淮河流域沿河、近水区域癌症高发;二、癌症高发与劣Ⅴ类淮河水密切相关。

而沈丘县卫生局一位副局长表示,虽然河水污染与癌症之间一定有关联,但关联究竟有多大,专家还在研究实验之中。

希望政府搭建一个公众可以参与的平台

沙颍河由沙河、颍河于周口汇流而成,自西向东流经河南中东部,全长600余公里,是淮河最大的支流。沈丘,是沙颍河入安徽的最后一站。

“你们得利,俺们得病;你们升迁,俺们升天。”这是流传在沈丘县民间的一则顺口溜。主要针对的是坐落在沙颍河流域大大小小的企业,其中不少为高污染企业,比如造纸、皮革、塑料、酒类等等。这些企业中比较知名的有:项城市莲花味精股份有限公司(下称“莲花味精”)、扶沟县的扶沟味精厂、漯河的银鸽实业集团以及丁集皮革业等。过去这些企业的工业污水基本上都排放在了沙颍河中。据当地人反映,前些年,沙颍河水色如墨汁、臭气熏天,曾发生过呛死人事件。

驸马沟是项城市污水入沙颍河的一条人工河道。其污水源主要是城市生活污水和莲花味精集团的工业废水。

“以前这里臭气熏天,活像一个化肥窖,人人都得捂着鼻子走。”76岁的老船工连德财说。据老人描述,在没有污染之前,这里的水清澈见底,如果有什么东西掉到水里,岸上看得一清二楚。水里的鱼又多又大,经常能够捕到十几斤重的大鱼。而现在,这里的鱼几乎绝迹。即使偶尔能捕捞上一两条,也没人敢吃。在污染最严重的时候,“水里的鱼给什么喂,什么就死”。

据说,前几年,水面上到处漂着白沫。有一次,不知何故,驸马沟的水面竟然着火了,把泄水闸烧坏了。

“以前河里洗澡的人很多,每年都要淹死好几个人。”连德财说,“不过,水污染后也有好处,不会淹死人了。因为没人去游泳了。”

仅这条小小的驸马沟,污水一流就是十几年,迟迟得不到治理。而早在1994年国家就启动了治淮工程,历经10年,投资600亿,但至今未能实现“水体还清”的目标。淮河干流支流的治污任务,依然十分严峻。

“环保局是属地管理。很多污水都是从别处流到沈丘的,我们一点办法也没有。”9月5日,沈丘县环保局副局长徐启亮对记者说。沈丘县水文站站长也表达了水文站的无能为力。他说,水文站的权限只限于取样监测,并没有管理职能,因此,对治理帮不上真正的忙。他透露,有时地方政府出于利益保护,还会在一定程度上干涉水文站取水样。

不过,在治污形成共识的今天,特别是在上级环保部门的重拳出击下,一些企业已经被迫加入治污的行列。比如位于项城市的莲花味精,这个昔日沙颍河的排污大户,曾屡被媒体曝光并被罚款,10多年被迫为环保交了7亿多元学费。项城市环保局前局长还因此“下课”,该市分管环

保工作的副市长,也因此被责令深刻检查。

“做好环保是首先对企业的效益负责。”莲花味精环保事业部负责人王飞对记者说,“我们企业曾经为环保付出过很惨痛的代价,几次差点被关闭,因此绝不能再走老路了。”

“淮河卫士”会长霍岱珊,在沙颍河治污问题上曾屡次和莲花味精交涉,可谓“老对头”。今天他也认为,莲花味精“的确下了功夫改造自己”。

“企业在主观上对自己负责了,在客观上就对社会负责了。”霍岱珊说,希望企业能够意识到,做好环保是分内的事,是真正对企业发展负责的事。

少了莲花味精的污水排放,驸马沟的水质,在当地人看来,已经稍有好转,臭味也不像以前那么明显了。远远望去,几个老人坐在树荫下乘凉,卖冷饮的小贩在吆喝生意,更远处的沙颍河大桥下,几个孩子正在水中攀登桥墩。

今天,最让霍岱珊头疼的不再是像莲花味精这样的大企业,而是许多名头不响的小企业。这些小企业经常和政府职能部门玩“猫捉老鼠”的游戏。如果仅仅依靠政府职能部门的人手,根本无法发现不达标的排放,更不用说治理了。“更何况,有些地方政府还会刻意保护本地的企业”。

“政策宣传就像文工团。”霍岱珊说,“光有文工团不行,解决问题还要靠步兵,要打阵地战。”

“公众就是步兵,就是打阵地战的基础。”霍岱珊说,“组织公众参与,可以形成对排污口的实时监控。”他一再呼吁,希望政府搭建一个公众可以参与的平台,让污染源无处隐身。

命都没了,经济发展了又能怎样

王子清家先后打过4口井,依次是4米、15米、28米、40米。

井一次比一次打得深,但水的口感并没有明显变好。他自己也不知道这些水到底安全不安全,会不会让自家人远离癌症。每逢周末,在外工作的儿子和在城里上学的孙女,总会带些纯净水回来,这样的水,全家人才敢放心地饮用。

3年前,在霍岱珊的联络下,亚洲博爱救助基金会为东孙楼村的全部村民安装了水过滤器。尽管“ 这些设备并不能根本改变水质”,但村民们还是松了口气。此后河南省财政每年安排4000万元专项资金,用于解决重污染地区群众饮水安全问题。沈丘县也在这一年修建了污水处理厂。同年,有关部门还为东孙楼村打了一口200米的深水井,并提供了主管道、潜水泵和无塔供水装置。入户管道需各家自行购买,为此,王子清花了800多元。

2006年1月26日,即春节前三天,村里人第一次吃上了深井水。王子清把所有盛水的家伙都接得满满的,痛痛快快享受了一番。然而16天后,水停了,王子清获知的消息是试运行。4个月后,深井水正式供应。不过,“经常是三天两头没水”。

今年8月初,深井水又停供。王子清只能重新饮用40米的压水井的水。可是,几天后,他的胃开始不适,“一天到晚折腾个没完”。其间,他的老伴过生日,因为没水,他只得用摩托车载着老伴,到沈丘县城过生日。

“潜水泵的功率太小,负荷太大。周边几个村的水,都是接东孙楼的水,电机超负荷运转,烧坏了。”深井水管理员说,“潜水泵是水利局提供的,我到水利局找过,可水利局说没有配件。”

这位管理员表示,自己曾和厂家联系过,但总也联系不上。“电机坏了,潜水泵就不能用了,得换新的”。

然而换潜水泵又产生一个问题:“水利局不给换”,村里又没有钱,他不知道到哪儿去弄钱。“我也想过集资,但又怕集资违法。”管理员说,他只得挨家挨户做工作,一家收三五元,先把大功率的潜水泵买回来,以便尽早让村里人喝上“比较放心”的深井水。

另一个让他头痛的问题是,1元/吨的水费,还不够付电费和管理费用。“实在没钱,那就只好断水了。”管理员摇了摇头。

“以前,我最大的心愿就是村子里能打上一口深井。”王子清俯身望着井底,“可是三天两头断水,成本又那么高,以后我们该怎么办呢?”

虽然深井水供得断断续续,可毕竟隔三岔五有了水吃。然而,有了深井水,并不意味着癌症病魔从此就远离了这个村庄。霍岱珊以前联系过的一些癌症患者,相继都离开人世,现在不断仍有新的患者的名字传入他的耳朵。

王子清也常常担心,活着的人会有各种隐疾。他希望有关部门能为村里的人做一些专项检查,建立村民医疗档案,并派专人检验一下深井水的水质,是否真正得到了改善。

虽然新农村建设的口号,在东孙楼村喊的与外面的世界一样响,但老王真诚希望“不要仅仅是一阵风,仅仅是应付检查”,而是能确实给村里改善一下环境,比如道路硬化,渠塘净化,等等。

“命都没了,经济发展了又能怎样?”王子清质问。

对于东孙楼村出现的新问题及群众呼声,沈丘县卫生局一位副局长称,有关部门曾做出过应对措施,但这些应对措施还没有公开,不便透露。

不过,霍岱珊倒是带来一条好消息:一位日籍华裔将为村里提供生物过滤技术,据说应用此技术,届时就可喝上“达标”的水。

“莲花味精总经理高君也说了,他们公司将积极对待沙颍河的污染问题,要为历史的欠债填坑(埋单)。”霍岱珊说。

尽管东孙楼村治污的脚步在加快,可村子外的污染仍在继续。途经纸店镇一带,依然可闻到刺鼻的气味。司机介绍说,那一带的皮革厂很多,污染特别严重,许多树都死了。记者沿途看到,沟渠里的水黑乎乎的,像是粘稠的发酵物,沟渠边的几行树,叶子已经完全脱落,毫无生机。

一只野鸭子在不远处的水塘里游弋,司机放慢车速,瞟了一眼。

“这年头,能看到野鸭子可不是一件容易的事。”他说。

就在SIGGRAPH大会刚结束之后,AMD和暴雪在AMD官方网站上放出了《星际争霸II》的官方技术文档,通过游戏引擎技术的展示让星际迷们感受到越来越多的惊喜。

画面优化给CPU带来考验
着色方面,在使用原型的基础上利用3D Studio MAX让程序员对整体效果做最大的优化,反复的提炼使得整个作品就像被艺术家精心雕琢一样,配合上8000个独特的、不重复的线性着色渲染代码,使得Starcraft II与早期的游戏代码相比增加了N倍。

        在游戏制作初期,暴雪就认识到GPU的强大性能,因此在设计的时候就采用了以GPU为主的优化和大幅度图像质量增加。

        由于使用大量像素渲染操作,如果在游戏中当你选择了控制成百上千的zerglings或者marines等作战单位集体行动,势必造成CPU超负荷,即便是强大的GPU这也是一个考验。
大量的视觉特效(Based Effects)
        包括FP16 HDR、光线散射/反射效果(Diffuse and specular for lighting)、景深效果(depth of field)、体积雾(fog volumes)、动态环境遮蔽(dynamic ambient occlusion)、智能贴图置换(smart displacement)等等,这些都是Starcraft II的“BT”之处。

        然而,作为一个即时战略游戏,暴雪依然在“故事情节”的设定上下足了功夫,在游戏引擎的影响下,延迟缓冲器的深度和平均值,包括着色组建都完全为了效果而服务。而照明管道和阴影的利用也让深景效果等一些特效表现得淋漓尽致。不过,这些特效都还在讨论中。
在早期的开发过程中,图形引擎也作为一个重点中的重点进行设计:
可扩展性第一
        对于游戏引擎来说,一个主要的设计目标是扩展的引擎。暴雪的游戏质量是人所共知的,不光是他们的能力,更重要的是经验,从以前的一系列游戏开发经验来说,整个游戏各种族之间能力的平衡问题非常重要,而且图像效果之间的兼容性也必须考虑到,这样也是为了各种不同平台硬件之间搭配的玩家都能体验这个游戏的魅力所在,以确保游戏有足够的竞争力,因而从ATI Radeon 9800/NVIDIA GeForce FXs系列到ATI Radeon HD 4800s和NVIDIA GeForce G200s都可以轻松的进行游戏。
        相比之下,GPU的负载才是重点,像素着色单元往往会因为大量的单位同时出现而使得GPU难以承受,顶点着色单元的运用也必须合理,而先进的GPU才能体验到最大限度的特效,而对于普通的GPU只能尽量减少使用率来保证游戏的流畅度。
一个引擎,两个“世界”(Dual Nature of the Engine)

        这个双重性质的引擎使得整个游戏有更完美的体验,其实就是说SC2具有两个视角模式,一个是普通的RTS视角、一个是单人模式的RPG视角,当然在这两个模式下呈现的画面效果是有所不同的。具备两个视觉模式的原因正是我们之前提到的故事模式,当切换到单人模式的RPG视角时,玩家将会体验到暴雪对于整个游戏设定的精妙之处,通过一系列互动,包括对话等手段,其实从某种感觉上来说更像是第一人称射击游戏(FPS)。
    暴雪还将对这些不同的设定做更为细致的讨论,这样才能让玩家体验到不同的技术效果的运用。
屏幕基础效果
        作为Starcraft II的另一个设计目标,照明环境模式让游戏的互动更多,之前在魔兽争霸三中,每个单位有一个硬性限制,有多少亮度,可能会影响它在任何特定时间。出于这个原因,使用动态照明是相当微不足道的,但是在Starcraft II中每个单位有一个照明设备,当其中一个开启之后其他也会开启,这样效果非常好,但是由此带来的地图的设计和绘制,包括地图地形切片就成了相当复杂的问题。而即便是解决了这些,给GPU带来的负荷也是巨大的。
        针对于此,暴雪也做了很多限定 :
        ◆ 颜色组成部分,并不受当地照明,如发射、环境地图和点燃前期的彩色组成部分;
        ◆ 深度;
        ◆ 每像素正常;
        ◆ 如果使用静止环境闭塞,出口的环境闭塞的纹理被忽略,如果屏幕空间环境闭塞启用;
        ◆ 亮灯的弥漫物质的颜色;
        ◆ 亮灯的镜面材料的颜色。

解码缓冲器
        所有的缓冲器应该都使用相同的深度,不幸的是似乎这些缓冲器远远不能满足暴雪的需要,这些缓冲器以24字节每像素推动输出带宽,这样使得整个带宽明显不足,因此在安置光源的时候必须牺牲一些。
        为了向MRTs提供每像素值以保证用于各种的效果,因而以下必不可少:
        ◆ 深度值为照明、雾卷、动态环境闭塞和智能景深,预测,边缘检测和厚度测量;
        ◆ 平均值为动态环境闭塞;
        ◆ 弥漫性及镜面照明。
延迟渲染
        在Starcraft II中延迟渲染只适用与当前的渲染,包括灯光的点和散射出去的面都要再渲染,但是由于游戏中会出现很多的照明设备,如果都使用这样的方法渲染的话一定会造成画面过于缓慢,因此延迟缓冲器的出现也解决了这一难题。在延迟渲染和着色方程式的帮助下计算机能很快的绘制出不同形式或者更为复杂的光源,这样也为其他的计算提供了一个后处理的过程。
像素坐标重建

        受益于早期的样板,暴雪在设计新的形状和色彩的时候轻松了不少,而且同时还释放了CPU。

        相机原理我们都知道了,就通过这样的模式使得暴雪在视觉上更了解该如何设计。

屏幕空间环境光遮蔽
        屏幕空间环境光遮蔽(Space Ambient Occlusion,简称SSAO)。如果对这个名词感到陌生,那提及到让大家记忆犹深的《Crysis》逼真的光照效果时,一切就很简单了,这就是SSAO技术的独到之处。
        暴雪在这使用这方案的时候考虑到了整个空间的效果和质感,也许从某写方面上来看,没这个必要,但是基于暴雪的理念,一点点瑕疵都是不被允许的。

        在任何可见的点和表面在屏幕上,采取多个样本(8至32),这些样本,表现了在三维空间中从目前的点计算,到预计回屏幕空间所需的时间和深度。

        现在的目的是检查是否深入采样点,如果接近这个更远的采样点本身能获取信息的话就这么做下去,这是一个函数问题,因此需要复杂的计算。


        不过在对地图的计算时不会采用这样的方法,这仅仅是为了形成一个空间的效果而已。
模糊效果

        前面的一切都是为了更加细致的描绘出所有的场景,但是,有时候游戏还是需要一些模糊的图形图像,如果一直使用SSAO技术的话,必然导致不真实。
        对于SSAO来说,虽然是一种优势,但是高智能的判断在这时也显得尤为重要,何时需要高精度的细致图像,何时需要动态模糊效果,无论是着色还是渲染都需要大量的资源的计算才能显现这些复杂的效果。
自我闭塞

        这也是一个相当复杂的效果,就像一个围绕着一个半球体产生偏移向量,这一点上在屏幕上(这意味着需要使用大量的延迟缓冲器),由一个矩阵转化每个偏移向量和正常向量来抵销矢量。
边缘处理
        偏移向量在空间中并不像在屏幕空间中一样,由于镜头的不断移动使得SSAO不断变化,这样就需要在移动的过程中对镜头的边缘进行处理,以保证完美的视觉效果,但是纹处理包装上并不是一件简单的事。
SSAO的表现
        SSAO提供的效果是让人相当满意的,视觉图像质量的处理近乎完美,但是成本过高,而且大量使用还是会造成系统性能瓶颈,这样得不偿失,因此合理的使用这个技术也是讨论的问题之一。
SSAO和整体光线效果
        从图中很明显的发现了SSAO的精妙之处,如此逼真的效果让人赞叹不已,其实更多的还是其后面的技术支撑。



    我们可以把一切制约因素一起使用以下过程表示:
        ◆为每个像素在源的形象和存储执行一个全屏幕通过计算混乱循环结果,在Alpha通道的每边缩减一个CoC图像缓冲区的四分之一大小;
        ◆产生中等模糊图像通过应用的RGB高斯模糊与每个样本对源图像加权CoC;
        ◆产生的最大模糊图像只有缩小的RGB的图像缓冲区源图像的四分之一,每一个CoC和大型模糊缓冲器可以同时使用不同的通道;
        ◆最高模糊图像与RGB样本加权由缩减CoC执行,Alpha通道中载有CoC,也有模糊,但其样本不加权本身;
        ◆缩小和模糊一张深度地图成为一个缩减深度图像,重用深入SSAO缩减(SSAO不模糊深度 );
        ◆然后开始最后的景深着色,有一定的形象来源,中等和大型模糊、模糊CoC的形象,非模糊深入地图和缩减深入形象的渲染。



        景深渲染包括:
        ◇计算小模糊价值,直接使用小样本着色四近邻像素;
        ◇计算CoC的像素(缩减CoC将不匹配);
        ◇样本非模糊,使用模糊的深入比较——计算机CoC,如果是模糊的深入,比非模糊的深入更远,否则使用CoC价值样本,模糊CoC的形象;
        ◇计算贡献,从每一个可能的模糊图象,计算小模糊的颜色,中型和大型的图像模糊的基础上,CoC的因素;
        ◇小型,中型和大型模糊;
        ◇输出Alpha包括的源(无模糊)形象。
处理透明物体渲染
        透明度是一个值得深入研究的问题,当涉及到开发时暴雪的董事会认为延迟渲染技术不支持透明度的话就应该在其他地方加上这个功能,而事实证明这是一个正确的选择。
        作为是典型的就是延迟绘制技术,透明度的问题还设计到树荫等一系列问题,因此必须选择一些有代表性的物体来标记之后再做探讨。光线的问题在透明度的谈论中再一次被提及,因为这是个相辅相成的东西,因此暴雪在制作这一切的时候都努力的寻找解决方案。
半透明阴影(Translucent Shadows)
        这种技术能令烟雾、爆炸也能投射出阴影效果。

        早期在建模的时候影子系统都是成功地利用屏幕空间信息解决跟踪问题,否则将会困难很多,但这次暴雪将显示如何延长阴影地图的每像素信息与一些额外的信息通道,可以用来容易的充实阴影,地图上实现半透明的阴影支持。
        阴影地图算法是延长与第二地图的阴影信息形成半透明的阴影,大部分地图的影子仍然会包含不透明信息的阴影,此外还需要做到在颜色的缓冲区发现颜色半透明的阴影。不过,这一切都需要硬件的支持,如果硬件不支持将会有一个空的颜色,因此在考虑到深景等特效的时候暴雪依然在处理阴影效果。
        首先是清理,以白色调和,然后填补渲染透明物体的阴影,就这样形成一个透明的阴影色彩缓冲区,再加上测试,处理这些透明光过滤器,最后形成需要的效果。
光过滤处理器

总结:
        从上面简短的一份官方技术文档(因为AMD只放出这一部分),我们已经可以了解到暴雪在SC2这个游戏上所付出的努力和贡献了,其效果之华丽恐怕也是惊人的。作为暴雪十多年磨一剑的大作,《星际争霸II》可是包含了现在最尖端的技术和效果,无论是暴雪的质量还是技术相信都是世界顶级的水平,这样的游戏公司确实在为自己的的作品留芳百世而努力!不过,至于还要等多久,至今仍是一个谜。

NDIS HOOK是专业级防火墙使用的一种拦截技术,NDIS HOOK的重点是如何获得特定协议对应NDIS_PROTOCOL_BLOCK指针,获得了该指针,接下来就可以替换该协议所注册的收发函数,而达到拦截网络数据的目的。
     获 得NDIS_PROTOCOL_BLOCK指针的方法一般是用NdisRegisterProtocol注册一个新的协议,所获得的协议句柄实际上就是一 个NDIS_PROTOCOL_BLOCK指针,顺着该指针遍历NDIS_PROTOCOL_BLOCK链表,就可以找到你所要挂钩的协议所对应的 NDIS_PROTOCOL_BLOCK.之所以可以这样做,是因为每注册一个协议,系统都会把该协议对应的NDIS_PROTOCOL_BLOCK放置 在协议链表的开头,该协议链表每个元素都是NDIS_PROTOCOL_BLOCK类型,代表一个已经注册的协议。
     事 实上我们需要的只是TCPIP协议族的NDIS_PROTOCOL_BLOCK指针,毕竟TCP,IP,ARP,ICMP等等几乎所有我们感兴趣的协议, 都是在tcpip.sys协议驱动里面实现的。如果我们只需要TCPIP协议所对应的NDIS_PROTOCOL_BLOCK,那么上面的方法就有点繁琐 了。我们可以试着寻找更简便的方法来获得TCPIP协议的NDIS_PROTOCOL_BLOCK.
于 是我对tcpip.sys驱动进行了反汇编,发现NDIS_PROTOCOL_BLOCK指针存放在一个名为_ARPHandle的全局变量里面,所以如 果能找到_ARPHandle的地址,我们就成功了,我们完全可以把该全局变量的偏移量作为一个常量来使用,但这里纯粹为了拓宽思路,我介绍另一种找到该 全局变量的方法。
     Tcpip.sys有个导出函数叫IPDelayedNdisReEnumerateBindings,该函数内部曾经出现过_ARPHandle 的地址,为什么会出现它的地址呢,因为该函数内部调用过NdisReEnumerateProtocolBindings函数,懂得反汇编的应该知道,在 用call指令调用函数之前,必然会用到push指令将函数的参数压到栈里面去,不巧的是, NdisReEnumerateProtocolBindings函数只有一个参数,而该参数恰恰是一个NDIS_PROTOCOL_BLOCK指针类 型,在这里,实际上就是把_ARPHandle当作参数传给了
NdisReEnumerateProtocolBindings,所以_ARPHandle的地址必然会出现在push指令的后面,说具体一点,紧跟push指令的四个字节就是_ARPHandle的地址。
      所以具体的思路就是这样,先找到IPDelayedNdisReEnumerateBindings函数的地址,然后从该函数的地址开始搜索push指令的特征码,搜到了以后,把紧跟push指令的四个字节作为指向NDIS_PROTOCOL_BLOCK指针的指针返回。
     也许有的人会问,如果IPDelayedNdisReEnumerateBindings函数体内部出现过多次push指令,岂不是会搜出不正确的地址,事实上,虽然都叫push指令,然而在机器码级别是不同的,push指令的机器码表示有十几种之多,用来区别不同的寻址方式,调用NdisReEnumerateProtocolBindings 时用的push指令字节序列是0xff35,这个push指令表示后面紧跟的四个字节是一个内存地址,而不是一个立即数或者寄存器之类的。知道了这些,我 们就可以清楚,在一个有限的地址范围,0xff35的唯一性是可以得到满足的。根据我的观察,在win2000,winxp,win2003上面,IPDelayedNdisReEnumerateBindings本身是一个很短的函数,0xff35指令确实只出现过一次,所以该方法是很可靠的。
思路已经出来了,下面我把详细的代码给大家贴出来,理解这些代码需要对windows Pe格式有所了解,如果你不想理解也行,代码可以直接拿来用。
       以下是我写的一个 获取内核模块某个导出函数地址的 通用例程。这里主要是为了获取tcpip.sys模块的导出函数IPDelayedNdisReEnumerateBindings
   void* GetRoutineAddress(char* ModuleName,char* RoutineName)
{
       PIMAGE_DOS_HEADER dos_hdr;
    PIMAGE_NT_HEADERS nt_hdr;
    PIMAGE_EXPORT_DIRECTORY export_dir;
    ULONG *fn_name, *fn_addr, i;
      char* base;
      base=(char*)FindModule(ModuleName);//该函数用来获得内核模块的基地址
    if(!base)
        return NULL;
    DbgPrint("tcpip address:%p",base);
    dos_hdr = (PIMAGE_DOS_HEADER)base;
    if (dos_hdr->e_magic != IMAGE_DOS_SIGNATURE)
        return NULL;
    nt_hdr = (PIMAGE_NT_HEADERS)(base + dos_hdr->e_lfanew);
    export_dir = (PIMAGE_EXPORT_DIRECTORY)(base + nt_hdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
    fn_name = (ULONG *)(base + export_dir->AddressOfNames);
    fn_addr = (ULONG *)(base + export_dir->AddressOfFunctions);
    for (i = 0; i < export_dir->NumberOfNames; i++, fn_name++, fn_addr++)
    {
        if (strcmp(RoutineName, base + *fn_name) == 0)
        {
            return base + *fn_addr;
        }
    }
    return NULL;
}
以下是FindModule函数的实现:
void *
FindModule(char *name)
{
    ULONG i, n, *q;
    PSYSTEM_MODULE_INFORMATION p;
    void *base;
    ZwQuerySystemInformation(SystemModuleInformation, &n, 0, &n);
    q = (ULONG *)ExAllocatePool(PagedPool, n);
    ZwQuerySystemInformation(SystemModuleInformation, q, n * sizeof (*q), 0);
    p = (PSYSTEM_MODULE_INFORMATION)(q + 1);
    base = NULL;
    for (i = 0; i < *q; i++) {
        if (_stricmp(p.ImageName + p.ModuleNameOffset, name) == 0) {
            base = p.Base;
            break;
        }
    }
    ExFreePool(q);
    return base;
}
以下是获取tcpip协议的NDIS_PROTOCOL_BLOCK指针的函数
   void* GetProtocolBlock()
{
    char* base;
    char bytes[]={0xff,0x35};
    base=GetRoutineAddress("tcpip.sys","IPDelayedNdisReEnumerateBindings");
     while(RtlCompareMemory(base,bytes,2)!=2)
    {
       base++;
    }
    return **((void***)(base+2));
}

---INLINE HOOK实现NDIS HOOK
前面讲述了如何通过获取NDIS_PROTOCOL_BLOCK来实现NDIS HOOK,这里讲述第二种方法,那就是inline hook方法。说起inline hook,也不是什么新鲜玩意,无非是在一个函数的首部嵌入一个jmp机器指令,在该函数执行有效代码前就跳到我们的代理函数,在我们的代理函数里做了必要的处理以后,再跳回原来的函数,接着执行原函数的指令。
既然tcpip.sys是标准的NDIS协议驱动,那么收包函数显然应该是在tcpip.sys内部实现的,我们直接找到这两个收包函数,然后对其inline hook不就可以了吗?经过逆向分析,我找到了这两个函数,本人安装了两个XP系统,其中一个导出了这两个函数,另一个系统却没导出,所以我们仍然需要用特征码搜索这两个函数,这两个函数声明如下:
NDIS_STATUS
ARPRcv (NDIS_HANDLE BindContext,
NDIS_HANDLE MacContext,
UCHAR* HeadBuffer,
ULONG HeadSize,
UCHAR* Buffer,
ULONG BufferSize,
ULONG PacketSize);
INT
ARPRcvPacket (NDIS_HANDLE BindContext,
PNDIS_PACKET Packet);
搜索这两个函数地址的代码如下:
//以下全局变量保存两个函数的地址
void* ARPRcv=NULL;
void* ARPRcvPacket=NULL;
void SearchProtocolRoutine()
{
//以下分别为两个收包函数的特征码
UCHAR ARPRcvBytes[] ={0x8b,0xff,0x55,0x8b,0xec,0x56,0x8b,0x75,0x08,0x33};
UCHAR ARPRcvPacketBytes[]={0x8b,0xff,0x55,0x8b,0xec,0x51,0x53,0x56,0x57,0x8b};
//获取tcpip.sys模块的基地址,该函数在前一节已经提供给大家
char* base=FindModule("tcpip.sys");
while(ARPRcv==NULL||ARPRcvPacket==NULL)
{
if(ARPRcv==NULL&&
RtlCompareMemory(ARPRcvBytes,base,10)==10)
{
ARPRcv=base;
}
else if(ARPRcvPacket==NULL&&
RtlCompareMemory(ARPRcvPacketBytes,base,10)==10)
{
ARPRcvPacket=base;
}
base++;
}
}
各种编译器所编译的函数,前几个指令都是几乎一样的,用来建立堆栈帧,这些指令叫函数的序言。
在win2000上是三字节
push ebp
mov ebp, esp
到了winxp以及后续系统上,则变成了五字节
mov edi, edi
push ebp
mov ebp, esp
而一个近跳转指令刚好是五字节,在xp上刚好覆盖了函数的序言,所以在XP上挂钩也相对容易一点,这里着重说明如何对ARPRcv进行挂钩,我们在ARPRcv内部插入一个jmp指令,将跳到ARPRcvProx函数,该函数是个裸函数,函数实现如下:
_declspec(naked) ARPRcvProx()//跳板函数
{
_asm
{
mov edi, edi
push ebp
mov ebp ,esp
//七个参数开始压栈
push [ebp+20h]
push [ebp+1ch]
push [ebp+18h]
push [ebp+14h]
push [ebp+10h]
push [ebp+0ch]
push [ebp+8]
call NewARPRcv //调用NewARPRcv函数
cmp eax,0x10003 //判断函数返回值是否NDIS_STATUS_NOT_ACCEPTED
jz end //如果是NDIS_STATUS_NOT_ACCEPTED,直接结束本函数
//而不跳回到ARPRcv函数
mov eax,ARPRcv //如果返回的不是NDIS_STATUS_NOT_ACCEPTED,将会
//执行到这条指令,该指令将 ARPRcv函数的地址装入eax
add eax,5 //将ARPRcv地址值加上5,存入eax,表示即将跳转的//地址
jmp eax //开始跳回ARPRcv体内
end:
pop ebp
retn 1ch
}
}
在该函数内部,又调用了NewARPRcv函数,原型和ARPRcv保持一致,也必须由我们自己实现:
NDIS_STATUS
NewARPRcv(
IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_HANDLE MacReceiveContext,
IN PVOID HeaderBuffer,
IN UINT HeaderBufferSize,
IN PVOID LookAheadBuffer,
IN UINT LookaheadBufferSize,
IN UINT PacketSize
)
{
/*
在这里加入你的判断逻辑代码,是否拦截该数据
如果要拦截,则返回 NDIS_STATUS_NOT_ACCEPTED
否则返回NDIS_STATUS_SUCCESS,把数据交给ARPRcv处理
*/
return NDIS_STATUS_SUCCESS;
}
同样的原理,我们在ARPRcvPacket里面插入jmp指令,将跳转到ARPRcvPacketProx裸函数,该函数实现如下:
_declspec(naked) ARPRcvPacketProx()
{
_asm
{
mov edi, edi
push ebp
mov ebp ,esp
//两个参数开始压栈
push [ebp+0ch]
push [ebp+8]
call NewARPRcvPacket//调用NewARPRcvPacket
cmp eax,0 //如果返回0则表示拒绝该数据包
jz end //直接返回本函数
mov eax ,ARPRcvPacket
add eax ,5
jmp eax //跳回ARPRcvPacket函数第六个字节
end: pop ebp
retn 8
}
}
在该函数内部,将会调用NewARPRcvPacket,函数实现如下:
INT
NewARPRcvPacket(NDIS_HANDLE BindContext,
PNDIS_PACKET ndisPacket)
{
/*
在这里加入你的判断逻辑,是否拦截该数据,如果要拦截,则返回0,
否则返回非0
*/
DbgPrint("RcvPacket");
return 1;
}
请仔细阅读以上代码的注释,接下来,我们还必须提供一个函数实现安装和卸载挂钩功能
void PatchARPRcv(BOOLEAN isPatch)//isPatch为TRUE表示安装挂钩,为FALSE表示卸载挂钩。
{
/*即将用以下五个字节覆盖ARPRcv函数前五个字节
这5个字节就是jmp XXXX指令的机器码,因为跳转的相对地址还需要
进一步计算,所以暂时用零填充
*/
UCHAR patchBytes[5]={0xe9,0x00,0x00,0x00,0x00};
//即将用以下五个字节覆盖ARPRcvPacket函数前五个字节
UCHAR patchBytes2[5]={0xe9,0x00,0x00,0x00,0x00};
//保存原始函数的前五个字节,方便以后恢复挂钩
UCHAR restoreBytes[5]={0x8b,0xff,0x55,0x8b,0xec};
/*
以下两行代码计算跳转的偏移量
*/
int offset=(char*)ARPRcvProx-(char*)ARPRcv-5;
int offset2=(char*)ARPRcvPacketProx-(char*)ARPRcvPacket-5;
//修正patchBytes和patchBytes2中的相对地址
memcpy(patchBytes+1,&offset,4);
memcpy(patchBytes2+1,&offset2,4);
if(isPatch)
{
DisableWriteProtect();//禁止写保护
memcpy(ARPRcv,patchBytes,5);
memcpy(ARPRcvPacket,patchBytes2,5);
EnableWriteProtect(); //开启写保护
}
else
{
DisableWriteProtect();
memcpy(ARPRcv,restoreBytes,5);
memcpy(ARPRcvPacket,restoreBytes,5);
EnableWriteProtect();
}
}
因为ARPRcv和ARPRcvPacket函数处于只读页,所以必须先禁用写保护才能向其中插入代码,禁用写保护和开启写保护代码如下:
void
DisableWriteProtect()
{
_asm{
cli
mov eax, cr0
and eax, 0FFFEFFFFh
mov cr0, eax
}
}
void
EnableWriteProtect()
{
_asm{
mov eax, cr0
or eax, not 0FFFEFFFFh
mov cr0, eax
sti
}
}
注意这些代码暂时只适用XP系统,在win2000和win2003上都需要少许改动。