This commit is contained in:
particle-box
2026-01-23 20:22:47 +05:30
parent de4d8dac39
commit 327efafbe5
22 changed files with 449 additions and 819 deletions

View File

@@ -31,6 +31,7 @@ import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.Icon
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableLongStateOf
import androidx.compose.runtime.remember
@@ -80,6 +81,10 @@ class HomeAbout : Routes.Route() {
val tapCount = remember { mutableIntStateOf(0) }
val lastTapTime = remember { mutableLongStateOf(0L) }
LaunchedEffect(Unit) {
context.shortToast("Tap 5 times in this screen to see some magic 😉!")
}
Box(
modifier = Modifier
.fillMaxSize()

View File

@@ -54,6 +54,7 @@ import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.Notifications
import androidx.compose.material.icons.filled.Schedule
import androidx.compose.material.icons.filled.Settings
import androidx.compose.material.icons.outlined.Widgets
@@ -258,7 +259,8 @@ class HomeRootSection : Routes.Route() {
@Composable
private fun TopBarActionChip(
icon: ImageVector,
label: String,
label: String? = null,
contentDescription: String? = label,
onClick: () -> Unit,
) {
Surface(
@@ -274,15 +276,17 @@ class HomeRootSection : Routes.Route() {
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp)
) {
Icon(icon, contentDescription = label, tint = Color.White)
Text(
text = label,
color = Color.White,
fontSize = 13.sp,
fontWeight = FontWeight.Medium,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Icon(icon, contentDescription = contentDescription, tint = Color.White)
label?.let {
Text(
text = it,
color = Color.White,
fontSize = 13.sp,
fontWeight = FontWeight.Medium,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
}
}
}
}
@@ -888,18 +892,29 @@ class HomeRootSection : Routes.Route() {
.fillMaxWidth()
.padding(WindowInsets.statusBars.asPaddingValues())
.padding(horizontal = cardMargin, vertical = 8.dp),
horizontalArrangement = Arrangement.spacedBy(10.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
TopBarActionChip(
icon = Icons.Filled.Info,
label = "Announcements"
Row(
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalAlignment = Alignment.CenterVertically
) {
showAnnouncementsDialog = true
loadAnnouncements()
TopBarActionChip(
icon = Icons.Filled.Notifications,
label = null,
contentDescription = "Announcements"
) {
showAnnouncementsDialog = true
loadAnnouncements()
}
}
Row(
modifier = Modifier.wrapContentWidth(Alignment.End),
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalAlignment = Alignment.CenterVertically
) {
HomeActionChips()
}
Spacer(modifier = Modifier.weight(1f))
HomeActionChips()
}
Spacer(modifier = Modifier.height(12.dp))
HeroSection(

View File

@@ -1,3 +1,10 @@
## v1.2.0
- Fix: Prevent snap replay/missed audio voice call(thanks to RSR)
- Fix: Various messaging fixes for newer snap versions(thanks to RSR)
- New: Announcements feature(directly view important announcements right through the app!)
- Fix: Missing about page
- Fix: incorrect snap version instructions
## v1.1.2
- New: Chat Wallpaper Download(upstream commit)
- Fix: mappings error

434
native/rust/Cargo.lock generated
View File

@@ -4,9 +4,9 @@ version = 4
[[package]]
name = "adler2"
version = "2.0.1"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
[[package]]
name = "aes"
@@ -21,18 +21,24 @@ dependencies = [
[[package]]
name = "aho-corasick"
version = "1.1.4"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]]
name = "android_log-sys"
version = "0.3.2"
name = "android-tzdata"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d"
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
[[package]]
name = "android_log-sys"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937"
[[package]]
name = "android_logger"
@@ -56,9 +62,9 @@ dependencies = [
[[package]]
name = "autocfg"
version = "1.5.0"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
[[package]]
name = "base64"
@@ -68,15 +74,15 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "base64ct"
version = "1.8.3"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06"
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
[[package]]
name = "bitflags"
version = "2.10.0"
version = "2.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be"
[[package]]
name = "block-buffer"
@@ -89,9 +95,9 @@ dependencies = [
[[package]]
name = "bumpalo"
version = "3.19.1"
version = "3.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
[[package]]
name = "byteorder"
@@ -101,9 +107,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
version = "1.11.0"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
[[package]]
name = "bzip2"
@@ -127,11 +133,10 @@ dependencies = [
[[package]]
name = "cc"
version = "1.2.53"
version = "1.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "755d2fce177175ffca841e9a06afdb2c4ab0f593d53b4dee48147dfaade85932"
checksum = "c8293772165d9345bdaaa39b45b2109591e63fe5e6fbc23c6ff930a048aa310b"
dependencies = [
"find-msvc-tools",
"jobserver",
"libc",
"shlex",
@@ -145,9 +150,9 @@ checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]]
name = "cfg-if"
version = "1.0.4"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "cfg_aliases"
@@ -157,13 +162,14 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
[[package]]
name = "chrono"
version = "0.4.43"
version = "0.4.39"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118"
checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825"
dependencies = [
"android-tzdata",
"iana-time-zone",
"num-traits",
"windows-link",
"windows-targets 0.52.6",
]
[[package]]
@@ -215,9 +221,9 @@ dependencies = [
[[package]]
name = "crc32fast"
version = "1.5.0"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
dependencies = [
"cfg-if",
]
@@ -262,7 +268,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.96",
]
[[package]]
@@ -337,9 +343,9 @@ dependencies = [
[[package]]
name = "env_filter"
version = "0.1.4"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2"
checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0"
dependencies = [
"log",
"regex",
@@ -347,12 +353,12 @@ dependencies = [
[[package]]
name = "errno"
version = "0.3.14"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
dependencies = [
"libc",
"windows-sys 0.61.2",
"windows-sys 0.59.0",
]
[[package]]
@@ -361,17 +367,11 @@ version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
[[package]]
name = "find-msvc-tools"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8591b0bcc8a98a64310a2fae1bb3e9b8564dd10e381e6e28010fde8e8e8568db"
[[package]]
name = "flate2"
version = "1.1.8"
version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b375d6465b98090a5f25b1c7703f3859783755aa9a80433b36e0379a3ec2f369"
checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c"
dependencies = [
"crc32fast",
"miniz_oxide",
@@ -389,38 +389,15 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.17"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "getrandom"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
dependencies = [
"cfg-if",
"libc",
"r-efi",
"wasip2",
]
[[package]]
name = "goblin"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4db6758c546e6f81f265638c980e5e84dfbda80cfd8e89e02f83454c8e8124bd"
dependencies = [
"log",
"plain",
"scroll",
]
[[package]]
name = "goldberg"
version = "0.1.0"
@@ -451,15 +428,14 @@ dependencies = [
[[package]]
name = "iana-time-zone"
version = "0.1.64"
version = "0.1.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"log",
"wasm-bindgen",
"windows-core",
]
@@ -484,9 +460,9 @@ dependencies = [
[[package]]
name = "itoa"
version = "1.0.17"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674"
[[package]]
name = "jni"
@@ -512,19 +488,18 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "jobserver"
version = "0.1.34"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33"
checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
dependencies = [
"getrandom 0.3.4",
"libc",
]
[[package]]
name = "js-sys"
version = "0.3.85"
version = "0.3.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3"
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
dependencies = [
"once_cell",
"wasm-bindgen",
@@ -532,9 +507,9 @@ dependencies = [
[[package]]
name = "libc"
version = "0.2.180"
version = "0.2.169"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc"
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
[[package]]
name = "linux-raw-sys"
@@ -544,24 +519,23 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
[[package]]
name = "log"
version = "0.4.29"
version = "0.4.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f"
[[package]]
name = "memchr"
version = "2.7.6"
version = "2.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
[[package]]
name = "miniz_oxide"
version = "0.8.9"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924"
dependencies = [
"adler2",
"simd-adler32",
]
[[package]]
@@ -604,9 +578,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.21.3"
version = "1.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775"
[[package]]
name = "password-hash"
@@ -649,15 +623,9 @@ dependencies = [
[[package]]
name = "pkg-config"
version = "0.3.32"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
[[package]]
name = "plain"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
[[package]]
name = "powerfmt"
@@ -667,18 +635,18 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "ppv-lite86"
version = "0.2.21"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04"
dependencies = [
"zerocopy",
]
[[package]]
name = "proc-macro2"
version = "1.0.106"
version = "1.0.93"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
dependencies = [
"unicode-ident",
]
@@ -718,7 +686,6 @@ dependencies = [
"crc32fast",
"dobby-rs",
"ed25519-dalek",
"goblin",
"goldberg",
"jni",
"libc",
@@ -732,24 +699,18 @@ dependencies = [
"serde_json",
"sha2",
"zip",
"zstd 0.13.3",
"zstd 0.13.2",
]
[[package]]
name = "quote"
version = "1.0.43"
version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a"
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
[[package]]
name = "r-efi"
version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "rand"
version = "0.8.5"
@@ -777,14 +738,14 @@ version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.17",
"getrandom",
]
[[package]]
name = "regex"
version = "1.12.2"
version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
dependencies = [
"aho-corasick",
"memchr",
@@ -794,9 +755,9 @@ dependencies = [
[[package]]
name = "regex-automata"
version = "0.4.13"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
dependencies = [
"aho-corasick",
"memchr",
@@ -805,9 +766,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.8.8"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
[[package]]
name = "rustc_version"
@@ -820,9 +781,9 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.38.44"
version = "0.38.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6"
dependencies = [
"bitflags",
"errno",
@@ -833,9 +794,15 @@ dependencies = [
[[package]]
name = "rustversion"
version = "1.0.22"
version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "same-file"
@@ -846,26 +813,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "scroll"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1257cd4248b4132760d6524d6dda4e053bc648c9070b960929bf50cfb1e7add"
dependencies = [
"scroll_derive",
]
[[package]]
name = "scroll_derive"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed76efe62313ab6610570951494bdaa81568026e0318eaa55f167de70eeea67d"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
]
[[package]]
name = "semver"
version = "1.0.27"
@@ -874,45 +821,34 @@ checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
[[package]]
name = "serde"
version = "1.0.228"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
dependencies = [
"serde_core",
"serde_derive",
]
[[package]]
name = "serde_core"
version = "1.0.228"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.228"
version = "1.0.217"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.96",
]
[[package]]
name = "serde_json"
version = "1.0.149"
version = "1.0.135"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9"
dependencies = [
"itoa",
"memchr",
"ryu",
"serde",
"serde_core",
"zmij",
]
[[package]]
@@ -952,12 +888,6 @@ dependencies = [
"rand_core",
]
[[package]]
name = "simd-adler32"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
[[package]]
name = "spki"
version = "0.7.3"
@@ -987,9 +917,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.114"
version = "2.0.96"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a"
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
dependencies = [
"proc-macro2",
"quote",
@@ -1013,27 +943,27 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.96",
]
[[package]]
name = "time"
version = "0.3.45"
version = "0.3.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd"
checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
dependencies = [
"deranged",
"num-conv",
"powerfmt",
"serde_core",
"serde",
"time-core",
]
[[package]]
name = "time-core"
version = "0.1.7"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca"
checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
[[package]]
name = "typenum"
@@ -1043,9 +973,9 @@ checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
[[package]]
name = "unicode-ident"
version = "1.0.22"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
[[package]]
name = "version_check"
@@ -1065,37 +995,41 @@ dependencies = [
[[package]]
name = "wasi"
version = "0.11.1+wasi-snapshot-preview1"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
[[package]]
name = "wasip2"
version = "1.0.2+wasi-0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5"
dependencies = [
"wit-bindgen",
]
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.108"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566"
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
dependencies = [
"bumpalo",
"log",
"proc-macro2",
"quote",
"syn 2.0.96",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.108"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608"
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1103,92 +1037,42 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.108"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55"
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
dependencies = [
"bumpalo",
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.96",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.108"
version = "0.2.100"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12"
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
dependencies = [
"unicode-ident",
]
[[package]]
name = "winapi-util"
version = "0.1.11"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [
"windows-sys 0.61.2",
"windows-sys 0.59.0",
]
[[package]]
name = "windows-core"
version = "0.62.2"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [
"windows-implement",
"windows-interface",
"windows-link",
"windows-result",
"windows-strings",
]
[[package]]
name = "windows-implement"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
]
[[package]]
name = "windows-interface"
version = "0.59.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
]
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-result"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-strings"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
dependencies = [
"windows-link",
"windows-targets 0.52.6",
]
[[package]]
@@ -1209,15 +1093,6 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-sys"
version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
dependencies = [
"windows-link",
]
[[package]]
name = "windows-targets"
version = "0.42.2"
@@ -1339,30 +1214,25 @@ version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "wit-bindgen"
version = "0.51.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5"
[[package]]
name = "zerocopy"
version = "0.8.33"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd"
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
dependencies = [
"byteorder",
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.33"
version = "0.7.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1"
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.114",
"syn 2.0.96",
]
[[package]]
@@ -1391,12 +1261,6 @@ dependencies = [
"zstd 0.11.2+zstd.1.5.2",
]
[[package]]
name = "zmij"
version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfcd145825aace48cff44a8844de64bf75feec3080e0aa5cdbde72961ae51a65"
[[package]]
name = "zstd"
version = "0.11.2+zstd.1.5.2"
@@ -1408,11 +1272,11 @@ dependencies = [
[[package]]
name = "zstd"
version = "0.13.3"
version = "0.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9"
dependencies = [
"zstd-safe 7.2.4",
"zstd-safe 7.2.1",
]
[[package]]
@@ -1427,18 +1291,18 @@ dependencies = [
[[package]]
name = "zstd-safe"
version = "7.2.4"
version = "7.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059"
dependencies = [
"zstd-sys",
]
[[package]]
name = "zstd-sys"
version = "2.0.16+zstd.1.5.7"
version = "2.0.13+zstd.1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748"
checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa"
dependencies = [
"cc",
"pkg-config",

View File

@@ -27,7 +27,6 @@ sha2 = "0.10"
zip = "0.6.6"
base64 = "0.22.1"
ed25519-dalek = { version = "2.1.1", default-features = true, features = ["std"] }
goblin = "0.10.4"
[build-dependencies]
cc = "1.0"

View File

@@ -24,16 +24,11 @@ pub static CLIENT_MODULE: Lazy<MappedLib> = Lazy::new(|| {
pub fn set_native_lib_instance(instance: GlobalRef) {
NATIVE_LIB_INSTANCE
.set(instance)
.expect("NativeLib instance already set");
NATIVE_LIB_INSTANCE.set(instance).expect("NativeLib instance already set");
}
pub fn native_lib_instance() -> GlobalRef {
NATIVE_LIB_INSTANCE
.get()
.expect("NativeLib instance not set")
.clone()
NATIVE_LIB_INSTANCE.get().expect("NativeLib instance not set").clone()
}
pub fn set_java_vm(vm: *mut jni::sys::JavaVM) {
@@ -42,16 +37,13 @@ pub fn set_java_vm(vm: *mut jni::sys::JavaVM) {
pub fn java_vm() -> JavaVM {
unsafe {
JavaVM::from_raw(*JAVA_VM.get().expect("JavaVM not set") as *mut jni::sys::JavaVM)
.expect("Failed to get JavaVM")
JavaVM::from_raw(*JAVA_VM.get().expect("JavaVM not set") as *mut jni::sys::JavaVM).expect("Failed to get JavaVM")
}
}
pub fn attach_jni_env(block: impl FnOnce(&mut jni::JNIEnv)) {
let jvm = java_vm();
let mut env: jni::AttachGuard = jvm
.attach_current_thread()
.expect("Failed to attach to current thread");
let mut env: jni::AttachGuard = jvm.attach_current_thread().expect("Failed to attach to current thread");
block(&mut env);
}
}

View File

@@ -1,16 +1,11 @@
use crate::{secstrings, util::get_jni_string};
use jni::{objects::JObject, JNIEnv};
use std::{error::Error, sync::Mutex};
use jni::{objects::JObject, JNIEnv};
use crate::{secstrings, util::get_jni_string};
static NATIVE_CONFIG: Mutex<Option<NativeConfig>> = Mutex::new(None);
pub fn native_config() -> NativeConfig {
NATIVE_CONFIG
.lock()
.unwrap()
.as_ref()
.expect("NativeConfig not loaded")
.clone()
NATIVE_CONFIG.lock().unwrap().as_ref().expect("NativeConfig not loaded").clone()
}
#[derive(Debug, Clone)]
@@ -32,13 +27,11 @@ impl NativeConfig {
macro_rules! get_string {
($field:expr) => {
match env.get_field(&obj, $field, "Ljava/lang/String;")?.l()? {
jstring => {
if !jstring.is_null() {
Some(get_jni_string(env, jstring.into())?)
} else {
None
}
}
jstring => if !jstring.is_null() {
Some(get_jni_string(env, jstring.into())?)
} else {
None
},
}
};
}
@@ -80,11 +73,10 @@ pub fn get_blocker_config() -> BlockerConfig {
}
}
pub fn load_config(mut env: JNIEnv, _class: JObject, obj: JObject) {
NATIVE_CONFIG
.lock()
.unwrap()
.replace(NativeConfig::new(&mut env, obj).expect("Failed to load NativeConfig"));
pub fn load_config(mut env: JNIEnv, _class: JObject, obj: JObject) {
NATIVE_CONFIG.lock().unwrap().replace(
NativeConfig::new(&mut env, obj).expect("Failed to load NativeConfig")
);
info!("Config loaded {:?}", native_config());
}

View File

@@ -36,3 +36,15 @@ macro_rules! dobby_hook {
};
}
#[macro_export]
macro_rules! dobby_hook_sym {
($lib:expr, $sym:expr, $hook:expr) => {
if let Some(hook_symbol) = dobby_rs::resolve_symbol($lib, $sym) {
crate::dobby_hook!(hook_symbol, $hook);
debug!("hooked symbol: {}", $sym);
} else {
panic!("Failed to resolve symbol: {}", $sym);
}
};
}

View File

@@ -3,11 +3,11 @@ extern crate log;
mod common;
mod config;
mod hook;
mod mapped_lib;
mod sig;
mod util;
mod mapped_lib;
mod config;
mod sig;
mod modules;
mod security;
@@ -15,10 +15,7 @@ mod secstrings;
use android_logger::Config;
use log::LevelFilter;
use modules::{
custom_font_hook, duplex_hook, fstat_hook, linker_hook, sqlite_hook, unary_call_hook,
valdi_hook,
};
use modules::{valdi_hook, custom_font_hook, duplex_hook, fstat_hook, linker_hook, sqlite_hook, unary_call_hook};
use jni::{JNIEnv, JavaVM, NativeMethod};
use jni::objects::{JObject, JString, JClass, JValue};
@@ -169,11 +166,10 @@ fn init(mut env: JNIEnv, _class: JObject, signature_cache: JString) -> jstring {
let start_time = std::time::Instant::now();
// load signature cache
if !signature_cache.is_null() {
let sig_cache_str = util::get_jni_string(&mut env, signature_cache)
.expect("Failed to convert mappings to string");
let sig_cache_str = util::get_jni_string(&mut env, signature_cache).expect("Failed to convert mappings to string");
if let Ok(signature_cache) = serde_json::from_str(sig_cache_str.as_str()) {
sig::add_signatures(signature_cache);
} else {
@@ -181,11 +177,7 @@ fn init(mut env: JNIEnv, _class: JObject, signature_cache: JString) -> jstring {
}
}
common::set_native_lib_instance(
env.new_global_ref(_class)
.ok()
.expect("Failed to create global ref"),
);
common::set_native_lib_instance(env.new_global_ref(_class).ok().expect("Failed to create global ref"));
let _ = common::CLIENT_MODULE;

View File

@@ -24,24 +24,21 @@ impl MappedLib {
}
pub fn search(&mut self) -> Result<&Self, Box<dyn Error>> {
procfs::process::Process::myself()?
.maps()?
.iter()
.for_each(|map| {
let pathname = &map.pathname;
procfs::process::Process::myself()?.maps()?.iter().for_each(|map| {
let pathname = &map.pathname;
if let MMapPath::Path(path_buffer) = pathname {
let path = path_buffer.to_string_lossy();
if let MMapPath::Path(path_buffer) = pathname {
let path = path_buffer.to_string_lossy();
if path.contains(&self.name) {
self.regions.push(MappedRegion {
start: map.address.0,
end: map.address.1,
perms: map.perms,
});
}
if path.contains(&self.name) {
self.regions.push(MappedRegion {
start: map.address.0,
end: map.address.1,
perms: map.perms,
});
}
});
}
});
if self.regions.is_empty() {
return Err(format!("No regions found for {}", self.name).into());

View File

@@ -2,41 +2,33 @@ use std::{ffi::CStr, fs};
use nix::libc::{self, c_uint};
use crate::{config, def_hook, dobby_hook, modules::util::elf};
use crate::{config, def_hook, dobby_hook_sym};
def_hook!(open_hook, i32, |path: *const u8,
flags: i32,
mode: c_uint| {
if let Ok(pathname) = CStr::from_ptr(path).to_str() {
if pathname == "/system/fonts/NotoColorEmoji.ttf" {
if let Some(font_path) = config::native_config().custom_emoji_font_path {
if fs::metadata(&font_path).is_ok() {
return libc::openat(
libc::AT_FDCWD,
font_path.as_ptr() as *const u8,
flags,
mode,
);
} else {
warn!("custom emoji font path does not exist: {}", font_path);
def_hook!(
open_hook,
i32,
|path: *const u8, flags: i32, mode: c_uint| {
if let Ok(pathname) = CStr::from_ptr(path).to_str() {
if pathname == "/system/fonts/NotoColorEmoji.ttf" {
if let Some(font_path) = config::native_config().custom_emoji_font_path {
if fs::metadata(&font_path).is_ok() {
return libc::openat(libc::AT_FDCWD, font_path.as_ptr() as *const u8, flags, mode);
} else {
warn!("custom emoji font path does not exist: {}", font_path);
}
}
}
}
}
open_hook_original.unwrap()(path, flags, mode)
});
open_hook_original.unwrap()(path, flags, mode)
}
);
pub fn init() {
if config::native_config().custom_emoji_font_path.is_none() {
return;
}
let libc = elf::Elf::from_maps("/libc.so").expect("Failed to find libc.so in maps");
if let Some(ptr) = libc.get_symbol_address("open") {
dobby_hook!(ptr as _, open_hook);
} else {
panic!("Failed to find open symbol");
}
}
dobby_hook_sym!("libc.so", "open", open_hook);
}

View File

@@ -4,6 +4,7 @@ use jni::{objects::JObject, sys::jboolean, JNIEnv};
use crate::{common, def_hook, dobby_hook, util::get_jni_string};
def_hook!(
is_same_object,
jboolean,
@@ -19,15 +20,9 @@ def_hook!(
if !env.is_instance_of(&obj1, class).unwrap() {
return is_same_object_original.unwrap()(env, obj1, obj2);
}
let obj1_class_name = env
.call_method(&obj1, "getName", "()Ljava/lang/String;", &[])
.unwrap()
.l()
.unwrap()
.into();
let class_name =
get_jni_string(&mut env, obj1_class_name).expect("Failed to get class name");
let obj1_class_name = env.call_method(&obj1, "getName", "()Ljava/lang/String;", &[]).unwrap().l().unwrap().into();
let class_name = get_jni_string(&mut env, obj1_class_name).expect("Failed to get class name");
if class_name.contains("com.snapchat.client.duplex.MessageHandler") {
debug!("is_same_object hook: MessageHandler");
@@ -38,11 +33,9 @@ def_hook!(
}
);
pub fn init() {
common::attach_jni_env(|env| {
dobby_hook!(
(**env.get_native_interface()).IsSameObject.unwrap() as *mut c_void,
is_same_object
);
dobby_hook!((**env.get_native_interface()).IsSameObject.unwrap() as *mut c_void, is_same_object);
});
}
}

View File

@@ -1,48 +1,44 @@
use crate::{
config::{self, native_config},
def_hook, dobby_hook,
modules::util::elf,
};
use nix::libc;
use std::fs;
def_hook!(fstat_hook, i32, |fd: i32, statbuf: *mut libc::stat| {
if let Ok(link) = fs::read_link("/proc/self/fd/".to_owned() + &fd.to_string()) {
let link_str = link.to_string_lossy();
let config = native_config();
if config.disable_metrics && link_str.contains("files/blizzardv2/queues") {
if libc::unlink((link_str.to_string() + "\0").as_ptr()) == -1 {
warn!("Failed to unlink {}", link_str);
}
return -1;
}
use nix::libc;
if config.disable_bitmoji {
if link_str.contains("com.snap.file_manager_4_SCContent") {
use crate::{config::{self, native_config}, def_hook, dobby_hook_sym};
def_hook!(
fstat_hook,
i32,
|fd: i32, statbuf: *mut libc::stat| {
if let Ok(link) = fs::read_link("/proc/self/fd/".to_owned() + &fd.to_string()) {
let link_str = link.to_string_lossy();
let config = native_config();
if config.disable_metrics && link_str.contains("files/blizzardv2/queues") {
if libc::unlink((link_str.to_string() + "\0").as_ptr()) == -1 {
warn!("Failed to unlink {}", link_str);
}
return -1;
}
if link_str.contains("/files/file_manager/") {
let lower = link_str.to_lowercase();
if lower.contains("bitmoji") {
if config.disable_bitmoji {
if link_str.contains("com.snap.file_manager_4_SCContent") {
return -1;
}
if link_str.contains("/files/file_manager/") {
let lower = link_str.to_lowercase();
if lower.contains("bitmoji") {
return -1;
}
}
}
}
}
fstat_hook_original.unwrap()(fd, statbuf)
});
fstat_hook_original.unwrap()(fd, statbuf)
}
);
pub fn init() {
let config = config::native_config();
if config.disable_metrics || config.disable_bitmoji {
let libc = elf::Elf::from_maps("/libc.so").expect("Failed to find libc.so in maps");
if let Some(ptr) = libc.get_symbol_address("fstat") {
dobby_hook!(ptr as _, fstat_hook);
} else {
panic!("Failed to find fstat symbol");
}
dobby_hook_sym!("libc.so", "fstat", fstat_hook);
}
}
}

View File

@@ -1,20 +1,12 @@
use std::{
collections::HashMap,
ffi::{c_void, CStr},
sync::Mutex,
};
use std::{collections::HashMap, ffi::{c_void, CStr}, sync::Mutex};
use jni::{
objects::{JByteArray, JString},
JNIEnv,
};
use jni::{objects::{JByteArray, JString}, JNIEnv};
use nix::libc;
use once_cell::sync::Lazy;
use crate::{def_hook, dobby_hook, modules::util::elf};
use crate::{def_hook, dobby_hook_sym};
static SHARED_LIBRARIES: Lazy<Mutex<HashMap<String, Box<Vec<i8>>>>> =
Lazy::new(|| Mutex::new(HashMap::new()));
static SHARED_LIBRARIES: Lazy<Mutex<HashMap<String, Box<Vec<i8>>>>> = Lazy::new(|| Mutex::new(HashMap::new()));
def_hook!(
linker_openat,
@@ -25,13 +17,8 @@ def_hook!(
if let Some(content) = SHARED_LIBRARIES.lock().unwrap().remove(&pathname_str) {
let memfd = libc::syscall(libc::SYS_memfd_create, "jit-cache\0".as_ptr(), 0) as i32;
let content = content.into_boxed_slice();
if libc::write(
memfd,
content.as_ptr() as *const c_void,
content.len() as libc::size_t,
) == -1
{
if libc::write(memfd, content.as_ptr() as *const c_void, content.len() as libc::size_t) == -1 {
panic!("failed to write to memfd");
}
@@ -49,44 +36,25 @@ def_hook!(
}
);
pub fn add_linker_shared_library(
mut env: JNIEnv,
_: *mut c_void,
path: JString,
content: JByteArray,
) {
pub fn add_linker_shared_library(mut env: JNIEnv, _: *mut c_void, path: JString, content: JByteArray) {
let path = env.get_string(&path).unwrap().to_str().unwrap().to_string();
let content_length = env
.get_array_length(&content)
.expect("Failed to get array length");
let content_length = env.get_array_length(&content).expect("Failed to get array length");
let mut content_buffer = Box::new(vec![0i8; content_length as usize]);
env.get_byte_array_region(content, 0, content_buffer.as_mut_slice())
.expect("Failed to get byte array region");
env.get_byte_array_region(content, 0, content_buffer.as_mut_slice()).expect("Failed to get byte array region");
debug!("added shared library: {}", path);
SHARED_LIBRARIES
.lock()
.unwrap()
.insert(path, content_buffer);
SHARED_LIBRARIES.lock().unwrap().insert(path, content_buffer);
}
pub fn init() {
let linker = {
#[cfg(target_arch = "aarch64")]
{
elf::Elf::from_maps("/linker64").expect("Failed to find linker64 in maps")
}
#[cfg(target_arch = "arm")]
{
elf::Elf::from_maps("/linker").expect("Failed to find linker in maps")
}
};
if let Some(ptr) = linker.get_symbol_address("__dl___openat") {
dobby_hook!(ptr as _, linker_openat);
} else {
panic!("Failed to find open symbol");
#[cfg(target_arch = "aarch64")]
{
dobby_hook_sym!("linker64", "__dl___openat", linker_openat);
}
#[cfg(target_arch = "arm")]
{
dobby_hook_sym!("linker", "__dl___openat", linker_openat);
}
}

View File

@@ -1,8 +1,8 @@
pub mod custom_font_hook;
pub mod duplex_hook;
pub mod fstat_hook;
pub mod linker_hook;
pub mod sqlite_hook;
pub mod unary_call_hook;
pub mod util;
pub mod linker_hook;
pub mod duplex_hook;
pub mod sqlite_hook;
pub mod fstat_hook;
pub mod unary_call_hook;
pub mod valdi_hook;
pub mod custom_font_hook;

View File

@@ -1,34 +1,25 @@
use std::{
collections::HashMap,
ffi::{c_void, CStr},
mem::size_of,
ptr::addr_of_mut,
sync::Mutex,
};
use std::{collections::HashMap, ffi::{c_void, CStr}, mem::size_of, ptr::addr_of_mut, sync::Mutex};
use jni::{
objects::{JObject, JString},
JNIEnv,
};
use jni::{objects::{JObject, JString}, JNIEnv};
use nix::libc::{self, pthread_mutex_t};
use once_cell::sync::Lazy;
use crate::{common, def_hook, dobby_hook, sig, util::get_jni_string};
#[repr(C)]
#[derive(Clone, Copy, Debug)]
struct Sqlite3Mutex {
mutex: pthread_mutex_t,
mutex: pthread_mutex_t
}
#[repr(C)]
struct Sqlite3 {
pad: [u8; 3 * size_of::<usize>()],
mutex: *mut Sqlite3Mutex,
mutex: *mut Sqlite3Mutex
}
static SQLITE3_MUTEX_MAP: Lazy<Mutex<HashMap<String, pthread_mutex_t>>> =
Lazy::new(|| Mutex::new(HashMap::new()));
static SQLITE3_MUTEX_MAP: Lazy<Mutex<HashMap<String, pthread_mutex_t>>> = Lazy::new(|| Mutex::new(HashMap::new()));
def_hook!(
sqlite3_open,
@@ -40,38 +31,27 @@ def_hook!(
let sqlite3_mutex = (**pp_db).mutex;
if sqlite3_mutex != std::ptr::null_mut() {
let filename = CStr::from_ptr(filename)
.to_string_lossy()
.to_string()
.split("/")
.last()
.expect("Failed to get filename")
.to_string();
let filename = CStr::from_ptr(filename).to_string_lossy().to_string().split("/").last().expect("Failed to get filename").to_string();
debug!("sqlite3_open hook {:?}", filename);
SQLITE3_MUTEX_MAP
.lock()
.unwrap()
.insert(filename, (*sqlite3_mutex).mutex);
SQLITE3_MUTEX_MAP.lock().unwrap().insert(
filename,
(*sqlite3_mutex).mutex
);
}
}
result
}
}
);
pub fn lock_database(mut env: JNIEnv, _: *mut c_void, filename: JString, runnable: JObject) {
let database_filename =
get_jni_string(&mut env, filename).expect("Failed to get database filename");
let mutex = SQLITE3_MUTEX_MAP
.lock()
.unwrap()
.get(&database_filename)
.map(|mutex| *mutex);
let database_filename = get_jni_string(&mut env, filename).expect("Failed to get database filename");
let mutex = SQLITE3_MUTEX_MAP.lock().unwrap().get(&database_filename).map(|mutex| *mutex);
let call_runnable = || {
env.call_method(runnable, "run", "()V", &[])
.expect("Failed to call run method");
env.call_method(runnable, "run", "()V", &[]).expect("Failed to call run method");
};
if let Some(mut mutex) = mutex {
@@ -91,17 +71,16 @@ pub fn lock_database(mut env: JNIEnv, _: *mut c_void, filename: JString, runnabl
}
}
pub fn init() {
if let Some(signature) = sig::find_signature(
&common::CLIENT_MODULE,
"FF FF 00 A9 3F 00 00 F9",
-0x3C,
"9A 46 90 46 78 44 89 46 05 68",
-0xd,
&common::CLIENT_MODULE,
"FF FF 00 A9 3F 00 00 F9", -0x3C,
"9A 46 90 46 78 44 89 46 05 68",-0xd
) {
debug!("Found sqlite3_open signature: {:#x}", signature);
dobby_hook!(signature as *mut c_void, sqlite3_open);
} else {
panic!("Failed to find sqlite3_open signature");
warn!("Failed to find sqlite3_open signature");
}
}
}

View File

@@ -1,23 +1,17 @@
use std::ffi::{c_void, CStr};
use jni::{
objects::{JByteArray, JMethodID, JValue},
signature::ReturnType,
};
use jni::{objects::{JByteArray, JMethodID, JValue}, signature::ReturnType};
use nix::libc;
use once_cell::sync::OnceCell;
use crate::{
common::{self},
def_hook, dobby_hook, sig,
};
use crate::{common::{self}, def_hook, dobby_hook, sig};
#[repr(C)]
#[derive(Copy, Clone)]
struct SliceByteBuffer {
struct RefCountedSliceByteBuffer {
ref_counter: *mut c_void,
length: usize,
data: *mut u8,
data: *mut u8
}
#[repr(C)]
@@ -25,7 +19,7 @@ struct GrpcByteBuffer {
reserved: *mut c_void,
type_: *mut c_void,
compression: *mut c_void,
slice_buffer: *mut SliceByteBuffer,
slice_buffer: *mut RefCountedSliceByteBuffer
}
static NATIVE_LIB_ON_UNARY_CALL_METHOD: OnceCell<JMethodID> = OnceCell::new();
@@ -33,12 +27,7 @@ static NATIVE_LIB_ON_UNARY_CALL_METHOD: OnceCell<JMethodID> = OnceCell::new();
def_hook!(
unary_call,
*mut c_void,
|unk1: *mut c_void,
uri: *const u8,
grpc_byte_buffer: *mut *mut GrpcByteBuffer,
unk4: *mut c_void,
unk5: *mut c_void,
unk6: *mut c_void| {
|unk1: *mut c_void, uri: *const u8, grpc_byte_buffer: *mut *mut GrpcByteBuffer, unk4: *mut c_void, unk5: *mut c_void, unk6: *mut c_void| {
macro_rules! call_original {
() => {
unary_call_original.unwrap()(unk1, uri, grpc_byte_buffer, unk4, unk5, unk6)
@@ -56,73 +45,45 @@ def_hook!(
let mut env = java_vm.get_env().expect("Failed to get JNIEnv");
let slice_buffer_length = slice_buffer.length as usize;
let jni_buffer = env
.new_byte_array(slice_buffer_length as i32)
.expect("Failed to create new byte array");
env.set_byte_array_region(
&jni_buffer,
0,
std::slice::from_raw_parts(slice_buffer.data as *const i8, slice_buffer_length),
)
.expect("Failed to set byte array region");
let jni_buffer = env.new_byte_array(slice_buffer_length as i32).expect("Failed to create new byte array");
env.set_byte_array_region(&jni_buffer, 0, std::slice::from_raw_parts(slice_buffer.data as *const i8, slice_buffer_length)).expect("Failed to set byte array region");
let uri_str = CStr::from_ptr(uri).to_str().unwrap();
let native_request_data_object = env
.call_method_unchecked(
common::native_lib_instance(),
NATIVE_LIB_ON_UNARY_CALL_METHOD.get().unwrap(),
ReturnType::Object,
&[
JValue::from(&env.new_string(uri_str).unwrap()).as_jni(),
JValue::from(&jni_buffer).as_jni(),
],
)
.expect("Failed to call onNativeUnaryCall method")
.l()
.unwrap();
let native_request_data_object = env.call_method_unchecked(
common::native_lib_instance(),
NATIVE_LIB_ON_UNARY_CALL_METHOD.get().unwrap(),
ReturnType::Object,
&[
JValue::from(&env.new_string(uri_str).unwrap()).as_jni(),
JValue::from(&jni_buffer).as_jni()
]
).expect("Failed to call onNativeUnaryCall method").l().unwrap();
if native_request_data_object.is_null() {
return call_original!();
}
let is_canceled = env
.get_field(&native_request_data_object, "canceled", "Z")
.expect("Failed to get canceled field")
.z()
.unwrap();
let is_canceled = env.get_field(&native_request_data_object, "canceled", "Z").expect("Failed to get canceled field").z().unwrap();
if is_canceled {
info!("canceled request for {}", uri_str);
return std::ptr::null_mut();
}
let new_buffer: JByteArray = env
.get_field(&native_request_data_object, "buffer", "[B")
.expect("Failed to get buffer field")
.l()
.unwrap()
.into();
let new_buffer_length = env
.get_array_length(&new_buffer)
.expect("Failed to get array length") as usize;
let new_buffer: JByteArray = env.get_field(&native_request_data_object, "buffer", "[B").expect("Failed to get buffer field").l().unwrap().into();
let new_buffer_length = env.get_array_length(&new_buffer).expect("Failed to get array length") as usize;
let mut new_buffer_data = Box::new(vec![0i8; new_buffer_length]);
env.get_byte_array_region(&new_buffer, 0, new_buffer_data.as_mut_slice())
.expect("Failed to get byte array region");
env.get_byte_array_region(&new_buffer, 0, new_buffer_data.as_mut_slice()).expect("Failed to get byte array region");
let ref_counter_struct_size =
(slice_buffer.data as usize) - (slice_buffer.ref_counter as usize);
let ref_counter_struct_size = (slice_buffer.data as usize) - (slice_buffer.ref_counter as usize);
//we need to allocate a new ref_counter struct and copy the old ref_counter and the new_buffer to it
let new_ref = {
let new_ref = libc::malloc(ref_counter_struct_size + new_buffer_length) as *mut c_void;
libc::memcpy(new_ref, slice_buffer.ref_counter, ref_counter_struct_size);
libc::memcpy(
new_ref.offset(ref_counter_struct_size as isize),
new_buffer_data.as_ptr() as *const c_void,
new_buffer_length,
);
libc::memcpy(new_ref.offset(ref_counter_struct_size as isize), new_buffer_data.as_ptr() as *const c_void, new_buffer_length);
libc::free(slice_buffer.ref_counter);
new_ref
};
@@ -143,25 +104,20 @@ def_hook!(
pub fn init() {
if let Some(signature) = sig::find_signature(
&common::CLIENT_MODULE,
"AA A8 03 1F F8 ?? ?? 00 94 ?? ?? 05 91",
-0x47,
"0A 90 00 F0 3F F9",
-0x37,
"A8 03 1F F8 ?? ?? 00 94 ?? ?? ?? 91 ?? ?? ?? A9", -0x48,
"0A 90 00 F0 3F F9", -0x37
) {
dobby_hook!(signature as *mut c_void, unary_call);
common::attach_jni_env(|env| {
NATIVE_LIB_ON_UNARY_CALL_METHOD
.set(
env.get_method_id(
env.get_object_class(common::native_lib_instance()).unwrap(),
"onNativeUnaryCall",
"(Ljava/lang/String;[B)Lme/eternal/purrfectsnap/nativelib/NativeRequestData;",
)
.expect("Failed to get onNativeUnaryCall method id"),
)
.expect("unary call method already set");
NATIVE_LIB_ON_UNARY_CALL_METHOD.set(
env.get_method_id(
env.get_object_class(common::native_lib_instance()).unwrap(),
"onNativeUnaryCall",
"(Ljava/lang/String;[B)Lme/eternal/purrfectsnap/nativelib/NativeRequestData;"
).expect("Failed to get onNativeUnaryCall method id")
).expect("unary call method already set");
});
} else {
panic!("Can't find unaryCall signature");
error!("Can't find unaryCall signature");
}
}

View File

@@ -1,61 +0,0 @@
use procfs::process::MMapPath;
pub struct Elf<'elf> {
base_address: usize,
elf: goblin::elf::Elf<'elf>,
_buffer: &'elf [u8],
}
impl<'elf> Elf<'elf> {
pub fn from_maps(lib: &str) -> Option<Self> {
let maps = procfs::process::Process::myself().ok()?.maps().ok()?;
for memory_map in maps.iter() {
if let MMapPath::Path(path) = &memory_map.pathname {
let path = path.to_string_lossy();
if !path.contains(lib) {
continue;
}
let file_data = std::fs::read(path.to_string()).ok()?;
let file_buffer = Box::leak(file_data.into_boxed_slice());
if let Ok(elf) = goblin::elf::Elf::parse(file_buffer) {
return Some(Elf {
base_address: memory_map.address.0 as usize,
elf,
_buffer: file_buffer,
});
} else {
warn!(
"Failed to parse ELF for library {} at address {:x}",
lib, memory_map.address.0
);
}
}
}
None
}
pub fn get_symbol_address(&self, symbol: &str) -> Option<usize> {
for sym in &self.elf.dynsyms {
if let Some(name) = self.elf.dynstrtab.get_at(sym.st_name) {
if name == symbol {
return Some(self.base_address + sym.st_value as usize);
}
}
}
for sym in &self.elf.syms {
if let Some(name) = self.elf.strtab.get_at(sym.st_name) {
if name == symbol {
return Some(self.base_address + sym.st_value as usize);
}
}
}
None
}
}

View File

@@ -1,2 +1 @@
pub mod elf;
pub mod valdi_utils;

View File

@@ -43,12 +43,7 @@ pub struct ValdiModule {
impl ValdiModule {
pub fn parse(buffer: Vec<u8>) -> Result<ValdiModule, Error> {
let mut offset = 0;
let magic = u32::from_be_bytes([
buffer[offset],
buffer[offset + 1],
buffer[offset + 2],
buffer[offset + 3],
]);
let magic = u32::from_be_bytes([buffer[offset], buffer[offset + 1], buffer[offset + 2], buffer[offset + 3]]);
offset += 4;
@@ -90,12 +85,13 @@ impl ValdiModule {
tags.push(ModuleTag::new(has_padding, tag_buffer));
}
let tags = tags
.chunks(2)
.map(|chunk| (chunk[0].clone(), chunk[1].clone()))
.collect();
let tags = tags.chunks(2).map(|chunk| {
(chunk[0].clone(), chunk[1].clone())
}).collect();
Ok(ValdiModule { tags })
Ok(ValdiModule {
tags,
})
}
pub fn to_bytes(&self) -> Vec<u8> {

View File

@@ -1,29 +1,35 @@
use super::util::valdi_utils::{ModuleTag, ValdiModule};
use crate::{config, def_hook, dobby_hook, modules::util::elf, util::get_jni_string};
#![allow(dead_code, unused_imports)]
use super::util::valdi_utils::{ValdiModule, ModuleTag};
use std::{collections::HashMap, ffi::c_void, sync::Mutex};
use jni::{objects::JString, JNIEnv};
use once_cell::sync::Lazy;
use std::{
collections::HashMap,
ffi::c_void,
sync::Mutex,
};
use crate::{common, config, def_hook, dobby_hook, dobby_hook_sym, util::get_jni_string};
static AASSET_MAP: Lazy<Mutex<HashMap<usize, Vec<u8>>>> = Lazy::new(|| Mutex::new(HashMap::new()));
static LOADER_DATA: Mutex<Option<String>> = Mutex::new(None);
def_hook!(aasset_get_length, i32, |arg0: *mut c_void| {
if let Some(buffer) = AASSET_MAP.lock().unwrap().get(&(arg0 as usize)) {
return buffer.len() as i32;
def_hook!(
aasset_get_length,
i32,
|arg0: *mut c_void| {
if let Some(buffer) = AASSET_MAP.lock().unwrap().get(&(arg0 as usize)) {
return buffer.len() as i32;
}
aasset_get_length_original.unwrap()(arg0)
}
aasset_get_length_original.unwrap()(arg0)
});
);
def_hook!(aasset_get_buffer, *const c_void, |arg0: *mut c_void| {
if let Some(buffer) = AASSET_MAP.lock().unwrap().get(&(arg0 as usize)) {
return buffer.as_ptr() as *const c_void;
def_hook!(
aasset_get_buffer,
*const c_void,
|arg0: *mut c_void| {
if let Some(buffer) = AASSET_MAP.lock().unwrap().get(&(arg0 as usize)) {
return buffer.as_ptr() as *const c_void;
}
aasset_get_buffer_original.unwrap()(arg0)
}
aasset_get_buffer_original.unwrap()(arg0)
});
);
def_hook!(
aasset_manager_open,
@@ -39,13 +45,9 @@ def_hook!(
let loader_data = LOADER_DATA.lock().unwrap().clone().expect("No loader data");
let archive_buffer: Vec<u8> =
std::slice::from_raw_parts(asset_buffer as *const u8, asset_length as usize)
.to_vec();
let decompressed = zstd::stream::decode_all(&archive_buffer[..])
.expect("Failed to decompress valdi archive");
let mut valdi_module =
ValdiModule::parse(decompressed).expect("Failed to parse valdi module");
let archive_buffer: Vec<u8> = std::slice::from_raw_parts(asset_buffer as *const u8, asset_length as usize).to_vec();
let decompressed = zstd::stream::decode_all(&archive_buffer[..]).expect("Failed to decompress valdi archive");
let mut valdi_module = ValdiModule::parse(decompressed).expect("Failed to parse valdi module");
let mut tags = valdi_module.get_tags();
let mut new_tags = Vec::new();
@@ -56,22 +58,19 @@ def_hook!(
continue;
}
let old_file_name = name.split_once(".").unwrap().0.to_owned()
+ rand::random::<u32>().to_string().as_str();
let old_file_name = name.split_once(".").unwrap().0.to_owned() + rand::random::<u32>().to_string().as_str();
tag1.set_buffer((old_file_name.to_owned() + ".js").as_bytes().to_vec());
let original_module_path =
path.split_once(".").unwrap().0.to_owned() + "/" + &old_file_name;
let original_module_path = path.split_once(".").unwrap().0.to_owned() + "/" + &old_file_name;
let hooked_module = format!(
"{};module.exports = require(\"{}\");",
loader_data, original_module_path
let hooked_module = format!("{};module.exports = require(\"{}\");", loader_data, original_module_path);
new_tags.push(
(
ModuleTag::new(true, name.as_bytes().to_vec()),
ModuleTag::new(true, hooked_module.as_bytes().to_vec())
)
);
new_tags.push((
ModuleTag::new(true, name.as_bytes().to_vec()),
ModuleTag::new(true, hooked_module.as_bytes().to_vec()),
));
debug!("Valdi loader injected in {}", name);
break;
}
@@ -80,22 +79,22 @@ def_hook!(
valdi_module.set_tags(tags);
let compressed = valdi_module.to_bytes();
let compressed =
zstd::stream::encode_all(&compressed[..], 3).expect("Failed to compress");
let compressed = zstd::stream::encode_all(&compressed[..], 3).expect("Failed to compress");
AASSET_MAP
.lock()
.unwrap()
.insert(handle as usize, compressed);
AASSET_MAP.lock().unwrap().insert(handle as usize, compressed);
}
handle
}
);
def_hook!(aasset_close, c_void, |handle: *mut c_void| {
AASSET_MAP.lock().unwrap().remove(&(handle as usize));
aasset_close_original.unwrap()(handle)
});
def_hook!(
aasset_close,
c_void,
|handle: *mut c_void| {
AASSET_MAP.lock().unwrap().remove(&(handle as usize));
aasset_close_original.unwrap()(handle)
}
);
pub fn set_valdi_loader(mut env: JNIEnv, _: *mut c_void, code: JString) {
let new_code = get_jni_string(&mut env, code).expect("Failed to get loader code");
@@ -104,33 +103,11 @@ pub fn set_valdi_loader(mut env: JNIEnv, _: *mut c_void, code: JString) {
pub fn init() {
if !config::native_config().valdi_hooks {
return;
return
}
let lib_android =
elf::Elf::from_maps("/libandroid.so").expect("Failed to find libandroid.so in maps");
if let Some(ptr) = lib_android.get_symbol_address("AAsset_getBuffer") {
dobby_hook!(ptr as _, aasset_get_buffer);
} else {
panic!("Failed to find AAsset_getBuffer symbol");
}
if let Some(ptr) = lib_android.get_symbol_address("AAsset_getLength") {
dobby_hook!(ptr as _, aasset_get_length);
} else {
panic!("Failed to find AAsset_getLength symbol");
}
if let Some(ptr) = lib_android.get_symbol_address("AAsset_close") {
dobby_hook!(ptr as _, aasset_close);
} else {
panic!("Failed to find AAsset_close symbol");
}
if let Some(ptr) = lib_android.get_symbol_address("AAssetManager_open") {
dobby_hook!(ptr as _, aasset_manager_open);
} else {
panic!("Failed to find AAssetManager_open symbol");
}
dobby_hook_sym!("libandroid.so", "AAsset_getBuffer", aasset_get_buffer);
dobby_hook_sym!("libandroid.so", "AAsset_getLength", aasset_get_length);
dobby_hook_sym!("libandroid.so", "AAsset_close", aasset_close);
dobby_hook_sym!("libandroid.so", "AAssetManager_open", aasset_manager_open);
}

View File

@@ -61,18 +61,8 @@ pub fn find_signatures(module_base: usize, bytes_buffer: &[u8], pattern: &str, o
let mut mask = Vec::new();
let mut i = 0;
if let Some(cache) = SIGNATURE_CACHE
.lock()
.unwrap()
.iter()
.find(|(sig, _)| sig == pattern)
{
return cache
.1
.clone()
.into_iter()
.map(|offset| module_base + offset)
.collect();
if let Some(cache) = SIGNATURE_CACHE.lock().unwrap().iter().find(|(sig, _)| sig == pattern) {
return cache.1.clone().into_iter().map(|offset| module_base + offset).collect();
}
while i < pattern.len() {
@@ -80,7 +70,7 @@ pub fn find_signatures(module_base: usize, bytes_buffer: &[u8], pattern: &str, o
bytes.push(0);
mask.push('?');
} else {
bytes.push(u8::from_str_radix(&pattern[i..i + 2], 16).unwrap());
bytes.push(u8::from_str_radix(&pattern[i..i+2], 16).unwrap());
mask.push('x');
}
i += 3;
@@ -102,10 +92,7 @@ pub fn find_signatures(module_base: usize, bytes_buffer: &[u8], pattern: &str, o
}
if found {
if once {
SIGNATURE_CACHE
.lock()
.unwrap()
.push((pattern.to_string(), vec![i]));
SIGNATURE_CACHE.lock().unwrap().push((pattern.to_string(), vec![i]));
return vec![module_base + i];
}
results.push(module_base + i);
@@ -113,22 +100,14 @@ pub fn find_signatures(module_base: usize, bytes_buffer: &[u8], pattern: &str, o
i += 1;
}
SIGNATURE_CACHE
.lock()
.unwrap()
.push((pattern.to_string(), results.clone()));
SIGNATURE_CACHE.lock().unwrap().push((pattern.to_string(), results.clone()));
results
}
pub fn find_signature_executable(mapped_lib: &MappedLib, pattern: &str) -> Option<usize> {
let executable_regions = mapped_lib
.regions
.iter()
.filter(|region| {
region.perms.contains(MMPermissions::EXECUTE)
&& region.perms.contains(MMPermissions::READ)
})
.collect::<Vec<_>>();
let executable_regions = mapped_lib.regions.iter().filter(|region| {
region.perms.contains(MMPermissions::EXECUTE)
}).collect::<Vec<_>>();
for region in executable_regions {
let size = (region.end - region.start) as usize;
@@ -138,27 +117,16 @@ pub fn find_signature_executable(mapped_lib: &MappedLib, pattern: &str) -> Optio
let bytes_buffer = match read_region_bytes(module_base, size) {
Some(buffer) => buffer,
None => {
warn!(
"Unable to read executable region: {:#x} - {:#x}",
region.start, region.end
);
warn!("Unable to read executable region: {:#x} - {:#x}", region.start, region.end);
continue;
}
};
let results = find_signatures(module_base, &bytes_buffer, pattern, true);
if results.is_empty() {
warn!(
"Signature not found in region: {:#x} - {:#x}",
region.start, region.end
);
warn!("Signature not found in region: {:#x} - {:#x}", region.start, region.end);
} else {
debug!(
"Found {} results in region: {:#x} - {:#x}",
results.len(),
region.start,
region.end
);
debug!("Found {} results in region: {:#x} - {:#x}", results.len(), region.start, region.end);
return Some(results[0]);
}
}
@@ -167,21 +135,13 @@ pub fn find_signature_executable(mapped_lib: &MappedLib, pattern: &str) -> Optio
None
}
pub fn find_signature(
mapped_lib: &MappedLib,
_arm64_pattern: &str,
_arm64_offset: i64,
_arm32_pattern: &str,
_arm32_offset: i64,
) -> Option<usize> {
pub fn find_signature(mapped_lib: &MappedLib, _arm64_pattern: &str, _arm64_offset: i64, _arm32_pattern: &str, _arm32_offset: i64) -> Option<usize> {
#[cfg(target_arch = "aarch64")]
{
return find_signature_executable(mapped_lib, _arm64_pattern)
.map(|address| (address as i64 + _arm64_offset) as usize);
return find_signature_executable(mapped_lib, _arm64_pattern).map(|address| (address as i64 + _arm64_offset) as usize);
}
#[cfg(target_arch = "arm")]
{
return find_signature_executable(mapped_lib, _arm32_pattern)
.map(|address| (address as i64 + _arm32_offset) as usize);
return find_signature_executable(mapped_lib, _arm32_pattern).map(|address| (address as i64 + _arm32_offset) as usize);
}
}