This commit is contained in:
zhaarey 2024-12-20 17:46:15 +08:00
parent 3b3a73bb60
commit 6ffd3585b6
11 changed files with 166 additions and 41 deletions

View File

@ -27,6 +27,9 @@ jobs:
- name: Build - name: Build
run: | run: |
mkdir build
cd build
cmake ..
make make
- name: Set outputs - name: Set outputs
@ -41,3 +44,6 @@ jobs:
path: | path: |
rootfs rootfs
wrapper wrapper
Dockerfile

1
.gitignore vendored
View File

@ -89,3 +89,4 @@ rootfs/
.vscode/ .vscode/
wrapper wrapper
rootfs/system/bin/linker64 rootfs/system/bin/linker64
build/

58
CMakeLists.txt Normal file
View File

@ -0,0 +1,58 @@
cmake_minimum_required(VERSION 3.25)
project(wrapper)
include(ExternalProject)
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 11)
set(ANDROID_NDK_PATH "$ENV{HOME}/android-ndk-r23b")
set(TOOLCHAIN "${ANDROID_NDK_PATH}/toolchains/llvm/prebuilt/linux-x86_64")
set(CMAKE_C_COMPILER "${TOOLCHAIN}/bin/x86_64-linux-android22-clang")
set(CMAKE_CXX_COMPILER "${TOOLCHAIN}/bin/x86_64-linux-android22-clang++")
set(C_COMPILER "${TOOLCHAIN}/bin/clang")
set(CMAKE_C_FLAGS "-Wall -Werror -O3")
set(CMAKE_CXX_FLAGS "-Wall -Werror -O3")
set(CMDLINE_SOURCE cmdline.c)
set(HANDLE_SOURCE main.cpp)
set(MAIN_SOURCE main.c)
set(WRAPPER_SOURCE wrapper.c)
add_library(cmdline_object OBJECT ${CMDLINE_SOURCE})
add_library(handle_object OBJECT ${HANDLE_SOURCE})
add_executable(main ${MAIN_SOURCE} $<TARGET_OBJECTS:cmdline_object> $<TARGET_OBJECTS:handle_object>)
set_target_properties(main PROPERTIES
COMPILE_DEFINITIONS "MyRelease"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/rootfs/system/bin"
)
find_library(ANDROIDAPPMUSIC_LIB androidappmusic PATHS ${CMAKE_SOURCE_DIR}/rootfs/system/lib64)
find_library(STORESERVICESCORE_LIB storeservicescore PATHS ${CMAKE_SOURCE_DIR}/rootfs/system/lib64)
find_library(MEDIAPLATFORM_LIB mediaplatform PATHS ${CMAKE_SOURCE_DIR}/rootfs/system/lib64)
find_library(CXX_SHARED_LIB c++_shared PATHS ${CMAKE_SOURCE_DIR}/rootfs/system/lib64)
# Link libraries
target_link_libraries(main
${CXX_SHARED_LIB}
${ANDROIDAPPMUSIC_LIB}
${STORESERVICESCORE_LIB}
${MEDIAPLATFORM_LIB}
)
link_directories(${CMAKE_SOURCE_DIR}/rootfs/system/lib64)
ExternalProject_Add(
wrapper
PREFIX ${CMAKE_BINARY_DIR}
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}
CONFIGURE_COMMAND ""
BUILD_COMMAND ${C_COMPILER} -O3 -Wall -o wrapper ${WRAPPER_SOURCE}
BUILD_IN_SOURCE 1
INSTALL_COMMAND ""
DEPENDS main
)

10
Dockerfile Normal file
View File

@ -0,0 +1,10 @@
FROM ubuntu:latest
WORKDIR /app
COPY --from=builder /app /app
#COPY . /app
ENV args ""
CMD ["bash", "-c", "./wrapper ${args}"]
EXPOSE 10020 20020

View File

@ -1,16 +0,0 @@
all: cmdline.o handle.o main wrapper
cmdline.o:
~/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android22-clang -Wall -Werror -nostdlib -c -O3 -o cmdline.o cmdline.c
handle.o: main.cpp
~/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android22-clang++ -Wall -Werror -nostdlib -c -O3 -o handle.o main.cpp
main: handle.o test.c cmdline.o
~/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/x86_64-linux-android22-clang -DMyRelease -Wall -Werror -L ./rootfs/system/lib64 -landroidappmusic -lstoreservicescore -lmediaplatform -lc++_shared -O3 -Wall -o rootfs/system/bin/main cmdline.o handle.o test.c
wrapper: wrapper.c
~/android-ndk-r23b/toolchains/llvm/prebuilt/linux-x86_64/bin/clang -O3 -Wall -o wrapper wrapper.c
clean:
rm handle.o wrapper rootfs/system/bin/main cmdline.o

