大牛飘过,写得不好,多多包涵...
第一次发破文,等到写完了才发现我所总结的两点早已被 liuqiangni 给写了,汗,
相当的雷同啊,但愿liuqiangni不会认为我是抄的...最郁闷的是最后上网一搜索,
发现这个软件的破文已经相当多了...无论怎么样还是发了上来,毕竟是第一次写
的,作个纪念吧...
软件介绍:
xxQQ mima记录器无需后台监控进程即可监控,启动监控后您甚至可以删除本
软件,需要查看mima时,运行本软件即可!
1.监控孩子的QQ mima,方便家长管理子女,防止子女在网络里失足
2.记录女朋友、男朋友或配偶的QQ mima
3.记录在本机登录的其他QQ mima
破解步骤:
1:查壳,脱壳
使用peid查壳为NsPack 1.4 -> Liuxingping *,北斗的壳,esp定律可轻松脱掉,
在此就不详细说明了.
2.破解
运行脱壳后的文件,发现一会儿程序就退出并自动关机了,很明显,程序有校验.那
咱们就先去校验吧.OD载入程序,查找一下字符串,看能否得到一些有用的信息.果不其
然,有很多关于注册的信息,这里暂时先不管,接着往下看,我们看到一个
叫” seshutdownprivilege”的字符串,这里应该就是关机的关键所在了,双击进去,来
到这里:
00470D00 /$ 81EC A8000000 sub esp,0xA8
00470D06 |. 57 push edi
00470D07 |. B9 25000000 mov ecx,0x25
00470D0C |. 33C0 xor eax,eax
00470D0E |. 8D7C24 18 lea edi,dword ptr ss:[esp+0x18]
00470D12 |. F3:AB rep stos dword ptr es:[edi]
00470D14 |. 8D4424 18 lea eax,dword ptr ss:[esp+0x18]
00470D18 |. C74424 18 940>mov dword ptr ss:[esp+0x18],0x94
00470D20 |. 50 push eax ; /pVersionInformation
00470D21 |. FF15 58534A00 call dword ptr ds:[<&kernel32.GetVersion>; \GetVersionExA
00470D27 |. 8B4424 28 mov eax,dword ptr ss:[esp+0x28]
00470D2B |. 5F pop edi
00470D2C |. 83F8 02 cmp eax,0x2
00470D2F |. 75 6C jnz short dumped_.00470D9D
00470D31 |. 8D4C24 00 lea ecx,dword ptr ss:[esp]
00470D35 |. 51 push ecx ; /phToken
00470D36 |. 6A 28 push 0x28 ; |DesiredAccess = TOKEN_QUERY|TOKEN_ADJUST_PRIVILEGES
00470D38 |. FF15 B8514A00 call dword ptr ds:[<&kernel32.GetCurrent>; |[GetCurrentProcess
00470D3E |. 50 push eax ; |hProcess
00470D3F |. FF15 04504A00 call dword ptr ds:[<&advapi32.OpenProces>; \OpenProcessToken
00470D45 |. 85C0 test eax,eax
00470D47 |. 75 07 jnz short dumped_.00470D50
00470D49 |. 81C4 A8000000 add esp,0xA8
00470D4F |. C3 retn
00470D50 |> 8D5424 08 lea edx,dword ptr ss:[esp+0x8]
00470D54 |. 52 push edx ; /pLocalId
00470D55 |. 68 00E25100 push dumped_.0051E200 ; |seshutdownprivilege
00470D5A |. 6A 00 push 0x0 ; |SystemName = NULL
00470D5C |. FF15 08504A00 call dword ptr ds:[<&advapi32.LookupPriv>; \LookupPrivilegeValueA
00470D62 |. 8B4C24 00 mov ecx,dword ptr ss:[esp]
00470D66 |. 6A 00 push 0x0 ; /pRetLen = NULL
00470D68 |. 6A 00 push 0x0 ; |pPrevState = NULL
00470D6A |. 8D4424 0C lea eax,dword ptr ss:[esp+0xC] ; |
00470D6E |. 6A 00 push 0x0 ; |PrevStateSize = 0
00470D70 |. 50 push eax ; |pNewState
00470D71 |. 6A 00 push 0x0 ; |DisableAllPrivileges = FALSE
00470D73 |. 51 push ecx ; |hToken
00470D74 |. C74424 1C 010>mov dword ptr ss:[esp+0x1C],0x1 ; |
00470D7C |. C74424 28 020>mov dword ptr ss:[esp+0x28],0x2 ; |
00470D84 |. FF15 0C504A00 call dword ptr ds:[<&advapi32.AdjustToke>; \AdjustTokenPrivileges
00470D8A |. FF15 EC524A00 call dword ptr ds:[<&kernel32.GetLastErr>; [GetLastError
00470D90 |. 85C0 test eax,eax
00470D92 |. 74 09 je short dumped_.00470D9D
00470D94 |. 33C0 xor eax,eax
00470D96 |. 81C4 A8000000 add esp,0xA8
00470D9C |. C3 retn
00470D9D |> B8 01000000 mov eax,0x1
00470DA2 |. 81C4 A8000000 add esp,0xA8
00470DA8 \. C3 retn
发现本地调用来自 00470C47.跟进去
00470C10 . 8B4424 0C mov eax,dword ptr ss:[esp+0xC]
00470C14 . 81EC 94000000 sub esp,0x94
00470C1A . 8B48 14 mov ecx,dword ptr ds:[eax+0x14]
00470C1D . 53 push ebx
00470C1E . 56 push esi
00470C1F . 8B30 mov esi,dword ptr ds:[eax]
00470C21 . 85C9 test ecx,ecx
00470C23 . 74 0E je short dumped_.00470C33
00470C25 . 8B48 0C mov ecx,dword ptr ds:[eax+0xC]
00470C28 . 85C9 test ecx,ecx
00470C2A . 74 07 je short dumped_.00470C33
00470C2C . BB 01000000 mov ebx,0x1
00470C31 . EB 02 jmp short dumped_.00470C35
00470C33 > 33DB xor ebx,ebx
00470C35 > 83FE 01 cmp esi,0x1
00470C38 . 0F8C A2000000 jl dumped_.00470CE0 //这里可以跳到此过程结尾处
00470C3E . 83FE 05 cmp esi,0x5
00470C41 0F8F 99000000 jg dumped_.00470CE0 //这里也可以跳到此过程结尾处
00470C47 E8 B4000000 call dumped_.00470D00 //上面的子过程就是这个Call调用的
00470C4C . 85C0 test eax,eax
00470C4E . 0F84 8C000000 je dumped_.00470CE0
00470C54 . 83FE 04 cmp esi,0x4
00470C57 . 7C 21 jl short dumped_.00470C7A
00470C59 . 33C0 xor eax,eax
00470C5B . 83FE 04 cmp esi,0x4
00470C5E . 0F94C0 sete al
00470C61 . 53 push ebx
00470C62 . 50 push eax
00470C63 . E8 08720000 call <jmp.&kernel32.SetSystemPowerState>
00470C68 . 8B8C24 A00000>mov ecx,dword ptr ss:[esp+0xA0]
00470C6F . 5E pop esi
00470C70 . 5B pop ebx
00470C71 . 8901 mov dword ptr ds:[ecx],eax
00470C73 . 81C4 94000000 add esp,0x94
00470C79 . C3 retn
00470C7A > 83FE 01 cmp esi,0x1
00470C7D . 75 34 jnz short dumped_.00470CB3
00470C7F . 57 push edi
00470C80 . B9 25000000 mov ecx,0x25
00470C85 . 33C0 xor eax,eax
00470C87 . 8D7C24 0C lea edi,dword ptr ss:[esp+0xC]
00470C8B . 8D5424 0C lea edx,dword ptr ss:[esp+0xC]
00470C8F . F3:AB rep stos dword ptr es:[edi]
00470C91 . 52 push edx ; /pVersionInformation
00470C92 . C74424 10 940>mov dword ptr ss:[esp+0x10],0x94 ; |
00470C9A . FF15 58534A00 call dword ptr ds:[<&kernel32.GetVersionExA>; \GetVersionExA
00470CA0 . 8B4424 1C mov eax,dword ptr ss:[esp+0x1C]
00470CA4 . 5F pop edi
00470CA5 . 83E8 02 sub eax,0x2
00470CA8 . F7D8 neg eax
00470CAA . 1BC0 sbb eax,eax
00470CAC . 24 F9 and al,0xF9
00470CAE . 83C0 08 add eax,0x8
00470CB1 . EB 0C jmp short dumped_.00470CBF
00470CB3 > 33C0 xor eax,eax
00470CB5 . 83FE 02 cmp esi,0x2
00470CB8 . 0F95C0 setne al
00470CBB . 48 dec eax
00470CBC . 83E0 02 and eax,0x2
00470CBF > 85DB test ebx,ebx
00470CC1 . 74 02 je short dumped_.00470CC5
00470CC3 . 0C 04 or al,0x4
00470CC5 > 6A 00 push 0x0 ; /Reserved = 0
00470CC7 . 50 push eax ; |Options
00470CC8 . FF15 68544A00 call dword ptr ds:[<&user32.ExitWindowsEx>] ; \ExitWindowsEx
00470CCE . 8B8C24 A00000>mov ecx,dword ptr ss:[esp+0xA0]
00470CD5 . 5E pop esi
00470CD6 . 5B pop ebx
00470CD7 . 8901 mov dword ptr ds:[ecx],eax
00470CD9 . 81C4 94000000 add esp,0x94
00470CDF . C3 retn
00470CE0 > 8B9424 A00000>mov edx,dword ptr ss:[esp+0xA0]
00470CE7 . 5E pop esi
00470CE8 . 5B pop ebx
00470CE9 . C702 00000000 mov dword ptr ds:[edx],0x0
00470CEF . 81C4 94000000 add esp,0x94
00470CF5 . C3 retn
发现上面00470C38和00470C41处均可跳到此过程的结尾处,也就是可以跳过关机,随便
找一处改成jmp保存出来.运行结果证明我们找对了地方.现在我们就可以安心的调试了.
咱们继续看和注册相关的字符串,由于这个有太多的地方都有关键信息,我就不再一一
列出了,我们看了几处,很容易就发现了一个很明显的特点,比如下面这一处:
0040140B |. 6A FF push -0x1
0040140D |. 6A 08 push 0x8
0040140F |. 68 C0620116 push 0x160162C0
00401414 |. 68 01000152 push 0x52010001
00401419 |. E8 01590100 call dumped_.00416D1F
0040141E |. 83C4 18 add esp,0x18
00401421 |. 833D 288B5200>cmp dword ptr ds:[0x528B28],0x0
00401428 |. 0F85 22000000 jnz dumped_.00401450
0040142E |. 6A 00 push 0x0
00401430 |. 68 7E944A00 push dumped_.004A947E ; 试用版只显示QQ密码的前三位 注册后即可显示完整的QQ密码
00401435 |. 6A FF push -0x1
00401437 |. 6A 08 push 0x8
00401439 |. 68 9F5A0116 push 0x16015A9F
0040143E |. 68 01000152 push 0x52010001
00401443 |. E8 D7580100 call dumped_.00416D1F
00401448 |. 83C4 18 add esp,0x18
0040144B |. E9 1D000000 jmp dumped_.0040146D
00401450 |> 6A 00 push 0x0
00401452 |. 68 B4944A00 push dumped_.004A94B4 ; 感谢您注册本软件,现在您可以使用本软件的全部功能!
00401457 |. 6A FF push -0x1
00401459 |. 6A 08 push 0x8
0040145B |. 68 9F5A0116 push 0x16015A9F
00401460 |. 68 01000152 push 0x52010001
00401465 |. E8 B5580100 call dumped_.00416D1F
0040146A |. 83C4 18 add esp,0x18
以及下面这一处:
00406CE0 /. 55 push ebp
00406CE1 |. 8BEC mov ebp,esp
00406CE3 |. 81EC 04000000 sub esp,0x4
00406CE9 |. 833D 288B5200>cmp dword ptr ds:[0x528B28],0x1
00406CF0 |. 0F85 35000000 jnz dumped_.00406D2B
00406CF6 |. 6A 00 push 0x0
00406CF8 |. 6A 00 push 0x0
00406CFA |. 6A 00 push 0x0
00406CFC |. 68 01030080 push 0x80000301
00406D01 |. 6A 00 push 0x0
00406D03 |. 68 00000000 push 0x0
00406D08 |. 68 04000080 push 0x80000004
00406D0D |. 6A 00 push 0x0
00406D0F |. 68 60994A00 push dumped_.004A9960 ; 您已成功注册本软件,无须再次注册!
00406D14 |. 68 03000000 push 0x3
00406D19 |. BB 00934100 mov ebx,dumped_.00419300
00406D1E |. E8 F0FF0000 call dumped_.00416D13
00406D23 |. 83C4 28 add esp,0x28
看出来了么?都是这样一个结构:
cmp dword ptr ds:[0x528B28],0x1
关键跳转
注册或未注册
咱们再看一下这个cmp指令,是0x528B28这个地址的值与1比较,如果相等就跳,0x528B28
是一个静态的地址,写过程序的朋友应该猜到了,这里放的应该就是一个全局变量了.也就是
说这个程序大概是这样的,程序启动的时候验证是否已经注册,注册了的话就给这个全局变
成赋值为1(True),然后以后每次只根据这个全局变量来判断是否注册而可以使用相关的功能,
由此,我们就想到,如果我把这个地址的值改了1,那程序不就是已注册了吗?
下面就来验证我们这个想法,OD重载一下程序,把0x528B28处的值改成1,并在这里下内存
访问断点,然后我们运行程序,发现确实如我们所猜想的一样,所有的功能都可以使用了,点注
册按钮也提示已经注册.
咱们用一下各个功能,发现这个地址的值是一直都没有改变的,也就是说我们可以通过改
这个地址的值的方式来达到破解的目的,当然并不是所有的程序都是这样的.只是今天我们刚
好捡了个软柿子而已,大家具体情况具体分析.
保存我们改了0x528B28处值的程序,运行发现会提示使用的是破解软件,于是根据字符串
找到下的关键:
00405029 |. 83C4 10 |add esp,0x10
0040502C |. 33C9 |xor ecx,ecx
0040502E |> 41 |/inc ecx
0040502F |. 51 ||push ecx
00405030 |. 50 ||push eax
00405031 |. 3BC8 ||cmp ecx,eax
00405033 |. 0F8F E1000000 ||jg dumped_.0040511A //这个跳转可以跳过去
00405039 |. 68 04000400 ||push 0x40004
0040503E |. 68 785A0116 ||push 0x16015A78
00405043 |. 68 01000152 ||push 0x52010001
00405048 |. 68 01000000 ||push 0x1
0040504D |. B8 03000000 ||mov eax,0x3
00405052 |. BB 00BF4600 ||mov ebx,dumped_.0046BF00
00405057 |. E8 CF1C0100 ||call dumped_.00416D2B
0040505C |. 83C4 10 ||add esp,0x10
0040505F |. 6A 00 ||push 0x0
00405061 |. 6A 00 ||push 0x0
00405063 |. 6A 00 ||push 0x0
00405065 |. 68 01000000 ||push 0x1
0040506A |. BB 90714100 ||mov ebx,dumped_.00417190
0040506F |. E8 9F1C0100 ||call dumped_.00416D13
00405074 |. 83C4 10 ||add esp,0x10
00405077 |. 8B1D 388B5200 ||mov ebx,dword ptr ds:[0x528B38]
0040507D |. 895D F0 ||mov [local.4],ebx
00405080 |. 68 01030080 ||push 0x80000301
00405085 |. 6A 00 ||push 0x0
00405087 |. 68 80841E00 ||push 0x1E8480
0040508C |. 68 01030080 ||push 0x80000301
00405091 |. 6A 00 ||push 0x0
00405093 |. 68 10270000 ||push 0x2710
00405098 |. 68 02000000 ||push 0x2
0040509D |. BB A0734100 ||mov ebx,dumped_.004173A0
004050A2 |. E8 6C1C0100 ||call dumped_.00416D13
004050A7 |. 83C4 1C ||add esp,0x1C
004050AA |. 68 01030080 ||push 0x80000301
004050AF |. 6A 00 ||push 0x0
004050B1 |. 50 ||push eax
004050B2 |. 68 01000000 ||push 0x1
004050B7 |. BB E0834100 ||mov ebx,dumped_.004183E0
004050BC |. E8 521C0100 ||call dumped_.00416D13
004050C1 |. 83C4 10 ||add esp,0x10
004050C4 |. 8945 E8 ||mov [local.6],eax
004050C7 |. 8B45 E8 ||mov eax,[local.6]
004050CA |. 50 ||push eax
004050CB |. 8B5D F0 ||mov ebx,[local.4]
004050CE |. 8B1B ||mov ebx,dword ptr ds:[ebx]
004050D0 |. 85DB ||test ebx,ebx
004050D2 |. 74 09 ||je short dumped_.004050DD
004050D4 |. 53 ||push ebx
004050D5 |. E8 211C0100 ||call dumped_.00416CFB
004050DA |. 83C4 04 ||add esp,0x4
004050DD |> 58 ||pop eax
004050DE |. 8B5D F0 ||mov ebx,[local.4]
004050E1 |. 8903 ||mov dword ptr ds:[ebx],eax
004050E3 |. 6A 00 ||push 0x0
004050E5 |. 6A 00 ||push 0x0
004050E7 |. 6A 00 ||push 0x0
004050E9 |. 68 01030080 ||push 0x80000301
004050EE |. 6A 00 ||push 0x0
004050F0 |. 68 00000000 ||push 0x0
004050F5 |. 68 04000080 ||push 0x80000004
004050FA |. 6A 00 ||push 0x0
004050FC |. 68 76974A00 ||push dumped_.004A9776 ; 您使用的可能是破解软件,请到 www.qqjilu.com 下载试用版!
00405101 |. 68 03000000 ||push 0x3
00405106 |. BB 00934100 ||mov ebx,dumped_.00419300
0040510B |. E8 031C0100 ||call dumped_.00416D13
00405110 |. 83C4 28 ||add esp,0x28
00405113 |. 58 ||pop eax
00405114 |. 59 ||pop ecx
00405115 |.^ E9 14FFFFFF |\jmp dumped_.0040502E
这个就小case了.修改上面的跳转保存运行,OK,非常完美.这样我们就非常快速简捷的
破解了这个软件.
最后说一下我的一点点个人心得:
1:碰到通过全局变量来判断是否已经注册的程序,我们可以通过修改(patch)全局变
量的值来达到破解的目的.
2:另一种情况,就是整个程序都是通过注册验证函数来判断是否注册的,
可以修改注册验证函数的返回值来达到快速破解的目的.
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)