闲言
作为一名信息安全学习者,编写脚本能力应该是基础能力之一。或许有很多人不注重编写脚本能力,想着自身常备一些脚本即可,然而这样的思维是非常鼠目寸光的,脚本的存在有其必要性,事实上,是不可替代性。
闲言少叙,言归正传。
目标
如何写好一个脚本呢?一个好的脚本有如下特征:
- 脚本效率高
- 编写省时力
- 分工精而简
- 信息反馈足
下面我们会从MoeCTF2024·Web
方向的勇闯铜人阵一题讲解一个不错的脚本是如何一步步写出来的。
题目
题目入口:
只给玩家三秒的时间,笔者的手速是做不到的,同样如果只是靠手速解决这道题,那么笔者也觉得索然无味。这题并没有过多地涉及漏洞知识,我们只要了解题目机制再编写脚本即可。
这就是写脚本的第一个要求:先明白自己要写的脚本的工作原理、有什么需要注意的。
我们首先要知道参数:
本题有设置Session
,这就是我们需要注意的。
我们还要猜想如果成功了会发生什么。因为新生赛不会很难,所以笔者猜想成功后会出现flag:moectf{
,如此我们就有了停止标志。
让我们理理题目机制,这样有利于我们编写脚本:
题目会发送五次数字,我们必须爬取数字并返回对应的答案,五次以后会得到flag,我们同样要爬取flag。在这期间,我们要保证Session一直存在,不然会失败。
既然明白了,那么开始写脚本吧!
编写
分析
写之前肯定要分析细节,也就是解决问题:
- 怎么保存Session
- 怎么爬取数字
- 怎么构造答案
- 怎么编写
main.py
第一个问题读者自行看我脚本即可;中间两个问题我们单开两个文件再导入即可,方便调试;最后一个问题才是重点。
对于大多数比较灵活的脚本,main.py
的逻辑是很重要的。当我们不知道main.py
具体逻辑如何时,不妨先上手编写,边写边想。
main.py
但是本篇是进阶文章,所以就不再赘述基础的脚本编写,笔者直接给出main.py
脚本:
细节的读者会发现我第一行代码的特殊,还有发包方式的不同:
1 | session = requests.Session() |
1 | response = session.post(url, data=data) |
如此完美就可以接受并保存第一个响应包的Set-Cookie: session=balabala
,也就是解决了第一个问题。
通观main.py
代码,笔者只采用了一个while
循环。事实上,笔者刚开始写main.py
时并没有采用循环,连写好几段过程,这样不仅耗时耗力,还容易出错,于是笔者毅然决然选择while循环和函数封装。其实题目明面上表示第一次发包和后面几次发包的功能是不同的、参数是不同的,但是细心观察发现这两种请求包的原理几乎一模一样,只有POST
参数不同而已,该处不同完全可以用灵活的python
语法解决:
综上所述,我们目前解决了两个问题:
怎么保存Session
怎么编写
main.py
还剩两个问题:
- 怎么爬取数字
- 怎么构造答案
不妨细细思考,这两个问题都依赖于响应包,并且每个阶段的工作原理近乎一致,所以不妨编写一个函数,在响应包下来后多次利用该函数,这样不仅省时省空间,还利于调试,笔者于此还会得到一种美感。
fun_request.py
我们在fun_request.py
编写函数request()
读者可以看到我添加了很多调试语句,这些语句没有直接的作用,但是在脚本出问题时可以快速地、有针对性地解决问题,这何尝不是一种高效性的体现呢?
本函数还利用了另外一个函数,函数层层套用也是方便调试和寻找问题的一个优点!
fun_solve.py
该函数只接受题目并返回答案,如果有其他错误就不是该函数的问题,这就大大方便了定位错误。
思考
三个文件的代码,特别是两个函数,笔者很难自己想出来。但是笔者可以问GPT
,这就是写好脚本的一个比较实用的方法:自己想好逻辑,具体代码可以由人工智能代劳。当然别全部交给GPT就不管了,自己还是要调试的。
所以,写好一个脚本有以下一些方法:
- 理解工作机制和注意事项
- 明确脚本主体逻辑,明确分工和封装
- 多加注释和调试语句
- 不会的部分可以询问人工智能
最后,熟能生巧,勇于创新!