首页 > 其他分享 >【web_逆向13】ob混淆及实战

【web_逆向13】ob混淆及实战

时间:2023-08-27 11:55:15浏览次数:42  
标签:0x2246 web 13 return function ob 0x51eedc var data

什么是ob混淆?

  • OB 混淆和变量名混淆是常用的代码混淆技术。
  • OB 混淆是指在代码中添加一些无用的代码和函数,以增加代码的复杂度和难以理解性,从而增加代码的保护性。
  • 变量名混淆是指将变量名替换为无意义的字符串,增加代码的难度和防止代码的逆向分析。

ob混淆的特点

  • 它会把常规的所有的.操作处理成[]操作
  • 把所有的字符串进行加密处理. 进行统一管理, 同时提供字符串解密函数
  • 对数组进行打乱. 同时提供可以还原该数组的算法

实战

  • 1、获取电影年度排行榜数据:https://www.xxx.com.cn/BoxOffice/BO/Year/index.html
  • 2、经过分析,数据不在页面源代码;于是切换到Fetch/XHR,经过调试,发现返回的数据被加密了
  • 3、加密入口
  • 4、经过分析,加密数据大概率是由:JSON.parse(JSON.parse(webInstace.shell(e)))解密
  • 5、验证,console中将接口返回的加密数据,放到JSON.parse(webInstace.shell(e))中验证
  • 6、注意:由于此处是三元表达式,我们在滑动鼠标显示参数值的时候会运行代码,最好在console中输入函数,进入加密函数
  • 7、扣取此处代码
    var _0x4da59e = {
        'bUIIa': function _0x2a2af9(_0x779387, _0x4a4fec) {
            return _0x779387 + _0x4a4fec;
        }
    };
    var _0x9843d3 = function(_0x29d556, _0xcc6df, _0x3d7020) {
        if (0x0 == _0xcc6df)
            return _0x29d556[_0x2246('0x254', '4VZ$')](_0x3d7020);
        var _0x48914b;
        _0x48914b = '' + _0x29d556[_0x2246('0x255', 'GL3Q')](0x0, _0xcc6df);
        return _0x48914b += _0x29d556['substr'](_0x4da59e[_0x2246('0x256', 'DK[&')](_0xcc6df, _0x3d7020));
    };
    this[_0x2246('0x257', 'nArV')] = function(_0xa0c834) {
        var _0x51eedc = {
            'pKENi': function _0x2f627(_0x5b6f5a, _0x440924) {
                return _0x5b6f5a === _0x440924;
            },
            'wnfPa': 'ZGz',
            'VMmle': '7|1|8|9|5|2|3|6|0|4',
            'GKWFf': function _0x1a4e13(_0x40cfde, _0x16f3c2) {
                return _0x40cfde == _0x16f3c2;
            },
            'MUPgQ': function _0x342f0d(_0x19038b, _0x4004d6) {
                return _0x19038b >= _0x4004d6;
            },
            'hLXma': function _0x55adaf(_0x45a871, _0x161bdf) {
                return _0x45a871 + _0x161bdf;
            },
            'JdOlO': function _0x13e00a(_0x5899a9, _0x4bb34d) {
                return _0x5899a9 + _0x4bb34d;
            },
            'qrTpg': function _0x1198fb(_0x55b317, _0x22e1db, _0x1b091a) {
                return _0x55b317(_0x22e1db, _0x1b091a);
            },
            'pdmMk': function _0xe2b022(_0x4af286, _0x4c2fd4) {
                return _0x4af286 - _0x4c2fd4;
            },
            'xVKWW': function _0x1094a3(_0x5f3627, _0x2a0ac5, _0x3ad2e5) {
                return _0x5f3627(_0x2a0ac5, _0x3ad2e5);
            }
        };
        if (_0x51eedc[_0x2246('0x258', '@1Ws')](_0x2246('0x259', 'E&PI'), _0x51eedc['wnfPa'])) {
            this['_append'](a);
            return this[_0x2246('0x25a', 'GL3Q')]();
        } else {
            var _0x492a62 = _0x51eedc[_0x2246('0x25b', '&59Q')][_0x2246('0x25c', ')q#9')]('|')
              , _0x356b01 = 0x0;
            while (!![]) {
                switch (_0x492a62[_0x356b01++]) {
                case '0':
                    _0x554c90 = _grsa_JS[_0x2246('0x25d', 'E&PI')]['decrypt']({
                        'ciphertext': _grsa_JS['enc'][_0x2246('0x25e', 'sy^o')]['parse'](_0xa0c834)
                    }, _0x2cf8ae, {
                        'iv': _0x554c90,
                        'mode': _grsa_JS[_0x2246('0x16c', 'O^50')][_0x2246('0x25f', 'Who^')],
                        'padding': _grsa_JS[_0x2246('0x260', '7IfV')][_0x2246('0x261', 'E&PI')]
                    })[_0x2246('0x1c', 'yY#5')](_grsa_JS['enc'][_0x2246('0x262', ']2BX')]);
                    continue;
                case '1':
                    if (_0x51eedc[_0x2246('0x263', 'Jsmq')](null, _0xa0c834) || _0x51eedc[_0x2246('0x264', '!2eC')](0x10, _0xa0c834['length']))
                        return _0xa0c834;
                    continue;
                case '2':
                    _0xa0c834 = _0x9843d3(_0xa0c834, _0x2cf8ae, 0x8);
                    continue;
                case '3':
                    _0x2cf8ae = _grsa_JS[_0x2246('0x265', 'RQ2o')][_0x2246('0x266', '3j7z')][_0x2246('0x267', 'RQ2o')](_0x554c90);
                    continue;
                case '4':
                    return _0x554c90[_0x2246('0x268', 'cs*4')](0x0, _0x51eedc[_0x2246('0x269', 'MVsm')](_0x554c90[_0x2246('0x26a', '0J6f')]('}'), 0x1));
                case '5':
                    _0x554c90 = _0xa0c834[_0x2246('0x26b', 'UwHa')](_0x2cf8ae, 0x8);
                    continue;
                case '6':
                    _0x554c90 = _grsa_JS[_0x2246('0x26c', '4VZ$')]['Utf8']['parse'](_0x554c90);
                    continue;
                case '7':
                    if (!navigator || !navigator[_0x2246('0x26d', '0I#o')])
                        return '';
                    continue;
                case '8':
                    var _0x554c90 = _0x51eedc[_0x2246('0x26e', 'Yb4P')](_0x51eedc[_0x2246('0x26f', 'BQ5p')](parseInt, _0xa0c834[_0x51eedc[_0x2246('0x270', 'Z2VK')](_0xa0c834['length'], 0x1)], 0x10), 0x9)
                      , _0x2cf8ae = _0x51eedc[_0x2246('0x271', 'yY#5')](parseInt, _0xa0c834[_0x554c90], 0x10);
                    continue;
                case '9':
                    _0xa0c834 = _0x9843d3(_0xa0c834, _0x554c90, 0x1);
                    continue;
                }
                break;
            }
        }
    }
  • 8、逐步解析
    • 8.1:_0x51eedc,花指令--将一些简单表达式封装成了函数或者属性
    • 8.2:将所有的_0x2246()函数替换
    • 8.3:将所有的_0x51eedc[]还原
    • 8.4:如果是函数,扣取源代码;如果是函数参数,使用简单的a、b等代替;最后的还原效果
