【Root-Me】 ELF x86 - Stack buffer overflow basic 1
source link: https://exp-blog.com/safe/ctf/rootme/app-system/elf-x86-stack-buffer-overflow-basic-1/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Stack buffer overflow basic 1
登录靶机后,在当前目录发现 3 个文件:
- .passwd : 明显是目标文件,但是还没有权限打开
- ch13 : 由 ch13.c 编译而成的脚本文件,且其 owner 具备 S 位权限
- ch13.c : ch13 脚本的源文件,只是让我们看一下源码,知道其作用是当变量
check==0xdeadbeef
时,就帮当前用户进行提权
那么这题的切入点就在于如何令变量 check
的值变成 0xdeadbeef
实现当前用户提权,再读取 .passwd
文件。
首先来分析一下源码(分析要点我用注释进行标记了):
#include <stdlib.h>
#include <stdio.h>
/*
gcc -m32 -o ch13 ch13.c -fno-stack-protector
*/
int main()
{
int var;
int check = 0x04030201; // 初始值是方便让我们对比有没有成功修改了 check 的值
char buf[40]; // 注意到 数组buf 与 变量check 是相邻的,即它们的内存地址是连续的
// 数组buf 长度只有 40,但这行代码却从标准输入流读取 45 个字符
// 明显是在暗示可以通过 内存溢出 的方法覆写 变量check 的值
fgets(buf,45,stdin);
// 这两行输出是让我们确认 内存溢出 的结果的,真贴心
printf("\n[buf]: %s\n", buf);
printf("[check] %p\n", check);
if ((check != 0x04030201) && (check != 0xdeadbeef))
printf ("\nYou are on the right way!\n");
if (check == 0xdeadbeef)
{
printf("Yeah dude! You win!\nOpening your shell...\n");
system("/bin/dash");
printf("Shell closed! Bye.\n");
}
return 0;
}
为了可以准确地通过 内存溢出 覆写变量 check
,首先需要知道 fgets
的特性,这是 API 说明:
// fgets 会从 stream 读取 n-1 个字符存储到 s 指针指向的内存块,最后末尾自动补 \0
// 若 stream 的前 n-1 个字符中有换行符 \n,则读取到 \n (包括 \n),最后末尾自动补 \0
// 读取字符的数量只取决于这两个条件,与 s 指向的内存区(如数组)的长度无关
char *fgets 会从 (char *restrict s, int n, FILE *restrict stream);
回到这题,数组 buf
的长度是 40,而 fgets
读取的字符长度是 45,则可以构造如下的 payloads 先测试一下:
0000000000000000000000000000000000000000abcd
其中前 40 个字符 0
是用于填充数组 buf
的,后 4 个字符 abcd
才是利用内存溢出覆写到变量 check
的真正的攻击载荷。
执行命令 ./ch13
运行脚本,再输入这个 payloads ,最后按下回车输入 \n
,发现变量 check
的值被覆写了。
进一步分析变量 check
的值,是 0x64636261
,转换成 ASCII 码就是 dcba
, 而所输入的 payloads 是 abcd
,顺序刚好相反。至此就有足够条件可以构造真正的 payloads 了。
从 ch13.c
的源码可以知道,变量 check
的目标值是 0xdeadbeef
,转换成 ASCII 就是 Þ¾ï
。从测试 payloads 知道,顺序要逆转,因此真正的 payloads 就是:
0000000000000000000000000000000000000000ï¾Þ
执行命令 ./ch13
运行脚本,然后输入这个 payloads ,最后按下回车输入 \n
,发现变量 check
的值被成功覆写成 0xdeadbeef
, 同时也提权成功。
此时执行命令 cat .passwd
成功得到密码,完成挑战。
flag 下载后的 flagzip 的文件需要手动更改后缀为
*.zip
,然后解压即可(为了避免直接刷答案)
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK