Android 는 루트 없 이 apk 의 침묵 설 치 를 실현 합 니 다.

Android 의 침묵 설 치 는 매우 재 미 있 고 매력 적 인 것 같 습 니 다.그러나 일반적인 방법 으로 핸드폰 에 루트 권한 이 없 으 면 침묵 설 치 를 실현 하기 어 려 울 것 같 습 니 다.Android 는 표시 되 는 Intent 호출 을 제공 하지 않 기 때문에 보통 다음 과 같은 방식 으로 apk 를 설치 합 니 다.

Intent intent = new Intent(Intent.ACTION_VIEW); 
intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive"); 
startActivity(intent); 
그러나 이것 은 진정 으로 침묵 설 치 를 실현 하지 못 했다.사용자 인터페이스 가 있 기 때문에 사용자 가 알 게 될 것 이다.그렇다면 어떻게 백 스테이지 에 몰래 APK 를 설치 할 수 있 을 까?안 드 로 이 드 시스템 의 소스 코드 가 정상적으로 APK 를 설치 하 는 과정 을 보 려 고 할 수 밖 에 없습니다.제 가 다운로드 한 소스 코드 는 안 드 로 이 드 5.0 시스템 의 5 개의 G 크기 입 니 다.그러나 안 드 로 이 드 5.0 은 안전 한 업데이트 가 있 기 때문에 이전 버 전과 어느 정도 차이 가 있 습 니 다.하지만 하 나 를 배 운 후에 다른 비슷 한 과정 을 배 우 는 것 은 간단 합 니 다.C 언어 를 배 운 것 처럼 자바 도 어렵 지 않다.
Android 시스템 은 모든 Permission(권한)을 잠재 적 위험 에 따라'normal','dangerous','signature','signature OrSystem'등 네 가지 등급 으로 구분한다.APK 의 설치 에 대응 하 는 권한 은 INSTALL 입 니 다.PACKAGES,권한 등급 은 다음 두 가지 에 속 합 니 다.따라서 최종 적 으로 APK 의 침묵 설 치 를 실현 하려 면 특별한 처리 가 필요 합 니 다.설 치 된 이 프로 세 스 를 실행 하려 면 시스템 프로 세 스 가 필요 합 니 다.
그렇다면 안 드 로 이 드 자체 가 APK 설 치 를 어떻게 실현 하 는 지 살 펴 보 자.설 치 된 명령 은 pm install 입 니 다.시스템 소스 코드 의/framework s/base/cmds/pm/src/com/android/commands/pm/pm.자바 라 는 파일 을 찾 았 습 니 다.그 는 pm 명령 을 실 현 했 습 니 다.runInstall 방법 을 보 았 습 니 다.이것 이 바로 APK 의 설치 과정 입 니 다.

