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, 得到返回值:
【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这个内核对象,而不是创建物理磁盘上的"文件",返回值存到中。
由于我的虚拟机只有两块本地磁盘,没有光驱,所以路径"E:\CD_CHECK.DAT"不存在,返回错误,此时=-1;循环7次后,路径"I:\CD_CHECK.DAT"仍是不存在的,返回错误,=-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个才行:
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处修改的内容做了无用功,又不好修改,干脆重载程序,恢复原始代码直接修改成正确的参数如下:
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函数查找特定的文件来起到保护作用,但因为作者不够认真,将参数写错,怎么都得不到正确的结果。
附件内含原CM程序、Nop爆破程序,修改过的patch程序、虚拟光盘文件1.iso等,百度链接是:http://pan.baidu.com/s/1skMkJY9,密码:86pm,160个CM、我已练习过的前27个crackme程序(不含012)都在里面。
谢谢楼主 像楼主学习 学习一下,谢谢 谢谢楼主的分享! 好好学习天天向上,我也是刚起步,刚进这个圈子,要更加努力:lol 感谢楼主分享 谢谢楼主分享!!! 把 0x0040136A push ebx
改成 push edx 就可以了。edx 正好会等于 3,是在 msvcrt.dll 中设置的,就是那个盘符 "c:\","d:\" 等的长度,刚刚好可以用上,我在 win 10 和 win98 中测试都可以用。 solly 发表于 2019-7-17 22:39
把 0x0040136A push ebx
改成 push edx 就可以了。edx 正好会等于 3,是在 msvcrt.dll 中设置的,就 ...
谢谢大神!又学了一些知识!不管怎么做,达到目的就行!
页:
[1]