R0 CREW

2. Уроки реального взлома MiniTool Photo Recovery 3.0

⁠На прошлом уроке мы поняли как формируется activation code, и столкнулись с RSA шифрованием. Так как у нас нет приватного ключа, мы не можем создать валидные данные для активации, то создадим свою ключевую пару.

Для начала посмотрим характеристики ключа который зашит в программе, он в формате PEM, скармливаем его утилите openssl

openssl rsa -inform PEM -in pk.pem -pubin -text

Modulus (2048 bit):
    00:ef:6e:b9:30:55:89:ae:ad:4e:9f:a5:d1:a9:ad:
    a9:10:cd:19:ae:ac:fe:ee:61:83:03:1f:77:8b:da:
    31:6a:37:45:6d:89:a6:12:26:99:83:ca:4b:a2:0e:
    86:b8:b7:8e:9b:63:58:d1:7c:5c:28:e1:da:45:c1:
    51:da:c8:84:50:8c:1e:80:3d:9e:18:d8:0e:da:17:
    76:ae:75:94:d4:07:ef:09:06:8e:83:52:5c:09:b1:
    16:d0:52:e8:38:fa:03:69:93:32:87:c2:21:09:67:
    fa:03:27:80:b3:95:34:60:7f:d3:2c:49:80:bc:26:
    83:c5:d5:3a:4c:48:3c:cf:2d:82:db:71:a8:02:85:
    2f:71:9d:d2:49:02:4d:5b:3d:0d:a9:14:8d:9d:5e:
    fc:c1:99:87:ca:83:74:b9:0f:32:c8:c8:2b:31:84:
    35:db:e0:d9:fc:98:5e:ff:6c:12:38:f2:0e:67:00:
    e4:0b:02:ed:ce:d7:2f:12:c2:67:27:88:b6:e3:fa:
    3d:25:40:f5:9c:ca:4d:43:ce:32:01:33:c4:b3:75:
    b1:98:00:66:ac:c2:f2:40:ba:16:e0:1b:85:c1:7c:
    66:0c:11:fa:f7:c4:92:2c:6f:01:fb:37:d9:35:38:
    42:c8:5b:2c:59:3d:be:6b:76:a8:41:10:44:f0:b8:
    08:35
Exponent: 65537 (0x10001)
writing RSA key
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA7265MFWJrq1On6XRqa2p
EM0Zrqz+7mGDAx93i9oxajdFbYmmEiaZg8pLog6GuLeOm2NY0XxcKOHaRcFR2siE
UIwegD2eGNgO2hd2rnWU1AfvCQaOg1JcCbEW0FLoOPoDaZMyh8IhCWf6AyeAs5U0
YH/TLEmAvCaDxdU6TEg8zy2C23GoAoUvcZ3SSQJNWz0NqRSNnV78wZmHyoN0uQ8y
yMgrMYQ12+DZ/Jhe/2wSOPIOZwDkCwLtztcvEsJnJ4i24/o9JUD1nMpNQ84yATPE
s3WxmABmrMLyQLoW4BuFwXxmDBH698SSLG8B+zfZNThCyFssWT2+a3aoQRBE8LgI
NQIDAQAB
-----END PUBLIC KEY-----

rsa ключ 2048 бит, генерируем свою ключевую пару на python

import struct
import base64
import json
from Crypto.PublicKey import RSA as CryptoRSA
    
def genRSA():
    rsa=CryptoRSA.generate(2048)
    priv=rsa.exportKey()
    pub=rsa.publickey().exportKey(format='PEM')
    return priv,pub


if __name__=="__main__":
    priv,pub=genRSA()
    print priv
    print pub

у меня получились такие ключики

