android 如何在user版本中获取root权限

前提

本文介绍的方案是在有安卓底层SDK源码的方案下实行的,若不具备这个条件的就不用往下继续看了,以免耽误你的时间。

写作目的

公司是做工程设备,运行的是安卓系统,系统使用是的user,系统上层的app都是预安装的。正常情况下,这样的app的是没法做一些特权操作的,如重启系统、安装软件、读写一些特殊文件夹的文件。为了解决这些问题,特意做了一个方案,使第三方的app也拥有了root权限。

实现思路

我们知道系统启动后会运行init程序,init程序会解析init.rc脚本,并执行init.rc中的命令,而init程序是拥有root权限的,那么如果写一个服务程序,将此服务程序放入到init.rc中,使其开机启动,并常驻与系统中,这样这个服务程序也将拥有了root权限。而我们的第三方app想要获取一些特权操作时,只需要把把操作指令发送给我们的服务程序,由这个服务程序去执行即可。

最终效果

Runtime.getRuntime().exec(“god reboot”); // 第三方app执行了系统重启命令

不难看出,这其实是用java调用了一个exec方法执行了一条脚本命令,而god是我底层的一个发送程序,意思是将god后方的命令发送给我底层的一个服务程序。底层的服务程序收到命令后,就会去执行它。
下面简单说下代码

发送方部分代码(god)



#include <ctype.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>




#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>
#include "common/nativeNetServer.h"
#include "common/Utils.h"

int main(int argc,char *argv[]){
	
char cmdstr[1024] = {0};
	int i;
	if(argc < 2){
		return -1;
	}
	pNativeNetServerOps  netServer = createNativeNetServer();
	
	if(netServer == NULL){
		return -1;
	}
	char tempStr[32] = {0};
	for(i = 1;i<argc;i++){
		sprintf(cmdstr,"%s %s",cmdstr,argv[i]);
	}
	LOGD("[jerry] %s\n",cmdstr);
	return 	netServer->runScript(netServer,cmdstr,4);
}
static int runScript(struct NativeNetServerOps * ops, const char * str,int timeout) {
	pNativeNetServer pthis = (pNativeNetServer) ops;
	int ret  =-1;
	if (pthis == NULL || pthis->udpServer == NULL) {
		return -1;
	}
	char recvbuf[1024] = {0};
	MsgBody msg = UdpBuildMsg(NOT_ACK, CMD_RUN_SCRIPT, str, strlen(str) + 1);
	ret = pthis->udpServer->write(pthis->udpServer, msg.buf, msg.len,
			SERVER_IP_ADDR, SERVER_PORT);
	if(ret < 0){
		LOGE(" fail to write!");
		goto fail0;
	}
	ret = pthis->udpServer->read(pthis->udpServer,recvbuf,sizeof(recvbuf),timeout*1000);
	if(ret < 0){
		LOGE(" fail to read!");
		goto fail0;
	}
	pT_Comm_Head ackComm =  &recvbuf;
	LOGE("ackComm.dataPack.dataStart : %d\n",ackComm->dataPack.dataStart);
	return ackComm->dataPack.dataStart;
fail0:
	LOGE(" fail to runScript!");
	return -1;

}

这里的通讯使用的是socket,当然你也可以用管道或者binder或其他进程间通讯方案

服务端部分代码

static void cmdHandle(void* arg){

	pCmdArg cmdArg = arg;
	if(cmdArg == NULL){

		return;
	}	
	pT_Comm_Head commHead = (pT_Comm_Head )cmdArg->data;
	commHead->dataPack.dtatLen = ntohl(commHead->dataPack.dtatLen);
	switch(commHead->cmd)
	{
		case CMD_CONNECT_SCRIPT:{
			LOGD("CMD_CONNECT_SCRIPT\n");
			commHead->ackType = ACK_OK;
			udpServer->ack(udpServer,commHead,sizeof(T_Comm_Head),cmdArg->remoteInfo);
		}break;
		case CMD_RUN_SCRIPT:{
				char runScript[1024] = {0};
				int ret;
				memcpy(runScript,&commHead->dataPack.dataStart,commHead->dataPack.dtatLen);
			//	LOGD("system_run :[ %s ] start\n",runScript);
				ret = system(runScript);
				commHead->ackType = ACK_OK;
				commHead->dataPack.dataStart = ret;
				udpServer->ack(udpServer,commHead,sizeof(T_Comm_Head),cmdArg->remoteInfo);
				LOGD("system_run :[ %s ]  end\n",runScript);
				
			}
			break;

		case CMD_HEARTBEAT:{
				char heartbeatStr[1024] = {0};
				memcpy(heartbeatStr,&commHead->dataPack.dataStart,commHead->dataPack.dtatLen);
				daemonServer->keepHeartBeat(daemonServer,heartbeatStr);
			}	
			break;
		default:
			break;

	}

	if(cmdArg){
		if(cmdArg->data){
			free(cmdArg->data);
		}
		free(cmdArg);
	}


}

执行脚本时使用的是system,当然也可以使用popen并把代码的执行结果返回给app。

init.rc文件

service nativeNetserver /system/bin/nativeNetserver
    class main
    user root
    group root

后续

当然这只是众多方案中的一种,本人技术有限,目前只能想到这个方案,若有同行朋友还有其他解法或补充之处,交流一二简直再好不过,由于代码文件比较多,这里就不全部上传,若有需要的朋友可以联系我,我将毫无保留的分享给你。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值