var CryptoJS = require('crypto-js');

var func = function(a, b, c) {
    if (0 == b)
        return a['substr'](c);
    var ret;
    ret = '' + a['substr'](0, b);
    return ret += a['substr'](b + c);
};

var shell = function(data) {
    // if (!navigator || !navigator['userAgent'])
    //     return '';
    // if (false || false)
    //     return data;

    var a = parseInt(data[data['length'] -1], 16) + 9
        , b = parseInt(data[a], 16);

    data = func(data, a, 1);
    a = data['substr'](b, 8);
    data = func(data, b, 8);

    b = CryptoJS['enc']['Utf8']['parse'](a);
    a = CryptoJS['enc']['Utf8']['parse'](a);
    a = CryptoJS['DES']['decrypt']({
        'ciphertext': CryptoJS['enc']['Hex']['parse'](data)
    }, b, {
        'iv': a,
        'mode': CryptoJS['mode']['ECB'],
        'padding': CryptoJS['pad']['Pkcs7']
    })['toString'](CryptoJS['enc']['Utf8']);
    return a['substring'](0, a['lastIndexOf']('}')+1);
    };

  function fn(s) {
      return JSON.parse(shell(s))
  }

  //试跑代码
  s = '接口中返回的加密数据'
  console.log(shell(s));
  • 9、试跑以上代码
  • 10、支持,解密过程全部完整