private void runInstall() { 
 int installFlags = 0; 
 int userId = UserHandle.USER_ALL; 
 String installerPackageName = null; 
 
 String opt; 
 
 String originatingUriString = null; 
 String referrer = null; 
 String abi = null; 
 
 while ((opt=nextOption()) != null) { 
  if (opt.equals("-l")) { 
   installFlags |= PackageManager.INSTALL_FORWARD_LOCK; 
  } else if (opt.equals("-r")) { 
   installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; 
  } else if (opt.equals("-i")) { 
   installerPackageName = nextOptionData(); 
   if (installerPackageName == null) { 
    System.err.println("Error: no value specified for -i"); 
    return; 
   } 
  } else if (opt.equals("-t")) { 
   installFlags |= PackageManager.INSTALL_ALLOW_TEST; 
  } else if (opt.equals("-s")) { 
   // Override if -s option is specified. 
   installFlags |= PackageManager.INSTALL_EXTERNAL; 
  } else if (opt.equals("-f")) { 
   // Override if -s option is specified. 
   installFlags |= PackageManager.INSTALL_INTERNAL; 
  } else if (opt.equals("-d")) { 
   installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE; 
  } else if (opt.equals("--originating-uri")) { 
   originatingUriString = nextOptionData(); 
   if (originatingUriString == null) { 
    System.err.println("Error: must supply argument for --originating-uri"); 
    return; 
   } 
  } else if (opt.equals("--referrer")) { 
   referrer = nextOptionData(); 
   if (referrer == null) { 
    System.err.println("Error: must supply argument for --referrer"); 
    return; 
   } 
  } else if (opt.equals("--abi")) { 
   abi = checkAbiArgument(nextOptionData()); 
  } else if (opt.equals("--user")) { 
   userId = Integer.parseInt(nextOptionData()); 
  } else { 
   System.err.println("Error: Unknown option: " + opt); 
   return; 
  } 
 } 
 
 if (userId == UserHandle.USER_ALL) { 
  userId = UserHandle.USER_OWNER; 
  installFlags |= PackageManager.INSTALL_ALL_USERS; 
 } 
 
 final Uri verificationURI; 
 final Uri originatingURI; 
 final Uri referrerURI; 
 
 if (originatingUriString != null) { 
  originatingURI = Uri.parse(originatingUriString); 
 } else { 
  originatingURI = null; 
 } 
 
 if (referrer != null) { 
  referrerURI = Uri.parse(referrer); 
 } else { 
  referrerURI = null; 
 } 
 
 // Populate apkURI, must be present 
 final String apkFilePath = nextArg(); 
 System.err.println("\tpkg: " + apkFilePath); 
 if (apkFilePath == null) { 
  System.err.println("Error: no package specified"); 
  return; 
 } 
 
 // Populate verificationURI, optionally present 
 final String verificationFilePath = nextArg(); 
 if (verificationFilePath != null) { 
  System.err.println("\tver: " + verificationFilePath); 
  verificationURI = Uri.fromFile(new File(verificationFilePath)); 
 } else { 
  verificationURI = null; 
 } 
 
 LocalPackageInstallObserver obs = new LocalPackageInstallObserver(); 
 try { 
  VerificationParams verificationParams = new VerificationParams(verificationURI, 
    originatingURI, referrerURI, VerificationParams.NO_UID, null); 
 
  mPm.installPackageAsUser(apkFilePath, obs.getBinder(), installFlags, 
    installerPackageName, verificationParams, abi, userId); //  !!                 
 
  synchronized (obs) { 
   while (!obs.finished) { 
    try { 
     obs.wait(); 
    } catch (InterruptedException e) { 
    } 
   } 
   if (obs.result == PackageManager.INSTALL_SUCCEEDED) { 
    System.out.println("Success"); 
   } else { 
    System.err.println("Failure [" 
      + installFailureToString(obs) 
      + "]"); 
   } 
  } 
 } catch (RemoteException e) { 
  System.err.println(e.toString()); 
  System.err.println(PM_NOT_RUNNING_ERR); 
 } 
} 
이 과정 을 알 게 된 후에 어떻게 해 야 할 지 대충 알 게 되 었 다.시스템 밑바닥 에서 이 API 를 차단 한 이상 이 차단 을 돌아 서 사용 할 방법 을 생각해 보 세 요.먼저 떠 오 르 는 것 은 AIDL 을 사용 하 는 것 입 니 다.AIDL 이라는 것 을 모 르 는 도 모 에 게 먼저 물 어보 세 요~~위의 코드 에서 최종 적 으로 설 치 를 실현 한 다 는 말 입 니 다.mPm.intallPackage AsUser(...),mPm 은 무엇 입 니까?IPackageManager 유형 을 발견 하기 어렵 지 않 습 니 다.그러면 이 종 류 는 어디에서 나 옵 니까?찾 아 보 세 요./framework s/base/core/java/android/content/pm 이 가방 밑 에 있 습 니 다.우리 프로젝트 디 렉 터 리 밑 에 복사 하면 가방 이름 이 바 뀌 지 않 습 니 다.이 파일 만 복사 하면 안 될 것 입 니 다.다른 에 이 드 를 찾 을 수 없 으 면 복사 해 올 것 입 니 다.안 드 로 이 드 5.0 에서 에 이 드 가 바 뀌 는 것 이 비교적 크기 때문에 많은 것 을 복사 해 야 하고 변경 도 해 야 한다.나 도 그 가 잘못 보고 하지 않 은 것 으로 바 꾸 는 데 오 랜 시간 이 걸 렸 다.
최종 프로젝트 목록 은 다음 과 같 습 니 다~~

그렇다면 어떻게 사용 할 까?
4.567917.1.시스템 서비스 android.os.ServiceManager 를 먼저 가 져 옵 니 다.이것 은 또 숨겨 진 것 입 니 다.어떻게 합 니까?자바 수준 을 시험 할 때 가 왔 습 니 다~~맞습니다.반사 메커니즘 으로 ServiceManager 클래스 와 이 클래스 의 방법 을 얻 습 니 다.
4.567917.2.서비스 가 있 으 면 우 리 는 IPackage Manager 라 는 대상 을 받 아야 한다.
4.567917.3.IPackageManager 안의 installPackage 방법 으로 설치 합 니 다.
구현 코드 는 다음 과 같 습 니 다:

package com.example.autoinstall; 
 
import java.io.File; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.lang.reflect.Method; 
 
import android.app.Activity; 
import android.content.Intent; 
import android.content.pm.IPackageInstallObserver2; 
import android.content.pm.IPackageManager; 
import android.content.pm.VerificationParams; 
import android.net.Uri; 
import android.os.Bundle; 
import android.os.IBinder; 
import android.os.RemoteException; 
import android.view.View; 
 
public class MainActivity extends Activity { 
 
 @Override 
 protected void onCreate(Bundle savedInstanceState) { 
  super.onCreate(savedInstanceState); 
  setContentView(R.layout.activity_main); 
 } 
 
