Pwn学习笔记17:其他一些技术简介
PartialOverwrite
- 只更改func@got低位两个字节的值,可以替换为前后0x0000~0xffff范围内的地址
- 修改的两个字节中,ASLR只影响高4位(低12位不受ASLR影响)
- 也就是说,即使不泄漏地址,也有1/16的概率调用到想要的地址
- 重写stack上返回地址的低位三个字节也是可能的
CAROP(potetisensei和自己命名)
- 意思是Calc&AdjustROP,在func@got中,修正必要的差异,更改为想要的函数
- 首先,需要泄漏一些地址,确定libc,确定函数偏移
- 只需要
pop ecx; pop ebx; add [ecx], ebx; call [ecx];
这些ROP
- 不需要泄漏内存就可能调用system,可以用更少的ROP
- 31c3 CTF – pwn30 cairo
vtable攻略(no-NX时__libc_start_main的Wrapping)
- 只能任意更改vptr,可以指定成员函数的第一个参数字符串的情况
- 使vptr指向__libc_start_main@got之前一点,并在第一个参数字符串中写入shellcode
- 即使无法指定函数自身的地址,__libc_start_main也会作为Wrapper执行
- SECUINSIDE 2014 final – pwn300 notes
Thiscall攻略
- 可以控制指向object的指针,像thiscall一样,将第一个参数设置为自身的情况
- 预先申请大量内存后执行堆喷射,生成的类似地址字符串0xXX006873指向object(“\x73\x68\x00\xXX” == “sh¥0”)
- 在上面伪造的object指针中,将*object->vptr[i]设置为system()
- 如果调用该指针函数,会变成
*object@0xXX006873->vptr[i]("sh")
,可以使用thiscall
- SECUINSIDE 2014 final – pwn300 numbers
argv[0]泄漏内存
- canary检查失败异常结束时,stderr会显示错误信息
- 错误信息包括文件名,也就是argv[0],它是栈上的指针
- 如果在canary检查前覆盖了argv[0],将显示内存区域泄漏内存
- CodeGate 2015 – Pwnable400 beef_steak
与网络环境相关的问题
- pwn问题中,由于题目服务器与选手之间距离造成的问题
- 在发送1000字节或者更多数据造成溢出的情况下,数据传输失败并且溢出失败
- read()和recv()以非阻塞模式运行
- 在这种情况下,可以通过其他pwn问题获取的sell开始对该题目进行exploit
- 因为题目环境基本是在同一数据中心,相互之间通信速度非常快
- 即使是巨大的数据,一般也不会产生中断,可以轻松溢出
- CSAW CTF 2013 – Exploitation2, 30c3 CTF – PWN400 DOGE2
避免将垃圾传递给system()
- 如果执行system(垃圾+”;sh”),前半部分的垃圾字符串会造成执行错误,后半部分的字符串会调用shell
- 通过user_input覆盖func@got后,可以立即调用func(user_input,…)等
- 但是,x86中存在限制条件,地址中不能存在NULL
- Hack.lu 2014 – Exploit400 oreo
服务器上有帮助的文件
- 在/proc/self/stat中,有ESP和EIP的值。能够通过这个文件帮助获取特定的栈位置
- 在/proc/self/maps中,有进程自身的内存映射,ASLR环境下非常有帮助
- 某些情况下,可以通过进程的完整路径中获取到主目录的名称
- Hack.lu2014–Exploit500Mario,30c3CTF2013PWN400-DOGE2
dmesg命令
- 写了进程死因和EIP,可以用来判断进程是否执行了0xCC(=int3命令)
- CodeGate2015–Pwnable1000icbm(stage2)
I/O缓冲区的ROP
- scanf或者printf之类的,有一个映射区域作为I/O缓冲区(匿名映射的一部分)
- 可以利用I/O缓冲区进行stack pivot,相对自由的进行ROP
- SECUINSIDE 2013 – Pwnable750 Pwn me!!
间接引用FSB
- 在FSB可以多次使用的情况下有效。通常使用基于堆的FSB
- 在返回__libc_start_main附近,总有一个,栈上的地址->栈上的地址->栈上的值,这样的引用
- 通过第一个引用FSB,修改第二个地址的低位两个字节
- 通过第二个引用FSB,在栈上写入两个字节任意值
- 通过第一个引用FSB,修改第二个地址末尾两个字节增加的值
- 通过第二个引用FSB,在栈上写入两个字节任意值
- 通过这样重复,可以在栈上写入任意N个字节
- FSB结合栈上生成的值作为地址,可以将任意值写入任意内存
- Ghost in the shellcode 2015 Teaser – Pwn#1 Citadel, 31c3 CTF – pwn30 pong
environ技术
- 在GOT按以下顺序多次泄漏,获取stack地址
- func@got -> libc_base -> _dl_runtime_resolve@libc_got -> ld_base -> environ@ld_bss -> stack
- 即使对于基于堆的漏洞,也可以通过重复的任意内存泄漏来确定stack地址
DWARF伪造
- C++的异常处理是写在一个叫DWARF的数据结构中的,并且是从libgcc的bss区域的handler引用
- 通过伪造整个引用的DWARF,可以从异常处理返回后跳到任意位置
- 使用名叫katana的一个工具,可以生成手动更改的DWARF字符串
- CodeGate 2013 – Pwnable800 membership, Hack.lu 2014 – Exploit500 breakout
通过retf替换cs寄存器
- 在x64机器上运行x86二进制文件时有效
- 如果通过retf将cs寄存器从0x23修改为0x33,就可以将其更改为解释x64指令的模式
- 在某些情况下,可以绕过系统调用限制
- CodeGate 2015 – Pwnable800 rodent (stage2)
Last updated:
水平不济整日被虐这也不会那也得学,脑子太蠢天天垫底这看不懂那学不会