ZzPwn01:属于2023年的Pwn环境搭建(Docker in WSL)

一、前言

最近学Pwn有点遇到瓶颈了,干脆停下来整理下前面的知识。刚入门的时候最头疼的就是配置Pwn的环境,也是做了很多试错,最后敲定了wsl+docker的方案,下面给大家分享下。

二、Docker in WSL

简而言之,Windows Subsystem for Linux(WSL)是集成于Windows系统的Linux虚拟机,相比例如VMWare的其他虚拟机软件,突出的特点是启动特别快;以及你可以直接用Windows文件资源管理器(explorer.exe)访问Linux文件系统,非常令人满足。

文件资源管理器!再见,XFTP

在2023年,WSL的安装非常简单。我在这里直接引用微软文档里的原话:可以使用单个命令安装 WSL 所需的一切。 在管理员模式下打开 PowerShell 或 CMD,输入 wsl --install 命令,然后重启计算机。

wsl --install

如果你的网络通畅的话,喝杯茶上个厕所,回来就差不多该提示你重启了。重启之后再次运行wsl(可能也不用手动运行,我记得好像重启之后WSL终端会自己弹出来),然后按照提示配置用户名密码,你的Linux环境就搞定了。

哦,可爱的Ubuntu提示符

Docker是另一种虚拟化技术。简单地可以理解为它用于在Linux系统(是的,Linux系统,这也是为什么我们要装WSL)中启动更加轻量的虚拟机。关于Docker的入门知识,我强烈推荐这篇Docker从入门到实践,花上一两个小时把这篇文章过一遍,非常有帮助。

但在此之前,我们需要先安装Docker。如果你看了之前那篇微软的文档,你可能已经找到了这篇WSL 2 上的 Docker 远程容器入门。跟着文档做就好,我也说不出什么别的需要注意的了。文档里提到了安装 Visual Studio Code安装 Windows 终端两个选做,对于我们的需求来说都是必做,别偷懒。

在正式尝试Docker之前,另一项重要工作是给Docker换源(一点也不出人意料呢)。参照这篇博客docker 设置国内镜像源,选一个国内镜像源地址,推荐用阿里云的那个。但那篇里的“修改方法”里说的改/etc/docker/daemon.json对我们是没用的,高贵的docker-desktop用图形界面。如下图所示进到docker gui的设置界面,选择docker engine选项卡,填上registry-mirrors配置项。

设置镜像源

同样在设置里,确认你打开了docker的wsl集成。
打开之后会自动在你的WSL分发版里安装docker客户端

一切顺利的话,你已经可以在WSL中使用Docker了。
docker成功被集成到WSL分发版中

再次提示,如果你对Docker还不太了解,花些实践阅读Docker从入门到实践。你现在可以在你的系统中实践上面的操作了。
在WSL系统中,使用code .命令用vscode打开当前文件夹,使用explorer.exe .用Windows文件资源管理器打开当前文件夹。

三、DockerFile

写累了,明儿再写,这里先给一个DockerFile的参考:或者直接用skysider师傅的pwndocker

FROM ubuntu
WORKDIR /root
COPY ./sources.list /etc/apt/sources.list
COPY ./pwn ./pwn

# 处理32位程序支持
RUN dpkg --add-architecture i386 \
    && apt-get update \
    && apt-get install -y libc6:i386 libncurses5:i386 libstdc++6:i386 zlib1g:i386

# 安装实用程序
RUN apt-get install -y openssh-server gdb tmux vim netcat

# 安装python相关组件
RUN apt-get install -y python3 python3-pip python3-dev git libssl-dev libffi-dev build-essential \
    && python3 -m pip install --upgrade pip \
    && python3 -m pip install --upgrade pwntools \
    && python3 -m pip install --upgrade LibcSearcher

# 安装pwndbg
COPY ./pwndbg-dev ./pwndbg-dev
WORKDIR /root/pwndbg-dev
RUN chmod +x ./setup.sh \
    && ./setup.sh \
    && echo "export LANG=C.UTF-8" >> /root/.bashrc
WORKDIR /root

# Configure SSH server
RUN mkdir /var/run/sshd \
    && echo 'root:pwn' | chpasswd \
    && sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd \
    && echo "export VISIBLE=now" >> /etc/profile
COPY ./sshd_config /etc/ssh/sshd_config
ENV NOTVISIBLE "in users profile"


# 暴露SSH端口
EXPOSE 22
# 暴露ida Linux调试器端口;不过好像用不太上
EXPOSE 23946

# start sshd
CMD ["/usr/sbin/sshd","-D"]
# docker run -d --name zzpwn -p 32222:22 -p 23946:23946 zzkluck/pwnenv

使用时用vscode的ssh插件连进去就好了。

四、基础模板

首先是一个小脚本setup.sh用于第一次把二进制文件拷贝到环境中之后的初始化,减少了一些重复性的劳作:

#!/bin/bash
echo $1
pwn=$1
export pwn
chmod +x $pwn
checksec $pwn
$pwn

使用source调用:

source setup.sh ~/your_path/your_pwn_binary

第二个要分享的是pwntools的python模板pwn_init.py,用于另一些重复劳作:

from pwn import *                                       # 引入pwntools
from pwnlib.util.packing import p64, u64, p32, u32      # 帮助编辑器找到符号,消除warning
from os import getenv                                   # 通过读取环境变量自动获取目标文件

# 由pwntools提供的简单易用命令行参数解析器
# https://docs.pwntools.com/en/stable/args.html
online = args.R
debug = args.D
libc_local = args.L

# 决定使用哪一种LibcSearcher
if libc_local:
    import sys 
    sys.path.append('/root/LibcSearcher-master')
    from LibcSearcher_local import LibcSearcher
else:
    from LibcSearcher import LibcSearcher

# 设置pwntools日志级别,根据需要在info和debug之间切换
context.log_level = 'info'
# 指定tmux,使得gdb调试时可以分屏
context.terminal = ['tmux','splitw','-h']

# 从环境变量$pwn中获取目标文件位置
target_file = getenv('pwn')
# “The recommended method is to use context.binary to automagically set all of the appropriate values.”
#                                                  --- https://docs.pwntools.com/en/stable/context.html
# pwntools能够从二进制文件中自动解析context信息,主要是程序的32/64bits信息
context.binary = target_file
elf = context.binary

# 根据推断的程序位数决定libc
if elf.bits == 32:
    libc_file = '/lib/i386-linux-gnu/libc.so.6'

else:
    libc_file = '/lib/x86_64-linux-gnu/libc.so.6'
libc_ld = None

# 当然,也可以指定特定的libc,需要同时指定ld
# libc_file = 'libc/libc-2.23-u16-64.so'
# libc_file = "glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc-2.23.so"
# libc_ld = 'glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/ld-2.23.so'

libc = ELF(libc_file)

# 根据命令行参数选择启动方式,远程、调试或者直接运行
run_target = [target_file] if libc_ld is None else [libc_ld, target_file]
if online:
    p = remote('node4.buuoj.cn', int(args.R))
elif debug:
    p = gdb.debug(run_target, '''
        b *_start
        ''', env={'LD_PRELOAD': libc_file})
else:
    p = process(run_target, env={"LD_PRELOAD": libc_file})
p.info("Init Success!")

初始化模板完成以下几个任务:

  1. 根据命令行标志L决定选择哪个版本的LibcSearcher;
  2. 配置pwntools日志级别;
  3. 配置tmux分屏;
  4. 从环境变量$pwn读取由setup.sh指定的二进制文件位置;
  5. 推断或指定所需的libc,并配置程序运行时使用指定的libc;
  6. 如果指定了命令行标志R,则远程连接到靶场运行;
  7. 如果指定了命令行标志D,则挂载GDB调试运行。

对于攻击脚本exp.py,按以下方法使用:

from pwn import *
from pwnlib.util.packing import p64, u64, p32, u32
from pwn_init import p, elf, libc, LibcSearcher

# ---------------------------------------
# ------  Assistant Function Here  ------
# ---------------------------------------
def foo():
    pass

# ------------------------------
# ------  Your Code Here  ------
# ------------------------------
foo()
p.interactive()
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容