Wing IDE 5.0 破解之寻找注册码

来源:http://bbs.pediy.com/showthread.php?p=1253653

一.  工具:
1.  uncompyle2
2.  IDA Pro 6.1
3.  WingIDE 5.0本身
二.  工具安装
1.  安装Python2.7
2.  安装WinIDE 5.0
3.  解压uncompyle2,进入解压目录,执行命令python setup.py install
三.  破解过程
1.  直接拷贝C:\Wing IDE 5.0\bin\2.7\src.zip到C:\crack,解压。
2.  cd C:\Python27\Scripts,运行python uncompyle2 --py -o . c:\crack\src,反编译所有的pyo文件。
3.  启动WingIDE 5.0,选择”Obtain or extend a trial license”,获得个10天的试用。
点击help-->Enter License…,弹出的对话框中选择”Install and activate a permant license”,
随便输几个啥,我这里输入”FFFF”,提示如下图:
 
哈,说的很明白了。
4.  找License ID的规律
用WingIDE打开c:\crack\src\process\wingctl.py,搜索字符串”Invalid license id”,定位到这串代码

代码:

        if self.__fRadioActivate.get_active():
            id = self.__fLicenseIDEntry.get_text()
            errs, lic = abstract.ValidateAndNormalizeLicenseID(id)
            if len(errs) == 0 and id[0] == 'T':
                errs.append(_('You cannot enter a trial license id here'))
            if len(errs) > 0:
                msg = _('Invalid license id: %s. Please check and correct it.  Errors found were:\n\n%s') % (id, '\n'.join(errs))
                buttons = [dialogs.CButtonSpec(_('_OK'), None, wgtk.STOCK_OK)]
                dlg = messages.CMessageDialog(self.fSingletons, _('Invalid License ID'), msg, [], buttons)
                dlg.RunAsModal(self)
                return True

这可以看到,License ID首字符如果是’T’的话,则是trial license,这当然不是我们要的。
右键点击ValidateAndNormalizeLicenseID,选Go to Definition,到

代码:

def ValidateAndNormalizeLicenseID(id):
    errs, id2 = __ValidateAndNormalize(id)
    if len(id2) > 0 and id2[0] not in kLicenseUseCodes:
        errs.append(_('Invalid first character: Should be one of %s') % str(kLicenseUseCodes))
    if len(id2) > 1 and id2[1] != kLicenseProdCode:
        cur_product = 'Wing IDE %s' % config.kProduct
        lic_product = kLicenseProdForCode.get(id2[1], None)
        if lic_product is None:
            lic_product = _('an unknown product')
        else:
            lic_product = 'Wing IDE %s' % config.k_ProductNames[lic_product]
        errs.append(_('Your license is for %s, but you are currently running %s.  Please download the correct product from http://wingware.com/downloads or upgrade your license at https://wingware.com/store/upgrade') % (lic_product, cur_product))
    if len(errs) > 0:
        check_code = id.strip().upper().replace('-', '')
        if len(check_code) == 16:
            looks_like_11 = True
            for c in check_code:
                if c not in '0123456789ABCDEF':
                    looks_like_11 = False

            if looks_like_11:
                errs = [_('You cannot activate using a Wing IDE 1.1 license:  Please use a trial license or upgrade your license at http://wingware.com/store/upgrade')]
    if len(errs) > 0:
        return (errs, None)
    else:
        return ([], id2)

这时我们发现,这个函数是在abstract.py中的。
我们首先看看__ValidateAndNormalize在干些啥,转到定义,

代码:

def __ValidateAndNormalize(code):
    """Remove hyphens and extra space/chars in a license id or activation
    request, and validate it as within the realm of possibility.  Returns
    errs, value."""
    errs = []
    code = code.strip().upper()
    code2 = ''
    badchars = ''
    for c in code:
        if c in ('-', ' ', '\t'):
            pass
        elif c not in textutils.BASE30:
            code2 += c
            if badchars.find(c) == -1:
                badchars += c
        else:
            code2 += c

    if len(badchars) > 0:
        errs.append(_('Contains invalid characters: %s') % badchars)
    if len(code2) != 20:
        errs.append(_('Wrong length (should contain 20 non-hyphen characters)'))
    if len(errs) > 0:
        return (errs, code2)
    else:
        return ([], AddHyphens(code2))

