Skip to content
This repository was archived by the owner on Feb 12, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions daemon/src/main/jni/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ set(SOURCES
logcat.cpp
obfuscation.cpp
packagename.cpp
)
)

add_library(${PROJECT_NAME} SHARED ${SOURCES})

target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} ${EXTERNAL_ROOT}/rapidxml)

target_link_libraries(${PROJECT_NAME} PRIVATE lsplant_static dex_builder_static android log)

Expand Down
26 changes: 13 additions & 13 deletions daemon/src/main/jni/abx_utils/abx_decoder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,20 @@

class AbxDecoder {
public:
AbxDecoder(std::vector<char> str) {
AbxDecoder(std::vector<char>* str) {
mInput = str;
}

bool isAbx() {
// maybe empty?
if (mInput->size() < 5) return false;

curPos = 0;
std::vector<char> headerV = readFromCurPos(4);
const char* header = reinterpret_cast<const char*>(headerV.data());
return memcmp(header, startMagic, 4) == 0;
}

bool parse() {
if (!isAbx())
return false;
Expand Down Expand Up @@ -142,29 +152,19 @@ class AbxDecoder {

private:
int curPos = 0;
std::vector<char> mInput;
std::vector<char>* mInput;
std::vector<std::vector<char>> internedStrings;
std::vector<std::shared_ptr<XMLElement>> elementStack;
bool docOpen = false, rootClosed = false;
const std::vector<char> emptyString;

std::vector<char> readFromCurPos(int len) {
// std::cout << "Reading " << len << " bytes of data from " << curPos << std::endl;
std::vector ret(mInput.begin() + curPos, mInput.begin() + curPos + len);
std::vector ret(mInput->begin() + curPos, mInput->begin() + curPos + len);
curPos += len;
return ret;
}

bool isAbx() {
// maybe empty?
if (mInput.size() < 5) return false;

curPos = 0;
std::vector<char> headerV = readFromCurPos(4);
const char* header = reinterpret_cast<const char*>(headerV.data());
return memcmp(header, startMagic, 4) == 0;
}

char readByte() {
return readFromCurPos(1)[0];
}
Expand Down
64 changes: 59 additions & 5 deletions daemon/src/main/jni/packagename.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,17 @@
#include <errno.h>
#include <stdbool.h>

#include <rapidxml.hpp>

static const std::string packages_path = "/data/system/packages.xml";
static std::vector<char> LoadFileToStdVector(std::string filename);

extern "C" bool get_pkg_from_classpath_arg(const char* classpath_dir, char* package_name, size_t package_name_buffer_size) {
// !!! DO NOT REMOVE THIS FUNCTION UNLESS YOU ADDED IT IN RAPIDXML !!!
void rapidxml::parse_error_handler(const char *what, void *where) {
LOGE("rapidxml Parser error: %s, Start of string: %s\n", what, (char *) where);
}

extern "C" bool get_pkg_from_classpath_arg(const char* classpath_dir, char* package_name, size_t package_name_buffer_size) {
size_t dir_len = strlen(classpath_dir);
if(dir_len == 0 || dir_len >= 1024) {
LOGE("Invalid classpath dir length: %zu", dir_len);
Expand All @@ -24,13 +31,60 @@ extern "C" bool get_pkg_from_classpath_arg(const char* classpath_dir, char* pack

std::vector<char> packagesFile = LoadFileToStdVector(packages_path);

if(packagesFile.size() < 1)
{
if(packagesFile.empty()) {
LOGE("Failed to read packages.xml: %s", strerror(errno));
return false;
}

AbxDecoder decoder(packagesFile);

AbxDecoder decoder(&packagesFile);
if (!decoder.isAbx()) {
LOGD("This file is not ABX encoded, trying with XML fallback");

rapidxml::xml_document document;
document.parse<0>(packagesFile.data());

rapidxml::xml_node<> *root_node = document.first_node();
rapidxml::xml_node<> *current_node = nullptr;

if (strcmp(root_node->name(), "packages") != 0) {
LOGE("The root tag is not packages!");

goto abort_xml_read;
}

current_node = root_node->first_node("package");
while (current_node) {
{
rapidxml::xml_attribute<> *name_attr = current_node->first_attribute("name");
rapidxml::xml_attribute<> *code_path_attr = current_node->first_attribute("codePath");

if (!name_attr || !code_path_attr) goto continue_xml_loop;

char* code_path = code_path_attr->value();

if (strlen(code_path) != dir_len) goto continue_xml_loop;
if (strncmp(code_path, classpath_dir, dir_len) != 0) goto continue_xml_loop;

char* name = name_attr->value();
size_t name_len = strlen(name);

int copy_len = name_len < package_name_buffer_size - 1 ? static_cast<int>(name_len) : static_cast<int>(package_name_buffer_size - 1);
memcpy(package_name, name, copy_len * sizeof(char));
package_name[copy_len] = '\0';

document.clear();
return true;
}

continue_xml_loop:
current_node = current_node->next_sibling("package");
}

abort_xml_read:
document.clear();
return false;
}

if (decoder.parse() && decoder.root.get() && strcmp(decoder.root->mTagName.data(), "packages") == 0) {
for (auto pkg : decoder.root.get()->subElements) {
if (strcmp(pkg.get()->mTagName.data(), "package") != 0) continue;
Expand Down
Loading