-----BEGIN RSA PRIVATE KEY-----
MIIEpgIBAAKCAQEAwOY9lw75taUd7EH7XKOgh+P7kKGMZNglOZNfBhNnC35vzThT
LJLjZjVlassbRDDtLNHfxtDvq745R+19sQdMKXzkka/0O6dcjDrOeK3ZGRXGVqCk
iTf4pvK+jJU/PzU8NRyThRawXUxJRZ4wx7brTuE7gho2eQXB1+3xXGKfYYxofPzf
doEvB0y08843FQVX1iJNmb3gJqnAQzo3LSOH3yjnRv48pA1Fa6UmrZJ/Ppc0Okp1
WpPEP3TPB3Vi5iR4b5SlKD48+jrCY2AEm1g7JjA3V4MaHYqWdr9H6ltpiFF9+ziW
9zeIdL277JPDOsMt4g7yU0Ez+WZefSdsvEF9bQIDAQABAoIBAQCcuPOFTXd4K0Ta
dOlCZPbCMWpsIbStIidsVd24U/8+iWVQeNiquFTk77EMSSRIDPBFn+aN46c2BAEJ
/VxHfkRU2NHjw+9MoDdC/2xNBAIErXpNW4sSqVTuXv6NvZx7QEdAZ407bimwQ5Cs
bU/4kxcvKTNuCtoDDbhmNT4J717KoxuDzEviJRlmLxVf4nq97ahyUA1t89Hss2NF
RLHC3inkXyTw9wn1gE9i+Xi77ZH/eanldRZkc4PczHJxGdFVuJX0rIhNsG0Fs9rI
OFn7WCUrYzAKF8qq0+7clpmDCZSai+i5BxVt/hgLME5nva2KPvIlMINcPeO+rc5x
NM5nKiCJAoGBAMVTTJVm704QRfl8YNwFu0dI/jIg+EAR8gS4GUPek6sjszd4KcWq
xc6LFbOm3NvNP96nbGHvijQuzwTrixr2o3DDM+CywvY1/ioBhBtDNxnuKsXpTZZM
UtQ3kmDyNdUbisGzmEd+eGNu/odqyWbgWJXUT3b0ENy2FXGxC6S1eS43AoGBAPpC
BujTA8eLW0G+6Uy2CLbYn0u+JzdTEcs2x5EuKEIvd/z7vsRlqqMLtjFLvU/qU/2z
Gralyj3W2wG1nyHA73L6oOtB47qWbE5l+o5QPm+jMld9nUFq5M4jkjkNEzSwn19D
Hgsx16oi/JgO/076YbAaHspheyHYQa27fIvmPX97AoGBAK3o3HZQYljKvuFDXZqM
8qHBE0fbBvBw4HyIRLwsTrlmnW0l2qr795oxus67IawXGVOC+2LVW1jiaFJNxivd
c+7OG8rNwkZ9D6S18ViVxNp1rfz/wgHVAqtGzxviXM+VlpVhU7SvIiuAh5OR6i9h
SrHCjMaqFLJxSDULdNeVmVfBAoGBAKyad4uDZprtOb6pvt0iu/XoiE3EU+XrjF09
Zf1y+V9UwAwjUZrBiCQ2Qq3TUDnbI5zaN/V7eXaXRqvyKVQtbrk9tVktM7UQZJjZ
6yrWm4mB5InFYH2rDS5ECGkC5Jk1rGYWs5UDBn0Y7mCuD1bYiCHekhgBjdx0/C+o
HSmcXhQbAoGBAJO+os0qCqf7dcLSllh2LlDzxlnwuiBH854gLcF3vvG7PiIBY93d
81+nlSCz9AaokjPpctUTOoiNjmpjGEEQ+L9YdF2pbjrvLLT8Kbb4Z58jR6xCDuMq
f0jALcFhzF1BA1MB/zZBd+HTNU//8XFj1p5DzFgAu5z6trZAIWnNgDNG
-----END RSA PRIVATE KEY-----

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwOY9lw75taUd7EH7XKOg
h+P7kKGMZNglOZNfBhNnC35vzThTLJLjZjVlassbRDDtLNHfxtDvq745R+19sQdM
KXzkka/0O6dcjDrOeK3ZGRXGVqCkiTf4pvK+jJU/PzU8NRyThRawXUxJRZ4wx7br
TuE7gho2eQXB1+3xXGKfYYxofPzfdoEvB0y08843FQVX1iJNmb3gJqnAQzo3LSOH
3yjnRv48pA1Fa6UmrZJ/Ppc0Okp1WpPEP3TPB3Vi5iR4b5SlKD48+jrCY2AEm1g7
JjA3V4MaHYqWdr9H6ltpiFF9+ziW9zeIdL277JPDOsMt4g7yU0Ez+WZefSdsvEF9
bQIDAQAB
-----END PUBLIC KEY-----

далее нужно пропатчить pas2.dll нашим публичным ключиком, при этом не забываем что он должен быть зашифрован DES ECB, кроме того длинна шифрованных данных должна быть кратна 8, недостающие байты забиваем нулями

код который патчит длл будет таким

import struct
import base64
import json
from Crypto.Cipher import DES
from Crypto.PublicKey import RSA as CryptoRSA


def decodeDES(data):
    des=DES.new('7FB45FAB')
    dec=des.decrypt(data)
    return dec


def encodeDES(data):
    des=DES.new('7FB45FAB')
    l=len(data)
    pad='\x00'*(8-(l-((l/8)*8)))
    enc=data+pad
    dec=des.encrypt(enc)
    return dec



def genPatchData(priv,data):
    sig='\xC5\x03\x15\x61\xAD\xA9\x7E\x98'
    size=0x1C8
    i=data.find(sig)
    if i==-1:
        raise Exception('error sign')
    a=CryptoRSA.importKey(priv)
    p=a.publickey()
    pub=p.exportKey()
    enc=encodeDES(pub)
    patch=data[:i]+enc+data[i+size:]
    return patch


