CTFSHOW_OA题解
这道题似乎在网上没有很详细的WP,所以我就来写一下吧。
附件:pwn02
分析main
函数
经典的菜单,先放一下。
分析init
函数
注意到读入了flag
,并且将flag
复制到了某区域。注意到v5
似乎是某堆块,猜测堆块是存储用户的结构体。注意到Line22,似乎是root
的用户名。大胆猜测v5+1033
存储用户密码。故root
的密码为flag
。
分析create_new_user
函数
似乎没有明显的bug,尝试跟进change_password
函数。
分析change_password
函数
此处Line11验证了前文猜测v5+1033
是密码的猜想。
并且此处限制密码长度在0x7-0x18之间。此函数作用为向a1+1033
(即结构体密码字段)写入密码值。
目前为止似乎没有太大问题。先暂停一下回想我们的目的是获取root
的密码。继续向下分析。
分析login
函数
注意到该函数比较密码字段时只会比较前0x18个
注意到该函数s1
、dest
在栈上!
注意到自定义的get_input
函数,分析之。
分析get_input
函数
很鬼精的使用了安全的fgets
,但是却自作聪明的添加了Line15-18,导致最后一个字节是\0
。
回想一下create_new_user
,似乎看到两个全局变量:users
、nb_user
,分别存储用户堆块地址和用户数量,那么,root
在第几个呢?
答案是第0个,参见init
Line28。
同时,注意到login
的v3
是users
的索引,与s1
位置间隔0x400
,且get_input
可以输入1025字节,恰好覆盖索引低地址!
所以可以构造初步流程:
注册->登陆->覆盖v3
以获取root
注册时,可提交0x18个A,以便覆盖时使用。
1 | #-----create_new_user |
此时断点调试:
覆盖后:
成功。注意到return到menu
,传参为v3
,即root
的索引。
分析menu
函数
需要先激活一下,否则不能查看data
然后分析remove
函数
分析remove
函数
注意到图2,如果尝试删除root
账户,则users[0],users[1]
会变为新注册用户。
删除root
只是为了进入到show_data
环节,因为show_data
的对象是根据menu
传参的a1
来决定的。所以此时show_data
就可以获取root
的密码了。
exp:
1 | #create user&password -> login -> validate psn session -> delete root -> show root passwd |