Root-Rechte-Gewährung ohne Root-Rechte-Verwaltungsapp

4

4ndr0

Dauergast
430
Hi,

es geht mir auf die Nerven, dass ich jede su Anfrage doppelt beantworten muss. Erst XPrivacy, dann SuperSU.

Deshalb meine Frage: Benötige ich überhaupt eine "SU-App"? Müsste ich mir dann die Binary selbst bauen oder bekomme ich die vorkompiliert?

Ich möchte, dass jede App grundsätzlich erstmal ohne Nachfrage "su" aufrufen darf, da das ja sowieso von XPrivacy abgefangen wird. Oder gibt es da Sicherheitsbedenken?
 
Warum stellst du bei superSU nicht einfach in den Einstellungen auf "immer akzeptieren" statt auf "nachfragen"?
 
  • Danke
Reaktionen: 4ndr0
Das wäre natürlich eine simple Lösung :D

Aber ich habe ungerne unnötige Software auf meinem Telefon. Wäre das grundsätzlich möglich, die su Binary selbst zu bauen und auf SuperSU zu verzichten? Wenn ich SuperSU deinstalliere, wird dann auch die Binary von meinem Telefon entfernt?
 
Das kann ich dir leider nicht beantworten ;-)
 
Du brauchst die SU-App denn nur diese kann die rechte wirklich vergeben. xPrivacy vergibt keine Su-Rechte sondern fragt nur die Rechte zum beschränken ab (z.b. Internet, Netzwerk, etc.)

2 verschiedene sachen.

Ohne Su-App kannst du also keiner App Root geben. Im gegensatz zu den Antivirus Apps ist diese also Absolut wichtig.
 
Das su Binary das zu SuperSU gehört kannst Du auch ohne die SuperSU App auf Deinem Gerät haben (beispielsweise wenn Du per 'adb pull' vor der Deinstallation von SuperSU auf den PC sicherst und hinterher mit 'adb push' wieder auf das Gerät schiebst', oder mit einen 'Installierbaren ZIP' darauf installierst).

Das wird Dir aber nichts bringen, denn das su Binary, das zu SuperSU gehört, läßt nur dann Root-Zugriffe zu, wenn es von der SuperSU-App mitgeteilt bekommt, dass dieser Zugriff gestattet ist.

Ebenso wird es sich mit den SU-Binaries anderer Super-User Apps verhalten. Jedes su-Binary ist darauf abgestimmt, Root Zugriffe nur dann zu erlauben, wenn die dazugehörige App diesen Zugriff erlaubt.

Natürlich ist es aber möglich, ein su Binary selbst zu bauen, das Rootzugriffe generell erlaubt!

Das ist sogar bedeutend einfacher, als ein su-Binary zu konstruieren, das erst eine App um Erlaubnis fragen muss, denn das eigentliche Grundprinzip des su-Binaries ist total simpel.

Was zu genau tun ist hängt allerdings davon ab, welche Android-Version Du verwendest.

Eine Übersicht darüber, wie sich die Anforderungen an Root Binaries unter den verschieden Android-Versionen verändert haben:

https://www.android-hilfe.de/forum/...es-mit-lollipop-und-root-auf-sich.628069.html
 
  • Danke
Reaktionen: Lopan
Nochmal deutlich, ein su welches ohne Verwaltungsapp alles erlaubt ist nicht zu empfehlen.
Dann kann jede App alles machen, auch an xprivacy vorbei. Denn gegen Zugriffe per root Recht kann xprivacy nix machen.

cu
 
Aaskereija schrieb:
Du brauchst die SU-App denn nur diese kann die rechte wirklich vergeben.

Das ist wohl eher ein Missverständnis.

Die SU-App vergibt nicht die Rechte, sondern teilt dem su-Binary mit, dass der User bestätigt hat, dass das su-Binary die Rechte vergeben darf.

Da in Android ein Bnary jedoch nicht auf die Oberfläche zu greifen kann (Bzw sollte, es könnte es schon, ginge dann aber am SystemUI vorbei und würde den Ablauf der anderen Apps stören) muss ein su Bnary, das nicht pauschal jeder App Root Zugriff gestattet, immer mit Hilfe einer Super-User App mit dem User kommunizieren.
 
Naja ich habe eine Rom ohne SU App wo jede App die Rootrechte braucht Sie von vorne herein hat.

Der ursprüngliche Beitrag von 17:24 Uhr wurde um 17:25 Uhr ergänzt:

Das zum Thema das die SU App zwingend ist.
 
su ist das Programm (keine App) welches Apps nutzen können um Befehle mit root Rechten auszuführen.
Und das ist zwingend, weil das installiert zu haben ist das was man "root haben" nennt.

Die (zum su passende) Verwaltungsapp ist nicht zwingend (gibt wie schon gesagt su Programme ohne Verwaltungsapp, das ist das was du da wohl hast). Aber dringend zu empfehlen. Weil ohne kann jede App alles machen was sie will (das ist wie früher bei Windows, wenn man keinen eingeschränkten Account nutzt sondern unter dem Admin Account arbeitet).

BTW: su und die Verwaltungsapp gehören fest zusammen. Verschiedene Hersteller kann man nicht mischen.

cu
 
Zuletzt bearbeitet:
u.k-f schrieb:
Das ist wohl eher ein Missverst0Š1ndnis.

Die SU-App vergibt nicht die Rechte, sondern teilt dem su-Binary mit, dass der User best0Š1tigt hat, dass das su-Binary die Rechte vergeben darf.

Da in Android ein Bnary jedoch nicht auf die Oberfl0Š1che zu greifen kann (Bzw sollte, es k0‹2nnte es schon, ginge dann aber am SystemUI vorbei und w¨¹rde den Ablauf der anderen Apps st0‹2ren) muss ein su Bnary, das nicht pauschal jeder App Root Zugriff gestattet, immer mit Hilfe einer Super-User App mit dem User kommunizieren.

Kommt fuer mich aufs gleiche raus
 
Danke für die ausführlichen Erklärungen. Ich fasse mal zusammen: Die su Binary kommt als Bundle mit der jeweiligen Superuser App und triggert diese, sobald sie aufgerufen wird. Korrekt?

Ich könnte mir aber den Quellcode nehmen und diesen für die ARM Architektur kompilieren, dann könnte ich sie aufrufen, ohne dies in einer zugehörigen App erlauben zu müssen. Ist das mit einigermaßen fortgeschrittenen Linux-Kenntnissen machbar oder muss ich dafür Programmierer sein? :)