完整代码实现

  • js版本
import subprocess
from functools import partial
subprocess.Popen = partial(subprocess.Popen, encoding='utf-8')
import execjs
import requests
session = requests.session()

session.headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
}

f = open("01_en数据库.js", mode="r", encoding="utf-8")
js = execjs.compile(f.read())
f.close()


def get_movie_info_by_year(year):
    url = "https://www.xxxx.com.cn/API/GetData.ashx"
    data = {
        "year": year,
        "MethodName": "BoxOffice_GetYearInfoData",
    }

    resp = session.post(url, data=data)
    return js.call("fn", resp.text)


if __name__ == '__main__':
    for i in range(2008, 2024):
        print(get_movie_info_by_year(i))
  • 2、完全python实现
from Crypto.Cipher import DES
from Crypto.Util.Padding import unpad
import binascii
import json
import requests

"""
var func = function(a, b, c) {
    if (0x0 == b)
        return a['substr'](c);
    var ret;
    ret = '' + a['substr'](0x0, b);
    return ret += a['substr']((b+ c));
};

"""


def func(a, b, c):
    if 0 == b:
        return a[c:]    # a['substr'](c)   # substring
    ret = str(a[0: b])
    ret += a[b + c:]
    return ret


def shell(data):
    """
    if ((null == data) || 16 >= data['length'])
        return data;

    var a = parseInt(data[data['length']- 1], 16) + 9;
    var b = parseInt(data[a], 16);

    data = func(data, a, 1);

    a = data['substr'](b, 8);
    data = func(data, b, 8);
    """
    if data is None or len(data) <= 16:
        return data
    a = int(data[-1], 16) + 9
    b = int(data[a], 16)  # 取出來某一个数字
    data = func(data, a, 1)  # 从data中截取一段东西

    a = data[b: b+8]  # 从data中获取到了8个字符串

    data = func(data, b, 8)  # # 从data中截取一段东西

    des = DES.new(key=a.encode("utf-8"), mode=DES.MODE_ECB)
    ming_bs = des.decrypt(binascii.a2b_hex(data))  # 把 字符串还原成字节
    # 去掉填充
    ming_bs = unpad(ming_bs, 8)

    s = ming_bs.decode("utf-8")
    return s[:s.rindex("}")+1]


def fn(data):
    ret = shell(data)
    return json.loads(ret)


def get_movie_info_by_year(year):
    for i in range(10):  # 为了重试的.
        try:
            url = "https://www.xxxx.com.cn/API/GetData.ashx"
            data = {
                "year": year,
                "MethodName": "BoxOffice_GetYearInfoData",
            }
            resp = session.post(url, data=data)
            return fn(resp.text)
        except Exception as e:
            print("本次解密有问题")


if __name__ == '__main__':
    session = requests.session()

    session.headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36"
    }
    for i in range(2008, 2024):
        print(get_movie_info_by_year(i))

  • 3、注意点
    • 由于hex字符串在python与javascript中会稍有不同,例如:0123df在python总可能显示为:123df,会将第一位0去掉,所有需要在解析时加入循环与try处理

标签:0x2246,web,13,return,function,ob,0x51eedc,var,data
From: https://www.cnblogs.com/xwltest/p/17660103.html

