网站建设用哪种语言好,帮网站做点击,自学电商还是去培训机构,安徽黄山网站建设标 题:【原创】冰点密码破解 — 强悍的调试器 SOFTICE作 者: figo时 间: 2007-06-11,15:17链 接: http://bbs.pediy.com/showthread.php?t46153【文章标题】: 冰点密码破解【文章作者】: figo【作者邮箱】: yangtengfei56.com【作者QQ号】: 382174647【软件名称】: 冰点6.00.2…标 题: 【原创】冰点密码破解 — 强悍的调试器 SOFTICE作 者: figo时 间: 2007-06-11,15:17链 接: http://bbs.pediy.com/showthread.php?t46153【文章标题】: 冰点密码破解【文章作者】: figo【作者邮箱】: yangtengfei56.com【作者QQ号】: 382174647【软件名称】: 冰点6.00.220.1692 企业版 【加壳方式】: 未知壳【保护方式】: ANIT DEBUG,加壳【编写语言】: C , ASM32【使用工具】: SOFTICE MASM32 VC 6.0【操作平台】: WINXP【作者声明】: 纯技术交流,不针对任何软件.请勿用于恶意破坏等非法用途, 否则给自己或他人带来严重后果,概与本人无关.失误之处恳请批评指正, 或有更好的方法或者技巧,欢迎互相交流.--------------------------------------------------------------------------------【软件介绍】: Deep Freeze 是一款类似于还原精灵的系统还原软件,但它比还原精灵强悍,无论加密强度或安全性. 据介绍这软件无解,至今为找到破解方法.一旦弄丢了管理密码,只能格式化磁盘重新安装系统了. 笔者发布此文章只是为了交流技术,并无其它目的,请不要用于恶意破坏等非法用途. 如果文章能丢失为密码的用户带来一点帮助的话,笔者会十分欣慰的,毕竟好几天的努力才完成这文章的, Deep Freeze 的下载地址也不提供了,网上到处都是,版本是 6.20.220.1692 【详细过程】 破解前的准备: 先安装好 冰点 和 SOFTICE,笔者用的 DS3.2 中的 SOFTICE. 还有 IceExt 0.70 插件的安装(这并不是必须的, 只是写文章的时候要用到,后面会介绍 IceExt 插件的妙用).装好冰点后,把客户端的密码设置为:382174647 (呵呵,这是我的QQ号, 当然,你也可以设置为任意密码 ),把还原的盘设为 Z 盘(也可以任意, 但一般不设为自己的硬盘分区),最后安装客户端. 开始分析: 首先,按住键盘上的 CTRL ALT SHIFT F6 四个键,调出冰点的密码输入对话框. 输入任意密码,如: 234234. CTRL D 调出 SOFTICE. 此时,你可千万别指望能在内存中找到 234234 的数据,并置断点. 用 S 指令搜遍整个 4G 空间也一样,就算找到了,那也不是密码文本框的. 因为当改变文本框的内容时,该文本框会自动调用 NT 的 Native API :RtlRunEncodeUnicodeString 函数 进行加密. 当应用程序想获取文本内容时,该文本框又会调用 RtlRunDecodeUnicodeString 函数进行解密. 关于 RtlRunEncodeUnicodeString 和 RtlRunDecodeUnicodeString 的源代码可以在 NT 源代码中的 sertl.c 文件中找到. 其实 RtlRunEncodeUnicodeString 只是对数据进行简单的 XOR 运算,尽管加密算法简单,却很有效的防止在内存中被找出明码. 虽然我们可以不用知道 RtlRunDecodeUnicodeString 的具体算法,但为了利于破解,我们还是有必要知道它的定义: VOID RtlRunDecodeUnicodeString( UCHAR Seed, PUNICODE_STRING String ) 第一个参数是 : 字节类型, 加密的种子的值. 第二个参数是: 是个 PUNICODE_STRING 数据类型 指向被解密的数据的地址(注意了,是双重指针) 好了,通过上面的分析,我们开始对 RtlRunDecodeUnicodeString 下断点,点击 OK 按纽,程序被中断在如下代码: EAX0000002A EBX00000006 ECX7C822E07 EDX00140608 ESI0014C2A8 EDI0014CDB0 EBP0012F088 ESP0012F06C EIP7C94EF8B o d I s Z a P c CS001B DS0023 SS0023 ES0023 FS003B GS0000 --------------------------------------------------byte--------------PROT---(0)-- 0023:00E20034 B0 CD 14 00 03 00 00 00-28 CF 14 00 68 00 E2 00 ........(...h.? 0023:00E20044 00 00 00 00 03 00 01 00-90 A5 15 00 03 00 01 00 ........惀...... 0023:00E20054 B0 65 17 00 03 00 01 00-D0 25 19 00 03 00 01 00 .e.......%...... 0023:00E20064 F0 E5 1A 00 70 00 E2 00-00 00 00 00 78 00 E2 00 .?.p.?....x.? ------ntdll!RtlRunEncodeUnicodeString004D-------------------------------PROT32- ntdll!RtlRunDecodeUnicodeString 001B:7C94EF8B 8BFF MOV EDI,EDI 001B:7C94EF8D 55 PUSH EBP 001B:7C94EF8E 8BEC MOV EBP,ESP 刚才我们了解到 RtlRunDecodeUnicodeString 的第二个参数是指向密文的双重指针,输入: D *(ESP - 08) 这时,密文的地址如上面DATA 窗口所示,为 14CDB0H. 不要急着下断点,要等到它解密完毕. P RET ,跳出 RtlRunDecodeUnicodeString 然后 D 14CDB0 --------------------------------------------------byte--------------PROT---(0)-- 0023:0014CDB0 32 33 34 32 33 34 00 00-00 00 00 00 00 00 00 00 234234.......... 0023:0014CDC0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 可以看到明码已经出现在我们面前. 好了,可以对它下硬件读断点 bpm 14CDB0 R G 运行. 程序被中断在如下代码: ------USER32!EditWndProc0566--------------------------------------------PROT32- 001B:77D3352D F3A5 REPZ MOVSD 001B:77D3352F 8BC8 MOV ECX,EAX 001B:77D33531 83E103 AND ECX,03 001B:77D33534 F3A4 REPZ MOVSB 001B:77D33536 E8E3FBFFFF CALL 77D3311E 001B:77D3353B 5F POP EDI 001B:77D3353C 5E POP ESI 001B:77D3353D 8BC3 MOV EAX,EBX 001B:77D3353F 5B POP EBX 001B:77D33540 5D POP EBP 001B:77D33541 C21000 RET 0010 不难看出,这段代码主要是实现数据的复制 这时的 EDI 00BC932C, 而 ESI 则是刚才明码的地址, ESI 0014CDB0H 同样,对 00BC932CH 下硬件读断点.G 运行 . 接下来,程序再次中断在 RtlRunDecodeUnicodeString 上,我们再次重复上面这一过程. 唯一不同的是,这次明码是被复制到 00BCA488H 处.于是对 00BCA488H 再下一个硬件读断点. G 运行 . 程序中断在如下代码: AX00BCA488 EBX00BCA488 ECX0012F348 EDX32343332 ESI0012F33C EDI00BCAE11 EBP0012F284 ESP0012F254 EIP004961F2 o d I s Z a P c CS001B DS0023 SS0023 ES0023 FS003B GS0000 --------------------------------------------------byte--------------PROT---(0)-- 0023:00BCA488 32 33 34 32 33 34 00 00-26 00 00 00 EC 9C BC 00 234234.....鞙.. 0023:00BCA498 00 00 00 00 34 9D BC 00-00 00 00 00 13 00 00 00 ....4?......... 0023:00BCA4A8 00 00 00 00 01 00 00 00-24 00 00 00 16 00 00 00 ........$....... 0023:00BCA4B8 EC 46 BC 00 24 AA BC 00-4F 70 74 69 14 00 00 00 霧..$?.Opti.... -------------------------------------------------------------------------PROT32- 001B:004961F0 8B10 MOV EDX,[EAX] 001B:004961F2 83C004 ADD EAX,04 001B:004961F5 8BCA MOV ECX,EDX 001B:004961F7 81EA01010101 SUB EDX,01010101 001B:004961FD 81E280808080 AND EDX,80808080 001B:00496203 74EB JZ 004961F0 001B:00496205 F7D1 NOT ECX 001B:00496207 23D1 AND EDX,ECX 001B:00496209 74E5 JZ 004961F0 对每个字节减 1 ,再判断是否为负,这段代码应该是测试字符串长度的. 看看它返回的是什么值? P RET 代码如下: EAX00000006 EBX00BCA488 ECX00BCA488 EDX80800000 ESI0012F33C EDI00BCAE11 EBP0012F284 ESP0012F25C EIP0040BF90 o d I s z a P c CS001B DS0023 SS0023 ES0023 FS003B GS0000 DS:00BCAE110014 ------------------------------------------------------------------------------- 001B:0040BF87 E85CA20800 CALL 004961E8 001B:0040BF8C 59 POP ECX 001B:0040BF8D 8945FC MOV [EBP-04],EAX 001B:0040BF90 0FB707 MOVZX EAX,WORD PTR [EDI] 001B:0040BF93 85C0 TEST EAX,EAX 001B:0040BF95 7513 JNZ 0040BFAA EAX 返回 6,没猜错,果然是测字符串长度的. EAX 保存在 EBP -4 处,再对 EBP -4 下一个硬件读断点. G 运行. 程序中断在如下代码: 001B:0040BFB4 3B45FC CMP EAX,[EBP-04] 001B:0040BFB7 7407 JZ 0040BFC0 (NO JUMP) 001B:0040BFB9 33C0 XOR EAX,EAX 001B:0040BFBB E989000000 JMP 0040C049 此时的 EAX 9 (原来密码的长度) ,[EBP -4] 6 (输入密码的长度) 不相等就清零 EAX ,并跳到 40C049 再看看 40C049 处的代码: 001B:0040C049 5F POP EDI 001B:0040C04A 5E POP ESI 001B:0040C04B 5B POP EBX 001B:0040C04C 8BE5 MOV ESP,EBP 001B:0040C04E 5D POP EBP 001B:0040C04F C3 RET 这是子过程结束的标准语句. CMP EAX,[EBP-04] 和 JZ 0040BFC0 是判断输入密码和原密码的长度是否相符. 这两句很重要,请记住它,写密码破解程序时要用到它. 为了继续调试,把 Z 位 置 1,单步.. 代码如下: EAX00000009 EBX00BCA488 ECX00BCA488 EDX80800000 ESI0012F33C EDI00BCAE11 EBP0012F284 ESP0012F25C EIP0040BFC0 o d I s Z a P c CS001B DS0023 SS0023 ES0023 FS003B GS0000 DS:0012F33C9F448C62 --------------------------------------------------byte--------------PROT---(0)-- 0023:00BCA488 32 33 34 32 33 34 00 00-26 00 00 00 EC 9C BC 00 234234.....鞙.. 0023:00BCA498 00 00 00 00 34 9D BC 00-00 00 00 00 13 00 00 00 ....4?......... 0023:00BCA4A8 00 00 00 00 01 00 00 00-24 00 00 00 16 00 00 00 ........$....... 0023:00BCA4B8 EC 46 BC 00 24 AA BC 00-4F 70 74 69 14 00 00 00 霧..$?.Opti.... -------------------------------------------------------------------------PROT32- 001B:0040BFC0 8B16 MOV EDX,[ESI] 001B:0040BFC2 895604 MOV [ESI04],EDX 001B:0040BFC5 33C9 XOR ECX,ECX 001B:0040BFC7 8BD3 MOV EDX,EBX 001B:0040BFC9 894DF8 MOV [EBP-08],ECX 001B:0040BFCC 8D4702 LEA EAX,[EDI02] 001B:0040BFCF C745F402000000 MOV DWORD PTR [EBP-0C],00000002 001B:0040BFD6 8955E4 MOV [EBP-1C],EDX 001B:0040BFD9 8BF8 MOV EDI,EAX 001B:0040BFDB 8B4DF8 MOV ECX,[EBP-08] ;已经与密码比较过的字节数 001B:0040BFDE 3B4DFC CMP ECX,[EBP-04] ;密码的长度 001B:0040BFE1 7D64 JGE 0040C047 ;此处改为 JMP 0040C047,也可实现暴破 001B:0040BFE3 56 PUSH ESI 001B:0040BFE4 E8B7FEFFFF CALL 0040BEA0 ;密码算法的关键 CALL ,喜欢研究算法的朋友可以跟进瞧瞧,不过也无意义,等下解释为什么. 001B:0040BFE9 59 POP ECX 001B:0040BFEA 8B45E4 MOV EAX,[EBP-1C] ;指向输入的密码的第N个字节,N [EBP - 8] 001B:0040BFED 8A18 MOV BL,[EAX] 001B:0040BFEF 8A07 MOV AL,[EDI] 001B:0040BFF1 324604 XOR AL,[ESI04] ;解密出原密码的第N个字节 001B:0040BFF4 8845F3 MOV [EBP-0D],AL ;暂存 001B:0040BFF7 807D1400 CMP BYTE PTR [EBP14],00 001B:0040BFFB 7409 JZ 0040C006 001B:0040BFFD 3A5DF3 CMP BL,[EBP-0D] 001B:0040C000 742F JZ 0040C031 001B:0040C002 33C0 XOR EAX,EAX 001B:0040C004 EB43 JMP 0040C049 001B:0040C006 0FBED3 MOVSX EDX,BL 001B:0040C009 8955EC MOV [EBP-14],EDX 001B:0040C00C 8B4DEC MOV ECX,[EBP-14] 001B:0040C00F 51 PUSH ECX 001B:0040C010 E873D40800 CALL 00499488 001B:0040C015 59 POP ECX 001B:0040C016 50 PUSH EAX 001B:0040C017 0FBE45F3 MOVSX EAX,BYTE PTR [EBP-0D] 001B:0040C01B 8945E8 MOV [EBP-18],EAX 001B:0040C01E 8B55E8 MOV EDX,[EBP-18] 001B:0040C021 52 PUSH EDX 001B:0040C022 E861D40800 CALL 00499488 001B:0040C027 59 POP ECX 001B:0040C028 59 POP ECX 001B:0040C029 3BC8 CMP ECX,EAX ; 开始对比,EAX 为原密码的第N个字节 001B:0040C02B 7404 JZ 0040C031 ; 关键跳转,很重要,写破解程序时,要用到它. 001B:0040C02D 33C0 XOR EAX,EAX 001B:0040C02F EB18 JMP 0040C049 001B:0040C031 FF45E4 INC DWORD PTR [EBP-1C] 001B:0040C034 FF45F8 INC DWORD PTR [EBP-08] ;对比的字节地址加 1 001B:0040C037 47 INC EDI 001B:0040C038 FF45F4 INC DWORD PTR [EBP-0C] 001B:0040C03B 47 INC EDI 001B:0040C03C FF45F4 INC DWORD PTR [EBP-0C] 001B:0040C03F 8B55F8 MOV EDX,[EBP-08] 001B:0040C042 3B55FC CMP EDX,[EBP-04] 001B:0040C045 7C9C JL 0040BFE3 ;判断是否对比完毕.未完则继续. 001B:0040C047 B001 MOV AL,01 001B:0040C049 5F POP EDI 001B:0040C04A 5E POP ESI 001B:0040C04B 5B POP EBX 001B:0040C04C 8BE5 MOV ESP,EBP 001B:0040C04E 5D POP EBP 001B:0040C04F C3 RET 这段代码便是密码比较的最重要部分,由于代码长而复杂,于是就用注释来代替跟踪. 对冰点密码算法感兴趣的朋友,可以直接对 40BDC0H 置断点,并依照注释自己跟踪调试一下. 解密器的编写思路 : 既然程序可以把原密码解密出单字节并与输入密码进行循环比较,我们可以写一个程序, 对程序每次解出的单字节密码进行拼接. 如果把 40C029 — 40C030 之间8个字节全部用 NOP 填充,可以实现爆破. 这说明 40C029 — 40C030 之间有8个字节可以利用.而不远处 0040C03F 有 MOV EDX,[EBP-08] 这么一条指令,说明EDX 也可以利用. 于是解密程序先为 冰点 进程远程分配一段内存,然后把远程代码写入内存. 最后在 40C029 — 40C030 之间写如下代码: NOP MOV EDX,XXXXXXXX CALL EDX XXXXXXXX 为远程代码的起始地址,编译成字节码如下: 90,BA XXXXXXXX ,FF D2 . 刚好8个字节. 写此程序遇见的第一个问题就是: 如何确定原密码的长度? 也许你会说[EBP -4] 不就是吗? 不是的,[EBP - 4]其实是我们输入密码的长度. 这时,你可能更纳闷了,如果密码循环比较是由输入的密码的长度决定,那程序的安全性不就只有一个字节了? 别忘了,我们进入这段代码是通过强制跳转的,正常情况下,只有[EBP - 4]等与原密码的长度才进行比较. 就算使用代码补丁进入密码比较你也无法知道原密码的长度,唯一的办法就是让[EBP - 4] 等于原密码的长度, 然后再强行跳转.于是我们就在 40BFB4H 处的 CMP EAX,[EBP-04] 和 JZ 0040BFC0 下文章. 把它改为 MOV [EBP-04],EAX 和 JMP 0040BFC0 就可以完美解决. 具体代码实现: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;code.inc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; .486 .model flat, stdcall option casemap :none include /masm32/include/windows.inc include /masm32/include/masm32.inc include /masm32/include/kernel32.inc include /masm32/include/advapi32.inc include /masm32/include/user32.inc includelib /masm32/lib/masm32.lib includelib /masm32/lib/kernel32.lib includelib /masm32/lib/advapi32.lib includelib /masm32/lib/user32.lib GetPidFromProcName proto :DWORD WritePMem proto :DWORD,:DWORD,:DWORD,:DWORD .data procname db FrzState2k.exe ,00 mempatch db 0ebh,089h,045h,0fch farcall db 90h,0bah,0ffh,0d2h funadd dd ? szMsgBox db MessageBoxA,0 szuserdll db user32.dll,0 lpMsgfun dd ? szsvrname db MyServerName1,0 szstr1 db 冰点破解程序,0 szstr2 db 运行此程序后,按 CTRL SHIFT ALT F6,调出密码输入对话框,13,10 db 可以不用输入密码,或输入任意密码.,13,10 db 点击 OK ,即可显示密码,并进入控制界面!,13,10 db 本程序破解时,远程分配的空间并不释放.,13,10 db 多次运行后请重起!,13,10,13,10 db by figo (追风者),13, 10, QQ : 382174647,0 buf1 db 120h dup (00) buf2 db 124h dup (00) szfmt db %s,0 var1 db sys,0 .code mycode: lpmsg dd ? sztil db 密码为: ,0 szstr db password is szpwd db 70h dup (0) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; startcode: pushad call l1 l1: pop ebx sub ebx,offset l1 ;很经典的代码自定位技术,不陌生吧! lea edi, [ebx offset szpwd] mov edx,[ebp - 8] add edi,edx mov byte ptr [edi],al inc edx mov eax,[ebp -4] cmp edx,eax jl ext1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; push MB_OK or MB_SERVICE_NOTIFICATION ;由于冰点会不断把密码输入对话框置前,所以只能加上 MB_SERVICE_NOTIFICATION 常数. lea edi ,[ebx offset sztil] push edi lea edi ,[ebx offset szpwd] push edi push 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; mov eax,[ebx offset lpmsg] call eax ext1: popad ret codeend: GetPidFromProcName proc lpProcName:DWORD LOCAL stProcess : PROCESSENTRY32 LOCAL hSnapshot LOCAL dwProcessID mov dwProcessID, 0 invoke RtlZeroMemory, addr stProcess, sizeof stProcess mov stProcess.dwSize, sizeof stProcess invoke CreateToolhelp32Snapshot, TH32CS_SNAPPROCESS, 0 mov hSnapshot, eax invoke Process32First, hSnapshot, addr stProcess .while eax invoke lstrcmpi, lpProcName, addr stProcess.szExeFile .if eax0 mov eax, stProcess.th32ProcessID mov dwProcessID, eax .break .endif invoke Process32Next, hSnapshot, addr stProcess .endw invoke CloseHandle, hSnapshot mov eax, dwProcessID ret GetPidFromProcName endp WritePMem proc hproc:DWORD, rwadd:DWORD ,lpbuff:DWORD, nsize:DWORD local dwrwcnt local oldpct invoke VirtualProtectEx,hproc,lpbuff,4096,PAGE_EXECUTE_READWRITE,addr oldpct .if !eax ret .endif invoke WriteProcessMemory ,hproc,rwadd,lpbuff,nsize,addr dwrwcnt invoke VirtualProtectEx,hproc,lpbuff,4096,oldpct,addr oldpct mov eax, dwrwcnt ret WritePMem endp ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;code.inc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;deep.asm;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; include code.inc start: Main proc local hproc1 local hSCManager local hService ;//提权/// invoke GetCommandLine mov esi,eax invoke GetModuleFileName,NULL,addr buf1,255 invoke wsprintf,addr buf2,addr szfmt,addr buf1 ;如果不将文件路径加上双引号,则无在带有空格的路径名中正常运行. invoke lstrcat,addr buf2,addr var1 invoke lstrcmpi,addr buf2,esi jz startmain invoke OpenSCManager, NULL, NULL, SC_MANAGER_CREATE_SERVICE .if eax mov hSCManager, eax invoke OpenService, hSCManager, addr szsvrname , DELETE .if eax!0 mov hService, eax invoke DeleteService, hService invoke CloseServiceHandle,hService .endif invoke CreateService, hSCManager,addr szsvrname, addr szsvrname, / SERVICE_START SERVICE_QUERY_STATUS DELETE, / SERVICE_WIN32_OWN_PROCESS SERVICE_INTERACTIVE_PROCESS, SERVICE_DEMAND_START, / SERVICE_ERROR_IGNORE, addr buf2, NULL, NULL, NULL, NULL, NULL .if eax!0 mov hService, eax invoke StartService, hService, 0, NULL invoke DeleteService, hService invoke CloseServiceHandle, hService .endif invoke CloseServiceHandle, hSCManager .endif invoke ExitProcess,0 ;以服务的方式运行自身 startmain: invoke GetPidFromProcName ,addr procname invoke OpenProcess,PROCESS_ALL_ACCESS,NULL,eax mov hproc1,eax lea esi,mempatch invoke WritePMem,hproc1,0040bfb7h,esi,1 invoke WritePMem,hproc1,0040c02bh,esi,1 inc esi invoke WritePMem,hproc1,0040bfb4h,esi,3 invoke GetModuleHandle, addr szuserdll invoke GetProcAddress,eax,addr szMsgBox mov lpMsgfun,eax invoke VirtualAllocEx,hproc1,NULL,1024,MEM_COMMIT,PAGE_EXECUTE_READWRITE .if eax mov esi,eax invoke WritePMem,hproc1,esi,offset mycode,offset codeend - offset mycode invoke WritePMem,hproc1,esi,offset lpMsgfun ,4 mov edi,offset startcode - offset mycode add esi,edi mov funadd,esi mov esi,0040c029h invoke WritePMem,hproc1,esi,offset farcall,2 inc esi inc esi invoke WritePMem,hproc1,esi,offset funadd,4 add esi ,4 invoke WritePMem,hproc1,esi,offset farcall 2 ,2 .endif invoke MessageBox,NULL,addr szstr2,addr szstr1,MB_OK ;注意这句,笔者的用意可不是仅仅为了提示用户,而是必须要有这么个函数. invoke ExitProcess,0 Main endp end start; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;deep.asm;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 由于冰点是以服务的方式运行,进程具有SYSTEM 权限.要对它进行内存的读写与分配,须进行提权. 提权的方法有很多种,为了减小代码的篇幅,只好选最简单的提权方式: 以服务的方式运行自身,这样就可以很方便得到SYSTEM 权限. 唯一的缺憾就是另创进程,这在代码调试时,给 OD 带来不小的麻烦. 一次性密码的算法 G 继续运行冰点程序,程序又被中断.....,那是开始比较一次性密码. 具体调试方法与上面类似,这里就不再重复了,也可以把上面的代码稍加修改,用于解一次性密码. 解一次性密码较为理智的方法就是分析服务端的主程序,下面一次性密码的算法就是跟踪服务端程序得来的. 由于篇幅的原因,我只贴出算法,具体调试方法就不写了.因为分析一次性密码算法远远复杂于解客户端密码, 单单一次性密码的分析,就可以再写成一篇文章. 具体算法如下: ///OT.CPP #include stdio.h #include stdlib.h #include string.h #define UL unsigned long #define SI signed short int #define SL signed long UL pwd(UL a,UL b,UL c); SI hl(SI srt); UL cr(char str1[] ); void main(int argc, char* argv[]) { UL pwd1,pwd2,pwd3; char *cstcode new char[0x80]; char etystr[] {Igor Zagoruchenko} ; printf(/t/t One Time Password Generation System /n/n by figo /n/n); printf(/nPlease enter the customization code: /n); if(!(scanf(%s,cstcode))) return; printf(/nPlease enter OTP Token : /n); if(!(scanf(%8x,pwd1))) return; pwd2 cr(etystr); pwd3 cr(cstcode); pwd1 pwd(pwd1,pwd2,pwd3); printf(/n/nThe One Time Password is : /n/n); printf(%8X (Password valid for one use only)/n/n/n/n,pwd1); ltoa(pwd1,cstcode,16); pwd2 cr(cstcode); ltoa(pwd2,cstcode,16); cstcode strupr(cstcode ); printf(%4.4s-%8X (Password valid for multiple uses ) /n/n/n/n/n,cstcode,pwd1); delete cstcode; system(pause); } UL pwd(UL a,UL b,UL c) { SI s1,s2,s3; a ^ b; a ^ c; b a 0x10; b 0x10; c a 0x10; a b^c; s1 (SI)a; s2 (SI)b; s3 (SI)c; s1 hl (s1); s3 hl (s3); s3 ^ s2; a s1; a 0x10; a s3; return a; } SI hl(SI srt) { SL a,b,c; a srt; b a; a / 0xb1; b b%0xb1; c b * 0xab; a a; c - a; a c; b a; a 0x0f; a - b; srt (SI)a; return srt; } UL cr(char str1[] ) { int i 0 ,k 0; char c1; unsigned long rst 0,l1,l2; while (!(str1[i] 0)) { c1 str1[i]; if( (c1 A) (c1Z ) ) c1 | 0x20; else c1 c1; l1 c1; rst 4; l1 rst; rst l1; l1 0xf0000000; if(l1) { l2 l1 0x18; rst ^ l2; } l1 ~l1; rst l1; i; } return rst; } OT.CPP/// 上面代码是模拟冰点的一次性密码生成系统, 只是为了模拟演示算法,所以需要输入用户的自定义码. 直接在客户端解出一次性密码而不用用户自定义码的详细代码见附件(一定要安装冰点客户端才能解出一次性密码). 冰点的分析到此为止.文章的开始我们提到插件 IceExt 0.70.下面讲解 IceExt 0.70的妙用. 我们都知道 SOFTICE 无法象 OD 一样有强大的文本复制功能.但是写破文的时候用到的那些代码片段怎么办呢? 如果说是把它抄下来,然后再手动输入成文章,那这样的破文我是不会写的. IceExt 0.70 插件中有个转存屏幕的功能,但它保存的是RAW 格式的文件,而不是文本. 用十六进制编辑器打开IceExt 0.70 转存的文件,发现 RAW 格式其实很简单: 每个字符用2个字节保存: 第一个字节保存字符的值. 第二个字节保存字符的属性,低四位为前景色,高四位为背景色. 玩过十六位汇编的朋友,如果有尝试在显示缓冲区内写入彩色字的,应该对此不陌生吧! 再看一下文件的长度,刚好等于 WIDTH 的值 * LINES 的值 * 2 下面我就把提取RAW中字符的代码贴一下: ///duptxt.cpp// /*//2007.6.7 by figo (追风者) QQ: 382174647 仅用于学习交流,代码中有任何问题请联系我... 程序用法: duptxt.exe rawfilename [width] rawfilename 为IceExt Dump 出来的RAW 格式的文件. width 为SOFTICE 中 width 指令的设置值,默认为 80。 程序运行成功,会在 rawfilename 文件的目录下生成 rawfilename.txt 文件... //*/ #include stdio.h #include afx.h void main(int argc, char* argv[]) { CFile f1,f2; CString txtfn1; int width 80,lines, i,k; unsigned int cr0x0a0d; unsigned char tmp; if( argc 2) { printf(正确参数格式为:/n ); printf(%s rawfilename [width] /n,argv[0]); return; } else if(argc 2) { width atoi( argv[2] ); } if (!(f1.Open(argv[1],CFile::modeRead ))) { printf(%s 文件打开失败!/n,argv[1]); return; } txtfn1 argv[1]; txtfn1 .txt; if(!(f2.Open(txtfn1, CFile::modeWrite | CFile::modeCreate ))) { printf( %s 文件创建失败!/n,txtfn1); return ; } f1.SeekToBegin (); f2.SeekToBegin (); lines f1.GetLength (); lines / width * 2; for(k0 ;klines;k) { for(i 0 ; iwidth;i) { f1.Read (tmp,1); // if (tmp 0xc4) tmp -; else if((tmp 0x10)(tmp 0x20)) tmp 0x20; / f2.Write (tmp,1); f1.Seek (1,CFile::current); } f2.Write (cr,2); } f1.Close (); f2.Close (); } //duptxt.cpp/// 编译上面代码时,要注意在工程设置中选择 Use MFC in a Shared DLL . 代码使用的是MFC类,所以只要稍加修改,就可移植到 MFC程序中. 其实知道RAW 文件的格式,完全可以尝试自己编写一个,也相信你们会写的比我更好. --------------------------------------------------------------------------------【经验总结】 关于冰点: 冰点无解! 据网上介绍说此软件至今为找到破解方法. 其实这话不假,冰点的加密的确强悍.强壳,反加载,反调试,定时检测,以服务进程运行,能拦截IO...等技术 足以让众多的 Cracker 望而却步,纵然是 脱壳高手 静态分析高手,也很无奈. 因为无法加载它,它需要以服务的形式运行.并且会不断把窗体置前,以干扰调试. 采用多线程定时器保护,当某个线程检测到自己或另一个线程被暂停,就退出进程. 以上这些技术对付 OD 很是奏效,所以很有必要认识另一款功能强悍调试器 SOFTICE 一点补充: 其实冰点6.00.XXX.XXXX (企业版)的加密方法一样,只是版本的不同,使代码的偏移位置也不同. 所以解密器只针对与 6.00.220.1692 版,你也可以使用上面的跟踪方法来跟踪其它版的冰点. 找出偏移地址差,只要稍微修改一下代码,就能把解密器用于其它版本...... 文章的目的是为了学习调试方法和密码算法,所以不想花过多的时间去写一个通用与其他版本的解密器. 我也希望朋友们看这篇文章的时候的收获是学会用 SOFTICE 调试冰点,而不是得到冰点的解密器.... 在代码的注释中我提到: 密码算法的关键 CALL,就算跟进也无意义...... 在此我做一下解释: 因为就算知道冰点的密码算法你也很难做成注册机,它的并不难. 只是,冰点把密文数据压缩并写入文件, 你可能知道压缩后的位置,但却无法知道它解压后的数据地址或解压它 (应该不会去跟踪它是用哪一种压缩引擎压缩的吧? 万一发现那压缩引擎是自写的呢?). 知道算法能奈它何? 唉.............. 关于调试器: OllyDbg ,易用而功能强大的调试器,除了调试与系统底层相关的一些程序(比如 驱动,ROOTKITS,RING0 程序等) OD 几乎无所不能,其强大的代码智能分析功能是其它众多调试器所无法比拟的.不可否认OD 是最强用户级调试器. Cracker 们似乎渐渐忘掉曾经调试器中的王者 -- SOFTICE,《看雪论坛精华》中渐渐没了关于 SOFTICE 破解的文章. 但象冰点这种软件却只能用SOFTICE 来解,SOTFICE 是内核级调试器,中断时连系统时钟也一起停了. 可以不用担心定时器检测,所有线程都被挂起,操作系统也不例外,所以也不用担心窗口置前的干扰. SOFTICE 是即时呼出,冰点的反加载和调试器的捆绑失败,不是你所考虑的问题,你只要专心置好断点就行. 很难相信用 OD 可以解掉此类软件,笔者也尝试着OD 来解冰点,结果碰的一鼻子灰. 虽然随着虚拟计算机技术的不断成熟和计算机硬件的性能越来越好,价格却越来越便宜(笔者学计算机近五年了, 依然记得当初自己的 2500 比现在的 3800 贵 N 多,唉....,可怕的摩尔定律...) SOFTICE 很可能会被功能更为强大的双机内核调试器 WINDBG ,VISUAL SOFTICE 所替代. 但至少在今天,SOFTICE 的强大调试功能,灵活,稳定.都很值得我们花一些时间学它,并使用它. 文章到此结束,首先,谢谢你能看到这里. 当然,由于文章写的仓促错误在所难免. 对文章指正与建议是你对我作品最大的支持与肯定,谢谢你.............. --------------------------------------------------------------------------------【版权声明】: 本文原创于看雪技术论坛, 转载请注明作者与出处并保持文章的完整, 谢谢! 2007年06月12日 上午 09:36:06ps:一些与技术无关的话题关于冰点的破解其实不是偶然:很多天以前网上的一位朋友加了我QQ,他对我说: “我在看雪论坛上找你写的一篇老文章 ——《还原精灵密码算法分析》, 写的不错!......”.后来他又问我对冰点有没有研究?能不能解一下冰点?因为冰点还原类软件的新秀,在此之前我根本没用过冰点,甚至不知道如何安装冰点.但那时的我只看到“写的不错!”这些字眼(呵呵,好虚荣的我,总是喜欢把人家的客套话当回事,唉...).于是想都没想答应他: “最近忙,过两个礼拜帮你试试,好久没 CRACK 了,正好练练手...”破解冰点加写成文章花了我一个礼拜多的时间,真后悔当初好强,随便答应别人试试.不过这种事不会再有下次,不会再帮别人去专门破解某个软件了.因为我也是计算机初学者,并且非计算机专业的,也不兴趣于 CRACK ,更不会把 CRACK 当职业.CRACK 不过是我在学习编程和调试技术时,无心学会的技能,并不刻意学它.对我来说,学会分析和调试程序的最大用处是,可以参考别人的程序流程和纠正自己的代码.所以如果你也喜欢编程,喜欢 ROOTKIT ,喜欢研究系统底层....,那可能我们兴趣相似,我也很乐意与你相互学习或交流技术.但如果你加我QQ是为了破解某个软件,那么请另请高就吧!因为我的技术的确菜的要命,通常会让你失望的......因为解密的方法特殊,所以解密器只专用于 冰点6.00.220.1692 企业版.写文章的时候没有对它声明是我的疏忽,万用的冰点解密器我没兴趣编写(很浪费时间的!)不过文章中的解法却不受版本限制,希望能认真阅读... 再分享一下我老师大神的人工智能教程吧。零基础通俗易懂风趣幽默还带黄段子希望你也加入到我们人工智能的队伍中来https://blog.csdn.net/jiangjunshow