压缩包解压缩
得到level3 和libc
然后运行,就一个输入,然后就是helloworld
然后,发现只开了NX
用ida打开
溢出
就是rop,溢出,跳转到我们需要的函数,用到的是write,read函数,改写成system的地址,传入/bin/sh——拿到shell
注意:64位中,参数的传递是靠的是寄寄存器,不是栈
但是用gadget找不到连续的关于这三个参数的pop,所以不能用原来简单的思路
用ROP找不到的时候,在ida里面找
发现:
这两个部分如果结合到一起就可以完成对于要求的三个参数寄存器的设置——所以我们利用这段代码
而且这段代码还有特点——在0x4006b4retn的时候,我们需要跳转到0x400690的地址,而且,前面pop rbx,pop rbp,pop r12对于后面是有影响的,r12和rbx*8可以控制call的地址——调用我们需要的函数,rbx+1和rbp在后面有个比较,可以决定我们在执行完我们要执行的函数之后,程序的后续走向
这个函数中的这些代码是最简单的可利用gadget
这个破解过程中,我们需要
- 泄露libc的有关地址——转到write函数执行,赋给write的got表的地址(call 的地址接got表项(数据),jmp 的地址接plt表项(代码))
- 执行read函数,改写目标地址的值(一般是计算得到的system的地址)
- 传个/bin/sh的地址
##前期工作
溢出——填‘a’
覆盖rbp(随便一个值,后面rbp会取栈中的值,重写)
提供第一次跳转的地址
还有其他的计算偏移(write和system)——注意:在本机中调试的时候,偏移是用的本机的libc的偏移,在提交的时候,偏移用的是给的libc的偏移——一定要注意!!!!
##泄露libc的有关地址
我们通过上面的_libc_csu_init 函数来设置write的参数,注意因为用到了很多pop,还有mov,在写payload的时候注意顺序(一开始写的时候就把参数的顺序弄反了,没有仔细考虑)
而且要注意rbp要比rbx大1,rbx*8+r12==write的got地址——*8是二进制左移3位不是左移8位
##执行read函数
我们在利用_libc_csu_init的时候,控制这段代码重复执行,来为我们执行不同的函数,反复的设置参数寄存器的值,这也是为什么我们总是需要rbx(+1之后)==rbp
然后我们依然像刚刚那样设置参数值,我们这里修改write的got表,改成system的地址,所以在后面重写调用write的时候,实际调用的是system
##如何传入/bin/sh
###想法1:
利用interactive()——不行,在前面的时候,因为我们用的是_libc_csu_init,argv【0】已经设置了,如果默认会用参数寄存器中的值
###想法2:
把helloworld的位置(代码)改写成/bin/sh,在后面我们只要把第一个参数寄存器的值设置成当前helloworld的地址就行
——不行,因为这个地址是不可写的
###想法3:
找一个可写的地址——got表,在got表中有没有用到表项
可以改写下面两个函数的地址
然后再在system参数寄存器传入这个地址的指针
整个exp的思路就是这个样子