hackwaly / blog Goto Github PK
View Code? Open in Web Editor NEW我的博客
我的博客
申明:仅出于学习目的,如有侵权请通知我,我会立即删除。他人不得将此文中信息用于商业目的。
首先网上找了一下其他人是否有分享逆向《放置江湖》的经验,找到了这个 https://github.com/crazyyao0/codearchive/tree/master/reverse/%E6%94%BE%E7%BD%AE%E6%B1%9F%E6%B9%96
大概意思《放置江湖》应该是cocos2d-x写的,里面的数据和逻辑都在lua文件里。发布出来的apk里面打包进去的lua文件是加密过的,需要解密。作者是自己写的解密脚本,我比较懒,网上找了下看看有没有现成的。找到 https://github.com/lyzz0612/cocos_decrypt
这个脚本解密是全自动的,不过在识别 sign 和 key 的时候遇到了点问题。所幸它支持手动传 sign 和 key,网上也找到了如何寻找 cocos2d-x 加密的 sign 和 key:https://blog.csdn.net/u012278016/article/details/79607356
由于只需要破解一次,所以我没有去改进那个解密脚本,而是手动找出 sign 和 key 之后对 apk 做了解密。解密的过程中有点意外,解密脚本硬编码了需要解密的文件的后缀名为 .luac
,在《放置江湖》中,后缀名为 .lua
,所以需要调整下解密脚本。
解密完成后,提取出来的 *.lua
文件依然是二进制的,用 winhex 和未解密的版本作了下对比。发现文件是不一样的,这说明解密是完成了的,只不过解密出来的可能是 lua 的 bytecode,需要咱们反编译一下。
解密之后的 lua 文件在 winhex 下明显前四个字符是可见字符,应该是文件格式的 magic。显示为” LJ “,hex 为 “1B4C4A02“,猜测是 luajit 的 bytecode,通过搜索确认了我的猜测。于是开始搜索 luajit 的 decompiler。找到 https://gitlab.com/znixian/luajit-decompiler 应该是目前还在维护的版本。
反编译过程会出现很多 warning 和 exception,应该是 decompiler 不够完善导致的。不过不影响记录数据的 lua 文件的反编译。
由于我是比较懒的人,所以我比较乐意节省那些和我同样懒并且有着同样爱好的人的时间:
https://gist.github.com/hackwaly/3a7d6caeb50388c7b625c04105a39d60
引用计数在并发环境下,由于需要考虑并发问题,通常会引入原子操作,降低了引用计数的性能。
一种思路:
假定我们的编程语言的并发范式是 actor。
那么我们在讲一个可回收对象 send 到别的 actor 中去的时候,可以在那个 actor 下对这个对象单独进行计数。而原来的 actor 里的计数给它加一。当另外那个 actor 里的计数等于 0 的时候,才跨线程去更新原来 actor 里的计数减一,这样极大的减少了并发操作的次数,并且也不需要在计数上搞原子操作了。利用 actor 的消息队列就行了。
Consider this Javascript, executed in chrome in 2775.01ms on my MBP (please close devtools first before you test it). Why? Because under the hood ES7 use promise to implement await/async, which introduce massive overhead. Call an async function is doggy slow even if it actually doesn't do any async thing.
function sleep(t) {
return new Promise((resolve) => {
setTimeout(resolve, t);
});
}
async function small(i, n) {
if (i === Math.floor(n / 2)) {
await sleep(1000);
}
}
async function test(n) {
let t = performance.now();
for (let i = 0; i < n; i++) {
await small(i, n);
}
console.log(performance.now() - t);
}
test(5000000);
Now, I'll present you a novel approach to implement async/await. It combines CPS, state machine and exception to reconstruct call stack and avoid closure creation.
The javascript above then can transform to the javascript below. You can test it in your chrome. I'll explain it next time. These code is just prototype for proof. You don't need handwrite your async logic like these. There will be some compilers do it. Thank you!
function GetContinuation(callback, outerState) {
this.callback = callback;
this.stack = [];
this.outerState = outerState;
}
function makeContinuation(stack, index) {
if (index === stack.length) {
return function () {};
}
let func = stack[index];
let args = stack[index + 1];
let parent = makeContinuation(stack, index + 2);
return function () {
return func.apply(parent, args);;
};
}
function bind(func, this_, args) {
return function () {
return func.apply(this_, args);
};
}
function callcc(callback, outerState) {
throw new GetContinuation(callback, outerState);
}
function sleep(timeout, outerState) {
return callcc(function (continuation) {
setTimeout(continuation, timeout);
}, outerState);
}
function small(i, n, outerState) {
try {
if (i === Math.floor(n / 2)) {
sleep(1000, 0);
}
} catch (exn) {
if (exn instanceof GetContinuation) {
exn.stack.push(small_async, [exn.outerState, i, n]);
exn.outerState = outerState;
}
throw exn;
}
}
function small_async(state, i, n) {
try {
while (true) {
switch (state) {
case 0:
return this();
}
}
} catch (exn) {
if (exn instanceof GetContinuation) {
return exn.callback(bind(small_async, this, [exn.outerState, i, n]));
}
throw exn;
}
}
function test(n, outerState) {
var i;
var t;
try {
t = performance.now();
i = 0;
while (i < n) {
small(i, n, 0);
i ++;
}
console.log(performance.now() - t);
} catch (exn) {
if (exn instanceof GetContinuation) {
exn.stack.push(test_async, [exn.outerState, t, i, n]);
exn.outerState = outerState;
}
throw exn;
}
}
function test_async(state, t, i, n) {
try {
while (true) {
switch (state) {
case 0:
i++;
case 1:
if (i >= n) {
state = 2;
continue;
}
small(i, n, 0);
continue;
case 2:
console.log(performance.now() - t);
return this();
}
}
} catch (exn) {
if (exn instanceof GetContinuation) {
return exn.callback(bind(test_async, this, [exn.outerState, t, i, n]));
}
throw exn;
}
}
function main() {
test(5000000, 0);
}
function exec(main) {
var task;
task = main;
while (true) {
try {
return task();
} catch (exn) {
if (exn instanceof GetContinuation) {
task = function () {
return exn.callback(makeContinuation(exn.stack, 0));
};
} else {
throw exn;
}
}
}
}
exec(main);
1,每个gcref指向的struct的第一个(或-1个)字段,保存类型的metadata,里面有记录struct里哪些字段是gcref,以及他们的位置(最好是挨着放一起,这样记录下开始位置和数量就ok了)。
2,stack 里将 gcref 类型的变量,全部挨着放在一起叫 gcref stack。stack里在最前面保存一个 gcref stack中gcref的数量。gcref stack预留好寄存器里gcref在发生gc时要spill到gcref stack里的位置。
3,不搞 gc 的yield point了。也就是不在函数的进入或者退出的地方、循环的back edge前面等这些地方加判断是否需要 gc。而是通过外部线程暂停需要gc的线程,拿到pc,根据预先记录好的信息,计算出哪些寄存器是gcref,将它们存到栈上预留的gcref stack上。然后扫描stack就简单了。
4,stack 上预留给寄存器gcref的空间,不用每个frame都预留,只需要最里层的frame留就行了。那么这样依赖,gcref stack最好是放在栈顶。并且不要函数内支持动态扩展栈
5,把数据类型分为几大类:是否mutable,是否sendable,是否不可能含循环引用。针对特定的类型进行特定的gc方式。比如说 immutable + cyclic 可以用 traced gc。mutable + non-cyclic 可以用引用计数。mutable + sendable 可以从语言层面上搞成像js里transferable那样的。
6,no-escape的数据可以直接分配在栈里
我接触 React 的时候它才刚发布,但我完全想象不到 React 会发展到现在这样火。现在各种 React 的介绍文章,也不用我多废话 React 是一个什么样的东西了。
我这里只想泼一泼冷水,说一说 React 不太好的地方:
className
、htmlFor
,驼峰化的属性,还不支持命名空间属性。既不是 HTML,也不是 XML。你不能直接复制使用 HTML 代码了,这加重了用户的负担。A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.