Statement: This article is intended for technical exchanges and is not intended for the "square" (the new version of the square educational administration system password processing method has also changed, just use this as an introduction ......)! This article does not have any depth. It only explores the possibility of reverse Key obtaining when the plaintext, ciphertext, and algorithm are known! 0x00 background
We often encounter base64-encoded decoding requests from our friends (not to mention whether Base64 is used, which will be explained below ). For example, p6FDpXlnQ1tHlLZK + encoding = is very much like Base64 encoding, but the result you get from standard Base64 decoding is obviously not what you want (N is likely to happen ).
0x01 encoding/Decoding
Let's start with encoding and decoding. The simplest encoding (why not encrypt or decrypt it? See what you did with it ......) Is to map characters, for example:
a=eb=fc=g……v=zw=ax=by=cz=d
This is just an example. There are numbers, special characters, and so on. Of course, you can also use irregular ing to encode the code. If this encoding is used to encrypt the password, what are the defects?
Assume that a person already has several sets of plain text and corresponding ciphertext, then he can use these sets of plain text and ciphertext in his hand to find the law to restore the ing relationship, then, the ing relationship can easily crack other ciphertext.
As a result, we divide the recoverable plaintext encryption algorithms into the following categories (why is it possible to restore the ciphertext? Let the vendor answer this question !) :
① For example, bcdef = fghij cdefg = ghijk ...... This type of encryption does not require a tool. It can be visually tested and restored. ② A slightly more complex encryption algorithm, the ciphertext cannot find the regular, can prevent user cracking. However, if the encryption and decryption algorithm is missing, all users' passwords will be cracked! ③ The complex encryption algorithm uses a custom Key to encrypt plaintext, that is, the password is generated after some calculation of plaintext and Key. This algorithm has an advantage. Even if the algorithm is missing, it cannot be decrypted without a Key (we will discuss it later ). For example, pass = encode (str, key); str = decode (pass, key ). ④ More complex algorithms ...... (To be supplemented)
0x02 discuss jiam and jiemi in the square
Why is it another discussion? Because the "encryption" and "decryption" operations of the Zhengfang educational administration system have been discussed for many times. On the Internet, you can even find multiple versions of this algorithm (Baidu and Google ).
Two typical scenarios are:
① Multiple sets of ciphertext are available. We know the plaintext and encryption algorithms corresponding to several ciphertext groups. However, due to the inability to obtain the Key used for encryption, other ciphertext cannot be decrypted. ② The system can obtain the encrypted ciphertext due to a defect (of course, the plaintext is its own password, which is controllable), and cannot be decrypted after obtaining the ciphertext due to no Key.
In order to study this algorithm and try to get the inverse Key, I decided to write another VB version. The algorithm is located in/bin/zjdx. dll, so it's easy to find it. On the internet, find a "source code" and use Reflector to load zjdx. dll, followed by the jiam method on the login page Default2
The source code is as follows (comments have been written ):
Public string jiam (string PlainStr, string key) {string text3; int num3 = 1; int num4 = Strings. len (PlainStr); // obtain the plaintext length of the password for (int num1 = 1; num1 <= num4; num1 ++) {string text6 = Strings. mid (PlainStr, num1, 1); // obtain the next character string text2 = Strings in the password from the first character. mid (key, num3, 1); if (Strings. asc (text6) ^ Strings. asc (text2) <0x20) | (Strings. asc (text6) ^ Strings. asc (text2)> 0x7e) | (Strings. asc (text6) <0) | (Strings. asc (text6)> 0xff) // calculate the ASSCII code of a character captured in the text and the ASSCII code of a character captured in the Key, if the result is an ASSCII code that cannot be printed, the temporary string is directly added to the string {text3 = text3 + text6 ;} else // If the ASSCII code (33-126) of printable characters is returned after the XOR or, the temporary string plus the ASSCII code is the character of the XOR result {text3 = text3 + StringType. fromChar (Strings. chr (Strings. asc (text6) ^ Strings. asc (text2);} if (num3 = Strings. len (key) // if the last character is used in the Key, use Key {num3 = 0 ;} num3 ++;} from the beginning ;} if (Strings. len (text3) % 2) = 0) // if the final temporary result character length is an even number, then the final result = the First Half of the reverse character + the second half of the reverse character {string text4 = Strings. strReverse (Strings. left (text3, (int) Math. round (double) Strings. len (text3)/2); string text5 = Strings. strReverse (Strings. right (text3, (int) Math. round (double) Strings. len (text3)/2); text3 = text4 + text5;} return text3; // return the final result}
The jiami function has two parameters. PlainStr is the plaintext to be encrypted, and key is the key used for encryption. This function logic is annotated.
For more information about exclusive or operations, see http://technet.microsoft.com/zh-cn/subscriptions/csw1x2a6 (v = vs.80). aspx
For the convenience of understanding the following, it is explained as follows: three numbers a, B, c if (a xor B = c) Then (a xor B xor a = B ), (a xor B = ).
See the ASSCII code table: http://www.96yx.com/tool/ASC2.htm 33-126 is a printable character.
So far, the logic of jiam has been completely clear, and this function is transplanted to the vbprogram. The Code is as follows:
Public Function jiam(ByVal PlainStr As String, ByVal key As String) As String Dim strChar, KeyChar, NewStr As String Dim Pos As Integer Dim i, intLen As Integer Dim Side1, Side2 As String Pos = 1 For i = 1 To Len(PlainStr) strChar = Mid(PlainStr, i, 1) KeyChar = Mid(key, Pos, 1) If ((Asc(strChar) Xor Asc(KeyChar)) < 32) Or ((Asc(strChar) Xor Asc(KeyChar)) > 126) Or (Asc(strChar) < 0) Or (Asc(strChar) > 255) Then NewStr = NewStr & strChar Else NewStr = NewStr & Chr(Asc(strChar) Xor Asc(KeyChar)) End If If Pos = Len(key) Then Pos = 0 Pos = Pos + 1 Next If Len(NewStr) Mod 2 = 0 Then Side1 = StrReverse(Left(NewStr, CInt((Len(NewStr) / 2)))) Side2 = StrReverse(Right(NewStr, CInt((Len(NewStr) / 2)))) NewStr = Side1 & Side2 End If jiam = NewStr End Function
If the Key is known, how can I write the decrypted code?
The decryption function obtained by decompiling in zjdx. dll is as follows:
public string jiemi(string PlainStr, string key){ string text3; int num2 = 1; if ((Strings.Len(PlainStr) % 2) == 0) { string text4 = Strings.StrReverse(Strings.Left(PlainStr, (int) Math.Round(((double) Strings.Len(PlainStr)) / 2))); string text5 = Strings.StrReverse(Strings.Right(PlainStr, (int) Math.Round(((double) Strings.Len(PlainStr)) / 2))); PlainStr = text4 + text5; } int num3 = Strings.Len(PlainStr); for (int num1 = 1; num1 <= num3; num1++) { string text6 = Strings.Mid(PlainStr, num1, 1); string text2 = Strings.Mid(key, num2, 1); if (((((Strings.Asc(text6) ^ Strings.Asc(text2)) < 0x20) | ((Strings.Asc(text6) ^ Strings.Asc(text2)) > 0x7e)) | (Strings.Asc(text6) < 0)) | (Strings.Asc(text6) > 0xff)) { text3 = text3 + text6; } else { text3 = text3 + StringType.FromChar(Strings.Chr(Strings.Asc(text6) ^ Strings.Asc(text2))); } if (num2 == Strings.Len(key)) { num2 = 0; } num2++; } return text3;}
In fact, this function is not required. programmers with a little understanding can write the corresponding decryption function based on the encryption function.
Decryption logic:
+ -- Determine whether the ciphertext length is even | next step
| Yes (restructured ciphertext) No | next step
| The password and key intercepted by one digit are different or | next step
| Character combination based on different or result | next step
+ Final result |
The VB code written based on this logic is as follows:
Public Function jiemi (ByVal PlainStr As String, ByVal key As String) As String Dim strChar, KeyChar, newStr As String Dim Pos As Integer Dim I As Integer Dim Side1 As String Dim Side2 As String Pos = 1 If Len (PlainStr) Mod 2 = 0 Then Side1 = StrReverse (Left (PlainStr, CInt (Len (PlainStr)/2) 'reverse the leftmost half character of the plaintext password Side2 = StrReverse (Right (PlainStr, CInt (Len (PlainStr) /2) 'reverse the rightmost half character of the plaintext password PlainStr = Side1 & Side2 End If For I = 1 To Len (PlainStr) strChar = Mid (PlainStr, I, 1) 'One by one processing the character KeyChar = Mid (key, Pos, 1) 'in plainstr cyclically using the character If (Asc (strChar) Xor Asc (KeyChar) in the key) <32) or (Asc (strChar) Xor Asc (KeyChar)> 126) Or (Asc (strChar) <0) Or (Asc (strChar)> 255) then NewStr = NewStr & strChar Else NewStr = NewStr & Chr (Asc (strChar) Xor Asc (KeyChar) End If Pos = Len (key) then Pos = 0 Pos = Pos + 1 Next jiemi = NewStr End Function
The encryption and decryption functions have been completely written out, and two formulas are obtained: jiam (plaintext, key) = ciphertext jiemi (ciphertext, key) = plaintext
However, in the preceding scenario, the plaintext and ciphertext are known. Is it possible to calculate the Key: GetKey (plaintext, ciphertext) = key?
The answer is yes, because the jiam () function knows that the length of plaintext and ciphertext must be equal. Due to the known principle of exclusive or operation, plaintext (exclusive or) Cyclic key = ciphertext, {plaintext (exclusive or) key} (exclusive or) plaintext = cyclic Key, therefore, ciphertext (XOR) plaintext = cyclic Key.
Based on this logic, write the VB Code as follows:
Public Function GetKey (ByVal PlainStr As String, ByVal Pass As String) As String Dim strChar, KeyChar, newStr As String Dim Pos As Integer Dim I As Integer Dim Side1 As String Dim Side2 As String Pos = 1 If Len (PlainStr) Mod 2 = 0 Then Side1 = StrReverse (Left (PlainStr, CInt (Len (PlainStr)/2) 'reverse the leftmost half character of the plaintext password Side2 = StrReverse (Right (PlainStr, CInt (Len (PlainStr) /2) 'reverse the rightmost half character of the plaintext password PlainStr = Side1 & Side2 End If For I = 1 To Len (PlainStr) strChar = Mid (PlainStr, I, 1) 'process the character KeyChar = Mid (Pass, Pos, 1) in plainstr one by one) 'Use the character If strChar = KeyChar Then NewStr = NewStr & "*" Else NewStr = NewStr & Chr (Asc (strChar) Xor Asc (KeyChar) in a loop )) end If Pos = Pos + 1 Next GetKey = NewStrEnd Function
Here, we have encountered a problem, that is, some characters in the ciphertext are directly added to the result without going through the exclusive or operation, that is, the Key does not work at a specific character, therefore, the corresponding Key characters cannot be reversed in these locations. What should we do? As we have mentioned above, we have several sets of plain text and password comparisons, so we can determine the final Key through N sets of inverse operations (of course, if the password is long enough, this effect can be achieved, because the key length is certain [always used cyclically]), keys that are not involved in the calculation are usedNumber to replace (if the Key has!)
Test the plaintext ciphertext of several sets of comparisons and obtain the following key,
A***l*36*j*Ac**lf****wA*xy*f*65*wAcxy*f3**j*……
The final key value is: Acxylf365jw
0x03 Base64 encoding
Let's take a look at a similar Base64 encoding that can be encoded and can be restored!
Base64 introduction see: http://zh.wikipedia.org/zh-cn/Base64
The logic of Base64 is: String> 8-bit binary connection for each character> convert each 6-bit to a decimal table and connect the converted characters; if the number of bytes to be encoded cannot be divisible by 3, and one or two more bytes are added at the end, you can use the following method for processing: Use the 0-byte value to supplement the value at the end, enable it to be divided by 3, and then encode it with base64. Add one or two '=' After the encoded base64 text to indicate the number of supplemented bytes.
The maximum size of the six-digit binary is 111111, that is, the minimum value of 63 is 000000. Therefore, the encoding table contains 64 characters.
Base standard encoding table:
Example:
A qq =
BC QkM =
Under normal circumstances, the Base64 encoding table is ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789 +/=. What is the result if the characters in the encoding table are in another order?
I used this encoding table (equivalent to key): abcdefghijklmnopqrstuvwxyz0123456789 +/= ABCDEFGHIJKLMNOPQRSTUVWXYZ, encoding character: I Love You!
Get the string ssbm1Qz/if/I3se =, but use the standard encoding table to decode it and get: Several "garbled characters "...... If we know the pre-encoding and post-encoding characters but do not know the encoding table, can we determine the encoding table based on the array comparison?
The answer is yes: first, determine whether Base64 encoding is used based on the length of plaintext and ciphertext (details: Baidu, Google ), then, convert the plaintext value to an 8-bit binary value and convert it to the decimal value.
If we have a clear article: 11CA467C5B1C3C0AB1D6C8A81104CC868CDC0A91 and ciphertext: ciphertext =, the process of determining the encoding table is as follows:
Step 1: Convert plaintext to eight-bit binary:
00110001001100010100001101000001001101000011011000110111010000110011010101000010001100010100001100110011010000110011000001000001010000100011000101000100001101100100001100111000010000010011100000110001001100010011000000110100010000110100001100111000001101100011100001000011010001000100001100110000010000010011100100110001
Step 2: convert each 6-digit binary number to decimal (I use | for ease of viewing ):
12 | 19 | 5 | 3 | 16 | 19 | 16 | 54 | 13 | 52 | 12 | 53 | 16 | 35 | 5 | 3 | 12 | 52 | 12 | 48 | 16 | 20 | 8 | 49 | 17 | 3 | 25 | 3 | 14 | 4 | 4 | 56 | 12 | 19 | 4 | 48 | 13 | 4 | 13 | 3 | 14 | 3 | 24 | 56 | 16 | 52 | 17 | 3 | 12 | 4 | 4 | 57 | 12 | 16 |
Step 3 corresponds to the encrypted string:
Mtfdqtq2n0m1qJfdm0mWquiXrdzdoee4mteWnendody4q0rdmee5mq =
The position of m in the code table is 12, t in the code table is 19, and f in the code table is 5 ...... (Because the m behind is 12, the t is 19 ......, So it can be determined that this is a Base64 encoded table ). The variant encoding table is obtained after multiple sets of plaintext and ciphertext control: abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 +/=
So far, the Inverse Calculation of the encoding table is successfully completed.
For a Base64 encoding operation, the plaintext and ciphertext pairs can be used to easily reverse the encoding table. For example, the Base64 encoding of the same encoding table is used twice, is it possible to get the encoding table?
You can do the following analysis: (for example, because the first character is not affected by the subsequent characters After encoding, the following analysis shows the first character after each encoding)
After the first encoding, the character space is 8 to 31 characters in the encoding table (the ASSCII code of printable characters is 32-126)
...... Bin (A) = 01000001 Base64 (A) = 16th bits in the encoding table Bin (E) = 01000101 Base64 (E) = 17th bits in the encoding table Bin (I) = 01001001 Base64 (I) = 18th-bit Bin (M) = 01001101 Base64 (M) = 19th-bit Bin (Q) = 01010001 Base64 (Q) = 20th-bit Bin (U) in the encoding table) = 01010101 Base64 (U) = 21st bits in the encoding table Bin (Y) = 01011001 Base64 (Y) = 22nd bits in the encoding table ......
Since the character range after the first encoding must be in the following character ranges:
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789+/=
The minimum ASSCII code is "43", and the maximum is "122"
Therefore, after the second encoding, the character space is between 10th and 30 characters in the encoding table.
Because the result of quadratic encoding is known, you can use multiple sets of passwords to determine all characters in the encoding table between 10 and 30 (but the sequence is unknown ).
...... Base64 (Base64 (A) = Base64 (the 16th-bit character in the encoding table) Base64 (Base64 (E) = Base64 (the 17th-bit character in the encoding table) base64 (Base64 (I) = Base64 (18th characters in the encoding table )......
In this way, the Base encoding results of the 10-30 characters in the encoding table are all known (the result character is still between 10 and 30 characters)
Then a 21-element equation is obtained (if the equation is obtained, the position of a part of the characters in the encoding table is determined, but we haven't tried to solve it yet ......)
It can be seen that it is still very difficult to restore the encoding table after secondary encoding !)
0x04 reflection
This article only attempts to restore the Base64 encoding table from the first character. Is there any other way to easily restore the encoding table?
If edcode (str, key)-like ciphertext obtained after one encryption and known algorithms (password can be restored), can we use Plaintext and ciphertext to reverse the key?