相关文章

  • POJ 1308 Is It A Tree?
    这是我做出来的第一道有含量的ACM题,应该好好总结一下!这道1308的题,其实很简单,只要抓住了树的特征,就可以解出来。我的解法的思想是这样的:树的分支数m和树的结点数n有一个关系:n==m+1,只要抓住了这个特征,问题便可迎刃而解! 源代码:#include<stdio.h>#include<cstring>inta,b,m=0,n=0,k=......
  • Weblogic远程代码执行漏洞CVE-2023-21839
    漏洞简介Oracle发布安全公告,修复了一个存在于WebLogicCore中的远程代码执行漏洞(CVE-2023-21839),可在未经身份验证的情况下通过T3、IIOP协议远程访问并破坏易受攻击的WebLogicServer,成功利用该漏洞可能导致未授权访问和敏感信息泄露。影响版本OracleWeblogicServer12.2.1.3.......
  • oracle学习笔记(13)——数据库的启动与关闭
    1、常用的服务(1)OracleServiceSID     数据库服务,这个服务会自动地启动和停止数据库。如果安装了一个数据库,它的缺省启动类型为自动。服务进程为ORACLE.EXE,参数文件initSID.ora,日志文件SIDALRT.log,控制台SVRMGRL.EXE、SQLPLUS.EXE。     注:SID-数据库标识 ......
  • WEB项目概述和环境搭建
    第1章项目概述和环境搭建前言为了巩固web基础知识,提高综合运用能力。故在此章节我们将做了一个在线教育系统,要求每一位同学都能独立完成此案例1.项目概况1.1项目概述软件开发流程项目开发角色​参考PPT1.2项目需求优学管理系统是一款专门针对培训机构定制开发的......
  • 批量安装Linux系统之Cobbler构建
    一、cobbler简介cobbler是一款自动化操作系统安装的实现,与PXE安装系统的区别是可以同时部署多个版本的系统,而PXE只能选择一种系统。二、安装cobbler安装yum源yuminstallepel-release-yyuminstalldhcptftp-serverxinetdhttpdcobblercobbler-webpykickstartdebmirror-y......
  • Stable Diffusion Web UI页面CCS无效问题
    安装后进入http://127.0.0.1:7860,StableDiffusionWebUI页面CCS好像没有加载成功,显示如下: 最后发现,在webui-user.bat加入share参数后,页面正常了setCOMMANDLINE_ARGS=--share ......
  • CS0012: 类型“System.Data.Objects.DataClasses.EntityObject”在未被引用的程序集中
    CS0012:类型“System.Data.Objects.DataClasses.EntityObject”在未被引用的程序集中定义。必须添加对程序集“System.Data.Entity,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b77a5c561934e089”的引用。网址:yii666.com<网址:yii666.com处理办法,在web.config-》syst......
  • Stable diffusion webui炼指定的人物模型
    Stablediffusionwebui炼指定的人物模型1.打开自己的sd服务:修改自己的设置我本地的:http://192.168.1.4:7862/?__theme=dark修改设置--->训练:这个推荐勾上,会屏蔽vae文件,不然的话会出现很多问题反推提示词这里,不要勾选按字母排序了,取消勾选deepbooru上面的值选大过滤的标......
  • Web 安全字体和网络字体 (Web Fonts)
    什么是Web安全字体网络安全字体是由许多操作系统预先安装的字体。虽然不是所有的系统都安装了相同的字体,但你可以使用网络安全字体堆栈来选择几种看起来类似的字体,并且安装在你想支持的各种系统上。如果你想使用预装字体以外的字体,从CSS3开始,你可以使用网络字体Webfonts-Learn......
  • 基于JavaWeb的游戏信息管理系统设计与实现-计算机毕业设计源码
    摘要随着信息技术的发展,基于web模式的管理系统逐渐普及,网上查找信息是目前广受欢迎的模式。基于JavaWeb的游戏信息管理系统可以适应现代化快节奏的游戏方式,满足各类人群足不出户的在线查找游戏,利用基于JavaWeb的游戏信息管理系统可以获取游戏的排名信息,并可以记录个人的游戏数据,......