PWN学习笔记(一)Basic Rop
作者:互联网
此学习笔记主要基于CTF WIKI 中的Basic rop部分。附攻防世界cgpwn2的WP
网址为:https://wiki.x10sec.org/pwn/linux/stackoverflow/basic-rop/
--------------------------------------------------------------------
首先翻译了一下文章的开头,内容为:
打开NX保护后,很难继续直接将代码注入堆栈或堆中。攻击者也提出了相应的绕过保护的方法。目前最主要的是面向返回的程序设计。主要思想是基于堆栈缓冲区溢出使用程序中现有的小片段。)改变某些寄存器或变量的值以控制程序的执行流。所谓gadgets就是以ret结尾的指令序列,通过这些指令序列,我们可以修改某些地址的内容,以方便控制程序的执行过程。
之所以称之为ROP,是因为核心是使用指令集中的ret指令来改变指令流的执行顺序。ROP攻击通常必须满足以下条件
1.程序有溢出,可以控制返回地址。
2.您可以找到符合条件的小工具以及相应小工具的地址。
3.如果小工具的地址不是每次都固定的,那么我们需要找到一种方法来动态获取相应的地址。
可以从中获取的信息有:
1.使用ROP的前提是有栈溢出
2.ROP链由一系列小片段构成,对于这些具有特定作用的小片段我们可以将它们组装起来构造出payload,最终获取flag
3.寻找的这些小片段必须含有ret指令 。
一.ret2text
第一个例子 ret2text 这是一个简单的栈溢出,没有用到rop的方法,在此不做赘述。
二.ret2shellcode
首先是最基本的检查
可以看到这是一个32位的ELF文件,基本没有保护。
然后我们用IDA看一下反编译后的代码
可以从gets(&s)处进行栈溢出,但是这里面并没有bin/sh的地址。但是我们可以看到这里面有个未在main中定义的变量buf2,所以这应该是一个全局变量。我们直接点进去看这个变量。
可以看到全局变量buf2被储存在了bss字段,地址为0X0804A080.
我们打开gdb进行调试
可以看到bss对应的段是可读可写可执行的,可以从这里写入shellcode。
对于32位的文件shellcode 可以通过代码shellcode = asm(shellcraft.sh()) 来构造,对于64位文件则为 1.context.arch = "amd64" 2.shellcode = asm(shellcraft.amd64.sh())
最终构造的payload如下
拿到flag。
三.ret2syscall
首先是检察保护机制和文件类型
可以看到这是一个32位文件,只打开了NX保护。
打开IDA分析
这里有一个简单的栈溢出,继续反编译出的函数,并没有找到能让我们获取shell的代码,所以我们需要自己构造出一个能够让程序进行系统调用的函数,即执行execve("/bin/sh",NULL,NULL),从而拿到shell。
通过查阅资料可知对于32位的ELF文件,有以下关系:
mov eax, 0xb
mov ebx, [“/bin/sh”]
mov ecx, 0
mov edx, 0
int 0x80
=> execve("/bin/sh",NULL,NULL)
接下来的目标就很明确了,修改对应寄存器的值即可。
首先找到能够返回的寄存器地址,这里用到了ROPgadget工具。
如图,我们取第二条地址,同理,可以找到其它指令对应的地址。
另外,我们还需要获取bin/sh的地址。可以打开IDA,用shift+F12,再按ctrl+F直接搜索bin/sh,IDA就会找到含有这个字符串的地址。
还有一种方法。
首先打开python,然后一系列下图操作:
就找到了!
还有一种方法如图
啪的一下,很快啊!
最终构造出payload
这里面更多的细节可以参考https://zhuanlan.zhihu.com/p/137144976里面对系统调用的讲解!
四.ret2libc1
首先还是常规套路
没什么要特别说明的,直接下一步IDA调试
可以看到还是从gets这儿溢出,由于找不到系统调用函数,所以我尝试了一下上一题的方法自己构造一个
然后第一步就失败了,接下来怎么办呢,这时候我们发现还是能找到“bin/sh"的地址的,所以肯定还有其他方法实现系统调用。
我们继续看IDA,发现果然有callsystem 的地方
点进去看到地址
接下来就能构造payload了。
这里我们需要注意函数调用堆栈的结构。如果系统函数正常调用,调用时会有一个对应的返回地址,其中“bbbb”是假地址,然后是参数对应的参数内容。
攻防世界之cgpwn2
首先常规检查发现没什么值得特别注意的,直接打开IDA查看。
发现主函数除了调用了一个hello函数之外没做什么事儿,于是查看hello()函数
我们打开hello()函数后前面有一堆while if啥的,但是我们在虚拟机里执行这个程序发现真正有意义的还是上图这部分代码,所以分析这段代码,可以看到参数name,在这个函数里没有被定义,点进去发现是存放在BSS段的未初始化的全局变量,拿到一个有用的信息。
然后接着往下看,出现了gets(&s),显然有个栈溢出,又拿到一个信息。
之后我们找一找有没有可以执行系统调用的函数,发现在pwn里调用了system函数,于是我们就能拿到system_addr = 0x08048420,接下来找找有没有字符串bin/sh,随便用上面三种方法的一种,都找不到,这时候想起来还有name没用到,我们可以通过fgets输入改它的值,改成“/bin/sh",这就有了,这时候name的地址就是我们的"/bin/sh“的地址了。于是就可以构造payload,即栈溢出到我们构造的系统调用函数上就可以了。
。
作者小白一个,不足之处各位师傅多多指教!
标签:bin,可以,Rop,地址,sh,Basic,PWN,溢出,IDA 来源: https://blog.csdn.net/weixin_44120526/article/details/111561933