首页
社区
课程
招聘
[译]SVK Protector Help(下)
2004-10-11 15:16 12824

[译]SVK Protector Help(下)

2004-10-11 15:16
12824
      终于更新完毕了!!从下午1:00一直到现在,7个小时啊,累!!!还有SVKP的Order&Support及FAQ我就不译了,说句实在话,想必SVKP作者的英语也... ^_*
译者:Cnbragon[TT]

这是接着上面一部分的,还有一点没有译,我会不断的更新。
译的不准确的地方请各位兄弟指出。多谢!


使用注册密钥

尽管这种方法需要在应用程序的源代码中做一些改变,但是整个实施的安全性却是最大程度的。除此之外
用这种方法还可以为应用程序创建安全的演示和试用版本。

程序中的一部分源代码被专用字符所标记。如果没有正解的注册密钥就不可能使用这部分代码(例如LOAD
和SAVE函数的处理过程).这些代码会被加密并且只有在用户有正确的注册密钥的时候才可以解码。

在给将被加密的代码作了标记和执行专用的API函数后,应该先编译应用程序。然后再用SVK Protector
来保护它。别忘了在SVK Protector中设置"使用注册密钥"这一项。SVK Protector会为你生成私钥,这个
私钥在工程配置文件中。

>>>警告:绝不能让其他人使用你的配置文件。它可能会被误用以生成错误的注册文件!
 
   这个密钥作用后会生成名为"regkey.key"的授权文件。这个授权文件必须和被保护的程序放在同一
个目录下。只有这样才可以注册程序,被加密的部分才能正确的解密。

>>>警告:如果程序没有先被SVK Protector所保护那么程序不能正解的启动。

使用硬件注册密钥

SVK Protector也提供给那些想使用为专门的计算机生成的专用密钥来注册的用户.这些密钥的优点是它们
不能被移植到其它的计算机上的事实并且即使它们被散发到互联网上也对保护没有任何威协。在生成密钥
之前,需要用户计算机的一些相关数据.

使用不同类型的保护

使用SVK Protector并改变程序的源代码来保护程序是最好的保护方法.尽管它在所有方法中是最花费时间
的,但是所有努力的结果是值得的。按照它的名称,它是不同保护类型的组合。它使用下列方法:API函数
注册密钥和硬件保护.

用于DLL及OCX文件

这个版本完全兼容DLL文件.现在它可以在DLL文件中使用以及所有类型的编码块(RSA,类型1,类型2和特性
块)和SVKP Alive Checks.
对于DLL文件的功保护有些规则必须遵守;否则被保护的程序不会发挥作用。
有两种使用被保护的DLL文件的方法:
1.每个使用了被保护的.DLL的.EXE文件(或者.DLL文件)必须也要用SVKP来保护。
2.如果不能保护.EXE文件,那么也就不能用正常的方法来调用DLL中的函数。
使用LoadLibraryA或者LoadLibraryW来替换DLL.使用GetProcAddress从被保护的程序中获得调用函数的
地址.使用了被保护的.DLL文件的程序不能使用标准的方法来调用任何函数,因为这些函数不在输入表中.
被保护的程序不能正常的运行,因为被保护的.DLL文件的输出表被加密了这样就没有正确的输出函数名了.

>>>说明:保护.OCX文件的功能还没有进行测试,因此我们不建议使用它来保护.ocx.

用法举例

对一个已编译应用程序的保护

创建一个用这个方法保护的应用程序根本不是问题。你所要做的只是启动SVK Protector填写
"Product Name"(产品名称)和"Version"(版本)两个空就可以了。这些参数是必须的但是最好
把它们填上,举个例子如果你同时也使用了功能限制的话.最后你需要填写"File name to protect
(要保护的文件名)"并且按"Protect!!(保护!!)"按钮或者从菜单中选择"Protect file(保护文件)".
如果一切都执行正确的话,在"Status Bar(状态栏)"会显示出"File was successfully protected
(文件已经被成功保护)"的通知.现在你可以从菜单中选择"Test Protected file(测试保护的文件)"
来测试被保护的应用程序了.

虽然整个过程只需要几分钟,但是对抗破解者攻击的程序保护程度另人很满意.

使用API函数来保护应用程序

  SVK Protector使用专门的API函数来和被保护程序的保护之间进行通信,这些API函数使用很简单,但是需要改变程序的源代码.special.dll文件不需要和被保护的程序一起发布.这个文件只是用来测试的;应用程序不需要它,SVK Protector可以把它的API函数转化为它的保护.

Sample:

ASM:
        .586
        .MMX
        .model flat,stdcall

include ..\..\Inc&Lib\apimacro.mac
include ..\..\Inc&Lib.inc
INCLUDELIB      ..\..\Inc&Lib\iKERNEL32.lib
INCLUDELIB      ..\..\Inc&Lib\iUSER32.lib

;there are defined include file and library for SVKP's special functions
include         ..\..\Inc&Lib\special.inc
INCLUDELIB      ..\..&Lib\ispecial.lib

.DATA?
registration_information db 255 dup (?)         ;buffer for registration information

.DATA
capture db "API functions example.",0
message db "Now I will try some API functions",0
registered db "Registration data from key:",0
unregistered db "Unregistered version!",0
unregistered_user db "Please register to www...",0

.code
assume          fs      :flat
Start:
;int 3                                          ;only for debug version
        push 0
        push offset capture
        push offset message
        push 0
        iWin32 MessageBoxA

;now we will check for debuggers
        iWin32 SVKP_KillDebugger

;then we will lock keyboard
        iWin32 SVKP_LockKeyboard

;now we will read registration information
        iWin32 SVKP_GetRegistrationInformation, offset registration_information
        test eax, eax
        jz   jmp_unregistered_user              ;if there is not registration key, jump

        push 0
        push offset registered
        push offset registration_information
        push 0
        iWin32 MessageBoxA

        jmp  back_to_win

jmp_unregistered_user:
;if you want to do special action for unregistered version, You can do it there.
        push 0
        push offset unregistered
        push offset unregistered_user
        push 0
        iWin32 MessageBoxA
;end of part for non registered users

skip_unregistered_part:
back_to_win:

;now we will unlock keyboard
        iWin32 SVKP_UnLockKeyboard

;end of program
        push -1
        iWin32 ExitProcess

end Start

