明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 8790|回复: 33

[经验] [原创]给AutoLisp语言增加goto指令

  [复制链接]
发表于 2020-3-21 11:49 | 显示全部楼层 |阅读模式
本帖最后由 baitang36 于 2020-3-21 12:09 编辑

   众所周知,lisp语言是没有无条件跳转指令的,程序只能按顺序执行。fas是支持无条件跳转指令的,但正常的编译程序无法生成。我们可以变通一下,采取曲线救国的方式来实现。在lsp源码中写入特殊字符串,编译成正常fas程序后再修改,这样可以达到目的,实现在函数间无条件跳转。
请看源码:
(defun c:zhuce()
  (setq zcm (getint "请输入注册码:"))
  (if (= zcm 3637)(setq syz_goto 959461169)(princ"注册码错误!"));如注册码正确跳转
  (princ)
)
(defun t1 ()(princ "检查注册码")
(exit)
(setq syz_loc1 959461170 ) ;让程序跳到这里开始执行
(princ "注册码正确,欢迎使用")
  ;这里插入需要运行的程序
(princ)
  (princ)
)
这里的(setq syz_goto 959461169)和 (setq syz_loc1 959461170 )就是两个记号,fas的无条件跳转指令是57h(十进制87),只要找到这两个记号,计算出两个记号之间的间隔大小,就可以修改跳转,达到我们的目的。
959461169在fas中以16进制显示是31709,959461170是32709,很容易找到。
用winhex看修改前的tmp.fas是这样的:
Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F
00000000   0D 0A 20 46 41 53 34 2D  46 49 4C 45 20 3B 20 44      FAS4-FILE ; D
00000010   6F 20 6E 6F 74 20 63 68  61 6E 67 65 20 69 74 21   o not change it!
00000020   0D 0A 31 31 31 0D 0A 31  32 20 24 14 00 00 00 00     111  12 $     
00000030   09 0B 00 35 01 0A 00 03  06 09 00 03 09 00 33 35      5          35
00000040   0E 00 00 35 02 08 00 03  67 0D 00 00 00 33 31 37      5    g    317
00000050   30 39 06 07 00 57 09 00  00 00 09 06 00 35 01 05   09   W       5  
00000060   00 03 0A 35 00 05 00 03  16 14 00 00 00 00 09 04      5            
00000070   00 35 01 05 00 03 0A 35  00 03 00 03 0A 33 32 37    5     5     327
00000080   30 39 06 02 00 09 01 00  35 01 05 00 03 0A 35 00   09      5     5
00000090   05 00 03 0A 35 00 05 00  03 16 24 0D 0A 32 38 30       5     $  280
修改后的tmp改.fas是这样:
Offset      0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F
00000000   0D 0A 20 46 41 53 34 2D  46 49 4C 45 20 3B 20 44      FAS4-FILE ; D
00000010   6F 20 6E 6F 74 20 63 68  61 6E 67 65 20 69 74 21   o not change it!
00000020   0D 0A 31 31 31 0D 0A 31  32 20 24 14 00 00 00 00     111  12 $     
00000030   09 0B 00 35 01 0A 00 03  06 09 00 03 09 00 33 35      5          35
00000040   0E 00 00 35 02 08 00 03  67 0D 00 00 00 57 33 00      5    g    W3
00000050   00 00 20 20 20 57 09 00  00 00 09 06 00 35 01 05        W       5  
00000060   00 03 0A 35 00 05 00 03  16 14 00 00 00 00 09 04      5            
00000070   00 35 01 05 00 03 0A 35  00 03 00 03 0A 33 32 37    5     5     327
00000080   30 39 06 02 00 09 01 00  35 01 05 00 03 0A 35 00   09      5     5
00000090   05 00 03 0A 35 00 05 00  03 16 24 0D 0A 32 38 30       5     $  280
红色的部分是修改的数据。
改过的程序是不能被正确反编译的,因为正常的lisp没有goto。
用某流行的反编译工具反编译结果如下:
(vl-ACAD-defun (DEFUN C:ZHUCE() (setq ZCM (GETINT "请输入注册码:" ))  (if (= ZCM 3637 ) (PROGN   )(PROGN   )(PROGN   (PRINC "注册码错误!" ) )) (PRINC )  ) )
'C:ZHUCE
(DEFUN T1() (PRINC "检查注册码" ) (EXIT ) (setq SYZ_LOC1 959461170) (PRINC "注册码正确,欢迎使用" ) (PRINC ) (PRINC )  )
可以看出,关键的跳转没有弄出来。


