160个Crackme之027学习笔记

本帖最后由 海天一色001 于 2019-6-19 17:45 编辑

第27个CM,打开一看,两个按钮,一个应该是检查电脑光驱,一个是退出。这涉及到对硬件的操作了。



点击“Check for CD”按钮,弹出错误提示框:



第一步、查壳



无壳,Microsoft Visual C++ 6.0编程。
第二步、爆破
OD载入027,先用中文搜索:



最下面有5行值得注意的字符串,“Try again”“You lost”是错误提示的标题及内容, “You did it”“Well done, Cracker”则应该是正确提示的标题及内容了。而“CD_CHECK.DAT”可能是记录有无CD的文件,可能是将信息写入这个文件中,检查这个文件来弹出提示框吧。
先不管那么多,先双击“Well done, Cracker”这一行进入CPU窗口:



向上查看,00401485处是上方跳转来的地方,顺着向上查看,
到0040138C处,将je 00401485改成jmp 00401485;然后向下的00401392处是来自00401352处的跳转,那么将00401352处nop掉,然后将修改后的内容保存为可执行文件Cosh.1_nop.exe,打开它,点击“Check for CD”按钮,弹出成功提示框,爆破成功。



第三步、追码
撤消爆破时的两处修改,向上仔细观察代码:
在错误揭示上方有几个跳转引起了我的关注:0040138C处已分析过了,是跳过失败,跳向成功的指令;



0040139C处是跳到0040133D处,形成了一个循环的跳转指令,再向上看00401346和00401349处是GetDriveTypeA函数及其参数,再向下到00401357处是程序内存中的“CD_CHECK.DAT”。