这我们可以看到,License ID的字符必须在BASE30的范围内并且除掉’-’、’ ’、’\t’等字符后必须有20个字符。
程序定义的BASE30 = '123456789ABCDEFGHJKLMNPQRTVWXY',
这个定义是在C:\crack\src\wingutils\ textutils.py中。
现在返回ValidateAndNormalizeLicenseID函数,从第二行知道License ID的首字符必须是
kLicenseUseCodes中的一个kLicenseUseCodes = ['T', 'N', 'E', 'C', '1', '3', '6'],前面说过,’T’表示trial license
第四行告诉我们,License ID的第二个字符必须是kLicenseProdCode中的一个
这个kLicenseProdCode定义如下

代码:

kLicenseProdCodes = {config.kProd101: '1',
 config.kProdPersonal: 'L',
 config.kProdProfessional: 'N',
 config.kProdEnterprise: 'E'}
kLicenseProdCode = kLicenseProdCodes[config.kProductCode]

因为我们安装的是Professional版本,所以第二个字符应该是’N’,Enterprise版本还真不知道在哪里下载,反正官网上找不到~~~
好了,总结一下:
License ID 必须有20个字符且每个字符必须是'123456789ABCDEFGHJKLMNPQRTVWXY'中的;
字符必须首字母必须是['T', 'N', 'E', 'C', '1', '3', '6']中的一个,但是我们不会用’T’;
第二个字符必须是['1','L','N','E']中的一个。
那现在随便搞个”CN123-12345-12345-12345”输入:

Continue,哈,出来了这个,选择输入激活码

先不管,直接Continue,看看啥反应

哦,又是需要20个字符,并且必须是”AXX”开头,好吧,好戏要上场了。
5.  找Activation Code
还是在c:\crack\src\process\wingctl.py查找字符串” Invalid activation key”,来到这:

代码:

def __PageTwoContinue(self):
        if self.__fRadioDirect.get_active():
            self.__StartActivation()
            return True
        if self.__fRadioManual.get_active():
            act = self.__fManualEntry.get_text()
            errs, act = abstract.ValidateAndNormalizeActivation(act)
            if len(errs) > 0:
                title = _('Invalid License ID')
                msg = _('Invalid activation key: %s. Please check and correct it.  Errors found were:\n\n%s') % (self.__fManualEntry.get_text(), '\n'.join(errs))
                self.__ErrorDlg(title, msg)
                return True
            actbase = os.path.normpath(fileutils.join(config.kUserWingDir, 'license.pending'))

转到ValidateAndNormalizeActivation的定义处:

代码:

def ValidateAndNormalizeActivation(id):
    errs, id2 = __ValidateAndNormalize(id)
    if id2[:3] != kActivationPrefix:
        errs.append(_("Invalid prefix:  Should be '%s'") % kActivationPrefix)
    if len(errs) > 0:
        return (errs, None)
    else:
        return ([], id2)

又是__ValidateAndNormalize,前面已经分析过了。看后面,第二行代码清楚的告诉我们,
激活码前三个字符必须是kActivationPrefix ,这个kActivationPrefix = 'AXX'。
好了,我们随便输个”AXX23-12345-12345-12345”,这个当然是错误的。
在c:\crack\src\process\wingctl.py查找字符串” Invalid activation key”的下一处出现的地方,来到:

代码:

self.fLicense['activation'] = act
            err, info = self.fLicMgr._ValidateLicenseDict(self.fLicense, None)
            if err != abstract.kLicenseOK:
                msg = _('Invalid activation key: %s. Please check and correct it.') % self.__fManualEntry.get_text()
                errs.append('Current activation -- failed:')
                errs.extend([ '  ' + t for t in self.fLicMgr._StatusToErrString((err, info)) ])
                if len(errs) > 0:
                    msg += _('  Validation errors were:\n\n%s') % '\n'.join(errs)
                title = _('Invalid License ID')

