[2022]填鸭式shellcode编写教程 (四) 服务端编写 huoji shellcode 2022-09-08 747 次浏览 0 次点赞 是时候编写我们的服务端了,之前都是客户端 服务端就不用c++了,那玩意谁用谁知道,两个字 癌症.所以服务端改成http的服务端.这边**你要准备好python3,并且把pip的源换成国内的.** ### 安装好flask 假设你准备好了 **python3,并且把pip的源换成国内的** 你只需要在命令行输入 `python -m pip install flask` 即可安装好flask.然后找个目录新建一个.py文件 新手推荐使用jb全家桶作为IDE.但是我个人喜欢vscode.总之不要使用 不要使用 不要使用 notepad或者notepad++ ### flask的第一个hello world 虽然本系列不教python,但是为了后续的没问题,应该先写个hello world出来: 这是代码,请直接复制粘贴 ```cpp from flask import Flask app = Flask(__name__) @app.route("/") def root(): return '你好世界' if __name__ == "__main__": app.run(debug=True, host="0.0.0.0") ``` 然后打开控制台输入python xxx.py(xxx是你刚刚的python文件名) ![](https://key08.com/usr/uploads/2022/09/557611840.png) 当提示这些的时候,访问哪个running on xxx的url,你应该就看得到一个你好世界了 ### 准备接受指令的接口 首先我们需要对我们的远程协助软件的指令有个结构认知 在本系列我不打算使用json/protobuf啥的,因为对新手不友好.所以我们使用最传统的结构,也就是文本分隔符 定为 `客户端的密码|指令` 客户端在密码正确的情况下返回回显 **请注意,我们没有在做C2,我们在做的是合法的远程协助软件.合法的远程协助是需要客户端的密码的.这样代表是授权了.** ### 输入指令的接口 我们希望我们有个地方能输入指令,所以这个也需要有个接口.同时我们也希望有个输入的web界面 ### 需求汇总 1. 我们需要有个接口让客户端不断循环访问,接受命令然后执行 2. 我们需要有个接口让客户端执行完毕后返回回显给我们 3. 我们需要有个接口让我们能输入命令 4. 我们需要有个界面 本篇文章篇幅有限,只解决1-3的服务端的问题 ### 客户端 -> 服务端接口 ```cpp @app.route('/api/v1/client/get_cmd', methods=['GET']) def client_get_cmd(): return "这是命令" ``` 逐个介绍以下 `@app.route('/api/v1/client/get_cmd', methods=['GET'])` 这个代表当客户端访问`/api/v1/client/get_cmd`的时候,执行client_get_cmd这个方法 client_get_cmd返回一个"这是命令" 把这个代码放到上面空白的地方后,访问http://xxxxxx/api/v1/client/get_cmd 应该看得到这个接口的返回值了: ![](https://key08.com/usr/uploads/2022/09/4121361906.png) 然后我们需要定义一个全局变量,代表是我们要输入的命令,再把我们输出的内容替换成这个变量 这是代码: ```cpp from flask import Flask app = Flask(__name__) g_cmd = "" @app.route('/api/v1/client/get_cmd', methods=['GET']) def client_get_cmd(): global g_cmd return g_cmd @app.route("/") def root(): return '你好世界' if __name__ == "__main__": app.run(debug=True, host="0.0.0.0") ``` 后续我们就会操作这个g_cmd的变量 ### 客户端执行结果 -> 服务端 客户端执行完代码后,要给服务端发送回显代码,我们根据上面如法炮制,只不过这次我们就不能用get的方法了,用post的方法: ```cpp g_respone = "" @app.route('/api/v1/server/get_respone', methods=['POST']) def server_get_respone(): global g_respone g_respone = request.data.decode() return "1337" ``` 注意看有几个不同的是,我们这次用的是post的方法,而且变成了接受客户端的信息 至于为什么要用post方法因为回显有很多字符串是不能在url里面显示的,此外url也有显示的上限所以用post最大是4m的数据已经足够我们干活了 ### 服务端输入命令&服务端获取回显 跟第一步一样,如法炮制 ```cpp @app.route('/api/v1/server/send_cmd', methods=['GET']) def client_send_cmd(): global g_cmd g_cmd = request.args.get('key') + "|" + request.args.get('cmd') return {'success': True, 'cmd': g_cmd} ``` 这里返回了json,因为我们后续要用js渲染一些东西. 回显: ```cpp @app.route('/api/v1/server/get_client_respone', methods=['GET']) def server_get_client_respone(): global g_respone return g_respone ``` ### 测试 如果准确无误,我们可以模拟一遍服务端的流程: 浏览器访问 `http://xxxxx:5000/api/v1/server/send_cmd?key=1111&cmd=dir` 应该返回 ```cpp { "cmd": "1111|dir", "success": true } ``` 访问 `http://127.0.0.1:5000/api/v1/client/get_cmd` 应该返回你刚刚输入的命令和密钥 `1111|dir` ### 完整代码 ```cpp from flask import Flask from flask import request app = Flask(__name__) g_cmd = "" g_respone = "" @app.route('/api/v1/server/get_respone', methods=['POST']) def server_get_respone(): global g_respone g_respone = request.data.decode() return "1337" @app.route('/api/v1/server/get_client_respone', methods=['GET']) def server_get_client_respone(): global g_respone return g_respone @app.route('/api/v1/server/send_cmd', methods=['GET']) def client_send_cmd(): global g_cmd g_cmd = request.args.get('key') + "|" + request.args.get('cmd') return {'success': True, 'cmd': g_cmd} @app.route('/api/v1/client/get_cmd', methods=['GET']) def client_get_cmd(): global g_cmd return g_cmd @app.route("/") def root(): return '你好世界' if __name__ == "__main__": app.run(debug=True, host="0.0.0.0") ``` 下一章节我们将介绍客户端如何跟C2服务器进行联动 本文由 huoji 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。 点赞 0
只有地板了