 /** 
  * Button     
  * @param view 
  */ 
 public void install(View view) 
 { 
  String path = ""; 
  if (FileUtils.isSdcardReady()) { 
   path = FileUtils.getSdcardPath(); 
  } else { 
   path = FileUtils.getCachePath(this); 
  } 
  String fileName = path + "/AidlServerDemo.apk"; 
  File file = new File(fileName); 
   
  try { 
   if(!file.exists()) 
    copyAPK2SD(fileName); 
   Uri uri = Uri.fromFile(new File(fileName)); 
      //   Java      android.os.ServiceManager 
   Class<?> clazz = Class.forName("android.os.ServiceManager"); 
   Method method = clazz.getMethod("getService", String.class); 
   IBinder iBinder = (IBinder) method.invoke(null, "package"); 
   IPackageManager ipm = IPackageManager.Stub.asInterface(iBinder); 
   @SuppressWarnings("deprecation") 
   VerificationParams verificationParams = new VerificationParams(null, null, null, VerificationParams.NO_UID, null); 
      //     (       ,         ) 
   ipm.installPackage(fileName, new PackageInstallObserver(), 2, null, verificationParams, ""); 
  } catch (Exception e) { 
   // TODO Auto-generated catch block 
   e.printStackTrace(); 
  } 
 
 } 
 
 //        
 class PackageInstallObserver extends IPackageInstallObserver2.Stub { 
 
  @Override 
  public void onUserActionRequired(Intent intent) throws RemoteException { 
   // TODO Auto-generated method stub 
 
  } 
 
  @Override 
  public void onPackageInstalled(String basePackageName, int returnCode, String msg, Bundle extras) throws RemoteException { 
   //returnCode<span style="font-family: Arial, Helvetica, sans-serif;"> 1,      </span> 
 
 
  } 
 }; 
 
 /** 
  *   assets    APK   SD 
  * 
  * @param strOutFileName 
  * @throws IOException 
  */ 
 private void copyAPK2SD(String strOutFileName) throws IOException { 
  FileUtils.createDipPath(strOutFileName); 
  InputStream myInput = this.getAssets().open("AidlServerDemo.apk"); 
  OutputStream myOutput = new FileOutputStream(strOutFileName); 
  byte[] buffer = new byte[1024]; 
  int length = myInput.read(buffer); 
  while (length > 0) { 
   myOutput.write(buffer, 0, length); 
   length = myInput.read(buffer); 
  } 
  myOutput.flush(); 
  myInput.close(); 
  myOutput.close(); 
 } 
} 
각 버 전의 시스템 소스 코드 에 있 는 adl 이 다 를 수 있 으 므 로 구체 적 으로 호출 하 는 방법 과 파 라 메 터 는 실제 상황 에 따라 정 해 야 합 니 다.Pm.자바 라 는 파일 의 소스 코드 를 자세히 읽 어야 합 니 다.
다른 버 전에 서 는 이 네 개의 파일 만 복사 할 수 있 습 니 다:PackageManager.java,IPackageDeleteObserver.aidl,IPackagerInstallObserver.aidl,IPackageMoveObserver.aidl
그리고 설정 목록 파일 에 INSTALL 을 추가 해 야 합 니 다.PACKAGE 권한

<uses-permission android:name="android.permission.INSTALL_PACKAGES"/> 
그리고 이 응용 uid 를 시스템 단계 로 설정 하고 manifest 탭 에 다음 속성 을 추가 합 니 다.

android:sharedUserId="android.uid.system" 
이렇게 만 하면 침묵 설 치 를 실현 할 수 없습니다.시스템 은 이 app 이 시스템 등급 의 응용 이 라 고 생각 하지 않 기 때문에 이 응용 프로그램의 APK 에 시스템 서명 을 해 야 합 니 다.(주의:침묵 설 치 된 APK 가 아니 라 침묵 설 치 를 실현 하 는 APK 입 니 다.)서명 과정 은 다음 과 같 습 니 다.
총 세 개의 파일 이 필요 합 니 다.
  • 1、SignApk.jar                      %시스템 소스 코드%/out/host/linux-x86/framework/signapk.jar
  • 2、platform.x509.pem          %시스템 소스 코드%/build/target/product/security/platform.x509.pem
  • 3、platform.pk8                    %시스템 원본%/build/target/product/security/platform.pk8
  • 터미널 을 열 고 명령 자바-jar SignApk.jar platform.x509.pem platform.pk8 서명 하지 않 은 APK 서명 후 APK,예 를 들 어
    java -jar SignApk.jar platform.x509.pem  platform.pk8 AutoInstall.apk AutoInstall_new.apk 
    이후,서명 한 APK 를 휴대폰 에 설치 하고,켜 고,침묵 설 치 를 클릭 하고,프로그램 페이지 를 찾 아 보 니 설치 에 성 공 했 습 니 다~~
          
     
    더 많은 내용 은 주 제 를 참고 하여 학습 할 수 있다.
    본 고 는 주로 침묵 설 치 를 실현 하 는 방향 을 제 공 했 지만 구체 적 으로 각 시스템 을 어떻게 호 환 하 는 지 하 나 를 보면 열 을 안다.

    좋은 웹페이지 즐겨찾기