codelive 发表于 2014-5-8 17:34

360 CrackMe简单的分析

本帖最后由 codelive 于 2014-5-8 17:33 编辑

今天刚注册的吾爱,也是第一次发帧,先自我介绍一下吧,我是程序员一枚,从事编程15年了,擅长C++/C,没事也经常搞一些破解,但多数都是爆破,对反汇编后的算法研究很少,之前一直没在论坛里混过,感觉很孤独,许多时候在破解的很无助,现在终于加入大家庭了,希望在这里能得到大家的帮助,共同提高。

参加360这个破解大赛纯属是为了学习,起初以为应该很简单的,结果发现这个题目中涉及了非常多的技术和陷阱,能力有限,只进行了一些简单的分析,下面的文档已经提交给360了,不知道是否能得分,发此帖了算是记录一下吧.

<<360安全破解题CrackMe分析>> Adong-2014/04/24 ////////////////////////////////////////////////////////////////////////Name: 刘东发, 15工作经验的软件开发人员WeiBo: http://weibo.com/206069452,   @源带码//////////////////////////////////////////////////////////////////////// l首先进行了简单运行和测试,有以下发现: 1. 程序有加壳,原程序的区块进行压缩处理,用查找签名工具无法查出是何种程序开发语言或者是哪种已知的壳

2. 程序在运行时首先对程序数据解压缩,完全后会使用CreateProcess创建自己新的进程,新进程运行后,父进程退出。
3. 使用工具PETools对进程进行Dump,然后用ImportREC对IAT进行修复,虽然IAT修复成功,但程序运行会崩溃,初步判断程序运行后可能对部分程序数据进行了修改,虽然不能运行,但可以用IDA Pro工具进行静态分析。
4. 对Dump后的程序使用IDA Pro进行静态分析,发现有使用以下加解密API:CryptAcquireContextWCryptCreateHashCryptDecryptCryptDeriveKeyCryptDestroyHashCryptDestroyKeyCryptHashData
5. 在使用IDA Pro分析的字符串部分看到了 Cinflate 1.1.4 Copyright 1995-2002Mark Adler,表明程序可能是zlib压缩的。

l对程序进行调试分析:1.      使用OllyDbg Attach到运行的进程进行调试,程序有一些反跟踪/反调试处理,1)       频繁的SetTimer的调用,防止设置断点GetWindowTextW2)       有调用CreateThread创建一个线程,这个线程有可能是进行用户名和密码进行验证,但如果对线程函数部分进行调试,调试器会崩溃,可能是OD的问题,最终分析发现,这个线程就是Diasble/Enable “Register”按钮的,没其他作用.360:0040255A               push    0.360:0040255C               push    0.360:0040255E               push    edi.360:0040255F               push    offset sub_402050.360:00402564               push    0.360:00402566               push   0.360:00402568               call    CreateThread
.360:00402050 sub_402050      procnear               ; .360:00402050.360:00402050 arg_0         = dword ptr8.360:00402050.360:00402050               push    ebp.360:00402051               mov   ebp, esp.360:00402053               mov   ecx, .360:00402056               push    0               ; bEnable.360:00402058               push    3E8h            ; nIDDlgItem.360:0040205D               call    sub_417280.360:00402062               mov   ecx, eax.360:00402064               call    sub_417156.360:00402069            push    7D0h            ; dwMilliseconds.360:0040206E               call    Sleep.360:00402074               mov   ecx, .360:00402077               push    1               ; bEnable.360:00402079               push    3E8h            ; nIDDlgItem.360:0040207E               call    sub_417280.360:00402083               mov   ecx, eax.360:00402085               call    sub_417156.360:0040208A               xor   eax, eax.360:0040208C               pop   ebp.360:0040208D               retn    4.360:0040208D sub_402050      endp
3)       设置断点GetWindowTextW/GetDlgItemTextW获取用户输入函数后调试器还是崩溃(或许和调试器有关系,使用WinDbg没这个问题)4)       程序中使用了一些花指令防止静态分析5)       程序还做了欺骗,简单的改变CMP/JE指令,仍然是Failed,所以应该是在线程中进行的处理

