Reverse engineering psychology tests your life major

Posted by cloudzilla on Fri, 19 Nov 2021 05:38:30 +0100

Packet capture analysis

By capturing the application with burpsuite, it is found that the application is a pure front-end project and does not send data to the server. The front end uses React + TypeScript to build the project, and finally uses Webpack to package it.

You can see the packaged file structure of the webpack in the browser mapped source.

The topic switching of the page is realized by changing the background to take different pictures.

algorithm

You can see that the program saves the index of the options selected by the tester in the array (there are multiple choices, so it is an array nested array), and prints it on the console. Print the array every time you answer a question.

Follow up this index.tsx

import React from 'react'
import './index.pcss'
import {FetchesContext} from "@util/reducer"
import html2Canvas from 'html2canvas'
// @ts-ignore
import result from './result'
import {select_map} from '../p-2/q-10'

// const done_string = ["economics", "philosophy", "law", "sociology", "pedagogy", "Chinese language and literature", "foreign linguistics", "journalism", "history", "Mathematics", "physics", "Chemistry", "life science", "geography", "psychology", "computer science and technology", "civil engineering", "architecture", "Electromechanical Engineering", "agriculture and forestry", "medicine", "management", "art", "Drama, film and television director", "performing art", "Sports", "Archaeology", "E-sports"]
const done_string_2 = ["jingjixue", "zhexue", "faxue", "shehuixue", "jiaoyuxue", "hanyuyan", "waiguo", "xinwenxue", "lishixue", "shuxue", "wulixue", "huaxue", "shengmingkexue", "dilixue", "xinlixue", "jisuanjikexue", "tumugongcheng", "jianzhuxue", "jidiangongcheng", "nonglinxue", "yixue", "guanlixue", "yishu", "xijuyingshi", "biaoyan", "tiyuxue", "kaoguxue", "dianzijingji"]

export default () => {
  const ctx = React.useContext(FetchesContext)

  const {fetchesState: {name, profession, select_q_list}} = ctx

  const select = select_q_list.reduce((l: any, f: any, i: number) => {
    if (i !== 9) {
      // @ts-ignore
      l.push([f.index])
    } else {
      l.push(f.map((v: any) => select_map.indexOf(v)).sort((a: any, b: any) => a - b))
    }

    return l
  }, [])

  const index = result(select.slice(1))

  const type = done_string_2[index]

  console.log(type)

  const [src, changeSrc] = React.useState('')

  React.useEffect(() => {
    html2Canvas(document.getElementById('root'), {
      useCORS: true,
      width: 750,
      height: 1334,
      windowWidth: 750,
      windowHeight: 1334,
    })
      .then((canvas: any) => {
        canvas.toDataURL("image/png")

        changeSrc(canvas.toDataURL("image/jpeg"))
      })

  }, [])

  return (
    <div id="done" className={type}>
      {src && <img src={src} className="done-img" alt="" />}

      <div className="title">learn<span>{profession}</span>professional<span className="name">{name}</span></div>
      <div className="img-title" />

      <div className="logo" />

      <div className="code" />
    </div>
  )
}

Here, the Pinyin of the final result is saved in an array (finally, the Pinyin of the result is obtained through the index and printed on the console). Select is the index array of the user's selection item, and this array is passed to the result module to return the index of the recommended result (the select is intercepted and the selection item of the first question is removed).
The file corresponding to result is result.js
result.js file content

// Result page id:
// 0: Economics
// 1: Philosophy
// 2: Law
// 3: Sociology
// 4: Pedagogy
// 5: Chinese language and Literature
// 6: Foreign Linguistics
// 7: Journalism
// 8: History
// 9: Mathematics
// 10: Physics
// 11: Chemistry
// 12: Life Science
// 13: Geography
// 14: Psychology
// 15: Computer science and technology
// 16: Civil Engineering
// 17: Architecture
// 18: Electromechanical engineering
// 19: Agroforestry
// 20: Medicine
// 21: Management
// 22: Art
// 23: drama film and television director
// 24: Performing Arts
// 25: Physical Education
// 26: Archaeology
// 27: E-sports