priv="""-----BEGIN RSA PRIVATE KEY-----
MIIEpgIBAAKCAQEAwOY9lw75taUd7EH7XKOgh+P7kKGMZNglOZNfBhNnC35vzThT
LJLjZjVlassbRDDtLNHfxtDvq745R+19sQdMKXzkka/0O6dcjDrOeK3ZGRXGVqCk
iTf4pvK+jJU/PzU8NRyThRawXUxJRZ4wx7brTuE7gho2eQXB1+3xXGKfYYxofPzf
doEvB0y08843FQVX1iJNmb3gJqnAQzo3LSOH3yjnRv48pA1Fa6UmrZJ/Ppc0Okp1
WpPEP3TPB3Vi5iR4b5SlKD48+jrCY2AEm1g7JjA3V4MaHYqWdr9H6ltpiFF9+ziW
9zeIdL277JPDOsMt4g7yU0Ez+WZefSdsvEF9bQIDAQABAoIBAQCcuPOFTXd4K0Ta
dOlCZPbCMWpsIbStIidsVd24U/8+iWVQeNiquFTk77EMSSRIDPBFn+aN46c2BAEJ
/VxHfkRU2NHjw+9MoDdC/2xNBAIErXpNW4sSqVTuXv6NvZx7QEdAZ407bimwQ5Cs
bU/4kxcvKTNuCtoDDbhmNT4J717KoxuDzEviJRlmLxVf4nq97ahyUA1t89Hss2NF
RLHC3inkXyTw9wn1gE9i+Xi77ZH/eanldRZkc4PczHJxGdFVuJX0rIhNsG0Fs9rI
OFn7WCUrYzAKF8qq0+7clpmDCZSai+i5BxVt/hgLME5nva2KPvIlMINcPeO+rc5x
NM5nKiCJAoGBAMVTTJVm704QRfl8YNwFu0dI/jIg+EAR8gS4GUPek6sjszd4KcWq
xc6LFbOm3NvNP96nbGHvijQuzwTrixr2o3DDM+CywvY1/ioBhBtDNxnuKsXpTZZM
UtQ3kmDyNdUbisGzmEd+eGNu/odqyWbgWJXUT3b0ENy2FXGxC6S1eS43AoGBAPpC
BujTA8eLW0G+6Uy2CLbYn0u+JzdTEcs2x5EuKEIvd/z7vsRlqqMLtjFLvU/qU/2z
Gralyj3W2wG1nyHA73L6oOtB47qWbE5l+o5QPm+jMld9nUFq5M4jkjkNEzSwn19D
Hgsx16oi/JgO/076YbAaHspheyHYQa27fIvmPX97AoGBAK3o3HZQYljKvuFDXZqM
8qHBE0fbBvBw4HyIRLwsTrlmnW0l2qr795oxus67IawXGVOC+2LVW1jiaFJNxivd
c+7OG8rNwkZ9D6S18ViVxNp1rfz/wgHVAqtGzxviXM+VlpVhU7SvIiuAh5OR6i9h
SrHCjMaqFLJxSDULdNeVmVfBAoGBAKyad4uDZprtOb6pvt0iu/XoiE3EU+XrjF09
Zf1y+V9UwAwjUZrBiCQ2Qq3TUDnbI5zaN/V7eXaXRqvyKVQtbrk9tVktM7UQZJjZ
6yrWm4mB5InFYH2rDS5ECGkC5Jk1rGYWs5UDBn0Y7mCuD1bYiCHekhgBjdx0/C+o
HSmcXhQbAoGBAJO+os0qCqf7dcLSllh2LlDzxlnwuiBH854gLcF3vvG7PiIBY93d
81+nlSCz9AaokjPpctUTOoiNjmpjGEEQ+L9YdF2pbjrvLLT8Kbb4Z58jR6xCDuMq
f0jALcFhzF1BA1MB/zZBd+HTNU//8XFj1p5DzFgAu5z6trZAIWnNgDNG
-----END RSA PRIVATE KEY-----"""

if __name__=="__main__":
    data=open('x64\\Pas2.dll','rb').read()
    o=genPatchData(priv, data)
    open('x64\\Pas2.dll.patched','wb+').write(o)
    print 'done' 

подкладываем модифицированную pas2.dll программе

теперь можно шифровать запросы самостоятельно, напомню что формат сообщения выглядит так

base64_encode(json_encode([base64_encode(data1),base64_encode(data2)]))

исследуем функцию которая занимается расшифровкой данных

видим что данные извлекаются из json массива, выполняется base64_decode и передаются RSA_public_decrypt, расшифрованные данные соединяются вместе append

напишем код на python который зашифрует данные rsa

import struct
import base64
import json
from Crypto.Cipher import DES
from M2Crypto import RSA
from Crypto.PublicKey import RSA as CryptoRSA

