[AOS] How to use apksigner

koo00·2022년 5월 25일
1

zipalign 과 apksigner 를 활용해서 안드로이드 애플리케이션에 서명하는 방법에 대한 포스팅이다.
리패키징 테스트를 할 때 기존에는 jarsigner 로 서명을 했지만 Android 11 이상부터는 apksigner 로 서명해야 앱이 설치된다.

테스트에 앞서 환경 변수 세팅은 다음과 같다.

# keytool
C:\Program Files\Java\jdk1.8.0_202\bin
# zipalign, apksigner
C:\Users\user\AppData\Local\Android\Sdk\build-tools\32.1.0-rc1


앱 서명을 테스트하기 위해 안드로이드 스튜디오에서 간단한 코드를 작성한다.

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Toast.makeText(this, "Sign Test !", Toast.LENGTH_SHORT).show();
    }
}


다음으로 Build > Generate Signed Bundle or APK 메뉴에 접근한다.

Next > Create new... > 키 정보 입력 후 OK 버튼을 클릭해서 키를 생성한다.

아까 생성한 키 정보를 입력하고 Next > Release 체크 후 Finish 버튼을 클릭하면 앱 서명이 완료된다.

그러나 keytool 명령어로 확인해보니 이상하다. 다른 블로그에서는 잘 떴던 것 같은데..

> keytool -printcert -jarfile app-release.apk
서명된 jar 파일이 아닙니다.


그래서 그냥 zipalignapksigner 를 활용해서 직접 서명을 해보자.


먼저 생성한 apk 파일을 zipalign 명령어를 통해 최적화 시킨다. zipalign 을 하지 않아도 앱 설치 및 실행이 가능했지만 일단 Android Developer 에서 시키니까 따라하자. 나는 apksigner 를 사용할 것이기 때문에 zipalign 명령어를 서명하기 전에 실행해야 한다.

아래 명령어를 통해 zipalign 명령어를 실행시켜 준다.

> zipalign -p -f -v 4 app-release.apk zipaligned_release.apk
Verifying alignment of zipaligned_release.apk (4)...
      87 META-INF/com/android/build/gradle/app-metadata.properties (OK - compressed)
     180 classes.dex (OK - compressed)
 1988200 META-INF/androidx.activity_activity.version (OK)
 1988296 META-INF/androidx.annotation_annotation-experimental.version (OK)
 1988388 META-INF/androidx.appcompat_appcompat-resources.version (OK)
 1988472 META-INF/androidx.appcompat_appcompat.version (OK)
 1988556 META-INF/androidx.arch.core_core-runtime.version (OK)
 1988636 META-INF/androidx.cardview_cardview.version (OK)
 1988736 META-INF/androidx.coordinatorlayout_coordinatorlayout.version (OK)
 1988808 META-INF/androidx.core_core.version (OK)
 ...
 2295853 res/yP.xml (OK - compressed)
 2296444 res/yf.xml (OK - compressed)
 2296778 res/yx.xml (OK - compressed)
 2297278 res/z1.xml (OK - compressed)
 2297516 res/z3.xml (OK - compressed)
 2297784 res/zH.xml (OK - compressed)
 2298348 res/zq.xml (OK - compressed)
 2298820 resources.arsc (OK)
Verification succesful
>


실행 결과 zipaligned_release.apk 파일이 떨어지는데, apksigner 명령어로 해당 파일에 대해 서명을 진행한다.
이때 jks 파일은 아까 안드로이드 스튜디오에서 만든 koooo.jks 파일을 사용한다.

> apksigner sign --ks koooo.jks zipaligned_release.apk
Keystore password for signer #1:
> 


서명이 완료되면 keytool 명령어로 서명 정보를 확인할 수 있다.

> keytool -printcert -jarfile zipaligned_release.apk
서명자 #1:

서명:

소유자: CN=Koo, OU=Test, O=Test, L=Seoul, ST=Seoul, C=KR
발행자: CN=Koo, OU=Test, O=Test, L=Seoul, ST=Seoul, C=KR
일련 번호: 7e375792
적합한 시작 날짜: Mon May 23 12:42:33 KST 2022 종료 날짜: Fri May 17 12:42:33 KST 2047
인증서 지문:
         MD5:  1A:50:08:90:B8:96:43:0E:BC:81:6C:52:D6:F5:56:C2
         SHA1: 24:EC:E4:6D:9E:81:82:E8:F0:F3:09:0E:E1:4F:16:CD:7F:A3:68:92
         SHA256: 7A:CC:48:A3:6D:71:E9:5E:F4:BB:6F:9A:1D:E5:AD:B8:12:FA:5F:2D:28:F0:F0:B6:B4:2B:2E:F6:62:FC:B6:71
