-
-
[原创]第7题算法分析步骤
-
发表于: 2017-6-14 15:12 3491
-
工具:OD,VB,IDA
破解步骤:
1.该程序在Win7x64下运行异常,放入WinXP虚拟机,OD载入直接运行,下断:bp GetDlgItemTextA,输入注册码123456后回车,断下来了,返回到用户代码:
004104CD /$ 68 >push 0x90
004104D2 |. B8 >mov eax, 0045037E
004104D7 |. E8 >call 00413FD7
004104DC |. 8BF>mov esi, ecx
004104DE |. 6A >push 0x65
004104E0 |. 8D4>lea eax, dword ptr [ebp-0x80]
004104E3 |. 6A >push 0x0
004104E5 |. 50 push eax
004104E6 |. E8 >call 004156A0
004104EB |. 83C>add esp, 0xC
004104EE |. 8D4>lea eax, dword ptr [ebp-0x80]
004104F1 |. 6A >push 0x64 ; /Count = 64 (100.)
004104F3 |. 50 push eax ; |Buffer
004104F4 |. 68 >push 0x3E8 ; |ControlID = 3E8 (1000.)
004104F9 |. FF7>push dword ptr [esi+0x4] ; |hWnd
004104FC |. FF1>call dword ptr [<&USER32.GetDlgItemTextA>] ; \GetDlgItemTextA
00410502 |. 8D4>lea eax, dword ptr [ebp-0x80]
00410505 |. 50 push eax ; /Arg1
00410506 |. 8D8>lea ecx, dword ptr [ebp-0x98] ; |
0041050C |. E8 >call 0040FD2D ; \7-不问少.0040FD2D
00410511 |. 836>and dword ptr [ebp-0x4], 0x0
00410515 |. 8D4>lea eax, dword ptr [ebp-0x18]
00410518 |. 6A >push 0x5
0041051A |. 50 push eax
0041051B |. BB >mov ebx, 0x1AA
00410520 |. C74>mov dword ptr [ebp-0x18], 0x49444550
00410527 |. 53 push ebx
00410528 |. BF >mov edi, 00411B30
0041052D |. C64>mov byte ptr [ebp-0x14], 0x59
00410531 |. 57 push edi
00410532 |. E8 >call 00410DD6 ; code dec
00410537 |. 51 push ecx
00410538 |. 51 push ecx
00410539 |. 8D8>lea eax, dword ptr [ebp-0x98]
0041053F |. 89A>mov dword ptr [ebp-0x9C], esp
00410545 |. 8BC>mov ecx, esp
00410547 |. 50 push eax ; /Arg1
00410548 |. E8 >call 0040FD07 ; \7-不问少.0040FD07
0041054D |. C64>mov byte ptr [ebp-0x4], 0x1
00410551 |. C64>mov byte ptr [ebp-0x4], 0x0
00410555 |. 8D4>lea ecx, dword ptr [esi+0x40]
00410558 |. E8 >call 00411B30 ; code exec:user key exchange
0041055D |. 6A >push 0x5 ; /Arg4 = 00000005
0041055F |. 8D4>lea eax, dword ptr [ebp-0x18] ; |
00410562 |. 50 push eax ; |Arg3
00410563 |. 53 push ebx ; |Arg2
00410564 |. 57 push edi ; |Arg1
00410565 |. E8 >call 00410DD6 ; \code enc
0041056A |. 83C>add esp, 0x10
0041056D |. 8D4>lea ecx, dword ptr [esi+0x40]
00410570 |. E8 >call 00411825 ; calc key???
00410575 |. 834>or dword ptr [ebp-0x4], 0xFFFFFFFF
00410579 |. 8D8>lea ecx, dword ptr [ebp-0x98]
0041057F |. 6A >push 0x0 ; /Arg2 = 00000000
00410581 |. 6A >push 0x1 ; |Arg1 = 00000001
00410583 |. E8 >call <_memfree> ; \7-不问少.00410AE3
00410588 |. 33C>xor eax, eax
0041058A |. E8 >call 00413F81
0041058F \. C2 >retn 0x10
没有明显的比较过程,只能每个CALL里都看一下了。
2.00410532 call 00410DD6这个CALL里的操作是对00411B30处长度为0x1AA的代码使用“PEDIY”进行解码,然后00410558 call 00411B30运行,最后00410570 call 00411825再把代码加密。需要解密才运行,可见call 00411B30里有关键代码,跟进观察。
3.这个CALL 00411B30里算法比较绕,花了很长时才搞明白,分以下几步:
(1)先对输入码key xor 0xCC
(2)按字节调用00411C13 call 00410F4C在一个表里找索引值index,该表为:
tb1:
0016CFD0 89 BC 95 FC FB BA ED 9A BB AE FE 99 A2 98 B9 F9
0016CFE0 9F 84 9C FD 83 AD B6 A9 A5 F5 8C A7 9E 96 8A F4
0016CFF0 85 BE A8 8F 86 AF 88 9D 87 BF FF A1 8B 81 A0 AB
0016D000 8E BD B5 AA 82 94 A4 8D A3 F8 B4 FA 9B A6 B8 80
此表XOR 0xCC可以得到初始字符串列表:“EpY07v!Vwb2UnTu5SHP1Oazei9@kRZF8IrdCJcDQKs3mGMlgBqyfNXhAo4x6WjtL”
将索引值index进行计算,计算结果查上面的表tb1然后保存到原位置。算法用VB表示为:
For i = 1 To Len(s)
n = InStr(1, ss, Mid$(s, i, 1)) - 1
For j = 1 To i
n = (n + n \ 5 + 5) Mod &H40
Next
bb(i) = tb1(n)
Next
(3)在00411CA4 call 00410F75里,按字节XOR 0xCC再ror(5),保存回原位置,记为key2。
4.00410565 call 00410DD6把执行后的代码加密后,在00410570 call 00411825里验证刚才计算的结果,正确时执行后续操作。验证过程全部在00410570 call 00411825里,步骤为:
(1)00411987 call 0041191F把上一步计算的结果key2转换为HEX字符,记为key3。
(2)key3按字节调用004119F4 call 00410F4C在一个表里找索引值index,该表tb2为:
tb2:
00403D50 30 31 32 33 34 35 36 37 38 39 41 42 43 44 45 46 0123456789ABCDEF
将索引值index转换为四进制值保存。
(3)判断四进制结果的长度是否为0x50,即80字节。
(4)四进制结果与一个固定值比较,该固定值为:
tb3:
0016D120 02 02 00 03 00 00 02 03 00 01 02 03 02 00 00 02 10100011 00001011 00011011 10000010 A30B1B82
0016D130 02 00 02 02 02 03 02 03 01 00 02 02 02 01 02 03 10001010 10111011 01001010 10011011 8ABB4A9B
0016D140 02 02 02 01 02 03 02 03 02 01 00 03 02 02 02 02 10101001 10111011 10010011 10101010 A9BB93AA
0016D150 02 02 00 03 01 02 02 03 02 00 00 02 02 02 02 02 10100011 01101011 10000010 10101010 A36B82AA
0016D160 00 00 00 02 01 00 02 02 02 03 00 02 01 00 00 03 00000010 01001010 10110010 01000011 024AB243
把此四进制表转换为16进制,得到结果字符串为“A30B1B828ABB4A9BA9BB93AAA36B82AA024AB243”。
5.已经得到完整算法了,简化后VB表示为:
Function ShlAndSar(value As Byte) As Byte
Dim v1 As Long, v2 As Long
v1 = value
v1 = (v1 * 8) And &HFF
v2 = value And &H7F
If (value And &H80) <> 0 Then v2 = -v2
v2 = v2 \ 32
ShlAndSar = (v1 Or v2) And &HFF
End Function
Private Sub Command1_Click()
Dim ss As String
Dim i As Long, j As Long
Dim n As Byte
Dim s As String, t As String
ss = "EpY07v!Vwb2UnTu5SHP1Oazei9@kRZF8IrdCJcDQKs3mGMlgBqyfNXhAo4x6WjtL"
s = Text1.Text
For i = 1 To Len(s)
n = InStr(1, ss, Mid$(s, i, 1)) - 1
For j = 1 To i
n = (n + n \ 5 + 5) Mod &H40
Next
n = Asc(Mid$(ss, n + 1, 1))
n = ShlAndSar(n)
t = t & Right$("00" & Hex(n), 2)
Next
Text2.Text = t
End Sub
6.根据此算法,逆推还原算法,VB表示为:
Private Function GetIndex(ByVal n As Long, ByVal c As Long) As String
Dim i As Long, j As Long, k As Long
Dim s As String
Dim ss As String
ss = "EpY07v!Vwb2UnTu5SHP1Oazei9@kRZF8IrdCJcDQKs3mGMlgBqyfNXhAo4x6WjtL"
For i = 0 To 63
k = i
For j = 1 To n
k = (k + k \ 5 + 5) Mod &H40
Next
If k = c Then
s = Mid$(ss, i + 1, 1)
Exit For
End If
Next
GetIndex = s
End Function
Private Sub Command2_Click()
Dim ss As String
Dim i As Long, j As Long, k As Long
Dim n As Byte
Dim c As String
Dim s As String, t As String
Dim mm(&HFF) As Byte
For i = 0 To &HFF
mm(i) = ShlAndSar((i And &HFF))
Next
ss = "EpY07v!Vwb2UnTu5SHP1Oazei9@kRZF8IrdCJcDQKs3mGMlgBqyfNXhAo4x6WjtL"
s = Text1.Text
For i = 1 To Len(s) \ 2
n = Val("&H" & Mid$(s, i * 2 - 1, 2))
For j = 0 To &H7F
If mm(j) = n Then
n = InStr(1, ss, Chr(j)) - 1
t = t & GetIndex(i, n)
End If
Next
Next
Text2.Text = t
End Sub
得到注册码:BwndYbPHdPy2017@J9Ok
7.本来以为到这里就结束了,但是将此结果填进去还是没有正确提示。继续往下看,发现还有后续操作:
00411825 $ 6A >push 0x18
00411827 . B8 >mov eax, 0045054A
0041182C . E8 >call 0041400E
00411831 . 894>mov dword ptr [ebp-0x1C], ecx
00411834 . E8 >call 00411975 ; 校验注册码,必须返回1
00411839 . 84C>test al, al
0041183B . 0F8>je 00411919
00411841 . 6A >push 0x40 ; /Protect = PAGE_EXECUTE_READWRITE
00411843 . BB >mov ebx, 0x1000 ; |
00411848 . 53 push ebx ; |AllocationType => MEM_COMMIT
00411849 . 53 push ebx ; |Size => 1000 (4096.)
0041184A . 33F>xor esi, esi ; |
0041184C . 56 push esi ; |Address => NULL
0041184D . FF1>call dword ptr [<&KERNEL32.VirtualAlloc>] ; \申请空间
00411853 . 8BF>mov edi, eax
00411855 . 897>mov dword ptr [ebp-0x18], edi
00411858 . 68 >push 0x94 ; /Arg4 = 00000094
0041185D . 68 >push 00411A9C ; |Arg3 = 00411A9C
00411862 . 53 push ebx ; |Arg2 => 00001000
00411863 . 57 push edi ; |Arg1
00411864 . E8 >call 004121ED ; \复制代码
00411869 . 83C>add esp, 0x10
0041186C . 8BC>mov ecx, edi
0041186E . 894>mov dword ptr [ebp-0x14], ecx
00411871 . 897>mov dword ptr [ebp-0x4], esi
00411874 . 897>mov dword ptr [ebp-0x20], esi
00411877 . 8B4>mov ecx, dword ptr [ebp-0x1C]
0041187A > 81F>cmp esi, 0x94
00411880 . 7D >jge short 004118A9
00411882 . 8BC>mov eax, esi
00411884 . 33D>xor edx, edx
00411886 . F77>div dword ptr [ecx+0x34]
00411889 . 46 inc esi
0041188A . 897>mov dword ptr [ebp-0x20], esi
0041188D . 8D4>lea eax, dword ptr [ecx+0x24]
00411890 . 837>cmp dword ptr [eax+0x14], 0x10
00411894 . 72 >jb short 00411898
00411896 . 8B0>mov eax, dword ptr [eax]
00411898 > 8A0>mov al, byte ptr [eax+edx]
0041189B . 8B5>mov edx, dword ptr [ebp-0x14]
0041189E . 300>xor byte ptr [edx], al ; 使用输入key对代码解密
004118A0 . 42 inc edx
004118A1 . 895>mov dword ptr [ebp-0x14], edx
004118A4 . 895>mov dword ptr [ebp-0x24], edx
004118A7 .^ EB >jmp short 0041187A
004118A9 > 8B4>mov eax, dword ptr [ecx+0x34]
004118AC . 894>mov dword ptr [ebp-0x1C], eax
004118AF . 83C>add ecx, 0x24
004118B2 . 837>cmp dword ptr [ecx+0x14], 0x10
004118B6 . 72 >jb short 004118BA
004118B8 . 8B0>mov ecx, dword ptr [ecx]
004118BA > 8BC>mov eax, esi
004118BC . 33D>xor edx, edx
004118BE . F77>div dword ptr [ebp-0x1C]
004118C1 . 8A0>mov al, byte ptr [edx+ecx]
004118C4 . 8B4>mov ecx, dword ptr [ebp-0x14]
004118C7 . 300>xor byte ptr [ecx], al
004118C9 . 8D4>lea ecx, dword ptr [edi+0x60]
004118CC . BA >mov edx, 00411A9C
004118D1 . 8BC>mov eax, edx
004118D3 . 2BC>sub eax, ecx
004118D5 . 83C>add eax, 0x60
004118D8 . 014>add dword ptr [ecx+0x1], eax
004118DB . 8D8>lea ecx, dword ptr [edi+0x8B]
004118E1 . 8B4>mov eax, dword ptr [ecx+0x1]
004118E4 . 2BC>sub eax, ecx
004118E6 . 81C>add edx, 0x8B
004118EC . 03C>add eax, edx
004118EE . 894>mov dword ptr [ecx+0x1], eax
004118F1 . FF5>call dword ptr [ebp-0x18] ; 跳到解密代码执行
需要使用输入的注册码对代码解密,注册成功的提示藏在解密代码里。使用刚才得到的注册码,解密代码有错误指令。看来注册码有多解,需要逐一尝试才能得到正确的指令代码。先修改之前的VB程序:
Private Function GetIndex(ByVal n As Long, ByVal c As Long) As String
Dim i As Long, j As Long, k As Long
Dim s As String
Dim ss As String
ss = "EpY07v!Vwb2UnTu5SHP1Oazei9@kRZF8IrdCJcDQKs3mGMlgBqyfNXhAo4x6WjtL"
For i = 0 To 63
k = i
For j = 1 To n
k = (k + k \ 5 + 5) Mod &H40
Next
If k = c Then
s = s & "," & Mid$(ss, i + 1, 1)
End If
Next
GetIndex = s
End Function
Private Sub Command2_Click()
Dim ss As String
Dim i As Long, j As Long, k As Long
Dim n As Byte
Dim c As String
Dim s As String, t As String
Dim mm(&HFF) As Byte
For i = 0 To &HFF
mm(i) = ShlAndSar((i And &HFF))
Next
ss = "EpY07v!Vwb2UnTu5SHP1Oazei9@kRZF8IrdCJcDQKs3mGMlgBqyfNXhAo4x6WjtL"
s = Text1.Text
For i = 1 To Len(s) \ 2
n = Val("&H" & Mid$(s, i * 2 - 1, 2))
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!