FastStone Capture 软件注册算法破解及注册机编写

查看 137|回复 11
作者:暴龙兽   
FastStone Capture 注册算法分析
前言

前几日准备找一个可以将录屏转成gif图的软件,无意间发现了FastStone Capture。安装之后还需要注册码,碰巧还要申请一个大学的暑假实习,就花了四五天来分析一下注册算法,并写一下注册机。温馨提示:想要注册码的可以直接到文章结尾去下代码,跑一跑就出来了。

注册算法总流程图

用户名: 可以输入任意长度的内容。
注册码: 输入20个字节的字母,其中不能有数字。每五个字符之间用横线分割,如: ZYXWV-UTSRQ-PONML-KJIHG。
注册算法主要分为两部分的验证,将注册码分为三部分: rcode_one(前8字节),rcode_two(中间8字节),rcode_three(后4字节).



outline.png (51.22 KB, 下载次数: 3)
下载附件
2020-6-30 15:38 上传

验证算法一

关键函数0x6D4FEC --> 0x6D472C



0x6D472C.png (11.77 KB, 下载次数: 2)
下载附件
2020-6-30 15:25 上传

交叉过程
# 交叉函数涉及的数据只有username和rcode_one
def character_intersect(uname, rcode):
    uname_length = len(uname)
    rcode_length = len(rcode)
    s = ''
    i = j = num = 0
    while i


intersect_function.png (25.98 KB, 下载次数: 1)
下载附件
2020-6-30 15:24 上传

加密函数

加密函数涉及IDEA和BlowFish,Hash函数涉及Sha1和Sha512函数.
加密的内容: username和rcode_one 交叉的部分.

