shc 对 arm 设备不兼容,如何解决? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Distributions
Ubuntu
Fedora
CentOS
中文资源站
网易开源镜像站
lirunext
V2EX    Linux

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

  • &nsp;
  •   lirunext 2024-01-03 23:26:15 +08:00 2736 次点击
    这是一个创建于 721 天前的主题,其中的信息可能已经有所发展或是发生改变。
    一句话描述:通过 shc 和交叉编译链把脚本编译为可执行文件,在 arm 设备不能正常运行

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



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


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

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

    2 ,写了一个最简易的脚本 testsh.sh ,只包含显示 hello world ,使用 shc 加密为.c 文件和编译,在 x86 设备可以正常运行;使用交叉编译链编译.c 文件,在 arm 设备运行会报错:./testsh: {-0M:1t(说明脚本也没问题,是 shc 对 ARM 平台的兼容问题
    23 条回复    2024-01-17 20:52:04 +08:00
    424778940
        1
    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
        2
    424778940  
       2024-01-03 23:52:55 +08:00
    再说这个问题如果不是很复杂的脚本直接拿 cpp 写了编译不行吗?
    leonshaw
        3
    leonshaw  
       2024-01-04 01:53:28 +08:00 via Android
    arm 上原生编译不行吗?
    ysc3839
        4
    ysc3839  
       2024-01-04 05:37:38 +08:00 via Android
    我在 Android Termux 上试了下并没问题,原因不明。
    另外提醒一下,这些“shell 脚本加密”基本上都是掩耳盗铃,因为最终都是要用外部 shell 解释运行的,除非自身包含 shell 代码。
    看了下 shc 的运行流程,首次启动后会计算一个密钥,存放到环境变量中,然后用 exec 重启自身(是 sh -c exec "<自身路径>" 来重启的,而不是直接 exec 自身路径,原因不明),再用环境变量中的密钥解密出脚本,然后把解密后的脚本内容通过命令行传递给 shell 执行。
    破解起来也非常简单,直接 cat /proc/<进程 ID>/cmdline 就能看到解密后的脚本。
    所以脚本不复杂的话建议用 C 重写,如果可以的话建议把脚本发出来,不复杂的话我可以帮忙用 C 重写。
    liberize
        5
    liberize  
       2024-01-04 08:33:21 +08:00 via Android
    https://github.com/liberize/ssc
    试试我写的类似的用 pipe 方式的工具,比命令行参数方式更隐蔽一点。
    lsk569937453
        6
    lsk569937453  
       2024-01-04 09:06:20 +08:00
    @424778940 +1
    c/cpp/rust 楼主你有很多种选择的
    suyuyu
        7
    suyuyu  
       2024-01-04 09:27:57 +08:00
    想起了免流脚本
    kkhaike
        8
    kkhaike  
       2024-01-04 11:36:26 +08:00
    我有个问题很好奇。。既然 shc 编译后还是要依赖 bash 。那么编译的意义是不是就是打包的效果?
    lirunext
        9
    lirunext  
    OP
       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
        10
    lirunext  
    OP
       2024-01-04 20:07:24 +08:00
    @424778940 发生这个问题问题后,我也动过拿 cpp 写了后编译的念头,奈何不会 C 语言,工作太忙学习成本有点高。。。尝试用 chatGPT ,上传脚本让它转为一样效果的 c 文件,这家伙绕来绕去只给一小段代码。。。所以就搁置了。
    lirunext
        11
    lirunext  
    OP
       2024-01-04 20:20:22 +08:00
    @ysc3839 感谢,可能是我的 arm 设备有点特殊的问题。。这个破解的话关系不大,安全等级没那么高,主要是有规定不能是明文给用户,所以只能想“加层壳”。。。
    我也想过用 c 重写,奈何不懂 c ,再加上工作太忙,所以学习成本比较高。脚本还是有点复杂的,近 800 行了。。主要是涉及到一些公司的私有接口,不适合发出来呢。。。
    lirunext
        12
    lirunext  
    OP
       2024-01-04 20:22:51 +08:00
    @kkhaike 是的,加层壳,不要像文本文件那样可以轻松阅读就可以
    lirunext
        13
    lirunext  
    OP
       2024-01-04 20:24:03 +08:00
    @424778940 打错,应该是“我在提问前试过把脚本开头分别写为#!/bin/sh 和#!/bin/bash”
    duke000
        14
    duke000  
       2024-01-05 09:26:27 +08:00
    遇到过同样的问题,当时的解决方案是:

    在每个板子上执行 shc 和 gcc

    然后把板子的 TF 卡插到同款其它板子上,运行这个程序也会出错,每个板子都要单独执行 shc 和 gcc
    lirunext
        15
    lirunext  
    OP
       2024-01-06 00:18:07 +08:00
    @ysc3839 感觉有可能是一楼网友说的 busybox 的原因,我使用 shc 加上-B 参数后,再使用交叉编译链进行编译,在 arm 设备运行,就不会提示乱码了,而是提示/bin/sh: cannot execute binary file ,请问这样能判断是已经解密出脚本,是通过命令行传递给 shell 过程执行这个过程出的问题吗?
    hpc4you
        16
    hpc4you  
       2024-01-08 14:50:21 +08:00
    @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
        17
    liberize  
       2024-01-08 18:15:42 +08:00 via Android
    @hpc4you 同样参数直接终端手动调用试试。
    hpc4you
        18
    hpc4you  
       2024-01-15 14:50:29 +08:00
    @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
        19
    liberize  
       2024-01-15 21:50:34 +08:00
    @hpc4you 重新拉一下最新代码试试
    liberize
        20
    liberize  
       2024-01-15 22:54:57 +08:00
    另外,dev 分支用了另一种方式实现,解决了脚本不能读取标准输入的问题
    hpc4you
        21
    hpc4you  
       2024-01-17 14:33:17 +08:00
    @liberize 感谢.
    dev 分支可以解决问题. 实际操作中, scriptB 需要提示用户输入部分内容. 使用 dev 分支后, 运行负荷预期.

    默认 master 分支, 会跳过读取输入操作.

    输入读取采用的是`read -p`, 非常简陋的 bash SHELL.

    再次感谢.
    liberize
        22
    liberize  
       2024-01-17 18:39:55 +08:00 via Android   1
    @hpc4you 提醒一下,应该选一个 glibc 版本尽量低的系统运行 ssc ,这样生成的二进制文件依赖的 glibc 版本比较低,在老系统上也能运行
    hpc4you
        23
    hpc4you  
       2024-01-17 20:52:04 +08:00
    @liberize 多谢提醒.

    经过测试确认, dev branch, 可以处理屏幕输入, 目前看来符合我的应用场景.

    经过测试, 在 centOS7.9, 编译的二进制, 可以顺利在 Rocky8.8, AlmaLinux9.0, centOS7.9 运行.
    推测, 在 Ubuntu Focal, Jammy 也是可以运行的.

    再次感谢.
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1017 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 22:50 PVG 06:50 LAX 14:50 JFK 17:50
    Do have aith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86