VC:
#include <windows.h>
#include <io.h>
#include "..\..\Inc&Lib\special.h"
#pragma comment (lib,"SPECIAL")

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
        char *message = "SVKP's API functions example!";
        char* registration_information=(char*)malloc(255*sizeof(char));
        int flag;
       
        MessageBox(0,message,"",0);
       
        SVKP_KillDebugger();                // now we will check for debuggers

        SVKP_LockKeyboard();                // then we will lock keyboard

// if was registered flag=1  
        if(flag = SVKP_GetRegistrationInformation(registration_information)==0) {
// This is part for unregistered users               
                message = "Unregistered version!";               
                MessageBox(0,message,"",0);
        }
        else {
                message = "Registration data from key:";
                MessageBox(0,registration_information,message,0);     
        }
       
        SVKP_UnLockKeyboard();                // now we will unlock keyboard
        return 0;
}

Delphi:
unit main;

interface

procedure Start;

implementation

uses
  Registry,
  Classes,
  Windows,
  SysUtils,
  special;

var
  RegMessage : String;
  registration_information : String;

procedure Start;
begin
  try

    registration_information := '';
        SVKP_KillDebugger;          // now we will check for debuggers

    SVKP_LockKeyboard;          // then we will lock keyboard

    if SVKP_GetRegistrationInformation(registration_information)= 0 then
    begin
    // This is part for unregistered users
    RegMessage := 'Unregistered version!';
    MessageBox(0,PChar (RegMessage),'',0)
    end
    else
    begin
    // This is part for registered users
    RegMessage := 'Registration data from key:';
    MessageBox(0,PChar (registration_information),PChar (RegMessage),0);
    end;

    SVKP_UnLockKeyboard();    // now we will unlock keyboard

  except
  end;
end;
end.

VB:
Attribute VB_Name = "Module1"
Option Explicit

'There we declare SVKP's special functions'
Public Declare Function SVKP_GetRegistrationInformation Lib "SPECIAL.DLL" _
    (ByVal reginfoptr As String) As Long

Public Declare Function SVKP_LockKeyboard Lib "SPECIAL.DLL" _
    () As Long

Public Declare Function SVKP_UnLockKeyboard Lib "SPECIAL.DLL" _
    () As Long

Public Declare Function SVKP_KillDebugger Lib "SPECIAL.DLL" _
    () As Long

Sub Main()
Dim RegistrationInformation As String
Dim Flag As Boolean

'first we will lock keyboard'
SVKP_LockKeyboard

'now we will check for debuggers'
SVKP_KillDebugger

RegistrationInformation = String$(255, 0)
Flag = False
Flag = SVKP_GetRegistrationInformation(RegistrationInformation)
If Flag = True Then
MsgBox RegistrationInformation, vbInformation, "Registered Action!"
Else
MsgBox "Unregistered user!", vbInformation, "UnRegistered Action!"
End If

SVKP_UnLockKeyboard

End Sub

说明:参见"Examples/SVKP_api_functions"目录,那里有使用这个方法的例子.

不同类型保护的组合

这种保护方法一次组合使用了几种类型的保护.一个被保护的应用程序例如即可以使用API函数也
可以使用注册密钥等等的方法来保护.

Sample:

ASM:

        .586
        .MMX
        .model flat,stdcall

include ..\..\Inc&Lib\apimacro.mac
include ..\..\Inc&Lib\windows.inc
INCLUDELIB      ..\..\Inc&Lib.lib
INCLUDELIB      ..\..\Inc&Lib.lib

;there are defined include file and library for SVKP's special functions
include         ..\..\Inc&Lib.inc
INCLUDELIB      ..\..\Inc&Lib\ispecial.lib

.DATA?
registration_information db 255 dup (?)         ;buffer for registration information

.DATA
capture db "Encryption blocks example.",0
message db "Now I will try run encrypted block!",0

special_capture2 db "Message for unregistered users!",0
special_message2 db "You can buy our product at www....",0

.code
assume          fs      :flat
Start:
;int 3                                          ;only for debug version
        push 0
        push offset capture
        push offset message
        push 0
        iWin32 MessageBoxA

SVKP_ENCRYPTED_BLOCK_START                      ;start of encrypted block
;this code will encrypted and it will decrypted only if user have correct registration key
        push 0
        push offset special_capture
        push offset special_message
        push 0
        iWin32 MessageBoxA                      ;display message box for registered users

        jmp  skip_text
special_capture db "Message for registered users!",0
special_message db "This message box will show only if you have registered version!",0

skip_text:

SVKP_ENCRYPTED_BLOCK_END                        ;end of encrypted block

;now we will read registration information
        iWin32 SVKP_GetRegistrationInformation, offset registration_information
        test eax, eax
        jnz  skip_unregistered_part             ;if there is registration key, jump

;if you want to do special action for unregistered version, You can do it there.
        push 0
        push offset special_capture2
        push offset special_message2
        push 0
        iWin32 MessageBoxA
;end of part for non registered users

skip_unregistered_part:

        push -1
        iWin32 ExitProcess

end Start

VC:
#include <windows.h>
#include <io.h>
#include "...&Lib.h"
#pragma comment (lib,"SPECIAL")

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
        char *message = "Encryption blocks example!";
        char* registration_information=(char*)malloc(255*sizeof(char));
        int flag;

        MessageBox(0,message,"",0);
       
        SVKP_ENCRYPTED_BLOCK_START                //Start of encrypted block
// This code will encrypted and it will decrypted only if user have correct registration key

                message = "Registered version!";
                MessageBox(0,message,"",0);                // display message box for registered users

        SVKP_ENCRYPTED_BLOCK_END            // End of encrypted block       
       
// if was registered flag=1  
        if(flag = SVKP_GetRegistrationInformation(registration_information)==0) {
// This is part for unregistered users               
                message = "Unregistered version!";               
                MessageBox(0,message,"",0);
        }

        return 0;
}

Delphi:
unit main;

interface

procedure Start;

implementation

uses
  Registry,
  Classes,
  Windows,
  SysUtils,
  special;

var
  RegMessage : String;
// This procedure will encrypted and it will decrypted only if user have correctregistration key
procedure ActionForRegisteredUsers;
begin
    {$I include\delphi_svkp_block_begin.inc}
    RegMessage := 'Registered version!';
    MessageBox(0,PChar (RegMessage),'',0);
    {$I include\delphi_svkp_block_end.inc}
end;

procedure Start;
begin
  try

    RegMessage := 'Encryption blocks example';
    MessageBox(0,PChar (RegMessage),'',0);
    ActionForRegisteredUsers; // this procedure is only for registered users

  except
  end;
end;
end.

警告:不要在VB中使用这个方法!  

