ctfshow
pwn70 不可见字符
orw + 不可见字符绕过strlen()
1 | orw = asm(''' |
不可打印字符(non-printable characters)是指在计算机字符集中不对应于可见符号或图形的字符。这些字符通常用于控制文本的格式、流控制、数据结构或者是特殊的功能,而不是直接表示人类可读的内容。
1. 不可打印字符的分类
不可打印字符通常可以分为以下几类:
控制字符:这些字符用于控制设备(如打印机或终端)的行为。例如:
- 换行(Line Feed, LF):
\n
(ASCII 10),用于换行。 - 回车(Carriage Return, CR):
\r
(ASCII 13),用于返回到行首。 - 制表符(Tab):
\t
(ASCII 9),用于插入水平制表。 - 警告音(Bell):
\a
(ASCII 7),用于发出声音提示。
- 换行(Line Feed, LF):
终止字符:如
null
字符\0
(ASCII 0),常用于标记字符串的结束。特殊控制字符:如
ESC
(ASCII 27),用于引入控制序列。
2. 不可打印字符的ASCII码
以下是一些常见的不可打印字符及其对应的 ASCII 码:
字符 | 描述 | ASCII 码 |
---|---|---|
NUL |
空字符(null) | 0 |
SOH |
标题开始 | 1 |
STX |
正文开始 | 2 |
ETX |
正文结束 | 3 |
EOT |
传输结束 | 4 |
ENQ |
请求 | 5 |
ACK |
确认 | 6 |
BEL |
响铃 | 7 |
BS |
退格 | 8 |
HT |
水平制表符 | 9 |
LF |
换行 | 10 |
VT |
垂直制表符 | 11 |
FF |
换页 | 12 |
CR |
回车 | 13 |
SO |
转换为旁路 | 14 |
SI |
转换为内部 | 15 |
ESC |
转义 | 27 |
DEL |
删除 | 127 |
3. 应用场景
不可打印字符在计算机编程和文本处理中的应用非常广泛,包括但不限于:
- 文本格式和控制:在终端或打印机输出时,控制字符用来格式化输出。
- 数据结构:在某些数据结构中,特定的字符可能被用作分隔符或结束符。
- 协议设计:在网络通信协议中,不可打印字符可能用于标记消息的开始和结束,或者表示特定的控制信息。
不可打印字符在安全中的作用
在安全场景中,不可打印字符经常被用作绕过过滤器和检查的手段。例如:
- 缓冲区溢出攻击:攻击者可能会插入不可打印字符,以欺骗安全检查并执行恶意代码。
- 注入攻击:在某些情况下,攻击者可能会通过注入不可打印字符来操纵输入,绕过输入验证。
pwn162
有些东西在早些版本是有缺陷的?
- 远程环境:Ubuntu 16.04
思路:
首先明确在free时,程序会在free的chunk的fd处写0,并且show()函数无用所以要打stdout
- 利用unsortedbin的特性在chunk上留下libc地址(通过chunk shrink),该chunk称chunk A
- 利用程序的特性,部分覆盖使其1/16指向_IO_2_1_stdout_附近
- fastbin_dup(partial write)使chunk A链入fastbin那么stdout附近的那个chunk(B)就也被链入了fastbin
- 申请出chunk B修改stdout的flag->0xfbad1800 和 write_base的低位 -> \x00,并计算地址
- 用realloc调整栈帧使one_gadget成立
为什么覆盖libc地址的低2字节为b”\xdd\x25”?
在gdb中查看_IO_list_all的地址,可以看到stdout,如下:
1 | pwndbg> p (void*)_IO_list_all |
因为我们要在stdout上写入,就必须把它申请出来,并且fastbin取出chunk是要检查size域的,所以我们必须要在stdout附近伪造chunk,一般在libc地址上伪造的chunk的size都为7f
通过观察发现如下:
1 | pwndbg> x/30gx 0x7f8fe0a6b620-0x43 |
如上,在 0x7f8fe0a6b5dd 处可以很好的伪造size,后三位为 5dd 所以我们写libc低2字节为b”\xdd\x25”就有1/16的概率指向stdout附近。
最后再次通过fastbin_dup申请到__malloc_hook附近用one_gadget来getshell
1 | #!/usr/bin/env python3 |
pwn164
这题用的是realloc分配内存。
1 | realloc(void* ptr, size_t size) |
关于realloc有几个重要的知识点:
realloc(ptr,0)相当于free函数
realloc(0.size)相当于malloc函数
realloc(ptr,size)
newsize<size:进行分割,剩下的chunk如果大于等于MINSIZE则进行free
newsize<size:
- next 为top且满足需求,直接从top切割
- next为freechunk 且满足要求先合并(unlink)再切割
- next不满足要求进行malloc(newsize),然后进行数据拷贝,free原chun
关于 realloc的详细介绍,看这位大佬的blog: realloc相关知识点
解题:
本题就两个函数一个realloc,一个free函数。很简单
在realloc的时候,因为每次都是使用realloc_ptr,并且没有变化,导致每次申请的的chunk都会写在realloc_ptr指向的地址,再次申请比上一次的size大就可以往后溢
利用思路:
主要利用基础:UAF,double free
注意到题目中是没有show类型的函数的,所以想进行地址泄露应该要靠IO_FILE攻击
难点:利用realloc进行堆块合并后,再利用UAF进行地址覆盖