【工具】如何将一个脚本作为C语言的一个文件被include到新的C文件中然后执行?(C语言 array的方式)

快速回忆

bash 复制代码
vim my_shell.sh #如果修改shell名字,也需要修改c中对应的array和len宏定义
xxd -i my_shell.sh > my_shell.h
vim c_shell.c #拷贝本文的c_shell.c
gcc c_shell.c
./a.out
./a.out 1 2 3 #带参数执行,参数会被带到sub cmd中
# 修改脚本后需要全部重新来一遍,并且要删除掉默认路径的脚本,不然不会重新生成
注意的一点是,需要删掉脚本

背景

有些时候,用C语言想包括一个文件到运行态,因为C语言是静态程序,并且include的关键值只支持C格式,如何做到将某个文件存在于C语言中。

本文以一个C语言的例子,执行一个shell脚本,并且该脚本存在于C语言的bin文件中。

有什么用呢?

有些场景下不想提供脚本,只提供一个bin二进程程序。

方式

方式就是将脚本存储在C语言的数组中,作为内存动态加载,如果要执行,将该内存写入临时文件并且修改权限后执行。

先生成脚本的头文件

使用xxd命令,将二进制文件转化为C语言数组,然后C语言 include,然后动态的比如创建文件,然后执行文件。

xxd命令是用来制作一个十六进制dump的命令。比如:xxd -i 1.sh > shell_array.h

他会将文件按照十六进制生成一个C语言的头文件,并且头文件会用原来文件的名字创建数组(如果数字开头会添加__前缀,如果字母不会),并且把长度也标注出来

字母开头的文件:

可以看到 0x75是117,对应字符是u;最后一个字符是0xa, 表示\n

然后将该头文件包含

c_shell.c的文件

bash 复制代码
#include "stdio.h"
#include "unistd.h"
#include "string.h" //strlen需要

#include "my_shell.h" //脚本的数组
#define SHELL_ARRAY_NAME my_shell_sh //这里是xxd -i生成文件中的数组名字
#define SHELL_ARRAY_LEN my_shell_sh_len //这里是xxd -i生成文件中的数组长度
#define SHELL_TMP_NAME "/tmp/my_shell.sh"


int del_shell_script() {
        unlink(SHELL_TMP_NAME);
}

int gen_shell_script() {
        printf("Will locate script at :%s\n", SHELL_TMP_NAME);
        FILE *fp = fopen(SHELL_TMP_NAME, "wb");
        if (!fp) {
                printf("Failed open 1.log\n");
                return -1;
        }

        if (fwrite(SHELL_ARRAY_NAME, 1, SHELL_ARRAY_LEN, fp) != SHELL_ARRAY_LEN){
                printf("Failed to write %s\n", SHELL_TMP_NAME);
                fclose(fp);
                //unlink("1.log"); //删除文件
                return 1;
        }
        fclose(fp);

实操

脚本创建:

bash 复制代码
[root@localhost lab]# cat my_shell.sh 
echo $@
uname -r

生成C的array:xxd -i my_shell.sh > my_shell.h

创建c_shell.c:如果不变化名字,可以直接使用前面的c_shell.c如果变化名字,需要修改这几个地方:

bash 复制代码
#include "my_shell.h" //脚本的数组
#define SHELL_ARRAY_NAME my_shell_sh //这里是xxd -i生成文件中的数组名字
#define SHELL_ARRAY_LEN my_shell_sh_len //这里是xxd -i生成文件中的数组长度
#define SHELL_TMP_NAME "/tmp/my_shell.sh"

my_shell.h是根据xxd输出文件决定。

my_shell_sh和my_shell_sh_len是xxd的输入文件名字决定

SHELL_TMP_NAME是指定动态创建的地方。

编译新的bin文件和执行:gcc c_shell.c

如果要带参数执行,参数会被透传到脚本或者sub的bin代码中:

其他

这里除了shell,还可以是可执行程序。玩法有很多。可以用一个bin包含另外一个bin。

综述

本文这种方式有挺多挺好玩的模式,比如常见的一些工具,可以用它来把命令封装,比如需要输入的特殊参数,比如不想让别人看到的。甚至还可以做一些加解密的动作在里面。

相关推荐
潜创微科技--高清音视频芯片方案开发39 分钟前
2026年C转DP芯片方案深度分析:从适配场景到成本性能的优选指南
c语言·开发语言
青桔柠薯片2 小时前
从C语言到裸机运行:i.MX6ULL 的 GPIO 控制与编译链接过程分析
c语言·开发语言·imx6ull
xiaobobo33302 小时前
c语言结构体相关箭头运算符和点号运算符的联系以及c语言的“索引”思想
c语言·箭头运算符·点号运算符·索引思想
weixin_537590453 小时前
《C程序设计语言》练习答案(练习1-13)
c语言·开发语言·c#
always_TT3 小时前
从Python_Java转学C语言需要注意什么?
java·c语言·python
DA02214 小时前
Linux驱动-I2C总线驱动
linux·c语言·linux驱动
always_TT5 小时前
C语言保留字与标识符规则
c语言·开发语言
AI科技星7 小时前
光速螺旋量子几何统一场论——基于 v ≡ c 公理的四大基本力全维度求导证明与精准数值验证
c语言·开发语言·人工智能·算法·机器学习·平面
程序猿编码7 小时前
隐匿注入型ELF加壳器:原理、设计与实现深度解析(C/C++ 代码实现)
c语言·网络·c++·elf·代码注入
爱编码的小八嘎8 小时前
C语言完美演绎6-4
c语言