def decodeRSA(priv,license):
    txt=''
    js=json.loads(license.decode('base64'))
    for i in js:
        t=i.decode('base64')    
        rsa=RSA.load_key_string(priv)
        msg=rsa.private_decrypt(t,1)
        txt+=msg
    return json.loads(txt)

def encodeRSA(priv,resp):
    js=json.dumps(resp)
    ls=[]
    while len(js)>0:
        t=js[:0x90]
        js=js[0x90:]
        
        rsa=RSA.load_key_string(priv)
        msg=rsa.private_encrypt(t,1)
        
        ls.append(base64.b64encode(msg))

    return base64.b64encode(json.dumps(ls))

def decodeRSA(priv,license):
    txt=''
    js=json.loads(license.decode('base64'))
    for i in js:
        t=i.decode('base64')    
        rsa=RSA.load_key_string(priv)
        msg=rsa.private_decrypt(t,1)
        txt+=msg
    return json.loads(txt)



priv="""-----BEGIN RSA PRIVATE KEY-----
MIIEpgIBAAKCAQEAwOY9lw75taUd7EH7XKOgh+P7kKGMZNglOZNfBhNnC35vzThT
LJLjZjVlassbRDDtLNHfxtDvq745R+19sQdMKXzkka/0O6dcjDrOeK3ZGRXGVqCk
iTf4pvK+jJU/PzU8NRyThRawXUxJRZ4wx7brTuE7gho2eQXB1+3xXGKfYYxofPzf
doEvB0y08843FQVX1iJNmb3gJqnAQzo3LSOH3yjnRv48pA1Fa6UmrZJ/Ppc0Okp1
WpPEP3TPB3Vi5iR4b5SlKD48+jrCY2AEm1g7JjA3V4MaHYqWdr9H6ltpiFF9+ziW
9zeIdL277JPDOsMt4g7yU0Ez+WZefSdsvEF9bQIDAQABAoIBAQCcuPOFTXd4K0Ta
dOlCZPbCMWpsIbStIidsVd24U/8+iWVQeNiquFTk77EMSSRIDPBFn+aN46c2BAEJ
/VxHfkRU2NHjw+9MoDdC/2xNBAIErXpNW4sSqVTuXv6NvZx7QEdAZ407bimwQ5Cs
bU/4kxcvKTNuCtoDDbhmNT4J717KoxuDzEviJRlmLxVf4nq97ahyUA1t89Hss2NF
RLHC3inkXyTw9wn1gE9i+Xi77ZH/eanldRZkc4PczHJxGdFVuJX0rIhNsG0Fs9rI
OFn7WCUrYzAKF8qq0+7clpmDCZSai+i5BxVt/hgLME5nva2KPvIlMINcPeO+rc5x
NM5nKiCJAoGBAMVTTJVm704QRfl8YNwFu0dI/jIg+EAR8gS4GUPek6sjszd4KcWq
xc6LFbOm3NvNP96nbGHvijQuzwTrixr2o3DDM+CywvY1/ioBhBtDNxnuKsXpTZZM
UtQ3kmDyNdUbisGzmEd+eGNu/odqyWbgWJXUT3b0ENy2FXGxC6S1eS43AoGBAPpC
BujTA8eLW0G+6Uy2CLbYn0u+JzdTEcs2x5EuKEIvd/z7vsRlqqMLtjFLvU/qU/2z
Gralyj3W2wG1nyHA73L6oOtB47qWbE5l+o5QPm+jMld9nUFq5M4jkjkNEzSwn19D
Hgsx16oi/JgO/076YbAaHspheyHYQa27fIvmPX97AoGBAK3o3HZQYljKvuFDXZqM
8qHBE0fbBvBw4HyIRLwsTrlmnW0l2qr795oxus67IawXGVOC+2LVW1jiaFJNxivd
c+7OG8rNwkZ9D6S18ViVxNp1rfz/wgHVAqtGzxviXM+VlpVhU7SvIiuAh5OR6i9h
SrHCjMaqFLJxSDULdNeVmVfBAoGBAKyad4uDZprtOb6pvt0iu/XoiE3EU+XrjF09
Zf1y+V9UwAwjUZrBiCQ2Qq3TUDnbI5zaN/V7eXaXRqvyKVQtbrk9tVktM7UQZJjZ
6yrWm4mB5InFYH2rDS5ECGkC5Jk1rGYWs5UDBn0Y7mCuD1bYiCHekhgBjdx0/C+o
HSmcXhQbAoGBAJO+os0qCqf7dcLSllh2LlDzxlnwuiBH854gLcF3vvG7PiIBY93d
81+nlSCz9AaokjPpctUTOoiNjmpjGEEQ+L9YdF2pbjrvLLT8Kbb4Z58jR6xCDuMq
f0jALcFhzF1BA1MB/zZBd+HTNU//8XFj1p5DzFgAu5z6trZAIWnNgDNG
-----END RSA PRIVATE KEY-----"""

