Tsh源码阅读和分析
tsh是一款轻量级远程shell工具,可在多个平台上编译运行,被集成在较为完善的Linux rootkit Reptile 中
其实现了文件传输和真正的交互shell,交互全程用aes和sha1加密
代码量比socat小,但很精巧,适合初级红队开发者进行学习
本篇的关键在 tty和pty的设置与使用,其余涉及一点点信号、网络、多进程操作、IO模型会简略提一下
0x00 目录结构
1 |
|
0x01 主逻辑分析
为了保证加密传输,作者将加密逻辑抽象出来形成 pel.[ch](packet encrypt layer)
,对外提供4个接口,方便主逻辑调用
1 |
|
0x11 tsh client流程
通过指定参数,支持三种基本功能
交互shell
获取文件
传输文件
- 输入选项可以指定:IP or 反连、端口、密码、获取文件、发送文件,仅输入IP则默认动作(action)为连接远程shell
- 判断主被动连接
- 主动连接,创建socket并bind绑定地址之后,主动使用connect连接远程server。
- 被动连接,创建socket后bind地址,开启listen监听,使用accept等待连接到来
- 连接到来后,先发送密码,若没有设置密码,则使用硬编码于代码中的默认密码,如果错误则需要用户手输,再次错误则认证失败。如果用
-s
设置了密码,错误则直接认证失败 - 发送我们开头设置的动作(action),失败则调用shutdown关闭两端的socket
- 根据我们的action调用不同功能函数,runshell模式中如果设置了命令,则仅执行该命令后便返回
0x12 tshd server流程
tshd_server主流程
- process_init子流程
- 基本参数
- server主流程使用fork,作用是保证进程后台运行,这样我们运行tshd的时候就不用手动加
&
符号令进程后台运行 - while死循环处理到来连接。被动情况下等待client来连接我们,主动情况下如果连接不成功,则会等待5s,再次发起连接。连接成功时连接会交给process_client函数处理
- 在process_client流程中,会使用创建孙进程并退出父、子进程的方法,令孙进程由init进程接管,达到避免出现僵尸进程的效果
1 |
|
- 上面代码中
alarm(3)
的作用是给当前进程设置一个3秒的时钟,如果pel_server_init
处理太慢,则操作系统会发送一个SIGALRM信号中断此进程,达到合理关闭该进程的效果。alarm(0)
的作用是 如果流程正常进行,则取消闹钟
0x02 关键函数分析
0x21 tsh_runshell 客户端
1 |
|
0x22 tshd_runshell 服务端
1 |
|
0x03 技术分析
0x31 pty 与 tty 数据传导
二者为主从关系,pty (master),tty (slave)
伪终端的出现是因为一些面向终端应用的输入(或输出)不再直接来自(或去往)实际终端
伪终端是一对虚拟的字符设备,linux内核使用一种符合tty线规程(line discipline)的双向管道连接伪终端的主从设备
主设备上的任何写入操作都会反映到从设备上,反之亦然,从设备上的应用进程可以像使用传统终端一样读取来自主设备上应用程序的输入,以及向主设备应用输出信息
伪终端从设备应用通常是主设备应用的子进程,主应用打开一对伪终端并fork一个子进程,然后子进程打开并使用从设备,伪终端应用的实现模型可用下图表示
0x32 select IO多路复用模型
- select多路复用模型是Linux中三种多路复用模型之一
- 主要采取轮询文件标识符集合的模式,来达到高效率io目的
- 主要适用于少量且活性高的标识符
- select可以设置读、写、异常集合
- 这里使用的目的:使用单线程来完成多个并发连接请求
- 其实也能够用多线程来处理,即每次来一个连接请求,我们就开启一个线程去处理后续逻辑
- tsh的做法:一开始清空集合,然后将需要的文件标识符放入读集合中,再调用select同时设置最大文件标识符,这样select会在0~Max之间遍历所有标识符
- 当读集合中某个fd存在事件,那么select系统调用将会返回
- 然后使用FD_ISSET,判断事件集合中本次存在事件的标识符具体是哪一个,处理其后续逻辑
0x04 总结
Everything is file
宏的使用,做到跨平台,Linux系统编程基本方法
主动创建孤儿进程,避免出现僵尸进程
tty和pty的使用做到了真正的交互shell
- 这里说一下python shell,其连接后使用
pty.spawn("/bin/bash")
交互shell其实依然为某种程度哑shell,无法完成某些高交互进程(如:vim)的使用,需要进一步升级
- 这里说一下python shell,其连接后使用
设置窗口大小,控制返回值窗口
存在bug,输入
./tshd asdf
后台会一直创建进程,最终跑死机器
0x05 参考资料
[2] What’s the difference between various $TERM variables?
[3] 理解 Linux 中的 tty、pty、pts、console、terminal
[4] Why do I need to run “/bin/bash –login”
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!