说明:在SVKP 的"Examples/Encrypted_blocks_RSA"目录下有使用这个方法的例子.

用特征保护
    在选择这个选项之前需要先在菜单中选择"Use registration keys(使用注册密钥)",因为这个
函数是建立在注册密钥使用的基础之上.在选择了这个选项后加密密钥就可用于单独的特性了.别忘
了这个函数的使用需要对被保护程序的源代码做一些调整.
    可以在程序中设置32个保护特性.对于每个特性都可以选择多个代码块,这些代码块被标记为
SVKP_ENCRYPTED_BLOCK_TYPEX_START和SVKP_ENCRYPTED_BLOCK_TYPEX_END,X代表特性的号码.举例
说明对于特性1#可以有100个代码块,这些代码块只能在注册文件中进行解锁.这看起来很复杂,但
是使用这个函数相当容易(请看例子).
    因此,标记单独特性的开始和结束并且编译代码足够了.在SVK Protector中选择"Use features
for license keys(给授权密钥使用特性)"选项并且按下按钮"Protect!!",这些可以保护这个应用
程序.
    当你为你的客户生成注册密钥的时候,选择特性,将在特性菜单中解锁(例如我们选择特性1和3)
选择的特性将解锁但其它的特性将被锁定。这使得处理消费者的区别相当容易.
    例子:
ASM:
        .586
        .MMX
        .model flat,stdcall

include ..\..\Inc&Lib\apimacro.mac
include ..\..\Inc&Lib\windows.inc
INCLUDELIB      ..\..\Inc&Lib.lib
INCLUDELIB      ..\..\Inc&Lib\iUSER32.lib

;there are defined include file and library for SVKP's special functions
include         ..\..\Inc&Lib\special.inc
INCLUDELIB      ..\..\Inc&Lib\ispecial.lib

.DATA?
registration_information db 255 dup (?)         ;buffer for registration information

.DATA
capture db "Features example.",0
message db "Now I will try run some features!",0

capture_feature1 db "Feature 1",0
message_feature1 db "Feature 1 is not enabled in license!",0

special_capture2 db "Message for unregistered users!",0
special_message2 db "You can buy our product at www....",0

feature1_unlocked_flag db 0

.code
assume          fs      :flat
Start:
;int 3                                          ;only for debug version
        push 0
        push offset capture
        push offset message
        push 0
        iWin32 MessageBoxA

SVKP_ENCRYPTED_FEATURE1_START                   ;start of feature 1
;this code will encrypted and it will decrypted only if user have correct registration key with this feature unlocked
        push 0
        push offset special_capture1
        push offset special_message1
        push 0
        iWin32 MessageBoxA                      ;display message box for registered users

        jmp  skip_text
special_capture1 db "Message for registered users!",0
special_message1 db "Feature 1 is unlocked in license!",0

skip_text:
        mov  [feature1_unlocked_flag], 1        ;set flag, because feature is unlocked in license
SVKP_ENCRYPTED_FEATURE1_END                     ;end of feature 1

        cmp  [feature1_unlocked_flag], 1
        jz   skip_unregistered_feature1

;display text for users with feature 1 not unlocked
        push 0
        push offset capture_feature1
        push offset message_feature1
        push 0
        iWin32 MessageBoxA

skip_unregistered_feature1:

;now we will read registration information
        iWin32 SVKP_GetRegistrationInformation, offset registration_information
        test eax, eax
        jnz  skip_unregistered_part             ;if there is registration key, jump

;if you want to do special action for unregistered version, You can do it there.
        push 0
        push offset special_capture2
        push offset special_message2
        push 0
        iWin32 MessageBoxA
;end of part for non registered users

skip_unregistered_part:

;action for users with Feature 2 activated
SVKP_ENCRYPTED_FEATURE2_START
        push 0
        push offset special_capture3
        push offset special_message3
        push 0
        iWin32 MessageBoxA                      ;display message box for registered users

        jmp  skip_text2
special_capture3 db "Message for registered users!",0
special_message3 db "Feature 2 is unlocked in license!",0

skip_text2:
SVKP_ENCRYPTED_FEATURE2_END

;is possible select more than one part of code for one feature
SVKP_ENCRYPTED_FEATURE1_START
        push 0
        push offset special_capture4
        push offset special_message4
        push 0
        iWin32 MessageBoxA                      ;display message box for registered users

        jmp  skip_text3
special_capture4 db "Message for registered users!",0
special_message4 db "Feature 1 second part of code!",0

skip_text3:
SVKP_ENCRYPTED_FEATURE1_END

        push -1
        iWin32 ExitProcess

end Start

VC:
#include <windows.h>
#include <io.h>
#include "..\..\Inc&Lib\special.h"
#pragma comment (lib,"SPECIAL")

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
        char *message = "Features example!";
        char* registration_information=(char*)malloc(255*sizeof(char));
        int flag;
       
        MessageBox(0,message,"Now I will try run some features!",0);
       
        SVKP_ENCRYPTED_FEATURE1_START                 // Start of feature 1
// this code will encrypted and it will decrypted only if user have correct registration key with this feature unlocked

                MessageBox(0,"Feature 1 is unlocked in license!","Message for registered users!",0);                // display message box for registered users

        SVKP_ENCRYPTED_FEATURE1_END         // end of feature 1
       
// if was registered flag=1  
        if(flag = SVKP_GetRegistrationInformation(registration_information)==0) {
// This is part for unregistered users               
                message = "Unregistered version!";               
                MessageBox(0,message,"",0);
        }

// action for users with Feature 2 activated
        SVKP_ENCRYPTED_FEATURE2_START

                MessageBox(0,"Feature 2 is unlocked in license!","Message for registered users!",0);                // display message box for registered users
       
        SVKP_ENCRYPTED_FEATURE2_END
       
// is possible select more than one part of code for one feature
        SVKP_ENCRYPTED_FEATURE1_START

                MessageBox(0,"Feature 1 second part of code!","Message for registered users!",0);                //display message box for registered users

        SVKP_ENCRYPTED_FEATURE1_END
       
        return 0;
}

Delphi:
unit main;

interface

procedure Start;

implementation

uses
  Registry,
  Classes,
  Windows,
  SysUtils,
  special;

var
  RegMessage : String;
procedure ActionForRegisteredUsers;
begin
// this code will encrypted and it will decrypted only if user have correct registration key with this feature unlocked
    {$I include\delphi_svkp_block_feature1_begin.inc}
    RegMessage := 'Feature 1 is unlocked in license!';
    MessageBox(0,PChar (RegMessage),'Message for registered users!',0);
    {$I include\delphi_svkp_block_feature1_end.inc}