if __name__=="__main__":
    activation_code=encodeRSA(priv,{})
    print activation_code

я использовал M2Crypto через pip она у меня не поставилась и я взял готовую сборку для windows
https://github.com/dsoprea/M2CryptoWindows

результатом будет такой activation code

WyJBVzMzQlh4bENlVjRPR09rSFdldmxOWnFaVnFlVW1GVHcvNjBvSGM1K0FQTGRLTFBJWWJJeDdraDQ1RDlXZnUrK1RLNVZJeUtxUjAwWVhXa2RYa1g1Vm9TMXpUS3I4Wm05U00xSC9mUmtVNEhJV3diTDFkdjY0Y0tQNmZVTGFJT3lRMW9HNWtoM3JyeVFKZENOSUdzQ21VcDNrSlVMTm5JQmt4MEFFaUVtU29MamtzdDJxTWJSckxGY0RuMDNWSWRxb1kyMVIrc1YrWnlMMVNHcU52amxoRm5SRGJzMW1NUDk2cklKYTlIYnhMSmlNZXVIMWhsZHJxMTgxYS9mcGEzR1JCSHd5aGx6QnZyYTdDUjBlY0t3Z3Z0MllaUUwxZ29KUDA0c2thR3BpaytudklqcWlybVBuMFM3Y25xZDJhejRxTjRKWVJsK01UT1QwTUpSNnJRZ1E9PSJd

подставляем его в программу и смотрим корректность расшифровки в отладчике

я решил посмотреть перекрестные ссылки на функцию RSA шифрования

исследовав код можно понять что он принадлежит License Information, для расшифровки данных можно воспользоватся decodeRSA

в результате получим такое

{
    "LicenseCode": "123456-78A8E7-04D461-0D7679",
    "MachineCode": "1ae6c86a10b1210fd3f1aa6942cf41b6",
    "MachineInfo": "Motherboard Info: innotek gmbh|default system bios|0|\nCpuName:Intel(R) Core(TM) i5-4570R CPU @ 2.70GHz (3)",
    "VersionCode": "54143fe13d7deb6f918fb25bd4d8b4fc"
}

вернемся обратно к activation code, мы научились шифровать и расшифровывать запрос, но что лежит в полезной нагрузке пока не ясно

для этого продолжим отладку

тут мы успешно прошли процедуру шифрования

далее идет валидация параметров json, то что мы зашифровали RSA

