FastStone Capture 软件注册算法破解及注册机编写
本帖最后由 暴龙兽 于 2020-6-30 15:38 编辑# FastStone Capture 注册算法分析
### 前言
> 前几日准备找一个可以将录屏转成gif图的软件,无意间发现了FastStone Capture。安装之后还需要注册码,碰巧还要申请一个大学的暑假实习,就花了四五天来分析一下注册算法,并写一下注册机。温馨提示:想要注册码的可以直接到文章结尾去下代码,跑一跑就出来了。
### 注册算法总流程图
> 用户名: 可以输入任意长度的内容。
> 注册码: 输入20个字节的字母,其中不能有数字。每五个字符之间用横线分割,如: ZYXWV-UTSRQ-PONML-KJIHG。
> 注册算法主要分为两部分的验证,将注册码分为三部分: rcode_one(前8字节),rcode_two(中间8字节),rcode_three(后4字节).
### 验证算法一
> 关键函数0x6D4FEC --> 0x6D472C
**交叉过程**
```python
# 交叉函数涉及的数据只有username和rcode_one
def character_intersect(uname, rcode):
uname_length = len(uname)
rcode_length = len(rcode)
s = ''
i = j = num = 0
while i < uname_length and j < rcode_length:
if num % 2 == 0:
s += uname
i += 1
else:
s += rcode
j += 1
num += 1
if j != rcode_length:
s += rcode
if i != uname_length:
s += uname
return s.upper()
```
**加密函数**
> 加密函数涉及IDEA和BlowFish,Hash函数涉及Sha1和Sha512函数.
> 加密的内容: username和rcode_one 交叉的部分.
注意事项: 加密的方法有些不同,下面用代码讲解
```python
# 由于字符串编码为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, blowfish_encrypt_result)
# 明文部分与得到结果的一个字节异或
first_cipher += chr(((tmp >> 24) & 0xff) ^ ord(plain_text))
# blowfish_encrypt_result 在内存中循环左移一个字节
blowfish_encrypt_result = ((blowfish_encrypt_result << 8) & 0xffffffff) | blowfish_encrypt_result >> 24
blowfish_encrypt_result = ((blowfish_encrypt_result << 8) & 0xffffff00) | ((tmp >> 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 & 0xff ^ plain_text)
IDEA_encrypt_result = IDEA_encrypt_result + chr(tmp & 0xff ^ plain_text).encode('latin1')
two_cipher_base64 = base64.b64encode(two_cipher.encode('latin1'))
```
**函数0x6C4D78**
> (Sha1, blowfish)和(sha512, IDEA)都在此函数中完成,但传入的参数不同,应该是使用面向对象中的某些性质. 此函数主要完成hash函数和子密钥的生成.
**校验部分**
> 提取密文中的大写字符,与rcode_two进行比较.
### 验证算法二
> 函数0x6D50C0 --> 0x6D4BB8, 交叉函数和验证算法一一样.
**加密函数**
> 加密函数涉及IDEA和BlowFish,Hash函数涉及Sha1和Sha512函数。
> 加密的内容: username和rcode_one交叉的部分。
```python
# 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) - 0x31
# 多次使用idea加密
for i in range(plain_length * times):
tmp = idea.encrypt(IDEA_encrypt_result)
#
first_cipher = tmp & 0xff ^ plain_text
IDEA_encrypt_result = IDEA_encrypt_result + chr(tmp & 0xff ^ plain_text).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, blowfish_encrypt_result)
# 明文与8字节结果的一个字节异或
two_cipher = (tmp >> 24) & 0xff ^ plain_text
blowfish_encrypt_result = ((blowfish_encrypt_result << 8) & 0xffffffff) | blowfish_encrypt_result >> 24
blowfish_encrypt_result = ((blowfish_encrypt_result << 8) & 0xffffff00) | ((tmp >> 24) & 0xff) ^ plain_text
two_cipher_base64 = base64.b64encode(two_cipher)
```
**函数0x6C4D78**
> 与验证算法一中的一样.
**校验部分**
> 提取加密结果中的大写字符,与rcode_three相比较。
### 破解思路
> 整个验证思路:
- 1. username和rcode_one进行组合,结果为intersection_string。
- 2. 验证算法一对intersection_string进行运算,提取前8个大写字符,与rcode_two比较。
- 3. 验证算法二对intersection_string进行运算,提取前8个大写字符,与rcode_three比较。
- 4. 两个比较结果都为真,即可验证成功。
> 破解方法:
- 1. 输入用户名username和随机生成8字节字符串s1,组合后结果为s。
- 2. 验证算法一对s进行运算,提取前8个大写字符,作为s2。
- 3. 验证算法二对s进行运算,提取前4个大写字符,作为s2。
- 4. 最终的注册码为strcat(s1, s2, s3).
### 其他部分
> 以上内容介绍的是主要的验证算法,还有其他的一些函数,顺便介绍一些。
> 如何生成对应类型(Family、Educational、Corporate)的注册码? 下面用代码来进行说明:
```python
# 下面是生成对应类型的注册码,校验方法也很简单
# 提取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 License5000
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
```
### 总结
> 虽然看雪上面也有一篇关于破解[`FastStone Viewer`](https://bbs.pediy.com/thread-258428.htm),但破解这个软件还是花了四五天的时间。其实两者验证算法极其相识,但注册码还是不能通用,原因就是其中一个字符串不同,`FastStone Viewer`为`96332`, `FastStone Capture`为`96338`. 将[`FastStone Viewer`](https://bbs.pediy.com/thread-258428.htm)这篇文章中提到的注册机中的字符串`96332`修改为`96338`,生成的注册码也是可以用的.
### 心得
> 这是第一次真正的破解一个软件,虽然看了别人破解内容,但自己实地操作还是遇到许多坑,尤其是面向对象的一些性质。另外,就是一些加密算法要非常熟悉,这样才能整个数据的变化非常清楚,例如:`FastStone Capture`的BlowFish加密的内容不是用户名和注册码交叉的部分。
### 注册机
(https://github.com/pwnmelife/FastStone-Capture-Key-Generate.git) 暴龙兽 发表于 2020-6-30 15:16
版主,真心不会用吾爱的图片上传
https://www.52pojie.cn/misc.php?mod=faq&action=faq&id=29&messageid=36 专门为你录制的,MD代码不用动,图片上传后直接用论坛贴图的方式贴到正文中就好了,具体看上面链接。 我很奇怪的是,这个软件的官网为什么会被屏蔽? 本帖针对的FastStone Capture版本为9.3, 官网应该可以找到的 图片防盗链看不到 图片显示仅供内部交流 {:1_896:} 图挂掉了,但不看图也挺不错。 我重新上传一下吧 先收藏,慢慢研究。 @暴龙兽 图片盗链了,请把图片上传论坛本地吧。 谢谢分享了! Hmily 发表于 2020-6-30 15:14
@暴龙兽 图片盗链了,请把图片上传论坛本地吧。
版主,真心不会用吾爱的图片上传