// action for users with Feature 2 activated
    $I include_svkp_block_feature2_begin.inc
    RegMessage := 'Feature 2 is unlocked in license!';
    MessageBox(0,PChar (RegMessage),'Message for registered users!',0);
    {$I include\delphi_svkp_block_feature2_end.inc}

// is possible select more than one part of code for one feature
    $I include_svkp_block_feature1_begin.inc
    RegMessage := 'Feature 1 second part of code!';
    MessageBox(0,PChar (RegMessage),'Message for registered users!',0);
    {$I include\delphi_svkp_block_feature1_end.inc}

end;

procedure Start;
begin
  try

    RegMessage := 'Encryption blocks example';
    MessageBox(0,PChar (RegMessage),'',0);
    ActionForRegisteredUsers; //this procedure is only for registered users

  except
  end;
end;
end.

警告:在"Examples/Features/VB"目录下可以找到Visual Basic的例子!
说明:在SVKP 的"Examples/Features"目录下有使用这个方法的例子.

用时间限制保护

    使用SVK Protector可以快速和简单的为被保护的程序创建一个时间限制的试用版本.只要选
上"TimeLock"选项中的"Limited functional time of unregistered version of protected
program".然后选择时间限制的类型"执行次数"或者"天数".当然两个都可以选上."Number of
executions"选项是说未注册的版本可以使用多少次."Number of days"选项是说未注册的版本可以
使用多少天.
    除此这外你也可以使用"Reminder message",是说被保护的程序在每次启动的时候都会显示
"This is a shareware version.Please register your copy.".
    如果用户购买了被保护的程序并得到了正确的注册密钥,时间限制将被解除.

硬件锁定注册密钥
    可以为单个计算机生成特殊的注册密钥。为了这个目的在"Key protection"选项中有"Hardware
Id".
    首先选中使用硬件ID选项并且使用SVK Protector来对被保护的程序加密.然后需要生成特殊的
密钥.过程很相似.和普通的注册密钥一样填充"Registration information".别忘了填充"Hardware
ID".这个每个单一的计算机都不相同的数字可以在API 函数SVKP_GETHWInfo中获得.你的被保护的
程序可以在注册对话框或者关于对话框中显示这个数字.这仅取决于你.用户把这个数字发给你,然后
你用它来生成注册密钥.这个密钥只可以在这一台机子上使用.
    尽管"Check key"使用硬件ID的注册密钥,需要为特定的计算机输入正确的"硬件ID".否则不可能
检查这个密钥并且SVK Protector显示密钥错误.
    提示:在"Utilities/Display_HW_info"目录下有一个显示硬件ID并且保存到剪切版的程序.
    说明:硬件ID不能从密钥中得到,这也是为什么需要把每个密钥分开保存的原因.
Sample:

ASM:
        .586
        .MMX
        .model flat,stdcall

include ..\..\Inc&Lib\apimacro.mac
include ..\..\Inc&Lib\windows.inc
INCLUDELIB      ..\..\Inc&Lib\iKERNEL32.lib
INCLUDELIB      ..\..\Inc&Lib\iUSER32.lib

;there are defined include file and library for SVKP's special functions
include         ..\..\Inc&Lib\special.inc
INCLUDELIB      ..\..\Inc&Lib\ispecial.lib

.DATA?
registration_information db 255 dup (?)         ;buffer for registration information

HWInformation    dd 4 dup (?)

.DATA
special_message2 db "You can buy our product at www....",0dh,0dh
                 db "Please send us your Hardware ID:", 0dh, 0dh
hardware_key     db 32 dup (?)
hardware_key_end db 0dh,0dh,0dh
                 db "Your Hardware ID was copied to clipboard, please paste it to e-mail!",0dh
                 db "Now try to create registration key for this project and Hardware ID in SVKP.",0

capture db "Encryption blocks example.",0
message db "Now I will try run encrypted block!",0

special_capture2 db "Message for unregistered users!",0

allocated_memory dd 0
locked_mem       dd 0

.code
assume          fs      :flat
Start:
;int 3                                          ;only for debug version
        push 0
        push offset capture
        push offset message
        push 0
        iWin32 MessageBoxA

SVKP_ENCRYPTED_BLOCK_START                      ;start of encrypted block
;this code will encrypted and it will decrypted only if user have correct registration key
        push 0
        push offset special_capture
        push offset special_message
        push 0
        iWin32 MessageBoxA                      ;display message box for registered users

        jmp  skip_text
special_capture db "Message for registered users!",0
special_message db "This message box will show only if you have registered version!",0

skip_text:

SVKP_ENCRYPTED_BLOCK_END                        ;end of encrypted block

;now we will read registration information
        iWin32 SVKP_GetRegistrationInformation, offset registration_information
        test eax, eax
        jnz  skip_unregistered_part             ;if there is registration key, jump

;if you want to do special action for unregistered version, You can do it there.
        lea  esi, HWInformation
        iWin32 SVKP_GetHWInfo, esi

;        mov  esi, edi
        lea  edi, hardware_key
        lodsd
        call HexWrite32

        lodsd
        call HexWrite32

        lodsd
        call HexWrite32

        lodsd
        call HexWrite32

        push 0
        push offset special_capture2
        push offset special_message2
        push 0
        iWin32 MessageBoxA

        mov  byte ptr [hardware_key_end], 0

        iWin32 GlobalAlloc, 2002h, 32h
        mov  [allocated_memory], eax

        iWin32 GlobalLock, eax
        mov  [locked_mem], eax

        iWin32 lstrcpy, eax, offset hardware_key

        iWin32 GlobalUnlock, dword ptr [allocated_memory]

        iWin32 OpenClipboard, NULL

        iWin32 EmptyClipboard

        iWin32 SetClipboardData, 1, dword ptr [allocated_memory]

        iWin32 CloseClipboard
;end of part for non registered users

skip_unregistered_part:

        push -1
        iWin32 ExitProcess

HexWrite8  proc
        mov  ah, al
        and  al, 0fh
        shr  ah, 4
        or   ax, 3030h
        xchg al, ah
        cmp  ah, 39h
        ja   @@4
@@1:
        cmp  al, 39h
        ja   @@3
@@2:
        stosw
        ret
@@3:
        sub  al, 30h
        add  al,'A' - 10
        jmp  @@2
@@4:
        sub  ah, 30h
        add  ah, 'A' - 10
        jmp  @@1

HexWrite8      endp