.text:000007FEEEE0FF44 lea     rdx, [rsp+130h+var_F8]
.text:000007FEEEE0FF49 lea     rcx, [rsp+130h+var_108]
.text:000007FEEEE0FF4E call    cs:?toUtf8@QString@@QEBA?AVQByteArray@@XZ ; QString::toUtf8(void)
.text:000007FEEEE0FF54 nop
.text:000007FEEEE0FF55
.text:000007FEEEE0FF55 loc_7FEEEE0FF55:                        ; DATA XREF: .rdata:000007FEEEE2B7F0↓o
.text:000007FEEEE0FF55 xor     r8d, r8d
.text:000007FEEEE0FF58 mov     rdx, rax
.text:000007FEEEE0FF5B lea     rcx, [rsp+130h+var_110]
.text:000007FEEEE0FF60 call    cs:?fromJson@QJsonDocument@@SA?AV1@AEBVQByteArray@@PEAUQJsonParseError@@@Z ; QJsonDocument::fromJson(QByteArray const &,QJsonParseError *)
.text:000007FEEEE0FF66 nop
.text:000007FEEEE0FF67
.text:000007FEEEE0FF67 loc_7FEEEE0FF67:                        ; DATA XREF: .rdata:000007FEEEE2B7F8↓o
.text:000007FEEEE0FF67 lea     rdx, [rsp+130h+var_E0]
.text:000007FEEEE0FF6C mov     rcx, rax
.text:000007FEEEE0FF6F call    cs:?object@QJsonDocument@@QEBA?AVQJsonObject@@XZ ; QJsonDocument::object(void)
.text:000007FEEEE0FF75 nop
.text:000007FEEEE0FF76
.text:000007FEEEE0FF76 loc_7FEEEE0FF76:                        ; DATA XREF: .rdata:000007FEEEE2B800↓o
.text:000007FEEEE0FF76 mov     rdx, rax
.text:000007FEEEE0FF79 lea     rcx, [rsp+130h+var_F0]
.text:000007FEEEE0FF7E call    cs:??4QJsonObject@@QEAAAEAV0@AEBV0@@Z ; QJsonObject::operator=(QJsonObject const &)
.text:000007FEEEE0FF84 nop
.text:000007FEEEE0FF85
.text:000007FEEEE0FF85 loc_7FEEEE0FF85:                        ; DATA XREF: .rdata:000007FEEEE2B808↓o
.text:000007FEEEE0FF85 lea     rcx, [rsp+130h+var_E0]
.text:000007FEEEE0FF8A call    cs:??1QJsonObject@@QEAA@XZ      ; QJsonObject::~QJsonObject(void)
.text:000007FEEEE0FF90 nop
.text:000007FEEEE0FF91
.text:000007FEEEE0FF91 loc_7FEEEE0FF91:                        ; DATA XREF: .rdata:000007FEEEE2B810↓o
.text:000007FEEEE0FF91 lea     rcx, [rsp+130h+var_110]
.text:000007FEEEE0FF96 call    cs:??1QJsonDocument@@QEAA@XZ    ; QJsonDocument::~QJsonDocument(void)
.text:000007FEEEE0FF9C nop
.text:000007FEEEE0FF9D
.text:000007FEEEE0FF9D loc_7FEEEE0FF9D:                        ; DATA XREF: .rdata:000007FEEEE2B818↓o
.text:000007FEEEE0FF9D lea     rcx, [rsp+130h+var_F8]
.text:000007FEEEE0FFA2 call    cs:??1QByteArray@@QEAA@XZ       ; QByteArray::~QByteArray(void)
.text:000007FEEEE0FFA8 lea     rcx, [rsp+130h+var_F0]
.text:000007FEEEE0FFAD call    cs:?isEmpty@QJsonObject@@QEBA_NXZ ; QJsonObject::isEmpty(void)
.text:000007FEEEE0FFB3 test    al, al
.text:000007FEEEE0FFB5 setz    bl
.text:000007FEEEE0FFB8
.text:000007FEEEE0FFB8 loc_7FEEEE0FFB8:                        ; DATA XREF: .rdata:000007FEEEE2B820↓o
.text:000007FEEEE0FFB8 lea     rcx, [rsp+130h+var_108]
.text:000007FEEEE0FFBD call    cs:??1QString@@QEAA@XZ          ; QString::~QString(void)
.text:000007FEEEE0FFC3
.text:000007FEEEE0FFC3 loc_7FEEEE0FFC3:                        ; CODE XREF: j_checkActivationCode+A2↑j
.text:000007FEEEE0FFC3 test    bl, bl
.text:000007FEEEE0FFC5 setz    bl
.text:000007FEEEE0FFC8
.text:000007FEEEE0FFC8 loc_7FEEEE0FFC8:                        ; DATA XREF: .rdata:000007FEEEE2B828↓o
.text:000007FEEEE0FFC8 lea     rcx, [rsp+130h+activationCode]
.text:000007FEEEE0FFCD call    cs:??1QString@@QEAA@XZ          ; QString::~QString(void)
.text:000007FEEEE0FFD3 test    bl, bl
.text:000007FEEEE0FFD5 jnz     loc_7FEEEE10241
.text:000007FEEEE0FFDB mov     edx, 0Fh
.text:000007FEEEE0FFE0 lea     rcx, aActivationCode            ; "activation_code"
.text:000007FEEEE0FFE7 call    cs:?fromAscii_helper@QString@@CAPEAU?$QTypedArrayData@G@@PEBDH@Z ; QString::fromAscii_helper(char const *,int)
.text:000007FEEEE0FFED mov     [rsp+130h+activationCode], rax
.text:000007FEEEE0FFF2
.text:000007FEEEE0FFF2 loc_7FEEEE0FFF2:                        ; DATA XREF: .rdata:000007FEEEE2B830↓o
.text:000007FEEEE0FFF2 lea     r8, [rsp+130h+activationCode]
.text:000007FEEEE0FFF7 lea     rdx, [rbp+57h+var_98]
.text:000007FEEEE0FFFB lea     rcx, [rsp+130h+var_F0]
.text:000007FEEEE10000 call    cs:??AQJsonObject@@QEAA?AVQJsonValueRef@@AEBVQString@@@Z ; QJsonObject::operator[](QString const &)
.text:000007FEEEE10006 mov     rcx, rax
.text:000007FEEEE10009 lea     rdx, [rbp+57h+var_D0]
.text:000007FEEEE1000D call    cs:?toString@QJsonValueRef@@QEBA?AVQString@@XZ ; QJsonValueRef::toString(void)
.text:000007FEEEE10013 nop
.text:000007FEEEE10014
.text:000007FEEEE10014 loc_7FEEEE10014:                        ; DATA XREF: .rdata:000007FEEEE2B838↓o
.text:000007FEEEE10014 lea     rcx, [rsp+130h+activationCode]
.text:000007FEEEE10019 call    cs:??1QString@@QEAA@XZ          ; QString::~QString(void)
.text:000007FEEEE1001F mov     edx, 4
.text:000007FEEEE10024 lea     rcx, aDate                      ; "date"
.text:000007FEEEE1002B call    cs:?fromAscii_helper@QString@@CAPEAU?$QTypedArrayData@G@@PEBDH@Z ; QString::fromAscii_helper(char const *,int)
.text:000007FEEEE10031 mov     [rsp+130h+var_108], rax
.text:000007FEEEE10036
.text:000007FEEEE10036 loc_7FEEEE10036:                        ; DATA XREF: .rdata:000007FEEEE2B840↓o
.text:000007FEEEE10036 lea     r8, [rsp+130h+var_108]
.text:000007FEEEE1003B lea     rdx, [rbp+57h+var_68]
.text:000007FEEEE1003F lea     rcx, [rsp+130h+var_F0]
.text:000007FEEEE10044 call    cs:??AQJsonObject@@QEAA?AVQJsonValueRef@@AEBVQString@@@Z ; QJsonObject::operator[](QString const &)
.text:000007FEEEE1004A mov     rcx, rax
.text:000007FEEEE1004D lea     rdx, [rbp+57h+var_B8]
.text:000007FEEEE10051 call    cs:?toString@QJsonValueRef@@QEBA?AVQString@@XZ ; QJsonValueRef::toString(void)
.text:000007FEEEE10057 nop
.text:000007FEEEE10058
.text:000007FEEEE10058 loc_7FEEEE10058:                        ; DATA XREF: .rdata:000007FEEEE2B848↓o
.text:000007FEEEE10058 lea     rcx, [rsp+130h+var_108]
.text:000007FEEEE1005D call    cs:??1QString@@QEAA@XZ          ; QString::~QString(void)
.text:000007FEEEE10063 mov     edx, 7
.text:000007FEEEE10068 lea     rcx, aKeyhash                   ; "keyHash"
.text:000007FEEEE1006F call    cs:?fromAscii_helper@QString@@CAPEAU?$QTypedArrayData@G@@PEBDH@Z ; QString::fromAscii_helper(char const *,int)
.text:000007FEEEE10075 mov     [rbp+57h+var_C8], rax
.text:000007FEEEE10079
.text:000007FEEEE10079 loc_7FEEEE10079:                        ; DATA XREF: .rdata:000007FEEEE2B850↓o
.text:000007FEEEE10079 lea     r8, [rbp+57h+var_C8]
.text:000007FEEEE1007D lea     rdx, [rbp+57h+var_88]
.text:000007FEEEE10081 lea     rcx, [rsp+130h+var_F0]
.text:000007FEEEE10086 call    cs:??AQJsonObject@@QEAA?AVQJsonValueRef@@AEBVQString@@@Z ; QJsonObject::operator[](QString const &)
.text:000007FEEEE1008C mov     rcx, rax
.text:000007FEEEE1008F lea     rdx, [rbp+57h+var_C0]
.text:000007FEEEE10093 call    cs:?toString@QJsonValueRef@@QEBA?AVQString@@XZ ; QJsonValueRef::toString(void)
.text:000007FEEEE10099 nop
.text:000007FEEEE1009A
.text:000007FEEEE1009A loc_7FEEEE1009A:                        ; DATA XREF: .rdata:000007FEEEE2B858↓o
.text:000007FEEEE1009A lea     rcx, [rbp+57h+var_C8]
.text:000007FEEEE1009E call    cs:??1QString@@QEAA@XZ          ; QString::~QString(void)
.text:000007FEEEE100A4 mov     edx, 8
.text:000007FEEEE100A9 lea     rcx, aCodehash                  ; "codeHash"
.text:000007FEEEE100B0 call    cs:?fromAscii_helper@QString@@CAPEAU?$QTypedArrayData@G@@PEBDH@Z ; QString::fromAscii_helper(char const *,int)
.text:000007FEEEE100B6 mov     [rsp+130h+var_F8], rax
.text:000007FEEEE100BB
.text:000007FEEEE100BB loc_7FEEEE100BB:                        ; DATA XREF: .rdata:000007FEEEE2B860↓o
.text:000007FEEEE100BB lea     r8, [rsp+130h+var_F8]
.text:000007FEEEE100C0 lea     rdx, [rbp+57h+var_78]
.text:000007FEEEE100C4 lea     rcx, [rsp+130h+var_F0]
.text:000007FEEEE100C9 call    cs:??AQJsonObject@@QEAA?AVQJsonValueRef@@AEBVQString@@@Z ; QJsonObject::operator[](QString const &)
.text:000007FEEEE100CF mov     rcx, rax
.text:000007FEEEE100D2 lea     rdx, [rbp+57h+var_A8]
.text:000007FEEEE100D6 call    cs:?toString@QJsonValueRef@@QEBA?AVQString@@XZ ; QJsonValueRef::toString(void)
.text:000007FEEEE100DC nop
.text:000007FEEEE100DD
.text:000007FEEEE100DD loc_7FEEEE100DD:                        ; DATA XREF: .rdata:000007FEEEE2B868↓o
.text:000007FEEEE100DD lea     rcx, [rsp+130h+var_F8]
.text:000007FEEEE100E2 call    cs:??1QString@@QEAA@XZ          ; QString::~QString(void)
.text:000007FEEEE100E8 mov     edx, 5
.text:000007FEEEE100ED lea     rcx, aError                     ; "error"
.text:000007FEEEE100F4 call    cs:?fromAscii_helper@QString@@CAPEAU?$QTypedArrayData@G@@PEBDH@Z ; QString::fromAscii_helper(char const *,int)
.text:000007FEEEE100FA mov     [rsp+130h+var_110], rax
.text:000007FEEEE100FF
.text:000007FEEEE100FF loc_7FEEEE100FF:                        ; DATA XREF: .rdata:000007FEEEE2B870↓o
.text:000007FEEEE100FF lea     r8, [rsp+130h+var_110]
.text:000007FEEEE10104 lea     rdx, [rsp+130h+var_E0]
.text:000007FEEEE10109 lea     rcx, [rsp+130h+var_F0]
.text:000007FEEEE1010E call    cs:??AQJsonObject@@QEAA?AVQJsonValueRef@@AEBVQString@@@Z ; QJsonObject::operator[](QString const &)
.text:000007FEEEE10114 lea     rdx, [rbp+57h+var_58]
.text:000007FEEEE10118 mov     rcx, rax
.text:000007FEEEE1011B call    cs:?toValue@QJsonValueRef@@AEBA?AVQJsonValue@@XZ ; QJsonValueRef::toValue(void)
.text:000007FEEEE10121 nop
.text:000007FEEEE10122
.text:000007FEEEE10122 loc_7FEEEE10122:                        ; DATA XREF: .rdata:000007FEEEE2B878↓o
.text:000007FEEEE10122 xor     edx, edx
.text:000007FEEEE10124 mov     rcx, rax
.text:000007FEEEE10127 call    cs:?toInt@QJsonValue@@QEBAHH@Z  ; QJsonValue::toInt(int)

