【工具】如何将一个脚本作为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。

综述

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

相关推荐
2601_954526756 小时前
【工业传感与算法实战】温漂补偿与零点抗漂破局:基于二阶多项式拟合的 C/C++ 边缘校准算法,深度拆解“压力变送器什么牌子好”的技术硬指标
c语言·c++·算法
qq_448011166 小时前
C语言中的变量和函数的定义与声明
android·c语言·开发语言
aaaameliaaa10 小时前
指针之总结
c语言·笔记·算法
agathakuan10 小时前
Wireshark 解密並導出TLS 1.2 / TLS 1.3 明文的方法(可控制 Client 端)
c语言·wireshark·ssl·openwrt
caimouse10 小时前
protoc-gen-c 支持 proto3 `optional` 关键字修改记录
c语言·学习
noipp10 小时前
推荐题目:洛谷 P6231 [JSOI2013] 公交系统
c语言·数据结构·c++·算法·游戏·洛谷·luogu
c2385611 小时前
C/C++每日一练6
c语言·c++·算法
wdfk_prog11 小时前
嵌入式面试真题第 13 题:单硬件 Timer 下的高精度多路软件定时器架构设计
c语言·开发语言·面试·职场和发展·嵌入式
时间的拾荒人12 小时前
MySQL C语言连接 - 从入门到实战
android·c语言·mysql
code_pgf14 小时前
C/C++ 中 `typedef` 关键字详解
c语言·c++