rihntrha schrieb:
Nochmal deutlich, ein su welches ohne Verwaltungsapp alles erlaubt ist nicht zu empfehlen.
Dann kann jede App alles machen, auch an xprivacy vorbei. Denn gegen Zugriffe per root Recht kann xprivacy nix machen.
Das kann ich wiederum nicht ganz verstehen. Sobald irgendeine App auf meinem System die su Binary aufrufen möchte, meldet sich XPrivacy und fragt, ob ich den Zugriff auf /xbin/su erlauben möchte. Erst wenn ich das bestätige, meldet sich die Superuser App und fragt mich noch mal. Reagiere ich nicht, wird der Zugriff abgelehnt. Im Gegensatz zu den üblichen Superuser Lösungen muss also nicht die Binary die App fragen, ob sie darf, sondern XPrivacy selbst überwacht den Zugriff auf die Binaries. Kommt mir nach etwas Überlegung auch sinnvoller vor. Was spricht also dagegen, den Root-Zugriff per XPrivacy zu steuern?

Simon G. schrieb:
Naja ich habe eine Rom ohne SU App wo jede App die Rootrechte braucht Sie von vorne herein hat.
DAS halte ich wirklich für eine schlechte Idee. Allerdings würde mich interessieren, welche ROM du verwendest. Evtl. könnte ich ja diese Binary verwenden.
 
Zuletzt bearbeitet:
Vermutlich kann man ganz einfach das normale su (gehört zu jedem Linux, kommt von gnu?) mehmen.
Ich vermute die root Verwaltungsappsauthoren haben das auch genommen und ihre Funktion dort reingebastelt?

Ich würde hier anfangen zu Googlen.

BTW: Das xprivacy den Zugriff auf su selbst unterbinden kann wusste ich nicht.
Sicher das das auch funktioniert wenn eine lib das nativ aufruft? Xprivacy hängt sich ja nur in die Android API. Ich würde erstmal vermuten das xprivacy nur die Java System aufrufe kontrollieren kann.

Oder was ist wenn die App nen Shellscript startet und dieses su benutzt?

Wäre vermutlich besser das zu prüfen?

cu
 
  • Danke