формируем такой json

if __name__=="__main__":
    activation_code={'activation_code':'activation_code1',
                     'date':'',
                     'keyHash':'keyHash1',
                     'codeHash':'codeHash1',
                     'error':0}
    
    activation_code=encodeRSA(priv,activation_code)
    print activation_code 

и снова подставляем результат в форму activation code

WyJZazZaVld6VVdxSkZRTkRVMUxIUUxsVllJZVA3MnZpaWJVUmV1UGlWcitRMnJxdWtYc3MzQ3pMQncrSUFORmtOWkFhZGN0OVJEdGdNanVUT2ZtNWpMQ2tYZDBrRi95QUFJdDZhV2Nobk1iVjlJcGdRZWxoSHhvUE9QMmlBcCtRRmxRS1NTZkFaWDByRmxiclhGWGdDazB4N0tGdWRtTTVEeDBVWXljNjFPRm5ncDZiM0ZRWTBCQndBT0tXRVd6Unp4UVJjZWdvN1pOVWozd3JDOCt4ajRJZU9oaERGUy95alUzTFBPZXRMZktNNmdYUkFuOGV4bk0yQlhuazlXK0l1RTlLWnZzT2o4U1V6eDdwc2xmTmc4bEtzR0VBcHk4QVRaSThMMTdUR010YTRKdFBMOFpONjArNmpXQ2dibFphMFZVcGJWcTVBc2ZzOEFlZ2ZGTTNJcGc9PSJd