但是这里的函数self.fLicMgr._ValidateLicenseDict,用鼠标右键找不到定义的地方。
我们先看看self.fLicMgr是个啥东西,转到定义:

代码:

class CObtainLicenseDialog(dialogs.CGenericDialog):
    """Dialog used to obtain a new license"""
    kCharWidth = 60

    def __init__(self, singletons, lic = None):
        self.fSingletons = singletons
        self.fLicMgr = singletons.fLicMgr
        self.fLicense = lic

self.fLicMg是这个类初始化时传进来的,在类名上右键,点Find Points of Use,来到这里

代码:

def _ObtainLicense(self):
        """Prompt user to obtain a license, or quit if they don't get one"""
        if self._fPromptForSaveDialog or not wgtk.kQt and wgtk.gdk.pointer_is_grabbed():
            return
        if self.__fObtainLicenseDialog is not None:
            self.__fObtainLicenseDialog.Show()
            return
        self.__fObtainLicenseDialog = CObtainLicenseDialog(self.fSingletons)

这个_ObtainLicense函数是类CWingLicenseManager的成员,
初始化CObtainLicenseDialog的参数是类CWingLicenseManager的成员,转到定义

代码:

class CWingLicenseManager(abstract.CLicenseManager):
    """ Specialization of the generic license manager for use in Wing IDE """

    def __init__(self, singletons):
        """ Constructor """
        abstract.CLicenseManager.__init__(self)
        self.fSingletons = singletons
        self._fExpiringLicenseCheck = False
        self.__fObtainLicenseDialog = None
        self._fPromptForSaveDialog = False

找CWingLicenseManager这个类的使用点,来到singleton.py中

代码:

    def CreateLicMgr(self):
        """ Create license manager. Mucking with this code is a violation of
        your software license and a generally sleazy thing to do to a bunch of
        guys trying to make a living by creating some decent tools for you. So
        please don't do it. """
        lic_mgr = process.wingctl.CWingLicenseManager(self)
        self.fLicMgr = lic_mgr
        self.emit('changed', self)

这里终于可以知道CObtainLicenseDialog中的self.fLicMgr其实是CWingLicenseManager。
那么看看CWingLicenseManager的基类是啥?是abstract.py文件中的CLicenseManager,
这个类中有_ValidateLicenseDict()函数的定义。好了,转到这个函数去看看:

代码:

def _ValidateLicenseDict(self, lic, filename):
        """ Check license for internal integrity and expiration """
        lic['daysleft'] = _('expired')
        for key in kRequiredLicenseFields:
            if not lic.has_key(key):
                return (kLicenseCorrupt, _('Missing a required line %s') % key)

        err, msg = self._ValidatePlatform(lic['license'], lic['os'])
        if err != None:
            return (err, msg)
        err, msg = self._ValidateProduct(lic['product'])
        if err != None:
            return (err, msg)
        err, msg = self._ValidateVersion(lic['version'])
        if err != None:
            return (err, msg)
        try:
            lichash = CreateActivationRequest(lic)
            act30 = lic['activation']
            if lichash[2] not in 'X34':
                hasher = sha.new()
                hasher.update(lichash)
                hasher.update(lic['license'])
                digest = hasher.hexdigest().upper()
                lichash = lichash[:3] + textutils.SHAToBase30(digest)
                errs, lichash = ValidateAndNormalizeRequest(lichash)
            act = act30.replace('-', '')[3:]
            hexact = textutils.BaseConvert(act, textutils.BASE30, textutils.BASE16)
            while len(hexact) < 20:
                hexact = '0' + hexact

            config._locale_valid = 0
            valid = control.validate(lichash, lic['os'], lic['version'][:lic['version'].find('.')], hexact)
            valid = config._locale_valid
        except:
            valid = 0

        if not valid:
            return (kLicenseCorrupt, _('Invalid license activation'))
        daysleft = self._GetTermDaysLeft(lic)
        if daysleft == -1:
            lic['daysleft'] = _('unlimited')
        else:
            if daysleft == -2:
                return (kLicenseCorrupt, _('Invalid date or termdays in file'))
            if daysleft == 0:
                return (kLicenseExpired, None)
            if daysleft > 12 and lic['license'][0] == 'T':
                return (kLicenseCorrupt, _('Invalid date or termdays in file'))
            if daysleft > 190 and lic['license'][0] != 'T':
                return (kLicenseCorrupt, _('Invalid date or termdays in file'))
            lic['daysleft'] = str(daysleft) + _(' days left')
        errs = hostinfo.IDMatch(lic['hostinfo'])
        if len(errs) > 0:
            return (kLicenseHostMismatch, None)
        if filename is not None:
            err, info = self.__CheckUserCount(lic, filename)
        else:
            err = kLicenseOK
            info = []
        return (err, info)