View File

@ -11,6 +11,16 @@ For best results, it's recommended to use **Windows Subsystem for Linux (WSL)**.
- chocomint, for providing support for arm64 arch. - chocomint, for providing support for arm64 arch.
--- ---
### Version 2 Docker
Available for x86_64 and arm64. Need to download prebuilt version from releases or actions.
Build image: `docker build --tag wrapper .`
Login: `docker run -v ./rootfs/data:/app/rootfs/data -p 10020:10020 -e args="-L username:password -F -H 0.0.0.0" wrapper`
Run: `docker run -v ./rootfs/data:/app/rootfs/data -p 10020:10020 -e args="-H 0.0.0.0" wrapper`
### Version 2 ### Version 2

View File

@ -1,7 +1,7 @@
/* /*
File autogenerated by gengetopt version 2.23 File autogenerated by gengetopt version 2.23
generated with the following command: generated with the following command:
gengetopt -i wrapper.ggo gengetopt
The developers of gengetopt consider the fixed text that goes in all The developers of gengetopt consider the fixed text that goes in all
gengetopt output files to be in the public domain: gengetopt output files to be in the public domain:
@ -40,11 +40,13 @@ const char *gengetopt_args_info_help[] = {
" -D, --decrypt-port=INT (default=`10020')", " -D, --decrypt-port=INT (default=`10020')",
" -M, --m3u8-port=INT (default=`20020')", " -M, --m3u8-port=INT (default=`20020')",
" -P, --proxy=STRING (default=`')", " -P, --proxy=STRING (default=`')",
" -L, --login=STRING ", " -L, --login=STRING username:password",
" -F, --code-from-file (default=off)",
0 0
}; };
typedef enum {ARG_NO typedef enum {ARG_NO
, ARG_FLAG
, ARG_STRING , ARG_STRING
, ARG_INT , ARG_INT
} cmdline_parser_arg_type; } cmdline_parser_arg_type;
@ -72,6 +74,7 @@ void clear_given (struct gengetopt_args_info *args_info)
args_info->m3u8_port_given = 0 ; args_info->m3u8_port_given = 0 ;
args_info->proxy_given = 0 ; args_info->proxy_given = 0 ;
args_info->login_given = 0 ; args_info->login_given = 0 ;
args_info->code_from_file_given = 0 ;
} }
static static
@ -88,6 +91,7 @@ void clear_args (struct gengetopt_args_info *args_info)
args_info->proxy_orig = NULL; args_info->proxy_orig = NULL;
args_info->login_arg = NULL; args_info->login_arg = NULL;
args_info->login_orig = NULL; args_info->login_orig = NULL;
args_info->code_from_file_flag = 0;
} }
@ -103,6 +107,7 @@ void init_args_info(struct gengetopt_args_info *args_info)
args_info->m3u8_port_help = gengetopt_args_info_help[4] ; args_info->m3u8_port_help = gengetopt_args_info_help[4] ;
args_info->proxy_help = gengetopt_args_info_help[5] ; args_info->proxy_help = gengetopt_args_info_help[5] ;
args_info->login_help = gengetopt_args_info_help[6] ; args_info->login_help = gengetopt_args_info_help[6] ;
args_info->code_from_file_help = gengetopt_args_info_help[7] ;
} }
@ -244,6 +249,8 @@ cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
write_into_file(outfile, "proxy", args_info->proxy_orig, 0); write_into_file(outfile, "proxy", args_info->proxy_orig, 0);
if (args_info->login_given) if (args_info->login_given)
write_into_file(outfile, "login", args_info->login_orig, 0); write_into_file(outfile, "login", args_info->login_orig, 0);
if (args_info->code_from_file_given)
write_into_file(outfile, "code-from-file", 0, 0 );
i = EXIT_SUCCESS; i = EXIT_SUCCESS;
@ -410,6 +417,9 @@ int update_arg(void *field, char **orig_field,
val = possible_values[found]; val = possible_values[found];
switch(arg_type) { switch(arg_type) {
case ARG_FLAG:
*((int *)field) = !*((int *)field);
break;
case ARG_INT: case ARG_INT:
if (val) *((int *)field) = strtol (val, &stop_char, 0); if (val) *((int *)field) = strtol (val, &stop_char, 0);
break; break;
@ -440,6 +450,7 @@ int update_arg(void *field, char **orig_field,
/* store the original value */ /* store the original value */
switch(arg_type) { switch(arg_type) {
case ARG_NO: case ARG_NO:
case ARG_FLAG:
break; break;
default: default:
if (value && orig_field) { if (value && orig_field) {
@ -507,10 +518,11 @@ cmdline_parser_internal (
{ "m3u8-port", 1, NULL, 'M' }, { "m3u8-port", 1, NULL, 'M' },
{ "proxy", 1, NULL, 'P' }, { "proxy", 1, NULL, 'P' },
{ "login", 1, NULL, 'L' }, { "login", 1, NULL, 'L' },
{ "code-from-file", 0, NULL, 'F' },
{ 0, 0, 0, 0 } { 0, 0, 0, 0 }
}; };
c = getopt_long (argc, argv, "hVH:D:M:P:L:", long_options, &option_index); c = getopt_long (argc, argv, "hVH:D:M:P:L:F", long_options, &option_index);
if (c == -1) break; /* Exit from `while (1)' loop. */ if (c == -1) break; /* Exit from `while (1)' loop. */
@ -574,7 +586,7 @@ cmdline_parser_internal (
goto failure; goto failure;
break; break;
case 'L': /* . */ case 'L': /* username:password. */
if (update_arg( (void *)&(args_info->login_arg), if (update_arg( (void *)&(args_info->login_arg),
@ -586,6 +598,16 @@ cmdline_parser_internal (
goto failure; goto failure;
break; break;
case 'F': /* . */
if (update_arg((void *)&(args_info->code_from_file_flag), 0, &(args_info->code_from_file_given),
&(local_args_info.code_from_file_given), optarg, 0, 0, ARG_FLAG,
check_ambiguity, override, 1, 0, "code-from-file", 'F',
additional_error))
goto failure;
break;
case 0: /* Long option with no short option */ case 0: /* Long option with no short option */
case '?': /* Invalid option. */ case '?': /* Invalid option. */

View File

@ -51,9 +51,11 @@ struct gengetopt_args_info
char * proxy_arg; /**< @brief (default=''). */ char * proxy_arg; /**< @brief (default=''). */
char * proxy_orig; /**< @brief original value given at command line. */ char * proxy_orig; /**< @brief original value given at command line. */
const char *proxy_help; /**< @brief help description. */ const char *proxy_help; /**< @brief help description. */
char * login_arg; /**< @brief . */ char * login_arg; /**< @brief username:password. */
char * login_orig; /**< @brief original value given at command line. */ char * login_orig; /**< @brief username:password original value given at command line. */
const char *login_help; /**< @brief help description. */ const char *login_help; /**< @brief username:password help description. */
int code_from_file_flag; /**< @brief (default=off). */
const char *code_from_file_help; /**< @brief help description. */
unsigned int help_given ; /**< @brief Whether help was given. */ unsigned int help_given ; /**< @brief Whether help was given. */
unsigned int version_given ; /**< @brief Whether version was given. */ unsigned int version_given ; /**< @brief Whether version was given. */
@ -62,6 +64,7 @@ struct gengetopt_args_info
unsigned int m3u8_port_given ; /**< @brief Whether m3u8-port was given. */ unsigned int m3u8_port_given ; /**< @brief Whether m3u8-port was given. */
unsigned int proxy_given ; /**< @brief Whether proxy was given. */ unsigned int proxy_given ; /**< @brief Whether proxy was given. */
unsigned int login_given ; /**< @brief Whether login was given. */ unsigned int login_given ; /**< @brief Whether login was given. */
unsigned int code_from_file_given ; /**< @brief Whether code-from-file was given. */
} ; } ;

View File

@ -10,6 +10,7 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <netinet/in.h> #include <netinet/in.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h>
#include "import.h" #include "import.h"
#include "cmdline.h" #include "cmdline.h"
@ -22,6 +23,11 @@ static uint8_t leaseMgr[16];
struct gengetopt_args_info args_info; struct gengetopt_args_info args_info;
char *amUsername, *amPassword; char *amUsername, *amPassword;
int file_exists(char *filename) {
struct stat buffer;
return (stat (filename, &buffer) == 0);
}
static void dialogHandler(long j, struct shared_ptr *protoDialogPtr, static void dialogHandler(long j, struct shared_ptr *protoDialogPtr,
struct shared_ptr *respHandler) { struct shared_ptr *respHandler) {
const char *const title = std_string_data( const char *const title = std_string_data(
@ -79,8 +85,32 @@ static void credentialHandler(struct shared_ptr *credReqHandler,
int passLen = strlen(amPassword); int passLen = strlen(amPassword);
if (need2FA) { if (need2FA) {
printf("2FA code: "); if (args_info.code_from_file_flag) {
scanf("%6s", amPassword + passLen); fprintf(stderr, "[!] Enter your 2FA code into rootfs/data/code.txt\n");
fprintf(stderr, "[!] Example command: echo -n 114514 > rootfs/data/2fa.txt\n");
fprintf(stderr, "[!] Waiting for input...\n");
int count = 0;
while (1)
{
if (count >= 20) {
fprintf(stderr, "[!] Failed to get 2FA Code in 60s. Exiting...\n");
exit(0);
}
if (file_exists("/data/2fa.txt")) {
FILE *fp = fopen("/data/2fa.txt", "r");
fscanf(fp, "%6s", amPassword + passLen);
remove("/data/2fa.txt");
fprintf(stderr, "[!] Code file detected! Logging in...\n");
break;
} else {
sleep(3);
count++;
}
}
} else {
printf("2FA code: ");
scanf("%6s", amPassword + passLen);
}
} }
uint8_t *const ptr = malloc(80); uint8_t *const ptr = malloc(80);
@ -435,16 +465,18 @@ inline static int new_socket() {
const char* get_m3u8_method_play(uint8_t leaseMgr[16], unsigned long adam) { const char* get_m3u8_method_play(uint8_t leaseMgr[16], unsigned long adam) {
union std_string HLS = new_std_string_short_mode("HLS"); union std_string HLS = new_std_string_short_mode("HLS");
struct std_vector HLSParam = new_std_vector(&HLS); struct std_vector HLSParam = new_std_vector(&HLS);
static uint8_t z0 = 1; static uint8_t z0 = 0;
struct shared_ptr *ptr_result = (struct shared_ptr *) malloc(32); struct shared_ptr ptr_result;
_ZN22SVPlaybackLeaseManager12requestAssetERKmRKNSt6__ndk16vectorINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS7_IS9_EEEERKb( _ZN22SVPlaybackLeaseManager12requestAssetERKmRKNSt6__ndk16vectorINS2_12basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEENS7_IS9_EEEERKb(
ptr_result, leaseMgr, &adam, &HLSParam, &z0 &ptr_result, leaseMgr, &adam, &HLSParam, &z0
); );
if (_ZNK23SVPlaybackAssetResponse13hasValidAssetEv(ptr_result->obj)) { if (_ZNK23SVPlaybackAssetResponse13hasValidAssetEv(ptr_result.obj)) {
struct shared_ptr *playbackAsset = _ZNK23SVPlaybackAssetResponse13playbackAssetEv(ptr_result->obj); struct shared_ptr *playbackAsset = _ZNK23SVPlaybackAssetResponse13playbackAssetEv(ptr_result.obj);
union std_string *m3u8 = (union std_string *) malloc(24); union std_string *m3u8 = malloc(24);
_ZNK17storeservicescore13PlaybackAsset9URLStringEv(m3u8, playbackAsset->obj); void *playbackObj = playbackAsset->obj;
return std_string_data(m3u8); _ZNK17storeservicescore13PlaybackAsset9URLStringEv(m3u8, playbackObj);
const char *m3u8_str = std_string_data(m3u8);
return m3u8_str;
} else { } else {
return NULL; return NULL;
} }

View File

@ -1,6 +1,6 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include <errno.h> #include <errno.h>
#include <sched.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -35,21 +35,19 @@ int main(int argc, char *argv[], char *envp[]) {
chmod("/system/bin/linker64", 0755); chmod("/system/bin/linker64", 0755);
chmod("/system/bin/main", 0755); chmod("/system/bin/main", 0755);
if (unshare(CLONE_NEWPID)) {
perror("unshare");
return 1;
}
child_proc = fork(); child_proc = fork();
if (child_proc == -1) { if (child_proc == -1) {
perror("fork"); perror("fork");
return 1; return 1;
} }
if (child_proc > 0) { if (child_proc > 0) {
close(STDOUT_FILENO); close(STDOUT_FILENO);
wait(NULL); wait(NULL); // Parent waits for the child process to terminate
return 0; return 0;
} }
// Child process logic
mkdir("/data/data/com.apple.android.music/files", 0777); mkdir("/data/data/com.apple.android.music/files", 0777);
mkdir("/data/data/com.apple.android.music/files/mpl_db", 0777); mkdir("/data/data/com.apple.android.music/files/mpl_db", 0777);
execve("/system/bin/main", argv, envp); execve("/system/bin/main", argv, envp);

View File

@ -5,4 +5,5 @@ option "host" H "" string optional default="127.0.0.1"
option "decrypt-port" D "" int optional default="10020" option "decrypt-port" D "" int optional default="10020"
option "m3u8-port" M "" int optional default="20020" option "m3u8-port" M "" int optional default="20020"
option "proxy" P "" string optional default="" option "proxy" P "" string optional default=""
option "login" L "" string optional option "login" L "username:password" string optional
option "code-from-file" F "" flag off