Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
M
Magisk
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
Magisk
Commits
e938e717
Commit
e938e717
authored
Jan 30, 2020
by
topjohnwu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor PatchAPK code
parent
2eed09ef
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
48 additions
and
99 deletions
+48
-99
a.java
app/src/main/java/a/a.java
+0
-10
ManagerUpgrade.kt
...java/com/topjohnwu/magisk/core/download/ManagerUpgrade.kt
+1
-1
Keygen.kt
app/src/main/java/com/topjohnwu/magisk/core/utils/Keygen.kt
+3
-18
PatchAPK.kt
...src/main/java/com/topjohnwu/magisk/core/utils/PatchAPK.kt
+44
-70
No files found.
app/src/main/java/a/a.java
View file @
e938e717
package
a
;
package
a
;
import
com.topjohnwu.magisk.core.utils.PatchAPK
;
import
com.topjohnwu.signing.BootSigner
;
import
com.topjohnwu.signing.BootSigner
;
public
class
a
{
public
class
a
{
@Deprecated
public
static
boolean
patchAPK
(
String
in
,
String
out
,
String
pkg
)
{
return
PatchAPK
.
patch
(
in
,
out
,
pkg
);
}
public
static
boolean
patchAPK
(
String
in
,
String
out
,
String
pkg
,
String
label
)
{
return
PatchAPK
.
patch
(
in
,
out
,
pkg
,
label
);
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
BootSigner
.
main
(
args
);
BootSigner
.
main
(
args
);
}
}
...
...
app/src/main/java/com/topjohnwu/magisk/core/download/ManagerUpgrade.kt
View file @
e938e717
...
@@ -27,7 +27,7 @@ private fun RemoteFileService.patch(apk: File, id: Int) {
...
@@ -27,7 +27,7 @@ private fun RemoteFileService.patch(apk: File, id: Int) {
.
setContentText
(
""
)
.
setContentText
(
""
)
}
}
val
patched
=
File
(
apk
.
parent
,
"patched.apk"
)
val
patched
=
File
(
apk
.
parent
,
"patched.apk"
)
PatchAPK
.
patch
(
apk
,
patched
,
packageName
,
applicationInfo
.
nonLocalizedLabel
.
toString
()
)
PatchAPK
.
patch
(
apk
.
path
,
patched
.
path
,
packageName
,
applicationInfo
.
nonLocalizedLabel
)
apk
.
delete
()
apk
.
delete
()
patched
.
renameTo
(
apk
)
patched
.
renameTo
(
apk
)
}
}
...
...
app/src/main/java/com/topjohnwu/magisk/core/utils/Keygen.kt
View file @
e938e717
package
com.topjohnwu.magisk.core.utils
package
com.topjohnwu.magisk.core.utils
import
android.content.Context
import
android.content.pm.PackageManager
import
android.content.pm.PackageManager
import
android.util.Base64
import
android.util.Base64
import
android.util.Base64OutputStream
import
android.util.Base64OutputStream
import
com.topjohnwu.magisk.core.Config
import
com.topjohnwu.magisk.core.Config
import
com.topjohnwu.magisk.core.utils.PatchAPK.ALPHANUM
import
com.topjohnwu.magisk.core.utils.PatchAPK.ALPHANUM
import
com.topjohnwu.magisk.di.koinModules
import
com.topjohnwu.signing.CryptoUtils.readCertificate
import
com.topjohnwu.signing.CryptoUtils.readCertificate
import
com.topjohnwu.signing.CryptoUtils.readPrivateKey
import
com.topjohnwu.signing.CryptoUtils.readPrivateKey
import
com.topjohnwu.superuser.internal.InternalUtils
import
org.bouncycastle.asn1.x500.X500Name
import
org.bouncycastle.asn1.x500.X500Name
import
org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
import
org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
import
org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder
import
org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder
import
org.bouncycastle.operator.jcajce.JcaContentSignerBuilder
import
org.bouncycastle.operator.jcajce.JcaContentSignerBuilder
import
org.koin.core.context.GlobalContext
import
org.koin.core.context.startKoin
import
timber.log.Timber
import
java.io.ByteArrayOutputStream
import
java.io.ByteArrayOutputStream
import
java.math.BigInteger
import
java.math.BigInteger
import
java.security.KeyPairGenerator
import
java.security.KeyPairGenerator
...
@@ -33,7 +29,7 @@ private interface CertKeyProvider {
...
@@ -33,7 +29,7 @@ private interface CertKeyProvider {
}
}
@Suppress
(
"DEPRECATION"
)
@Suppress
(
"DEPRECATION"
)
class
Keygen
:
CertKeyProvider
{
class
Keygen
(
context
:
Context
)
:
CertKeyProvider
{
companion
object
{
companion
object
{
private
const
val
ALIAS
=
"magisk"
private
const
val
ALIAS
=
"magisk"
...
@@ -70,9 +66,6 @@ class Keygen: CertKeyProvider {
...
@@ -70,9 +66,6 @@ class Keygen: CertKeyProvider {
}
}
init
{
init
{
// This object could possibly be accessed from an external app
// Get context from reflection into Android's framework
val
context
=
InternalUtils
.
getContext
()
val
pm
=
context
.
packageManager
val
pm
=
context
.
packageManager
val
info
=
pm
.
getPackageInfo
(
context
.
packageName
,
PackageManager
.
GET_SIGNATURES
)
val
info
=
pm
.
getPackageInfo
(
context
.
packageName
,
PackageManager
.
GET_SIGNATURES
)
val
sig
=
info
.
signatures
[
0
]
val
sig
=
info
.
signatures
[
0
]
...
@@ -104,14 +97,6 @@ class Keygen: CertKeyProvider {
...
@@ -104,14 +97,6 @@ class Keygen: CertKeyProvider {
}
}
private
fun
init
():
KeyStore
{
private
fun
init
():
KeyStore
{
GlobalContext
.
getOrNull
()
?:
{
// Invoked externally, do some basic initialization
startKoin
{
modules
(
koinModules
)
}
Timber
.
plant
(
Timber
.
DebugTree
())
}()
val
raw
=
Config
.
keyStoreRaw
val
raw
=
Config
.
keyStoreRaw
val
ks
=
KeyStore
.
getInstance
(
"PKCS12"
)
val
ks
=
KeyStore
.
getInstance
(
"PKCS12"
)
if
(
raw
.
isEmpty
())
{
if
(
raw
.
isEmpty
())
{
...
@@ -135,7 +120,7 @@ class Keygen: CertKeyProvider {
...
@@ -135,7 +120,7 @@ class Keygen: CertKeyProvider {
val
dname
=
X500Name
(
"CN=${randomString()}"
)
val
dname
=
X500Name
(
"CN=${randomString()}"
)
val
builder
=
JcaX509v3CertificateBuilder
(
dname
,
BigInteger
(
160
,
Random
()),
val
builder
=
JcaX509v3CertificateBuilder
(
dname
,
BigInteger
(
160
,
Random
()),
start
.
time
,
end
.
time
,
dname
,
kp
.
public
)
start
.
time
,
end
.
time
,
dname
,
kp
.
public
)
val
signer
=
JcaContentSignerBuilder
(
"SHA
256
WithRSA"
).
build
(
kp
.
private
)
val
signer
=
JcaContentSignerBuilder
(
"SHA
1
WithRSA"
).
build
(
kp
.
private
)
val
cert
=
JcaX509CertificateConverter
().
getCertificate
(
builder
.
build
(
signer
))
val
cert
=
JcaX509CertificateConverter
().
getCertificate
(
builder
.
build
(
signer
))
// Store them into keystore
// Store them into keystore
...
...
app/src/main/java/com/topjohnwu/magisk/core/utils/PatchAPK.kt
View file @
e938e717
...
@@ -3,7 +3,6 @@ package com.topjohnwu.magisk.core.utils
...
@@ -3,7 +3,6 @@ package com.topjohnwu.magisk.core.utils
import
android.content.Context
import
android.content.Context
import
android.os.Build.VERSION.SDK_INT
import
android.os.Build.VERSION.SDK_INT
import
android.widget.Toast
import
android.widget.Toast
import
com.topjohnwu.magisk.BuildConfig
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.R
import
com.topjohnwu.magisk.core.Config
import
com.topjohnwu.magisk.core.Config
import
com.topjohnwu.magisk.core.Const
import
com.topjohnwu.magisk.core.Const
...
@@ -11,14 +10,13 @@ import com.topjohnwu.magisk.core.Info
...
@@ -11,14 +10,13 @@ import com.topjohnwu.magisk.core.Info
import
com.topjohnwu.magisk.core.isRunningAsStub
import
com.topjohnwu.magisk.core.isRunningAsStub
import
com.topjohnwu.magisk.core.view.Notifications
import
com.topjohnwu.magisk.core.view.Notifications
import
com.topjohnwu.magisk.data.network.GithubRawServices
import
com.topjohnwu.magisk.data.network.GithubRawServices
import
com.topjohnwu.magisk.extensions.DynamicClassLoader
import
com.topjohnwu.magisk.extensions.get
import
com.topjohnwu.magisk.extensions.get
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.extensions.subscribeK
import
com.topjohnwu.magisk.extensions.writeTo
import
com.topjohnwu.magisk.extensions.writeTo
import
com.topjohnwu.signing.JarMap
import
com.topjohnwu.signing.JarMap
import
com.topjohnwu.signing.SignAPK
import
com.topjohnwu.signing.SignAPK
import
com.topjohnwu.superuser.Shell
import
com.topjohnwu.superuser.Shell
import
io.reactivex.
Completab
le
import
io.reactivex.
Sing
le
import
timber.log.Timber
import
timber.log.Timber
import
java.io.File
import
java.io.File
import
java.io.FileOutputStream
import
java.io.FileOutputStream
...
@@ -28,12 +26,13 @@ import java.security.SecureRandom
...
@@ -28,12 +26,13 @@ import java.security.SecureRandom
object
PatchAPK
{
object
PatchAPK
{
private
const
val
LOWERALPHA
=
"abcdefghijklmnopqrstuvwxyz"
private
const
val
ALPHA
=
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
private
val
UPPERALPHA
=
LOWERALPHA
.
toUpperCase
()
private
val
ALPHA
=
LOWERALPHA
+
UPPERALPHA
private
const
val
DIGITS
=
"0123456789"
private
const
val
DIGITS
=
"0123456789"
val
ALPHANUM
=
ALPHA
+
DIGITS
const
val
ALPHANUM
=
ALPHA
+
DIGITS
private
val
ALPHANUMDOTS
=
"$ALPHANUM............"
private
const
val
ALPHANUMDOTS
=
"$ALPHANUM............"
private
const
val
APP_ID
=
"com.topjohnwu.magisk"
private
const
val
APP_NAME
=
"Magisk Manager"
private
fun
genPackageName
(
prefix
:
String
,
length
:
Int
):
CharSequence
{
private
fun
genPackageName
(
prefix
:
String
,
length
:
Int
):
CharSequence
{
val
builder
=
StringBuilder
(
length
)
val
builder
=
StringBuilder
(
length
)
...
@@ -81,18 +80,40 @@ object PatchAPK {
...
@@ -81,18 +80,40 @@ object PatchAPK {
return
true
return
true
}
}
fun
patch
(
apk
:
String
,
out
:
String
,
pkg
:
CharSequence
,
label
:
CharSequence
):
Boolean
{
try
{
val
jar
=
JarMap
.
open
(
apk
)
val
je
=
jar
.
getJarEntry
(
Const
.
ANDROID_MANIFEST
)
val
xml
=
jar
.
getRawData
(
je
)
if
(!
findAndPatch
(
xml
,
APP_ID
,
pkg
)
||
!
findAndPatch
(
xml
,
APP_NAME
,
label
))
return
false
// Write apk changes
jar
.
getOutputStream
(
je
).
write
(
xml
)
val
keys
=
Keygen
(
get
())
SignAPK
.
sign
(
keys
.
cert
,
keys
.
key
,
jar
,
FileOutputStream
(
out
).
buffered
())
}
catch
(
e
:
Exception
)
{
Timber
.
e
(
e
)
return
false
}
return
true
}
private
fun
patchAndHide
(
context
:
Context
,
label
:
String
):
Boolean
{
private
fun
patchAndHide
(
context
:
Context
,
label
:
String
):
Boolean
{
val
src
=
if
(
!
isRunningAsStub
&&
SDK_INT
>=
28
&&
val
dlStub
=
!
isRunningAsStub
&&
SDK_INT
>=
28
&&
Info
.
env
.
magiskVersionCode
>=
Const
.
Version
.
PROVIDER_CONNECT
)
{
Info
.
env
.
magiskVersionCode
>=
Const
.
Version
.
PROVIDER_CONNECT
// If not running as stub, and we are compatible with stub, use stub
val
src
=
if
(
dlStub
)
{
val
stub
=
File
(
context
.
cacheDir
,
"stub.apk"
)
val
stub
=
File
(
context
.
cacheDir
,
"stub.apk"
)
val
svc
=
get
<
GithubRawServices
>()
val
svc
=
get
<
GithubRawServices
>()
runCatching
{
try
{
svc
.
fetchFile
(
Info
.
remote
.
stub
.
link
).
blockingGet
().
byteStream
().
use
{
svc
.
fetchFile
(
Info
.
remote
.
stub
.
link
).
blockingGet
().
byteStream
().
use
{
it
.
writeTo
(
stub
)
it
.
writeTo
(
stub
)
}
}
}
.
onFailure
{
}
catch
(
e
:
Exception
)
{
Timber
.
e
(
it
)
Timber
.
e
(
e
)
return
false
return
false
}
}
stub
.
path
stub
.
path
...
@@ -102,7 +123,7 @@ object PatchAPK {
...
@@ -102,7 +123,7 @@ object PatchAPK {
// Generate a new random package name and signature
// Generate a new random package name and signature
val
repack
=
File
(
context
.
cacheDir
,
"patched.apk"
)
val
repack
=
File
(
context
.
cacheDir
,
"patched.apk"
)
val
pkg
=
genPackageName
(
"com."
,
BuildConfig
.
APPLICATION
_ID
.
length
)
val
pkg
=
genPackageName
(
"com."
,
APP
_ID
.
length
)
Config
.
keyStoreRaw
=
""
Config
.
keyStoreRaw
=
""
if
(!
patch
(
src
,
repack
.
path
,
pkg
,
label
))
if
(!
patch
(
src
,
repack
.
path
,
pkg
,
label
))
...
@@ -115,67 +136,20 @@ object PatchAPK {
...
@@ -115,67 +136,20 @@ object PatchAPK {
Config
.
suManager
=
pkg
.
toString
()
Config
.
suManager
=
pkg
.
toString
()
Config
.
export
()
Config
.
export
()
Shell
.
su
(
"pm uninstall ${BuildConfig.APPLICATION_ID}"
).
submit
()
Shell
.
su
(
"pm uninstall $APP_ID"
).
submit
()
return
true
}
@JvmStatic
@JvmOverloads
fun
patch
(
apk
:
String
,
out
:
String
,
pkg
:
CharSequence
,
label
:
String
=
"Manager"
):
Boolean
{
try
{
val
jar
=
JarMap
.
open
(
apk
)
val
je
=
jar
.
getJarEntry
(
Const
.
ANDROID_MANIFEST
)
val
xml
=
jar
.
getRawData
(
je
)
if
(!
findAndPatch
(
xml
,
BuildConfig
.
APPLICATION_ID
,
pkg
)
||
!
findAndPatch
(
xml
,
"Magisk Manager"
,
label
))
return
false
// Write apk changes
jar
.
getOutputStream
(
je
).
write
(
xml
)
val
keys
=
Keygen
()
SignAPK
.
sign
(
keys
.
cert
,
keys
.
key
,
jar
,
FileOutputStream
(
out
).
buffered
())
}
catch
(
e
:
Exception
)
{
Timber
.
e
(
e
)
return
false
}
return
true
return
true
}
}
fun
patch
(
apk
:
File
,
out
:
File
,
pkg
:
CharSequence
,
label
:
String
):
Boolean
{
try
{
if
(
apk
.
length
()
<
1
shl
18
)
{
// APK is smaller than 256K, must be stub
return
patch
(
apk
.
path
,
out
.
path
,
pkg
,
label
)
}
// Try using the new APK to patch itself
val
loader
=
DynamicClassLoader
(
apk
)
val
cls
=
loader
.
loadClass
(
"a.a"
)
for
(
m
in
cls
.
declaredMethods
)
{
val
pars
=
m
.
parameterTypes
if
(
pars
.
size
==
4
&&
pars
[
0
]
==
String
::
class
.
java
)
{
return
m
.
invoke
(
null
,
apk
.
path
,
out
.
path
,
pkg
,
label
)
as
Boolean
}
}
throw
Exception
(
"No matching method found"
)
}
catch
(
e
:
Exception
)
{
Timber
.
e
(
e
)
// Fallback to use the current implementation
return
patch
(
apk
.
path
,
out
.
path
,
pkg
,
label
)
}
}
fun
hideManager
(
context
:
Context
,
label
:
String
)
{
fun
hideManager
(
context
:
Context
,
label
:
String
)
{
Completable
.
fromAction
{
val
progress
=
Notifications
.
progress
(
context
,
context
.
getString
(
R
.
string
.
hide_manager_title
))
val
progress
=
Notifications
.
progress
(
context
,
context
.
getString
(
R
.
string
.
hide_manager_title
))
Notifications
.
mgr
.
notify
(
Const
.
ID
.
HIDE_MANAGER_NOTIFICATION_ID
,
progress
.
build
())
Notifications
.
mgr
.
notify
(
Const
.
ID
.
HIDE_MANAGER_NOTIFICATION_ID
,
progress
.
build
())
if
(!
patchAndHide
(
context
,
label
))
Single
.
fromCallable
{
patchAndHide
(
context
,
label
)
}.
subscribeK
{
if
(!
it
)
Utils
.
toast
(
R
.
string
.
hide_manager_fail_toast
,
Toast
.
LENGTH_LONG
)
Utils
.
toast
(
R
.
string
.
hide_manager_fail_toast
,
Toast
.
LENGTH_LONG
)
Notifications
.
mgr
.
cancel
(
Const
.
ID
.
HIDE_MANAGER_NOTIFICATION_ID
)
Notifications
.
mgr
.
cancel
(
Const
.
ID
.
HIDE_MANAGER_NOTIFICATION_ID
)
}
.
subscribeK
()
}
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment