看雪.WiFi万能钥匙 CTF 2017第十一题 点评及解题思路
发布日期:2025-01-04 10:41 点击次数:175
参赛题目Windows平台CrackMe题目答案75A29C09E180217C048420956C15DA309FF2B69170详细的题目设计1. 为程序写了一个简单的壳,对程序进行简单的异或加密(加了壳之后程序会报毒,水平有限暂时无法解决)。若对程序进行dump,会丢失藏在文件中但没有读入内存的DES解密函数,使序列号无法正常解密2. 使用自己实现LoadLibrary将kernel32导入到内存中,并使用自己实现的GetProcAddress通过已加密的函数名获取函数地址,隐藏api调用3. 程序入口处判断了是否处于调试状态,包括检查PEB的BeingDebugged、堆标志位和父进程名是否为explore.exe或cmd.exe1) 如果不为调试状态,则以调试方式打开程序本身,创建子进程2) 如果处于调试状态,则显示CrackMe对话框4. 通过SetUnhandledExceptionFilter设置了异常筛选器5. 当用户点击确定按钮时,会触发除0异常。如果本进程是通过父进程以调试模式打开,则该异常会被父进程捕获;否则,会被异常筛选器给捕获(正常情况不会来这里)6. 程序本身没有正常调用验证序列号的流程。当父进程捕捉到除0异常之后(程序第一次点击确认按钮时),会对错误的验证序列号的函数进行hook,从而跳转到正确的流程。7. 验证序列号流程程序中提供前96字节的DES解密算法明文(记为fuc1)。验证前会将pe文件中已的DES解密算法密文(记为fuc2)读入内存中。验证码的前10个字符组成4字节和1字节的两个秘钥,这两个秘钥对fuc2进行简单移位异或操作解密并与fuc1的前96字节比较,验证成功则继续。验证码的后32字符组成16字节密文,通过程序中提供的秘钥调用fuc1对密文进行解密,验证解密出的明文与程序中的明文进行比较,字符串相同则为提示成功。破解思路1. 对程序进行脱壳dump。可以通过修改自己加载的kernel32的地址为系统kernel32的地址,使用OD调试时即可观察到程序调用api情况2. 在WinMain中通过修改全局的调试状态标志位使得程序能够在调试状态下创建子进程(默认只能通过explore.exe和cmd.exe打开的进程才会创建子进程)3. 在处理调试事件的函数中下断点,找到程序的hook点和hook的内容,直接对程序对应位置修改机器码。此时还原了程序正确的流程,点击确认按钮就可以正常验证序列号4.
解密des函数的两个秘钥(共5个字节)可以通过穷举法获取,异或算法较为简单,很容易就能还原出来,通过解密密文和程序中的前96字节明文对比可以确认秘钥是否正确。需要注意的是,des函数需要在原文件中提取。这里获得的两个秘钥转为十六进制字符,得到序列号前10个字符。通过测试,对于i5-4210h
CPU单线程需要跑20分钟5. 识别出变形的des算法(在加密前和解密后需要对偶数位进行取反,即异或0x55),根据程序中提供的16位明文和秘钥进行加密,得到16位密文,对密文转为十六进制字符,得到序列号的后32个字符。此时组成的48位序列号即为最终答案下面选取攻击者 loudy 的破解分析使用工具:IDA6.8(反汇编分析) notepad(记录) vc6.0(解码) OD(调试)步 骤:一、代码自解密IDA载入看入口点和导入表,没有发现任何有用的东西,考虑该程序已经加密处理。二、识别真正流程继续OD动态跟踪,在此处发现DialogBoxParamW,有过MFC编程经验的朋友应该不陌生,说明我们已经找到关键点了(其实不然)。三、第一个关键算法实际调试时可以在4016AF处将JE用NOP代替,将401A43处修改为jmp 402303,即可绕过,直接调试主进程。另外,此题动态内存执行代码较多,建议关键位置下好“硬件执行”断点,便于调试。考虑对第9、10位的数字进行枚举,动态调试找到待解码和比较的数据,编写代码如下。