Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Web API Risk Control] dm_img series risk control params collection #951

Open
cxw620 opened this issue Jan 25, 2024 · 3 comments
Open

[Web API Risk Control] dm_img series risk control params collection #951

cxw620 opened this issue Jan 25, 2024 · 3 comments
Labels
新增/Add 添加或修改新的内容 主站杂项/Misc 接口:主站其他类型
Milestone

Comments

@cxw620
Copy link
Contributor

cxw620 commented Jan 25, 2024

The BAC community noticed that Bilibili has officially deployed increasingly stringent risk control measures. This issue is for collecting details of dm_img series risk control params.

Caution

  • Examples may be out of date. DO NOT JUST COPY THEM
  • New risk control params may be added at any time. When meet with -352 or -403 please open your browser's dev tool and check if there were any new dm_img series params not listed here. If not, feel free to leave comment in this issue. Take with details of the request!

Last updated: 2024/2/14 14:13

Must-added params

  • dm_img_list
  • dm_img_str
  • dm_img_inter
  • dm_cover_img_str

Description of each and corresponded generation algorithm

dm_img_list & dm_img_str

The two params are your brower's webgl fingerprint infos.

For personal usage, feel free to use const value from your browser.

let version;
let rendererAndVendor;
const gl = document.createElement("canvas").getContext("webgl");
if (gl) {
  version = gl.getParameter(gl.VERSION);
  const debugInfo = gl.getExtension("WEBGL_debug_renderer_info");
  if (debugInfo) {
    rendererAndVendor = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) +
      gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL);
  }
}
if (version === undefined) { // 禁用了 WebGL
  console.log("dm_img_str", "bm8gd2ViZ2");
  console.log("dm_cover_img_str", "bm8gd2ViZ2");
} else {
  console.log("dm_img_str", btoa(version).slice(0, -2));
  if (rendererAndVendor === undefined) { // 禁用了 WEBGL_debug_renderer_info 扩展
    console.log("dm_cover_img_str", "bm8gd2ViZ2wgZXh0ZW5zaW");
  } else {
    console.log("dm_cover_img_str", btoa(rendererAndVendor).slice(0, -2));
  }
}

Originally posted by @0f-0b in #868 (comment)

dm_img_inter

This param represents your mouse move and click event before the request.

The following example may be outdated.

const { floor, random } = Math;

function f114i(a, b, i) {
  const t = floor(random() * (114 * i));
  return [3 * a + 2 * b + t, 4 * a - 5 * b + t, t];
}

function f114(a, b) {
  const t = floor(random() * 114);
  return [2 * a + 2 * b + 3 * t, 4 * a - b + t, t];
}

function f514(a, b) {
  const t = floor(random() * 514);
  return [3 * a + 2 * b + t, 4 * a - 4 * b + 2 * t, t];
}

const eventTypes = ["mousemove", "click"];

/**
 * @param {Iterable<MouseEvent>} events 最近 50 次 `mousemove` 和 `click` 事件。
 * @returns {string} `dm_img_list` 的值。
 */
export function getDmImgList(events) {
  return JSON.stringify(Array.from(events, (event, index) => {
    const [x, y, z] = f114i(event.x, event.y, index);
    return {
      x,
      y,
      z,
      timestamp: floor(event.timeStamp),
      k: floor(random() * 67) + 60,
      type: eventTypes.indexOf(event.type),
    };
  }));
}

const tagNames = [
  "span", "div", "p", "a", "img", "input", "button", "ul", "ol", "li",
  "h1", "h2", "h3", "h4", "h5", "h6", "form", "textarea", "select", "option",
  "table", "tr", "td", "th", "label", "strong", "em", "section", "article",
];

/**
 * @param {DOMRectReadOnly} windowBounds
 *   初始全零,窗口大小和滚动位置都没变则保持全零;
 *   窗口大小改变时 `width` 和 `height` 属性分别更新为 `innerWidth` 和 `innerHeight`;
 *   滚动位置改变时 `x` 和 `y` 属性分别更新为 `scrollX` 和 `scrollY`。
 * @param {Iterable<Element>} elements
 *   初值是 `document.querySelectorAll("div[data-v-risk=fingerprint]")` 返回的两个元素;
 *   `mousemove` 或 `click` 时更新为只含事件的 `target` 一个元素。
 * @returns {string} `dm_img_inter` 的值。
 */
export function getDmImgInter(windowBounds, elements) {
  return JSON.stringify({
    ds: Array.from(elements, (element) => {
      const bounds = element.getBoundingClientRect();
      const [x1, y1, z1] = f114(bounds.y | 0, bounds.x | 0);
      const [x2, y2, z2] = f514(bounds.width | 0, bounds.height | 0);
      return {
        t: tagNames.indexOf(element.tagName.toLowerCase()) + 1,
        c: btoa(element.className).slice(0, -2),
        p: [x1, z1, y1],
        s: [z2, x2, y2],
      };
    }),
    wh: f114(windowBounds.width, windowBounds.height),
    of: f514(windowBounds.y, windowBounds.x),
  });
}

Originally posted by @0f-0b in #868 (comment)

dm_cover_img_str

See webglVendorAndRenderer from fingerprintjs2. Just base64 encoded.

APIs using dm_img series risk control params

More details are wanted.

@xiaoyv404 xiaoyv404 added 新增/Add 添加或修改新的内容 主站杂项/Misc 接口:主站其他类型 labels Jan 25, 2024
@xiaoyv404 xiaoyv404 added this to the API Update milestone Jan 25, 2024
@xiaomo489
Copy link

这个dm_img_list算法貌似不行

@z0z0r4
Copy link
Collaborator

z0z0r4 commented Feb 14, 2024

dm_cover_img_str 呢?这里好像没提及

@0f-0b
Copy link
Contributor

0f-0b commented Apr 12, 2024

windowBounds 初始全零,窗口大小和滚动位置都没变则保持全零

B 站更新了算法。现在 windowBounds 总是等于 new DOMRect(scrollX, scrollY, innerWidth, innerHeight),不再全零。

但浏览器不登录正常使用也触发风控,或许必须带 SESSDATA cookie。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
新增/Add 添加或修改新的内容 主站杂项/Misc 接口:主站其他类型
Projects
None yet
Development

No branches or pull requests

5 participants