PCWorker 破解(算法)分析
【破文标题】:PCWorker 破解(算法)分析
【破文作者】:Skyer
【软件名称】:PCWorker
【软件大小】:325 KB
【使用平台】:Win9x/Me/NT/2000/XP
【发布公司】:http://www.pcworker.net
【软件简介】:像按键精灵可自动按键 (可免费注册)
【加密方式】:License File
【编译语言】:VC 6
【功能限制】:时间限制
【调试环境】:WinXP, OllyDBG 1.10
【破解日期】:2005-04-02
【破解目的】:研究算法分析 (此软件注册不用钱, 作者只是想了解有那些人在使用这软件)
【作者声明】:初学Crack,只是感兴趣,没有其它目的。失误之处敬请诸位大侠赐教!
─────────────────────────────────
【破解过程】:
第一次发文,请多指教..
1. 先执行一次 pcworker,记下 PCKEY,并去除 -,关闭
2. OD 载入 pcworker.exe 执行到
PCWorker.ii 是注册档,向 PCWorker 注册后,作者会发 email 到你的信箱
00432BC2 > \68 24E74400
push PCWorker.0044E724
; ASCII "\PCWorker.ii"
00432BC7 . 8D4424 1C
lea eax,
dword ptr ss:[
esp+1C]
00432BCB . 68 4C144500
push offset <PCWorker.EXEPath>
00432BD0 . 50
push eax
00432BD1 . E8 3C570000
call <jmp.&MFC42.#924_operator+>
00432BD6 . 8B4C24 18
mov ecx,
dword ptr ss:[
esp+18]
00432BDA . C68424 C412000>
mov byte ptr ss:[
esp+12C4],8
00432BE2 . 51
push ecx
00432BE3 . FF15 80F84300
call dword ptr ds:[<&PCWorker.KMCF_Acc>
; PCWork_1.KMCF_AccessFile
00432BE9 . 8B2D 54F84300
mov ebp,
dword ptr ds:[<&PCWorker.CKMC_>
; PCWork_1.CKMC_IniFile::GetValue
00432BEF . 83C4 04
add esp,4
00432BF2 . 84C0
test al,
al
00432BF4 . 0F84 BC030000
je PCWorker.00432FB6
继续往下执行到
0043363B . 68 1CE74400
push PCWorker.0044E71C
; ASCII "PCKEY"
00433640 . E8 794C0000
call <jmp.&MFC42.#537_CString::CString>
00433645 . 8B15 D0E54400
mov edx,
dword ptr ds:[44E5D0]
; PCWorker.0044E5D4
0043364B . 51
push ecx
0043364C . 8BCC
mov ecx,
esp
0043364E . 896424 40
mov dword ptr ss:[
esp+40],
esp
00433652 . 52
push edx
00433653 . C68424 D412000>
mov byte ptr ss:[
esp+12D4],34
0043365B . E8 5E4C0000
call <jmp.&MFC42.#537_CString::CString>
00433660 . 8D4424 1C
lea eax,
dword ptr ss:[
esp+1C]
00433664 . 8BCD
mov ecx,
ebp
00433666 . 50
push eax
00433667 . C68424 D412000>
mov byte ptr ss:[
esp+12D4],7
0043366F . FF15 54F84300
call dword ptr ds:[<&PCWorker.CKMC_Ini>
; PCWork_1.CKMC_IniFile::GetValue
这里会从 pcworker.ini 读取 [Registration] 下的注册信息,但我们的设定文件无此信息, 手动加上
[Registration]
PCKEY=填入第一次执行 pcworker 记录的 pckey
Name=Skyer
Birthday=1981/01/30
Serial=kKR7sky $
本文主要要找出 Serial 的算法
重新分析 pcworker.exe (Ctrl+F2),执行到
004337E1 . 8B0F
mov ecx,
dword ptr ds:[
edi]
; Serial
004337E3 . BB 0A000000
mov ebx,0A
; 长度一定要为 10
004337E8 . 3959 F8
cmp dword ptr ds:[
ecx-8],
ebx
004337EB . 7D 1A
jge short PCWorker.00433807
了解 Serial 长度必为 10
再往下到
004338E8 > /8A0408
mov al,
byte ptr ds:[
eax+
ecx]
004338EB . |8B1D 24144500
mov ebx,
dword ptr ds:[<PCKeyXOR>]
004338F1 . |884424 10
mov byte ptr ss:[
esp+10],
al
004338F5 . |8B4424 10
mov eax,
dword ptr ss:[
esp+10]
004338F9 . |25 FF000000
and eax,0FF
004338FE . |33D8
xor ebx,
eax
00433900 . |41
inc ecx
00433901 . |891D 24144500
mov dword ptr ds:[<PCKeyXOR>],
ebx
00433907 . |8B02
mov eax,
dword ptr ds:[
edx]
00433909 . |3B48 F8
cmp ecx,
dword ptr ds:[
eax-8]
0043390C .^\7C DA
jl short PCWorker.004338E8
这里是算 pckey 的 xor 编码 (由左至右一个一个 xor) => 取名 PCKeyXOR
转成代码大概是:
int sum=0;
for (i=0; i<PCKeyLength; i++)
sum = sum ^ PCKey[ i ]
0043392C > /8A1408
mov dl,
byte ptr ds:[
eax+
ecx]
0043392F . |8B2D 18144500
mov ebp,
dword ptr ds:[<PCKeyAdd>]
00433935 . |885424 10
mov byte ptr ss:[
esp+10],
dl
00433939 . |8B5424 10
mov edx,
dword ptr ss:[
esp+10]
0043393D . |81E2 FF000000
and edx,0FF
00433943 . |03EA
add ebp,
edx
00433945 . |40
inc eax
00433946 . |892D 18144500
mov dword ptr ds:[<PCKeyAdd>],
ebp
0043394C . |8B51 F8
mov edx,
dword ptr ds:[
ecx-8]
0043394F . |3BC2
cmp eax,
edx
00433951 .^\7C D9
jl short PCWorker.0043392C
pckey 的 add 编码 (由左至右一个一个 add) => 取名 PCKeyAdd
转成代码大概是:
int sum=0;
for (i=0; i<PCKeyLength; i++)
sum = sum + PCKey[ i ]
00433955 . 8B96 11010000
mov edx,
dword ptr ds:[
esi+111]
; Serial
0043395B . 8BE8
mov ebp,
eax
0043395D . 33C0
xor eax,
eax
0043395F . B9 01000000
mov ecx,1
00433964 > 0FBE1C0A
movsx ebx,
byte ptr ds:[
edx+
ecx]
00433968 . 03C3
add eax,
ebx
0043396A . 41
inc ecx
0043396B . 83F9 08
cmp ecx,8
0043396E .^ 7E F4
jle short PCWorker.00433964
00433970 . 8B8E 19010000
mov ecx,
dword ptr ds:[
esi+119]
00433976 . BB 5F000000
mov ebx,5F
0043397B . 41
inc ecx
0043397C . 898E 19010000
mov dword ptr ds:[
esi+119],
ecx
00433982 . 8A0A
mov cl,
byte ptr ds:[
edx]
00433984 . 33D2
xor edx,
edx
00433986 . F7F3
div ebx
00433988 . 0FBEC9
movsx ecx,
cl
0043398B . 0FBEC2
movsx eax,
dl ; 编码 / 5F 的余数
0043398E . 83C0 20
add eax,20
00433991 . 3BC8
cmp ecx,
eax
00433993 . 74 08
je short PCWorker.0043399D
检查 Serial 是否正确
转成代码大概是:
int key1 = Serial[0];
int sum=0;
int key2;
for (i=1; i<9; i++)
sum += Serial[ i ]
key2 = (sum % 0x5f) + 0x20
if (key1 == key2)
正确!!
004339DA > \2BFD
sub edi,
ebp ; 比较执行时间!! 有没有低于 0.5 s
004339DC . 81FF F4010000
cmp edi,1F4
004339E2 . 76 08
jbe short PCWorker.004339EC
这里判断有没有被调试,强迫跳到 004339EC 吧
00433C55 > /8A0408
mov al,
byte ptr ds:[
eax+
ecx]
00433C58 . |884424 10
mov byte ptr ss:[
esp+10],
al
00433C5C . |8B5424 10
mov edx,
dword ptr ss:[
esp+10]
00433C60 . |A1 28144500
mov eax,
dword ptr ds:[<NameADD>]
00433C65 . |81E2 FF000000
and edx,0FF
00433C6B . |03C2
add eax,
edx
00433C6D . |41
inc ecx
00433C6E . |A3 28144500
mov dword ptr ds:[<NameADD>],
eax
00433C73 . |8B07
mov eax,
dword ptr ds:[
edi]
00433C75 . |3B48 F8
cmp ecx,
dword ptr ds:[
eax-8]
00433C78 .^\7C
DB jl short PCWorker.00433C55
Name 的 add 编码 (由左至右一个一个 add) => 取名 NameADD
00433C7A > \A1 04144500
mov eax,
dword ptr ds:[<PCKey>]
; PCKey
00433C7F . 8A48 02
mov cl,
byte ptr ds:[
eax+2]
00433C82 . 8D4424 10
lea eax,
dword ptr ss:[
esp+10]
00433C86 . 884C24 10
mov byte ptr ss:[
esp+10],
cl
00433C8A . 8B5424 10
mov edx,
dword ptr ss:[
esp+10]
00433C8E . 52
push edx ; 第 3 byte 为 rand key
00433C8F . 50
push eax
00433C90 . E8 8BE9FFFF
call <PCWorker.算 PCKey>
00433C95 . 8B00
mov eax,
dword ptr ds:[
eax]
00433C97 . 8B8E 05010000
mov ecx,
dword ptr ds:[
esi+105]
00433C9D . 50
push eax
00433C9E . 51
push ecx
00433C9F . FFD5
call ebp
00433CA1 . 83C4 10
add esp,10
00433CA4 . 8D4C24 10
lea ecx,
dword ptr ss:[
esp+10]
00433CA8 . 85C0
test eax,
eax
00433CAA . 0F95C3
setne bl
这里是验证 PCKey 的正确性,因为我们的 PCKey 是一开始执行时由 pcworker 产生的
一定正确! 有兴趣研究的朋友们,可进入 00433C90 这个 call 研究研究
00433CD1 > /8A1408
mov dl,
byte ptr ds:[
eax+
ecx]
00433CD4 . |885424 10
mov byte ptr ss:[
esp+10],
dl
00433CD8 . |8B4424 10
mov eax,
dword ptr ss:[
esp+10]
00433CDC . |8B15 28144500
mov edx,
dword ptr ds:[<NameXOR>]
00433CE2 . |25 FF000000
and eax,0FF
00433CE7 . |33D0
xor edx,
eax
00433CE9 . |41
inc ecx
00433CEA . |8915 28144500
mov dword ptr ds:[<NameXOR>],
edx
00433CF0 . |8B07
mov eax,
dword ptr ds:[
edi]
00433CF2 . |3B48 F8
cmp ecx,
dword ptr ds:[
eax-8]
00433CF5 .^\7C DA
jl short PCWorker.00433CD1
Name 的 xor 编码 (由左至右一个一个 xor) => 取名 NameXOR
00433D9A . 8B96 11010000
mov edx,
dword ptr ds:[
esi+111]
00433DA0 . 33C0
xor eax,
eax
00433DA2 . 8BCB
mov ecx,
ebx
00433DA4 > 0FBE3C11
movsx edi,
byte ptr ds:[
ecx+
edx]
00433DA8 . 33C7
xor eax,
edi
00433DAA . 41
inc ecx
00433DAB . 83F9 08
cmp ecx,8
00433DAE .^ 7E F4
jle short PCWorker.00433DA4
00433DB0 . 8A4A 09
mov cl,
byte ptr ds:[
edx+9]
00433DB3 . 33D2
xor edx,
edx
00433DB5 . BF 5F000000
mov edi,5F
00433DBA . F7F7
div edi
00433DBC . 80C2 20
add dl,20
00433DBF . 3ACA
cmp cl,
dl
00433DC1 . 74 07
je short PCWorker.00433DCA
检查 Serial 是否正确
转成代码大概是:
int key1 = Serial[9];
int sum=0;
int key2;
for (i=1; i<9; i++)
sum = sum ^ Serial[ i ]
key2 = (sum % 0x5f) + 0x20
if (key1 == key2)
正确!!
004340FD > /8A0408
mov al,
byte ptr ds:[
eax+
ecx]
00434100 . |8B1D 2C144500
mov ebx,
dword ptr ds:[45142C]
00434106 . |884424 10
mov byte ptr ss:[
esp+10],
al
0043410A . |8B4424 10
mov eax,
dword ptr ss:[
esp+10]
0043410E . |25 FF000000
and eax,0FF
00434113 . |33D8
xor ebx,
eax
00434115 . |41
inc ecx
00434116 . |891D 2C144500
mov dword ptr ds:[45142C],
ebx
0043411C . |8B02
mov eax,
dword ptr ds:[
edx]
0043411E . |3B48 F8
cmp ecx,
dword ptr ds:[
eax-8]
00434121 .^\7C DA
jl short PCWorker.004340FD
Birthday 的 xor 编码 (由左至右一个一个 xor) => 取名 BirthdayXOR
00434141 > /8A1408
mov dl,
byte ptr ds:[
eax+
ecx]
00434144 . |8B1D 20144500
mov ebx,
dword ptr ds:[<BirthdayAdd>]
0043414A . |885424 10
mov byte ptr ss:[
esp+10],
dl
0043414E . |8B5424 10
mov edx,
dword ptr ss:[
esp+10]
00434152 . |81E2 FF000000
and edx,0FF
00434158 . |03DA
add ebx,
edx
0043415A . |40
inc eax
0043415B . |891D 20144500
mov dword ptr ds:[<BirthdayAdd>],
ebx
00434161 . |8B51 F8
mov edx,
dword ptr ds:[
ecx-8]
00434164 . |3BC2
cmp eax,
edx
00434166 .^\7C D9
jl short PCWorker.00434141
Birthday 的 add 编码 (由左至右一个一个 add) => 取名 BirthdayAdd
在 4513f8 下内存访问断点,可找到所有比较 Serial 的规则
00408674 . 8B85 1B0C0000
mov eax,
dword ptr ss:[
ebp+C1B]
; PCKeyAdd编码
0040867A . 8B15 20144500
mov edx,
dword ptr ds:[<BirthdayAdd编码>]
00408680 . 8B3D 1C144500
mov edi,
dword ptr ds:[<NameAdd编码>]
00408686 . 03C2
add eax,
edx
00408688 . 03C7
add eax,
edi
0040868A . 33D2
xor edx,
edx
0040868C . BE 5F000000
mov esi,5F
00408691 . 8B0D F8134500
mov ecx,
dword ptr ds:[<Serial>]
00408697 . F7F6
div esi
00408699 . 8A49 01
mov cl,
byte ptr ds:[
ecx+1]
0040869C . 0FBEC1
movsx eax,
cl
0040869F . 0FBED2
movsx edx,
dl
004086A2 . 83C2 20
add edx,20
004086A5 . 3BC2
cmp eax,
edx
004086A7 . 74 07
je short PCWorker.004086B0
这里是比较 Serial[1]
转换成代码如下..
int sum = PCKeyAdd + BirthdayAdd + NameAdd
char s1 = (sum % 0x5f) + 0x20
比较 Serial[2]
转换成代码如下..
int sum = PCKeyXor ^ BirthdayXor ^ NameXor
char s2 = (sum % 0x5f) + 0x20
比较 Serial[3]
转换成代码如下..
int sum = PCKeyAdd ^ BirthdayAdd ^ NameAdd
char s3 = (sum % 0x5f) + 0x20
比较 Serial[4]
转换成代码如下..
int sum = PCKeyXor + BirthdayXor + NameXor
char s4 = (sum % 0x5f) + 0x20
比较 Serial[8]
转换成代码如下..
int sum = BirthdayXor & NameAdd | PCKeyXor
char s8 = (sum % 0x5f) + 0x20
其中 Serial[5] ~ Serial[7] 随便,不重要
最后,来整理一下算法..
1. Serial 是依 PCKey, Name, Birthday 算出来的. 长度为 10 (Serial[0] ~ Serial[9])
2. 算出 pckey, name, birthday 的 add, xor 值
3. 算出 Serial[1], Serial[2], Serial[4], Serial[4], Serial[8]
4. Serial[5] ~ Serial[7] 随便填
5. 算出 Serial[0] & Serial[9]
6. 结束..
以下是 python 写的注册机 (python 2.4)
使用方式:
D:\Data\Python>python PcworkerReg.py F-QYUC-TFGY-NGBN Skyer 1932/01/34
会产生 pcworker.ii, 放到 pcworker 下即可
------------PcworkerReg.py-----------------
import sys, string
def CalAddSum(s):
sum = 0
smap = map(lambda x: ord(x), s)
for i in smap:
sum += i
return sum
def CalXorSum(s):
xors = 0
smap = map(lambda x: ord(x), s)
for i in smap:
xors = xors ^ i
return xors
def main(args):
if len(args) != 4:
print 'Usage: %s [PCKEY] [Name] [Birthday]' % (args[0])
return
pckey = string.replace(args[1], '-', '')
pckey = string.upper(pckey)
nameadd = CalAddSum(args[2])
namexor = CalXorSum(args[2])
birthadd = CalAddSum(args[3])
birthxor = CalXorSum(args[3])
pckeyadd = CalAddSum(pckey)
pckeyxor = CalXorSum(pckey)
#Serial, 2nd byte
c1 = chr(((nameadd + birthadd + pckeyadd) % 0x5f) + 0x20)
#Serial, 3rd byte
c2 = chr(((namexor ^ birthxor ^ pckeyxor) % 0x5f) + 0x20)
#Serial, 4th byte
c3 = chr(((nameadd ^ birthadd ^ pckeyadd) % 0x5f) + 0x20)
#Serial, 5th byte
c4 = chr(((namexor + birthxor + pckeyxor) % 0x5f) + 0x20)
#Serial, 9th byte
c8 = chr(((birthxor & nameadd | pckeyxor) % 0x5f) + 0x20)
key = c1+c2+c3+c4+'sky'+c8
c0 = chr((CalAddSum(key) % 0x5f) + 0x20)
c9 = chr((CalXorSum(key) % 0x5f) + 0x20)
key = c0 + key + c9
o = open('pcworker.ii', 'w')
o.write('[Registration]\n')
o.write('PCKEY=%s\n' % (pckey))
o.write('Name=%s\n' % (args[2]))
o.write('Birthday=%s\n' % (args[3]))
o.write('Serial=%s\n' % (key))
if __name__ == '__main__':
main(sys.argv)
-----------------------------------------------------
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法