PWN小知识

由于pwn相关的一些专业术语新手入门时不易了解(我也是),因此在此写下零零碎碎(有错误请在评论区指出或补充),并且还有一些相关容易忘记的命令(多看多用)

NX

即No-eXecute(不可执行)的意思,NX(DEP)的基本原理是将数据所在内存页标识为不可执行,当程序溢出成功转入shellcode时,程序会尝试在数据页面上执行指令,此时CPU就会抛出异常,而不是去执行恶意指令。

NX位(No-eXecute),也称为XD位(eXecute Disable),是现代CPU提供的一个硬件安全特性,用于标记内存页是否可以执行代码。启用NX位可以提高操作系统的安全性,因为它可以防止攻击者将数据区域(如栈或堆)中的代码作为执行指令。

当NX位启用时:

  • 数据执行保护(DEP):操作系统可以利用NX位来实现数据执行保护(DEP),防止在非执行内存区域(如默认的栈和堆)执行代码。
  • 防止缓冲区溢出攻击:这使得缓冲区溢出和某些类型的内存损坏攻击更加困难,因为即使攻击者能够将恶意代码注入到一个程序的内存空间,也不能执行注入的代码,因为内存页不允许执行。
  • 与ASLR协同工作:NX位通常与地址空间布局随机化(ASLR)结合使用,以进一步提高安全性。

在大多数现代操作系统中,NX位默认是启用的。例如,在Linux系统中,可以通过执行dmesg | grep NX来检查NX位是否启用。如果看到输出中有”NX (Execute Disable) protection: active”这样的信息,就表示NX位是启用的。

在编译程序时,可以使用特定的编译器选项来确保生成的二进制文件与NX位特性兼容,例如在GCC中使用-z noexecstack选项可以防止栈被标记为可执行,这样就可以利用NX位提供的保护。

Canary

表示栈保护功能有没有开启。栈溢出保护是一种缓冲区溢出攻击缓解手段,当函数存在缓冲区溢出攻击漏洞时,攻击者可以覆盖栈上的返回地址来让shellcode能够得到执行。当启用栈保护后,函数开始执行的时候会先往栈里插入cookie信息,当函数真正返回的时候会验证cookie信息是否合法,如果不合法就停止程序运行。

在计算机安全领域,”canary”(金丝雀)一词通常指的是”栈金丝雀”,这是一种用于检测和防止缓冲区溢出攻击的保护措施。栈金丝雀是一个已知的值,它被放置在栈上的局部变量和控制数据(如返回地址)之间。其思想是,如果发生缓冲区溢出,并且覆盖了返回地址,那么在覆盖返回地址之前,这个金丝雀值也会被覆盖。

在函数调用结束之前,程序会检查栈金丝雀的值是否发生改变。如果金丝雀值被覆盖,程序就知道发生了栈溢出攻击,并且可以采取措施,通常是立即终止程序,以防止攻击者执行任意代码。这种方法是一种普遍的安全防护措施,被广泛应用于现代操作系统和编译器中。

当你看到”Canary found”这样的信息时,可能是在描述一个安全检查机制发现了栈金丝雀的值已经被篡改,从而检测到了潜在的攻击。

GOT和PLT不为人知的关系

在ELF(Executable and Linkable Format)文件中,GOT(Global Offset Table)和PLT(Procedure Linkage Table)协同工作以支持动态链接。它们通常用于动态链接库(shared libraries)中的函数调用。

这里是它们如何工作的简要概述:

  1. PLT (Procedure Linkage Table): 当你的程序调用一个动态链接库(如 libc)中的函数时,它实际上首先调用的是PLT中的一个”桩”(stub)。这个桩是一个小的代码片段,它跳转到GOT中的一个特定条目。
  2. GOT (Global Offset Table): GOT包含了函数和变量的地址。在程序第一次调用外部函数时,GOT中相应的条目被设置为指向PLT中的另一个条目,该条目将控制权转交给动态链接器,它将查找真正的函数地址,然后更新GOT中的条目以指向该地址。这意味着在第一次调用之后,GOT条目会被更新,以后的每次调用都会直接跳转到实际的函数地址,而不再经过PLT。

因此,回答你的问题:在程序启动时,GOT表上的函数地址并不存储PLT函数的地址,而是存储一个指向动态链接器进行符号解析的地址。一旦符号(例如函数)被解析,GOT表中的条目会被更新为指向实际的函数地址。这个过程被称为懒惰绑定(lazy binding),因为符号解析是在运行时按需进行的。

简而言之,GOT最初包含指向PLT中代码的指针,用于触发动态解析。解析完成后,GOT会被更新为指向实际的函数地址。

RELRP

Full RELRO(完全的重定位只读)和Partial RELRO(部分的重定位只读)是Linux系统中用来提高二进制程序安全性的技术。它们控制程序启动时动态链接器如何处理全局偏移表(GOT)和过程链接表(PLT)。以下是它们之间的主要区别:

Partial RELRO

  • GOT保护: Partial RELRO不会将GOT设置为只读,这意味着程序运行时GOT中的条目可以被修改。
  • 性能: 通常比Full RELRO有更好的性能,因为它允许延迟绑定,即在函数第一次被调用时才解析其地址。
  • 安全性: 提供了一定程度的保护,但不如Full RELRO强。
  • 启动时间: 启动时间较短,因为不需要在程序启动时立即解析所有的动态符号。

Full RELRO

  • GOT保护: 将GOT设置为只读,防止攻击者在运行时修改GOT中的条目。
  • PLT和GOT分离: PLT条目在程序启动时就被解析并填充到GOT中,之后GOT被标记为只读。
  • 性能: 可能会有轻微的性能损失,因为启动时需要解析所有动态链接的函数地址。
  • 安全性: 提供更高水平的安全性,防止了GOT覆写攻击,这是一种常见的利用技术。
  • 启动时间: 启动时间可能会稍长,因为需要在程序执行前解析所有的动态符号。

总的来说,Full RELRO提供了更高级别的安全保护,但可能会以轻微增加的启动时间和潜在的运行时性能开销为代价。Partial RELRO则提供了一个折中方案,它比没有RELRO的情况更安全,但提供的保护不如Full RELRO全面。

在编译时,可以使用以下GCC链接器选项来指定RELRO的级别:

  • Partial RELRO: -Wl,-z,relro
  • Full RELRO: -Wl,-z,relro -Wl,-z,now

选择哪种级别取决于你对安全性和性能的需求。对于安全性要求高的应用程序,推荐使用Full RELRO。

ASLR

ASLR 是地址空间布局随机化(Address Space Layout Randomization)的缩写,是操作系统用来提高安全性的一种技术。ASLR 通过随机分配系统和程序的内存地址,使得攻击者很难预测和利用固定的地址来执行恶意操作。

以下是关于 ASLR 的一些关键点:

  1. 随机化:ASLR 会随机化进程内存布局的关键区域的位置,例如可执行文件的基址、堆栈、堆和库的位置。
  2. 防止利用漏洞:ASLR 的主要目的是减少依赖于已知内存地址的攻击,如缓冲区溢出、返回到库函数攻击等。
  3. 实现方式:ASLR 由操作系统内核实现,通常对应用程序是透明的。但是,为了有效利用 ASLR,应用程序和系统库需要编译为位置无关代码(Position Independent Code,PIC)。
  4. 兼容性问题:虽然 ASLR 可以提高安全性,但有时也会导致一些假设地址不变的程序出现问题。开发者需要确保他们的程序能够适应随机化的地址。
  5. 绕过技术:尽管 ASLR 非常有效,但它并非万无一失。攻击者已经开发出了绕过 ASLR 的技术,比如通过暴力破解内存地址或使用信息泄露来发现进程的基址。
  6. 可配置性:在许多系统中,ASLR 可以根据需要进行配置甚至禁用。例如,在 Linux 系统中,/proc/sys/kernel/randomize_va_space 文件用于控制 ASLR 的使用。
  7. 栈保护和DEP:ASLR 通常与其他安全机制如栈保护和数据执行保护(Data Execution Prevention,DEP)一起使用,形成对攻击的更全面的防御。

PIE

简单来说pie就是指硬盘到可执行文件的映射 如果no pie那么映射就没有随机化