HexWrite16  proc
        push ax
        xchg al, ah
        call HexWrite8
        pop  ax
        call HexWrite8
        ret
HexWrite16  endp

HexWrite32  proc
        push eax
        shr  eax, 16
        call HexWrite16
        pop  eax
        call HexWrite16
        ret
HexWrite32  endp

end Start

VC:
#include <windows.h>
#include <io.h>
#include "..\..\Inc&Lib\special.h"
#pragma comment (lib,"SPECIAL")

void TraslateToASCII(char* hardware_key, char* HWInformation)
{
        __asm{
        mov  esi, HWInformation
                mov  edi, hardware_key
        lodsd
        call HexWrite32

        lodsd
        call HexWrite32

        lodsd
        call HexWrite32

        lodsd
        call HexWrite32                
                jmp  endik

HexWrite32:               
        push eax
        shr  eax, 16
        call HexWrite16
        pop  eax
        call HexWrite16
        ret

HexWrite16:
        push ax
        xchg al, ah
        call HexWrite8
        pop  ax
        call HexWrite8
        ret

HexWrite8:
        mov  ah, al
        and  al, 0fh
        shr  ah, 4
        or   ax, 3030h
        xchg al, ah
        cmp  ah, 39h
        ja   a4
a1:
        cmp  al, 39h
        ja   a3
a2:
        stosw
        ret
a3:
        sub  al, 30h
        add  al,'A' - 10
        jmp  a2
a4:
        sub  ah, 30h
        add  ah, 'A' - 10
        jmp  a1

endik:
        }
}

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
        char *message = "Encryption blocks example!";
        char* registration_information=(char*)malloc(255*sizeof(char));
        char* HWInformation=(char*)malloc(20*sizeof(char));
        int flag;
        char* unregister_message=(char*)malloc(255*sizeof(char));
        char* hardware_key=(char*)malloc(35*sizeof(char));
        char *first_message="You can buy our product at www....";
        char *second_message="Please send us your Hardware ID:";
        char *third_message="Your Hardware ID was copied to clipboard, please paste it to e-mail";
        char *fourth_message="Now try to create registration key for this project and Hardware ID in SVKP.";
        LPVOID allocated_memory;
        LPVOID locked_mem;

        MessageBox(0,message,"",0);

        SVKP_ENCRYPTED_BLOCK_START                // Start of encrypted block
// This code will encrypted and it will decrypted only if user have correct registration key

                message = "Registered version!";
                MessageBox(0,message,"",0);                // display message box for registered users

        SVKP_ENCRYPTED_BLOCK_END            // End of encrypted block       
       
// if was registered flag=1  
        if(flag = SVKP_GetRegistrationInformation(registration_information)==0) {
// This is part for unregistered users               
                message = "Unregistered version!";               
// Get Hardware ID
                SVKP_GetHWInfo(HWInformation);
// Prepare message for display               
                TraslateToASCII(hardware_key,HWInformation);
                TraslateToASCII(hardware_key+8,HWInformation+4);
                TraslateToASCII(hardware_key+16,HWInformation+8);
                TraslateToASCII(hardware_key+24,HWInformation+12);
                hardware_key[32]=0x0d;
                hardware_key[33]=0x0d;
                hardware_key[34]=0x00;
                unregister_message=first_message;
                lstrcat(unregister_message,second_message);
                lstrcat(unregister_message,hardware_key);
                lstrcat(unregister_message,third_message);
                lstrcat(unregister_message,fourth_message);
               
// display message               
                MessageBox(0,unregister_message,message,0);

// copy Hardware ID to clipboard
                hardware_key[32]=0x00;
                allocated_memory=GlobalAlloc(0x2002, 0x32);
                locked_mem=GlobalLock(allocated_memory);
                lstrcpy((char*)locked_mem,hardware_key);
                GlobalUnlock(allocated_memory);
                OpenClipboard(NULL);
                EmptyClipboard();
                SetClipboardData(1,allocated_memory);
                CloseClipboard();
        }
        return 0;
}

Delphi:
function TraslateToHex(Buf:pchar; sz:integer):string;
var I:integer;
var D:integer;
var M:integer;
begin
  result:='';
  M:=0;
  for I:=0 to sz-1 do
  begin
        M:=I*4;
        for D:=3 downto 0 do result:=result+IntToHex(ord(Buf[D+M]),2);
  end;
end;

procedure CopyToClipboard(const s:string);
var m:dword;
begin
  m:=GlobalAlloc(GMEM_MOVEABLE or GMEM_DDESHARE,length(s)+1);
  lstrcpy(GlobalLock(m),pchar(s));
  GlobalUnlock(m);
  OpenClipboard(0);
  EmptyClipboard;
  SetClipboardData(cf_text,m);
  CloseClipboard;
end;

procedure Test;
var
  hardware_key,unregistered_msg:string;
  registration_info,HWInformation:array[0..255] of char;
begin
  messagebox(0,'Encryption blocks example!','',0);
  {$I .\include\delphi_svkp_block_begin.inc}  // Start of encrypted block

  // Code inside this block will be decrypted only for users with valid registration key
  messagebox(0,'Registered version!','',0);   // a message for registered users
  // Add here an useful code available only for registered users...

  {$I .\include\delphi_svkp_block_end.inc}    //End of encrypted block

  if SVKP_GetRegistrationInformation(registration_info)<>1 then begin
    // This is part for unregistered users
    SVKP_GetHWInfo(HWInformation); //Get Hardware ID
    hardware_key:=TraslateToHex(HWInformation,4);
    unregistered_msg:=
     'You can buy our product at www...'#10#10+
     'Please send us your Hardware ID:'#10+hardware_key+#10#10+
     'Your Hardware ID was copied to clipboard, please paste it to e-mail'#10#10+
     'Now try to create registration key for this project and Hardware ID in SVKP.';
    messagebox(0,pchar(unregistered_msg),'Unregistered version!',0);
    CopyToClipboard(hardware_key); //copy Hardware ID to clipboard
  end;
end;

begin
  Test;
end.

说明:在SVKP 的"Examples/HW_locked"目录下有使用这个方法的例子.

分组加密类型1和类型2
    这些分组和RSA分组很相似.也是加密程序中的一部分,但是不像RSA分组,它们不依赖于密钥。
