The title provides two files: flag.tar and libarchive.dylib
1, Decompress
flag.tar is a file that cannot be directly decompressed under windwos. Directly decompress it with tar -xvf flag.tar command:
the prompt is not a tar compressed file, but it contains a file header of flag.txt. Decompress a flag.txt file.
use the file flag.tar command to view the file format:
is a POSIX tar compressed package
About POSIX format:
1. Compress
if you use GNU tar, there is a parameter to set the format of the generated file:
-H. -- format = format creates an archive in the specified format
FORMAT is one of the following formats:
gnu | GNU tar 1.13.x format |
---|---|
oldgnu | GNU format as per tar < = 1.12 |
pax | POSIX 1003.1-2001 (pax) format |
posix | Equivalent to pax |
ustar | POSIX 1003.1-1988 (ustar) format |
v7 | old V7 tar format |
so if you want to package the flag directory into a posix format tar package, you can use
tar -cf flag.tar --format=posix flag
Or
tar -cf flag.tar -H posix flag
2. Decompression:
tar -xvf flag.tar -H posix
2, View file
continue to return to the topic and open flag.txt:
every four hexadecimal digits, separated by commas, should be the input or output file used by another file libarchive.dylib. Check the format of libarchive.dylib:
it is a 64 bit dynamic link shared library on the Mac platform
open with IDA64:
3, Analysis program
according to the format of flag.txt file, when inputting and outputting, the data should be formatted with% 04x and% 04x of formatted string. Directly search% 04x and% 04x in IDA string window:
find the output position by% 04X__ int64 __ fastcall archive_ write_ client_ Write (_int64a1, _int64a2, unsigned _int64a3) function:
Function prototype:
int __sprintf_chk (char *s, int flags, size_t len, const char *format, ...)
__sprintf_chk(&v9[v3], 0, 0xFFFFFFFFFFFFFFFFLL, "%04X,", sub_101[v8++]);
sub_101[v8 + +] writes formatted output to & V9 [V3] according to format string "% 04X,"
Function prototype:
void * __memcpy_chk (void *dest, const void *src, size_t len, size_t dstlen)
__memcpy_chk(v10, v9, v18, -1LL);
copy the value of v9 to v10
so let's take a look at sub_101 how does the value of the array come from? Select sub_101 right click Jump to xrefs or shortcut key X to view sub_101 place of array:
the second time is in this archive_ write_ client_ In the write function, click use sub for the first time_ 101 array should be where its value is generated:
posi is the array subscript of a global variable. This sub_ The 1023458 function calculates one sub each time from the input * a1_ 101 [posi].
find the last call sub_ Where the 1023458 function is:
sub_1023456(int a1) function:
sure enough sub_ The 1023457 function calls sub every time in the loop_ The 1023456 function returns different subscript return values as sub according to the input characters_ Parameter of 1023458 function, call sub_1023458 function to sub_101 array assignment.
sub_1023456(int a1) function:
sub_ The actual parameter v9 array of function 1023458 has three elements, which exactly correspond to sub above_ * a1, a1[1], a1[2] of 1023458 function.
find the calling sub again_ Where the 1023457 function is found, it is archive_write_client_write function:
4, Main logic of the program:
therefore, the main logic of the current program is in archive_ write_ client_ In the write function, the flow chart is as follows:
1. First, archive_write_client_write function line 25:
__memcpy_chk(v13, a2, a3, -1LL);
Copy the length a3 bytes of the string from the input string a2 to v13;
2. Then, when the string length A3 > 0x200, call sub_1023457(v13, (unsigned int)a3); Calculate the input string V13;
3,sub_1023456(v5) determines whether each character of the input string belongs to the ctable [] array, sets the pending flag bit according to different situations, and then sets the return value to return;
4. Every 3 times V9 [– v6] = sub_1023456(v5). After resetting the three values of the new v9[3] array, execute sub once_ 1023458(v9),sub_1023458 function mainly calculates a sub_101[v2] = *a1 + 40 * a1[1] + 1600 * a1[2];
5. After the calculation, return to archive_write_client_write function:
__sprintf_chk(&__s[v3], 0, 0xFFFFFFFFFFFFFFFFLL, "%04X,", sub_101[v11++]);
Will put sub_101[v8 + +] writes the formatted output to & V9 [V3] according to the format string "% 04X,".
5, Reverse thinking:
So we now know the final result sub_101, to get the initial input v13.
Step 1:
1. The first is sub_ Sub solution in 1023458 function_ 101 [V2] = a1 + 40 * a1[1] + 1600 * a1[2] this ternary system of linear equations, each sub_ The values of 101 [V2] can be calculated to obtain the values A1, a1[1], a1[2] of a group of v9 arrays:
*a1=sub_101[v2] % 40; a1[1]=(sub_101[v2] / 40) % 40; a1[2]=sub_101[v2] / 1600;
Step 2:
2. After that, the value of each group v9 array corresponds to one sub_1023456 the character input by the function, that is, find the input character (the character corresponding to the ctable array subscript) according to the function return value (ctable array subscript). sub_1023457 function call sub_1023456(v5) assigns a value to the three numbers of v9 array, and then calls sub_1023458 function.
(1)sub_ The principle of 1023456 (V5) function is to judge the input characters. If they belong to the first 39 of the ctable array, pending is set to 0, the corresponding ctable array subscript i is directly returned, and after returning, the cycle of assigning value to v9[1] will exit;
(2) If it belongs to the last 39 (i+39) of the ctable array, 39 is returned, and the next return value is i; If it does not belong to the ctable array, 37 is returned.
therefore, when we know the return value, we need to push back to get the input characters, which can be divided into two cases: the return value is 39, that is, it belongs to the last 39 characters, and the return value is less than 39, that is, it belongs to the first 39 characters.
here, for the convenience of understanding sub_1023457 and sub_1023456 function, we directly reproduced its logic in C language:
#include<stdio.h> #include<stdbool.h> bool pending; int sub_1023456_shifted = -1; int ctable[] = { 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x20, 0x0A, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x28, 0x21, 0x40, 0x23, 0x2C, 0x2E, 0x3F, 0x2F, 0x2A, 0x29, 0x3C, 0x3E, 0x00}; int main() { char * v3; // rax unsigned int v5; // [rsp+4h] [rbp-2Ch] int v6; // [rsp+8h] [rbp-28h] int v9[3]; // [rsp+1Ch] [rbp-14h] BYREF char a1[] = "abcABc";//Define a character array int length = sizeof(a1); int i; v6 = 3; v3 = a1; // Input string while ( v3-a1 < length ) { v5 = *v3++; //printf("%c ",v5); pending = 1; // This is a global bool variable, pending, in sub_ Its value is also changed in 1023456 (V5) while ( pending ) { v9[--v6] = sub_1023456(v5); // v9[2], v9[1], v9[0] =, a character v5 can get up to 3 different return values //printf("%d ",v9[v6]); if ( !v6 ) // Execute when v6=0 { for(i = 0 ; i<3; i++){ printf("%d ",v9[i]); } printf("\n"); //sub_1023458(v9); // The V9 array calls sub every time it gets three values_ 1023458 function to sub_101 assign a value to the array v6 = 3; // Reassign to 3 } } } if ( v6 != 3 ) // If the above v9 array has not been assigned all values, the rest will be supplemented with 0 and sub will continue to be called_ 1023458 function to sub_101 assign last value to array { while ( v6 != -1 ) v9[--v6] = 0; for(i = 0 ; i<3; i++){ printf("%d ",v9[i]); } printf("\n"); //sub_1023458(v9); } return 0; } int sub_1023456(int a1) { int v2; // [rsp+0h] [rbp-Ch] int i; // [rsp+0h] [rbp-Ch] int v4; // [rsp+4h] [rbp-8h] unsigned int v5; // [rsp+8h] [rbp-4h] v4 = a1; // Characters entered if ( sub_1023456_shifted == -1 ) { if ( a1 == 126 ) // ASCII value equals 126 ('~') v4 = 0; for ( i = 0; i < 39; ++i ) { if ( ctable[i] == v4 ) // The first 39 of ctable array include lowercase letters and numbers. If v4 is in it { pending = 0; // If pending is set to 0, the loop assigned to v9 will exit return (unsigned int)i; // Just return the subscript } if ( ctable[i + 39] == v4 ) // The last 39 of the ctable array include uppercase letters and symbols if v4 is in it { pending = 1; // Setting pending to 1 will continue to assign value to v9[1] sub_1023456_shifted = i; // This value is changed to the current i, and the else part will be executed the next time return 39; // Return 39, and the next return value will be directly the current i } } pending = 0; // If the value of v4 is not in the array v5 = 37; // ctable[37] is a space } else { v2 = sub_1023456_shifted; // Gets the i returned from the last execution sub_1023456_shifted = -1; // The value is reset to - 1 and the if part is executed next time pending = 0; // pending set to 0 v5 = v2; } return v5; // Returns the last executed i }
Operation results:
you can see that when the input string is "ABC ABC", the corresponding output is:
3 2 1
39 1 39
0 3 2
The subscript of the character 'a' in the ctable array is 1, so the return value is 1 and assigned to v9[2];
The subscript of the character 'b' in the ctable array is 2, so the return value is 2 and assigned to v9[1];
The subscript of the character 'c' in the ctable array is 3, so the return value is 3 and assigned to v9[0];
The subscript of the character 'A' in the ctable array is 40, so the return value is 39, assigned to v9[2], and the next return value is 1, assigned to v9[1];
The subscript of the character 'B' in the ctable array is 41, so the return value is 39, assigned to v9[0], and the next return value is 2, assigned to v9[2];
The subscript of the character 'c' in the ctable array is 3, so the return value is 3 and assigned to v9[1];
Finally, v9[0] was not assigned, so 0 was added at last.
6, Decryption code:
at this point, we fully understand the encryption process and reverse thinking. Next, we write the decryption code in Python:
# py -3 # -*- coding: utf-8 -*- # coding:utf-8 # Finally, the ciphertext in flag.txt ciphertext=[0xF5D1,0x4D6B,0xED6A,0x08A6,0x38DD,0xF7FA,0x609E,0xEBC4,0xE55F,0xE6D1,0x7C89,0xED5B,0x0871,0x1A69,0x5D58,0x72DE,0x224B,0x3AA6,0x0845,0x7DD6,0x58FB,0xE9CC,0x0A2D,0x76B8,0xED60,0x251A,0x1F6B,0x32CC,0xE78D,0x12FA,0x201A,0xE889,0x2D25,0x922A,0x4BC5,0xF5FF,0xF8E5,0xC79B,0x3A77,0x4BDB,0xEA11,0x5941,0x58BD,0x3A95,0xF5C9,0xA225,0xAD40,0xF8BD,0x095D,0x70B6,0x458C,0xE7A9,0xEA68,0x252F,0x094B,0x5E41,0x0969,0x6015,0x5ED5,0xF6E5,0x59B9,0x7CAF,0x66DF,0x265B,0x7837,0x57B4,0x7CAF,0xAED9,0xF707,0x6A3C,0xF8E5,0xF509,0x7C8B,0x0915,0x2235,0x336F,0x33E9,0x2D14,0x7C91,0x5804,0x83E5,0xE78D,0xF4EA,0x0874,0xED6B,0x4B35,0xE839,0x57B4,0xE77C,0xEA68,0x2525,0xAD41,0xED6F,0x3A4A,0x4BCC,0x6015,0xF440,0x0858,0x3AA6,0x7809,0x671D,0x0874,0xEA77,0x63AF,0x2E91,0x5845,0xF6C4,0x086D,0x7795,0x3939,0x57B4,0x7C89,0x82DC,0x32ED,0xB994,0xC7AF,0x9135,0x0E65,0x1B66,0xED5B,0x3235,0x6577,0x5A80,0x3AD3,0xE776,0x1EE5,0xAD41,0xED59,0x864C,0x70B4,0x3876,0xED67,0x64D6,0xF8E5,0xF505,0xEAD9,0x7C9C,0x32ED,0xB994,0xB4EF,0x0C6C,0xF665,0xF5F5,0x9047,0x521A,0xE99E,0xEA68,0x252F,0x9D09,0x76B7,0xE776,0x1ED0,0x095D,0x0D4D,0x5D5A,0x087B,0x2005,0x1526,0x7E76,0x85AD,0x78B9,0xE8B6,0x782C,0x251C,0x32ED,0x7F68,0xEBE3,0xEA41,0x57FD,0xED59,0x846D,0x7A05,0xB994,0xBB78,0xED6A,0x08A6,0x38DD,0x3B5D,0x7E45,0xE839,0x738C,0xE9CC,0x0A2D,0x764A,0x609E,0xE8B6,0xEA68,0x2524,0xE6BB,0x7C9C,0x639F,0x3A95,0x0895,0xF40F,0x8328,0xEA69,0x7EE5,0xF8BD,0x7F7D,0x0D6D,0x70B6,0x458C,0xE8B6,0xEA68,0x251C,0x6065,0xB35F,0xC789,0x5845,0x7F7D,0x6D89,0x4C6E,0xA20E,0x60B5,0x7E45,0xED59,0xF707,0x69EF,0x922A,0x4BC5,0xF6EF,0x8635,0xF4B9,0x57B4,0x7CF8,0xED60,0x2510,0x095D,0x20AF,0x3545,0xF40F,0x8328,0xEA41,0x58A4,0x225D,0x7E7C,0x4BDB,0xF8BD,0x082C,0xEAE7,0x5D57,0x5D50,0x0914,0xE7C7,0x8624,0x7CF8,0xED60,0x2511,0x7C8E,0x7159,0x8416,0x7EF9,0xE7E5,0x774A,0x3895,0x1EC9,0x7C90,0x09B9,0x58BD,0x5FF5,0xE99E,0xEA68,0x250A,0x224C,0xEA3D,0x73F5,0x7C89,0x53A6,0x3190,0x3B5D,0x1526,0x7DD5,0x666A,0x0919,0x225F,0xCDEF,0x79E1,0x7E7B,0x7E6B,0x082C,0xA277,0xE885,0xE8BB,0xE775,0x5FF7,0xEA68,0x251B,0x7FDF,0x589D,0x7A05,0x779A,0x8A5A,0x7C91,0x5D5C,0x32ED,0xF628,0x2195,0xF49A,0x0C77,0xEAE1,0x59B9,0x58BD,0xE570,0xE99E,0xEA3D,0x73F9,0x13AD,0x2BF5,0x225D,0x7F7D,0x70B6,0x4A9C,0x337A,0x1EC9,0x4D05,0x7E75,0x2578,0xED59,0x38E5,0x1ECA,0xA210,0x3B5D,0x779A,0x8A6F,0xC790,0x2518,0x4B41,0x7C89,0x5D49,0x4D05,0x152D,0x73C5,0x79F9,0x4BED,0x913C,0x37C9,0x5D4D,0x53C8,0x0941,0x7C97,0x5D5B,0x346A,0x82D8,0x5F36,0x801F,0xC800] # All v9 arrays v9 = [] # Character subscript array from each v9 array v5 = [] # Input flag flag = "" # ctable character constant array ctable = [ 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x20, 0x0A, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x28, 0x21, 0x40, 0x23, 0x2C, 0x2E, 0x3F, 0x2F, 0x2A, 0x29, 0x3C, 0x3E, 0x00] ## 1. A set of three numbers a0, a1 and a2 are obtained by solving the 3-dimensional linear equation for cipher in ciphertext: a0 = cipher%40 a1 = (cipher//40)%40 a2 = cipher//1600 v9 += [a2,a1,a0] # 2. The number in the v9 array can get the character subscript i=0 while i < len(v9): # The number equals 39, plus the next number to form a subscript of the last 40 characters if v9[i] == 39: v5 += [v9[i]+v9[i+1]] i += 2 # Numbers within 39 are directly indexed to the first 40 characters else : v5 += [v9[i]] i += 1 # Each character subscript corresponds to a character, which is in the character subscript array for lab in v5: # Remove the last pile of 0 if ctable[lab] != 0x0: flag += chr(ctable[lab]) print(flag)
Operation results:
get this text:
Milos Raonic (born 1990) is a Canadian professional tennis player. He reached a career high world No. 4 singles ranking in May 2015, as ranked by the Association of Tennis Professionals (ATP). His career highlights include a Grand Slam final at the 2016 Wimbledon Championships and two Grand Slam semifinals at the 2014 Wimbledon Championships and 2016 Australian Open. He was the 2011 ATP Newcomer of the Year, and has been ranked continuously inside the top 20 since August 2012. Raonic is the first player born in the 1990s to win an ATP title, to be ranked in the top 10, and to qualify for the ATP World Tour Finals. He has eight ATP singles titles, all won on hard courts. He is frequently described as having one of the best serves among his contemporaries. Statistically, he is among the strongest servers in the Open Era, winning 91p of service games to rank third all time. Aided by his serve, he plays an all court style with an emphasis on short points.
its MD5 value: 2c8cd31daeba8753815851f13e6370b3.
however, when the code is executed on the PyCharm client under windbos, it needs to add a line feed, because it comes with a line feed when the linux terminal outputs, but we need to add it here, otherwise the md5 value will be different:
# py -3 # -*- coding: utf-8 -*- # coding:utf-8 from hashlib import md5 # Finally, the ciphertext in flag.txt ciphertext=[0xF5D1,0x4D6B,0xED6A,0x08A6,0x38DD,0xF7FA,0x609E,0xEBC4,0xE55F,0xE6D1,0x7C89,0xED5B,0x0871,0x1A69,0x5D58,0x72DE,0x224B,0x3AA6,0x0845,0x7DD6,0x58FB,0xE9CC,0x0A2D,0x76B8,0xED60,0x251A,0x1F6B,0x32CC,0xE78D,0x12FA,0x201A,0xE889,0x2D25,0x922A,0x4BC5,0xF5FF,0xF8E5,0xC79B,0x3A77,0x4BDB,0xEA11,0x5941,0x58BD,0x3A95,0xF5C9,0xA225,0xAD40,0xF8BD,0x095D,0x70B6,0x458C,0xE7A9,0xEA68,0x252F,0x094B,0x5E41,0x0969,0x6015,0x5ED5,0xF6E5,0x59B9,0x7CAF,0x66DF,0x265B,0x7837,0x57B4,0x7CAF,0xAED9,0xF707,0x6A3C,0xF8E5,0xF509,0x7C8B,0x0915,0x2235,0x336F,0x33E9,0x2D14,0x7C91,0x5804,0x83E5,0xE78D,0xF4EA,0x0874,0xED6B,0x4B35,0xE839,0x57B4,0xE77C,0xEA68,0x2525,0xAD41,0xED6F,0x3A4A,0x4BCC,0x6015,0xF440,0x0858,0x3AA6,0x7809,0x671D,0x0874,0xEA77,0x63AF,0x2E91,0x5845,0xF6C4,0x086D,0x7795,0x3939,0x57B4,0x7C89,0x82DC,0x32ED,0xB994,0xC7AF,0x9135,0x0E65,0x1B66,0xED5B,0x3235,0x6577,0x5A80,0x3AD3,0xE776,0x1EE5,0xAD41,0xED59,0x864C,0x70B4,0x3876,0xED67,0x64D6,0xF8E5,0xF505,0xEAD9,0x7C9C,0x32ED,0xB994,0xB4EF,0x0C6C,0xF665,0xF5F5,0x9047,0x521A,0xE99E,0xEA68,0x252F,0x9D09,0x76B7,0xE776,0x1ED0,0x095D,0x0D4D,0x5D5A,0x087B,0x2005,0x1526,0x7E76,0x85AD,0x78B9,0xE8B6,0x782C,0x251C,0x32ED,0x7F68,0xEBE3,0xEA41,0x57FD,0xED59,0x846D,0x7A05,0xB994,0xBB78,0xED6A,0x08A6,0x38DD,0x3B5D,0x7E45,0xE839,0x738C,0xE9CC,0x0A2D,0x764A,0x609E,0xE8B6,0xEA68,0x2524,0xE6BB,0x7C9C,0x639F,0x3A95,0x0895,0xF40F,0x8328,0xEA69,0x7EE5,0xF8BD,0x7F7D,0x0D6D,0x70B6,0x458C,0xE8B6,0xEA68,0x251C,0x6065,0xB35F,0xC789,0x5845,0x7F7D,0x6D89,0x4C6E,0xA20E,0x60B5,0x7E45,0xED59,0xF707,0x69EF,0x922A,0x4BC5,0xF6EF,0x8635,0xF4B9,0x57B4,0x7CF8,0xED60,0x2510,0x095D,0x20AF,0x3545,0xF40F,0x8328,0xEA41,0x58A4,0x225D,0x7E7C,0x4BDB,0xF8BD,0x082C,0xEAE7,0x5D57,0x5D50,0x0914,0xE7C7,0x8624,0x7CF8,0xED60,0x2511,0x7C8E,0x7159,0x8416,0x7EF9,0xE7E5,0x774A,0x3895,0x1EC9,0x7C90,0x09B9,0x58BD,0x5FF5,0xE99E,0xEA68,0x250A,0x224C,0xEA3D,0x73F5,0x7C89,0x53A6,0x3190,0x3B5D,0x1526,0x7DD5,0x666A,0x0919,0x225F,0xCDEF,0x79E1,0x7E7B,0x7E6B,0x082C,0xA277,0xE885,0xE8BB,0xE775,0x5FF7,0xEA68,0x251B,0x7FDF,0x589D,0x7A05,0x779A,0x8A5A,0x7C91,0x5D5C,0x32ED,0xF628,0x2195,0xF49A,0x0C77,0xEAE1,0x59B9,0x58BD,0xE570,0xE99E,0xEA3D,0x73F9,0x13AD,0x2BF5,0x225D,0x7F7D,0x70B6,0x4A9C,0x337A,0x1EC9,0x4D05,0x7E75,0x2578,0xED59,0x38E5,0x1ECA,0xA210,0x3B5D,0x779A,0x8A6F,0xC790,0x2518,0x4B41,0x7C89,0x5D49,0x4D05,0x152D,0x73C5,0x79F9,0x4BED,0x913C,0x37C9,0x5D4D,0x53C8,0x0941,0x7C97,0x5D5B,0x346A,0x82D8,0x5F36,0x801F,0xC800] # All v9 arrays v9 = [] # Character subscript array from each v9 array v5 = [] # Input flag flag = "" # ctable character constant array ctable = [ 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x20, 0x0A, 0x00, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x28, 0x21, 0x40, 0x23, 0x2C, 0x2E, 0x3F, 0x2F, 0x2A, 0x29, 0x3C, 0x3E, 0x00] ## 1. A set of three numbers a0, a1 and a2 are obtained by solving the 3-dimensional linear equation for cipher in ciphertext: a0 = cipher%40 a1 = (cipher//40)%40 a2 = cipher//1600 v9 += [a2,a1,a0] # 2. The number in the v9 array can get the character subscript i=0 while i < len(v9): # The number equals 39, plus the next number to form a subscript of the last 40 characters if v9[i] == 39: v5 += [v9[i]+v9[i+1]] i += 2 # Numbers within 39 are directly indexed to the first 40 characters else : v5 += [v9[i]] i += 1 # Each character subscript corresponds to a character, which is in the character subscript array for lab in v5: # Remove the last pile of 0 if ctable[lab] != 0x0: flag += chr(ctable[lab]) # There is a new line at the end of this paragraph flag += '\n' print(flag) # Output MD5 value in lowercase hexadecimal print("md5 The value is:",md5(flag.encode()).hexdigest())
Operation results:
you can also get its MD5 value: 2c8cd31daeba8753815851f13e6370b3.