서명 알고리즘 이름: SHA256withRSA
주체 공용 키 알고리즘: 2048비트 RSA 키
버전: 3

확장:

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: 94 BC 6E 6A D1 77 BD 0E   99 08 07 2B 5B 07 26 A2  ..nj.w.....+[.&.
0010: 9E 9D 07 94                                        ....
]
]


>


keystore 파일은 keytool 명령어로도 생성할 수 있다.

> keytool -genkey -alias koooo -keyalg RSA -validity 20000 -keystore koooo.keystore
키 저장소 비밀번호 입력:
새 비밀번호 다시 입력:
이름과 성을 입력하십시오.
  [Unknown]:  Koo
조직 단위 이름을 입력하십시오.
  [Unknown]:  Test
조직 이름을 입력하십시오.
  [Unknown]:  Test
구/군/시 이름을 입력하십시오?
  [Unknown]:  Seoul
시/도 이름을 입력하십시오.
  [Unknown]:  Seoul
이 조직의 두 자리 국가 코드를 입력하십시오.
  [Unknown]:  KR
CN=Koo, OU=Test, O=Test, L=Seoul, ST=Seoul, C=KR이() 맞습니까?
  [아니오]:  Y

<koooo>에 대한 키 비밀번호를 입력하십시오.
        (키 저장소 비밀번호와 동일한 경우 Enter 키를 누름):

Warning:
JKS 키 저장소는 고유 형식을 사용합니다. "keytool -importkeystore -srckeystore koooo.keystore -destkeystore 
koooo.keystore -deststoretype pkcs12"를 사용하는 산업 표준 형식인 PKCS12로 이전하는 것이 좋습니다.
>


keytool 로 생성한 koooo.keystore 파일로 동일하게 서명을 진행한다.

> zipalign -p -f -v 4 app-release.apk zipaligned_release2.apk
Verifying alignment of zipaligned_release2.apk (4)...
      87 META-INF/com/android/build/gradle/app-metadata.properties (OK - compressed)
     180 classes.dex (OK - compressed)
 1988200 META-INF/androidx.activity_activity.version (OK)
 1988296 META-INF/androidx.annotation_annotation-experimental.version (OK)
 1988388 META-INF/androidx.appcompat_appcompat-resources.version (OK)
 1988472 META-INF/androidx.appcompat_appcompat.version (OK)
 1988556 META-INF/androidx.arch.core_core-runtime.version (OK)
 1988636 META-INF/androidx.cardview_cardview.version (OK)
 1988736 META-INF/androidx.coordinatorlayout_coordinatorlayout.version (OK)
 1988808 META-INF/androidx.core_core.version (OK)
 ...
  2295853 res/yP.xml (OK - compressed)
 2296444 res/yf.xml (OK - compressed)
 2296778 res/yx.xml (OK - compressed)
 2297278 res/z1.xml (OK - compressed)
 2297516 res/z3.xml (OK - compressed)
 2297784 res/zH.xml (OK - compressed)
 2298348 res/zq.xml (OK - compressed)
 2298820 resources.arsc (OK)
Verification succesful
> 
> apksigner sign --ks koooo.keystore zipaligned_release2.apk
Keystore password for signer #1:
> 
> keytool -printcert -jarfile zipaligned_release2.apk
서명자 #1:

서명:

소유자: CN=Koo, OU=Test, O=Test, L=Seoul, ST=Seoul, C=KR
발행자: CN=Koo, OU=Test, O=Test, L=Seoul, ST=Seoul, C=KR
일련 번호: 16d698e6
적합한 시작 날짜: Mon May 23 15:20:29 KST 2022 종료 날짜: Tue Feb 23 15:20:29 KST 2077
인증서 지문:
         MD5:  D9:59:AB:94:99:13:81:8F:17:F1:0E:79:5A:B7:24:A2
         SHA1: 87:1B:14:60:B8:F9:21:27:DA:2A:28:86:27:FA:7F:BD:94:23:4C:42
         SHA256: 67:59:22:44:7B:2B:6E:C1:AF:62:6C:8D:41:8E:80:7A:BE:84:97:FD:F3:70:64:65:89:E3:56:28:AC:41:95:7A
서명 알고리즘 이름: SHA256withRSA
주체 공용 키 알고리즘: 2048비트 RSA 키
버전: 3

확장:

#1: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: CB 35 E5 C9 36 2D AA D2   93 C0 DA BD 86 A1 CA 0D  .5..6-..........
0010: BE 9E 87 7F                                        ....
]
]


> 


그리고 certutil 명령어를 통해 apk 파일의 해시 값을 확인할 수 있다.

