一次Python执行js脚本的突破-webshpereXOR加解密实现

直接上代码

加解密函数在js中

111.js文件是从websphere xor conline 抓取的。索性把所有的JavaScript中所有的函数给保存了
var END_OF_INPUT = -1;

var base64Chars = new Array(
    'A','B','C','D','E','F','G','H',
    'I','J','K','L','M','N','O','P',
    'Q','R','S','T','U','V','W','X',
    'Y','Z','a','b','c','d','e','f',
    'g','h','i','j','k','l','m','n',
    'o','p','q','r','s','t','u','v',
    'w','x','y','z','0','1','2','3',
    '4','5','6','7','8','9','+','/'
);

var reverseBase64Chars = new Array();
for (var i=0; i < base64Chars.length; i++){
    reverseBase64Chars[base64Chars[i]] = i;
}

var base64Str;
var base64Count;
function setBase64Str(str){
    base64Str = str;
    base64Count = 0;
}
function readBase64(){    
    if (!base64Str) return END_OF_INPUT;
    if (base64Count >= base64Str.length) return END_OF_INPUT;
    var c = base64Str.charCodeAt(base64Count) & 0xff;
    base64Count++;
    return c;
}
function encodeBase64(str){
    setBase64Str(str);
    var result = '';
    var inBuffer = new Array(3);
    var lineCount = 0;
    var done = false;
    while (!done && (inBuffer[0] = readBase64()) != END_OF_INPUT){
        inBuffer[1] = readBase64();
        inBuffer[2] = readBase64();
        result += (base64Chars[ inBuffer[0] >> 2 ]);
        if (inBuffer[1] != END_OF_INPUT){
            result += (base64Chars [(( inBuffer[0] << 4 ) & 0x30) | (inBuffer[1] >> 4) ]);
            if (inBuffer[2] != END_OF_INPUT){
                result += (base64Chars [((inBuffer[1] << 2) & 0x3c) | (inBuffer[2] >> 6) ]);
                result += (base64Chars [inBuffer[2] & 0x3F]);
            } else {
                result += (base64Chars [((inBuffer[1] << 2) & 0x3c)]);
                result += ('=');
                done = true;
            }
        } else {
            result += (base64Chars [(( inBuffer[0] << 4 ) & 0x30)]);
            result += ('=');
            result += ('=');
            done = true;
        }
        lineCount += 4;
        if (lineCount >= 76){
            result += ('\n');
            lineCount = 0;
        }
    }
    return result;
}

function readReverseBase64(){   
    if (!base64Str) return END_OF_INPUT;
    while (true){      
        if (base64Count >= base64Str.length) return END_OF_INPUT;
        var nextCharacter = base64Str.charAt(base64Count);
        base64Count++;
        if (reverseBase64Chars[nextCharacter]){
            return reverseBase64Chars[nextCharacter];
        }
        if (nextCharacter == 'A') return 0;
    }
    return END_OF_INPUT;
}

function ntos(n){
    n=n.toString(16);
    if (n.length == 1) n="0"+n;
    n="%"+n;
    return unescape(n);
}

function decodeBase64(str){
    setBase64Str(str);
    var result = "";
    var inBuffer = new Array(4);
    var done = false;
    while (!done && (inBuffer[0] = readReverseBase64()) != END_OF_INPUT
        && (inBuffer[1] = readReverseBase64()) != END_OF_INPUT){
        inBuffer[2] = readReverseBase64();
        inBuffer[3] = readReverseBase64();
        result += ntos((((inBuffer[0] << 2) & 0xff)| inBuffer[1] >> 4));
        if (inBuffer[2] != END_OF_INPUT){
            result +=  ntos((((inBuffer[1] << 4) & 0xff)| inBuffer[2] >> 2));
            if (inBuffer[3] != END_OF_INPUT){
                result +=  ntos((((inBuffer[2] << 6)  & 0xff) | inBuffer[3]));
            } else {
                done = true;
            }
        } else {
            done = true;
        }
    }
    return result;
}

function decode(s) {

//   var s = document.form1.encodedtxt.value;//表示获取名为 encodedtxt 的表单元素的值。

  // strip {xor} if existant
  if (s.toUpperCase().substring(0,5)=="{XOR}") {
    s = s.substr(5);
  }
  
  s = decodeBase64( s );
  
  // XOR each char to ASCII('_') (underscore is 95)
  var r = '';
  for (i=0; i< s.length; i++) {
    r += String.fromCharCode(s.charCodeAt(i) ^ 95 );
  
  }
  return r;
//   document.form1.decodedtxt.value=r; //表示获取名为 encodedtxt 的表单元素的值。
  
}

function encode(s) {

//   var s = document.form1.decodedtxt.value;
 
  // XOR each char to ASCII('_') (underscore is 95)
  var r = '';
  for (i=0; i< s.length; i++) {
    r += String.fromCharCode(s.charCodeAt(i) ^ 95 );
  
  }  
  r = encodeBase64( r );
  
  // add {xor}     
  return  "{xor}" + r;
//   document.form1.encodedtxt.value= "{xor}" + r;
  
}

不必深究加解密具体过程,使用Python直接调用js的函数,这里用python3 -m pip install pyexecjs

具体使用方式:

import execjs
import os
# 打印mac默认的js执行环境
# node = execjs.get()
# print(dir(node))
# print(node.exec_)
# script_path = os.path.abspath(__file__)
script_dir = os.path.dirname(os.path.abspath(__file__))
print(script_dir)
# print(script_path)

ctx = execjs.compile(open("/绝对路径/111.js",'r',encoding='utf-8').read())
 
result = ctx.call('encode', 'adminmin')
result2 = ctx.call('decode',"{xor}Oz4rPj0+LDovPiwsKDAtOw==")
print(result)
print(result2)

效果

image

参考与发散思考

  1. 最全总结!聊聊 Python 调用 JS 的几种方式
    https://cloud.tencent.com/developer/article/1670121

方式一:PyExecJS

PyExecJS 是使用最多的一种方式,底层实现方式是:在本地 JS 环境下运行 JS 代码

支持的 JS 环境包含:Node.js、PyV8、PhantomJS、Nashorn 等

方式二:js2py

js2py作为一个纯 Python 实现的 JS 解释器,可以完全脱离 JS 环境,直接将 JS 代码转换为 Python 代码

方式三:Node.js 推荐

实际上是使用 Python 的os.popen执行 node 命令,执行 JS 脚本

首先,确保本地已经安装了 Node.js 环境

修改 JS 脚本,新增一个导出函数 init ,方便内部函数被调用

方式四:PyV8

PyV8 是 Google 将 Chrome V8 引擎用 Python 封装的依赖库

它不依赖本地 JS 环境,运行速度很快

用途

日常 Web 端爬虫过程中,经常会遇到参数被加密的场景,因此,我们需要分析网页源代码
通过调式,一层层剥离出关键的 JS 代码,使用 Python 去执行这段代码,得出参数加密前后的 Python 实现

可以用户前端js加密传参,暴力破解。bp插件编写

posted @ 2023-09-11 16:29  壹個人坐在角落  阅读(41)  评论(0编辑  收藏  举报