为了更好地分析代码,在0040139C处跳回的0040133D 上一句0040133A处下断,F9运行:在CM027中点击“Check for CD”按钮,中断于0040133A处,F8单步向下,运行到00401346处,注释中RootPathName = ""变成了RootPathName = "C:\";继续向下,调用系统函数GetDriveTypeA, [eax]得到返回值:
【GetDriveTypeA(RootPathName as string),返回值指定驱动器的类型,它可以是以下值之一:
DRIVE_UNKNOWN     = 0; {未知磁盘类型}
DRIVE_NO_ROOT_DIR = 1; {无效的根路径}
DRIVE_REMOVABLE   = 2; {可移动磁盘,如软盘}
DRIVE_FIXED       = 3; {本地硬盘}
DRIVE_REMOTE      = 4; {网络磁盘 远程驱动器}
DRIVE_CDROM       = 5; {光驱:CD-ROM}
DRIVE_RAMDISK     = 6; {RAM 磁盘 虚拟内存盘}
RootPathName的形式应该是“C:\”这样的,程序中应该是先将C:\至P:\都存入内存中,用到时再调用】
与0x3比较,如果是本地硬盘,则跳走,不是本地硬盘,则向下进行:
00401368到00401374处是CreateFileA函数及所需参数;从网上查了下CreateFileA函数,大致明白了函数的意义。(CreateFileA函数详解我已存了一份word文档,放入附件中了。)在Win32 API中有一系列操作内核对象的函数,创建内核对象的函数大多命名为CreateXxxx型,这里是创建File这个内核对象,而不是创建物理磁盘上的"文件",返回值存到[eax]中。
由于我的虚拟机只有两块本地磁盘,没有光驱,所以路径"E:\CD_CHECK.DAT"不存在,返回错误,此时[eax]=-1;循环7次后,路径"I:\CD_CHECK.DAT"仍是不存在的,返回错误,[eax]=-1;
继续向下就会来到错误揭示。
小结一下,跳过所有本地磁盘的盘符,在其他盘符的根目录下只要有CD_CHECK.DAT文件,就能够弹出成功提示了。
根据这个思路,应该用一个光驱或虚拟一个光驱,或者插入U盘,在其根目录下新建一个CD_CHECK.DAT,运行CM027,应该能弹出成功提示。试了一下,不成功!!!
哪里错了?再来看CreateFileA函数及所需参数:
函数声明HANDLE CreateFile(
LPCTSTR lpFileName, //普通文件名或者设备文件名
DWORD dwDesiredAccess, //访问模式(写/读)
DWORD dwShareMode, //共享模式
LPSECURITY_ATTRIBUTES lpSecurityAttributes, //指向安全属性的指针
DWORD dwCreationDisposition, //如何创建
DWORD dwFlagsAndAttributes, //文件属性
HANDLE hTemplateFile //用于复制文件句柄);
从OD中查看到的参数顺序正好和声明中相反,一个个对照下来,



FileName = "E:\CD_CHECK.DAT"、Access = GENERIC_READ、ShareMode = FILE_SHARE_READ、pSecurity = NULL这前四项都没问题,后两项Attributes = 0、hTemplateFile = NULL也没问题,只有第五项Mode = 0x0(dwCreationDisposition)错误!查得参数dwCreationDisposition的值是常数量,作用是指明当打开的对象存在或不存在的时候需如何处理。
这个参数必须是以下值其中之一:
CREATE_NEW            创建新文件/对象(当对象已经存在是将返回失败)。
   CREATE_ALWAYS         总是创建(如果对象存在就覆盖它,清除当前属性,把文件属性和dwFlagsAndAttributes指定的标志相结合)。
   OPEN_EXISTING          打开文件(如果不存在就返回失败)。
   OPEN_ALWAYS           存在就打开;若不存在,假如dwCreationDisposition==CREATE_NEW就创建一个新文件。
   TRUNCATE_EXISTING     存在就打开,且清空文件内容(至少要有GENERIC_WRITE权限);若文件不存在就返回失败。
没有“0”的存在。
为了防止出现自以为是的错误,我将mode=0x0这里的值分别进行修改为“1”至“5”,均不正确,仔细查看,原来是7个参数,修改后变成了6个参数,程序没崩溃就好了,肯定是不会正确的。



再想个歪招,在这里7个参数的位置处,我先跳转到其他地方,将参数凑齐,再跳回来,不就行了吗?这好象也是花指令的方式吧。试一试,不成功,那就再试!
将CPU窗口代码使劲向下翻,看到一大堆的“000000”,随意在地址00401D00处下个断点,返回00401368处,修改指令为“jmp 00401D00”,



在00401368这一行右键菜单上选择“跟随”命令,来到00401D00处:



CreateFileA函数有7个参数,在0040136E和00401373处有2个参数,那么在00401D00处需要加入5个才行:
[Asm] 纯文本查看 复制代码

00401D00      53            push ebx
00401D01      53            push ebx
00401D02      68 201D4000   push Cosh_1.00401D20
00401D07      53            push ebx
00401D08      6A 01         push 0x1
00401D0A    ^ E9 5FF6FFFF   jmp Cosh_1.0040136E

然后在00401D20一行上点击右键“数据窗口中跟随”—“选择”命令,



在数据窗口的ASCII列下从头开始选择13位,点击右键,二进制编辑:



输入“OPEN_EXISTING”字符,此时如下图所示:



将所有修改保存到可执行文件Cosh.1_patch.exe,试运行一下,还是错误!(此时先用winiso制作了一个光盘镜像并挂载到系统下,盘符为F:\,根目录下创建了一个0字节的CD_CHECK.DAT文件)
肯定是修改的有问题!在OD中给00401D00处下断,F9运行,点击“Check for CD”按钮,程序中断,然后F8向下运行,至00401374处,堆栈窗口显示如下情况,可以看出,参数Mode=0x401D20,而不是0x401D20处的内容。



那么在这里右键点击,选择“修改”命令,将401D20改成“1”看看:



此时参数Mode马上变成了CREATE_NEW ,我需要的参数是OPEN_EXISTING,说明这里要修改成“3”才对。



这样修改后发现在00401D20处修改的内容做了无用功,又不好修改,干脆重载程序,恢复原始代码直接修改成正确的参数如下:
[Asm] 纯文本查看 复制代码

00401368   . /E9 93090000   jmp Cosh_1_p.00401D00
0040136D     |90            nop
0040136E   > |68 00000080   push 0x80000000                                ; |Access = GENERIC_READ
00401373   . |50            push eax                                       ; |FileName = 00000001 ???
00401374   . |FF15 00204000 call dword ptr ds:[<&KERNEL32.CreateFileA>]    ; \CreateFileA

00401D00   > \53            push ebx
00401D01   .  53            push ebx
00401D02   .  6A 03         push 0x3
00401D04   .  53            push ebx
00401D05   .  6A 01         push 0x1
00401D07   .^ E9 62F6FFFF   jmp Cosh_1_p.0040136E

再保存成Cosh.1_patch1.exe,试运行一次,成功了!



这个程序其实很简单,利用CreateFileA函数查找特定的文件来起到保护作用,但因为作者不够认真,将参数写错,怎么都得不到正确的结果。
附件

027.zip

(185.97 KB, 下载次数: 0)

2019-6-19 17:43 上传
点击文件名下载附件

下载积分: 吾爱币 -1 CB

内含原CM程序、Nop爆破程序,修改过的patch程序、虚拟光盘文件1.iso等,百度链接是:http://pan.baidu.com/s/1skMkJY9,密码:86pm,160个CM、我已练习过的前27个crackme程序(不含012)都在里面。

THE END
喜欢就支持以下吧
点赞0
分享
评论 抢沙发
  • 管埋员的头像-小北的自留地

    昵称

  • 取消
    昵称