> certutil -hashfile zipaligned_release.apk MD5
MD5의 zipaligned_release.apk 해시:
d2a4de87a9cb4eaf571e8aa072153fdf
CertUtil: -hashfile 명령이 성공적으로 완료되었습니다.
> 
> certutil -hashfile zipaligned_release2.apk SHA1
SHA1의 zipaligned_release2.apk 해시:
4320ebab17236b3de03620681780c32fd8a79458
CertUtil: -hashfile 명령이 성공적으로 완료되었습니다.
>

매번 리패키징할 때마다 apktool > zipalign > apksigner 명령어를 반복적으로 실행해야 하기 때문에 자동화시킬 필요가 있다.

@ECHO off
TITLE Let's Repackaging !

@ECHO ---------------------------------------------------------------
@ECHO !                                                             !
@ECHO !                        Let's Koo00 !                        !
@ECHO !                                                             !
@ECHO ---------------------------------------------------------------
@ECHO.

REM 실행 전 Java 및 Build Tool 환경 변수 세팅 필요
REM keystore 생성 방법 : keytool -genkey -alias koooo -keyalg RSA -validity 20000 -keystore koooo.keystore

REM 리사이닝 툴 세팅
SET APKTOOL=apktool.jar
SET KEYSTORE=keystore's name
SET KEYPASS=keystore's password

:START
IF EXIST crack.apk (
	SET /p ANSWER="[-] Do you want to remove crack.apk first ? (Y/N) : "
)

IF "%ANSWER%" == "Y" (
	start /wait /b powershell -ExecutionPolicy -Command "rm crack.apk"
	@ECHO [!] Remove Done.
	@ECHO.
) ELSE (
	@ECHO [!] Pass !
	@ECHO.
)

SET /p APK="[*] Input APK's Name : "
@ECHO.
IF NOT EXIST %APK% (
	goto ERROR
)


IF EXIST %APK% (
	start /wait /b java -jar %APKTOOL% d -rf %APK% -o tmp
	@ECHO.
	@ECHO [!] Decomplie Done.
	@ECHO.
	
	start /wait /b java -jar %APKTOOL% b tmp -o tmp.apk
	@ECHO.
	@ECHO [!] Repackaging Done.
	
	start /wait zipalign -p -f -v 4 tmp.apk crack.apk
	@ECHO [!] Zipalign Done.
	
	cmd /c apksigner sign --ks %KEYSTORE% --ks-pass pass:%KEYPASS% crack.apk
	@ECHO [!] Resigning Done.
	
	@ECHO.
	@ECHO [!] All Done !
	@ECHO.
	
	start /b powershell -ExecutionPolicy -Command "rm -r tmp*"
	
	@ECHO [+] 인증서 소유자 : 
	start /wait /b powershell -ExecutionPolicy -Command "(keytool -printcert -jarfile crack.apk | select-object -index 4).toString().Split(':')[1].Trim()"
	@ECHO.
	
	@ECHO [+] 인증서 지문^(SHA1^) : 
	start /wait /b powershell -ExecutionPolicy -Command "(keytool -printcert -jarfile crack.apk | select-object -index 10).toString().Trim().ToLower() -split 'SHA1: ' -split ':' -join ''"
	@ECHO.
	
	@ECHO [+] %APK% MD5 : 
	start /wait /b powershell -ExecutionPolicy -Command "certutil -hashfile %APK% MD5 | select-object -index 1"
	@ECHO.
	
	@ECHO [+] %APK% SHA1 : 
	start /wait /b powershell -ExecutionPolicy -Command "certutil -hashfile %APK% SHA1 | select-object -index 1"
	@ECHO.
	
	@ECHO [+] crack.apk MD5 : 
	start /wait /b powershell -ExecutionPolicy -Command "certutil -hashfile crack.apk MD5 | select-object -index 1"
	@ECHO.
	
	@ECHO [+] crack.apk SHA1 : 
	start /wait /b powershell -ExecutionPolicy -Command "certutil -hashfile crack.apk SHA1 | select-object -index 1"
	@ECHO.
	
	start /wait /b powershell -ExecutionPolicy -Command "rm crack.apk.idsig"
	
	exit
)

:ERROR
@ECHO [!] This file doesn't exist... Please retry...
@ECHO.


배치 파일에는 APK 파일의 해시 값과 인증서 정보를 확인할 수 있는 스크립트를 추가했다.
스크립트를 실행시키면 리사이닝부터 APK 파일 정보까지 한 번에 해결할 수 있다!

나중에 앱 디컴파일 이후 MainActivity 에 Smali 코드를 삽입해서 Toast 를 띄우는 과정을 추가해서 파이썬으로 다시 짜봐야겠다!

profile
JFDI !

1개의 댓글

comment-user-thumbnail
2024년 11월 25일

Using apksigner is a straightforward process that involves signing your APK with a keystore and verifying the signature. Make sure to keep your geometry dash lite and key secure, as they are essential for updates to your app in the future.

답글 달기

관련 채용 정보