注意事项: 加密的方法有些不同,下面用代码讲解
# 由于字符串编码为byte时, 会出现一个字节变成两个字节的情况, 所以使用latin1编码。
plain_text = t_third # username和registeration code的交叉部分
first_cipher = str()
# blowfish_encrypt_result 作为初始化的
blowfish_encrypt_result = bf.main_transform(0, 0)
for i in range(len(plain_text)):
    tmp = bf.main_transform(blowfish_encrypt_result[0], blowfish_encrypt_result[1])
    # 明文部分与得到结果的一个字节异或
    first_cipher += chr(((tmp[0] >> 24) & 0xff) ^ ord(plain_text))
    # blowfish_encrypt_result 在内存中循环左移一个字节
    blowfish_encrypt_result[0] = ((blowfish_encrypt_result[0] > 24
    blowfish_encrypt_result[1] = ((blowfish_encrypt_result[1] > 24) & 0xff) ^ ord(plain_text)
first_cipher_base64 = base64.b64encode(first_cipher.encode('latin1'))
plain_text = first_cipher_base64 # IDEA 加密的部分是blowfish得到的base64结果
two_cipher = str()
IDEA_zero_byte = b'\x00\x00\x00\x00\x00\x00\x00\x00'
IDEA_encrypt_result = idea.encrypt(IDEA_zero_byte)
for i in range(len(plain_text)):
    tmp = idea.encrypt(IDEA_encrypt_result)
    # 明文部分与得到结果的一个字节异或
    two_cipher += chr(tmp[0] & 0xff ^ plain_text)
    IDEA_encrypt_result = IDEA_encrypt_result[1:] + chr(tmp[0] & 0xff ^ plain_text).encode('latin1')
two_cipher_base64 = base64.b64encode(two_cipher.encode('latin1'))


encryption_one_function.png (73.91 KB, 下载次数: 2)
下载附件
2020-6-30 15:24 上传

函数0x6C4D78

(Sha1, blowfish)和(sha512, IDEA)都在此函数中完成,但传入的参数不同,应该是使用面向对象中的某些性质. 此函数主要完成hash函数和子密钥的生成.



0x6C4D78.png (50.66 KB, 下载次数: 2)
下载附件
2020-6-30 15:24 上传

校验部分

提取密文中的大写字符,与rcode_two进行比较.



verfiy_first.png (28.13 KB, 下载次数: 4)
下载附件
2020-6-30 15:23 上传

验证算法二

函数0x6D50C0 --> 0x6D4BB8, 交叉函数和验证算法一一样.



encryption_two.png (11.85 KB, 下载次数: 1)
下载附件
2020-6-30 15:23 上传

加密函数

加密函数涉及IDEA和BlowFish,Hash函数涉及Sha1和Sha512函数。
加密的内容: username和rcode_one交叉的部分。

# IDEA encrypt
plain_text = (s_third).encode('utf-8')
plain_length = len(plain_text)
first_cipher = bytearray(plain_length)
IDEA_zero_byte = b'\x00\x00\x00\x00\x00\x00\x00\x00'
IDEA_encrypt_result = idea.encrypt(IDEA_zero_byte)
times = ord(register_code[0]) - 0x31
# 多次使用idea加密
for i in range(plain_length * times):
    tmp = idea.encrypt(IDEA_encrypt_result)
    #
    first_cipher[i % plain_length] = tmp[0] & 0xff ^ plain_text[i % plain_length]
    IDEA_encrypt_result = IDEA_encrypt_result[1:] + chr(tmp[0] & 0xff ^ plain_text[i % plain_length]).encode('latin1')
first_cipher_base64 = base64.b64encode(first_cipher)
print("the middle 8 character, IDEA base64 cipher" + str(first_cipher_base64))
# blowfish encrypt,明文部分为上一步加密之后的base64编码
plain_text = first_cipher_base64
two_cipher = bytearray(len(plain_text))
blowfish_zero_byte = b'\x00\x00\x00\x00\x00\x00\x00\x00'
blowfish_encrypt_result = bf.main_transform(0, 0)
for i in range(len(plain_text)):
    tmp = bf.main_transform(blowfish_encrypt_result[0], blowfish_encrypt_result[1])
    # 明文与8字节结果的一个字节异或
    two_cipher = (tmp[0] >> 24) & 0xff ^ plain_text
    blowfish_encrypt_result[0] = ((blowfish_encrypt_result[0] > 24
    blowfish_encrypt_result[1] = ((blowfish_encrypt_result[1] > 24) & 0xff) ^ plain_text
two_cipher_base64 = base64.b64encode(two_cipher)


encryption_two_function.png (74.43 KB, 下载次数: 2)
下载附件
encryption_two_function
2020-6-30 15:23 上传

函数0x6C4D78

与验证算法一中的一样.

校验部分

提取加密结果中的大写字符,与rcode_three相比较。



check_two.png (23.78 KB, 下载次数: 2)
下载附件
check
2020-6-30 15:22 上传

破解思路

整个验证思路:

  • [ol]
  • username和rcode_one进行组合,结果为intersection_string。
    [/ol]
  • 验证算法一对intersection_string进行运算,提取前8个大写字符,与rcode_two比较。
    [/ol]
  • 验证算法二对intersection_string进行运算,提取前8个大写字符,与rcode_three比较。
    [/ol]
  • 两个比较结果都为真,即可验证成功。
    破解方法:
    [/ol]

  • [ol]
  • 输入用户名username和随机生成8字节字符串s1,组合后结果为s。
    [/ol]
  • 验证算法一对s进行运算,提取前8个大写字符,作为s2。
    [/ol]
  • 验证算法二对s进行运算,提取前4个大写字符,作为s2。
    [/ol]
  • 最终的注册码为strcat(s1, s2, s3).
    [/ol]


    其他部分

    以上内容介绍的是主要的验证算法,还有其他的一些函数,顺便介绍一些。



    other_function.png (60.17 KB, 下载次数: 3)
    下载附件
    other_function
    2020-6-30 15:21 上传


    如何生成对应类型(Family、Educational、Corporate)的注册码? 下面用代码来进行说明:

    # 下面是生成对应类型的注册码,校验方法也很简单
    # 提取rcode_one中的3、7、5、1四个位置的字符,分别与'M'、'D'、'I'、'O'四个字符相减
    # 得到的四个数字依次拼接,与下面数字进行比较
    # 1111 --> Family License that covers up to 5 computers
    # 4997 --> Educational Site License
    # 4998 --> Educational Worldwide License
    # 4999 --> Corporate Site License
    # > 5000 --> Corporate Worldwide License
    # FVLQORJM -->  Educational Site License
    def generate_8_upper_case():
        # Family License that covers up to 5 computers 1111
        family_registeration_code = "{0}{1}{2}{3}{4}{5}{6}{7}".format(randomString(1), 'P', randomString(1), 'N', randomString(1), 'K', randomString(1), 'E')
        # Educational Site License 4997
        education_site_registeration_code = "{0}{1}{2}{3}{4}{5}{6}{7}".format(randomString(1), 'V', randomString(1), 'Q', randomString(1), 'R', randomString(1), 'M')
        # Educational Worldwide License 4998
        education_worldwide_registeration_code = "{0}{1}{2}{3}{4}{5}{6}{7}".format(randomString(1), 'W', randomString(1), 'Q', randomString(10), 'R', randomString(1), 'M')
        # Corporate Site License 4999
        Corporate_site_registeration_code = "{0}{1}{2}{3}{4}{5}{6}{7}".format(randomString(1), 'X', randomString(1), 'Q', randomString(1), 'R', randomString(1), 'M')
        # Corporate Worldwide License  5000
        corporate_worldwide_registeration_code = "{0}{1}{2}{3}{4}{5}{6}{7}".format(randomString(1), 'T', randomString(1), 'R', randomString(1), 'K', randomString(1), 'E')
        return [family_registeration_code, education_site_registeration_code, education_worldwide_registeration_code, Corporate_site_registeration_code, corporate_worldwide_registeration_code]
    总结

    虽然看雪上面也有一篇关于破解FastStone Viewer,但破解这个软件还是花了四五天的时间。其实两者验证算法极其相识,但注册码还是不能通用,原因就是其中一个字符串不同,FastStone Viewer为96332, FastStone Capture为96338. 将FastStone Viewer这篇文章中提到的注册机中的字符串96332修改为96338,生成的注册码也是可以用的.

    心得

    这是第一次真正的破解一个软件,虽然看了别人破解内容,但自己实地操作还是遇到许多坑,尤其是面向对象的一些性质。另外,就是一些加密算法要非常熟悉,这样才能整个数据的变化非常清楚,例如:FastStone Capture的BlowFish加密的内容不是用户名和注册码交叉的部分。

    注册机
    Github

    算法, 函数

  • 屁屁踢   


    暴龙兽 发表于 2020-6-30 15:16
    版主,真心不会用吾爱的图片上传

    https://www.52pojie.cn/misc.php? ... 29&messageid=36 专门为你录制的,MD代码不用动,图片上传后直接用论坛贴图的方式贴到正文中就好了,具体看上面链接。
    暴龙兽
    OP
      

    我很奇怪的是,这个软件的官网为什么会被屏蔽?
    Windows10   

    本帖针对的FastStone Capture版本为9.3, 官网应该可以找到的
    不懂破解   

    图片防盗链看不到
    seed   

    图片显示仅供内部交流
    暴龙兽
    OP
      

    图挂掉了,但不看图也挺不错。
    bamyoo   

    我重新上传一下吧
    hu007   

    先收藏,慢慢研究。
    暴龙兽
    OP
      

    @暴龙兽 图片盗链了,请把图片上传论坛本地吧。
    您需要登录后才可以回帖 登录 | 立即注册