Open cxw620 opened 10 months ago
x-exbadbasket
seems not a must so we can leave it empty.
Here's example of x-exbadbasket
(already converted into json string and formatted) with explain (may be wrong) of each param. Not familiar with reverse engineering native codes and I need more help.
{
"b00e":"tv.danmaku.bili", // pn => process name
"a0c6":"7.57.2", // vn => version name
"c94e":"3.2.43", // sdk_version => ?
"cd5e":"android", // os
"b59e":"", // serial, leave it empty
"dd3b":0, // root?
"a769":0, // root?
"fd49":"11", // osv => os version
"c203":"", // mac, default empty
"b935":458243454, // apk_sign => **Not know how `libbili.so` gets such value**
"ed96":"", // mid
"f438":"XU0D0580A80C82276D9DF33B4D20665C42E33", // buvid
"e57c":"Dalvik/2.1.0 (Linux; U; Android 11; Pixel 2 XL Build/RP1A.201005.004.A1) 7.57.2 os/android model/Pixel 2 XL mobi_app/android build/7572100 channel/master innerVer/7572110 osVer/11 network/2", // ua
"aff2":1, // app_id
"edc2":1705589660, // ctime
"e24d":7572110, // vc => version code
"e701":"13566853", // build => build sn
"e29f":"0", // ptrace
"e58c":"", // frida => **Not know how `libbili.so` gets such value**
"fd4c":"", // xposed => **Not know how `libbili.so` gets such value**
"d7be":"", // magisk => **Not know how `libbili.so` gets such value**
"e7fa":1, // net
"debc":"google", // brand
"adf0":"Pixel 2 XL", // model
"ccd6":1705677891, // fts
"ada0":"a3811c3af294c9ff045bf24c9bb0545b2024011923245159b5fa061488ab5b05" // fp => see `fp_local`
}
I'm more than curious about the relation between hashcode and real name(ahh, pure characters seen from the register) like b00e
and pn
. MD5 or any else? I don't know...
I successfully generate hexsign
of APP platform with the help of your code.
But I do not know how to get bili_ticket
with hexsign
of APP platform from API. I tried to add these extra fields to request headers or URL querys but failed.
To be honest, Rust is too abstract to understand. So I use TypeScript to test.
Here is my code.
import crypto from 'crypto';
function app_sign(device_info: Uint8Array, x_exbadbasket: Uint8Array, x_fingerprint: Uint8Array): string {
const hmac = crypto.createHmac('sha256', 'Ezlc3tgtl');
hmac.update(device_info);
hmac.update('x-exbadbasket').update(x_exbadbasket);
hmac.update('x-fingerprint').update(x_fingerprint);
return hmac.digest('hex');
}
function web_sign(timestamp: number): string {
const hmac = crypto.createHmac('sha256', 'XgwSnGZ1p');
hmac.update(`ts${timestamp}`);
return hmac.digest('hex');
}
async function gen_bili_ticket(mark: 'ec01' | 'ec02', hexsign: string, timestamp: number, csrf: string | null): Promise<any> {
const url: string = 'https://api.bilibili.com/bapis/bilibili.api.ticket.v1.Ticket/GenWebTicket';
const params: URLSearchParams = new URLSearchParams({
key_id: mark,
hexsign: hexsign,
'context[ts]': timestamp.toString(),
csrf: csrf || ''
});
try {
const response = await fetch(`${url}?${params.toString()}`, {
method: 'POST',
headers: {
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0'
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return data;
} catch (e) {
throw e;
}
}
(async () => {
try {
const timestamp: number = Math.floor(Date.now() / 1000);
const apphexsign: string = app_sign(
new Uint8Array([0x1, 0x2, 0x3, 0x4]),
new Uint8Array([0x5, 0x6, 0x7, 0x8]),
new Uint8Array([0x5, 0x6, 0x7, 0x8]),
);
const webhexsign: string = web_sign(timestamp);
console.log('AppHexSign:', apphexsign);
console.log('WebHexSign:', webhexsign);
const appbiliticket = await gen_bili_ticket('ec01', apphexsign, timestamp, null);
const webbiliticket = await gen_bili_ticket('ec02', webhexsign, timestamp, null);
console.log('AppBiliTicket:', appbiliticket);
console.log('WebBiliTicket:', webbiliticket);
} catch (e) {
console.error('Failed to get BiliTicket:', e);
}
})();
Here is output.
❯ ts-node bili_ticket_all.ts
AppHexSign: 4b7790ee464223540731d50cbf71d8a8622943aea679ad126189f6b41767c5aa
WebHexSign: 8d88ea3fa5bdd525c9ad64d13d422930a49f97c935f0762fbb1f1657869fb885
AppBiliTicket: { code: -400, message: 'invalid sign', ttl: 1 }
WebBiliTicket: {
code: 0,
message: 'OK',
data: {
ticket: 'eyJhbGciOiJIUzI1NiIsImtpZCI6InMwMyIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MjUyNTUxMzIsImlhdCI6MTcyNDk5NTg3MiwicGx0IjotMX0.WPO-oWCbNmLkl3wiuYsZOm5EFdFk5nF6IXXkdm5Qaus',
created_at: 1724995872,
ttl: 259200,
context: {},
nav: {
img: 'https://i0.hdslb.com/bfs/wbi/7cd084941338484aae1ad9425b84077c.png',
sub: 'https://i0.hdslb.com/bfs/wbi/4932caff0ff746eab6f01bf08b70ac45.png'
}
},
ttl: 1
}
I successfully generate
hexsign
of APP platform with the help of your code. But I do not know how to getbili_ticket
withhexsign
of APP platform from API. I tried to add these extra fields to request headers or URL querys but failed. To be honest, Rust is too abstract to understand. So I use TypeScript to test.
Not REST api https://api.bilibili.com/bapis/bilibili.api.ticket.v1.Ticket/GenWebTicket
but gRPC for app.
Since the way getting web
bili_ticket
was found by @aynuarance in https://github.com/SocialSisterYi/bilibili-API-collect/issues/903, I guess that the way getting appbili_ticket
is similar and also makes use of HS256, meaning that what we need to do is finding the HMAC key. After a day of hard work REing oflibbili.so
(OLLVM obfuscation, f**k you), I successfully did so.Encryption algorithm: HMAC-SHA256
HMAC KEY INFO:
ec02
XgwSnGZ1p
ec01
Ezlc3tgtl
Details:
Progress:
x-exbadbasket
from normal APP.x-exbadbasket
fromlibbili.so
.