当我们有一个shell时,会执行一些常用的命令,如ls ,whoami, ifconfig......但是部分的机器有监控execve之类的玩意,可能会记录我们运行的这些命令。
比如下面的执行方法:
#include <stdlib.h>
int main(int argc, char const *argv[])
{
system("whoami");
system("pwd");
return 0;
}
可以看到strace可以跟踪到我们进行了两次的execve调用,执行了什么命令。
既然这些常用的命令也是一个个程序,那我们将这些功能做成一个程序,需要时调用,这样既可以有功能,还不用execve去运行一个程序。为了满足这个需求,我找来了busybox
BusyBox 是一个集成了三百多个最常用Linux命令和工具的软件。BusyBox 包含了一些简单的工具,例如ls、cat和echo等等,还包含了一些更大、更复杂的工具,例grep、find、mount以及telnet。有些人将 BusyBox 称为 Linux 工具里的瑞士军刀。简单的说BusyBox就好像是个大工具箱,它集成压缩了 Linux 的许多工具和命令,也包含了 Linux 系统的自带的shell。
大多数发行版都带上了busybox,那我们用busybox执行命令看看。
这样执行还是能看到给的参数,而且每次执行命令我们都要运行busybox一次,不能达到隐藏的效果。
那么有没办法能够不需要每次都运行busybox,还能执行诸如ls,cat等命令呢?
经过查询得知,我们可以将busybox编译为一个共享动态链接库的形式,然后在自己的程序中去调用,可以传入需要执行的命令和参数,这样可以随时在自己的程序中使用busybox的工具了。
首先,从busybox官网下载源码(https://busybox.net/)
解压后,使用make menuconfig配置编译动态库,勾选 Build shared libbusybox
编译完成后会生成一个libbusybox的so
这样我们就可以使用dlopen和dlsym去调用busybox内的小工具了。
如下例子是使用busybox中的ls命令,参数为-al
void *dp = dp = dlopen("./libbusybox.so", RTLD_LAZY);
void *fc = dlsym(dp, "lbb_main");
typedef void (*bb)(char **argv);
bb func = (bb)fc;
char* _argv[] = {"ls","-al",0};
func(_argv);
我们还可以使用fork()的办法,做一个busybox shell。运行后续可以重复输入命令使用。
可以看到,除了第一次运行之外,后续使用各种小工具都无execve。也可以和其他技巧配合,比如参数加密输入再解密执行。
#include <iostream>
#include <string>
#include <vector>
#include <dlfcn.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
using namespace std;
vector<string> split2(const string &str, const string &pattern)
{
char *strc = new char[strlen(str.c_str()) + 1];
strcpy(strc, str.c_str());
vector<string> res;
char *temp = strtok(strc, pattern.c_str());
while (temp != NULL)
{
res.push_back(string(temp));
temp = strtok(NULL, pattern.c_str());
}
delete[] strc;
return res;
}
int main()
{
void *dp = dp = dlopen("./libbusybox.so", RTLD_LAZY);
void *fc = dlsym(dp, "lbb_main");
typedef void (*bb)(char **argv);
bb func = (bb)fc;
cout << "use ctrl+c or quit to exit." << endl;
int pid;
while (1)
{
string command;
cout << "busybox >";
getline(cin, command);
vector<string> cmd_vec = split2(command, " ");
if(!command.compare("quit"))
exit(0);
int arg_count = cmd_vec.size();
int pid = fork();
if (pid < 0)
{
/* error occurred */
cout << "forked failed" << endl;
exit(-1);
}
else if (pid == 0)
{
/* child process */
const char **argv_bb = (const char **)malloc(sizeof(char *) * arg_count + 1);
memset(argv_bb, 0, sizeof(char *) * arg_count + 1);
for (int i = 0; i < arg_count; ++i)
{
argv_bb[i] = cmd_vec[i].c_str();
}
func((char **)argv_bb);
free(argv_bb);
}
else
{
/* parent process */
/* parent will wait for the child to complete*/
wait(NULL);
cout << "busybox command Complete!" << endl;
}
}
return 0;
}
BY:先知论坛
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论