意思是说不管是注册的还是未注册的版本都是在使用这部分代码的时候才解码.看起来这个函数不
吸引人,但事实不是如此.现在保护程序不被内存转储很困难。确切的说这个函数可以避免对程序
的内存转储。
    分组加密类型1
      第一种分组类型在使用之前开始解码并且在使用完之后再进行加密。整个解码和加密的过程
    很快因此很容易解决经常使用的函数。推荐在关键代码处使用这个类型,比如检测注册或者
    需要保护的代码处(例如所知道如何做的地方).
    加密分组类型2
      第二咱分组类型在使用之前开始解码并在使用之后从内存中删除.这也是为什么要仔细地选择
    需要保护的代码的原因。必须意识到这个分组只能启动一次。推荐在代码的初始化部分中使用
    这种分组类型。这样转储程序就不会起作用了。
警告:
1.不要递归调用被加密的分组。
2.不要使用try...finally来包含分组...(Delphi)
3.不要在加密分组中调用Exit或者Abort

Sample:

ASM:
        .586
        .MMX
        .model flat,stdcall

include ..\..\Inc&Lib\apimacro.mac
include ..\..\Inc&Lib\windows.inc
INCLUDELIB      ..\..\Inc&Lib\iKERNEL32.lib
INCLUDELIB      ..\..\Inc&Lib\iUSER32.lib

;there are defined include file and library for SVKP's special functions
include         ..\..\Inc&Lib\special.inc
INCLUDELIB      ..\..\Inc&Lib\special.lib

.DATA?
registration_information db 255 dup (?)         ;buffer for registration information

.DATA
capture db "Encryption blocks example.",0
message db "Now I will try run encrypted block!",0

special_capture2 db "Message for unregistered users!",0
special_message2 db "You can buy our product at www....",0

.code
assume          fs      :flat
Start:
;int 3                                          ;only for debug version

;this code will decrypted before using and after use removed
;tip: This type of blocks is very good use in initialize part of program
;(load DLL(s), initialize data, fill some special variables and etc.)
SVKP_ENCRYPTED_BLOCK_TYPE2_START
        push 0
        push offset capture
        push offset message
        push 0
        iWin32 MessageBoxA
SVKP_ENCRYPTED_BLOCK_TYPE2_END

SVKP_ENCRYPTED_BLOCK_START                      ;start of encrypted block RSA
;this code will encrypted and it will decrypted only if user have correct registration key
        push 0
        push offset special_capture
        push offset special_message
        push 0
        iWin32 MessageBoxA                      ;display message box for registered users

        jmp  skip_text
special_capture db "Message for registered users!",0
special_message db "This message box will show only if you have registered version!",0

skip_text:

SVKP_ENCRYPTED_BLOCK_END                        ;end of encrypted block

;This code will decrypted before using and encrypted again after use
SVKP_ENCRYPTED_BLOCK_TYPE1_START
;now we will read registration information
        iWin32 SVKP_GetRegistrationInformation, offset registration_information
        test eax, eax
        jnz  skip_unregistered_part             ;if there is registration key, jump

;if you want to do special action for unregistered version, You can do it there.
        push 0
        push offset special_capture2
        push offset special_message2
        push 0
        iWin32 MessageBoxA

;end of part for non registered users
skip_unregistered_part:
SVKP_ENCRYPTED_BLOCK_TYPE1_END

        push -1
        iWin32 ExitProcess

end Start

VC:
#include <windows.h>
#include <io.h>
#include "..\..\Inc&Lib\special.h"
#pragma comment (lib,"SPECIAL")

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
        char *message = "Encryption blocks example!";
        char* registration_information=(char*)malloc(255*sizeof(char));
        int flag;

// this code will decrypted before using and after use removed
// tip: This type of blocks is very good use in initialize part of program
// (load DLL(s), initialize data, fill some special variables and etc.)       
        SVKP_ENCRYPTED_BLOCK_TYPE2_START
        MessageBox(0,message,"",0);
        SVKP_ENCRYPTED_BLOCK_TYPE2_END

        SVKP_ENCRYPTED_BLOCK_START                // Start of encrypted block
// This code will encrypted and it will decrypted only if user have correct registration key
                message = "Registered version!";
                MessageBox(0,message,"",0);                // display message box for registered users

        SVKP_ENCRYPTED_BLOCK_END            // End of encrypted block       
       
// This code will decrypted before using and encrypted again after use
        SVKP_ENCRYPTED_BLOCK_TYPE1_START
// if was registered flag=1  
        if(flag = SVKP_GetRegistrationInformation(registration_information)==0) {
                // This is part for unregistered users               
                message = "Unregistered version!";               
                MessageBox(0,message,"",0);
        }
        SVKP_ENCRYPTED_BLOCK_TYPE1_END

        return 0;
}

Delphi:
unit main;

interface

procedure Start;

implementation

uses
  Registry,
  Classes,
  Windows,
  SysUtils,
  special;

var
  RegMessage : String;
// This procedure will encrypted and it will decrypted only if user have correct registration key
procedure ActionForRegisteredUsers;
begin
    {$I include\delphi_svkp_block_begin.inc}
    RegMessage := 'Registered version!';
    MessageBox(0,PChar (RegMessage),'',0);
    {$I include\delphi_svkp_block_end.inc}
end;

procedure Start;
begin
  try

// this code will decrypted before using and after use removed
// tip: This type of blocks is very good use in initialize part of program
// (load DLL(s), initialize data, fill some special variables and etc.)
    {$I include\delphi_svkp_block_type2_begin.inc}
    RegMessage := 'Encryption blocks example';
    {$I include\delphi_svkp_block_type2_end.inc}

// This code will decrypted before using and encrypted again after use
    {$I include\delphi_svkp_block_type1_begin.inc}
    MessageBox(0,PChar (RegMessage),'',0);
    ActionForRegisteredUsers; //this procedure is only for registered users
    {$I include\delphi_svkp_block_type1_end.inc}
  except
  end;
end;
end

注意:不要在Visual Basic中使用此方法!
说明:在SVKP 的"Examples/Encrypted_blocks_Type1&Type2"目录下有使用这个方法的例子.

实时控制检查
    你可以给你的程序加上实时控制,这是一个极好的附加保护,它可以检测是否有人正在试图
清除SVK Protector的保护.你只需要在你的程序中加一些简单的宏就可以了(和使用加密块一样的)
例如SVKP_ALIVE_CHECK_1.在svk protector保护程序之后,实时控制将会被插入以替代这些宏。
推荐把这些控制插在那些随机启动或者很少使用的模块中,因为这会加大破解者查找这些控制的
难度.
    可以使用两种检查类型:
    SVKP_ALIVE_CHECK_1 假如SVKP已被从程序中清除,那么寄存器EAX, EBX, ECX, EDX, ESI, EDI,
                       EBP将变成0并且ESP寄存器将会包含和检查前不同的值.

    SVKP_ALIVE_CHECK_2 假如SVKP已被从程序中清除那么ESP寄存器将会包含和检查前不同的值.