6)       对是否被调试有检查,会调用 IsDebuggerPresent ,ZwQueryInformationProcess等API来Check,如果被Debug则计算错误7)       程序本身好像有些问题,比如第一次输入了username和password,计算出了一个结果,然后重新输入后不管是否正确就不在重新计算验证了。
2.      写了一个DLL,HOOK一些API函数,比如GetWindowTextW等,使用工具CFF 增加DLL导入,以便可以HOOK到进程的API调用
3.      在运行中发现,修改过的程序在计算的时候结果是不正确的,猜测可能是程序有检验,通过使用Procmon.exe监视程序访问的文件或者注册表发现, 程序会读取文件尾部4个字节的数据 35 F6 73 9C,这个数值一样是类似CRC32的一样计算结果 ,Procmon Log :ReadFile C:\test\360\360.exe      Offset: 780,362, Length: 4
4.      因为不能修改程序,要破解算法也复杂,所以使用动态注入DLL的方式,工具是我很久以前写的程序:


主要是HOOK几个API:
CryptAcquireContextW, CryptCreateHash, CryptDecrypt,CryptDeriveKey, CryptHashData




下图是用给的提示用户名:360和正确的密码输入,返回API HOOK的Log output:


解密的结果: 5375636365737300000000000000000000000000000000000000000000000000就是字符串: Success,HASH数据 6C696E67647578就是: lingdux,如果输入错误的密码,则不会调用到CryptDecrypt相关的函数,因此可能在此之前就有一个预先的判断。 5.      写了一个程序对API过程进行了模拟,大概代码是:// "lingdux"const BYTE password[] = { 0x6C, 0x69, 0x6E, 0x67,0x64, 0x75, 0x78 };CryptAcquireContextW(&hCryptProv, NULL,MS_ENHANCED_PROV_W, PROV_RSA_FULL, 0);CryptCreateHash(hCryptProv, CALG_MD5, 0, 0,&hHash);CryptHashData(hHash, (BYTE *)password,sizeof(password), 0);CryptDeriveKey(hCryptProv, CALG_3DES_112, hHash,KEYLENGTH, &hKey);
解密:CryptDecrypt(hKey, 0, bEOF, 0, pbBuffer, &dwCount);加密:CryptEncrypt(hKey, NULL, bEOF, 0, pbBuffer,&dwCount, dwBufferLen);
所以综上所述,只要用户名和密码变换后加密的数据是:1D55F56FED567B9533643A387D13D91FA80C08B173AF80820D5C5E91216546EBCB368D08EEA3691B,就是正确的。

6.      对username和password的变换分析:通过查看程序资源,可以得知username EditBox的ID是1001(3E9h),password的ID是1002(3EAh),所以可以很容易知道这个位置是获取输入的代码:
      其实到这里,就已经很容易做一个Patch程序来暴利破解了,当然如果要实现注册机,就必须知道程序的具体算法,还需要再进行分析,本人由于时间关系,目前就分析到这里了,不过自己确信最终一定能够分析出算法,等我有时间会再继续。          最后非常感谢360公司举办的大赛,这个CrackMe确实是一个非常不错的,融合了多种反调试/防破解技术,是一个很好的学习程序,在破解的同时自己的水平也有了提高。

codelive 发表于 2014-5-8 18:23

零度x 发表于 2014-5-8 18:16
前来膜拜注入dll输出log的大牛,LZ对微软提供的加密解密方法好熟悉啊。

DLLl注入/直接IAT导入可以使很多破解工作大大的简化,完全不用仔细的分析代码,能够快速的进行破解,但如果使用的是非标准的API就不容易了。

codelive 发表于 2014-5-8 17:53

Hmily 发表于 2014-5-8 17:40
codelive应该是专业开发人员,破解思路很独特,但这样有些细节可能看不到了。

确实如此,我的汇编功力还差很多,就怕分析算法,这方面需要努力加强。

star0angel 发表于 2014-5-8 17:38

膜拜大牛这就爆破了

Hmily 发表于 2014-5-8 17:40

codelive应该是专业开发人员,破解思路很独特,但这样有些细节可能看不到了。

manbajie 发表于 2014-5-8 17:42

来看看 学习一下

hongzhi214 发表于 2014-5-8 17:44

支持一下啊

Passerby 发表于 2014-5-8 17:46

需要学习,大牛的思路值得借鉴,欢迎大牛加入到吾爱。

codelive 发表于 2014-5-8 17:52

star0angel 发表于 2014-5-8 17:38
膜拜大牛这就爆破了

之后因为有事没有再继续分析,现在看了其他大牛的分析,我只是分析了一点皮毛而已,还差很远,惭愧。{:1_937:}

血染de枫彩 发表于 2014-5-8 18:07

感谢分享经验学习啦

supercomx 发表于 2014-5-8 18:11

膜拜一下大牛!
页: [1] 2 3 4
查看完整版本: 360 CrackMe简单的分析