/tmp/duangsuse.sock
说起来,因为有这个小号的原因 我知道 drakeet 曾经研究的反破解也的确是取得了一些进步,至少他都知道我能找到『黑箱』里的符号了 当然,作为 C 开发者我也是知道怎么办的,CC -fvisibility=hidden, __attribute__((visibility("hidden"))), static, LD --exclude-symbols, strip -K Java_io_Main_digest 都可以 可惜 drakeet 虽然的确是从我曾经的逆向工程经验里学到了很多应对经验了...…
简而言之,我看了一部分后觉得他维护的果然还是变勤快了。
而且内容质量看起来也是高了不少,虽然还算是意料之中,分享的大部分还是停留在使用层面...
两个看到了想说什么的:
1. native 中不依赖 PackageManager 和 signature API 进行签名验证的方法
猜测:
a. 手动算 file 再算 dex hash 和长度什么的,总之就是利用文件系统
b. 找几个应用类算代码 hash 校验,不过实际上这也不叫签名验证
c. JNI 是否 Android 有提供验证的方法
d. 检查重新打包时一切可能发生改变的东西,比如安装包大小?APK 的路径完全可以用 native 的系统 API 得到,不依赖 Java API。
drakeet 早就说过他可以,不过具体怎么办恕我无才,我就猜不出了,而且我不打算再去当甚么猴子,当成迷吧。
但是,如果还有下一次,恐怕我会当成迷的东西真的会少很多。
2. Kotlin 里使用
后来自认为是 DSL 方便点而已。
至于 Android 和 Java 开发/日常部分我不熟悉也就不看了,关于逆向和代码保护的标题我看了,也就是防猴不防人。
没做 OCR 的原因是机器太卡了...
而且内容质量看起来也是高了不少,虽然还算是意料之中,分享的大部分还是停留在使用层面...
两个看到了想说什么的:
1. native 中不依赖 PackageManager 和 signature API 进行签名验证的方法
猜测:
a. 手动算 file 再算 dex hash 和长度什么的,总之就是利用文件系统
b. 找几个应用类算代码 hash 校验,不过实际上这也不叫签名验证
c. JNI 是否 Android 有提供验证的方法
d. 检查重新打包时一切可能发生改变的东西,比如安装包大小?APK 的路径完全可以用 native 的系统 API 得到,不依赖 Java API。
drakeet 早就说过他可以,不过具体怎么办恕我无才,我就猜不出了,而且我不打算再去当甚么猴子,当成迷吧。
但是,如果还有下一次,恐怕我会当成迷的东西真的会少很多。
2. Kotlin 里使用
Number.dp 扩展属性而不是 Number.dp()
开始我套了一下:JavaScript 里 String.prototype.bold 是不是也得变成『accessor』呢后来自认为是 DSL 方便点而已。
10.dp 不是比 10.dp() 好看么,虽然在符合直觉上有争论(显然第二个语义上有 10.makeAs(dp) 的意思,第一个则从表述上取胜)。至于 Android 和 Java 开发/日常部分我不熟悉也就不看了,关于逆向和代码保护的标题我看了,也就是防猴不防人。
没做 OCR 的原因是机器太卡了...
/tmp/duangsuse.sock
oop.lua
... 我打算浅尝辄止了,因为事情的确比较多... 我不想在 #Lua 和 #OOP 上花太多精力
简单讲一下,
take 一个 object、一个 chainf、一个 hasnextf,具体怎么做就是通过 hasnextf 确认是否有下一项、 chainf 箭头完成状态切换。
InvocationChain 就是 ListIterator 控制,使用完全相同参数调用的函数 chain 而已,利用副作用在受管函数间传递,实现了 OOP 的 call-super chain 模式(不过不能做到在没有 call 的时候自动调用,需要额外添加处理余项的逻辑)
Lua 的 C 用户接口使用
非 prototype 的意思就是:
Prototype 使用 prototype 创建(初始化)对象
prototype 也可能有自己的 prototype,prototype 创建先 call 自己的 prototype 初始化目标对象,再 call 自己的 initializer(constructor)
非 prototype 就是类似 Java 的实现方法,自动生成 call-super 调用,保证初始化都做过了。
简单讲一下,
LinkIterable 和 InvocationChain 也非常简单,LinkIterabletake 一个 object、一个 chainf、一个 hasnextf,具体怎么做就是通过 hasnextf 确认是否有下一项、 chainf 箭头完成状态切换。
InvocationChain 就是 ListIterator 控制,使用完全相同参数调用的函数 chain 而已,利用副作用在受管函数间传递,实现了 OOP 的 call-super chain 模式(不过不能做到在没有 call 的时候自动调用,需要额外添加处理余项的逻辑)
Lua 的 C 用户接口使用
lua_ 开头,Lua 支持 C Closure。非 prototype 的意思就是:
Prototype 使用 prototype 创建(初始化)对象
prototype 也可能有自己的 prototype,prototype 创建先 call 自己的 prototype 初始化目标对象,再 call 自己的 initializer(constructor)
非 prototype 就是类似 Java 的实现方法,自动生成 call-super 调用,保证初始化都做过了。
class Animal(id: Int, name: String, friendly: Boolean = true)Kotlin 里这种行为比 Java 8 里明显(
class Cat(nick: String, fur_color: Cat.Property.FurColor): Animal(0, "cat", true)
class MagicAnimal constructor(id: Int, name: String, friendly: Boolean): Animal(id,name,friendly)
MagicAnimal 明明没有专门定义子类型的架构器,可还是用了 Animal())。class MagicAnimal extends Animal {}
Lua OOP 的这个事情不发就可以了。(逃跑
/tmp/duangsuse.sock
... 我打算浅尝辄止了,因为事情的确比较多... 我不想在 #Lua 和 #OOP 上花太多精力 简单讲一下,LinkIterable 和 InvocationChain 也非常简单,LinkIterable take 一个 object、一个 chainf、一个 hasnextf,具体怎么做就是通过 hasnextf 确认是否有下一项、 chainf 箭头完成状态切换。 InvocationChain 就是 ListIterator 控制,使用完全相同参数调用的函数 chain 而已,利用副作用在受管函数间传递,实现了…
对 Lua OO 的理解不够深入,vtable 的 meta 方法向上查找没有注意到。
本来应该是实例 __index 到本 class 的 vtable 找,每一 class 的 vtable 找不到就到上层找,我的是实例级别包办一切。
而且我不知道可以给 __index 指定一个 table 作为代理...
本来应该是实例 __index 到本 class 的 vtable 找,每一 class 的 vtable 找不到就到上层找,我的是实例级别包办一切。
而且我不知道可以给 __index 指定一个 table 作为代理...
Telegram 连接总是不太平... 唉,doge 酱的 Telegram Web 勉强可以用
待会我打算先写篇文章(因为
标题是《状态机模型、分词器、解析器、解释器》
画点 dia...
待会我打算先写篇文章(因为
npm install -g web-ext 垃圾成功不了,NPM 是基于 GIt VCS 的包管理... 某 maintainer 手贱写错部署配置了)标题是《状态机模型、分词器、解析器、解释器》
画点 dia...
/tmp/duangsuse.sock
Telegram 连接总是不太平... 唉,doge 酱的 Telegram Web 勉强可以用 待会我打算先写篇文章(因为 npm install -g web-ext 垃圾成功不了,NPM 是基于 GIt VCS 的包管理... 某 maintainer 手贱写错部署配置了) 标题是《状态机模型、分词器、解析器、解释器》 画点 dia...
我修改了一下,平复了思路上的区别... 的确是我辣鸡不少,本来递归查找就应该是虚表级别的事情,我却让实例级别来做。
顺便 #fix 一下:
之前消息 https://t.me/dsuse_tmp/11 里的『某个作用域』应为『某个生存周期(lifetime)』
顺便 #fix 一下:
之前消息 https://t.me/dsuse_tmp/11 里的『某个作用域』应为『某个生存周期(lifetime)』
Telegram
/tmp/duangsuse.sock
我也是... 完全没有注意到它要干什么,可能的确是要运行时生成子类实现吧?
既然出现了 Animation ,一般认为都是关于前端的事情吧,可是这明明是序列化,对数据表示方式的变换(所以它只是一个用例啊...)。
我只知道,如果开发者写一个 class UserPhotoInptMedia(): InputMedia() 就可以直接在代码里访问到 companion object 里的 module 了,或许是这么用:
val buffer = InputMedia.module.serializ…
既然出现了 Animation ,一般认为都是关于前端的事情吧,可是这明明是序列化,对数据表示方式的变换(所以它只是一个用例啊...)。
我只知道,如果开发者写一个 class UserPhotoInptMedia(): InputMedia() 就可以直接在代码里访问到 companion object 里的 module 了,或许是这么用:
val buffer = InputMedia.module.serializ…
数据流和某些数据本身的回溯真的是不好做的,lifetime 也很难分析
就像这次我奇怪的递归查找一样,其实这不是最好看最高效能的方法(虽然它也很好)。
设计思路永远应该是第一,可是实现的方法就有那么多种,怎么才能对自己的架构拥有良好的直觉呢?
架构是个更大的问题,可是对于连数据生存周期和依赖都看不透的我来说有点高大上 了。
虚表做并且缓存的事情,我让实例去做,但是编程中我也发现
对于高阶函数 UpValue 数据生存周期的选择和分析,真是不好做啊,
感觉自己可能莫名其妙就引用错了 UpValue,或许本来应该做成参数的,或许应该搞清楚数据依赖是来自哪个作用域该来自哪里,或许...
做到容易,做好难... #Lua 附上使用例子:
就像这次我奇怪的递归查找一样,其实这不是最好看最高效能的方法(虽然它也很好)。
设计思路永远应该是第一,可是实现的方法就有那么多种,怎么才能对自己的架构拥有良好的直觉呢?
架构是个更大的问题,可是对于连数据生存周期和依赖都看不透的我来说有点高大上 了。
虚表做并且缓存的事情,我让实例去做,但是编程中我也发现
对于高阶函数 UpValue 数据生存周期的选择和分析,真是不好做啊,
感觉自己可能莫名其妙就引用错了 UpValue,或许本来应该做成参数的,或许应该搞清楚数据依赖是来自哪个作用域该来自哪里,或许...
做到容易,做好难... #Lua 附上使用例子:
animal = inherit.class()
animal.ctor = function(o, id) o.name= id end
function animal:describe()
print("我是" .. self.name) end
cat = inherit.class(animal)
cat.ctor = function(o, id) o.name= "猫" .. id end
meo = cat.new('喵喵')
meo:describe() -- 我是猫喵喵
dog = inherit.class(animal)
dog.ctor = mk_nameprefix_ctor("狗")
woof = dog.new("招财")
woof:describe() -- 我是狗招财
coolanimal = inherit.class(animal)
function coolanimal:describe()
print(self.name .. " 是很酷的!") end
caffe = coolanimal.new("Caffe")
caffe:describe() -- Caffe 是很酷的!
pig = mk_animal("猪")
goog = mk_animal("神秘鸽", coolanimal)
pig.new("哼哼"):describe() -- 我是猪哼哼
goog.new("咕咕"):describe()
-- 神秘鸽咕咕 是很酷的!
/tmp/duangsuse.sock
数据流和某些数据本身的回溯真的是不好做的,lifetime 也很难分析 就像这次我奇怪的递归查找一样,其实这不是最好看最高效能的方法(虽然它也很好)。 设计思路永远应该是第一,可是实现的方法就有那么多种,怎么才能对自己的架构拥有良好的直觉呢? 架构是个更大的问题,可是对于连数据生存周期和依赖都看不透的我来说有点高大上 了。 虚表做并且缓存的事情,我让实例去做,但是编程中我也发现 对于高阶函数 UpValue 数据生存周期的选择和分析,真是不好做啊, 感觉自己可能莫名其妙就引用错了 UpVal…
如果想要覆盖『父类』(实质是自己的 prototype)的架构器,很不幸,不可能
因为你的父类架构器总在你之前调用。
如果想要使用某个类的父类架构器,可以
1. 指名道姓地引用,
1. 用名字去引用父类的方法
2. 修改 oop 模块的 member_creation
以上 (2) 项目都是玩玩而已,实际上完全没有必要(跑
如果想要拥有静态方法和静态字段,则需要建立
面向对象的混入(mix-in) 必须通过修改 vtable 虚表查找和 oop 模型来建立,因为要混入额外的成员查找路径
因为你的父类架构器总在你之前调用。
如果想要使用某个类的父类架构器,可以
1. 指名道姓地引用,
animal.ctor(o)
2. 修改 oop 模块的源码,让 __newindex 元方法在冲突的时候定义 dog.super_ctor, 或者直接使用 dog.super.ctor
如果面向对象实例行为的覆盖想要使用父类的操作:1. 用名字去引用父类的方法
2. 修改 oop 模块的 member_creation
__newindex, 在发现覆盖的时候定义一个 super_XXX 就可以以上 (2) 项目都是玩玩而已,实际上完全没有必要(跑
如果想要拥有静态方法和静态字段,则需要建立
companion object
使用静态(需要和实例级别的成员完全隔离)的时候也得完全隔离(虽然实际作用域上是行为和状态都不分开,实例作用域可以随便引用静态成员,和 Lua OOP 里的相称,不过 LuaOOP 里 cat.name 是不能当成『类』的『静态成员』看待的,只有实例成员才会向上查找继承树)object = inherit.class()
animal.helper = object.new()
animal.helper.feed_animal = function ...面向对象的混入(mix-in) 必须通过修改 vtable 虚表查找和 oop 模型来建立,因为要混入额外的成员查找路径
/tmp/duangsuse.sock
... 我打算浅尝辄止了,因为事情的确比较多... 我不想在 #Lua 和 #OOP 上花太多精力 简单讲一下,LinkIterable 和 InvocationChain 也非常简单,LinkIterable take 一个 object、一个 chainf、一个 hasnextf,具体怎么做就是通过 hasnextf 确认是否有下一项、 chainf 箭头完成状态切换。 InvocationChain 就是 ListIterator 控制,使用完全相同参数调用的函数 chain 而已,利用副作用在受管函数间传递,实现了…
LinkIterable 可以用来实现基于 super 指针的超类成员查找InvocationChain 则可以实现对架构器链条的调用(非 prototype 模式的,子类架构器可以选择是否调用超类架构器来初始化)不过还是先写... 《基于状态机的流处理程序和文本解释器》 休息一下~
Traceback.java
3.8 KB
#Java 咳咳,既然频道只有认识我的几位 dalao,我就发下链接了。其实这个是我重写 drakeets 上面的。
利用
tracefmt("main") 来生成对 console application 的回溯追踪test2::Traceback← 86
test
::↑← 85
类似这样,它能提示很多信息,不止一个 name
/tmp/duangsuse.sock
Traceback.java
我特意下载了图片,不知道隔壁实现的可以看看:
我现在已经不敢评价他的代码了,每次涉及一点点负面都要解释半天真麻烦啊。
所以代码我一个字都没有动,都是战战兢兢地完全复制下来的 0_0
我们直接跳过
我现在已经不敢评价他的代码了,每次涉及一点点负面都要解释半天真麻烦啊。
所以代码我一个字都没有动,都是战战兢兢地完全复制下来的 0_0
/** @author Drakeet Xu */
object Debugs {
fun stackTrace(self: Any, @IntRange(from = 2) limit: Int = 3): String? {...}
}
其中,实际实现:if (!BuildConfig.DEBUG) return null
val result = StringBuilder()
var length = 0
for ((i, it) in Thead.currentThread().stackTrace.withIndex()) {...}
return result.toString()
在循环里,我们处理格式化问题。if (i < 4 || it.methodName.contains("\$default")) continue
如果还在访问开始的 4 项 (0,1,2,3) (反射了上面的 Thead.currentThread().stackTrace.withIndex() 和自己的调用记录),或者方法名包含 $default(一般自动生成的方法名包含此)我们直接跳过
if (length > 0) result.append(" <- ")
如果不是输出的第一项,则我们输出一个箭头,目标是实现字符串列表的 join
if (self.javaClass.name != it.className) { result.append(it.className).append(".") }
如果不是当前应用程序的类,则附上类名信息result.append(it.methodName.replace("\$app_debug",""))
输出项目方法名,去掉其中的 $app_debug 部分length++
if (length >limit) break
如果已经输出了 n 项,就停止输出。
/tmp/duangsuse.sock
我特意下载了图片,不知道隔壁实现的可以看看: 我现在已经不敢评价他的代码了,每次涉及一点点负面都要解释半天真麻烦啊。 所以代码我一个字都没有动,都是战战兢兢地完全复制下来的 0_0 /** @author Drakeet Xu */ object Debugs { fun stackTrace(self: Any, @IntRange(from = 2) limit: Int = 3): String? {...} } 其中,实际实现: if (!BuildConfig.DEBUG) return…
其中,
实际的逻辑
上面的『状态机』部分就有一个好,它是自律(self-managed) 的
其实编程中一般被抽象为实例(模块)或高阶方法、generator,它只是保留状态,随时可以挂起。
就像上面的 forEach,其实完全可以删掉,变成『输入流对接到状态机 🐤 上』
输入流结束后,
partitionWhile 使用了状态机模式实现。partitionWhile:
input List<T> xs
input Predicate<? super T> p
output Pair<List<T
>, List<T>> res
这是此算法的签名 where part (0), takeall; part -> takeall
两个状态。计算可以这么描述forEach x : xs两个同步操作、三个输入信号 take, drop, x
let drop = p.test(x), take = !drop
dropIt = res.component0.add(x)
takeIt = res.component1::add(x)
实际的逻辑
part <- drop = dropIt
part <- take = takeIt => takeall
我们在获得了第一个 take 的项目后同时通过状态转移进入了 takeall 状态takeall <- drop/take = takeIt
takeall 状态里,无论 take 还是 drop 的结果都是 takedstate* <- take = takeIt
所以才说我写的代码烂,因为理论稍微看一下就知道,已经覆盖了所有情况。上面的『状态机』部分就有一个好,它是自律(self-managed) 的
其实编程中一般被抽象为实例(模块)或高阶方法、generator,它只是保留状态,随时可以挂起。
就像上面的 forEach,其实完全可以删掉,变成『输入流对接到状态机 🐤 上』
输入流结束后,
res 里面就是整个算法的结果了。