Sample:

ASM:
        .586
        .MMX
        .model flat,stdcall

include ..\..\Inc&Lib\apimacro.mac
include ..\..\Inc&Lib\windows.inc
INCLUDELIB      ..\..\Inc&Lib\iKERNEL32.lib
INCLUDELIB      ..\..\Inc&Lib\iUSER32.lib

; There are defined include file and library for SVKP's special functions
include         ..\..\Inc&Lib\special.inc
INCLUDELIB      ..\..\Inc&Lib\ispecial.lib

.DATA?
registration_information db 255 dup (?)         ;buffer for registration information

.DATA
capture db "Alive Checks example.",0
message db "Now I will try run some checks!",0

capture2 db "SVKP is alive!",0
message2 db "SVKP protection was not removed!",0

.code
assume          fs      :flat
Start:
;int 3                                          ;only for debug version
        push 0
        push offset capture
        push offset message
        push 0
        iWin32 MessageBoxA

; Don't forget use these checks random or in not very offen used procedures!
SVKP_ALIVE_CHECK_1
SVKP_ALIVE_CHECK_2

        push 0
        push offset capture2
        push offset message2
        push 0
        iWin32 MessageBoxA

        push -1
        iWin32 ExitProcess

end Start

VC:
#include <windows.h>
#include <io.h>
#include "..\..\Inc&Lib\special.h"
#pragma comment (lib,"SPECIAL")

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow)
{
        char *message = "Now I will try run some checks!";
       
        MessageBox(0,message,"Alive Checks example.",0);
       
// Don't forget use these checks random or in not very offen used procedures!
        SVKP_ALIVE_CHECK_1
        SVKP_ALIVE_CHECK_2

        MessageBox(0,"SVKP protection was not removed!","SVKP is alive!",0);

        return 0;}

Delphi:
unit main;

interface

procedure Start;

implementation

uses
  Registry,
  Classes,
  Windows,
  SysUtils,
  special;

var
  RegMessage : String;

procedure Start;
begin
  try

    RegMessage := 'Now I will try run some checks!';
    MessageBox(0,PChar (RegMessage),'Alive Checks example.',0);

// Don't forget use these checks random or in not very offen used procedures!

    $I include_svkp_alive_check_1.inc
    $I include_svkp_alive_check_2.inc

    RegMessage := 'SVKP protection was not removed!';
    MessageBox(0,PChar (RegMessage),'SVKP is alive!',0);

  except
  end;
end;
end.

说明:在SVKP 的"Examples/SVKP_Checks"目录下有使用这个方法的例子.

命令行特性
    为了自动运行工程和在处理完文件后自选退出,你可以使用如下的SVK Protector命令行参数
    Svkp.exe name_of_project_file.svkp

    例子:
    c:\program files\svkp\svkp.exe c:\program files\svkp\examples\Advanced_TimeLock.\dialog_example.svkp

    因为工程文件不能编辑,所以可以在保护你的程序之前自动完成不同的设置(比如如果压缩将被或者
将不被使用那么SVKP_USE_COMPRESS=YES或者SVKP_USE_COMPRESS=NO)或者编辑SVK Protector显示的文本.

用户注册密钥生成
    为了使生成注册密钥的过程自动化,你必须使用一个特定的DLL--SVKP_DLL.DLL.这个文件被SVKP
所保护,因此和其它授权文件的使用条件是一样的.详细的信息可以在使用DLL&OCX文件这一节中找到.
    标准用户可以使用以下函数:
描述:
    这个函数返回SVKP的版本.
函数原型:
VOID XX33(VOID)
返回值:
    这个函数返回SVKP的版本参数值

XX34关联SVKP_Initialize_DLL

描述:
这个函数初始DLL.需要在初始的开始调用这个函数.

原型:
VOID XX34(VOID)

返回值:
1=一切顺利
-1=装载RSA加密DLL出现问题
-33=异常错误

XX33关联SVKP_Free_DLL

描述:
这个函数清空缓冲并初始化内存.

原型:
VOID XX35(VOID)

返回值:
这个函数没有返回参数.

XX37关联SVKP_Load_RSA_keys

描述:
这个函数从工程文件中装载RSA密钥.

原型:
BOOL XX37(
LPCTSTR lpProjectFile    //工程名的地址
);

参数:
lpProjectFile
指向一个以空结尾的字符串,指定了工程名.

返回值:
1=一切顺利
-1=读取公钥出现问题
-2=读取私钥出现问题
-3=从工程文件中读取密钥出现问题
-33=异常错误

XX38关联SVKP_Generate_license_key

描述:
这个函数在内存中生成授权

原型:
BOOL XX38(
LPCTSTR lpRegInformation,   //注册信息指针
DWORD nRegInformationSize,  //注册信息长度
LPCTSTR lpHWInformation,    //硬件信息指针
LPCTSTR lpTimeExpirationData, //时间到期数据指针
DWORD Unknown               //没有使用的参数
);

参数:
lpRegInformation
指向注册信息文本
nRegInformationSize
以字节为单位的注册信息的大小
lpHWInformation
指向为硬件锁定授权的硬件信息.这个参数可以为空.
lpTimeExpirationData
指向为时间限制授权的时间到期信息.格式dd/mm/yyyy比如20/10/2004.这个参数可以为空.
DWORD Unknown
请使用NULL.

返回值:
这个函数返回指向生成的授权
-1=参数错误
-2=私钥错误
-3=加密出现问题
-4=硬件ID错误
-5=到期数据错误
-33=异常错误

XX39关联SVKP_Check_licence_key

描述:
这个函数从内存中检测授权

原型:
BOOL XX39(
LPVOID lpLicenseKey,   //内存中授权密钥的地址
LPCTSTR lpHWInformation, //硬件信息指针
);

参数:
lpLicenseKey
指向内存中授权密钥
lpHWInformation
指向为硬件锁定授权的硬件信息.这个参数可以为空.
返回值:
这个函数返回指向返回结构的指针
+0=指向解密注册信息
+4=指向密钥到期的数据或者如果到期数据没有使用为空
+8=不知道
-1=参数错误
-2=授权密钥错误
-3=这是硬件锁定密钥调用函数不需要硬件ID
-4=错误的硬件信息
-33=异常错误

XX40关联SVKP_Load_license_key

描述:
这个函数加载授权密钥到内存

