From 6ffd3585b6f867572d9deb5dda8ee838cdd436fb Mon Sep 17 00:00:00 2001 From: zhaarey <157944548+zhaarey@users.noreply.github.com> Date: Fri, 20 Dec 2024 17:46:15 +0800 Subject: [PATCH] update --- .github/workflows/build.yml | 6 ++++ .gitignore | 1 + CMakeLists.txt | 58 +++++++++++++++++++++++++++++++++++++ Dockerfile | 10 +++++++ Makefile | 16 ---------- README.md | 10 +++++++ cmdline.c | 30 ++++++++++++++++--- cmdline.h | 9 ++++-- test.c => main.c | 52 ++++++++++++++++++++++++++------- wrapper.c | 12 ++++---- wrapper.ggo | 3 +- 11 files changed, 166 insertions(+), 41 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 Dockerfile delete mode 100644 Makefile rename test.c => main.c (93%) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 31e941b..f447380 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,6 +27,9 @@ jobs: - name: Build run: | + mkdir build + cd build + cmake .. make - name: Set outputs @@ -41,3 +44,6 @@ jobs: path: | rootfs wrapper + Dockerfile + + diff --git a/.gitignore b/.gitignore index 02afee2..c96359f 100644 --- a/.gitignore +++ b/.gitignore @@ -89,3 +89,4 @@ rootfs/ .vscode/ wrapper rootfs/system/bin/linker64 +build/ \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..66a9497 --- /dev/null +++ b/CMakeLists.txt @@ -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} $ $) + +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 +) \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..236958f --- /dev/null +++ b/Dockerfile @@ -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 \ No newline at end of file diff --git a/Makefile b/Makefile deleted file mode 100644 index 94ec809..0000000 --- a/Makefile +++ /dev/null @@ -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 diff --git a/README.md b/README.md index 7ac366b..199457a 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,16 @@ For best results, it's recommended to use **Windows Subsystem for Linux (WSL)**. - 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 diff --git a/cmdline.c b/cmdline.c index 49e2d89..fa0341d 100644 --- a/cmdline.c +++ b/cmdline.c @@ -1,7 +1,7 @@ /* File autogenerated by gengetopt version 2.23 generated with the following command: - gengetopt -i wrapper.ggo + gengetopt The developers of gengetopt consider the fixed text that goes in all 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')", " -M, --m3u8-port=INT (default=`20020')", " -P, --proxy=STRING (default=`')", - " -L, --login=STRING ", + " -L, --login=STRING username:password", + " -F, --code-from-file (default=off)", 0 }; typedef enum {ARG_NO + , ARG_FLAG , ARG_STRING , ARG_INT } 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->proxy_given = 0 ; args_info->login_given = 0 ; + args_info->code_from_file_given = 0 ; } static @@ -88,6 +91,7 @@ void clear_args (struct gengetopt_args_info *args_info) args_info->proxy_orig = NULL; args_info->login_arg = 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->proxy_help = gengetopt_args_info_help[5] ; 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); if (args_info->login_given) 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; @@ -410,6 +417,9 @@ int update_arg(void *field, char **orig_field, val = possible_values[found]; switch(arg_type) { + case ARG_FLAG: + *((int *)field) = !*((int *)field); + break; case ARG_INT: if (val) *((int *)field) = strtol (val, &stop_char, 0); break; @@ -440,6 +450,7 @@ int update_arg(void *field, char **orig_field, /* store the original value */ switch(arg_type) { case ARG_NO: + case ARG_FLAG: break; default: if (value && orig_field) { @@ -507,10 +518,11 @@ cmdline_parser_internal ( { "m3u8-port", 1, NULL, 'M' }, { "proxy", 1, NULL, 'P' }, { "login", 1, NULL, 'L' }, + { "code-from-file", 0, NULL, 'F' }, { 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. */ @@ -574,7 +586,7 @@ cmdline_parser_internal ( goto failure; break; - case 'L': /* . */ + case 'L': /* username:password. */ if (update_arg( (void *)&(args_info->login_arg), @@ -586,6 +598,16 @@ cmdline_parser_internal ( goto failure; 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 '?': /* Invalid option. */ diff --git a/cmdline.h b/cmdline.h index 9073b37..bacb29d 100644 --- a/cmdline.h +++ b/cmdline.h @@ -51,9 +51,11 @@ struct gengetopt_args_info char * proxy_arg; /**< @brief (default=''). */ char * proxy_orig; /**< @brief original value given at command line. */ const char *proxy_help; /**< @brief help description. */ - char * login_arg; /**< @brief . */ - char * login_orig; /**< @brief original value given at command line. */ - const char *login_help; /**< @brief help description. */ + char * login_arg; /**< @brief username:password. */ + char * login_orig; /**< @brief username:password original value given at command line. */ + 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 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 proxy_given ; /**< @brief Whether proxy was given. */ unsigned int login_given ; /**< @brief Whether login was given. */ + unsigned int code_from_file_given ; /**< @brief Whether code-from-file was given. */ } ; diff --git a/test.c b/main.c similarity index 93% rename from test.c rename to main.c index b4e7313..b053fa5 100644 --- a/test.c +++ b/main.c @@ -10,6 +10,7 @@ #include #include #include +#include #include "import.h" #include "cmdline.h" @@ -22,6 +23,11 @@ static uint8_t leaseMgr[16]; struct gengetopt_args_info args_info; 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, struct shared_ptr *respHandler) { const char *const title = std_string_data( @@ -79,8 +85,32 @@ static void credentialHandler(struct shared_ptr *credReqHandler, int passLen = strlen(amPassword); if (need2FA) { - printf("2FA code: "); - scanf("%6s", amPassword + passLen); + if (args_info.code_from_file_flag) { + 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); @@ -435,16 +465,18 @@ inline static int new_socket() { const char* get_m3u8_method_play(uint8_t leaseMgr[16], unsigned long adam) { union std_string HLS = new_std_string_short_mode("HLS"); struct std_vector HLSParam = new_std_vector(&HLS); - static uint8_t z0 = 1; - struct shared_ptr *ptr_result = (struct shared_ptr *) malloc(32); + static uint8_t z0 = 0; + struct shared_ptr ptr_result; _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)) { - struct shared_ptr *playbackAsset = _ZNK23SVPlaybackAssetResponse13playbackAssetEv(ptr_result->obj); - union std_string *m3u8 = (union std_string *) malloc(24); - _ZNK17storeservicescore13PlaybackAsset9URLStringEv(m3u8, playbackAsset->obj); - return std_string_data(m3u8); + if (_ZNK23SVPlaybackAssetResponse13hasValidAssetEv(ptr_result.obj)) { + struct shared_ptr *playbackAsset = _ZNK23SVPlaybackAssetResponse13playbackAssetEv(ptr_result.obj); + union std_string *m3u8 = malloc(24); + void *playbackObj = playbackAsset->obj; + _ZNK17storeservicescore13PlaybackAsset9URLStringEv(m3u8, playbackObj); + const char *m3u8_str = std_string_data(m3u8); + return m3u8_str; } else { return NULL; } diff --git a/wrapper.c b/wrapper.c index 2bac137..11cc551 100644 --- a/wrapper.c +++ b/wrapper.c @@ -1,6 +1,6 @@ #define _GNU_SOURCE + #include -#include #include #include #include @@ -35,24 +35,22 @@ int main(int argc, char *argv[], char *envp[]) { chmod("/system/bin/linker64", 0755); chmod("/system/bin/main", 0755); - if (unshare(CLONE_NEWPID)) { - perror("unshare"); - return 1; - } child_proc = fork(); if (child_proc == -1) { perror("fork"); return 1; } + if (child_proc > 0) { close(STDOUT_FILENO); - wait(NULL); + wait(NULL); // Parent waits for the child process to terminate return 0; } + // Child process logic mkdir("/data/data/com.apple.android.music/files", 0777); mkdir("/data/data/com.apple.android.music/files/mpl_db", 0777); execve("/system/bin/main", argv, envp); perror("execve"); return 1; -} \ No newline at end of file +} diff --git a/wrapper.ggo b/wrapper.ggo index b03edbc..3d8b8b6 100644 --- a/wrapper.ggo +++ b/wrapper.ggo @@ -5,4 +5,5 @@ option "host" H "" string optional default="127.0.0.1" option "decrypt-port" D "" int optional default="10020" option "m3u8-port" M "" int optional default="20020" 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