明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 769|回复: 7

[【不死猫】] 抗反编译方法(第9讲)参数一对一自定义可选多参数及20指令思考

[复制链接]
发表于 2021-9-16 10:50 | 显示全部楼层 |阅读模式
本帖最后由 不死猫 于 2021-10-30 22:18 编辑

lisp函数在编译后函数十进制编码为:

20 aa bb cc dd
已知dd默认都是0,修改为1可以实现多参数传递(此方法最早由晨语公布),
由于当dd等于1时超过cc上限的参数传递给最后一个参数转为大参数表,lsp从大参数里提取数据需要判断最后一位的情况,假如最后一个参数本身就是表,则不容易判断传递过来的参数到底是几个。




试验发现,bb决定接收参数个数的下限,cc决定接收参数个数的上限,因此下面的修改可以直接实现多参数,不需要对dd修改处理,也就不需要修改lsp程序提取大参数,并且参数传递是一对一的
20 aa 0 255 0
以0-100个参数为例,编译以下代码:
(defun tt(a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15 a16 a17 a18 a19 a20 a21 a22 a23 a24 a25 a26 a27 a28 a29 a30 a31 a32 a33 a34 a35 a36 a37 a38 a39 a40 a41 a42 a43 a44 a45 a46 a47 a48 a49 a50 a51 a52 a53 a54 a55 a56 a57 a58 a59 a60 a61 a62 a63 a64 a65 a66 a67 a68 a69 a70 a71 a72 a73 a74 a75 a76 a77 a78 a79 a80 a81 a82 a83 a84 a85 a86 a87 a88 a89 a90 a91 a92 a93 a94 a95 a96 a97 a98 a99 a100 )
        (setq i 1)
        (repeat 100
                (princ (eval (read (strcat "a" (itoa i)))))
                (princ " ")
                (setq i (1+ i))
        )
        (princ)
)
默认编码如下:
020 101 100 100 000

修改为:
020 101 000 100 000
即可。

测试:
命令: (tt 1)
1 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
命令: (tt 1 2)
1 2 nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
命令: (tt 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18  19  20
21  22  23  24  25  26  27  28  29  30  31  32  33  34  35  36  37  38  39  40
41  42  43  44  45  46  47  48  49  50)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 nil nil nil nil
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil
nil nil nil nil nil nil


这里用100个参数举例子,从抗反编译角度来说,也用不了那么多。
如果需要0-255个可选参数,就自定义a1-a255个参数重新编译即可。
不过用满255个会有弊端,见下文。


======对20指令重新思考的分割线======

因为20指令后面第4位改1之后,函数调用可以传递多个参数,一直认为第4位是实现多参数的关键字。
重新阅读了【首发】定义真正意义的可选参数FAS 20号指令的深入研究这两篇文章后
这几天重新对20指令的后面几位字节和多参数的再次思考。
得到的试验结果如下:
第1位:声明使用无名变量,其值需等于函数体所有无名变量的总和(实际参数传递也是以无名变量存在),初始化无名变量。
(注意当无名参数数量刚好为256的倍数时,编译后该位等于0,编译后的函数就会造成内存错误。)
第2位:自定义函数能接受的参数最少个数,没有初始化功能。
第3位:自定义函数能接受的参数最多个数,初始化无名变量,当第3位为255时,第4位改1不再对多参数有影响,因为函数调用的最多参数个数是255个。
第4位:初始化无名变量。改为1后,当参数超过第3位数量时,把多的参数压入到下一个参数成为表,也就是以表的形式传递后续变量。此时可接受的参数个数+1。

常用的多参数实现就有下面几种模式:
按一对一传递,修改2/3位(2位改小3位不变或改小)
按大参数传递,修改:
                        2/3/4位(2位改小3位改小)
                        或3/4位(3位改小)
                        或2/4位+补参数
                        或1/4位+补参数
(若第3位不变或增加,则需要改第1位+补参数)

fas需要避免生成256倍数的无名变量,例如下面这段编译后加载会报错:







本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

评分

参与人数 1明经币 +3 金钱 +30 收起 理由
highflybird + 3 + 30

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下
 楼主| 发表于 2021-9-16 10:52 | 显示全部楼层