тут еще код в котором проверяются параметры json

проверяется формат серийного номера

маска

сериный номер должен быть в формате
123456-123456-123456-123456

проходим и эту проверку

форматируются данные серийника и разбиваются на две части

12345612 3456123456123456

а тут еще и шифруются четырьмя различными константами

проверяется серийный номер

общий алгоритм будет таким

version = [‘8e957302’,‘c8e84503’,‘5abfebbb’,‘49d5b5dd’]

  1. 123456-123456-123456-123456
  2. 123456123456123456123456
  3. 12345612 3456123456123456
  4. des_ecb_encode(‘8e957302’,‘12345612’)==‘3456123456123456’

можем написать генератор для серийного номера

def get_serial(key,pref):
    pref=pref[:8]
    d=DES.new(key)
    e=d.encrypt(pref[:8])
    a=e.encode('hex').upper()
    sn=pref[:6]+'-'+pref[6:]+a[:4]+"-"+a[4:4+6]+'-'+a[4+6:]
    return sn


if __name__=="__main__":
    codes=['8e957302','c8e84503','5abfebbb','49d5b5dd']
    code='49d5b5dd'
    
    serial=get_serial(code,'12345678')
    print serial

получим такое

123456-78A8E7-04D461-0D7679

как результат прошли еще одну проверку

на этот раз у меня все, на следующем уроке мы сформируем правильный activation code

Очень классно.