ctfshow_pwn前置杂记
一些Linux指令
SSH
SSH(Secure Shell)是一种网络协议,用于安全地远程登录到计算机系统。SSH 主要用于以下场景:
远程命令行登录
文件传输(通过 SFTP 或 SCP)
端口转发
使用格式:
ssh ctfshow@题目地址 -p题目端口号
ls
ls
命令用于列出目录内容
eg:
ls
:列出当前目录的内容。ls -l
:以长格式列出当前目录的内容,显示文件的详细信息。ls -a
:列出当前目录的所有文件,包括隐藏文件(以点开头的文件)。ls /path/to/directory/
:列出指定目录的内容。注:ls后加 / 是为了明确指定路径避免歧义
nc
nc
(Netcat)是一个功能强大的网络工具,用于读取和写入网络连接
看起来你正在使用 gdb
(GNU 调试器)来调试一个程序。gdb
是一个强大的工具,可以帮助你分析和调试程序的行为。如果你有具体的调试需求或遇到问题,请告诉我更多细节,我可以提供进一步的帮助。
echo
echo 是一个常用的命令行工具,用于将指定的文本输出到标准输出设备(通常是终端,也可以是指定文件)。这个命令非常简单但功能强大,常用于脚本编写和日常操作中的调试信息显示。
echo [选项] [字符串]
利用echo将CTFshow写入key文件:
1 | echo "CTFshow">key //>为重定向,可以理解为重定向了标准输出设备 |
常见选项:
-n : 不输出末尾的换行符
-e : 启用对反斜杠转义字符的支持
exec
使用 exec
可以让新的命令完全替代当前的 shell 进程,而不仅仅是作为一个子进程运行。
exec [选项] 命令 [参数…]
当获得一个shell后可使用exec执行特定命令:
程序给了我们一个shell但是不是交互式的我们可以使用了exec函数来执行sh命令,并使用1>&0来进行输出重定向,即exec sh 1>&0
这个命令将标准输出重定向到标准输入,实际上就是将命令的输出发送到后续命令的输入。具体来说,1>&0中的1表示标准输出,0表示标准输入。通过将标准输出重定向到标准输入,可以实现将命令的输出作为后续命令的输入。这样可以在执行sh命令后,进入一个交互式的Shl环境,可以在该环境中执行命令并与用户进行交互。
也可以直接exec cat/ctf* 1>&0将cat/ctf*命令的输出发送到标准输入,实际上就是将命令的输
出再次输出到屏幕上。
编译与链接
在编译和链接命令中,-o
是一个常用的选项,用于指定输出文件的名称。
nasm
nasm是一种汇编语言编译器,用于将低级的汇编代码转换成机器码。它支持多种输出格式,包括但不限于ELF、COFF和二进制文件等。
利用nasm将.asm(文本文件)编译成ELF格式的.o(对象文件):
1 | nasm -f elf flag.asm -o flag.o |
-f elf
: 指定输出文件的格式为ELF(Executable and Linkable Format),这是Linux系统常用的二进制文件格式。flag.asm
: 输入的汇编源代码文件。-o flag.o
: 指定输出的文件名为flag.o
,这是一个对象文件。
ld
ld为链接器,用于将对象文件链接成一个可执行文件
1 | ld -m elf_i386 -o flag flag.o |
-m elf_i386
: 指定目标架构为i386(即32位x86架构)。这确保生成的可执行文件适用于32位系统。-o flag
: 指定输出的可执行文件名为flag
。flag.o
: 输入的对象文件。
常见的 gdb 命令:
启动程序
gdb
1 | run |
查看当前进程的虚拟内存映射
这将显示程序的各个内存段及其地址范围、权限等信息。
gdb
1 | vmmap |
寄存器及寻址方式
汇编指令与寄存器
- mov:将值从一个寄存器移动到另一个寄存器或内存地址。
- push:将寄存器的值压入栈中,ESP/ESP减少。
- pop:从栈中弹出值到寄存器,ESP/ESP增加。
- call:调用函数,将返回地址压入栈中。
- ret:从函数返回,从栈中弹出返回地址到EIP/RIP。
立即寻址方式
mov eax, 11 ; 将11赋值给eax
add eax, 114504 ; eax加上114504
sub eax, 1 ; eax减去1
最后eax的值为11+114504-1=114514
寄存器寻址方式
mov ebx, 0x36d ; 将0x36d赋值给ebx
mov edx, ebx ; 将ebx的值赋值给edx
直接寻址方式(存地址)
mov ecx, msg ; 将msg的地址赋值给ecx
eg:mov ecx, dword_80490E8
dword_80490E8
是一个 32 位的双字(double word),其值是一个内存地址。这条指令的作用是将内存地址 0x80490E8 直接赋值给寄存器 ecx。这意味着 ecx 现在存储的是这个地址本身,而不是该地址所指向的数据。
寄存器间接寻址方式(存对应地址上所对应的值)
mov esi, msg ; 将msg的地址赋值给esi
mov eax, [esi] ; 将esi所指向的地址的值赋值给eax
方括号 [ ]
表示间接寻址,即访问的是括号内表达式所指向的内存地址中的内容,而不是表达式本身。
.data:080490E8 57 65 6C 63 dword_80490E8 dd 636C6557h *这段代码表示的是在地址 080490E8
处的数据段中定义了一个双字(dword)变量 dword_80490E8
,其值为 636C6557h
*其中h为汇编中表示16进制数的后缀
寄存器相对寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
add ecx, 4 ; 将ecx 寄存器中的值增加4(地址加4)
mov eax, [ecx] ; 将ecx所指向的地址的值赋值给eax
基址变址寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
mov edx, 2 ; 将2赋值给edx
mov eax, [ecx + edx*2] ; 将ecx+edx*2所指向的地址的值赋值给eax
相对基址变址寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
mov edx, 1 ; 将1赋值给edx
add ecx, 8 ; 将ecx加上8
mov eax, [ecx + edx*2 - 6] ; 将ecx+edx*2-6所指向的地址的值赋值给eax
gcc编译文件
1 | gcc -o hello hello.c |
关闭所有保护:
**
-fno-stack-protector
**:- 禁用堆栈保护器(Stack Protector),防止在函数调用中插入额外的检查代码。
**
-z execstack
**:
- 允许堆栈执行,禁用 NX 位(No-eXecute)保护。
**
-Wl,-z,norelro
**:- 禁用只读重定位表(RELRO),使数据段不被标记为只读。
**
-D_FORTIFY_SOURCE=0
**:
- 禁用源代码级别的安全强化功能。
- **
-no-pie
**:
- 禁用位置独立代码(PIE),生成非位置独立的可执行文件,不利于 ASLR 的有效性。
开启所有保护:
- **
-fstack-protector-all
**:启用全面的堆栈保护器。 - **
-z relro
**:启用部分 RELRO。 - **
-z now
**:启用完全 RELRO。 - **
-D_FORTIFY_SOURCE=2
**:启用源代码级别的强化。 - **
-pie
**:生成位置独立的可执行文件(PIE),有助于 ASLR。 - **
-Wl,-z,noexecstack
**:确保堆栈不可执行(默认情况下通常是这样的)。
命令注入获取shell
下面这段为连上靶机后执行的命令
1 | How much do you know about Linux commands? |
使用;分隔ls并根据下方源码中的获取输入的漏洞送/bin/sh进去,如果不用;分隔则只会尝试列出/bin/sh目录。
1 | case 2: |
当输入2时会执行上面的代码,其中read获取输入,0xAuLL对应十进制值为10故最多可输入10个字节,strcat将buf的值赋值给dest,dest又在system中故可输入/bin/sh获取shell。
;为分隔command1;command;command三条指令会按照顺序执行,并且前面的指令执行是否成功不会影响后边指令的执行。
command1&command 两条指令会在后台同时执行。
文件输出流
文件输出流(File Output Stream)是一种用于将数据写入到文件中的输入/输出流,
基本功能:文件输出流主要用于创建新文件或将数据追加到现有文件。
工作原理:当你创建一个文件输出流对象并指定目标文件后,你可以通过该对象的方法来写入数据。这些方法包括
write
方法,可以接受单个字节或字节数组作为参数。
关闭输出流是一个非常重要的步骤,它确保了所有缓冲的数据都被正确地写入到目标文件,并且释放了系统资源。具体来说,关闭输出流会有以下几个效果:
- 刷新缓冲区:如果输出流有内部缓冲区(大多数情况下都有),关闭流会强制将缓冲区中的所有未写入数据写入到目标文件中。这确保了没有任何数据丢失。
- 释放资源:操作系统对打开的文件描述符数量有限制。如果不及时关闭输出流,可能会导致资源泄露,最终耗尽可用的文件描述符,从而影响程序的正常运行。
- 防止数据损坏:在某些情况下,不关闭输出流可能导致数据部分写入或完全未写入,从而造成数据损坏或不完整。
- 提高性能:及时关闭不再需要的输出流可以减少不必要的内存占用和系统开销,有助于提高程序的整体性能。
- 异常处理:即使在发生异常的情况下,也应该尽量关闭输出流。使用 try-with-resources 语句可以自动管理资源的关闭,简化代码并减少错误发生的可能性。
设置ALSR保护参数
ASLR(Address Space Layout Randomization)是一种操作系统级别的安全保护机制,旨在增加软件系统的安全性。它通过随机化程序在内存中的布局,使得攻击者难以准确地确定关键代码和数据的位置,从而增加了利用软件漏洞进行攻击的难度。
开启不同等级会有不同的效果:
1.内存布局随机化:ASLR的主要目标是随机化程序的内存布局。在传统的内存布局中,不同的库和模块通常会在固定的内存位置上加载,攻击者可以利用这种可预测性来定位和利用漏洞。ASLR通过随机化这些模块的加载地址,使得攻击者无法准确地确定内存中的关键数据结构和
代码的位置。
2.地址空间范围的随机化:ASLR还会随机化进程的地址空间范围。在传统的地址空间中,栈、堆、代码段和数据段通常会被分配到固定的地址范围中。ASLR会随机选择地址空间的起始位置和大小,从而使得这些重要的内存区域在每次运行时都有不同的位置。
3.随机偏移量:ASLR会引入随机偏移量,将程序和模块在内存中的相对位置随机化。这意味着每个模块的实际地址是相对于一个随机基址偏移的,而不是绝对地址。攻击者需要在运行时发现这些偏移量,才能准确地定位和利用漏洞。
4.堆和栈随机化:ASLR也会对堆和栈进行随机化。堆随机化会在每次分配内存时选择不同的起始地址,使得攻击者无法准确地预测堆上对象的位置。栈随机化会随机选择栈帧的起始位置,使得攻击者无法轻易地覆盖返回地址或控制程序流程。
在linux中,ALSR的全局配置/proc/sys/kernel/randomize_va_space(这是一个用于控制地址随机化的文件)有三种情况
修改一个文件的ASLR:
首先将终端目录定位到文件,或者直接在文件处打开终端
1 | cat /proc/sys/kernel/randomize_va_space |
在未开启PIE的情况下不论ASLR操作数是多少函数的地址都不会改变。
地址空间布局随机化(Address Space Layout Randomization, ASLR)和位置无关可执行文件(Position-Independent Executable, PIE)是两个重要的安全机制。