I found a interesting website http://geek.qq.com/tree/ shared by a friend in the recruitment group. It's really addictive! This tree-planting activity is actually like a game of passing levels. As you plant more trees, new gameplay elements are unlocked. I'm just a newbie, and when I reached 1 million trees, I couldn't keep up. In the levels I played, I had to decrypt and deobfuscate js and perform other operations, which was quite entertaining. It's important to note that you can only plant the next tree after successfully planting one, so running multiple threads to parallel the interface is pointless.
The first level consists of planting 1-10,000 trees, and it's quite simple. It's just a matter of issuing a simple request. There's only one value in the array, and you just need to retrieve it and send it back. In fact, most of the processing for this game takes place in the middle of this process.
/**
pull example
http://159.75.70.9:8081/pull?u=0000081082CCDB14682A1505892071B1
example response
{"c":"A274075A","a":[73513],"t":"000010510000000086A11C1156D6202A"}
push example
http://159.75.70.9:8081/push?t=000010510000000086A11C1156D6202A&a=73513
example response
{"success":1,"score":1}
In fact, during the game, all you need to pay attention to is the a property, which is obtained from the array in the push part, so you can just use pop directly.
varf=function(obj){returnnewPromise(resolve=>{resolve(obj.a.pop());})}while(true){try{let token ="0000081082CCDB14682A1505892071B1"let pull =await(awaitfetch(`${cgi}/pull?u=${token}`)).json();let val =awaitf(pull);let push =await(awaitfetch(`${cgi}/push?t=${pull.t}&a=${val}`)).json(); console.log(push);if(!push.success)throw push;}catch(e){break;}}// Note: the variable cgi has been globally defined
The second level consists of planting 10,000-100,000 trees. After the first request, a <script> will be dynamically inserted into the global window based on the value of the c property in the returned push object. Then, a function is called to calculate the value to be submitted for the push. The calculations given are either a long delay or a time-consuming looping operation, challenging you to optimize it in order to speed up the tree planting process.
/**
pull example
http://159.75.70.9:8081/pull?u=0000081082CCDB14682A1505892071B1
example response
{"c":"A3C2EA99","a":[79124],"t":"00001051000100011B214AC36A8E9369"}
push example
http://159.75.70.9:8081/push?t=00001051000100011B214AC36A8E9369&a=6260686500
example response
{"success":1,"score":10002}
It seems straightforward, just calculating a[0]*a[0]+a[0], but if you call this method directly, there will be a delay of about 2s, so you need to optimize it yourself.
varf=function(obj){returnnewPromise(resolve=>{const a = obj.a.pop();resolve(a*a+a);})}```javascript
while(true){
try{
let token = "0000081082CCDB14682A1505892071B1"
let pull = await (await fetch(`${cgi}/pull?u=${token}`)).json();
let val = await f(pull);
let push = await (await fetch(`${cgi}/push?t=${pull.t}&a=${val}`)).json();
console.log(push);
if(!push.success) throw push;
}catch(e){
break;
}
}
// Note: The variable `cgi` has been globally defined
Level 3 involves 100,000-250,000 trees, and this is where the JavaScript starts to move towards encryption and obfuscation.
/**
Example of pull
http://159.75.70.9:8081/pull?u=0000081082CCDB14682A1505892071B1
Example response
{"c":"A5473788","a":[359,626,105471],"t":"0000105100100000072FD4E99C75A6C6"}
Example of push
http://159.75.70.9:8081/push?t=0000105100100000072FD4E99C75A6C6&a=17923
Example response
{"success":1,"score":100001}
At this point, the dynamically-loaded JavaScript looks like this.
In this js, the loop operation is very time-consuming. Just by looking at 0x30d3f = 199999 and the internal for loop, we can tell. But we can simplify this loop and the entire code to plant trees faster.
It looks very uncomfortable, for this confusion, we will handle the self-executing function to make the generated function name clearer. I have to say vscode is really useful. Here I have some other code to facilitate testing. Now, we have an overall understanding of this obfuscated code.
I must complain here. It really became so big to obfuscate this file, and there's only this much code after processing. Also, this code uses a generator to implement a calculation method similar to using Java multi-threading to sort (of course js is single-threaded) and to create time delays to prevent us from planting trees. Here we will implement the calculation method based on its logic.
varf=function(obj){returnnewPromise(resolve=>{let counter =0; obj.a.sort((a, b)=> a-b); obj.a.forEach((v, i)=>{const operater =[(_,__)=>_ + __,(_,__)=>_ - __,(_,__)=>_ * __][(i+1)%3]; counter =operater(counter, v);})resolve(-counter);})}while(true){try{let token ="0000081082CCDB14682A1505892071B1"let pull =await(awaitfetch(`${cgi}/pull?u=${token}`)).json();let val =awaitf(pull);let push =await(awaitfetch(`${cgi}/push?t=${pull.t}&a=${val}`)).json(); console.log(push)if(!push.success)throw push;}catch(e){break;}}// Note: The variable cgi has been globally defined
Level 5 is 500k-1M trees. A WebAssembly suddenly appeared in level 5, which I have never used before, and it really caught me off guard. Although I didn't understand it before, I tried to learn it overnight and passed level 5.
/**
pull example
http://159.75.70.9:8081/pull?u=0000081082CCDB14682A1505892071B1
Example response
{"c":"A661E542","a":[334562437,6452978],"t":"0000081000666290FA5B0B81481B32CD"}
push example
http://159.75.70.9:8081/push?t=0000081000666290FA5B0B81481B32CD&a=334562804
Example response
{"success":1,"score":500006}
At this time, the dynamically loaded js looks like this.
```javascript
var f = async function({a:A}){
const fetcher = await fetch("data:application/octet-binary;base64,AGFzbQEAAAABBwFgAn9/AX8CFwIETWF0aANtaW4AAARNYXRoA21heAAAAwIBAAcHAQNSdW4AAgpgAV4BBn8gACECIAFBAWsiBARAA0AgAiEDQQAhBkEKIQcDQCADQQpwIQUgA0EKbiEDIAUgBhABIQYgBSAHEAAhByADQQBLDQALIAIgBiAHbGohAiAEQQFrIgQNAAsL");
const buffer = await fetcher.arrayBuffer();
const compiler = await WebAssembly.compile(buffer);
const instantiate = await WebAssembly.instantiate(compiler, {Math:Math});
console.log(instantiate.exports); // Check the location of the Run method [[FunctionLocation]]
return instantiate.exports.Run(...A)
}
console.log(f({"c":"A661E542","a":[116823665, 6153003],"t":"0000081000500002F1D882C546c34290"}).then(res => console.log(res)));
// 116823707
// https://www.wasm.com.cn/docs/semantics/#32-bit-integer-operators
Finally, I debugged it slowly and simulated the operation of this wasm with js, the running speed was much faster. Then I passed this level, this stack-based language is quite fun.
while(true){try{let token ="0000081082CCDB14682A1505892071B1"let pull =await(awaitfetch(`${cgi}/pull?u=${token}`)).json();let val =awaitf(pull);let push =await(awaitfetch(`${cgi}/push?t=${pull.t}&a=${val}`)).json(); console.log(push)if(!push.success)throw push;}catch(e){break;}}// // Note: The variable cgi has been defined globally
I know I got a bit carried away writing this, but there's still a lot of things left to do. My teacher's paper needs to be presented next week. I spent the whole afternoon playing, but now I better get back to work. As I'm writing this, some bigwigs have already planted 2 million trees. I've only planted 1 million so far and I'm ranked 82nd. Hats off to those big shots.