I'm not sure about a "known technique with a name" - perhaps keywords like "inverse function" or "bidirectionalization" might help, e.g. In pure functional languages, is there an algorithm to get the inverse function?
For this particular function, luckily it seems pretty straightforward to invert as long as the f365xx
string constants abide by some certain properties. Notice that cArr
is filled one-by-one and each character is independent of each other. We can try to use both the characters and the length of the string to try to decode the input i
. Specifically,
- A single character will give us candidates for
i10
, which will give us candidates for charAt
. Repeating over all the characters, hopefully only one candidate will work for every character, and that candidate will give us i7
/i2
-> i2
/i3
-> i
if the strings are "benevolent".
- If the strings are not benevolent, then the length of the string will give us candidates for
charAt2
which, together with the candidates for charAt
, will give us candidates for i8
/i6
. Hopefully there is only one candidate pair i6
/i8
-> i5
/i6
-> -> i4
-> i
if the string constants are benevolent.
If the strings are still not benevolent, then it is unsolvable since the function is not one-to-one.
I'll outline the algorithm for the 2 bullet points now, but as a disclaimer, I haven't tested this and it's just pseudocode.
From a character
Let's say you start with the first character, cArr[0]
. If we focus on the 3 lines inside the for loop,
int i10 = charAt + i9;
int charAt3 = f3651b[i10 / 8192].charAt(i10 % 8192) & 65535;
cArr[i9] = f3650a[charAt3 / 8192].charAt(charAt3 % 8192);
Then we can get charAt3
by finding where cArr[0]
appears in f3650a
. For example,
charAt3candidates = []
for i = 0 to length(f3650a)-1:
indexCandidates = f3650[i].indexOf(cArr[0])
for indexCandidate in indexCandidates:
charAt3candidate = i * 8192 + indexCandidate
if indexCandidate >= 8192 or charAt3candidate >= 65536:
continue
charAt3candidates.append(charAt3candidate)
Note that we filter out indexCandidate >= 8192
and charAt3candidate >= 65536
due to modulo's and bitwise and's that make greater values impossible (x & 65535 == x % 65536
since 65536 = 2^16).
Do a similar process to find the candidates for i10
and subtract i9
to get candidates for charAt
. If you have more than one candidate, repeat this process for every character in cArr
and keep only the candidates of charAt
which are valid for every character in cArr
. Even after repeating for every character in cArr
, you may still have many candidates.
For each candidate of charAt
, use the right-half of the expression for charAt
:
charAt % 65536 = (str.charAt(i7) & 65535)
combined with str = f3652c[i2]
to try to find i2
/i7
the same way we tried to find charAt3
and i10
. Note that the left half of the expression, ((str.charAt(i7 + 1) & 65535) << 16)
, doesn't matter (for now). Hope and pray that this only gives you one possible choice of i2
/i7
. If so, use it to find i2
/i3
-> i
. If there's more than one option, then we have to try using the length of the string.
From the length of the string
The length of the string gives us charAt2
, and we can use a similar process as before to find all the candidates for i8
and str2
(i5
). Note in this process we have to try with every possible candidate for charAt
. Hopefully there is only one candidate pair for i8
/i5
remaining. If so, use it to find i5
/i6
-> i4
-> i
. If there are more than 1 candidate, then the function is not one-to-one and it's impossible to invert.
Good luck!