Reaktionen: 4ndr0
rihntrha schrieb:
Oder was ist wenn die App nen Shellscript startet und dieses su benutzt?
Dann wird XPrivacy mich zuerst fragen, ob diese /system/bin/sh aufrufen darf, denn ohne explizite Erlaubnis darf keine App die Shell aufrufen und somit auch kein Shellskript ;)
 
Zuletzt bearbeitet:
OK ;-)
Bleibt die Frage ob xprivacy auch Systemaurufe die per libc erfolgen unterbinden kann.
Aber vermutlich fragt dich dann xprivacy ob die App überhaupt ihre lib laden darf ;-)

cu
 
So etwas fragt XPrivacy tatsächlich. Allerdings hat mich dein Post nochmal zur gezielten Recherche bewegt und ich habe folgendes gefunden:
https://github.com/M66B/XPrivacy schrieb:
(10) Can I restrict root access?

Yes, via "Shell (commands, superuser) > su", but be aware that applications can acquire root privileges through native libraries too. An example is Android Terminal Emulator.

Du hast also offenbar absolut Recht. Ich vermute, dass das Xposed Framework einfach nicht tief genug im System sitzt, wie das afaik Cydia Substrate tun würde.

Thema erledigt. Meine ursprüngliche Frage ist damit wohl beantwortet und das Xposed Framwork einfach nicht mächtig genug, um die Superuser App zu ersetzen. Schade. Danke an alle für die Denkanstöße :)
 
Aaskereija schrieb:
Kommt fuer mich aufs gleiche raus

Das ist dann wirklich ein Problem. Wenn man sich mit Software Anwendung oder gar Entwicklung eingehender beschäftigt, sollte man schon zu feinem Differenzieren in der Lage sein!

Nach Deinen Ausführungen wäre ein ein su-Binary ohne SU-App nicht machbar. Da es aber möglich ein su-Binary zu erstellen, das keine SU-App benötigt, kann Deine Aussage ja nicht richtig sein. (Siehe Code-Block unten, QED :smile:)

Deswegen habe ich die Richtigstellung gepostet.

rihntrha schrieb:
Vermutlich kann man ganz einfach das normale su (gehört zu jedem Linux, kommt von gnu?) mehmen.
Ich vermute die root Verwaltungsappsauthoren haben das auch genommen und ihre Funktion dort reingebastelt?

Das su-Binary aus Linux enthält ebenfalls Code, um eine Berichtungs-Abfrage durchzuführen, in Falle von Linux aber die Abfrage des root-Passwortes, das es unter Android jedoch nicht gibt.

Es ist aber gar nicht nötig, großartig auf fremden Code zurückzugreifen, um ein simples su-Binary zu posten, denn es ist nur ein setuid(0) und setgid(0) und ein exec auf /system/bin/sh.

Ein einfaches su Binary kann mit diesem Code implementiert werden:

Code:
//(c) by u.k-f 2014
//Demo Code, not for productive use!
//Do not use, grants root access to any App!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>

static int executionFailure(char *context)
{
        fprintf(stderr, "su: %s. Error:%s\n", context, strerror(errno));
        return -errno;
}

static int permissionDenied()
{
        // the superuser activity couldn't be started
        printf("su: Permission denied\n");
        return 1;
}

int main(int argn, char** args)
{
        struct stat stats;
        int uid = 0;
        int gid = 0;
        if(setgid(gid) || setuid(uid))
                return permissionDenied();
        char *exec_args[2];
        exec_args[0] = "sh";
        exec_args[1] = NULL;
        execv("/system/bin/sh", exec_args);
        return executionFailure("sh");
}

Das Binary muss dann als User 0 Group 0 mit den Rechten 6755 ins Filesystem 'in den PATH' gelegt werden.

Dann wird das su-Binary jeder aufrufenden App root-Rechte geben.

Allerdings wird das nur bis einschließlich Android 4.2 funktionieren. Ab Android 4.3 wird der 'User-Context-Wechsel'

Code:
if(setgid(gid) || setuid(uid))
        return permissionDenied();

von SELINUX verhindert.

Deswegen arbeitet man ab Android 4.3 mit einem su-Daemon Prozess, der von Start an im User-Context 0 (root) läuft.

Dieser Daemon-Prozess kann (wie ein ssh-Daemon) von einem su-Client (der dann als su-binary dient) über einen Socket aufgerufen werden, und dessen Befehle (im root-Context) ausführen.

Ein einfacher su-Client