可以看到,算法不复杂,用lichash和lic[‘license’]做sha运算,之后将sha的值用BASE30变换,
将lichash的前三个字符附加在前面的到新的lichash。
最初的lichash是CreateActivationRequest得到的,
这其实就是在要我们输入激活码那个对话框中显示的Request Code=’ RW518-Q2NNM-13PRE-JQ3JR’。
lic[‘license’]其实就是输入的License ID。
通过看ValidateAndNormalizeRequest的代码,可知lichash的前三个字符分别是:
’R’代表这个是Request code;’W’表示是Windows;’5’表示是5.*版本。
关键就在这句

代码:

valid = control.validate(lichash, lic['os'], lic['version'][:lic['version'].find('.')], hexact)

,好,看看control是啥定义:

代码:

if sys.platform[:5] in ('win32', 'darwi') or sys.platform[:5] == 'linux' and os.uname()[4] not in ('ppc', 'ppc64', 'arm7l'):
    import ctlutil as control
else:
    try:
        import pycontrol
        control = pycontrol
    except ImportError:
        dirname = os.path.dirname(__file__).replace('.zip', '')
        control = LoadFromDat(fileutils.join(dirname, 'pycontrol.dat'), 'pycontrol')

这个ctlutil是啥?搜,我用的Everyting这软件,搜到C:\Wing IDE 5.0\bin\2.7\src\process\ctutil.pyd,这其实就是个dll,IDA反编译它。
反编译后的哑名函数不多,就5个,挨个看。看到sub_10001410这函数的时候,猛然发现有个”_locale_valid”

代码:

.text:10001410 sub_10001410    proc near               ; DATA XREF: .data:100030A8o
.text:10001410
.text:10001410 var_110         = dword ptr -110h
.text:10001410 var_10C         = dword ptr -10Ch
.text:10001410 var_108         = dword ptr -108h
.text:10001410 var_104         = dword ptr -104h
.text:10001410 var_100         = byte ptr -100h
.text:10001410 arg_4           = dword ptr  8
.text:10001410
.text:10001410                 sub     esp, 110h
.text:10001416                 cmp     dword_100030E0, 0
.text:1000141D                 jnz     short loc_10001432
.text:1000141F                 push    offset aConfig  ; "config"
.text:10001424                 call    ds:PyImport_ImportModule
.text:1000142A                 add     esp, 4
.text:1000142D                 mov     dword_100030E0, eax
.text:10001432
.text:10001432 loc_10001432:                           ; CODE XREF: sub_10001410+Dj
.text:10001432                 push    esi
.text:10001433                 mov     esi, ds:PyInt_FromLong
.text:10001439                 push    edi
.text:1000143A                 push    0
.text:1000143C                 call    esi ; PyInt_FromLong
.text:1000143E                 mov     edi, ds:PyObject_SetAttrString
.text:10001444                 push    eax
.text:10001445                 mov     eax, dword_100030E0
.text:1000144A                 push    offset a_locale_valid ; "_locale_valid"
.text:1000144F                 push    eax
.text:10001450                 call    edi ; PyObject_SetAttrString
.text:10001452                 lea     ecx, [esp+128h+var_108]

想到前面_ValidateLicenseDict的代码中也有这么一句:valid=config._local_valid,料想这函数就是在验证了。使用IDA强大的F5,马上就知道,sub_10001020是在计算真正的激活码

代码:

.text:10001489                 mov     ecx, [esp+118h+var_10C]
.text:1000148D                 lea     eax, [esp+118h+var_100]
.text:10001491                 push    eax             ; char *
.text:10001492                 mov     eax, [esp+11Ch+var_104]
.text:10001496                 push    ecx             ; int
.text:10001497                 mov     ecx, [esp+120h+var_110]
.text:1000149B                 call    sub_10001020    ; 计算真正的activation key
.text:100014A0                 add     esp, 8
.text:100014A3                 test    eax, eax
.text:100014A5                 jnz     short loc_100014FC
.text:100014A7                 mov     edx, [esp+118h+var_108] ; 得到输入的activation key的地址
.text:100014AB                 lea     ecx, [esp+118h+var_100] ; 得到计算的Activation Key的地址
.text:100014AF                 nop
.text:100014B0
.text:100014B0 loc_100014B0:                           ; CODE XREF: sub_10001410+BAj
.text:100014B0                 mov     al, [ecx]
.text:100014B2                 cmp     al, [edx] ; 我的妈呀,明文比较呀,这是要发啊~~~
.text:100014B4                 jnz     short loc_100014D0
.text:100014B6                 test    al, al
.text:100014B8                 jz      short loc_100014CC
.text:100014BA                 mov     al, [ecx+1]
.text:100014BD                 cmp     al, [edx+1]
.text:100014C0                 jnz     short loc_100014D0
.text:100014C2                 add     ecx, 2
.text:100014C5                 add     edx, 2
.text:100014C8                 test    al, al
.text:100014CA                 jnz     short loc_100014B0

现在用IDA在1000149B处下断点调试,直接附加到wing.exe,输入License ID:” CN123-12345-12345-12345”,
输入假的激活码” AXX23-12345-12345-12345”。F8单步过lea ecx,[esp+118h+var_100],
内存窗口里转到ecx的地址,得到的是:
“55DF6297CE47296C1916”,这是真正的激活码的sha值,现在要做的就是把这sha转换到BASE30,
然后前面附加”AXX”就行了。新建一个py文件,转换代码如下:

代码:

realcode='55DF6297CE47296C1916'
act30=BaseConvert(realcode,BASE16,BASE30)
while len(act30) < 17:
    act30 = '1' + act30

这里的BaseConvert函数是从c:\crack\src\wingutils\textutils.py中拷贝来的。运行一下这个py,得到:
act30=”1X8TBXQFVWRYLBDKB”
所以激活码是AXX1X8TBXQFVWRYLBDKB
6.注册机的制作
进入sub_10001020,算法非常简单,不多说了,直接上注册机
CalcActivationCode.rar.
注册机是个python源代码文件,没有使用任何附加库,直接可以跑
使用时,编辑下RequestCode就行了
看下效果吧
*转载请注明来自看雪论坛@PEd

时间: 2024-09-20 20:09:55

Wing IDE 5.0 破解之寻找注册码的相关文章

Wing IDE v4.0.2发布 面向Python的编程工具

WingIDE是个相当优秀的 IDE:其编辑器包括大量语言的语法标签高亮显示,虽然它只是个面向 Python 的工具.源代码浏览器对浏览项目或模块非常实用(表现在可导航源代码和文档行摘要中).虽然没有监视器,但调试器设计得很好.编辑器有优秀的命令自动完成和函数跳转列表,但是没有代码合并.面向项目风格的 IDE 对于大型产品非常有用(在这方面,除了 Komodo 以外,它是大多免费 IDE 中较好的).总体的界面就像增强的 Idle,使用了与许多 TK 和 XWindow 界面类似的"多窗口&qu

Wing IDE v4.0.3发布 一个相当优秀的IDE

Wing IDE它是一个基于Python编程语言开发的集成开发环境.这个版本可以运行在基于Intel处理器的Linux操作系统上,为软件开发者提供了一个集成的工程管理器.图形界面的调试器.源代码浏览器,并预设了一个高级的源代码编辑器.事实证明,和C.C++.Java以及其它编程语言相比,Python将大大提高程序员的开发效率.Wing IDE将充分地利用Python简单.功能强大以及可升级性等独特的优势.据Archaeopteryx软件公司透露,他们的开发人员一直在使用Wing IDE,大大提高

