Skip to content

Instantly share code, notes, and snippets.

@Redict
Last active May 5, 2024 04:25
Show Gist options
  • Save Redict/f6aa178890ef2e4f0f1e821d04d88773 to your computer and use it in GitHub Desktop.
Save Redict/f6aa178890ef2e4f0f1e821d04d88773 to your computer and use it in GitHub Desktop.
WolframAlpha Pro free and unlimited access to API
import requests
from hashlib import md5
from urllib.parse import urlsplit, urlencode, unquote_plus
headers = {"User-Agent": "Wolfram Android App"}
APPID = "3H4296-5YPAGQUJK7" # Mobile app AppId
SERVER = "api.wolframalpha.com"
SIG_SALT = "vFdeaRwBTVqdc5CL" # Mobile app salt
s = requests.Session()
s.headers.update(headers)
def calc_sig(query):
"""
Calculates WA sig value(md5(salt + concatenated_query)) with pre-known salt
@query
In format of "input=...&arg1=...&arg2=..."
"""
params = list(filter(lambda x: len(x) > 1, list(map(lambda x: x.split("="), query.split("&"))))) # split string by & and = and remove empty strings
params.sort(key = lambda x: x[0]) # sort by the key
s = SIG_SALT
# Concatenate query together
for key, val in params:
s += key + val
s = s.encode("utf-8")
return md5(s).hexdigest().upper()
def craft_signed_url(url):
"""
Craft valid signed URL if parameters known
@query
In format of "https://server/path?input=...&arg1=...&arg2=..."
"""
(scheme, netloc, path, query, _) = urlsplit(url)
_query = {"appid": APPID}
_query.update(dict(list(filter(lambda x: len(x) > 1, list(map(lambda x: list(map(lambda y: unquote_plus(y), x.split("="))), query.split("&")))))))
query = urlencode(_query)
_query.update({"sig": calc_sig(query)}) # Calculate signature of all query before we set "sig" up.
return f"{scheme}://{netloc}{path}?{urlencode(_query)}"
def basic_test(query_part):
"""
Simple PoC
@query_part
Example is "input=%url_encoded_string%&arg1=...&arg2=..."
https://products.wolframalpha.com/api/documentation/#formatting-input
"""
r = s.get(craft_signed_url(f"https://{SERVER}/v2/query.jsp?{query_part}"))
if r.status_code == 200:
return r.text
else:
raise Exception(f"Error({r.status_code}) happened!\n{r.text}")
if __name__ == "__main__":
print(basic_test("input=y%27+%3D+y%2F%28x%2By%5E3%29&podstate=Solution__Step-by-step+solution&format=plaintext&output=json"))
@Redict
Copy link
Author

Redict commented Jan 27, 2020

Hello, everyone! Mobile applications have been very vulnerable lately. That's why I decided to take a look at WolframAlpha's Android app in search of sensitive information. I found the AppId as well as the salt for the signature generation algorithm, which allowed me to use WolframAlpha Pro absolutely free and unlimited of course(no 2000 per month limit). That's how I found out all this. First I ran jadx and started looking at the code quickly, and there I found the following important classes to understand.

com.wolfram.alpha.:
WAEngine
WAQuery
WAQueryParameter
com.wolfram.android.alpha.asynctask.

QueryTask
com.wolfram.android.alpha.*
WolframAlphaApplication
The QueryTask class contains a method for generating a signature -- getMd5Digest (which also contains salt), as well as a way to setup it in setSignatureParameter. The WolframAlphaApplication class contains AppId.

Then, I wrote a script in Python that uses the information I received.

Here I publish PoC for solving differential equation with step-by-step parameter. https://gist.github.com/Redict/f6aa178890ef2e4f0f1e821d04d88773.

Conclusion: Obfuscate your mobile applications to make them harder to reverse.

@AngeloD2022
Copy link

How did you obtain the salt value? Not sure if they've obfuscated it since, but from looking at it, it's not clearly defined. Anyhow, your script still works and thank you.

@Redict
Copy link
Author

Redict commented Feb 11, 2021

@AngeloD2022 it is located as plaintext in apk file

@Wowzerf
Copy link

Wowzerf commented Feb 20, 2021

Hello! New here I was wondering how do I set it up once I downloaded the zip file on my computer?

@Redict
Copy link
Author

Redict commented Feb 20, 2021

Hello! New here I was wondering how do I set it up once I downloaded the zip file on my computer?

There is my website for it, but it's currently not working, i'll fix it as soon as possible

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment