PWN

PWN study 0x02

不适合人类阅读,非常水的自我笔记

Posted by Elli0t on 2020-04-08

寄存器

  • 64bit: rax,rbx,rcx,rdx,rsi,rdi
  • 32bit: eax,ebx,ecx,edx,esi,edi
  • 16bit: ax,bx,cx,dx,si,di
  • 像 r8,r9,…,r15 这样的寄存器不经常遇到

64位:

  • rsp: 栈顶寄存器
  • rbp: 栈基址寄存器
  • rip: 指令寄存器

  • 注意⚠️:栈有高地址向低地址生长
  • 参数
    • 32位:参数通过栈传递
    • 64位:参数先通过寄存器传递,寄存器不够用了才用栈传递
      • 寄存器使用顺序:rdi,rsi,rdx,…
    • 例如:puts(“hello world”);
      • 32位:hello world 字符串地址在栈上
      • 64位:字符串地址存在 rdi 寄存器中

汇编指令

  • push & pop
    • 函数开始的时候会保存 rbp (push rbp),之后会 pop 出来恢复 rbp
  • add,sub,mul,xor,… 运算指令
    • sub rsp,0x20 开辟栈空间
  • lea 取地址
  • leave ⚠️
    • 维护栈帧,相当于 mov rsp,rbp;pop rbp; 维护 rsp,rbp 指针
  • syscall(64位),int(32位)
    • 系统中断,配合寄存器也可以调用函数

函数调用栈

基本保护方式

通过 checksec 工具可以检查二进制文件开启了哪些保护机制

ASLR

操作系统给的一个保护机制

  • 每次执行时,stack,heap,libc 的位置都不一样,但是 code 段不变
  • 本地调试的时候可以关闭系统的 ASLR
  • 查看是否开启 ASLR
    • cat /proc/sys/kernel/randomize_va_space
  • 通过 ldd 指令可以看看 libc 地址的变化
  • 开启和关闭 ASLR:

RELRO

分成三种状态

  • Disabled
    • got 表和 plt 表都可写
    • fini_arry 也可写 ⚠️
  • Partial(默认)
    • 只有 got 表可写
    • 考虑劫持 got 表
  • Fulled
    • load time 的时候全部函数的地址就已经 resolve 完成,got 表和 plt 表都不可写

Canary

金丝雀

  • 函数调用在栈中保存一个随机值,返回时检查这个随机值是否被篡改
  • 开启时一般可以放弃栈溢出了
  • 为了防止泄漏,canary 的低字节是 ‘\x00’

NX

  • 堆栈不可执行
  • NX 关闭时,堆栈上的数据可以被当成代码来执行
    • 找到 rxw 的段,写入 shellcode 然后跳转到 shellcode
  • NX 开启时,考虑 ROP

    ROP: 我们控制执行程序已有的代码的时候也可以控制程序执行好几段不相邻的程序已有的代码(也就是gadgets),这就是我们所要说的rop。

PIE

  • 地址随机化
  • gcc 默认不开启
  • PIE 开启后,code 段和 data 段都会变动
  • IDA 中显示的是偏移而不是真实地址

ASLR 不负责代码段以及数据段的随机化工作,这项工作由 PIE 负责。但是只有在开启 ASLR 之后,PIE 才会生效。开启ASLR+PIE的一个直接的困扰就是,你会发现没有地方可以写,所有的got表、plt表、bss段地址都是不确定的。只有通过泄漏才可以确定地址。

参考链接

www.freebuf.com
https://blog.csdn.net/gyhgx/article/details/53439417
Pwn学习历程(1)–基本工具、交互、调试
https://pwntools.readthedocs.io/en/stable/
(pwntools 官网介绍)