1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > [kernel]linux内核基础: 版本 源码 编译与调试

[kernel]linux内核基础: 版本 源码 编译与调试

时间:2022-01-27 15:49:44

相关推荐

[kernel]linux内核基础: 版本 源码 编译与调试

linux kernel 安全基础(版本、源码、编译与调试)

文章目录

linux kernel 安全基础(版本、源码、编译与调试)内核基础知识内核版本号与各发行版版本管理linux内核版本查看任意commit 所属内核版本ubuntu版本镜像下载与老镜像下载版本号查看与含义ubuntu内核和linux 官方内核区别ubuntu 更换内核以及源码下载ubuntu 常见版本对应内核版本kernel 编译编译准备查看已有操作系统的编译选项配置和编译menuconfig 依赖选项检查编译结果kernel调试qemu 调试安装qemu(自己编译)制作启动组件initrd启动脚本vmware 调试内核普通调试双机调试常用gdb插件pwndbg+pwngdbpeda一些gdb命令参考

内核基础知识

Linux最早是由芬兰 Linus Torvalds为尝试在英特尔x86架构上提供自由的类Unix操作系统而开发的。该计划开始于1991年,在计划的早期有一些 Minix黑客提供了协助,而如今全球无数程序员正在为该计划无偿提供帮助。

linux 内核官网:/

源码下载地址:/pub/linux/kernel/

内核版本号与各发行版版本管理

linux内核版本

linux 版本号由三个数字组成A.B.C,如5.15.5,分别含义:

A:目前发布的主版本,增长很缓慢,通常后面的数字比较大了的时候该数字会增长。

B:次版本号,表示稳定的版本号。

C:修订版本号,代表改版本补丁次数,在下一个稳定版本发布之前出现补丁和修复会更新该版本号。非长期维护版本一般20多个。

预发布版:很久之前内核通过版本号中的第二个数字即B的奇偶来表示稳定版和预发布版。但现在已经取消这个规则,现在预发布版用-rcX来表示如5.17-rc3,X为数字,一般不超过rc8。

长期维护版:linux 会长期维护几个版本,每次出现重要的错误修复都会对该版本打补丁,无论是否有更新的版本:

linux发行商也会维护自己的长期维护版内核。不同发行商的内核版本号含义有细微不同,下面介绍一些ubuntu 的。

参考:/category/releases.html

查看任意commit 所属内核版本

任意一个kernel commit链接,如:/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4ff2980b6bd2aa6b4ded3ce3b7c0ccfab29980af

可以直接查看tree 中Makefile:

文件开头就是版本号:

ubuntu版本

镜像下载与老镜像下载

镜像下载地址:/

老镜像下载地址:https://old-/releases

版本号查看与含义

查看ubuntu 本身的版本:

cat /etc/issue# resultUbuntu 20.04.2 LTS \n \l# orlsb_release -a# resultNo LSB modules are available.Distributor ID: UbuntuDescription: Ubuntu 20.04.2 LTSRelease: 20.04Codename: focal

ubuntu 版本代号:

查看ubuntu 内核版本:

uname -r# result5.13.0-35-generic

ubuntu内核版本号格式形如5.13.0-35-generic,其中:

5.13.0:代表linux 内核稳定版本号5.13,一般ubuntu中最后小修订号都是0,因为ubuntu会自己合入补丁。

35:由ubuntu进行的第35次修订(合入补丁)。

generic:通用版本,除此之外还可能有服务器版server或老式处理器的i386版等。

ubuntu内核和linux 官方内核区别

ubuntu 会对上游内核的特定稳定版本进行rebase,并对该版本进行补丁管理,但由于上游linux 内核版本过一阵就会进入下一个版本,而ubuntu 通常不会,ubuntu 通常会自己去合入补丁。换句话说,ubuntu 只是松散的机遇上游稳定版本维护ubuntu 版本,必须查看更新日志来确定ubuntu 更新的功能。

参考:/Kernel/FAQ#Kernel.2FFAQ.2FGeneralVersionMeaning.What_does_a_specific_Ubuntu_kernel_version_number_mean.3F