原型:
BOOL XX40(
LPCTSTR lpLicenseFile         //授权文件名地址
);

参数:
lpLicenseFile
指向一个以空结尾的字符串,指向授权文件名

返回值:
这个函数返回装载授权文件的内存地址
-1=参数错误
-2=装载授权文件出现问题
-33=异常错误

XX41关联SVKP_Save_license_key

描述:
这个函数保存由XX38关联SVKP_Generate_license_key在内存中生成的授权密钥.

原型:
BOOL XX40 (

LPCTSTR lpLicenseFile,       //授权文件名地址
LPVOID  lpLicenseKey         //授权密钥的内存地址
);

参数:
lpLicenseFile
指向一个以空结尾的字符串,指向授权文件名
lpLicenseKey
指向内存的授权密钥

返回值:
1=一切顺利
-1=参数错误
-33=异常错误

说明:SVKP_DLL.DLL还有其它的对标准用户无效的函数(例如生成特殊密钥).如果你对此感兴趣,
请通过email:sales@anticracking.sk和我们联系

  Visual Basic开发者的注意事项
    visual Basic程序设计语言的结构不允许使用第三方的程序保护方法(对应用程序的某些部分进行
加密).不过好的软件保护可以使用特殊的API函数来使其更安全.但是可以使用SVK Protector的注册
密钥.
API描述
   
这些专用API函数的使用是很方便的。已经在汇编,Visual C++,Delphi和Visual Basic中测试通过。
假设你需要从某个DLL中调用函数(例如special.dll)
现在你可以使用下面的专用函数了:
SVKP_GetRegistrationInformation
SVKP_LockKeyboard
SVKP_UnlockKeyboard
SVKP_KillDebugger
SVKP_RebootComputer
SVKP_GetHWInfo

SVKP_GetRegistrationInformation

函数功能:
GetRegistrationInformation - 获得指向注册信息的指针.

函数原型:
BOOL SVKP_GetRegistrationInformation(
LPCTSTR lpRegistrationInformation //注册信息的缓冲区地址
);

参数:
lpRegistrationInformation
注册信息的255位长缓冲区地址.SVK Protector把从注册密钥中得到的注册信息放在那里.

返回值:
如果函数调用成功,返回值为真.
如果函数调用失败,返回值为假.

SVKP_LockKeyboard

函数功能:
这个函数可以锁定键盘.调用了这个函数后,不仅仅是调用的程序不能使用键盘,整个Windows的所有程序
都不能使用键盘.这个函数对代码的关键部分(检验授权或者时间限制)很有好处.别忘了在这之后要调用
SVKP_UnlockKeyboard.

函数原型:
VOID SVKP_LockKeyboard(VOID)

返回值:
这个函数没有返回值.

>>>备注:在这个SVK Protector版本中这个函数已经不再使用,因为某些类型的键盘会产生问题.

SVKP_UnlockKeyboard

函数功能:
这个函数可以解锁键盘.调用了这个函数后就可以使用键盘了.

函数原型:
VOID SVKP_UnLockKeyboard(VOID)

返回值:
这个函数没有返回值.

>>>备注:在这个SVK Protector版本中这个函数已经不再使用,因为某些类型的键盘会产生问题.

SVKP_KillDebugger

函数功能:
这个函数可以检测所有的调试器.建议在代码的关键部分(检查授权或才时间限制)之前调用它.如果
检测到调试器,它将不和用户打招呼就重起计算机.

函数原型:
VOID SVKP_KillDebugger(VOID)

返回值:
这个函数没有返回值.

SVKP_RebootComputer

函数功能:
有时需要重起计算机.这个函数将不和用户打任何招呼而安全的重起计算机.

函数原型:
VOID SVKP_RebootComputer(VOID)

返回值:
这个函数没有返回值.

>>>警告:请慎用这个函数因为用户所有没保存的工作都会丢失.

>>>备注:由于一些问题这个函数在这个版本的SVK Protector中已经不再使用.

SVKP_GetHWInfo

函数功能:
硬件ID的16字节长度的缓冲区地址.这个硬件ID每个计算机都是不同的,SVK Protector用它来生成注册
密钥.调用这个API你可以找到一个硬件ID,例如你可以把显示在用户的显示器上.他把这个硬件ID发给你
你用这个硬件ID为他生成一个只可以在他的计算机上工作的注册密钥。

函数原型:
BOOL SVKP_GetHWInfo(
LPCTSTR lpHWInformation //硬件ID的缓冲区地址
);

返回值:
这个函数没有返回值

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
点赞7
打赏
分享
最新回复 (12)
雪    币: 32408
活跃值: (18760)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
kanxue 8 2004-10-11 16:24
2
0
谢谢 cnbragon  翻译了这么多好文章。
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
nbw 24 2004-10-11 23:03
3
0
学习!
雪    币: 85263
活跃值: (198560)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
linhanshi 2004-10-12 00:30
4
0
支持!!!
雪    币: 3686
活跃值: (1036)
能力值: (RANK:760 )
在线值:
发帖
回帖
粉丝
cnbragon 18 2004-10-13 16:29
5
0
:D
哇,多谢各位的鼓励!
因为最近比较忙,我会抽时间出来把它翻译完,今天又更新了一些
雪    币: 416
活跃值: (29)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
basaiyv1 2004-10-18 13:03
6
0
喔!太牛了。
雪    币: 202
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
我还是我 2004-10-30 20:33
7
0
支持你~学习
谢谢你啊
雪    币: 241
活跃值: (160)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xiluoyou 2004-10-30 21:59
8
0
支持
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
nbw 24 2004-10-31 21:33
9
0
支持!!!
雪    币: 258
活跃值: (230)
能力值: ( LV12,RANK:770 )
在线值:
发帖
回帖
粉丝
qiweixue 19 2004-11-4 19:24
10
0
支持~~楼主,不知道是 什么译的~:D
增点人气,~~
雪    币: 3686
活跃值: (1036)
能力值: (RANK:760 )
在线值:
发帖
回帖
粉丝
cnbragon 18 2004-11-5 23:06
11
0
就是手工译的啊,没有用什么所谓的工具!!
不确定的时候就查查字典!!
雪    币: 414
活跃值: (531)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
nig 4 2004-11-6 07:43
12
0
兄弟真是高啊,这样就乐了不少人了.
雪    币: 61
活跃值: (160)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
pendan2001 4 2004-12-16 09:55
13
0
强烈支持先!!!小弟苦寻很久拉,谢谢
游客
登录 | 注册 方可回帖
返回