Mitm-perk-quiz

hacking Perk Pop Quiz (Android/iOS game) by mitm


Project maintained by alshell7 Hosted on GitHub Pages

Perk Pop Quiz

Well its one of those apps (available for Android/ iOS) which award you with special bonuses like Gift Cards, points redeeming to Cash!, or even buy few stuff with the points you have collected by playing quiz, answering to the questions on any topic you like. As simple as that.

 

So? What’s mitm-perk-quiz?

Well straight and simple, here we are going to learn, how to be a serious smart pant, a great genius, a walking Wikipedia, a human version of IBM’s Watson, who could just answer any any general question, like how Google would come up with the results!. So, we learn here now, and then, answer the questions that are asked to us in this Perk Pop Quiz app without having ever gone wrong, and finally to earn points (the cash redeeming you know).

Okay! that’s enough now.. I was just kidding 💀 I ain’t got any super powers to help you with or something I can make you cast a spell to be that “Intelligent” 😉. Yes but that’s true, that you would answer any question asked to you inside the app, so in end you can collect the points smoothly without having do no mistakes.

Ahem!, pretty straight to say, just get to know the right answer, and select it from the options given to you for that question of that particular session.

So how are we going to do that?. Exactly, that is what we are going to know how, check it out below..

 

Scenario...

Okay!, I ain’t gonna narrate any story story here 💭. Its just how it all started for this. I were doing some web debugging (sniffing HTTP requests) on the phone from my PC (performing a mitm, Man In The Middle attack, not with any “attack” intentions really), on few of the android apps I installed lately, just to check how and why often do they communicate with network in background (of course I am damn concerned with my phones soon battery drain issue too 😞 ..)

It was time for this Perk Pop Quiz app. Gosh!, it had too many HTTP requests running in background. I played a solo quiz on a random quiz category, and noticed, that in one of the HTTP GET requests the app made (prior to the moment I started the game), it contained all the Questions, Options, Answers, in JSON format. So now I got a bit mouth watered. I had almost thought of getting a power bank after having it known.

But damn!, there was a critical issue to have them utilized, the answers, were, ENCRYPTED!. And those can only be decrypted by the app installed by the user. Spent 4 days trying to analyze how is the app decrypting the answers.

Reverse Engineered the apk file using Apktool. Deep shoveled the source code, apprehended the Activity where the quiz is performed, and finally found the exact piece of code which decrypts the answers. And after that, I got a complete idea, and then I could wind up the stuff like below, when the session of quiz is just about to begin (after the ads finish displaying, and the game ticks to start off) these things happen..

 

Server Responsibility:

Host = api-tv.perk.com

URL = /v5/ppq/questions.json

  1. Correct answer is encrypted (actually hashed) using SHA-1 algorithm.

  2. The Correct answer of each question is digested (as hexadecimal) by adding the access_token (authentication token otherwise) that was provided for the user with the right option id of that question.

  3. Server sends (on a user’s single HTTP GET request) the questions, options in normal text, with correct answer encrypted from the above process mentioned in step 2.

A raw idea, is something like,

curl --get https://api-tv.perk.com/v5/ppq/questions.json?access\_token={a 40 character value}&category_id={ type of quiz represented numerically }&limit= { number of questions }

 

Client (User/App) Responsibility:

Example, the Response received now is, {"status":"success","message":null,"data":{"batch_id":"df9ec8c7c5599bdab553c24b1a2071bbcbbd738b8227549e20d9f40e3649ff20","questions":[

{"id":"226702","question_text":"What is a common name for the Aurora Borealis?","is_boolean":false,"img":null,"answers":[{"id":"905977","answer_text":"Gegenschein"},{"id":"905978","answer_text":"Plage"},{"id":"905975","answer_text":"Northern Lights"},{"id":"905976","answer_text":"Zodiacal light"}],"correct":"62a541f079038ed11c83b4615c926828a42d67a3"},

{"id":"226700","question_text":"What is usually seen near the poles in the night sky that can be red, yellow or green?","is_boolean":false,"img":null,"answers":[{"id":"905969","answer_text":"Gegenschein"},{"id":"905968","answer_text":"Zodiacal light"},{"id":"905967","answer_text":"Aurora"},{"id":"905970","answer_text":"Plage"}],"correct":"a1359ec9c77390088796895854a7d2d5b803eedc"},

{"id":"226659","question_text":"When the Earth is directly between the Sun and the Moon, it is called a\/an _________ eclipse.","is_boolean":false,"img":null,"answers":[{"id":"905806","answer_text":"Transit"},{"id":"905803","answer_text":"Lunar"},{"id":"905804","answer_text":"Solar"},{"id":"905805","answer_text":"Inferior conjunction"}],"correct":"0d5f38b422b2650b74ab925c86eb7749b6bc600f"},

{"id":"226751","question_text":"The mantle makes up about ____% of Earth's volume.","is_boolean":false,"img":null,"answers":[{"id":"906171","answer_text":"84"},{"id":"906172","answer_text":"97"},{"id":"906173","answer_text":"12"},{"id":"906174","answer_text":"20"}],"correct":"cb5a1e645f1ab427ac4b1654db91d0d37f5d0098"},

{"id":"226604","question_text":"What mineral has perfect cleavage in six directions?","is_boolean":false,"img":null,"answers":[{"id":"905586","answer_text":"Fluorite"},{"id":"905585","answer_text":"Sodalite"},{"id":"905583","answer_text":"Sphalerite"},{"id":"905584","answer_text":"Diamond"}],"correct":"44829a277381a356295ebllb1c1ea4d827e31d1a"},

{"id":"226580","question_text":"What would you call the solid material that is carried within the stream?","is_boolean":false,"img":null,"answers":[{"id":"905487","answer_text":"Suspended load"},{"id":"905490","answer_text":"Bed load"},{"id":"905488","answer_text":"Dissolved load"},{"id":"905489","answer_text":"Floating load"}],"correct":"ece190cfc99bf5800a5a8d9b93999dca89dd828f"}],

"current_streak":0,"longest_streak":1,"answer_responses":{"correct":["You're on a roll!","Smart cookie!","NAILED IT!","Aww YEAH!",":D","BOOM!","BINGO!!!","You're on FIRE!","BINGO!!","Correct!","Good one!","YES!"],"incorrect":["Try again!","Try another one.",":(","Dang!","Nope :(","Ouch"]}}}

You can notice the correct answer for every question is encrypted.

  1. Receive the JSON data from the server by providing the access_token to it, that was registered and stored for that particular user.

  2. Parse the data and display it graphically in structured way to user.

  3. When the user selects the option, verify if it is correct in this way,

    1. Add (concatenate) the the access_token and the option’s id (JSON attribute) of that question.

    2. Calculate the SHA-1 of the sum from above.

    3. Check each of the resultant hash of the options id’s are equal to the Correct attribute of the question. The one which equals is the right option!

A snippet for it goes like,

def verifyRightAnswer(answer_id, correct_sha, authentication_token):
        h = HashUtil.sha1Hash
        right_answer_id = str(answer_id)
        auth_token = str(authentication_token)
        auth_correction = auth_token + right_answer_id
        result = h(auth_correction)
        #print(result)
        return (result == correct_sha)

Whoaaa!! All this happens is in matter of a second, and you have only the next very 5 seconds already to answer up for the next question, by then you’ve got to,

  1. Intercept the the HTTP requests between your phone (client) and the perk servers.

  2. Process the JSON data and decrypt the answers and view them.

  3. Search for question and its answer that is randomly asked from the list of questions the server sends.

Huff!! hell go with the perk! You must be saying this to me :trollface:

Do you think we should give up here?.. Nope I don’t think so 👼, as long as we can automate few things.

But before we proceed further, I highly recommend you have the prerequisites that you need in order to achieve this hack successfully.

Things Required

So what are we waiting for?, lets get started right away!

STEP 1 (setting up the things...)

Make sure your PC and your android phone is connected to the same network. That would simply mean, connecting to a same Wi-Fi.

Setting up the fiddler, so that we can intercept the requests of the Perk Pop Quiz on your phone.

I haven’t tried up with iPhone version. Well things should remain same as long as iOS permits to install the certificates, and run proxy over Wi-Fi.

If everything was followed up correctly so far, you should see all the web sessions (the requests and their responses) captured inside fiddler, made by all your installed android apps (and of your systems too).

STEP 2 (getting your Perk identity)

Finding the authentication token (access_token)