Code:
//(c) by u.k-f 2014
//Demo Code, not for productive use!
//Do not use, grants root access to any App!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define UDS_FILE "/dev/socket/su"

static void *read_thread(void *cookie)
{
	char buffer[128];
	int * hdlr = (int *)cookie;
	int sp = hdlr[0];
	int length;
	length = read(STDIN_FILENO, buffer, sizeof(buffer));
	// length==0:EOF  length==-1:Error
	while(length > 0) {
		send(sp, buffer, length, 0);
		length = read(STDIN_FILENO, buffer, sizeof(buffer));
	}
	close(sp);
	return NULL;
}

static void *write_thread(void *cookie)
{
	char buffer[128];
	int * hdlw = (int *)cookie;
	int sp = hdlw[0];
	int length;
	int limit;
	int part;
	int stream;
	part = recv(sp, buffer, 1,0);
	// length==0:EOF  length==-1:Error
	while(part > 0) {
		limit = buffer[0] &0x7F;
		stream = (buffer[0] &0x80)?STDERR_FILENO:STDOUT_FILENO;
		length=0;
		while (limit>length && part>0)
		{
			part = recv(sp, &buffer[length], limit-length,0);
			length+=part;
		}
		write(stream, buffer, length);
		length = recv(sp, buffer, 1,0);
	}
	return NULL;
}




static int executionFailure(char *context)
{
	fprintf(stderr, "su: %s. error:%s\n", context, strerror(errno));
	return -errno;
}

int main(int argn, char** args)
{
	int uid = 0;
	int gid = 0;
	pthread_t pr,pw;
	void ** ret;
	int create_socket;
	struct sockaddr_un address;
	int size;
	create_socket=socket (PF_LOCAL, SOCK_STREAM, 0);
	if (create_socket==0)
		executionFailure("Socket create");
	address.sun_family = AF_LOCAL;
	strcpy(address.sun_path, UDS_FILE);
	if (connect ( create_socket,(struct sockaddr *) &address,sizeof (address))!= 0)
		executionFailure("Socket connect");
	if (argn==2 && (strcasecmp(args[1],"-p")==0))
	{
		send(create_socket,"echo $$\n",8,0);
	}
	pthread_create(&pr,NULL,read_thread,&create_socket);
	pthread_create(&pw,NULL,write_thread,&create_socket);
	pthread_join(pw,ret);
	close (create_socket);
	exit(0);
}

Und der dazugehörige su-Daemon würde dann so aussehen können:

Code:
//(c) by u.k-f 2014
//Demo Code, not for productive use!
//Do not use, grants root access to any App!

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <sys/stat.h>
#include <sys/wait.h>

#define UDS_FILE "/dev/socket/su"

static void *out_thread(void *cookie) {
	char buffer[128];
	int * hdlo = (int *) cookie;
	int rp = hdlo[0];
	int wp = hdlo[1];
	int sp = hdlo[2];
	int length;
	close(wp);
	length = read(rp, &buffer[1], sizeof(buffer)-1);
	// length==0:EOF  length==-1:Error
	while (length > 0) {
		buffer[0]=length;
		pthread_mutex_lock((pthread_mutex_t *)hdlo[3]);
		send(sp, buffer, length+1, 0);
		pthread_mutex_unlock((pthread_mutex_t *)hdlo[3]);
		length = read(rp, &buffer[1], sizeof(buffer)-1);
	}
	close(rp);
	return NULL ;
}

static void *err_thread(void *cookie) {
	char buffer[128];
	int * hdle = (int *) cookie;
	int rp = hdle[0];
	int wp = hdle[1];
	int sp = hdle[2];
	int length;
	close(wp);
	length = read(rp, &buffer[1], sizeof(buffer)-1);
	// length==0:EOF  length==-1:Error
	while (length > 0) {
		buffer[0]=length | 0x80;
		pthread_mutex_lock((pthread_mutex_t *)hdle[3]);
		send(sp, buffer, length+1, 0);
		pthread_mutex_unlock((pthread_mutex_t *)hdle[3]);
		length = read(rp, &buffer[1], sizeof(buffer)-1);
	}
	close(rp);
	return NULL ;
}

static void *in_thread(void *cookie) {
	char buffer[128];
	int * hdli = (int *) cookie;
	int rp = hdli[0];
	int wp = hdli[1];
	int sp = hdli[2];
	int length;
	close(rp);
	length = recv(sp, buffer, sizeof(buffer), 0);
	// length==0:EOF  length==-1:Error
	while (length > 0) {
		write(wp, buffer, length);
		length = recv(sp, buffer, sizeof(buffer), 0);
	}
	close(wp);
	return NULL;
}

static void *client_thread(void* cookie) {
	pthread_mutex_t lock;
	int hdlo[4];
	int hdle[4];
	int hdli[3];
	pthread_t p;
	hdlo[2] = (int) cookie;
	hdle[2] = (int) cookie;
	hdli[2] = (int) cookie;
	pthread_mutex_init(&lock,NULL);
	hdlo[3] = (int) &lock;
	hdle[3] = (int) &lock;
	//pipefd[0]:lesen  [1]:schreiben
	if (pipe(hdlo) == -1) {
		perror("pipe()");
		exit(EXIT_FAILURE);
	}
	if (pipe(hdle) == -1) {
		perror("pipe()");
		exit(EXIT_FAILURE);
	}
	if (pipe(hdli) == -1) {
		perror("pipe()");
		exit(EXIT_FAILURE);
	}
	int state;
	pid_t pid = fork();
	switch (pid) {
	case -1:
		perror("fork()");
		exit(EXIT_FAILURE);
	case 0:    //Kind
		close(hdlo[0]);
		close(hdle[0]);
		close(hdli[1]);
		// leite stdout nach pipefd[1] um
		if (dup2(hdlo[1], STDOUT_FILENO) == -1) {
			perror("dup2()");
			exit(EXIT_FAILURE);
		}
		if (dup2(hdle[1], STDERR_FILENO) == -1) {
			perror("dup2()");
			exit(EXIT_FAILURE);
		}
		if (dup2(hdli[0], STDIN_FILENO) == -1) {
			perror("dup2()");
			exit(EXIT_FAILURE);
		}
		if (execlp("sh", "sh", NULL ) == -1) {
			perror("exec");
			exit(EXIT_FAILURE);
		}
		break;
	default:    //Elternprozess
		pthread_create(&p, NULL, out_thread, hdlo);
		pthread_create(&p, NULL, err_thread, hdle);
		pthread_create(&p, NULL, in_thread, hdli);
		while (wait(&state) != pid) ;
		shutdown((int) cookie, SHUT_RDWR);
		pthread_mutex_destroy(&lock);
		printf("Exited %d state %d\n", pid, state);
	}
	return NULL;
}

int main(void) {
	int create_socket, new_socket;
	FILE* f;
	socklen_t addrlen;
	ssize_t size;
	struct sockaddr_un address;
	const int y = 1;
	int hdlr[3];
	int hdlw[3];
	ssize_t length;
	pthread_t p;
	if ((create_socket = socket(AF_LOCAL, SOCK_STREAM, 0)) > 0)
		printf("Socket created\n");
	else
		exit(EXIT_FAILURE);
	unlink(UDS_FILE);
	address.sun_family = AF_LOCAL;
	strcpy(address.sun_path, UDS_FILE);
	if (bind(create_socket, (struct sockaddr *) &address, sizeof(address))!= 0){
		printf("Port busy\n");
		exit(EXIT_FAILURE);
	}
	listen(create_socket, 5);
	printf("Change mod %s %d\n", UDS_FILE,chmod(UDS_FILE, 0666);
	addrlen = sizeof(struct sockaddr_in);
	while (1) {
		new_socket = accept(create_socket, (struct sockaddr *) &address,&addrlen);
		if (new_socket > 0) {
			printf("Client connected\n");
			pthread_create(&p, NULL, client_thread, (void *)new_socket);
		}
	}
	close(create_socket);
	return EXIT_SUCCESS;
}

Das su-Client Binary sollte man su nennen. Es kann mit den Rechten 0755 'in den PATH' gelegt werden, UID und GID sind hier egal.

Der su-Daemon muss dann während des Boot-Vorganges mit root-Rechten gestartet werden.

Auch diese Kombination von su-Client/su-Daemon würden jeder aufrufenden App root-Rechte verleihen.
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: rihntrha und 4ndr0

Ähnliche Themen

B
  • Blooddrunked
Antworten
3
Aufrufe
593
textmarker007
T
Schwammkopf
  • Schwammkopf
Antworten
3
Aufrufe
551
rene3006
R
alf.228
Antworten
5
Aufrufe
1.835
Tetsujin
Tetsujin
Zurück
Oben Unten