某音a_bogus补环境轻松拿捏

731 阅读4分钟

1.挂载点(加密函数入口)

记得加入我们的学习群:点击链接加入群聊:h5.qun.qq.com/s/62P0xwrCN…

相信大家备受jsvmp算法还原密密麻麻的日志数字所困扰,那么有没有简单一点的办法呢?有啊,就是补环境,补环境最终目的是,让js代码运行的环境像浏览器一样,从而能够避开js代码里的环境检测,从而生成正确的加密的值。

看过我的文章《补环境过xhs的x2环境检测》,就知道,jsvmp 挂载了函数到window下面,xhs的挂载点容易看出,直接就是window._webmsxyw(url, json_data),那么a_bogus的挂载点是在哪呢?

image.png

可以看出,bdms.js文件将bdms对象挂载在了window下面。

那么我们看看window.bdms长啥样:

image.png

发现这个对象下嵌套了很多函数,而且都叫e,只是e下的_u ,_v有所不同。我们看看我们需要的加密函数:

image.png

就是这个s函数调用后产生了a_bogus,那么s函数,我们如何调用到它呢?有的伙伴可能想到了,找到它在哪,然后导出到全局,这个想法虽好,但是实际不可行,如图:

image.png

s函数,定位到位置后:

image.png

这个看起来不是那么容易导出到全局。涉及变量和作用域问题。

结合前面讲的,我们能在init下找到我们需要的加密函数:

image.png

他的路径是:

window.bdms.init._v[2].p[42]

然后传入参数即可调用。

2.补环境

接下来开始写代码,把所有bdms.js文件代码全部贴到本地,然后,直接运行node bdms.js,不出意外要出意外,也就是缺window等的,接下来就是挂上Proxy缺啥补啥,总结就是:

let _navigator = {
  webdriver: false,
  userAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
  // geolocation: {},
  mimeTypes: {
    "0": {
      description: "Portable Document Format"
    },
    "1": {
      description: "Portable Document Format"
    }

  },
  cookieEnabled: true,
  appVersion: "5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36",
  appCodeName: "Mozilla",
  appName: "Netscape",
  language: 'zh-CN',
  languages: ['zh-CN', 'zh'],
  bluetooth: {
    [Symbol.toStringTag]: "Bluetooth"
  },
  credentials: {},
  deviceMemory: 8,
  // keyboard: {},
  // locks: {}
  platform: "MacIntel",
  product: "Gecko",
  productSub: "20030107",
  maxTouchPoints: 0,
  storage: {},
  requestMediaKeySystemAccess: function requestMediaKeySystemAccess() { },
  getBattery: function getBattery() { return { isCharging: true } },
  vibrate: function vibrate() {

  },
  connection: {},
  plugins: {
    length: 3,
    item: function item() { },
  },
  hardwareConcurrency: 12,
  webkitPersistentStorage: {},
  webkitTemporaryStorage: {},
  pdfViewerEnabled: true,
  geolocation: {
    "toString": function () {
      return "[object Geolocation]"
    }
  },
  doNotTrack: null,
  userActivation: {
    hasBeenActive: true,
    isActive: true
  },
  appCodeName: "Mozilla",
  scheduling: {},
  vendorSub: "",
  productSub: "20030107",
  vendor: "Google Inc.",
  maxTouchPoints: 0,
}


let _localStorage = {}
_localStorage.getItem = function getItem() {
  console.log("localstorage getItem  ---  ", arguments)
  if (arguments[0] === "xmst") {
    return "R57LHQY4V2N66nbe3oTiiwCb3mr1lpaOc8m5fuc823gxqfhT7FYLSfXFHaf5l5hyC6rZnYNGPYyhcgh1pM8A0InHasK16KlCLBQWLo4YD2EKoPamzDqi"
  }
}
_localStorage.getItem.toString = function toString() {
  return "function getItem() { [native code] }"
}

let localStorage = new Proxy(_localStorage, my_handler(Object.keys({ _localStorage })[0], 30));


let _sessionStorage = {}
let sessionStorage = new Proxy(_sessionStorage, my_handler(Object.keys({ _sessionStorage })[0], 30));



let _location = {
  href: "https://www.xiaohongshu.com/explore",
  pathname: "/explore"
};

function XMLHttpRequest() {
}

XMLHttpRequest.prototype = {
  value: undefined,
  toJSON: undefined,
  withCredentials: true
}
let _screen = {
  availWidth: 1680,
  availHeight: 1050,
  width: 1680,
  height: 1050,
  colorDepth: 24,
  pixelDepth: 24,
  orientation: {
    type: "landscape-primary",
    angle: 0
  },
};

function CanvasRenderingContext2D() { }
CanvasRenderingContext2D.toString = function () { return "function CanvasRenderingContext2D() { [native code] }" }
function HTMLCanvasElement() { }
HTMLCanvasElement.toString = function () { return "function HTMLCanvasElement() { [native code] }" }


function openDatabase() { }
openDatabase.toString = function () { return "function openDatabase() { [native code] }" }


function AudioContext() { }
AudioContext.toString = function () { return "function AudioContext() { [native code] }" }


function setInterval() { }
setInterval.toString = function () { return "function setInterval() { [native code] }" }


function requestAnimationFrame() { }
requestAnimationFrame.toString = function () { return "function requestAnimationFrame() { [native code] }" }

function fetch() { }
fetch.toString = function () { return "function fetch() { [native code] }" }
// console.log(CanvasRenderingContext2D.toString())
let _window = {
  _sdkGlueVersionMap: {},
  XMLHttpRequest: XMLHttpRequest,
  // sessionStorage: function () {
  // },
  localStorage: _localStorage,
  screen: _screen,
  navigator: _navigator,
  document: _document,
  location: _location,
  devicePixelRatio: 1.25,
  setInterval: setInterval,
  requestAnimationFrame: requestAnimationFrame,
  external: {},
  fetch: fetch,
  addEventListener: function addEventListener() { },
  innerWidth: 452,
  innerHeight: 963,
  outerWidth: 1680,
  outerHeight: 1650,
  screenX: 0,
  screenY: 0,
  pageYOffset: 0,
  pageYOffset: 0,
};

其实补的也不多,但就是一个问题,补环境得过程比较玄幻,有的错误得补出来后,才会继续抛出,也就是递归检测,你得补了上级才有下级的检测,比如你得补window下的screen吧,再次运行,他就会抛出screen的属性异常,比如screen.width是undefined,然后就继续补上。

不断完善就能得到最终结果:

我测试了新旧两版的结果如下:

image.png

总之就是,难点在于寻找加密函数挂载在了window下的哪里?这个还是需要一点点感觉,至于为什么bdms.js运行后,会将很多e函数挂载,而且每个对应的_v的列表的前两个值不一样,这个就需要看到反编译后的代码或许能解释。

记得加入我们的学习群:点击链接加入群聊:h5.qun.qq.com/s/62P0xwrCN…