Skip to content

Commit 191c35e

Browse files
feat: offline channel
1 parent 2d5318e commit 191c35e

2 files changed

Lines changed: 78 additions & 6 deletions

File tree

import.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,22 @@ extern struct shared_ptr *_ZNK17storeservicescore10URLRequest5errorEv(void *);
264264
extern struct shared_ptr *_ZNK17storeservicescore10URLRequest8responseEv(void *);
265265
extern struct shared_ptr *_ZNK17storeservicescore11URLResponse18underlyingResponseEv(void *);
266266

267+
extern void * _ZN17storeservicescore15PurchaseRequestC2ERKNSt6__ndk110shared_ptrINS_14RequestContextEEE(void *, struct shared_ptr *);
268+
extern void *_ZN17storeservicescore15PurchaseRequest23setProcessDialogActionsEb(void *, int);
269+
extern void *_ZN17storeservicescore15PurchaseRequest12setURLBagKeyERKNSt6__ndk112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE(void *, union std_string *);
270+
extern void *_ZN17storeservicescore15PurchaseRequest16setBuyParametersERKNSt6__ndk112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE(void *, union std_string *);
271+
extern void *_ZN17storeservicescore15PurchaseRequest3runEv(void *);
272+
extern struct shared_ptr *_ZNK17storeservicescore15PurchaseRequest8responseEv(void *);
273+
extern struct shared_ptr *_ZN17storeservicescore16PurchaseResponse5errorEv(void *);
274+
extern struct std_vector _ZNK17storeservicescore16PurchaseResponse5itemsEv(void *);
275+
extern struct std_vector _ZNK17storeservicescore12PurchaseItem6assetsEv(void *);
276+
extern union std_string *_ZNK17storeservicescore13PurchaseAsset3URLEv(void *, void *);
277+
extern int _ZNK17storeservicescore19StoreErrorCondition9errorCodeEv(void *);
278+
279+
extern void *_ZN17storeservicescore14RequestContext8fairPlayEv(void *, void *);
280+
extern struct std_vector _ZN17storeservicescore8FairPlay21getSubscriptionStatusEv(void *);
281+
282+
267283
const char *const android_id = "dc28071e981c439e";
268284
const char *const fairplayCert = "MIIEzjCCA7agAwIBAgIIAXAVjHFZDjgwDQYJKoZIhvcNAQEFBQAwfzELMAkGA1UEBhMCVVMxEz"
269285
"ARBgNVBAoMCkFwcGxlIEluYy4xJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9y"

main.c

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@
2323

2424
static struct shared_ptr apInf;
2525
static uint8_t leaseMgr[16];
26+
static struct shared_ptr reqCtx;
2627
struct gengetopt_args_info args_info;
2728
char *amUsername, *amPassword;
2829
struct shared_ptr GUID;
2930
int decryptCount = 1000;
31+
int offlineFlag;
3032
char *device_infos[9];
3133

3234
// Account info cache
@@ -595,6 +597,37 @@ inline static int new_socket() {
595597
}
596598

597599

600+
const char* get_m3u8_method_download(struct shared_ptr reqCtx, unsigned long adam) {
601+
void *purchase_request = malloc(1024);
602+
_ZN17storeservicescore15PurchaseRequestC2ERKNSt6__ndk110shared_ptrINS_14RequestContextEEE(purchase_request, &reqCtx);
603+
_ZN17storeservicescore15PurchaseRequest23setProcessDialogActionsEb(purchase_request, 1);
604+
union std_string urlBagKey = new_std_string("subDownload");
605+
_ZN17storeservicescore15PurchaseRequest12setURLBagKeyERKNSt6__ndk112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE(purchase_request, &urlBagKey);
606+
char *buyParametersStr = malloc(128);
607+
sprintf(buyParametersStr, "salableAdamId=%lu&price=0&pricingParameters=SUBS&productType=S", adam);
608+
union std_string buyParameters = new_std_string(buyParametersStr);
609+
_ZN17storeservicescore15PurchaseRequest16setBuyParametersERKNSt6__ndk112basic_stringIcNS1_11char_traitsIcEENS1_9allocatorIcEEEE(purchase_request, &buyParameters);
610+
_ZN17storeservicescore15PurchaseRequest3runEv(purchase_request);
611+
struct shared_ptr *response = _ZNK17storeservicescore15PurchaseRequest8responseEv(purchase_request);
612+
struct shared_ptr *error = _ZN17storeservicescore16PurchaseResponse5errorEv(response->obj);;
613+
if (error->obj == NULL) {
614+
struct std_vector items = _ZNK17storeservicescore16PurchaseResponse5itemsEv(response->obj);
615+
struct shared_ptr *firstItem = items.begin;
616+
struct std_vector assets = _ZNK17storeservicescore12PurchaseItem6assetsEv(firstItem->obj);
617+
struct shared_ptr *lastAsset = (struct shared_ptr *)assets.end - 1;
618+
union std_string *url_str = malloc(sizeof(union std_string));
619+
_ZNK17storeservicescore13PurchaseAsset3URLEv(url_str, lastAsset->obj);
620+
const char *url = std_string_data(url_str);
621+
if (url) {
622+
char *result = strdup(url); // Make a copy
623+
free(url_str);
624+
return result;
625+
}
626+
}
627+
return NULL;
628+
}
629+
630+
598631
const char* get_m3u8_method_play(uint8_t leaseMgr[16], unsigned long adam) {
599632
union std_string HLS = new_std_string_short_mode("HLS");
600633
struct std_vector HLSParam = new_std_vector(&HLS);
@@ -656,7 +689,12 @@ void handle_m3u8(const int connfd) {
656689
}
657690
char *ptr;
658691
unsigned long adamID = strtoul(adam, &ptr, 10);
659-
const char *m3u8 = get_m3u8_method_play(leaseMgr, adamID);
692+
const char *m3u8;
693+
if (offlineFlag) {
694+
m3u8 = get_m3u8_method_download(reqCtx, adamID);
695+
} else {
696+
m3u8 = get_m3u8_method_play(leaseMgr, adamID);
697+
}
660698
if (m3u8 == NULL) {
661699
fprintf(stderr, "[.] failed to get m3u8 of adamId: %ld\n", adamID);
662700
writefull(connfd, "\n", sizeof("\n"));
@@ -974,6 +1012,19 @@ void write_music_token(void) {
9741012
fclose(fp);
9751013
}
9761014

1015+
int offline_available() {
1016+
struct shared_ptr *fairplay = malloc(16);
1017+
_ZN17storeservicescore14RequestContext8fairPlayEv(fairplay, reqCtx.obj);
1018+
struct std_vector fairplay_status = _ZN17storeservicescore8FairPlay21getSubscriptionStatusEv(fairplay->obj);
1019+
char *begin_ptr = (char*)fairplay_status.begin;
1020+
char *second_item_ptr = begin_ptr + 16;
1021+
int state = *(int*)((char*)second_item_ptr + 8);
1022+
if (state == 2 || state == 3) { // kFPSubscriptionCanPlayContent, kFPSubscriptionCanStreamAndPlayContent
1023+
return 1;
1024+
}
1025+
return 0;
1026+
}
1027+
9771028
int main(int argc, char *argv[]) {
9781029
cmdline_parser(argc, argv, &args_info);
9791030
char *copy_that_needs_to_be_freed = NULL;
@@ -988,12 +1039,12 @@ int main(int argc, char *argv[]) {
9881039
#endif
9891040

9901041
init();
991-
const struct shared_ptr ctx = init_ctx();
1042+
reqCtx = init_ctx();
9921043
if (args_info.login_given) {
9931044
amUsername = strtok(args_info.login_arg, ":");
9941045
amPassword = strtok(NULL, ":");
9951046
}
996-
if (args_info.login_given && !login(ctx)) {
1047+
if (args_info.login_given && !login(reqCtx)) {
9971048
fprintf(stderr, "[!] login failed\n");
9981049
return EXIT_FAILURE;
9991050
}
@@ -1004,10 +1055,15 @@ int main(int argc, char *argv[]) {
10041055
_ZN22SVPlaybackLeaseManager12requestLeaseERKb(leaseMgr, &autom);
10051056
FHinstance = _ZN21SVFootHillSessionCtrl8instanceEv();
10061057

1058+
offlineFlag = offline_available();
1059+
if (offlineFlag) {
1060+
printf("[+] This account supports offline channel\n");
1061+
}
1062+
10071063
// Cache account info
1008-
g_storefront_id = get_account_storefront_id(ctx);
1009-
g_dev_token = get_dev_token(ctx);
1010-
g_music_token = get_music_user_token(get_guid(), g_dev_token, ctx);
1064+
g_storefront_id = get_account_storefront_id(reqCtx);
1065+
g_dev_token = get_dev_token(reqCtx);
1066+
g_music_token = get_music_user_token(get_guid(), g_dev_token, reqCtx);
10111067
fprintf(stderr, "[+] account info cached successfully\n");
10121068

10131069
write_storefront_id();

0 commit comments

Comments
 (0)