【原创】action script viewer 6猥琐注册算法分析【简要注册机源码】
本来此篇文章也在旧blog上发表,现在重新折腾。
【破文标题】action script viewer 6注册算法分析【简要注册机源码】
【破文作者】coolspace
【破解工具】PEiD,IDA,Filemon
【破解平台】Windows XP sp3
【软件名称】action script viewer 6 pre-release5
【原版下载】放狗
【保护方式】keyfile
【软件简介】Action s cript Viewer (ASV)是款SWF (Flash)反编译的(decompiler 是翻译机器语言或有时目标代码的计算机程序(产品从编译器) 成一种高级语言(原始代码) 。由比较, 反汇编程序翻译机器语言成汇编语言。)win32应用程序.能让你查看SWF文件里面的动作脚本;能让你抽取位图、音频、视频、字体等原始文件;能让你浏览SWF文件的内部架构;能帮你重建SWF的FLA文件,导出SWF的原始资源文件和一个JSFL命令。
【破解声明】以前偷偷的弄个几个软件,但是这倒是第一次写破文,问题多多,看官见谅。软件注册校验地方太多,破文没贴全。看keygen代码领会精神即可
【破解内容】
偶然机会,放狗搜到最新版的asv主程序,马上下载,然后运行。结果无界面:funk: :funk: 。初步估计是原来的注册失效了(这个软件的注册一般不能跨大版本使用)。:lol
根据以前版本的使用经验,没发现有输入注册码的地方,并从官网得知,应该为keyfile型注册
这是个很好的工具,如是决定灭之(最开始也没想到软件的注册这么猥琐)。
一、定位keyfile文件名
开启神器Filemon,运行asv主程序,发现载入了一个名为asv5.pke的文件。初步断定,keyfile就是这个。另外还载入了一个ASV5U.DLL。这个文件peid查为delphi dll文件,估计从其中调用了部分导出函数,之后再说。
这里插一句,最开始忘记上官网看了,之后灭完后上官网一看,连注册文件的文件名都已经告诉用户了,这步可以省略:funk:
二、查壳,脱壳
peid查主程序为upx压缩壳,脱之,脱壳后显示为delphi程序。过程省去不表。
三、分析算法
IDA载入脱壳后的主程序,载入相应sig文件。等IDA分析完成后,查找字符串asv5.pke。
定位到这个地方。
引用:
CODE:007E8120 s->Asv5_pke db ‘\asv5.pke’,0
进入,发现是个名为Asv5_pke的字符串,继续查找Asv5_pke,定位到以下地方。(这里的代码有部分我已经根据自己的习惯标注过了,变量名,函数名什么的)
引用:
CODE:007E7BF0 Readregfile proc near
CODE:007E7BF0
CODE:007E7BF0 var_4C = dword ptr -4Ch
CODE:007E7BF0 var_48 = dword ptr -48h
CODE:007E7BF0 src = dword ptr -2Ch
CODE:007E7BF0 var_28 = dword ptr -28h
CODE:007E7BF0 dllname = dword ptr -24h
CODE:007E7BF0 result = dword ptr -20h
CODE:007E7BF0 var_1C = dword ptr -1Ch
CODE:007E7BF0 var_18 = dword ptr -18h
CODE:007E7BF0 var_14 = dword ptr -14h
CODE:007E7BF0 var_10 = dword ptr -10h
CODE:007E7BF0 asv5_pke_filename= dword ptr -0Ch
CODE:007E7BF0 var_8 = dword ptr -8
CODE:007E7BF0 dest = byte ptr -4
CODE:007E7BF0 unknow = byte ptr 0
CODE:007E7BF0
CODE:007E7BF0 000 push ebp
CODE:007E7BF1 004 mov ebp, esp
CODE:007E7BF3 004 mov ecx, 5
CODE:007E7BF3
CODE:007E7BF8
CODE:007E7BF8 loc_7E7BF8: ; CODE XREF: Readregfile+Dj
CODE:007E7BF8 004 push 0
CODE:007E7BFA 004 push 0
CODE:007E7BFC 004 dec ecx ; Decrement by 1
CODE:007E7BFD 004 jnz short loc_7E7BF8 ; Jump if Not Zero (ZF=0)
CODE:007E7BFD
CODE:007E7BFF 02C push ecx
CODE:007E7C00 030 push ebx
CODE:007E7C01 034 push esi
CODE:007E7C02 038 push edi
CODE:007E7C03 03C mov ebx, offset File_asv5pke
CODE:007E7C08 03C xor eax, eax ; Logical Exclusive OR
CODE:007E7C0A 03C push ebp
CODE:007E7C0B 040 push offset loc_7E8108
CODE:007E7C10 044 push dword ptr fs:[eax]
CODE:007E7C13 048 mov fs:[eax], esp
CODE:007E7C16 048 sub ds:dword_81FA50, 1 ; Integer Subtraction
CODE:007E7C1D 048 jnb loc_7E80E0 ; Jump if Not Below (CF=0)
CODE:007E7C1D
CODE:007E7C23 048 xor esi, esi ; Logical Exclusive OR
CODE:007E7C25 048 push ebp
CODE:007E7C26 04C push offset loc_7E7FE5
CODE:007E7C2B 050 push dword ptr fs:[esi]
CODE:007E7C2E 054 mov fs:[esi], esp
CODE:007E7C31 054 lea edx, [ebp+var_8] ; Load Effective Address
CODE:007E7C34 054 xor eax, eax ; Logical Exclusive OR
CODE:007E7C36 054 call System::ParamStr(int) ; Call Procedure //取命令行参数中的程序路径
CODE:007E7C36
CODE:007E7C3B 054 mov eax, [ebp+var_8]
CODE:007E7C3E 054 lea edx, [ebp+dest] ; Load Effective Address
CODE:007E7C41 054 call sub_7D7CCC ; Call Procedure //取程序所在目录
CODE:007E7C41
CODE:007E7C46 054 lea eax, [ebp+dest] ; dest
CODE:007E7C49 054 mov edx, offset s->Asv5_pke ; src
CODE:007E7C4E 054 call System::__linkproc__ LStrCat(void) ; Call Procedure //取keyfile全路径
CODE:007E7C4E
CODE:007E7C53 054 mov eax, dword ptr [ebp+dest]
CODE:007E7C56 054 call sub_7D8720 ; Call Procedure //跟进这个call,发现时校验keyfile是否存在
CODE:007E7C56
CODE:007E7C5B 054 lea edx, [ebp+var_10] ; Load Effective Address
CODE:007E7C5E 054 xor eax, eax ; Logical Exclusive OR
CODE:007E7C60 054 call System::ParamStr(int) ; Call Procedure //重复以上过程,取得程序路径
CODE:007E7C60
CODE:007E7C65 054 mov eax, [ebp+var_10]
CODE:007E7C68 054 lea edx, [ebp+asv5_pke_filename] ; Load Effective Address
CODE:007E7C6B 054 call sub_7D7CCC ; Call Procedure //取得程序所在目录
CODE:007E7C6B
CODE:007E7C70 054 lea eax, [ebp+asv5_pke_filename] ; dest
CODE:007E7C73 054 mov edx, offset s->Asv5_pke ; src
CODE:007E7C78 054 call System::__linkproc__ LStrCat(void) ; Call Procedure //获得keyfile全路径
CODE:007E7C78
CODE:007E7C7D 054 mov edx, [ebp+asv5_pke_filename]
CODE:007E7C80 054 mov eax, ebx
CODE:007E7C82 054 call System::__linkproc__ Assign(System::TTextRec &,System::AnsiString) ; Call Procedure //打开keyfile
CODE:007E7C82
CODE:007E7C87 054 mov eax, ds:off_80E5E0
CODE:007E7C8C 054 mov byte ptr [eax], 0
CODE:007E7C8F 054 mov edx, 1
CODE:007E7C94 054 mov eax, ebx
CODE:007E7C96 054 call System::__linkproc__ ResetFile(System::TFileRec &,int) ; Call Procedure //设置文件读取指针指向文件头
CODE:007E7C96
CODE:007E7C9B 054 call System::__linkproc__ _IOTest(void) ; Call Procedure
CODE:007E7C9B
CODE:007E7CA0 054 mov eax, ebx
CODE:007E7CA2 054 call System::__linkproc__ FileSize(System::TFileRec &) ; Call Procedure //取得keyfile文件大小
CODE:007E7CA2
CODE:007E7CA7 054 call System::__linkproc__ _IOTest(void) ; Call Procedure
CODE:007E7CA7
CODE:007E7CAC 054 cmp eax, 4 ; Compare Two Operands
CODE:007E7CAF 054 jge short loc_7E7CB6 ; Jump if Greater or Equal (SF=OF)
CODE:007E7CAF
CODE:007E7CB1 054 call System::__linkproc__ Halt0(void) ; Call Procedure
CODE:007E7CB1
CODE:007E7CB6 ; —————————————————————————
CODE:007E7CB6
CODE:007E7CB6 loc_7E7CB6: ; CODE XREF: Readregfile+BFj
CODE:007E7CB6 054 push 0
CODE:007E7CB8 058 mov edx, offset i
CODE:007E7CBD 058 mov ecx, 4
CODE:007E7CC2 058 mov eax, ebx
CODE:007E7CC4 058 call System::__linkproc__ BlockRead(System::TFileRec &,void *,int,int &) ; Call Procedure //读取keyfile前四字节
CODE:007E7CC4
CODE:007E7CC9 054 call System::__linkproc__ _IOTest(void) ; Call Procedure
CODE:007E7CC9
CODE:007E7CCE 054 cmp ds:i, 5565341h ; <suspicious> ; Compare Two Operands //将前四字节与某固定值比较,不等则跳出,这个固定值可以称之为sign
CODE:007E7CD8 054 jz short loc_7E7CDF ; Jump if Zero (ZF=1)
CODE:007E7CD8
CODE:007E7CDA 054 call System::__linkproc__ Halt0(void) ; Call Procedure
CODE:007E7CDA
CODE:007E7CDF ; —————————————————————————
CODE:007E7CDF
CODE:007E7CDF loc_7E7CDF: ; CODE XREF: Readregfile+E8j
CODE:007E7CDF 054 mov eax, ebx
CODE:007E7CE1 054 call System::__linkproc__ FileSize(System::TFileRec &) ; Call Procedure //获得keyfile文件大小
CODE:007E7CE1
CODE:007E7CE6 054 call System::__linkproc__ _IOTest(void) ; Call Procedure
CODE:007E7CE6
CODE:007E7CEB 054 sub eax, 4 ; Integer Subtraction //文件大小减4
CODE:007E7CEE 054 mov edx, ds:pfilesize_plus_4
CODE:007E7CF4 054 mov [edx], eax //文件大小减4后的数值保存在 pfilesize_plus_4所指向的区域
CODE:007E7CF6 054 mov eax, 10h ; count
CODE:007E7CFB 054 call System::__linkproc__ GetMem(int) ; Call Procedure //分配0x10h内存
CODE:007E7CFB
CODE:007E7D00 054 mov edx, ds:MD5result_dll //保存刚分配的内存的指针(这里的变量名都是我完成后的命名)
CODE:007E7D06 054 mov [edx], eax
CODE:007E7D08 054 lea edx, [ebp+var_28] ; Load Effective Address
CODE:007E7D0B 054 xor eax, eax ; Logical Exclusive OR
CODE:007E7D0D 054 call System::ParamStr(int) ; Call Procedure //取程序路径
CODE:007E7D0D
CODE:007E7D12 054 mov eax, [ebp+var_28]
CODE:007E7D15 054 lea edx, [ebp+dllname] ; Load Effective Address
CODE:007E7D18 054 call sub_7D7CCC ; Call Procedure //取程序目录
CODE:007E7D18
CODE:007E7D1D 054 lea eax, [ebp+dllname] ; dest
CODE:007E7D20 054 mov edx, offset s->Asv5u_dll ; src
CODE:007E7D25 054 call System::__linkproc__ LStrCat(void) ; Call Procedure //取dll路径
CODE:007E7D25
CODE:007E7D2A 054 mov eax, [ebp+dllname] ; dllname
CODE:007E7D2D 054 lea edx, [ebp+result] ; result
CODE:007E7D30 054 call MD5_File ; Call Procedure //未知call,跟进
CODE:007E7D30
跟进call MD5_File。
如下
引用:
CODE:004FFF78 MD5_File proc near ; CODE XREF: Readregfile+140p
CODE:004FFF78
CODE:004FFF78 var_10 = dword ptr -10h
CODE:004FFF78 var_C = byte ptr -0Ch
CODE:004FFF78 hfile_dll = dword ptr -8
CODE:004FFF78 handlestream = dword ptr -4
CODE:004FFF78
CODE:004FFF78 000 push ebp
CODE:004FFF79 004 mov ebp, esp
CODE:004FFF7B 004 add esp, 0FFFFFFF0h ; Add
CODE:004FFF7E 014 push ebx
CODE:004FFF7F 018 push esi
CODE:004FFF80 01C mov esi, edx
CODE:004FFF82 01C mov ebx, eax
CODE:004FFF84 01C push 0 ; hTemplateFile
CODE:004FFF86 020 push 80h ; dwFlagsAndAttributes
CODE:004FFF8B 024 push 3 ; dwCreationDisposition
CODE:004FFF8D 028 push 0 ; lpSecurityAttributes
CODE:004FFF8F 02C push 1 ; dwShareMode
CODE:004FFF91 030 push 80000000h ; dwDesiredAccess
CODE:004FFF96 034 mov eax, ebx
CODE:004FFF98 034 call System::__linkproc__ LStrToPChar(System::AnsiString) ; Call Procedure
CODE:004FFF98
CODE:004FFF9D 034 push eax ; lpFileName
CODE:004FFF9E 038 call CreateFileA ; Call Procedure //打开dll文件
CODE:004FFF9E
CODE:004FFFA3 01C mov [ebp+hfile_dll], eax
CODE:004FFFA6 01C cmp [ebp+hfile_dll], 0 ; Compare Two Operands
CODE:004FFFAA 01C jge short loc_4FFFCF ; Jump if Greater or Equal (SF=OF)
CODE:004FFFAA
CODE:004FFFAC 01C mov [ebp+var_10], ebx
CODE:004FFFAF 01C mov [ebp+var_C], 0Bh
CODE:004FFFB3 01C lea eax, [ebp+var_10] ; Load Effective Address
CODE:004FFFB6 01C push eax
CODE:004FFFB7 020 push 0
CODE:004FFFB9 024 mov ecx, offset off_4FFF70
CODE:004FFFBE 024 mov dl, 1
CODE:004FFFC0 024 mov eax, off_420B28
CODE:004FFFC5 024 call Sysutils::Exception::Exception(System::TResStringRec *,System::TVarRec *,int) ; Call Procedure
CODE:004FFFC5
CODE:004FFFCA 01C call System::__linkproc__ RaiseExcept(void) ; Call Procedure
CODE:004FFFCA
CODE:004FFFCF
CODE:004FFFCF loc_4FFFCF: ; CODE XREF: MD5_File+32j
CODE:004FFFCF 01C xor eax, eax ; Logical Exclusive OR
CODE:004FFFD1 01C push ebp
CODE:004FFFD2 020 push offset loc_50003B
CODE:004FFFD7 024 push dword ptr fs:[eax]
CODE:004FFFDA 028 mov fs:[eax], esp
CODE:004FFFDD 028 mov ecx, [ebp+hfile_dll]
CODE:004FFFE0 028 mov dl, 1
CODE:004FFFE2 028 mov eax, Thandlestream
CODE:004FFFE7 028 call unknown_libname_478 ; BDS 2005-2006 and Delphi6-7 Visual Component Library 创建stream对象,并与createfile返回的handle关联,等同于filestream
CODE:004FFFE7
CODE:004FFFEC 028 mov [ebp+handlestream], eax
CODE:004FFFEF 028 xor eax, eax ; Logical Exclusive OR
CODE:004FFFF1 028 push ebp
CODE:004FFFF2 02C push offset loc_50001D
CODE:004FFFF7 030 push dword ptr fs:[eax]
CODE:004FFFFA 034 mov fs:[eax], esp
CODE:004FFFFD 034 mov edx, esi ; a2
CODE:004FFFFF 034 mov eax, [ebp+handlestream] ; handlestream
CODE:00500002 034 call MD5_stream ; Call Procedure //关键call,跟进
CODE:00500002
CODE:00500007 034 xor eax, eax ; Logical Exclusive OR
CODE:00500009 034 pop edx
CODE:0050000A 030 pop ecx
CODE:0050000B 02C pop ecx
CODE:0050000C 028 mov fs:[eax], edx
CODE:0050000F 028 push offset loc_500024
CODE:0050000F
CODE:00500014
CODE:00500014 loc_500014: ; CODE XREF: MD5_File:loc_500022j
CODE:00500014 02C mov eax, [ebp+handlestream]
CODE:00500017 02C call System::TObject::Free(void) ; Call Procedure
CODE:00500017
CODE:0050001C 02C retn ; Return Near from Procedure
CODE:0050001C
CODE:0050001D ; —————————————————————————
CODE:0050001D
CODE:0050001D loc_50001D: ; DATA XREF: MD5_File+7Ao
CODE:0050001D ; CODE:off_6A002Eo
CODE:0050001D ; CODE:off_6D44E8o
CODE:0050001D 000 jmp unknown_libname_58 ; BDS 2005-2006 and Delphi6-7 Visual Component Library
CODE:0050001D
CODE:00500022 ; —————————————————————————
CODE:00500022
CODE:00500022 loc_500022: ; DATA XREF: CODE:off_70EEC4o
CODE:00500022 ; CODE:off_710794o
CODE:00500022 ; CODE:off_71232Co
CODE:00500022 ; CODE:off_712EDCo
CODE:00500022 02C jmp short loc_500014 ; Jump
CODE:00500022
CODE:00500024 ; —————————————————————————
CODE:00500024
CODE:00500024 loc_500024: ; CODE XREF: MD5_File+A4j
CODE:00500024 ; DATA XREF: MD5_File+97o
CODE:00500024 028 xor eax, eax ; Logical Exclusive OR
CODE:00500026 028 pop edx
CODE:00500027 024 pop ecx
CODE:00500028 020 pop ecx
CODE:00500029 01C mov fs:[eax], edx
CODE:0050002C 01C push offset loc_500042
CODE:0050002C
CODE:00500031
CODE:00500031 loc_500031: ; CODE XREF: MD5_File+C8j
CODE:00500031 020 mov eax, [ebp+hfile_dll]
CODE:00500034 020 push eax ; hObject
CODE:00500035 024 call CloseHandle ; Call Procedure
CODE:00500035
CODE:0050003A 020 retn ; Return Near from Procedure
CODE:0050003A
CODE:0050003B ; —————————————————————————
CODE:0050003B
CODE:0050003B loc_50003B: ; DATA XREF: MD5_File+5Ao
CODE:0050003B 000 jmp unknown_libname_58 ; BDS 2005-2006 and Delphi6-7 Visual Component Library
CODE:0050003B
CODE:00500040 ; —————————————————————————
CODE:00500040 020 jmp short loc_500031 ; Jump
CODE:00500040
CODE:00500042 ; —————————————————————————
CODE:00500042
CODE:00500042 loc_500042: ; CODE XREF: MD5_File+C2j
CODE:00500042 ; DATA XREF: MD5_File+B4o
CODE:00500042 01C pop esi
CODE:00500043 018 pop ebx
CODE:00500044 014 mov esp, ebp
CODE:00500046 004 pop ebp
CODE:00500047 000 retn ; Return Near from Procedure
CODE:00500047
CODE:00500047 MD5_File endp
跟进CALL MD5_stream.如下
引用:
CODE:00500048 MD5_stream proc near ; CODE XREF: MD5_File+8Ap
CODE:00500048
CODE:00500048 input = byte ptr -1068h
CODE:00500048 Context = dword ptr -68h
CODE:00500048 handlestreamstartpos= dword ptr -10h
CODE:00500048 handlestreamsize= dword ptr -0Ch
CODE:00500048 a2 = dword ptr -8
CODE:00500048 handlestream = dword ptr -4
CODE:00500048
CODE:00500048 000 push ebp
CODE:00500049 004 mov ebp, esp
CODE:0050004B
CODE:0050004B loc_50004B: ; DATA XREF: CODE:006E29D0o
CODE:0050004B ; CODE:006E59B0o
CODE:0050004B ; CODE:006EBB90o
CODE:0050004B ; CODE:006EBE3Co
CODE:0050004B ; CODE:006ED880o
CODE:0050004B 004 add esp, 0FFFFF004h ; Add
CODE:00500051 1000 push eax
CODE:00500052 1004 add esp, 0FFFFFF98h ; Add
CODE:00500055 106C push ebx
CODE:00500056 1070 push esi
CODE:00500057 1074 mov [ebp+a2], edx
CODE:0050005A 1074 mov [ebp+handlestream], eax
CODE:0050005D 1074 lea eax, [ebp+Context] ; Load Effective Address
CODE:00500060 1074 call MD5_INIT ; Call Procedure
CODE:00500060
CODE:00500065 1074 mov eax, [ebp+handlestream]
CODE:00500068 1074 mov edx, [eax]
CODE:0050006A 1074 call dword ptr [edx] ; Indirect Call Near Procedure
CODE:0050006A
CODE:0050006C 100C mov [ebp+handlestreamsize], eax
CODE:0050006F 100C mov eax, [ebp+handlestream]
CODE:00500072
CODE:00500072 loc_500072: ; DATA XREF: CODE:006A0278o
CODE:00500072 100C call Classes::TStream::GetPosition(void) ; Call Procedure
CODE:00500072
CODE:00500077 100C mov [ebp+handlestreamstartpos], eax
CODE:0050007A 100C xor esi, esi ; Logical Exclusive OR
CODE:0050007C 100C xor eax, eax ; Logical Exclusive OR
CODE:0050007E 100C push ebp
CODE:0050007F 1010 push offset loc_5000E1
CODE:00500084 1014 push dword ptr fs:[eax]
CODE:00500087 1018 mov fs:[eax], esp
CODE:0050008A 1018 xor ecx, ecx ; Logical Exclusive OR
CODE:0050008C 1018 xor edx, edx ; Logical Exclusive OR
CODE:0050008E 1018 mov eax, [ebp+handlestream]
CODE:00500091 1018 mov ebx, [eax]
CODE:00500093 1018 call dword ptr [ebx+14h] ; Indirect Call Near Procedure
CODE:00500093
CODE:00500096
CODE:00500096 loc_500096: ; CODE XREF: MD5_stream+7Cj
CODE:00500096 100C lea edx, [ebp+input] ; Load Effective Address
CODE:0050009C 100C mov ecx, 1000h
CODE:005000A1 100C mov eax, [ebp+handlestream]
CODE:005000A4 100C mov ebx, [eax]
CODE:005000A6 100C call dword ptr [ebx+0Ch] ; Indirect Call Near Procedure
CODE:005000A6
CODE:005000A9 100C mov ebx, eax
CODE:005000AB 100C add esi, ebx ; Add
CODE:005000AD 100C lea edx, [ebp+input] ; input
CODE:005000B3 100C lea eax, [ebp+Context] ; Context
CODE:005000B6 100C mov ecx, ebx ; len
CODE:005000B8 100C call MD5_update ; Call Procedure
CODE:005000B8
CODE:005000BD 100C test ebx, ebx ; Logical Compare
CODE:005000BF 100C jz short loc_5000C6 ; Jump if Zero (ZF=1)
CODE:005000BF
CODE:005000C1 100C cmp esi, [ebp+handlestreamsize] ; Compare Two Operands
CODE:005000C4 100C jnz short loc_500096 ; Jump if Not Zero (ZF=0)
CODE:005000C4
CODE:005000C6
CODE:005000C6 loc_5000C6: ; CODE XREF: MD5_stream+77j
CODE:005000C6 100C xor eax, eax ; Logical Exclusive OR
CODE:005000C8 100C pop edx
CODE:005000C9 1008 pop ecx
CODE:005000CA 1004 pop ecx
CODE:005000CB 1000 mov fs:[eax], edx
CODE:005000CE 1000 push offset loc_5000E8
CODE:005000CE
CODE:005000D3
CODE:005000D3 loc_5000D3: ; CODE XREF: MD5_stream+9Ej
CODE:005000D3 1004 xor ecx, ecx ; Logical Exclusive OR
CODE:005000D5 1004 mov edx, [ebp+handlestreamstartpos]
CODE:005000D8 1004 mov eax, [ebp+handlestream]
CODE:005000DB 1004 mov ebx, [eax]
CODE:005000DD 1004 call dword ptr [ebx+14h] ; Indirect Call Near Procedure
CODE:005000DD
CODE:005000E0 1004 retn ; Return Near from Procedure
CODE:005000E0
CODE:005000E1 ; —————————————————————————
CODE:005000E1
CODE:005000E1 loc_5000E1: ; DATA XREF: MD5_stream+37o
CODE:005000E1 000 jmp unknown_libname_58 ; BDS 2005-2006 and Delphi6-7 Visual Component Library
CODE:005000E1
CODE:005000E6 ; —————————————————————————
CODE:005000E6 1004 jmp short loc_5000D3 ; Jump
CODE:005000E6
CODE:005000E8 ; —————————————————————————
CODE:005000E8
CODE:005000E8 loc_5000E8: ; CODE XREF: MD5_stream+98j
CODE:005000E8 ; DATA XREF: MD5_stream+86o
CODE:005000E8 1000 lea edx, [ebp+Context] ; Load Effective Address
CODE:005000EB 1000 mov eax, [ebp+a2]
CODE:005000EE 1000 call MD5_final ; Call Procedure
CODE:005000EE
CODE:005000F3 1000 pop esi
CODE:005000F4 FFC pop ebx
CODE:005000F5 FF8 mov esp, ebp
CODE:005000F7 004 pop ebp
CODE:005000F8 000 retn ; Return Near from Procedure
CODE:005000F8
CODE:005000F8 MD5_stream endp
跟进这个函数里面的几个关键call,可以发现是个标准的md5函数。因此,至此我们可以知道CODE:007E7D30 054 call MD5_File ; Call Procedure
这行就是将dll文件打开,对其进行md5校验,获得md5值,保存。
接下来,我们继续最开始的部分进行分析
引用:
CODE:007E7D35 054 mov eax, ds:MD5result_dll
CODE:007E7D3A 054 mov eax, [eax]
CODE:007E7D3C 054 lea esi, [ebp+result] ; Load Effective Address //保存dll的md5结果
CODE:007E7D3F 054 mov edi, eax
CODE:007E7D41 054 movsd ; Move Byte(s) from String to String
CODE:007E7D42 054 movsd ; Move Byte(s) from String to String
CODE:007E7D43 054 movsd ; Move Byte(s) from String to String
CODE:007E7D44 054 movsd ; Move Byte(s) from String to String
CODE:007E7D45 054 mov eax, ds:bool_unknow
CODE:007E7D4A 054 mov byte ptr [eax], 0
CODE:007E7D4D 054 call sub_6B7910 ; Call Procedure
CODE:007E7D4D
CODE:007E7D52 054 test al, al ; Logical Compare
CODE:007E7D54 054 jz short loc_7E7D6B ; Jump if Zero (ZF=1)
CODE:007E7D54
CODE:007E7D56 054 mov eax, ds:pfilesize_plus_4
CODE:007E7D5B 054 cmp dword ptr [eax], 400h ; Compare Two Operands
CODE:007E7D61 054 jnb short loc_7E7D6B ; Jump if Not Below (CF=0)
CODE:007E7D61
CODE:007E7D63 054 mov eax, ds:bool_unknow
CODE:007E7D68 054 mov byte ptr [eax], 1
CODE:007E7D68
CODE:007E7D6B
CODE:007E7D6B loc_7E7D6B: ; CODE XREF: Readregfile+164j
CODE:007E7D6B ; Readregfile+171j
CODE:007E7D6B 054 mov eax, ds:pfilesize_plus_4
CODE:007E7D70 054 cmp dword ptr [eax], 400h ; Compare Two Operands
CODE:007E7D76 054 jnb short loc_7E7D7D ; Jump if Not Below (CF=0) keyfile大小不可小于0×400+4
CODE:007E7D76
CODE:007E7D78 054 call System::__linkproc__ Halt0(void) ; Call Procedure
CODE:007E7D78
CODE:007E7D7D ; —————————————————————————
CODE:007E7D7D
CODE:007E7D7D loc_7E7D7D: ; CODE XREF: Readregfile+186j
CODE:007E7D7D 054 push 0
CODE:007E7D7F 058 mov ecx, ds:pfilesize_plus_4
CODE:007E7D85 058 mov ecx, [ecx]
CODE:007E7D87 058 mov edx, ds:regfilecontent_nohead
CODE:007E7D8D 058 mov eax, ebx
CODE:007E7D8F 058 call System::__linkproc__ BlockRead(System::TFileRec &,void *,int,int &) ; Call Procedure //将keyfile文件内容的剩下部分读取到regfilecontent_nohead指向的区域。【也就是不包括开头4个字节的内容】
CODE:007E7D8F
CODE:007E7D94 054 call System::__linkproc__ _IOTest(void) ; Call Procedure
CODE:007E7D94
CODE:007E7D99 054 mov eax, ebx
CODE:007E7D9B 054 call System::__linkproc__ Close(System::TTextRec &) ; Call Procedure
CODE:007E7D9B
CODE:007E7DA0 054 call System::__linkproc__ _IOTest(void) ; Call Procedure
CODE:007E7DA0
CODE:007E7DA5 054 mov ebx, 0C8h
CODE:007E7DAA 054 mov eax, ds:regfilecontent_nohead
CODE:007E7DAF 054 mov edx, ds:buff
CODE:007E7DAF
CODE:007E7DB5
CODE:007E7DB5 loc_7E7DB5: ; CODE XREF: Readregfile+1DCj
CODE:007E7DB5 054 mov esi, eax
CODE:007E7DB7 054 mov edi, edx
CODE:007E7DB9 054 mov ecx, 20h
CODE:007E7DBE 054 rep movsd ; Move Byte(s) from String to String //
CODE:007E7DC0 054 add edx, 80h ; Add
CODE:007E7DC6 054 add eax, 80h ; Add
CODE:007E7DCB 054 dec ebx ; Decrement by 1
CODE:007E7DCC 054 jnz short loc_7E7DB5 ; Jump if Not Zero (ZF=0)
CODE:007E7DCC
CODE:007E7DCE 054 xor ebx, ebx ; Logical Exclusive OR
CODE:007E7DD0 054 mov ecx, ds:pfilesize_plus_4
CODE:007E7DD6 054 mov ecx, [ecx]
CODE:007E7DD8 054 mov eax, ecx
CODE:007E7DDA 054 sub eax, 1BE7h ; Integer Subtraction //这一部分用除法来校验keyfile大小不可为0x1be7 +4;
CODE:007E7DDF 054 push eax
CODE:007E7DE0 058 mov eax, 400h
CODE:007E7DE5 058 pop edx
CODE:007E7DE6 054 mov esi, edx
CODE:007E7DE8 054 cdq ; EAX -> EDX:EAX (with sign)
CODE:007E7DE9 054 idiv esi ; Signed Divide
CODE:007E7DEB 054 test eax, eax ; Logical Compare
CODE:007E7DED 054 jnz short loc_7E7DF0 ; Jump if Not Zero (ZF=0)
CODE:007E7DED
CODE:007E7DEF 054 inc ebx ; Increment by 1
CODE:007E7DEF
CODE:007E7DF0
CODE:007E7DF0 loc_7E7DF0: ; CODE XREF: Readregfile+1FDj
CODE:007E7DF0 054 mov eax, ds:pfilesize_plus_4
CODE:007E7DF5 054 mov eax, ecx
CODE:007E7DF7 054 sub eax, 1C43h ; Integer Subtraction //同理校验不可为0x1c43+4
CODE:007E7DFC 054 push eax
CODE:007E7DFD 058 mov eax, 400h
CODE:007E7E02 058 pop edx
CODE:007E7E03 054 mov esi, edx
CODE:007E7E05 054 cdq ; EAX -> EDX:EAX (with sign)
CODE:007E7E06 054 idiv esi ; Signed Divide
CODE:007E7E08 054 test eax, eax ; Logical Compare
CODE:007E7E0A 054 jnz short loc_7E7E0D ; Jump if Not Zero (ZF=0)
CODE:007E7E0A
CODE:007E7E0C 054 inc ebx ; Increment by 1
CODE:007E7E0C
CODE:007E7E0D
CODE:007E7E0D loc_7E7E0D: ; CODE XREF: Readregfile+21Aj
CODE:007E7E0D 054 mov eax, ds:pfilesize_plus_4
CODE:007E7E12 054 mov eax, ecx
CODE:007E7E14 054 sub eax, 1D2Fh ; Integer Subtraction //不可为0x1d2f+4
CODE:007E7E19 054 push eax
CODE:007E7E1A 058 mov eax, 400h
CODE:007E7E1F 058 pop edx
CODE:007E7E20 054 mov esi, edx
CODE:007E7E22 054 cdq ; EAX -> EDX:EAX (with sign)
CODE:007E7E23 054 idiv esi ; Signed Divide
CODE:007E7E25 054 test eax, eax ; Logical Compare
CODE:007E7E27 054 jnz short loc_7E7E2A ; Jump if Not Zero (ZF=0)
CODE:007E7E27
CODE:007E7E29 054 inc ebx ; Increment by 1
CODE:007E7E29
CODE:007E7E2A
CODE:007E7E2A loc_7E7E2A: ; CODE XREF: Readregfile+237j
CODE:007E7E2A 054 mov eax, ds:pfilesize_plus_4
CODE:007E7E2F 054 mov eax, ecx
CODE:007E7E31 054 sub eax, 21B6h ; Integer Subtraction //不可为0x21b6+4
CODE:007E7E36 054 push eax
CODE:007E7E37 058 mov eax, 400h
CODE:007E7E3C 058 pop edx
CODE:007E7E3D 054 mov esi, edx
CODE:007E7E3F 054 cdq ; EAX -> EDX:EAX (with sign)
CODE:007E7E40 054 idiv esi ; Signed Divide
CODE:007E7E42 054 test eax, eax ; Logical Compare
CODE:007E7E44 054 jnz short loc_7E7E47 ; Jump if Not Zero (ZF=0)
CODE:007E7E44
CODE:007E7E46 054 inc ebx ; Increment by 1
CODE:007E7E46
CODE:007E7E47
CODE:007E7E47 loc_7E7E47: ; CODE XREF: Readregfile+254j
CODE:007E7E47 054 mov eax, ds:pfilesize_plus_4
CODE:007E7E4C 054 mov eax, ecx
CODE:007E7E4E 054 sub eax, 20E0h ; Integer Subtraction //不可为0x20e0+4
CODE:007E7E53 054 push eax
CODE:007E7E54 058 mov eax, 400h
CODE:007E7E59 058 pop edx
CODE:007E7E5A 054 mov esi, edx
CODE:007E7E5C 054 cdq ; EAX -> EDX:EAX (with sign)
CODE:007E7E5D 054 idiv esi ; Signed Divide
CODE:007E7E5F 054 test eax, eax ; Logical Compare
CODE:007E7E61 054 jnz short loc_7E7E64 ; Jump if Not Zero (ZF=0)
CODE:007E7E61
CODE:007E7E63 054 inc ebx ; Increment by 1
CODE:007E7E63
CODE:007E7E64
CODE:007E7E64 loc_7E7E64: ; CODE XREF: Readregfile+271j
CODE:007E7E64 054 mov eax, ds:pfilesize_plus_4
CODE:007E7E69 054 mov eax, ecx
CODE:007E7E6B 054 sub eax, 2126h ; Integer Subtraction //不可为0×2126+4
CODE:007E7E70 054 push eax
CODE:007E7E71 058 mov eax, 400h
CODE:007E7E76 058 pop edx
CODE:007E7E77 054 mov esi, edx
CODE:007E7E79 054 cdq ; EAX -> EDX:EAX (with sign)
CODE:007E7E7A 054 idiv esi ; Signed Divide
CODE:007E7E7C 054 test eax, eax ; Logical Compare
CODE:007E7E7E 054 jnz short loc_7E7E81 ; Jump if Not Zero (ZF=0)
CODE:007E7E7E
CODE:007E7E80 054 inc ebx ; Increment by 1
CODE:007E7E80
CODE:007E7E81
CODE:007E7E81 loc_7E7E81: ; CODE XREF: Readregfile+28Ej
CODE:007E7E81 054 mov eax, ds:pfilesize_plus_4
CODE:007E7E86 054 mov eax, ecx
CODE:007E7E88 054 sub eax, 1DA7h ; Integer Subtraction //不可为0x1da7+4
CODE:007E7E8D 054 push eax
CODE:007E7E8E 058 mov eax, 400h
CODE:007E7E93 058 pop edx
CODE:007E7E94 054 mov esi, edx
CODE:007E7E96 054 cdq ; EAX -> EDX:EAX (with sign)
CODE:007E7E97 054 idiv esi ; Signed Divide
CODE:007E7E99 054 test eax, eax ; Logical Compare
CODE:007E7E9B 054 jnz short loc_7E7E9E ; Jump if Not Zero (ZF=0)
CODE:007E7E9B
CODE:007E7E9D 054 inc ebx ; Increment by 1
CODE:007E7E9D
CODE:007E7E9E
CODE:007E7E9E loc_7E7E9E: ; CODE XREF: Readregfile+2ABj
CODE:007E7E9E 054 mov eax, ds:pfilesize_plus_4
CODE:007E7EA3 054 mov eax, ecx
CODE:007E7EA5 054 sub eax, 1DABh ; Integer Subtraction //不可为0x1dab+4
CODE:007E7EAA 054 push eax
CODE:007E7EAB 058 mov eax, 400h
CODE:007E7EB0 058 pop edx
CODE:007E7EB1 054 mov esi, edx
CODE:007E7EB3 054 cdq ; EAX -> EDX:EAX (with sign)
CODE:007E7EB4 054 idiv esi ; Signed Divide
CODE:007E7EB6 054 test eax, eax ; Logical Compare
CODE:007E7EB8 054 jnz short loc_7E7EBB ; Jump if Not Zero (ZF=0)
CODE:007E7EB8
CODE:007E7EBA 054 inc ebx ; Increment by 1
CODE:007E7EBA
CODE:007E7EBB
CODE:007E7EBB loc_7E7EBB: ; CODE XREF: Readregfile+2C8j
CODE:007E7EBB 054 mov eax, ds:pfilesize_plus_4
CODE:007E7EC0 054 mov eax, ecx
CODE:007E7EC2 054 sub eax, 150Bh ; Integer Subtraction //不可为0x150b+4
CODE:007E7EC7 054 push eax
CODE:007E7EC8 058 mov eax, 400h
CODE:007E7ECD 058 pop edx
CODE:007E7ECE 054 mov esi, edx
CODE:007E7ED0 054 cdq ; EAX -> EDX:EAX (with sign)
CODE:007E7ED1 054 idiv esi ; Signed Divide
CODE:007E7ED3 054 test eax, eax ; Logical Compare
CODE:007E7ED5 054 jnz short loc_7E7ED8 ; Jump if Not Zero (ZF=0)
CODE:007E7ED5
CODE:007E7ED7 054 inc ebx ; Increment by 1
CODE:007E7ED7
CODE:007E7ED8
CODE:007E7ED8 loc_7E7ED8: ; CODE XREF: Readregfile+2E5j
CODE:007E7ED8 054 mov eax, ds:pfilesize_plus_4
CODE:007E7EDD 054 sub ecx, 2018h ; Integer Subtraction //不可为0×2018+4
CODE:007E7EE3 054 mov eax, 400h
CODE:007E7EE8 054 cdq ; EAX -> EDX:EAX (with sign)
CODE:007E7EE9 054 idiv ecx ; Signed Divide
CODE:007E7EEB 054 test eax, eax ; Logical Compare
CODE:007E7EED 054 jnz short loc_7E7EF0 ; Jump if Not Zero (ZF=0)
CODE:007E7EED
CODE:007E7EEF 054 inc ebx ; Increment by 1
CODE:007E7EEF
CODE:007E7EF0
CODE:007E7EF0 loc_7E7EF0: ; CODE XREF: Readregfile+2FDj
CODE:007E7EF0 054 mov eax, ds:pfilesize_plus_4
CODE:007E7EF5 054 mov eax, [eax]
CODE:007E7EF7 054 sub eax, 16E7h ; Integer Subtraction //不可为0x16e7+4
CODE:007E7EFC 054 push eax
CODE:007E7EFD 058 mov eax, 400h
CODE:007E7F02 058 pop edx
CODE:007E7F03 054 mov ecx, edx
CODE:007E7F05 054 cdq ; EAX -> EDX:EAX (with sign)
CODE:007E7F06 054 idiv ecx ; Signed Divide
CODE:007E7F08 054 test eax, eax ; Logical Compare
CODE:007E7F0A 054 jnz short loc_7E7F0D ; Jump if Not Zero (ZF=0)
CODE:007E7F0A
CODE:007E7F0C 054 inc ebx ; Increment by 1
CODE:007E7F0C
CODE:007E7F0D
CODE:007E7F0D loc_7E7F0D: ; CODE XREF: Readregfile+31Aj
CODE:007E7F0D 054 mov eax, ds:pfilesize_plus_4
CODE:007E7F12 054 mov eax, [eax]
CODE:007E7F14 054 sub eax, 1F54h ; Integer Subtraction //不可为0x1f54+4
CODE:007E7F19 054 push eax
CODE:007E7F1A 058 mov eax, 400h
CODE:007E7F1F 058 pop edx
CODE:007E7F20 054 mov ecx, edx
CODE:007E7F22 054 cdq ; EAX -> EDX:EAX (with sign)
CODE:007E7F23 054 idiv ecx ; Signed Divide
CODE:007E7F25 054 test eax, eax ; Logical Compare
CODE:007E7F27 054 jnz short loc_7E7F2A ; Jump if Not Zero (ZF=0)
CODE:007E7F27
CODE:007E7F29 054 inc ebx ; Increment by 1
CODE:007E7F29
CODE:007E7F2A
CODE:007E7F2A loc_7E7F2A: ; CODE XREF: Readregfile+337j
CODE:007E7F2A 054 cmp ebx, 0Fh ; Compare Two Operands
CODE:007E7F2D 054 jnz short loc_7E7F86 ; Jump if Not Zero (ZF=0)
CODE:007E7F2D
CODE:007E7F2F 054 mov eax, ds:bool_unknow
CODE:007E7F34 054 mov byte ptr [eax], 1
CODE:007E7F37 054 mov eax, ds:const1
CODE:007E7F3C 054 mov dword ptr [eax], 0CF1h
CODE:007E7F42 054 mov eax, ds:const2
CODE:007E7F47 054 mov dword ptr [eax], 0CE4h
CODE:007E7F4D 054 mov eax, ds:const3
CODE:007E7F52 054 mov dword ptr [eax], 0BFBh
CODE:007E7F58 054 mov eax, ds:const4
CODE:007E7F5D 054 mov dword ptr [eax], 0B83h
CODE:007E7F63 054 mov eax, ds:const5
CODE:007E7F68 054 mov dword ptr [eax], 0B6Ah
CODE:007E7F6E 054 mov eax, ds:const6
CODE:007E7F73 054 mov dword ptr [eax], 0D84h
CODE:007E7F79 054 mov eax, ds:const7
CODE:007E7F7E 054 mov dword ptr [eax], 8ABh
CODE:007E7F84 054 jmp short loc_7E7FDB ; Jump
CODE:007E7F84
CODE:007E7F86 ; —————————————————————————
CODE:007E7F86
CODE:007E7F86 loc_7E7F86: ; CODE XREF: Readregfile+33Dj
CODE:007E7F86 054 mov eax, ds:bool_unknow
CODE:007E7F8B 054 mov byte ptr [eax], 0
CODE:007E7F8E 054 mov eax, ds:const1
CODE:007E7F93 054 mov dword ptr [eax], 0C8Dh
CODE:007E7F99 054 mov eax, ds:const2
CODE:007E7F9E 054 mov dword ptr [eax], 0C80h
CODE:007E7FA4 054 mov eax, ds:const3
CODE:007E7FA9 054 mov dword ptr [eax], 0B97h
CODE:007E7FAF 054 mov eax, ds:const4
CODE:007E7FB4 054 mov dword ptr [eax], 0B1Fh
CODE:007E7FBA 054 mov eax, ds:const5
CODE:007E7FBF 054 mov dword ptr [eax], 0B06h
CODE:007E7FC5 054 mov eax, ds:const6
CODE:007E7FCA 054 mov dword ptr [eax], 0D20h
CODE:007E7FD0 054 mov eax, ds:const7
CODE:007E7FD5 054 mov dword ptr [eax], 847h
CODE:007E7FD5
CODE:007E7FDB
CODE:007E7FDB loc_7E7FDB: ; CODE XREF: Readregfile+394j
CODE:007E7FDB 054 xor eax, eax ; Logical Exclusive OR
CODE:007E7FDD 054 pop edx
CODE:007E7FDE 050 pop ecx
CODE:007E7FDF 04C pop ecx
CODE:007E7FE0 048 mov fs:[eax], edx
CODE:007E7FE3 048 jmp short loc_7E7FF4 ; Jump
CODE:007E7FE3
CODE:007E7FE5 ; —————————————————————————
CODE:007E7FE5
CODE:007E7FE5 loc_7E7FE5: ; DATA XREF: Readregfile+36o
CODE:007E7FE5 000 jmp System::__linkproc__ HandleAnyException(void) ; Jump
CODE:007E7FE5
CODE:007E7FEA ; —————————————————————————
CODE:007E7FEA 048 call System::__linkproc__ Halt0(void) ; Call Procedure
CODE:007E7FEA
CODE:007E7FEF ; —————————————————————————
CODE:007E7FEF 048 call System::__linkproc__ DoneExcept(void) ; Call Procedure
CODE:007E7FEF
CODE:007E7FF4
CODE:007E7FF4 loc_7E7FF4: ; CODE XREF: Readregfile+3F3j
CODE:007E7FF4 048 mov eax, ds:regfilecontent_nohead
CODE:007E7FF9 048 mov edx, ds:regfilecontent_nohead_2
CODE:007E7FFF 048 mov [edx], eax //将指向读取到的keyfile内容的指针的地址与另外一个全局变量关联
CODE:007E8001 048 mov eax, offset procname
CODE:007E8006 048 call System::__linkproc__ LStrClr(void *) ; Call Procedure //清空变量procname中的内容
CODE:007E8006
CODE:007E800B 048 mov ds:i, 1 //循环变量i,初始值1
CODE:007E800B
CODE:007E8015
CODE:007E8015 loc_7E8015: ; CODE XREF: Readregfile+489j
CODE:007E8015 048 mov eax, ds:pfilesize_plus_4
CODE:007E801A 048 mov eax, [eax]
CODE:007E801C 048 sub eax, 404h ; Integer Subtraction //*pfilesize_plus_4-0×404
CODE:007E8021 048 mov ecx, 4Eh //(*pfilesize_plus_4-0×404)%0x4e
CODE:007E8026 048 xor edx, edx ; Logical Exclusive OR
CODE:007E8028 048 div ecx ; Unsigned Divide
CODE:007E802A 048 mov eax, edx
CODE:007E802C 048 add eax, 180h ; Add //(*pfilesize_plus_4-0×404)%0x4e+0×180,记为offset
CODE:007E8031 048 xor edx, edx ; Logical Exclusive OR
CODE:007E8033 048 push edx
CODE:007E8034 04C push eax
CODE:007E8035 050 mov eax, ds:i
CODE:007E803A 050 cdq ; EAX -> EDX:EAX (with sign)
CODE:007E803B 050 add eax, [esp+4Ch+var_4C] ; Add
CODE:007E803E 050 adc edx, [esp+4Ch+var_48] ; Add with Carry
CODE:007E8042 050 add esp, 8 ; Add
CODE:007E8045 048 mov edx, ds:regfilecontent_nohead_2
CODE:007E804B 048 mov edx, [edx]
CODE:007E804D 048 movzx eax, byte ptr [edx+eax-1] ; Move with Zero-Extend //取*(*regfilecontent_nohead_2 + offset + i – 1)的内容
CODE:007E8052 048 lea ecx, [ebp+src] ; Load Effective Address //存入src
CODE:007E8055 048 mov edx, 2
CODE:007E805A 048 call Sysutils::IntToHex(int,int) ; Call Procedure //转为16进制表示的字符串
CODE:007E805A
CODE:007E805F 048 mov edx, [ebp+src] ; src
CODE:007E8062 048 mov eax, offset procname ; dest
CODE:007E8067 048 call System::__linkproc__ LStrCat(void) ; Call Procedure //附加到procname尾部
CODE:007E8067
CODE:007E806C 048 inc ds:i ; Increment by 1 //循环变量+1
CODE:007E8072 048 cmp ds:i, 7 ; Compare Two Operands //循环6次
CODE:007E8079 048 jnz short loc_7E8015 ; Jump if Not Zero (ZF=0)
CODE:007E8079
CODE:007E807B 048 mov eax, offset procname ; dest
CODE:007E8080 048 mov ecx, ds:procname ; src2
CODE:007E8086 048 mov edx, offset s->U_1 ; src1
CODE:007E808B 048 call System::__linkproc__ LStrCat3(void) ; Call Procedure //procname前面加上字符“u”
CODE:007E808B
CODE:007E8090 048 mov edx, ds:procname
CODE:007E8096 048 mov eax, offset s->F0cb0b439e0b ; “F0CB0B439E0B”
CODE:007E809B 048 call unknown_libname_76 ; BDS 2005-2006 and Delphi6-7 Visual Component Library
CODE:007E809B
CODE:007E80A0 048 test eax, eax ; Logical Compare
CODE:007E80A2 048 jz short loc_7E80B1 ; Jump if Zero (ZF=1)
CODE:007E80A2
CODE:007E80A4 048 mov eax, offset procname
CODE:007E80A9 048 call j_unknown_libname_75_0 ; Call Procedure
CODE:007E80A9
CODE:007E80AE 048 mov byte ptr [eax], 0FCh
CODE:007E80AE
CODE:007E80B1
CODE:007E80B1 loc_7E80B1: ; CODE XREF: Readregfile+4B2j
CODE:007E80B1 048 mov eax, ds:procname
CODE:007E80B6 048 call System::__linkproc__ LStrToPChar(System::AnsiString) ; Call Procedure
CODE:007E80B6
CODE:007E80BB 048 push eax ; lpProcName
CODE:007E80BC 04C mov eax, ds:off_80DF94
CODE:007E80C1 04C mov eax, [eax]
CODE:007E80C3 04C push eax ; hModule
CODE:007E80C4 050 call GetProcAddress ; Call Procedure //从dll中获得导出名为procname的函数的地址,由此可以看成keyfile中包含dll中某个关键函数的导出名信息。
CODE:007E80C4
CODE:007E80C9 048 mov edx, ds:u1E6B093FF0D8_funaddr
CODE:007E80CF 048 mov [edx], eax
CODE:007E80D1 048 mov eax, ds:procname
CODE:007E80D6 048 cmp byte ptr [eax], 0FCh ; Compare Two Operands
CODE:007E80D9 048 jnz short loc_7E80E0 ; Jump if Not Zero (ZF=0)
CODE:007E80D9
CODE:007E80DB 048 call System::__linkproc__ Halt0(void) ; Call Procedure
CODE:007E80DB
CODE:007E80E0 ; —————————————————————————
CODE:007E80E0
CODE:007E80E0 loc_7E80E0: ; CODE XREF: Readregfile+2Dj
CODE:007E80E0 ; Readregfile+4E9j
CODE:007E80E0 048 xor eax, eax ; Logical Exclusive OR
CODE:007E80E2 048 pop edx
CODE:007E80E3 044 pop ecx
CODE:007E80E4 040 pop ecx
CODE:007E80E5 03C mov fs:[eax], edx
CODE:007E80E8 03C push offset loc_7E810F
CODE:007E80E8
CODE:007E80ED
CODE:007E80ED loc_7E80ED: ; CODE XREF: Readregfile+51Dj
CODE:007E80ED 040 lea eax, [ebp+src] ; Load Effective Address
CODE:007E80F0 040 mov edx, 3
CODE:007E80F5 040 call System::__linkproc__ LStrArrayClr(void *,int) ; Call Procedure
CODE:007E80F5
CODE:007E80FA 040 lea eax, [ebp+var_10] ; Load Effective Address
CODE:007E80FD 040 mov edx, 4
CODE:007E8102 040 call System::__linkproc__ LStrArrayClr(void *,int) ; Call Procedure
CODE:007E8102
CODE:007E8107 040 retn ; Return Near from Procedure
CODE:007E8107
CODE:007E8108 ; —————————————————————————
CODE:007E8108
CODE:007E8108 loc_7E8108: ; DATA XREF: Readregfile+1Bo
CODE:007E8108 000 jmp unknown_libname_58 ; BDS 2005-2006 and Delphi6-7 Visual Component Library
CODE:007E8108
CODE:007E810D ; —————————————————————————
CODE:007E810D 040 jmp short loc_7E80ED ; Jump
CODE:007E810D
CODE:007E810F ; —————————————————————————
CODE:007E810F
CODE:007E810F loc_7E810F: ; CODE XREF: Readregfile+517j
CODE:007E810F ; DATA XREF: Readregfile+4F8o
CODE:007E810F 03C pop edi
CODE:007E8110 038 pop esi
CODE:007E8111 034 pop ebx
CODE:007E8112 030 mov esp, ebp
CODE:007E8114 004 pop ebp
CODE:007E8115 000 retn ; Return Near from Procedure
CODE:007E8115
CODE:007E8115 Readregfile endp
到这里,keyfile的读取,以及从中取出dll文件名的过程已经分析完了,接下来就是重头部分,keyfile中内容的校验了。
这里我们可以根据前面获得的两个与keyfile内容有关联的变量regfilecontent_nohead,regfilecontent_nohead_2进行定位
依次定位到以下这些对keyfile内容有校验的地方
引用:
CODE:0066E840 aboutform_create proc near
CODE:0066E840
CODE:0066E840 var_1C = dword ptr -1Ch
CODE:0066E840 var_18 = dword ptr -18h
CODE:0066E840 var_14 = dword ptr -14h
CODE:0066E840 var_10 = dword ptr -10h
CODE:0066E840 src = dword ptr -0Ch
CODE:0066E840 var_8 = dword ptr -8
CODE:0066E840 dest = byte ptr -4
CODE:0066E840
CODE:0066E840 000 push ebp
CODE:0066E841 004 mov ebp, esp
CODE:0066E843 004 xor ecx, ecx ; Logical Exclusive OR
CODE:0066E845 004 push ecx
CODE:0066E846 008 push ecx
CODE:0066E847 00C push ecx
CODE:0066E848 010 push ecx
CODE:0066E849 014 push ecx
CODE:0066E84A 018 push ecx
CODE:0066E84B 01C push ecx
CODE:0066E84C 020 push ebx
CODE:0066E84D 024 push esi
CODE:0066E84E 028 push edi
CODE:0066E84F 02C mov edi, eax
CODE:0066E851 02C xor eax, eax ; Logical Exclusive OR
CODE:0066E853 02C push ebp
CODE:0066E854 030 push offset loc_66EAB7
CODE:0066E859 034 push dword ptr fs:[eax]
CODE:0066E85C 038 mov fs:[eax], esp
CODE:0066E85F 038 mov eax, ds:pfilesize_plus_4
CODE:0066E864 038 mov eax, [eax]
CODE:0066E866 038 add eax, 8413h ; Add
CODE:0066E86B 038 sub eax, 404h ; Integer Subtraction
CODE:0066E870 038 mov edx, ds:Prandomseed //prandomseed这个变量是经过观察,确定为随机数函数的randomseed变量的指针。用于初始化随机数引擎
CODE:0066E876 038 mov [edx], eax
CODE:0066E878 038 mov eax, ds:pfilesize_plus_4
CODE:0066E87D 038 mov eax, [eax]
CODE:0066E87F 038 sub eax, 404h ; Integer Subtraction
CODE:0066E884 038 mov ecx, 12h
CODE:0066E889 038 xor edx, edx ; Logical Exclusive OR
CODE:0066E88B 038 div ecx ; Unsigned Divide
CODE:0066E88D 038 mov esi, edx //esi=(*pfilesize_plus_4 – 0x404u) % 0×12;记为offset1
CODE:0066E88F 038 mov ebx, esi
CODE:0066E891 038 test ebx, ebx ; Logical Compare
CODE:0066E893 038 jle short loc_66E8A2 ; Jump if Less or Equal (ZF=1 | SF!=OF)
CODE:0066E893
CODE:0066E895
CODE:0066E895 loc_66E895: ; CODE XREF: aboutform_create+60j
CODE:0066E895 038 mov eax, 100h ; ARange
CODE:0066E89A 038 call Random ; BDS 2005-2006 and Delphi6-7 Visual Component Library //计算随机数offset1次
CODE:0066E89A
CODE:0066E89F 038 dec ebx ; Decrement by 1
CODE:0066E8A0 038 jnz short loc_66E895 ; Jump if Not Zero (ZF=0)
CODE:0066E8A0
CODE:0066E8A2
CODE:0066E8A2 loc_66E8A2: ; CODE XREF: aboutform_create+53j
CODE:0066E8A2 038 mov ebx, 1
CODE:0066E8A7 038 lea eax, [ebp+dest] ; Load Effective Address
CODE:0066E8AA 038 call System::__linkproc__ LStrClr(void *) ; Call Procedure
CODE:0066E8AA
CODE:0066E8AF 038 test ebx, ebx ; Logical Compare
CODE:0066E8B1 038 jz short loc_66E8E9 ; Jump if Zero (ZF=1)
CODE:0066E8B1
CODE:0066E8B3
CODE:0066E8B3 loc_66E8B3: ; CODE XREF: aboutform_create+A7j
CODE:0066E8B3 038 inc esi ; Increment by 1
CODE:0066E8B4 038 mov eax, 100h ; ARange
CODE:0066E8B9 038 call Random ; BDS 2005-2006 and Delphi6-7 Visual Component Library //取随机数
CODE:0066E8B9
CODE:0066E8BE 038 mov ebx, eax
CODE:0066E8C0 038 mov eax, ds:regfilecontent_nohead
CODE:0066E8C5 038 movzx eax, byte ptr [eax+esi-1] ; Move with Zero-Extend //eax=*(regfilecontent_nohead + offset – 1)
CODE:0066E8CA 038 xor ebx, eax ; Logical Exclusive OR
CODE:0066E8CC 038 test ebx, ebx ; Logical Compare
CODE:0066E8CE 038 jz short loc_66E8E5 ; Jump if Zero (ZF=1)
CODE:0066E8CE
CODE:0066E8D0 038 lea eax, [ebp+src] ; dest
CODE:0066E8D3 038 mov edx, ebx ; source
CODE:0066E8D5 038 call IntToStr ; BDS 2005-2006 and Delphi6-7 Visual Component Library //转为16进制
CODE:0066E8D5
CODE:0066E8DA 038 mov edx, [ebp+src] ; src
CODE:0066E8DD 038 lea eax, [ebp+dest] ; dest
CODE:0066E8E0 038 call System::__linkproc__ LStrCat(void) ; Call Procedure //附加到字符串dest尾部,最终通过动态调试,确定这部分代码为从keyfile中获得注册用户名好显示在关于框中
CODE:0066E8E0
CODE:0066E8E5
CODE:0066E8E5 loc_66E8E5: ; CODE XREF: aboutform_create+8Ej
CODE:0066E8E5 038 test ebx, ebx ; Logical Compare
CODE:0066E8E7 038 jnz short loc_66E8B3 ; Jump if Not Zero (ZF=0)
CODE:0066E8E7
CODE:0066E8E9
CODE:0066E8E9 loc_66E8E9: ; CODE XREF: aboutform_create+71j
CODE:0066E8E9 038 mov eax, ds:pfilesize_plus_4
CODE:0066E8EE 038 mov eax, [eax]
CODE:0066E8F0 038 add eax, 8414h ; Add
CODE:0066E8F5 038 sub eax, 404h ; Integer Subtraction
CODE:0066E8FA 038 mov edx, ds:Prandomseed
CODE:0066E900 038 mov [edx], eax
CODE:0066E902 038 mov eax, ds:pfilesize_plus_4
CODE:0066E907 038 mov eax, [eax]
CODE:0066E909 038 sub eax, 404h ; Integer Subtraction
CODE:0066E90E 038 mov ecx, 17h
CODE:0066E913 038 xor edx, edx ; Logical Exclusive OR
CODE:0066E915 038 div ecx ; Unsigned Divide
CODE:0066E917 038 mov esi, edx
CODE:0066E919 038 mov ebx, esi
CODE:0066E91B 038 test ebx, ebx ; Logical Compare
CODE:0066E91D 038 jle short loc_66E92C ; Jump if Less or Equal (ZF=1 | SF!=OF)
CODE:0066E91D
CODE:0066E91F
CODE:0066E91F loc_66E91F: ; CODE XREF: aboutform_create+EAj
CODE:0066E91F 038 mov eax, 100h ; ARange
CODE:0066E924 038 call Random ; BDS 2005-2006 and Delphi6-7 Visual Component Library
CODE:0066E924
CODE:0066E929 038 dec ebx ; Decrement by 1
CODE:0066E92A 038 jnz short loc_66E91F ; Jump if Not Zero (ZF=0)
CODE:0066E92A
CODE:0066E92C
CODE:0066E92C loc_66E92C: ; CODE XREF: aboutform_create+DDj
CODE:0066E92C 038 mov ebx, 1
CODE:0066E931 038 lea eax, [ebp+var_10] ; Load Effective Address
CODE:0066E934 038 mov edx, dword ptr [ebp+dest]
CODE:0066E937 038 call System::__linkproc__ WStrFromLStr(System::WideString &,System::AnsiString) ; Call Procedure
CODE:0066E937
CODE:0066E93C 038 mov edx, [ebp+var_10]
CODE:0066E93F 038 mov eax, [edi+30Ch]
CODE:0066E945 038 call sub_4C3360 ; Call Procedure
CODE:0066E945
CODE:0066E94A 038 lea eax, [ebp+dest] ; Load Effective Address
CODE:0066E94D 038 call System::__linkproc__ LStrClr(void *) ; Call Procedure
CODE:0066E94D
CODE:0066E952 038 test ebx, ebx ; Logical Compare
CODE:0066E954 038 jz short loc_66E98C ; Jump if Zero (ZF=1)
CODE:0066E954
CODE:0066E956
CODE:0066E956 loc_66E956: ; CODE XREF: aboutform_create+14Aj
CODE:0066E956 038 inc esi ; Increment by 1
CODE:0066E957 038 mov eax, 100h ; ARange
CODE:0066E95C 038 call Random ; BDS 2005-2006 and Delphi6-7 Visual Component Library
CODE:0066E95C
CODE:0066E961 038 mov ebx, eax
CODE:0066E963 038 mov eax, ds:regfilecontent_nohead
CODE:0066E968 038 movzx eax, byte ptr [eax+esi+7Fh] ; Move with Zero-Extend
CODE:0066E96D 038 xor ebx, eax ; Logical Exclusive OR
CODE:0066E96F 038 test ebx, ebx ; Logical Compare
CODE:0066E971 038 jz short loc_66E988 ; Jump if Zero (ZF=1)
CODE:0066E971
CODE:0066E973 038 lea eax, [ebp+var_14] ; dest
CODE:0066E976 038 mov edx, ebx ; source
CODE:0066E978 038 call IntToStr ; BDS 2005-2006 and Delphi6-7 Visual Component Library
CODE:0066E978
CODE:0066E97D 038 mov edx, [ebp+var_14] ; src
CODE:0066E980 038 lea eax, [ebp+dest] ; dest
CODE:0066E983 038 call System::__linkproc__ LStrCat(void) ; Call Procedure //这部分代码最终确定为从keyfile中获得注册邮箱并显示。
之后的和窗体caption相关的代码就没贴了。
此为第一部分,keyfile中username和email的保存
再看第二部分
引用:
CODE:00501340 sub_501340 proc near ; CODE XREF: sub_7DB244+6Ep
CODE:00501340
CODE:00501340 var_8 = dword ptr -8
CODE:00501340 var_2 = byte ptr -2
CODE:00501340 var_1 = byte ptr -1
CODE:00501340 arg_0 = byte ptr 8
CODE:00501340
CODE:00501340 000 push ebp
CODE:00501341 004 mov ebp, esp
CODE:00501343 004 add esp, 0FFFFFFF8h ; Add
CODE:00501346 00C push ebx
CODE:00501347 010 push esi
CODE:00501348 014 push edi
CODE:00501349 018 mov [ebp+var_1], cl
CODE:0050134C 018 mov edi, edx
CODE:0050134E 018 mov esi, eax
CODE:00501350 018 mov eax, esi
CODE:00501352 018 mov edx, [eax]
CODE:00501354 018 call dword ptr [edx+4] ; Indirect Call Near Procedure
CODE:00501354
CODE:00501357 018 xor eax, eax ; Logical Exclusive OR
CODE:00501359 018 mov [ebp+var_8], eax
CODE:0050135C 018 mov eax, ds:pfilesize_plus_4
CODE:00501361 018 mov eax, [eax]
CODE:00501363 018 add eax, 8418h ; Add
CODE:00501368 018 sub eax, 404h ; Integer Subtraction
CODE:0050136D 018 mov ds:randomseed2, eax //初始化随机数引擎
CODE:00501372 018 mov ebx, 1 //初始化循环计数i
CODE:00501372
CODE:00501377
CODE:00501377 loc_501377: ; CODE XREF: sub_501340+78j
CODE:00501377 018 mov eax, 100h
CODE:0050137C 018 call random2 ; Call Procedure //计算随机数,结果记为r
CODE:0050137C
CODE:00501381 018 lea edx, [ebx+80h] ; Load Effective Address
CODE:00501387 018 mov ecx, ds:regfilecontent_nohead_2
CODE:0050138D 018 mov ecx, [ecx]
CODE:0050138F 018 movzx edx, byte ptr [ecx+edx-1] ; Move with Zero-Extend //edx=*(regfilecontent_nohead_2 + i + 128 – 1)
CODE:00501394 018 xor eax, edx ; Logical Exclusive OR //eax=*(regfilecontent_nohead_2 + i + 128 – 1)^r;
CODE:00501396 018 lea edx, [ebx+280h] ; Load Effective Address
CODE:0050139C 018 mov ecx, ds:regfilecontent_nohead_2
CODE:005013A2 018 mov ecx, [ecx]
CODE:005013A4 018 movzx edx, byte ptr [ecx+edx-1] ; Move with Zero-Extend //edx=*(regfilecontent_nohead_2 + i + 640 – 1)
CODE:005013A9 018 cmp eax, edx ; Compare Two Operands //比较eax,edx
CODE:005013AB 018 setnz al ; Set Byte if Not Zero (ZF=0)
CODE:005013AE 018 and eax, 7Fh ; Logical AND //取比较的结果的底八位
CODE:005013B1 018 add [ebp+var_8], eax ; Add
//将比较结果加到var_8上,即var_8+=((*(regfilecontent_nohead_2 + i + 128 – 1)^r)!=*(regfilecontent_nohead_2 + i + 640 – 1))&0x7f
CODE:005013B4 018 inc ebx ; Increment by 1
CODE:005013B5 018 cmp ebx, 7Dh ; Compare Two Operands
CODE:005013B8 018 jnz short loc_501377 ; Jump if Not Zero (ZF=0)
CODE:005013B8
CODE:005013BA 018 cmp [ebp+var_8], 0 ; Compare Two Operands //比较var_8。如果为假,则执行之后部分,否则跳过。由此可见,上一步的循环的每次计算结果都必须使((*(regfilecontent_nohead_2 + i + 128 – 1)^r)!=*(regfilecontent_nohead_2 + i + 640 – 1))为0.
CODE:005013BE 018 jnz loc_5014A4 ; Jump if Not Zero (ZF=0)
CODE:005013BE
CODE:005013C4 018 cmp [ebp+var_1], 0 ; Compare Two Operands
CODE:005013C8 018 jz short loc_50140B ; Jump if Zero (ZF=1)
CODE:005013C8
CODE:005013CA 018 mov al, [ebp+arg_0]
CODE:005013CD 018 mov [esi+10h], al
CODE:005013D0 018 cmp al, 9 ; Compare Two Operands
CODE:005013D2 018 jbe short loc_5013E0 ; Jump if Below or Equal (CF=1 | ZF=1)
CODE:005013D2
之后还有其他很多地方对keyfile内容有校验,零零总总加起来有差不多10几处。所以这里分析的时候就不一一贴出了。具体怎么校验的还是看keygen的代码吧。。。orz
【总结】
action script viewer是个典型的将注册信息分多个地方进行校验的软件,即使软件能正常打开,并显示注册正确,也有可能在运行时碰到暗桩。这类的注册验证方式极其猥琐。同时action script viewer的keyfile的生成,有如下规则
1、注册用户名(废话)
2、注册邮箱(废话)
3、asv5u.dll的某个重要的导出函数的函数名(所以asv的注册keyfile适合asv5u.dll一同发布的,虽然这个dll已经很久没更新过了)
4、给定用户名,邮箱,导出函数名,keyfile并不唯一,里面包含很多多余填充信息
5、keyfile的大小可以任意指定,只要满足开始的>1024+4的要求就行。另外我怀疑,每个版本的asv的keyfile的大小都是指定的,之后asv升级后通过keyfile大小的校验,禁止已经过期的注册用户的使用。
【结束语】
软件算法零零碎碎的地方太多,所以只贴了几个典型的地方,还有很多段没贴,大家有兴趣的看keygen代码吧。
1 2 3 4 5 6 7 | int __fastcall TForm1::myrandom(int range) { int result; myrandomseed=myrandomseed*0x8088405+1; result=(myrandomseed) * (unsigned __int64)range >> 32; return result; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | void __fastcall TForm1::Button1Click(TObject *Sender) { int filesize=0x1f58+10; filesize可以任意指定,满足校验要求即可 char buffer[0x1f58+10]; char option[]={'2','0','0','4','1','\0'}; memset(buffer,0,0x1f58+10); int i=filesize,j=1; myrandomseed=0; while (i) { //初始化 i--; buffer[i]=myrandom(0xff); } buffer[0]='\x41'; buffer[1]='\x53'; buffer[2]='\x56'; //写入sign buffer[3]='\x05'; buffer[4]='\x65'; buffer[5]='\xff'; buffer[6]='\x69'; buffer[((filesize-4-0x404)%0x4e+0x180)+4]='\x1e'; buffer[((filesize-4-0x404)%0x4e+0x180)+5]='\x6b'; buffer[((filesize-4-0x404)%0x4e+0x180)+6]='\x09'; buffer[((filesize-4-0x404)%0x4e+0x180)+7]='\x3f'; // 写入export function name,从dll中得出 buffer[((filesize-4-0x404)%0x4e+0x180)+8]='\xf0'; buffer[((filesize-4-0x404)%0x4e+0x180)+9]='\xd8'; //////////////////////////////////////////////////////////////////////////////// char *p; myrandomseed=filesize-4+0x8010-1; i=(filesize-4-0x404)%0x12; while(i) { myrandom(0x100); i--; } j=1; i=124; p=buffer+(filesize-4-0x404)%0x12+4; do { int randomresult=myrandom(0x100); if(Eusername->Text.Length()>=j) { *p=randomresult^ (*(byte *)(Eusername->Text.c_str()+j-1)); //写入用户名 }else{ *p=randomresult; } p++; j++; i--; }while(i); //////////////////////////////////////////////////////////////////////////////// myrandomseed=filesize-4+0x8010; i=(filesize-4-0x404)%0x17; while(i) { myrandom(0x100); i--; } j=1; i=112; p=buffer+(filesize-4-0x404)%0x17+128+4; do { int randomresult=myrandom(0x100); if(Eemail->Text.Length()>=j) { *p=randomresult^ (*(byte *)(Eemail->Text.c_str()+j-1)); //写入email }else{ *p=randomresult; } p++; j++; i--; }while(i); //////////////////////////////////////////////////////////////////////////////// myrandomseed=filesize-4+0x8011; i=(filesize-4-0x404)%0x4e; while(i) { myrandom(0x100); i--; } i=15; p=buffer+(filesize-4-0x404)%0x4e+255+4+1; j=0; while(i) { int randomresult=myrandom(0x100); if(j>24))^(myrandom(0x100)); *(p+1)=((byte)(crcresult>>16))^(myrandom(0x100)); *(p+2)=((byte)(crcresult>>8))^(myrandom(0x100)); *(p+3)=((byte)crcresult)^(myrandom(0x100)); kcount++; } int len=1024; p=buffer+4; crcresult=cal_crc(p,len); buffer[filesize-4]=((byte)(crcresult>>24))^1; buffer[filesize-4+1]=((byte)(crcresult>>16))^2; buffer[filesize-4+2]=((byte)(crcresult>>8))^3; buffer[filesize-4+3]=((byte)crcresult)^4; //////////////////////////////////////////////////////////////////////////////// p=NULL; TFileStream *temp=new TFileStream("D:\\Program Files\\flash tools\\ASV\\asv5.pke",fmCreate); temp->WriteBuffer(buffer,filesize); delete temp; } |
老师.能否送我一个ASV2009的注册码.谢谢
你好,找asv2009破解版的几天了这不现在还在找可惜都没找到.我还是个学生又没钱买个正版的,想用它来反编译两个swf来学习,还希望你能给注册码,或是破解版的。谢谢了。
@黑夜
抱歉,被人找到老家来了,不再提供~
再PS:新版我也么有
asv2009破解版 我找了很久也没找到咯 不知道老师有没 如果有的话就发我一份咯 先谢谢了
你好,能否给一份完整的注册机源码和程序我?谢谢。
@疯舞小子
注册机和程序你都要,是不是要上淘宝开店呢?
@疯舞小子
自己动手,丰衣足食
不是要去什么淘宝上开店哦,asv2010都已经出来了你认为我会拿asv6pre去卖钱?我自己也有asv2009正版哦,只不过想研究研究是怎么写的。。。。我用代码写不出来。。。调试的时候一堆错误。。。。
要asv2009可以保存版的去
http://share.zcool.com.cn/thread-77493-1-1.html
下载。
我已经放出来了呵呵。
呵呵,2009早已搞定,只是不方便放出而已
膜拜ing