Android实现su权限的一种方法
背景
- Platform: IMX6Q
- OS: Android5.1
- Kernel: 3.14.52
需求
项目需求,有些功能需要root权限,但是以前做的系统没有添加su权限进去,所以就另辟蹊径用了这个办法。
实现
底层init启动一个service,主要是实现一个socket服务端,监听客户端发过来的命令,然后执行它。虽然apk与该service在不同的空间,有不同的权限,但底层init启动的service具有root权限
Service服务端实现
源代码大致如下
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <cutils/sockets.h>
#include <sys/un.h>
#include <netinet/in.h>
#define LOG_TAG "root_proxy"
#define LOG_NDEBUG 0
#include <utils/Log.h>
int main(int argc, char **argv)
{
int client_fd = -1;
int server_fd;
again:
server_fd = android_get_control_socket("root_proxy");
listen(server_fd, 5);
fcntl(server_fd, F_SETFD, FD_CLOEXEC);
ALOGV("listen");
while (1) {
int ret;
char buf[128];
if (client_fd == -1) {
struct sockaddr addr;
socklen_t alen = sizeof(addr);
client_fd = accept(server_fd, &addr, &alen);
ALOGV("client connect:%s", strerror(errno));
if (client_fd == -1) {
close(server_fd);
goto again;
}
fcntl(client_fd, F_SETFD, FD_CLOEXEC);
}
memset(buf, 0, 128);
ret = read(client_fd, buf, 128);
if (ret == 0) {
ALOGV("client exit");
close(client_fd);
client_fd = -1;
} else if (ret > 0) {
ALOGV("buf=%s", buf);
system(buf);
}
}
return 0;
}
如果需要返回结果,可使用管道,重定向,大致代码如下:
strlcat(recv_buf, " 2>&1", sizeof(recv_buf));
FILE *fp = popen(recv_buf, "r");
if (!fp) {
ALOGE("exec command failed. (%d)\n", -errno);
close(sock_client);
continue;
}
while (fgets(send_buf, sizeof(send_buf), fp)) {
ALOGI("Send %d bytes: %s\n", strlen(send_buf), send_buf);
len = send(sock_client, send_buf, strlen(send_buf), 0);
if (len < (int)strlen(send_buf)) {
ALOGE("send failed. (%d)\n", len);
break;
}
}
添加到编译环境
可参考:https://notes.z-dd.online/2019/12/02/Android源码添加自己的可执行程序/
将该Service添加到external
添加init自启动
在系统对应的init.rc里面添加:
service root_proxy /system/bin/root_proxy
class main
socket root_proxy stream 777 root radio
APK客户端实现
大致代码如下:
LocalSocket mSocket = new LocalSocket();
LocalSocketAddress address = new LocalSocketAddress("root_proxy",
LocalSocketAddress.Namespace.RESERVED);
if (mSocket != null){
try
{
mSocket.connect(address);
OutputStream mOutputStream = mSocket.getOutputStream();
mOutputStream.write((cmd).getBytes());
mOutputStream.flush();
mOutputStream.close();
mSocket.close();
Log.i(ConstVar.PORDUCT_NAME, "WriteToRild: " + cmd);
} catch (IOException e) {
e.printStackTrace();
}
}
mSocket = null;
try {
Thread.sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
参考
评论