shc 对 arm 设备不兼容,如何解决?

2024-01-03 23:26:15 +08:00
 lirunext
一句话描述:通过 shc 和交叉编译链把脚本编译为可执行文件,在 arm 设备不能正常运行

楼主想要:解决这个问题,或者有其他的把 sh 脚本加密成二进制或其它方式可以在 arm 设备运行的方法



楼主写了一个.sh 脚本文件在某 arm 设备运行正常,需要共享出去使用,但涉及设备的某些私有接口因此需要加密,使用 shc 加密为.c 格式文件,在 x86 电脑使用交叉编译链编译为 arm 平台的可执行文件,在 arm 设备运行提示:./xxxx: ▒▒▒AP▒h▒▒▒4F▒kK▒,▒


为了验证是交叉编译链的问题,还是脚本的问题,或者又是 shc 这个工具对 ARM 平台的兼容问题,做了以下验证:

1 ,写了一个最简易的 c 文件,只包含显示 hello world 。在 x86 电脑直接使用 gcc 编译,在 x86 设备可以正常运行;在 x86 电脑交叉编译后,在 arm 设备也可以正常运行;————说明交叉编译链没问题

2 ,写了一个最简易的脚本 testsh.sh ,只包含显示 hello world ,使用 shc 加密为.c 文件和编译,在 x86 设备可以正常运行;使用交叉编译链编译.c 文件,在 arm 设备运行会报错:./testsh: Ʈ▒▒{▒▒-▒0M:1▒t(————说明脚本也没问题,是 shc 对 ARM 平台的兼容问题
1989 次点击
所在节点    Linux
23 条回复
424778940
2024-01-03 23:51:19 +08:00
注意 shc 的文档有这么一句话 "The compiled binary will still be dependent on the shell specified in the first line of the shell code (i.e shebang) (i.e. #!/bin/sh), thus shc does not create completely independent binaries."

你最好看看是不是 arm 自带的 sh 的问题, 有很多精简系统用的是 busybox 然后可能还不是 bash 而是 ash 之类的
424778940
2024-01-03 23:52:55 +08:00
再说这个问题如果不是很复杂的脚本直接拿 cpp 写了编译不行吗?
leonshaw
2024-01-04 01:53:28 +08:00
arm 上原生编译不行吗?
ysc3839
2024-01-04 05:37:38 +08:00
我在 Android Termux 上试了下并没问题,原因不明。
另外提醒一下,这些“shell 脚本加密”基本上都是掩耳盗铃,因为最终都是要用外部 shell 解释运行的,除非自身包含 shell 代码。
看了下 shc 的运行流程,首次启动后会计算一个密钥,存放到环境变量中,然后用 exec 重启自身(是 sh -c exec "<自身路径>" 来重启的,而不是直接 exec 自身路径,原因不明),再用环境变量中的密钥解密出脚本,然后把解密后的脚本内容通过命令行传递给 shell 执行。
破解起来也非常简单,直接 cat /proc/<进程 ID>/cmdline 就能看到解密后的脚本。
所以脚本不复杂的话建议用 C 重写,如果可以的话建议把脚本发出来,不复杂的话我可以帮忙用 C 重写。
liberize
2024-01-04 08:33:21 +08:00
https://github.com/liberize/ssc
试试我写的类似的用 pipe 方式的工具,比命令行参数方式更隐蔽一点。
lsk569937453
2024-01-04 09:06:20 +08:00
@424778940 +1
c/cpp/rust 楼主你有很多种选择的
suyuyu
2024-01-04 09:27:57 +08:00
想起了免流脚本
kkhaike
2024-01-04 11:36:26 +08:00
我有个问题很好奇。。既然 shc 编译后还是要依赖 bash 。那么编译的意义是不是就是打包的效果?
lirunext
2024-01-04 20:04:18 +08:00
@424778940
谢谢,感觉可能和你说的有关系,我在提问前试过把脚本开头分别写为#!/bin/bash 和#!/bin/bash ,shc 加密和交叉编译后,在设备运行都是报错乱码;

我这 arm 设备里面是有自带 busybox 的,但不知道是否是默认用这个。我看到你说了 busybox 后,尝试过
1 、把脚本开头写成#!/bin/busybox ,shc 带与不带-B 都会提示 shc Unknown shell (busybox): specify [-i][-x][-l]
shc: Success


2 、查到加 shc 加上-B 参数可以兼容 busybox ,把脚本开头分别写为#!/bin/sh 和#!/bin/bash ,shc 加密和交叉编译后,在设备运行都提示:
/bin/sh: cannot execute binary file


现在不清楚脚本首行到底应该写啥



以下是一些信息,不知是否有用

在终端运行:cat /etc/shells
结果是:
# /etc/shells: valid login shells
/bin/sh
/bin/bash


在终端运行:echo $SHELL
结果是:/bin/sh

在终端运行:ls -l /bin/ | grep bash
结果是:
lrwxrwxrwx 1 root root 14 Jul 24 11:10 bash -> /bin/bash.bash
-rwxr-xr-x 1 root root 912864 Jul 24 10:50 bash.bash
lrwxrwxrwx 1 root root 14 Jul 24 11:10 sh -> /bin/bash.bash
lirunext
2024-01-04 20:07:24 +08:00
@424778940 发生这个问题问题后,我也动过拿 cpp 写了后编译的念头,奈何不会 C 语言,工作太忙学习成本有点高。。。尝试用 chatGPT ,上传脚本让它转为一样效果的 c 文件,这家伙绕来绕去只给一小段代码。。。所以就搁置了。
lirunext
2024-01-04 20:20:22 +08:00
@ysc3839 感谢,可能是我的 arm 设备有点特殊的问题。。这个破解的话关系不大,安全等级没那么高,主要是有规定不能是明文给用户,所以只能想“加层壳”。。。
我也想过用 c 重写,奈何不懂 c ,再加上工作太忙,所以学习成本比较高。脚本还是有点复杂的,近 800 行了。。主要是涉及到一些公司的私有接口,不适合发出来呢。。。
lirunext
2024-01-04 20:22:51 +08:00
@kkhaike 是的,加层壳,不要像文本文件那样可以轻松阅读就可以
lirunext
2024-01-04 20:24:03 +08:00
@424778940 打错,应该是“我在提问前试过把脚本开头分别写为#!/bin/sh 和#!/bin/bash”
duke000
2024-01-05 09:26:27 +08:00
遇到过同样的问题,当时的解决方案是:

在每个板子上执行 shc 和 gcc

然后把板子的 TF 卡插到同款其它板子上,运行这个程序也会出错,每个板子都要单独执行 shc 和 gcc
lirunext
2024-01-06 00:18:07 +08:00
@ysc3839 感觉有可能是一楼网友说的 busybox 的原因,我使用 shc 加上-B 参数后,再使用交叉编译链进行编译,在 arm 设备运行,就不会提示乱码了,而是提示/bin/sh: cannot execute binary file ,请问这样能判断是已经解密出脚本,是通过命令行传递给 shell 过程执行这个过程出的问题吗?
hpc4you
363 天前
@liberize
不晓得是 bug 还是我弄错了.
在 scriptA 中调用 scriptB, 遭遇以下提示信息:
```
/bin/bash: --: invalid option
Usage: /bin/bash [GNU long option] [option] ...
/bin/bash [GNU long option] [option] script-file ...
GNU long options:
--debug
--debugger
--dump-po-strings
--dump-strings
--help
--init-file
--login
--noediting
--noprofile
--norc
--posix
--pretty-print
--rcfile
--rpm-requires
--restricted
--verbose
--version
Shell options:
-ilrsD or -c command or -O shopt_option (invocation only)
-abefhkmnptuvxBCHP or -o option
```

其中, scriptB 也是脚本, 先用 ssc 编译为二进制, 比如名字是 scriptB.x,
在 scriptA 中, 采用/full/path/scriptB.x 调用, 然后看到了如上的输出信息.
liberize
362 天前
@hpc4you 同样参数直接终端手动调用试试。
hpc4you
356 天前
@liberize 抱歉, 我实在很外行. 我尽量详尽的描述我的操作过程.

其中, scriptB, 是采用 shell 编写的, 如果单纯运行 bash scriptB --help, 可以打印简单的使用说明.
比如可以实现 bash scriptB --sync_do "XXXX“之类的操作. 当然也支持./scriptB --sync_do "XXXX".

scriptA 当然也是 bash shell.

使用 SHC, 先编译 scriptB, 然后再从 scriptA 调用编译后的 scriptB.x, 运行符合预期.
再把 scriptA 使用 SHC 编译为 scriptA.x, 运行./scriptA.x 结果也是符合预期的.

按照同样的流程, 使用 ssc 先编译了 scriptB, 得到 scriptB.y, 运行 ./scriptB.y --help, 就会看到前序报告的提示信息.

我技能有限, 能分享的信息, 叙述完毕.
liberize
355 天前
@hpc4you 重新拉一下最新代码试试
liberize
355 天前
另外,dev 分支用了另一种方式实现,解决了脚本不能读取标准输入的问题

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1005637

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX