WSL2
Windows Subsystem for Linux,在windows上运行的linux子系统
前一段时间一直在用WSL kali+vscode+python3,做pwn的题目还有linux上的逆向题.确实比用vmware开一个虚拟机方便一万倍
但是对wsl的了解也就仅限于一些简单的命令比如ls
等等,对于子系统和主系统的网络关系,以及子系统的其他用法,没有了解过
现在想了解一下子系统的结构,怎么用子系统完成操作系统的课程实验(编译内核,系统调用,内核模块,设备驱动)
以及如何修改子系统的各种设置,比如防火墙,与主机的网络关系,网络发现等
随性更新...
安装/卸载wsl
安装wsl
后面的实验都是基于WSL2已经安装完成,kali子系统已经能够在终端上运行了.安装wsl可以去微软官网(这部分已经被翻译过了),要添加windows功能
具体参考WSL 的基本命令 | Microsoft Docs
在微软应用市场上可以下载各种linux系统,比如ubuntu18.04和ubuntu20.04,kali,debian等等
更方便的方法是在命令行上
查看本机已安装子系统
wsl -l
1 | PS C:\Users\86135\Desktop\pwn> wsl -l |
查看可以安装的子系统
wsl -l -o
1 | PS C:\Users\86135\Desktop\pwn> wsl -l -o |
设置默认的wsl
wsl --set-default <子系统名>
在powershell中使用wsl命令时,有一个默认使用的子系统,比如我现在默认使用kali-linux,当终端上直接输入wsl时默认唤醒kali-linux,而不是ubuntu
1 | PS C:\Users\86135\Desktop\pwn> wsl --set-default ubuntu |
卸载子系统
在微软应用商店里是木法卸载子系统的,在终端上行
wsl --unregister <子系统名>
1 | PS C:\Users\86135\Desktop\pwn> wsl --unregister ubuntu |
三炮!
出去!
唤醒/关闭wsl
选择唤醒哪一个子系统
wsl -d <子系统名>
1 | PS C:\Users\86135\Desktop\pwn> wsl -d ubuntu |
选择登录用户
wsl -u <用户名>
比如可以选择使用root登录系统,也可以使用普通用户登录系统.
只要是从powershell上唤醒子系统,不需要输入登录密码
1 | PS C:\Users\86135\Desktop\pwn> wsl -u root |
设置默认登录用户
kali的默认登录用户是普通用户,权限有限.现在想要将默认登录用户改成root,如此不需要su或者sudo再输入密码
<子系统名> config --default-user <用户名>
1 | PS C:\Users\86135\Desktop\pwn> kali config --default-user root |
查看子系统内核版本wsl --status
1 | PS C:\Users\86135\Desktop\pwn> wsl --status |
子系统关机
关闭子系统所在的终端并不会关闭wsl,它会在后台运行,因此下一次打开wsl的时候会发现开启的很快.
在powershell上使用wsl --shutdown
就可以关闭所有在后台运行的子系统
如果不想关闭所有后台子系统,只停止其中的某一个,可以wsl --terminate <子系统名>
工作目录
windows下wsl的位置
\\wsl.localhost\kali-linux
1 | PS Microsoft.PowerShell.Core\FileSystem::\\wsl.localhost\kali-linux> pwd |
这到底是个啥地方呢?前面怎么好长一坨,FileSystem后面还有俩冒号
1 | PS C:\Users\86135> cd \\wsl.localhost\kali-linux |
如果在这个目录下面,想使用cd ..退到爹目录,接着说找不到爹目录
实际上可以直接用explorer访问wsl的文件系统
wsl上windows的位置
1 | ┌──(root㉿Executor)-[/mnt/c/Users/86135/Desktop/pwn] |
即windows的根目录在wsl上为/mnt/
比如桌面就是/mnt/c/Users/86135/Desktop/
D盘就是/mnt/d/
共享环境变量
在wsl上可以调用windows的环境变量中的应用程序
不同于windows终端的是,wsl上调用win的应用需要.exe后缀
1 | ┌──(root㉿Executor)-[~] |
也可以用wsl打开主系统中已经添加到环境变量的窗口应用程序
也可以在wsl上调用主系统的cmd,切换到主系统的cmd终端
1 | ┌──(root㉿Executor)-[~] |
至于两个系统的终端怎么怎么联系.
这都是茴香豆的n种写法,不会有人闲的让终端之间踢皮球吧
并且还有设置开关这些功能,我寻思多多益善吧,不冲突关他干啥呢
wsl执行linux命令
正常情况下,linux上的可执行程序.elf或者.out,在windows上是没法执行的.同理win上的.exe也无法在linux上执行
而wsl就提供了一种在windows上执行linux可执行目标文件的方法
1 | 用法: wsl.exe [参数] [选项...] [命令行] |
比如
1 | PS C:\Users\86135\Desktop\pwn> ls -l |
在输入wsl ls -l
命令之后终端等了好长时间去了,推测是启动子系统去了.
估计这个过程就是在子系统上运行了ls -l
命令之后,将结果反馈给powershell,然后powershell打印到屏幕上
高级配置
wsl上两个配置文件wsl.conf
.wslconfig
微软给出的这两个文件的描述
wsl.conf
- 作为 unix 文件存储在
/etc
分发目录中。- 用于按分布配置设置。 在此文件中配置的设置将仅应用于包含存储此文件的目录的特定 Linux 分发版。
- 可用于版本、WSL 1 或 WSL 2 运行的分发版。
- 若要访问已安装的发行版的
/etc
目录,请使用发行版的命令行和cd /
访问根目录,然后使用ls
列出文件或使用explorer.exe .
在 Windows 文件资源管理器中查看。 目录路径应如下所示:/etc/wsl.conf
.wslconfig
- 存储在
%UserProfile%
目录中。- 用于全局配置作为 WSL 2 版本运行的所有已安装 Linux 分发版的设置。
- 仅适用于 WSL 2 运行的分发版。 作为 WSL 1 运行的分发版不会受到此配置的影响,因为它们未作为虚拟机运行。
- 要访问
%UserProfile%
目录,请在 PowerShell 中使用cd ~
访问主目录(通常是用户配置文件C:\Users\<UserName>
),或者可以打开 Windows 文件资源管理器并在地址栏中输入%UserProfile%
。 目录路径应如下所示:C:\Users\<UserName>\.wslconfig
这两个文件在默认情况下是不存在的,只有我们需要修改wsl的参数时,才需要在相应位置建立这么一个文件.
wsl
再启动时就会考虑这些文件里的规定了
wsl.conf
放在子系统里
.wslconfig
放在主系统里.
在使用wmware的时候,我们可以自由决定虚拟机占用多大内存,最多使用多少个处理器,这就是.wslconfig
的作用
在修改之前,首先在wsl上观察一下处理器数量
1 | ┌──(root㉿Executor)-[/mnt/c/Users/86135] |
wsl显示有16个,现在修改.wslconfig
给他改成8个
观察一下总内存大小
1 | ┌──(root㉿Executor)-[/mnt/c/Users/86135] |
现在修改.wslconfig
文件,调整上面两个值
C:\Users\86135\.wslconfig
1 | # Settings apply across all Linux distros running on WSL 2 |
调整后保存,子系统重启,再打印观察
1 | ┌──(root㉿Executor)-[~] |
发现刚才的修改确实奏效了
换下载源
首先备份原来的源
1 | ┌──(root㉿Executor)-[~] |
将该文件修改为阿里云的源
1 | deb https://mirrors.aliyun.com/kali kali-rolling main non-free contrib |
修改之后可以apt update
看看成功没
1 | ┌──(root㉿Executor)-[~] |
设置代理
找个好地方vim bash_profile
1 | export http_proxy=http://172.25.144.1:7891/ |
这里172.25.144.1是我windows本机的wsl网卡地址,这玩意儿可以在/etc/resolv.conf
查看
1 | ┌──(root㉿Executor)-[/home] |
端口号为啥是7891呢,因为我本机clash在7891上开的代理端口
注意clash开允许局域网,系统代理
写完了bash_profile之后保存退出,然后source bash_profile
这样对于本终端就已经更换了代理,重新开机或者打开其他终端都没有此设置
wsl迁移
kali-linux迁移前的C卷大小
由于我想为kali安装一个xfce桌面,KDE桌面很大,又要剥削压迫C卷,于是就像把wsl搬到D卷
先用安装了python3的ubuntu20.04LTS做了一个实验,结果迁移后的ubuntu还是有python3的,这意味着以前的修改都会保留
kali-linux迁移过程:
1.wsl关机
1 | wsl --shutdown |
2.选好目的地
我将D:,加一个wsl父目录是因为,同父目录下还有D:,将powershell的当前工作目录调整到D:
1 | PS D:\wsl\kali> pwd |
3.选择需要导出的子系统
使用wsl -l
指令列出所有已经注册的子系统名
1 | PS D:\wsl\kali> wsl -l |
4.导出kali-linux.tar
1 | wsl --export <子系统名> <tar包路径> |
1 | PS D:\wsl\kali> wsl --export kali-linux ./kali.tar |
本条命令的意义是,将名为kali-linux的子系统,导出到当前工作目录下的kali.tar中
5.卸载本来安装在C卷的kali-linux
1 | wsl --unregister <子系统名> |
1 | PS D:\wsl\kali> wsl --unregister kali-linux |
6.导入迁移到D卷的kali-linux
1 | wsl --import <子系统名> <子系统安装路径> <tar包路径> |
1 | PS D:\wsl\kali> wsl --import kali-linux . ./kali.tar |
本条命令的意义是,从当前目录的kali.tar包导入子系统到当前目录,子系统名叫kali-linux
7.验证导出成功
终端启动kali成功
虽然迁移kali只给C省出了3G的磁盘空间...
但是可以放心安装桌面了
安装桌面
在此之前需要保证wsl升级到wsl2,换下载源到阿里云(如果梯子流量管够忽略)
安装Win-KeX
Win-KeX是windows为kali专门提供的桌面体验,具有以下功能
- 窗口模式:在专用窗口中启动Kali Linux桌面
- 无缝模式:在Windows和Kali应用程序和菜单之间共享Windows桌面
- 声音支持
- 无特权和根会话支持
- 共享剪贴板,可在Kali Linux和Windows应用之间进行剪切和粘贴支持
- 多会话支持:根窗口和非私有窗口以及无缝会话同时进行
安装之前先apt update
更新一下
之后安装Win-KeX
1 | apt install -y kali-win-kex |
安装可能很慢...但是速度是百度云盘两倍(比烂是吧)
安装完成后在kali上使用kex命令,输入一些密码之后,就可以使用xfce桌面了
在kex中使用F8键可以选择桌面以windows窗口运行还是全屏运行,
全屏时就和真的kali系统没有区别了,所有键鼠命令都会被kali捕获,不会发往windows
F8的fullscreen可以设置窗口或者全屏模式
完整everything
一开始安装的子系统只是最小安装,只安装了一个系统,各种武器都没有安装
kali子系统完整安装
1 | apt install kali-linux-everything |
大约有20个G,还是在学校wifi环境下安装吧,使用流量划不来
ida+wsl远程调试
终于会动态调试了
但是windows上的IDA似乎只能用local windows debugger,其他的各种各样的设置看了就烦
今天终于不厌其烦试了试IDA+remote linux debugger在ida上调试elf文件
终于调通了
需要ida,wsl
remote linux debugger
win11+wsl kali+ida
IDA-<version>/dbgsrv/
这个目录下面有调试需要使用的文件
如果要使用linux远程调试elf文件,需要linux_server和linux_server64两个文件,把他俩复制到kali的文件系统中去
1 | ┌──(root㉿Executor)-[/home/kali] |
cd 到该目录下,修改其权限
可以使用--help看linux_server的用法
1 | chmod 777 linux_server |
1 | ┌──(root㉿Executor)-[/home/kali] |
执行linux_server
1 | ┌──(root㉿Executor)-[/home/kali] |
此时kali已经在监听其23946端口了
现在用ida打开一个32位elf程序,F9或者点击Debugger下拉菜单,选择调试器Remote Linux debugger
然后调试运行(ida默认也是访问远程主机的23946端口,如果不是则这里肯定联不通,ida会让重新设置端口的)
必然会报错找不到输入文件,
一看报错信息,原来输入文件是从远程linux上找的,当然找不到
OK之后ida提供了替代方案
点这个Use
found就可以使用本机的C:\Users\86135\Desktop\malloc\main
作为输入文件了
但是调试界面刚出来又没了,原来是忘记下断点了
在main函数(或者其他地方)下断点,然后重新调试运行,可以调试了
甚至可以使用F5反汇编,显然是linux上的光棍儿gdb做不到的
remote gbd debugger
既然linux上也有gdb,那么是不是也可以用远程gdb调试呢?确实能调通,安一个gdbserver剩下的随便拾到拾到就行了
1 | apt install gdbserver |
/usr/src/WSL2-Linux-Kernel-linux-msft-wsl-5.15.137.3/arch/x86/boot/bzImage
编译内核
如果用普通的linux内核直接编译,然后给wsl换这个普通内核,这样wsl起不来
编译wsl内核需要有专门的config文件
内核源码可以用原版的,比如到这里下载Index of /pub/linux/kernel/v5.x/
以5.8.13为例,
1 | wget https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.8.13.tar.gz |
然后在内核源码的根目录下
1 | mkdir Microsoft |
这玩意儿可以抄WSL2-Linux-Kernel/Microsoft/config-wsl at wsl-xyb-port-5.8.y-latest · xieyubo/WSL2-Linux-Kernel · GitHub,注意版本,5.8的内核就得抄5.8的config_wsl,直接复制粘贴
可以修改其中的CONFIG_LOCALVERSION
,改成自定义内核名称后缀
完事之后退到内核源码根目录下
1 | make KCONIFG_CONFIG=./Microsoft/config-wsl -j`nproc` |
编译完了之后会生成./arch/x86/boot/bzImage,这就是可以引导的内核
可以安装头文件
1 | make modules_install |
更换内核
默认配置
如果没有在~/.wslconfig中修改内核位置,那么可以这样整:
编译内核完成后,将生成的bzImage可引导镜像放到本机的C:\Windows\System32\lxss\tools
这个位置
wsl --shutdown
在C:\Windows\System32\lxss\tools
中,将之前的内核镜像kernel改个名,比如oldkernel
然后将刚搬过来的bzImage改成kernel
重启wsl
uname -a
查看当前内核版本
1 | ┌──(root㉿Executor)-[/home/dustball/kernelROP/mydev] |
指定kernel位置
比如在windows的~/.wslconfig
中这样写
1 | # Settings apply across all Linux distros running on WSL 2 |
这就指定了wsl内核使用c:\\opt\\kernel
编译内核模块
需要更滑内核
编译内核模块需要内核头文件,
如果已经编译过wsl内核,并且make modules_install && make install
,那么就可以直接编译内核模块了
如果没有编译过内核,需要先编译内核
假设内核模块hello.c这样写
1 | // hello.c |
它的Makefile这样写
1 | # Makefile |
KDIR这个自己写,通常是/lib/modules/$(shell uname -r)
1 | make |
之后在当前目录下生成hello.ko
加载到内核
1 | insmod hello.ko |