【破文标题】我的第一次暴破
【破文作者】nohacks(非安全)
【破解平台】winXP + SP2
【作者邮箱】kker.cn04@163.com
【软件名称】CodeFantasy系列CrackMe2
【软件大小】48.5 KB
【下载地址】www.nohack.cn
【破解工具】PEiD0.94、OD1.0
【保护方式】序列号
【软件限制】CrackMe
【破解目的】学习破解。
【破解声明】我乃小菜鸟一只,偶得一点心得,愿与大家分享:)
内容:
用PEID0.94查壳――无壳且随便输入用户名和注册码没有任何失败提示!
看来根据提示找关键跳转的方法行不通,好,那么我来看它的API调用,看有没有我们需要的
用OD载入直接CTRL+N,部分结果如下:
名称位于 CrackMe2
地址 区段 类型 ( 名称 注释
......
0040C1B8 .idata 导入 ( kernel32.GetACP
0040C240 .idata 导入 ( user32.GetClientRect
0040C118 .idata 导入 ( kernel32.GetCommandLineA
0040C1B4 .idata 导入 ( kernel32.GetCPInfo
0040C0EC .idata 导入 ( kernel32.GetCurrentThreadId
0040C1B0 .idata 导入 ( kernel32.GetDiskFreeSpaceA
0040C23C .idata 导入 ( user32.GetDlgItem
0040C238 .idata 导入 ( user32.GetDlgItemTextA ;就是这里,取控件文本的API
0040C144 .idata 导入 ( user32.GetKeyboardType
0040C114 .idata 导入 ( kernel32.GetLocaleInfoA
0040C1AC .idata 导入 ( kernel32.GetLocaleInfoA
0040C110 .idata 导入 ( kernel32.GetModuleFileNameA
0040C1A8 .idata 导入 ( kernel32.GetModuleFileNameA
0040C10C .idata 导入 ( kernel32.GetModuleHandleA
0040C17C .idata 导入 ( kernel32.GetModuleHandleA
0040C1A4 .idata 导入 ( kernel32.GetModuleHandleA
0040C108 .idata 导入 ( kernel32.GetProcAddress
0040C1A0 .idata 导入 ( kernel32.GetProcAddress
0040C104 .idata 导入 ( kernel32.GetStartupInfoA
0040C13C .idata 导入 ( kernel32.GetStdHandle
0040C19C .idata 导入 ( kernel32.GetStdHandle
0040C198 .idata 导入 ( kernel32.GetStringTypeExA
0040C234 .idata 导入 ( user32.GetSystemMetrics
0040C100 .idata 导入 ( kernel32.GetThreadLocale
0040C194 .idata 导入 ( kernel32.GetThreadLocale
0040C0E8 .idata 导入 kernel32.GetVersion
0040C190 .idata 导入 ( kernel32.GetVersionExA
0040C230 .idata 导入 ( user32.GetWindowRect
0040C22C .idata 导入 ( user32.GetWindowTextA
.....
看到没有,有调有GetDlgItemTextA这个取对话框文本的API,一般用来取回客户输入,我们就用它
来下断:
Command :BPX GetDlgItemTextA
F9,运行程序,输入用户名:nohacks,注册码:5201314
点击注册,啪的一声断在这里:
00408D8C |> \68 FF000000 push 0FF ; /Count = FF (255.); Case 3EA of switch 00408D6B
00408D91 |. 68 A0A24000 push CrackMe2.0040A2A0 ; |Buffer = CrackMe2.0040A2A0
00408D96 |. 68 F2030000 push 3F2 ; |ControlID = 3F2 (1010.)
00408D9B |. 8B45 08 mov eax,dword ptr ss:[ebp+8] ; |
00408D9E |. 50 push eax ; |hWnd
00408D9F |. E8 90B9FFFF call <jmp.&user32.GetDlgItemTextA> ; \GetDlgItemTextA
00408DA4 |. 8D45 B4 lea eax,dword ptr ss:[ebp-4C]
00408DA7 |. BA A0A24000 mov edx,CrackMe2.0040A2A0
00408DAC |. B9 FF000000 mov ecx,0FF
00408DB1 |. E8 BAAAFFFF call CrackMe2.00403870
00408DB6 |. 837D B4 00 cmp dword ptr ss:[ebp-4C],0
00408DBA |. 0F84 9E000000 je CrackMe2.00408E5E
00408DC0 |. 68 FF000000 push 0FF ; /Count = FF (255.)
00408DC5 |. 68 A0A34000 push CrackMe2.0040A3A0 ; |Buffer = CrackMe2.0040A3A0
00408DCA |. 68 F3030000 push 3F3 ; |ControlID = 3F3 (1011.)
00408DCF |. 8B45 08 mov eax,dword ptr ss:[ebp+8] ; |
00408DD2 |. 50 push eax ; |hWnd
00408DD3 |. E8 5CB9FFFF call <jmp.&user32.GetDlgItemTextA> ; \GetDlgItemTextA
00408DD8 |. 8D45 AC lea eax,dword ptr ss:[ebp-54]
00408DDB |. BA A0A24000 mov edx,CrackMe2.0040A2A0
00408DE0 |. B9 FF000000 mov ecx,0FF
00408DE5 |. E8 86AAFFFF call CrackMe2.00403870
00408DEA |. 8B45 AC mov eax,dword ptr ss:[ebp-54]
00408DED |. 8D55 B0 lea edx,dword ptr ss:[ebp-50]
00408DF0 |. E8 BFFCFFFF call CrackMe2.00408AB4
00408DF5 |. 8B45 B0 mov eax,dword ptr ss:[ebp-50]
00408DF8 |. 50 push eax
00408DF9 |. 8D45 A8 lea eax,dword ptr ss:[ebp-58]
00408DFC |. BA A0A34000 mov edx,CrackMe2.0040A3A0
00408E01 |. B9 FF000000 mov ecx,0FF
00408E06 |. E8 65AAFFFF call CrackMe2.00403870
00408E0B |. 8B55 A8 mov edx,dword ptr ss:[ebp-58]
00408E0E |. 58 pop eax
00408E0F |. E8 60ABFFFF call CrackMe2.00403974
00408E14 |. 75 48 jnz short CrackMe2.00408E5E ;★★关键跳,从这里跳向死亡
00408E16 |. 6A 40 push 40 ; /Style = MB_OK|MB_ICONASTERISK|MB_APPLMODAL
00408E18 |. 68 5C8F4000 push CrackMe2.00408F5C ; |Title = "注册提示"
00408E1D |. 68 688F4000 push CrackMe2.00408F68 ; |Text = "恭喜您,注册码正确!"
00408E22 |. 8B45 08 mov eax,dword ptr ss:[ebp+8] ; |
00408E25 |. 50 push eax ; |hOwner
00408E26 |. E8 41B9FFFF call <jmp.&user32.MessageBoxA> ; \MessageBoxA
看到没有,"注册提示"前有个跳转,00408E14处的这个跳转就是关键跳转了,如果跳走就去死
不跳则成功,暴破很简单,把jnz改为jz就OK了,还想追出真码?继续:
我在关键跳里下断看看,如果是明文比较,应该会留下痕迹的,在00408E14处按F2下断,接着F9继续运行
再次断下,看看OD右下角的注释栏,看到了什么?反正我的是这样:
0012FA74 0012FB64 指针到下一个 SEH 记录
0012FA78 00408F14 SE 句柄
0012FA7C 0012FADC
0012FA80 00000000
0012FA84 00D0099C ASCII "5201314"
0012FA88 00D00948 ASCII "nohacks"
0012FA8C 00D00984 ASCII "PpqiPbdmJu."
0012FA90 00D00934 ASCII "nohacks"
很明显了,真码就是: PpqiPbdmJu.
输入试试,成功了!
破解总结:
暴破:
把00408E14处的jnz改为jz就OK了
KEY:
用户名:nohacks
注册码:PpqiPbdmJu.
注册机:
我乃小菜鸟一只,希望高手指教!
附:破解常用断点设置
软件破解的主要工具是softice,如何在softice中设置好断点对于破解的成功是非常重要的,下
面列举了 一些常用的断点设置,这些断点同样适合于Trw2000,两者基本上是兼容的
bpx hmemcpy 破解万能断点,拦截内存拷贝动作
bpx Lockmytask 当你用其它断点都无效时可以试一下,这个断点拦截按键的动作
实在找不到断点可以试下面的方法:
bmsg handle wm_gettext 拦截注册码(handle为对应窗口的句柄)
bmsg handle wm_command 拦截OK按钮(handle为对应窗口的句柄)
拦截窗口:
bpx CreateWindow 创建窗口
bpx CreateWindowEx(A) 创建窗口
bpx ShowWindow 显示窗口
bpx UpdateWindow 更新窗口
bpx GetWindowText(A) 获取窗口文本
拦截消息框:
bpx MessageBox(A) 创建消息框
bpx MessageBoxExA 创建消息框
bpx MessageBoxIndirect(A) 创建定制消息框
拦截警告声:
bpx MessageBeep 发出系统警告声(如果没有声卡就直接驱动系统喇叭发声)
拦截对话框:
bpx DialogBox 创建模态对话框
bpx DialogBoxParam(A) 创建模态对话框
bpx DialogBoxIndirect 创建模态对话框
bpx DialogBoxIndirectParam(A) 创建模态对话框
bpx CreateDialog 创建非模态对话框
bpx CreateDialogParam(A) 创建非模态对话框
bpx CreateDialogIndirect 创建非模态对话框
bpx CreateDialogIndirectParam(A) 创建非模态对话框
bpx GetDlgItemText(A) 获取对话框文本
bpx GetDlgItemInt 获取对话框整数值
拦截剪贴板:
bpx GetClipboardData 获取剪贴板数据
拦截注册表:
bpx RegOpenKey(A) 打开子健 ( 例:bpx RegOpenKey(A) if *(esp+8)=='****' )
bpx RegOpenKeyEx 打开子健 ( 例:bpx RegOpenKeyEx if *(esp+8)=='****' )
bpx RegQueryValue(A) 查找子健 ( 例:bpx RegQueryValue(A) if *(esp+8)=='****' )
bpx RegQueryValueEx 查找子健 ( 例:bpx RegQueryValueEx if *(esp+8)=='****' )
bpx RegSetValue(A) 设置子健 ( 例:bpx RegSetValue(A) if *(esp+8)=='****' )
bpx RegSetValueEx(A) 设置子健 ( 例:bpx RegSetValueEx(A) if *(esp+8)=='****' )
“****”为指定子键名的前4个字符,如子键为“Regcode”,则“****”= “Regc”
功能限制拦截断点:
bpx EnableMenuItem 禁止或允许菜单项
bpx EnableWindow 禁止或允许窗口
bmsg hMenu wm_command 拦截菜单按键事件,其中hMenu为菜单句柄
bpx K32Thk1632Prolog 配合bmsg hMenu wm_command使用,可以通过这个断点进入菜单处理程序
应用示例:
CALL [KERNEL32!K32Thk1632Prolog]
CALL [......] <-- 由此跟踪进入菜单处理程序
CALL [KERNEL32!K32Thk1632Epilog]
拦截时间:
bpx GetLocalTime 获取本地时间
bpx GetSystemTime 获取系统时间
bpx GetFileTime 获取文件时间
bpx GetTickCount 获得自系统成功启动以来所经历的毫秒数
bpx GetCurrentTime 获取当前时间(16位)
bpx SetTimer 创建定时器
bpx TimerProc 定时器超时回调函数
拦截文件:
bpx CreateFileA 创建或打开文件 (32位)
bpx OpenFile 打开文件 (32位)
bpx ReadFile 读文件 (32位)
bpx WriteFile 写文件 (32位)
bpx _lcreat 创建或打开文件 (16位)
bpx _lopen 打开文件 (16位)
bpx _lread 读文件 (16位)
bpx _lwrite 写文件 (16位)
bpx _hread 读文件 (16位)
bpx _hwrite 写文件 (16位)
拦截驱动器:
bpx GetDrivetype(A) 获取磁盘驱动器类型
bpx GetLogicalDrives 获取逻辑驱动器符号
bpx GetLogicalDriveStringsA 获取当前所有逻辑驱动器的根驱动器路径
拦截狗:
bpio -h 378(或278、3BC) R 378、278、3BC是并行打印端口
bpio -h 3F8(或2F8、3E8、2E8) R 3F8、2F8、3E8、2E8是串行端口
VB程序专用断点:
bpx msvbvm50!__vbaStrCmp 比较字符串是否相等
bpx msvbvm50!__vbaStrComp 比较字符串是否相等
bpx msvbvm50!__vbaVarTstNe 比较变量是否不相等
bpx msvbvm50!__vbaVarTstEq 比较变量是否相等
bpx msvbvm50!__vbaStrCopy 复制字符串
bpx msvbvm50!__vbaStrMove 移动字符串
bpx MultiByteToWideChar ANSI字符串转换成Unicode字符串
bpx WideCharToMultiByte Unicode字符串转换成ANSI字符串
上面的断点对应VB5程序,如果是VB6程序则将msvbvm50改成msvbvm60即可
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!