第一步:用winhex将下面数据生成rar格式的文件。D000000000000第二步:在winhex中取65h-71h一段数据ctrlc后粘贴到密码输入框点确定完成秒破。(实例一)实例二D000000000000选中14h-1bh一段数据ctrlc后粘贴到密码输入框中后面再加上dch-e3h处的ASCII字符,确定后即秒破了!信不信由你!RAR加密的原理,是将UNICODE格式的密码,与随机生成的一个8字节的SALT连在一起,根据它生成AES算法的密钥来进行加密。而加密后的RAR中,除了加密后的原压缩内容之外,文件头结构还保存了这个SALT值用于解密。原则上SALT的生成过程跟用户输入时的密码一点关系都没有,因此它本来不保存关于密码的显式信息,但是我们可以对WINRAR程序进行patch,使SALT跟密码发生直接联系,从而使这个SALT成为潜在的“后门”。由于SALT只有8个字节,所以对于8个字节以内的密码,可以直接保存在SALT中(或者简单的XOR一下或其他,反正可以用很容易的可逆的算法处理)。那么密码超出8字节怎么办?这里楼主分为两种方式处理,分别是实例一和实例二。实例一应该是利用了把文件头的HEAD_SIZE字段改大,这样文件头多出来的地方(WINRAR读取文件头时是跳过这部分的)就可以保存密码8字节以后的内容。实例一中的65h-6ch内容就是SALT,而6dh-71h就属于把HEAD_SIZE改大之后多出来的部分了。但是实例一这种方法应用的前提是文件头没加密。如果文件头被加密(这时MAIN_HEAD的HEAD_FLAGS包含0x0080),那么MAIN_HEAD后面紧跟着的就是SALT(实例二的14h-1bh内容),SALT后面则是被加密的所有内容(包括文件头)。那么怎么把密码8字节以后部分搞进去?实例二的做法,我猜是因为加密过程是16字节为一组,加密后的内容也应该是16字节的倍数,所以解密时也以16字节为单位读取,当文件内容最后跟着一段小于16字节的数据时,WINRAR解密时直接无视这段数据。于是就可以把密码的后半部分放在文件最后(但是不能超过16字节),这样用这种方法可以保存不超过23字节的密码。按照这个思路,我调试了一下我电脑上的WINRAR3.70。我只考虑密码不超过8字节,实际上问题就是找到WINRAR程序操作压缩的过程,在程序把SALT和密码连在一起之前,把SALT改为和密码一样,这样压缩出来的就是那样的文件了。超过8字节的代码只要按照上述思路自己修改生成后的RAR就可以了。具体步骤:创建一个新RAR文件,OD载入WINRAR程序,F9跑起来,打开这个空RAR文件,往里面添加一个文件,这时WINRAR程序会弹出添加文件到压缩文件的对话框。第一步要做的是在这个对话框保存我们输入的密码时断下。怎么定位这个并不难,因为当在添加文件的对话框中高级选项卡点击“设置密码”的时候,会弹出输入密码的框,就从拦截这个对话框入手,程序弹出这个子对话框采用的是DialogBoxParamA,只要在这个API上下断就可以断下:77D3B144>8BFF mov edi,edi ;WinRAR.004BB5D0看堆栈:0012A404 00482A3B/CALL到DialogBoxParamA来自WinRAR.00482A360012A408 00400000|hInst=004000000012A40C 004AC73C|pTemplate="GETPASSWORD2"0012A410 00040714|hOwner=00040714('高级',class='#32770',parent=001B06FA)0012A414 0047D78A|DlgProc=WinRAR.0047D78A0012A418 0012A428\lParam=0012A428进到调用来源00482A36,看一下调用过程:00482A1E|.8D957CFFFFFFlea edx,dwordptr[ebp-84]00482A24|.52 push edx ;/lParam00482A25|.688AD74700 push 0047D78A ;|DlgProc=WinRAR.0047D78A00482A2A|.53 push ebx ;|hOwner00482A2B|.683CC74A00 push 004AC73C ;|pTemplate="GETPASSWORD2"00482A30|.FF3548214B00push dwordptr[4B2148] ;|hInst=0040000000482A36|.E895F10100 call ;\DialogBoxParamA00482A3B|.85C0 test eax,eax00482A3D|.0F95C1 setne cl00482A40|.83E101 and ecx,100482A43|.8BD9 mov ebx,ecx00482A45|.84DB test bl,bl00482A47|.7415 je short00482A5E00482A49|.8D857CFFFFFFlea eax,dwordptr[ebp-84]00482A4F|.50 push eax00482A50|.57 push edi00482A51|.E82A520100 call 00497C80 ;CopyString由于对话框调用完后紧接着是一个字符串拷贝,因此可以推断传送给密码对话框的这个lParam参数就是让密码对话框保存密码的位置,对话框关闭之后又将密码Copy到一个全局数据区保存起来(对对话框窗口过程的调试证明这个推测是正确的),而此时的edi就是保存密码的全局数据区地址,这个值是004BB5D0。在callDialogBoxParamA的下一句下断,F9让密码对话框出现,填写密码(不要超过8字节),按确定,断下了,然后F8观察CopyString的参数证实上面的推测是正确的。现在仍然在对话框的窗口过程中:00446AB4|.E827BF0300 call 004829E000446AB9|.84C0 test al,al00446ABB|.7447 je short00446B0400446ABD|.B8E6000000 mov eax,0E600446AC2|.803DD0B54B00>cmp byteptr[4BB5D0],000446AC9|.7505 jnz short00446AD000446ACB|.05F8020000 add eax,2F800446AD0|>E8FBBAFCFF call 004125D0显然后续代码证实了4BB5D0开始的全局数据区的确是在存取密码的。于是下一步在WINRAR程序从这里取出密码进行加密操作的时候把它断下。对4BB5D1下硬件访问断点(为什么要下在4BB5D1而不直接在4BB5D0,那是因为如果下在4BB5D0,将会断到大量的cmp byteptr[4BB5D0],0,而只有开始读取4BB5D1处才能说明是真正的在读取其内容而不是单独地比较密码是否为空),F9跑起来,完成添加文件对话框的设置点确定关闭这个对话框,OD断下:00497C53|.2BC3 |sub eax,ebx00497C55|.7526 |jnz short00497C7D00497C57|.84DB |test bl,bl00497C59|.7422 |je short00497C7D00497C5B|.8A4102 |mov al,byteptr[ecx2]00497C5E|.8A5A02 |mov bl,byteptr[edx2]这是一个CompareString,CtrlF90041139D|>/FF75FC /push dwordptr[ebp-4]004113A0|.|69C3AA000000|imul eax,ebx,0AA004113A6|.|81C0303F4A00|add eax,004A3F30 ;ASCII".,];/[]"004113AC|.|50 |push eax004113AD|.|E882680800 |call 00497C34004113B2|.|83C408 |add esp,8 ;到这里004113B5|.|85C0 |test eax,eax004113B7|.|0F858F000000|jnz 0041144C在一个循环里,在下面F4跳出循环:00411456|>\807DEB00 cmp byteptr[ebp-15],00041145A|.0F850B020000jnz 0041166B00411460|.8D9560FEFFFFlea edx,dwordptr[ebp-1A0] ;保存UNICODE形式的密码00411466|.B97F000000 mov ecx,7F0041146B|.8B45FC mov eax,dwordptr[ebp-4] ;004BB5D0,密码字符串指针0041146E|.E841F0FFFF call 004104B4 ;ANSI转换成UNICODE00411473|.66:C7855EFFF>mov wordptr[ebp-A2],00041147C|.8D9558FDFFFFlea edx,dwordptr[ebp-2A8]00411482|.8D8560FEFFFFlea eax,dwordptr[ebp-1A0]00411488|.B900000001 mov ecx,10000000041148D|.E842F0FFFF call 004104D4 ;stringcopy00411492|.8D8560FEFFFFlea eax,dwordptr[ebp-1A0]00411498|.E8CBF2FFFF call 00410768 ;取UNICODE字符串长度0041149D|.03C0 add eax,eax0041149F|.85FF test edi,edi004114A1|.8945E4 mov dwordptr[ebp-1C],eax004114A4|.7419 je short004114BF004114A6|.6A08 push 8004114A8|.57 push edi004114A9|.8D9558FDFFFFlea edx,dwordptr[ebp-2A8]004114AF|.0355E4 add edx,dwordptr[ebp-1C]004114B2|.52 push edx004114B3|.E8D8650800 call 00497A90 ;memcpy?004114B8|.83C40C add esp,0C004114BB|.8345E408 add dwordptr[ebp-1C],8上面这段代码就很清楚了,就是把密码变为UNICODE并把SALT加在后面。因此此时的edi就是保存SALT的指针,数据窗口中观察:02A32D6CECD4D14B47600F6E 煸袺G`n?.如果此时不修改这个SALT值,让WINRAR完成整个过程,再在RAR文件中观察文件头结构会发现SALT的确是这个内容。现在在这里直接把这个位置用密码字符串代替(为了学习楼主,我把密码同样搞成几个标点符号):02A32D6C2E2C5D3B2F5B5D00 .,];/[]解除断点让WINRAR完成操作。生成的RAR文件内容:D000000000000WINHEX打开文件,在文件3ch-43h处正是SALT值,也正是我设的密码(只有7个字节,所以最后是00):Offset 01234567 89ABCDEF00000030 2E2C5D3B .,];00000040 2F5B5D00 /[].至此我成功在WINRAR3.70中通过OD调试WINRAR程序实践了楼主所说的内容,显然只剩下把这个过程转化成patch就可以实用化了。