PIE代表“位置独立可执行文件”(Position Independent Executable)。这是一种编译选项,可以使得生成的可执行文件在内存中的加载位置可以变化,而不是固定的。位置独立的代码(PIC)通常用于共享库(shared libraries),以便库可以被加载到任何内存地址,而不需要额外的重定位开销。PIE将这一概念扩展到了整个可执行文件。

启用PIE的主要优点是提高了安全性,特别是与地址空间布局随机化(ASLR)一起使用时。ASLR可以随机化进程的内存布局,但如果可执行文件不是位置独立的,那么它的代码段通常会被加载到内存中的固定地址。这可能会使得某些类型的攻击(如基于内存地址的攻击)更容易执行。PIE使得整个可执行文件可以被加载到随机的地址,从而增加了攻击者成功利用内存漏洞的难度。

以下是PIE的一些关键特性:

  1. 内存随机化:PIE允许操作系统在每次运行程序时将其加载到内存中的随机位置,这增加了攻击者预测程序内存布局的难度。
  2. 与ASLR的结合:PIE是ASLR有效的关键组成部分。没有PIE,ASLR对于可执行文件的代码段的随机化就不会那么有效。
  3. 性能开销:尽管现代处理器和操作系统已经对此进行了优化,但位置独立的代码可能会引入轻微的性能开销,因为它需要在运行时进行额外的地址计算。
  4. 链接选项:在GCC中,可以通过添加-fPIE(用于编译)和-pie(用于链接)选项来生成PIE。

例如,使用以下命令编译和链接一个程序:

1
gcc -fPIE -pie -o my_program my_program.c
  1. 广泛支持:大多数现代操作系统和编译器都支持PIE,使其成为提高软件安全性的标准做法。

总的来说,PIE是现代软件安全的重要特性,它与ASLR等技术结合,有效地提高了操作系统的抵抗远程代码执行攻击的能力。

ASLR影响的是堆,共享库,栈等等
PIE影响的是ELF本身的映射

ROPgadget

1
ROPgadget --binary rop  --only 'pop|ret' | grep 'eax'
1
ROPgadget --binary ret2libc1 --string '/bin/sh' 

一些ASCII码对应的字符

可能有人觉得没用,我觉得在gdb的时候还是有一点点用的,因此写下,可能也是本人水平低下

十进制 十六进制 控制字符 转义字符 说明 Ctrl + 下列字母
0 00 NUL \0 Null character(空字符) @
1 01 SOH Start of Header(标题开始) A
2 02 STX Start of Text(正文开始) B
3 03 ETX End of Text(正文结束) C
4 04 EOT End of Transmission(传输结束) D
5 05 ENQ Enquiry(请求) E
6 06 ACK Acknowledgment(收到通知/响应) F
7 07 BEL \a Bell(响铃) G
8 08 BS \b Backspace(退格) H
9 09 HT \t Horizontal Tab(水平制表符) I
10 0A LF \n Line feed(换行键) J
11 0B VT \v Vertical Tab(垂直制表符) K
12 0C FF \f Form feed(换页键) L
13 0D CR \r Carriage return(回车键) M
14 0E SO Shift Out(不用切换) N
15 0F SI Shift In(启用切换) O
16 10 DLE Data Link Escape(数据链路转义) P
17 11 DC1 Device Control 1(设备控制1) /XON(Transmit On) Q
18 12 DC2 Device Control 2(设备控制2) R
19 13 DC3 Device Control 3(设备控制3) /XOFF(Transmit Off) S
20 14 DC4 Device Control 4(设备控制4) T
21 15 NAK Negative Acknowledgement(拒绝接收/无响应) U
22 16 SYN Synchronous Idle(同步空闲) V
23 17 ETB End of Trans the Block(传输块结束) W
24 18 CAN Cancel(取消) X
25 19 EM End of Medium(已到介质末端/介质存储已满) Y
26 1A SUB Substitute(替补/替换) Z
27 1B ESC \e Escape(溢出/逃离/取消) [
28 1C FS File Separator(文件分割符) \
29 1D GS Group Separator(分组符) ]
30 1E RS Record Separator(记录分隔符) ^
31 1F US Unit Separator(单元分隔符) _
32 20 SP White space [Space]
127 7F DEL Delete(删除) ?