本帖子中包含更多资源

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

x

评分

参与人数 4明经币 +4 金钱 +5 收起 理由
hhh454 + 1 + 5 赞一个!
Kye + 1 谢谢大佬分享具体方法
taoyi0727 + 1 楼主老牛了,lisp的安全你做了很大贡献,虽.
tryhi + 1 给力,非常有用!

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下
发表于 2020-3-21 22:05 | 显示全部楼层
请教大佬如何获取修改的57 33 00 00 00 20 20 20,结合大佬以前帖子fas文件中的if和goto指令 理解:57为goto指令,33为跳转字节长度(51个,十进制https://tool.oschina.net/hexconvert/ 在线转的),前一个记号为绿色背景部分,字节数8个(理解应是前5个字节,不清楚后3个字节06 07 00为何也算为前一记号的一部分),两个记号之间的间隔大小理解为黄色背景部分,字节数40个,合计48个,与33h((51个,十进制)不相等,请问那个地方理解错了?另请问修改段的20 20 20 的含义,如何才能获取到?谢谢

00000040   0E 00 00 35 02 08 00 03  67 0D 00 00 00 33 31 37      5    g    317
00000050   30 39 06 07 00 57 09 00  00 00 09 06 00 35 01 05   09   W       5  
00000060   00 03 0A 35 00 05 00 03  16 14 00 00 00 00 09 04      5            
00000070   00 35 01 05 00 03 0A 35  00 03 00 03 0A 33 32 37    5     5     327
00000080   30 39 06 02 00 09 01 00  35 01 05 00 03 0A 35 00   09      5     5

发表于 2020-7-3 02:07 | 显示全部楼层
本帖最后由 yxp 于 2020-7-3 04:42 编辑

老哥老当益壮,志在千里啊。照猫画虎改造成功,不知道能否跨程序 goto ?

另外请教 33 31 37 30 39 06 07 00 中
31 37 30 39  是小端法存储的  h39303731,也就是十进制的 959,461,169
06 07 其中 06 是 setq , 07 是什么意思? 00  是结束符

57 后紧跟的跳转字节数,如果大于256怎么办,用两个字节存储?

(defun c:test ()
  (princ "\n跳转测试 --1")
  (setq firstData 321654987)
  (princ "\n跳转测试 --2")
  (setq secondData 321654987)
  (princ "\n跳转测试 --3")  
  (princ)
)

改造完成,测试完全没问题!

本帖子中包含更多资源

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

x
发表于 2020-3-21 15:16 | 显示全部楼层
处理跳出循环

(defun c:qq()
  (setq i 1)
  (while (< i 5)
        (setq i (1+ i))
        (print "ok")
        (setq goto 987987987)
        (print "不再执行")
  )
  (princ)
)

源码执行:

C:QQ
命令: qq
"ok"
"不再执行"
"ok"
"不再执行"
"ok"
"不再执行"
"ok"
"不再执行"

跳转后:

命令: qq
"ok"
"ok"
"ok"
"ok"
发表于 2020-3-21 12:01 | 显示全部楼层
真的是大神!!!!
继续深挖
发表于 2020-3-21 12:15 | 显示全部楼层
本帖最后由 不死猫 于 2020-3-21 23:13 编辑

重磅!反编译的吐血

注意这个跳会影响返回值,可能返回 :CALLBACK-ENTRY
发表于 2020-3-21 12:35 来自手机 | 显示全部楼层
震惊!一男子居然做出这种事情,让反编译……
发表于 2020-3-21 12:44 | 显示全部楼层
楼主老牛了,lisp的安全你做了很大贡献
发表于 2020-3-21 14:36 | 显示全部楼层
本帖最后由 Kye 于 2020-3-21 14:41 编辑

谢谢baitang36大佬的详细讲解,上次tryhi老师在QQ 群里分享goto方法时,俺一脸懵逼,也不敢细问
发表于 2020-3-21 18:42 | 显示全部楼层
现在大佬们写lisp程序都是直接用winhex打开fas来写了,惹不起,惹不起……
发表于 2020-3-21 21:18 来自手机 | 显示全部楼层
牛逼大发了~~~
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-3-29 09:35 , Processed in 0.315396 second(s), 29 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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