深入分析CTFshow-PWN入门-pwn23的解法与原理

pwn23

这一题相较之前题目难度跨度较大,对挨着做题的同学很不友好
此文章简单解释了代码逻辑和栈溢出崩溃的原理,希望对入门者有帮助
也欢迎各位师傅批评指正!

image

下载附件加权限看信息

image

32 位小端序,直接运行报错

image

在文件夹中添加ctfshow_flag文件,仍然报错

image

将文件复制到根目录去,发现可以正常运行,但是没什么效果
拖进 ida,F5反编译

image

程序先是把 flag 读取到全局变量 flag
signal(11, (__sighandler_t)sigsegv_handler);
这行代码的作用是 注册信号处理函数,具体来说:
● 11是信号编号,对应 SIGSEGV(Segmentation Fault,段错误信号),当程序发生非法内存访问(如访问未分配的内存、写入只读内存等)时,操作系统会发送 SIGSEGV信号。
● (__sighandler_t)sigsegv_handler将自定义函数 sigsegv_handler注册为 SIGSEGV的处理函数,当程序触发段错误时,操作系统会调用 sigsegv_handler而不是默认的崩溃行为。
跟进sigsegv_handler看一下程序发生非法内存访问时会执行什么

image

fprintf(stderr, "%s\n", flag)将flag的内容输出到标准错误流
也就是把 flag 打印了出来
也就是说只要人为制造非法内存访问就可以泄露出 flag
回到 main 函数继续分析

image

int argc表示命令行参数的数量(包括程序名本身)
例如:运行 ./pwn 1 时,argc = 2(./pwn、1 分别时是两个参数)
这里要求argc>1,也就是要求运行 ./pwn 时最少还要再附带一个参数
const char **argv
参数值数组(Argument Vector):
是一个指向字符串数组的指针,每个字符串对应一个命令行参数。
argv[0]:程序名称(如 "./pwn")
argv[1]:第一个参数(如 "1")
argv[argc]:总是 NULL,表示数组结束
这里程序中的argv[1]即代表程序名称后跟着的那个参数
其作为ctfshow()函数的参数运行该函数
步入函数分析

image

这里将我们传进来的参数又复制给了变量dest
dest 空间是有限的,但是 strcpy 没有被限制长度,只要dest 中放不下参数src,也就是我们运行程序时后面跟的参数够长,就会造成缓冲区溢出,从而导致非法内存访问泄露出 flag

image

可以看到这里距离ebp有0x3E大小的空间,也就是 62 字节
再加上覆盖ebp的 4 字节,一共需要 66 字节就可以造成覆盖ebp导致非法内存访问,当然,多余 66 个字节也完全可以

image

访问到了本地根目录的 flag
开启环境, ssh 连接容器

image

直接给我们了 shell,但是访问不到 flag 文件
pwnme就是附件程序,我们利用这个程序的报错来打印 flag

image

拿到 flag

posted @ 2025-08-05 21:23  Claire_cat  阅读(30)  评论(0)    收藏  举报