Wing IDE v4.0发布 相当优秀的IDE工具

WingIDE是个相当优秀的 IDE:其编辑器包括大量语言的语法标签高亮显示,虽然它只是个面向 Python 的工具.源代码浏览器对浏览项目或模块非常实用(表现在可导航源代码和文档行摘要中).虽然没有监视器,但调试器设计得很好.编辑器有优秀的命令自动完成和函数跳转列表,但是没有代码合并.面向项目风格的 IDE 对于大型产品非常有用(在这方面,除了 Komodo 以外,它是大多免费 IDE 中较好的).总体的界面就像增强的 Idle,使用了与许多 TK 和 XWindow 界面类似的"多窗口&qu

Wing IDE 4.0.4发布 Python编程语言集成开发环境

Wingware的Wing IDE已发布4.0.4版本,一个专门为Python编程语言设计的集成开发环境. Wing IDE是一个跨平台的Python IDE,提供了一个专业的代码编辑器VI,Emacs和其他键绑定,自动完成,通话时间提示,重构,一个强大的图形调试器,版本控制,单元测试,搜索和许多其他功能. 在4.0.4版本中的变化: * History in shells stores whole entered blocks, not individual lines and allows

J2ME MIDP Currency Converter Tutorial for NetBeans IDE 4.0

j2me MIDP Currency Converter Tutorial for NetBeans IDE 4.0Feedback http://www.netbeans.org/kb/articles/tutorial-currencyconverter-40.html Feedback The Currency Converter application you will build in this tutorial shows you how to: start a j2me MIDP

NetBeans IDE 6.0 Java快速入门指南

欢迎使用 NetBeans IDE! 本教程提供 NetBeans IDE 工作流程的简单介绍和快速指南.我们将指导大家创建一个简单的 "Hello World" Java 控制台应用程序.完成此教程之后,您将具备如何在 IDE 中创建.编译和运行应 用程序的基本知识. 本教程可在 10 分钟之内完成. 完成本教程之后,您可以继续学习 NetBeans IDE 的 在线文档中心.该部分提供的教程全面介绍了众 多 IDE 特性和编程技巧,可应用于各种应用程序类型.如果对 "He

迁移NetBeans Visual Web Pack应用程序至NetBeans IDE 6.0

本文档帮助您把 NetBeans Visual Web Pack 应用程序迁移到 NetBeans IDE 的 Web 支持上. 要使用本教程,您需要安装 NetBeans IDE 6.0,并且选择"Web & Java EE"或"All"安装包.要了解有关操作 NetBeans IDE 的更多信息,请参见 NetBeans 网站上的支持和文档页. Visual Web JSF 向后兼容工具包提供了增补库,可视 Web 设计师需要用它们来支持基于 J2SE

在NetBeans IDE 6.0中开发通用Java应用程序简介

本简明教程将演示如何在 NetBeans IDE 6.0 中开发 Java SE 应用程序.本教程假定您对 Java 应用程序的开发已比较熟悉.在讲解过程中,我们将演示如何通过一些 IDE 特性简化应用程序开发. 我们将开发一个单词转换应用程序,用于将多个英文单词转换为一个英文单词.生成单词的构成形式为第一个词的第一个字母.第二个词的第二个字母.第三个词的第三个字母,依此类推.该生成词称为 离合词. 建立项目 我们创建的应用程序将包含两个项目: 具有实用程序类的 java 库项目. 具有 mai

NetBeans IDE 6.0指南之如何构建GUI程序

这篇入门教程将教会您怎样创建一个简单的人机交互界面以及向其中添加简单 的后台功能. 特别地,我们将向您展示如何按 Swing 规范编写控制按钮和域代 码. 我们将会使用到布局管理.设计简单 GUI 界面以及添加一些"按钮(button) "和"文本字段(text field)"组件. "文本字段"是用来接收输入和显示输出 的,"按钮"在前端用来起动相应功能. 我们将创建的应用程序会是一个简单但 实用的计算器. 获得更多GUI设