· 6 years ago · Nov 01, 2019, 03:30 PM
1import requests
2import json
3import copy
4import random
5import bs4
6import re
7import des
8import base64
9import time
10import random
11import datetime
12from Crypto.Cipher import AES
13from hashlib import pbkdf2_hmac
14from os import urandom
15from padding import pad
16
17
18HEX_LIST = list(range(97, 103)) + list(range(48, 58))
19
20DES_KEY = "co.vmob.sdk.android.encrypt.key";
21MASTER_KEY = "d4eee068-272a-4aec-9681-5e16dcef6fbd";
22
23
24#Get the account token ID named: bearer <ACCOUNT KEY>
25def get_registration_token(content, headers = base_headers):
26
27 #Check if content are ok
28 if not content:
29 return None
30
31 #Create a new device id to bypass the checking of devide
32 fake_device_id = make_fake_device_uid().decode('ascii')[:-1].replace("/", "_").replace("+", "-") + "_"
33 #Create a new plexure for bypass the control of the endpoint
34 plexure_api = encryptAES(f'{MASTER_KEY}|{getModifiedDate()}', fake_device_id)
35
36 #Create temp headers for this request using the base_headers as base
37 tmp_headers = copy.deepcopy(headers)
38
39 #Change the device id to avoid recognizing
40 tmp_headers["x-vmob-uid"] = fake_device_id
41 #Change the plexure key for this vmob
42 tmp_headers["x-plexure-api-key"] = plexure_api
43 #Space allocated to request the offer
44 tmp_headers["Content-Length"] = str(len(content))
45
46 #make post request to create the account
47 response = requests.post(url, content, headers=tmp_headers).text
48
49 #Content lenght if all go Correct
50 if "bearer" in response:
51 return 'bearer ' + json.loads(response)['access_token']
52
53 #The response is not correct...
54 return None
55
56
57#Get a right date to be used for the encryption of the plexure
58def getModifiedDate():
59
60 now = datetime.datetime.utcnow()
61 return str((now - datetime.timedelta(seconds=600)).isoformat(timespec="microseconds")) + '0Z'
62
63
64#Make a fake device uid using DES encryption
65def make_fake_device_uid(password=DES_KEY):
66
67 salt = ''.join([chr(random.choice(HEX_LIST)) for _ in range(16)])
68 cipher = des.DesKey(password[:8].encode('ascii'))
69 value = cipher.encrypt(f'co.vmob.android.sdk.{salt}'.encode('ascii'), padding=True)
70
71 return base64.encodebytes(value)
72
73
74#Make the inverse operation
75def decryptDES(text, password=DES_KEY):
76 text = text[:-1].replace("_", "/").replace("-", "+")
77 text = base64.decodebytes(text.encode('utf-8'))
78
79 cipher = des.DesKey(password[:8].encode('utf-8'))
80 value = cipher.decrypt(text)
81
82 return value.decode('utf-8')
83
84
85def encryptAES(text, password):
86
87 salt = urandom(8)
88 block = pbkdf2_hmac('sha1', password.encode('utf-8'), salt, 100, 48)
89
90 key = block[:32]
91 iv = block[32:48]
92
93 cipher = AES.new(key, AES.MODE_CBC, iv)
94 text = pad(text.encode('utf-8'), AES.block_size, style="pkcs7")
95
96 encrypted = cipher.encrypt(text) + salt
97
98 return base64.encodebytes(encrypted).decode('utf-8').replace("\n", "").replace(" ", "")
99
100
101#Get all the content of json response using token and the productID(offer code)
102def get_offer(token, offerID, headers = base_headers):
103
104 #Used to call the reedemOffers API
105
106 #Create a new device id to bypass the checking of devide
107 fake_device_id = make_fake_device_uid().decode('ascii')[:-1].replace("/", "_").replace("+", "-") + "_"
108 #Create a new plexure for bypass the control of the endpoint
109 plexure_api = encryptAES(f'{MASTER_KEY}|{getModifiedDate()}', fake_device_id)
110
111 #Create temp headers for this request using the base_headers as base
112 tmp_headers = copy.deepcopy(headers)
113
114 #Change the device id to avoid recognizing
115 tmp_headers["x-vmob-uid"] = fake_device_id
116 #Change the plexure key for this vmob
117 tmp_headers["x-plexure-api-key"] = plexure_api
118 #Change the token with the last account's registration_token
119 tmp_headers["Authorization"] = token
120 #Used by default on the call of API
121 tmp_headers["x-vmob-location_accuracy"] = "3.0"
122 #Space allocated to request the offer
123 tmp_headers["Content-Lenght"] = "17"
124
125 #Create a JSON file which send the offerID
126 content = json.dumps({"offerId":int(offerID),"offerInstanceUniqueId":str(offerID)})
127
128 response = requests.post(url, content, headers=tmp_headers).text
129
130 #Check for some error
131 if "error" in response:
132 return None
133
134 #All go right so it will return the data as a dict
135 return json.loads(response)