//10 questions, choose to pass in the array, because there are multiple choices, and the array is set in the array
//The selection order starts from 0, 0 represents the first option, 1 represents the second
//For example, select: [0], [1], [3], [0], [0,1,2,3], [0,1,2,3,4], [0]]
function getResult(select) {
  if (!Array.prototype.shuffle) {
    Array.prototype.shuffle = function () {
      for (var j, x, i = this.length; i; j = parseInt(Math.random() * i), x = this[--i], this[i] = this[j], this[j] = x)
        return this;
    };
  }
  var config = {
    0: {
      0: [1, 0, 2, 3, 4, 5, 6, 7, 8, 21, 26],
      1: [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 26],
      2: [22, 23, 24, 25, 27],
    },
    1: {
      0: [0, 2, 6, 7, 20, 21, 25],
      1: [3, 4, 24],
      2: [5, 14, 22],
      3: [1, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 23, 26, 27],
    },
    2: {
      0: [1, 3, 4, 5, 9, 10, 14, 21, 22, 23, 24, 27],
      1: [0, 2, 6, 7, 8, 11, 12, 13, 15, 16, 17, 18, 19, 20, 25, 26],
    },
    3: {
      0: [0, 2, 3, 4, 6, 7, 20, 21, 24, 25],
      1: [1, 5, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 22, 23, 26, 27],
    },
    4: {
      0: [1, 3, 4, 5, 9, 10, 14, 21, 22, 23, 24, 27],
      1: [0, 2, 6, 7, 8, 11, 12, 13, 15, 16, 17, 18, 19, 20, 25, 26],
    },
    5: {
      0: [1, 0, 2, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19, 20, 21, 23, 25, 26, 27],
      1: [3, 4, 5, 14, 22, 24],
    },
    6: {
      0: [1, 8, 9, 10, 11, 12, 13, 20, 26],
      1: [5, 22, 23, 24],
      2: [15, 16, 17, 18, 19, 25, 27],
      3: [3, 4, 6, 7, 14],
      4: [0, 2, 21],
    },
    7: {
      0: [1, 8, 9, 10, 11, 12, 13, 20, 26],
      1: [5, 22, 23, 24],
      2: [15, 16, 17, 18, 19, 25, 27],
      3: [3, 4, 6, 7, 14],
      4: [0, 2, 21],
    },
    8: {
      0: [4, 5, 7, 14, 21, 23, 6],
      1: [6, 15],
      2: [13],
      3: [10, 16, 17, 18],
      4: [12, 19, 20, 25],
      5: [1, 2, 7, 21],
      6: [0, 9, 15, 16, 18, 10, 14],
      7: [17, 22, 24, 23],
      8: [3, 8, 26, 13],
      9: [11, 12, 19, 20, 26],
      10: [25, 27],
      11: [22, 24],
    },
    9: {
      0: [],
      1: [],
      2: []
    }
  };

  var result = [];
  for (var topic_num = 0; topic_num < select.length; topic_num++) {
    // Traverse the answer to this question
    for (var j = 0; j < select[topic_num].length; j++) {
      var user_select = select[topic_num][j];
      // Get configuration
      var tmp = config[topic_num][user_select];
      // merge
      result = result.concat(tmp);
    }
  }
  var result_map = {};
  var max = -1;
  // Disrupt the result
  result.shuffle();
  for (var i = 0; i < result.length; i++) {
    if (typeof result_map[result[i]] == "undefined") {
      result_map[result[i]] = 0;
    }
    result_map[result[i]]++;
    if (max == -1) {
      max = result[i];
    } else {
      if (result_map[result[i]] > result_map[max]) {
        max = result[i];
      }
    }
  }

  //console.log(result);
  //console.log(result_map);
  //console.log(max);
  return max;
}

// test
// Console.log (getResult ([[0], [3], [0], [1], [0], [0], [0], [0], [0], [0,5,6], [1]])); / / expected result 1
//getResult([[1],[3],[1],[1],[1],[0],[2],[2],[1,2,6],[1]]); / / expected result 15
//GetResult ([[2], [3], [0], [1], [0], [0], [1], [1], [1], [0,7,10], [1]]); / / expected result 23

export default getResult;

Ten questions are passed in, and each option will correspond to an array of recommended majors. The array saves the index of recommended majors, such as [1, 0, 2, 3, 4, 5, 6, 7, 8, 21, 26].

 for (var topic_num = 0; topic_num < select.length; topic_num++) {
    // Traverse the answer to this question
    for (var j = 0; j < select[topic_num].length; j++) {
      var user_select = select[topic_num][j];
      // Get configuration
      var tmp = config[topic_num][user_select];
      // merge
      result = result.concat(tmp);
    }
  }

This section expands nested arrays into one-dimensional arrays.

if (!Array.prototype.shuffle) {
    Array.prototype.shuffle = function () {
      for (var j, x, i = this.length; i; j = parseInt(Math.random() * i), x = this[--i], this[i] = this[j], this[j] = x)
        return this;
    };
  }

Add shuffle to the Array to disrupt the order of the Array.

 var result_map = {};
 var max = -1;
for (var i = 0; i < result.length; i++) {
    if (typeof result_map[result[i]] == "undefined") {
      result_map[result[i]] = 0;
    }
    result_map[result[i]]++;
    if (max == -1) {
      max = result[i];
    } else {
      if (result_map[result[i]] > result_map[max]) {
        max = result[i];
      }
    }
  }

Traverse the result, result_map[result[i]] + +, result_map[result[i]] saves the number of occurrences of result[i], maintains a max as the mode in the result, and finally returns max (max is the index of the recommended specialty)

summary

The technical route is React+TypeScript+Webpack, single page program, pure front-end application, ten questions, each option of each question will give a list of recommended majors, and finally take the major with the most occurrences as the test result.

Topics: Javascript React