100 个可选参数文件:

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2021-9-16 11:14 | 显示全部楼层
经过试验,这办法是可行的。如果只是为了对抗反编译,没必要用255,最小是原来的个数减一就可以
发表于 2021-9-16 16:54 | 显示全部楼层
大概看了一下,好像没有新东西,似乎都是我以前说过的?http://bbs.mjtd.com/thread-181052-1-1.html



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
 楼主| 发表于 2021-9-17 09:40 | 显示全部楼层
本帖最后由 不死猫 于 2021-9-18 15:17 编辑
tryhi 发表于 2021-9-16 16:54
大概看了一下,好像没有新东西,似乎都是我以前说过的?http://bbs.mjtd.com/thread-181052-1-1.html

新东西:
1. 在不改第四位的情况下,第二位改为0,第三位改为255,就可以代替第四位改1。
2. 第三
表达应该是接收参数个数的上限


如果不改第四位会有“参数太多”问题,现在可以消除这个。
另外
“无限多个参数”说法是有问题的,参数最多是255个,再多就不能编译了。
"第三字节表示大参数个数"的说法有个前提是第四位改1,改造后总接收的参数数量=第三位+1。
 楼主| 发表于 2021-9-17 10:18 | 显示全部楼层
这个方法需要写好参数数量再编译,这样才能获取,否则直接改 20 aa 0 255 0 不改其他地方后面的参数是获取不到的。
发表于 2021-9-17 18:03 | 显示全部楼层
不死猫 发表于 2021-9-17 09:40
新东西:
1. 在不改第四位的情况下,第二位改为0,第三位改为255,就可以代替第四位改1。
2. 第三位表 ...

替代不了的第四位0,无限参数指的是可以用apply传递无限个参数
 楼主| 发表于 2021-9-18 09:28 | 显示全部楼层
tryhi 发表于 2021-9-17 18:03
替代不了的第四位0,无限参数指的是可以用apply传递无限个参数

哦,原来你是说apply后面跟无限个参数。
我重新思考了一下,说代替是不准确,因为我看来第四位改1本就不是无限参数的开关,功能是把多的参数压入最后变量上(原来说的大参数),按这个思路,源码稍微修改就可以代替第四位改1:

引用你的例子
;;例子1:
;;允许0至无限多个参数
(defun 2bei (a)
;        (setq a 1122334455 a 0 a 0);这句你应该是写多了
        (* 2 (apply '+ a))
)
(2bei 1 2 3)
原文中调用无限个参数修改20 1 1 1 0 改为20 1 0 0 1之后,可以这样调用:
(apply '2bei (list 1 2 3 4 5 6 7 8 9 10 ))
如果不修改第四位为1的话,直接这样调用可以等价(相当于把多的参数放入第0位参数组成表)
(apply '2bei (list (list 1 2 3 4 5 6 7 8 9 10)))

;;例子2:
;;允许0至无限多个参数
(defun princx (strs)
        (setq a 1122334455 a 0 a 0)
        (while (setq a(car strs))
                (setq strs(cdr strs))
                (princ a)
        )
        (princ)
)
原文中调用无限个参数修改20 1 1 1 0 改为20 1 0 0 1之后,可以这样调用:
(apply 'princx (list 1 2 3 4 5 6 7 8 9 10 ))
如果不修改第四位为1的话,直接这样调用可以等价(相当于把多的参数放入第0位参数组成表)
(apply 'princx (list (list 1 2 3 4 5 6 7 8 9 10)))

;;例子4:
;;允许2至无限多个参数
(defun boolex (a b c)
        (setq a 1122334455 a 2 a 0)
        (apply 'boole (append(list a b)c))
)
原文中调用无限个参数修改20 3 3 3 0 改为20 3 2 2 1之后,可以这样调用:
(apply 'boolex (list 1 2 3 4 5 6 7 8 9 10 ))
如果不修改编码的话,直接这样调用可以等价(相当于把多的参数放入第2位参数组成表)
(apply 'boolex (list 1 2 (list 3 4 5 6 7 8 9 10)))

这个也验证了第四位的作用是把多的参数做成表传递,做成表就是"无限参数"。其实手工写也一样。
而且不改2/3位,只把第4位改1大参数都不能直接获取。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-4-26 17:28 , Processed in 0.659159 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表