ubuntu 更换内核以及源码下载

更换内核

apt-get install linux-image-5.11.0-44-generic # 版本号根据需求更改#下载新版本内核一般直接生效,不生效如下操作:grep menuentry /boot/grub/grub.cfgvim /etc/default/grub#修改 GRUB_DEFAULT 选项为上面结果中想要启动内核的下标update-grub#如果不生效的话(一般是下载旧版本内核)则直接进入/boot 目录将之前的内核相关文件(带之前内核编号的文件)全部删掉,然后启动时候报找不到内核,然后手动选择内核启动也可以

获得ubuntu内核源码

可以直接apt source 获得:

apt source linux-image-unsigned-5.11.0-44-generic # 版本号根据需求更改

或前往ubuntu 内核git:/git/ubuntu/

git下载对应版本:

git clone git:///ubuntu/ubuntu-focal.git -b Ubuntu-hwe-5.13-5.13.0-35.40_20.04.1 --depth 1

网很卡的话,使用clash:

clash 订阅&下载:https://portal.wallless.xyz/

clash 配置TAP虚拟网卡:/tech/clash-atp.html

ubuntu 常见版本对应内核版本

老镜像下载地址:http://old-/releases/

kernel 编译

编译准备

先下载源码,上面已经说过了,不多说。

有很多依赖项,如下命令安装依赖:

apt-get build-dep linux linux-image-5.11.0-44-generic

安装之后也不一定全,make 的时候根据报错依次安装就行。

如下docker 环境 可以编译kernel 5.x 版本内核

https://registry./r/chenaotian/kernelcompile

docker run -ti --rm -h kc --name kc -v D:/share:/work chenaotian/kernelcompile:latest /bin/bashdocker exec -it kc /bin/bash

查看已有操作系统的编译选项

cat /usr/src/linux-headers-`uname -r`/.config #或cat /boot/config-`uname -r`

配置和编译

debian 体系的内核编译可以参考:/Kernel/BuildYourOwnKernel

改文章的方法是编译内核deb包,也就是跟apt-get 安装的内核同款的编译方式。我们不需要完整编译出他的东西,我们只对内核本身感兴趣。所以按照他提供的部分方法进行就可以(需要按照上面“获得ubuntu内核源码”中的git方法下载代码):

LANG=C fakeroot debian/rules clean# 下面这一步我们只需要构建binary-generic,因为内核在这里,不需要其他的LANG=C fakeroot debian/rules binary-generic

开始编译之后,我们不需要编译出完整的deb包,只需要一个内核就行,所以看到如下输出可以直接ctrl+c结束:

拷贝图中红框的命令bzImage 前的部分:

make ARCH=x86 CROSS_COMPILE= KERNELVERSION=5.13.0-35-generic CONFIG_DEBUG_SECTION_MISMATCH=y KBUILD_BUILD_VERSION="40~20.04.1" LOCALVERSION= localver-extra= CFLAGS_MODULE="-DPKG_ABI=35" PYTHON=/usr/bin/python3 O=/tmp/aa/ubuntu-focal/debian/build/build-generic -j4

接下来使用menuconfig 来编辑我们自定义的编译选项,选项设置为<*>代表编译进内核,设置为<M>代表编译成内核模块,**这里要设置成<*>。**一般要开启调试符号,除此之外根据要分析的漏洞开启必要的编译选项。/是搜索编译选项关键字。menuconfig结束之后,通过修改.config文件也可以修改编译选项。如果有互相依赖的情况,后续编译的时候会询问,问题不大,menuconfig 命令如下(上面拷贝的命令后加menuconfig 即可):

make ARCH=x86 CROSS_COMPILE= KERNELVERSION=5.13.0-35-generic CONFIG_DEBUG_SECTION_MISMATCH=y KBUILD_BUILD_VERSION="40~20.04.1" LOCALVERSION= localver-extra= CFLAGS_MODULE="-DPKG_ABI=35" PYTHON=/usr/bin/python3 O=/tmp/aa/ubuntu-focal/debian/build/build-generic -j4 menuconfig