As the requests are made by the phone, you can see them getting added up in the session list of the Fiddler one after the other. Its time now, we capture that request which holds the access_token that designates our identity in the app.

The above two steps are not required to perform repeatedly, on each hack. As long as you are not performing it on different Wi-Fi network.

STEP 3 (sharpening up the tools)

Make sure you’ve installed SyntaxView addon for fiddler. Not compulsory though.

This was the most difficult part for me to step up. But thankfully succeeded in making it out. I wouldn’t even write this all if I failed. Everything was done, I got even the script written to decrypt, and display the results. So when I tried playing the quiz, with the things I had now, the moment I begun with the quiz, captured the response (one which server sends from the URL /v5/ppq/questions.json), and immediately fed the response data to the script from the notepad, and got the results too. But guess what? I could just still answer one bloody question correctly :D.

Because it took me 13 seconds to do this after the quiz started. And another 5-6 seconds to search for question and its answer that is randomly asked from the list server sends (which I was talking about initially). And of all, the whole quiz session is just of 30-45 seconds hardly. I was doom struck with this. Can’t just have a partner to help me find and read out the answers. It sounds so ugly-hack! Yew :X.

Then I taught of integrating any of open source available sniffers like Pyshark or Scapy within my script. So that the things I did by feeding the response data to script manually, should now be done automatically in background, by programming in such a way to sniff just on the host api-tv.perk.com, and any request made to this host matches to the request which we need, its response should be fed to the scripts main module which process’s and display the results. Which would remove that 13-15 seconds lag to answer.

Googled a lot to get it done. But, Windows didn’t let me to integrate it in some or the other way. The dependencies, different build tools required, the sniffers failed to compile, version mismatch issues with the dependencies, huff!, I reached the ends but felt to just give up. It was like all the time digging in, went in misery so far.

But a few days later, I accidentally came on this, Customize Rules..option under Rules of the menu, in Fiddler. Damn good it was to know there’s such option too. Got hands little dirty in it, and Tada!, found the solution. The steps to follow are below..

Make the script to self trigger, the moment when quiz starts

    if (oSession.fullUrl.Contains("https://api-tv.perk.com/v5/ppq/questions.json?") && oSession.responseCode == 200)
    {
      //Save the complete response in a file that you created
      var filePerk = "H:\\#alshell\\perk_data.json";
      System.IO.File.WriteAllText(filePerk, oSession.GetResponseBodyAsString());

      //This is the location of the script which processes the response.
      //Change it to your version of location.
      //Notice and place the Backslash Constants correctly.
      var mitmScript: String = "\"H:\\#projects\\Python Scripts\\mitm-perk-quiz.py\"";

      //Parameter to send for the python script
      //This is different from the filePerk object above though,
      //just the Backslash Constants are included well
      //for the sake of correct parameter to be passed for the script
      var jf: String = "\"H:\\#alshell\\perk_data.json\"";

      //The location of the python interpreter must be present
      //in the Environment Variables of your system.
      //Otherwise the script wont be able to compile. The latest python releases have
      //the PATH of python automatically set during the installation.
      var myProcessStartInfo: ProcessStartInfo = new ProcessStartInfo("python");

      //The script returns the output, configure the process to receive it through Standard Output
      myProcessStartInfo.UseShellExecute = false;
      myProcessStartInfo.RedirectStandardOutput = true;

      //Set the arguments to the script
      myProcessStartInfo.Arguments = mitmScript + " --jsonfile " + jf;

      var myProcess: Process = new Process();
      myProcess.StartInfo = myProcessStartInfo; 

      //Start the execution of script
      myProcess.Start();

      //Read the output
      var myStreamReader: StreamReader = myProcess.StandardOutput; 
      var myResults = myStreamReader.ReadToEnd();

      //Wait from the script to exit and then quit the process executing it.
      myProcess.WaitForExit(); 
      myProcess.Close();

      //Display the results
      MessageBox.Show(myResults);

    }

  That is it! Done. You are just a step away now.

 

FINAL STEP

Set the access_token in the script.

Ultimately...

Hope you felt cozy with the steps. I’d be grateful if I were too let know with different approach than this. Have a nice perk time 💥

License

The content of this project itself is licensed under the Creative Commons Attribution 3.0 license, and the underlying source code used to format and display that content is licensed under the MIT license.