添加调试符号:

Kernel hacking ---> Compile-time checks and compiler options [*] Compile the kernel with debug info

一些可能需要的编译选项(踩过坑的):

# 设置调试符号CONFIG_DEBUG_INFO=y# fuse 开启,一些漏洞利用会用到CONFIG_FUSE_FS=y# VIPC 开启,可以使用msg系列CONFIG_SYSVIPC=yCONFIG_SYSVIPC_SYSCTL=yCONFIG_SYSVIPC_COMPAT=yCONFIG_CHECKPOINT_RESTORE=y # 设置这个才能正确调用msg 里的copy 系列函数

最后编译出内核(上面拷贝的命令后加bzImage):

make ARCH=x86 CROSS_COMPILE= KERNELVERSION=5.13.0-35-generic CONFIG_DEBUG_SECTION_MISMATCH=y KBUILD_BUILD_VERSION="40~20.04.1" LOCALVERSION= localver-extra= CFLAGS_MODULE="-DPKG_ABI=35" PYTHON=/usr/bin/python3 O=/tmp/aa/ubuntu-focal/debian/build/build-generic -j4 bzImage

O= 后面的目录是编译结果目录,.config 和编译结果 和System.map 都在这个目录之中。

menuconfig 依赖选项

menuconfig 中如果有的选项无法配置成*,只能配置成M的话,可能是依赖没有满足,如:

depends 代表的是依赖,如果想要将某个编译选项配置成y(而不是m),那么根据这个依赖的逻辑表达式他所有依赖的选项都要配置成y。建议在menuconfig 上操作,如果直接改.config 中为y,大概率会编译失败。

这里我直接把NF_CONNTRACK 取消配置,则直接可以将OPENVSWITCH 配置成y,但问题是我需要NF_CONNTRACK ,所以就要满足整个表达式,也就是后面的所有都要配置成y。而他们自己还是可能有依赖的东西,都要配置成y 才行。

如果这种配置选项,无法通过按数字键跳转:

那么说明现在他是自动配置成m 的,看到Selected by[m],说明下面选项决定了它被配置成m:

一般要把下面的选项改成y 才行,而他们自己可能也有依赖,所以,都一起改成y。

检查编译结果

System.map 文件可以查看一些关键函数有没有

cat System.map |grep function_name

strings 查看一些字符串

strings vmlinux |grep function_name

gdb 打开查看符号,断点或list

gdb vmlinuxb function_namelist function_name

kernel调试

qemu 调试

安装qemu(自己编译)

qemu 源码 : /download/#source

wget /qemu-6.2.0.tar.xztar xvJf qemu-6.2.0.tar.xzcd qemu-6.2.0./configuremake

可能的一些依赖:

apt-get install ninja-buildapt-get install libpixman-1-dev

制作启动组件initrd

可以直接去别人github 拷一个initrd过来用,也可以自己做。做一个简易版initrd的主要工作就是静态编译一个busybox。这种initrd 里面没有lib 啥的,分析漏洞的exp 和poc 只能静态编译来测试,如果想要做一个比较全的initrd 比较麻烦。

建议随便找一个别人分析漏洞的环境把里面的initrd 拷贝过来就行。比如:

/chenaotian/CVE--0185/tree/main/qemu

解包和打包cpio:

cpio -idmv < ../rootfs.img #解包cpiofind . | cpio -o --format=newc > ../rootfs.img #打包cpio

如果一定需要动态链接的exp,偷懒方法就是,ldd 查看exp 需要的动态库,然后将ld-linux-x86-64.so.2 和其他依赖的so全部拷贝到文件系统中,qemu 启动后,用LD_LIBRARY_PATH 来运行:

将上面那些so全部拷贝到一个文件夹内然后放入rootfs中制作成initrd.img,然后启动qemu,按照如下方法运行:

cp ...so ./rootfs/exp #将so 拷贝到制作initrd.img的目录中cd ./rootfsfind . | cpio -o --format=newc > ../rootfs.img #制作initrd.imgcd .././boot.sh #启动qemu# qemu 启动后cd /expdirexport LD_LIBRARY_PATH=`pwd`./ld-linux-x86-64.so.2 ./exploit

kill 命令

ps -ef |grep qemu | grep -v grep | awk '{print $2}' | xargs kill -9

启动脚本

qemu 的启动脚本boot.sh 如下,方便每次修改exp直接启动,直接在boot.sh中生成initrd.img:

#! /bin/shcd ./rootfsfind . | cpio -o --format=newc > ../rootfs.img cd ../qemu-system-x86_64 \-m 512M \-kernel ./bzImage \-initrd ./rootfs.img \-nographic \-append "console=ttyS0 root=/dev/sda rw nokaslr quiet" \-netdev user,id=t0, -device e1000,netdev=t0,id=nic0 \-cpu kvm64,+smep,+smap \-gdb tcp::10086

vmware 调试内核

普通调试

在虚拟机配置文件(.vmx)后加:

debugStub.listen.guest64="1"

然后直接

gdbtarget remote :8864

反正我是没成功,据说在开了Hyper-V的机器上会失败,但我关了Hyper-V也没成功(具体表现为,能gdb挂上,一设置断点就崩溃,有时候还会损坏虚拟机),所以虽然看起来方便,但着实没用。

参考:/yxysuanfa/p/6844459.html

双机调试

被调试机:服务机

调试机:客户机

先在虚拟机设备里删除打印机,然后添加串行端口。使用命名串行端口,服务器和客户端都写这个:

//./pipe/com_1

设置波特率和测试串口通信:

#服务端设置波特率stty -F /dev/ttyS0 115200#测试 客户端输入,服务端接受echo "haha" > /dev/ttyS0#如果ttyS0不行就试试ttyS1啥的

然后服务器配置调试相关参数:

先修改/etc/default/grub:

GRUB_CMDLINE_LINUX_DEFAULT="quiet 3 kgdbwait kgdboc=ttyS0,115200"

然后更新grub,执行:

update-grub

然后重启,之后就可以尝试调试了。

gdb挂载命令:

set arch i386:x86-64:intel set remotebaud 115200target remote /dev/ttyS0

如果跑起来需要中断的话,在服务机执行:

echo g > /proc/sysrq-trigger

参考://03/30/2030%20%E5%8F%8C%E6%9C%BA%E8%B0%83%E8%AF%95Linux%E5%86%85%E6%A0%B8/

常用gdb插件

pwndbg+pwngdb

pwndbg:/pwndbg/pwndbg

pwngdb:/scwuaptx/Pwngdb

先安装pwndbg,直接下载之后运行./setup.sh即可,中途可能会因为git 断开,执行git init,然后继续执行就行。

然后安装pwngdb,直接下载解压,然后编辑~/.gdbinit:

source /root/pwndbg-dev/gdbinit.pysource /root/Pwngdb-master/pwngdb.pysource /root/Pwngdb-master/angelheap/gdbinit.pydefine hook-runpythonimport angelheapangelheap.init_angelheap()endend

peda

peda:/longld/peda

直接下载执行:

echo "source ~/peda/peda.py" >> ~/.gdbinit

一些gdb命令

#显示xxx 结构体的成员大小和偏移(需要符号)pt/o struct xxx #跳过断点1 117次,用来断正好溢出的fsconfigignore 1 117

参考

linux kernel官网:/

linux kernel 发行简介:/category/releases.html

ubuntu kernel FAQ:/Kernel/FAQ#Kernel.2FFAQ.2FGeneralVersionMeaning.What_does_a_specific_Ubuntu_kernel_version_number_mean.3F

内核编译:/Kernel/BuildYourOwnKernel

普通vmware 调试:/yxysuanfa/p/6844459.html

双机调试://03/30/2030%20%E5%8F%8C%E6%9C%BA%E8%B0%83%E8%AF%95Linux%E5%86%85%E6%A0%B8/

问了韬神一堆问题:/veritas501

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。