Androidのsuコマンドの実装
suコマンド(user-debugでビルドするとついてくる子)がどう実装されているのか、気になったので調べました。
suが実際にやっていることは、setuid/setgidを0/0で呼び出すことです。 呼び出す前にセキュリティチェックを行なっており、AID_ROOTかAID_SYSTEM以外のUIDからは実行できないように弾いています。
/* Until we have something better, only root and the shell can use su. */
myuid = getuid();
if (myuid != AID_ROOT && myuid != AID_SHELL) {
fprintf(stderr,"su: uid %d not allowed to sun", myuid);
return 1;
}
treeのソースを読んでみて、だいたいの流れが分かったので、真似てsuモドキを作ってみました。
Android.mk
ポイントはLOCAL_FORCE_STATIC_EXECUTABLEのあたり。 静的リンクとしないとsetuid/setgidがsegfaultします。
include $(CLEAR_VARS)
LOCAL_MODULE := susample
LOCAL_SRC_FILES := susample.c
LOCAL_FORCE_STATIC_EXECUTABLE := true
LOCAL_STATIC_LIBRARIES := libc
include $(BUILD_EXECUTABLE)
setuid/setgid
このツールでは、setuid/setgidした後、rootのshを立ち上げるだけとしました。 権限チェックも無し!危険!
int main(int argc, char *argv[])
{
uid_t uid = 0, myuid;
gid_t gid = 0;
myuid = getuid();
printf("myuid = %dn", myuid);
if(setgid(gid) || setuid(uid)){
printf("su: permission denied");
return 1;
}
printf("su: exec shn");
execlp("/system/bin/sh", "sh", NULL);
return 1;
}
Permissionを整える
最後に、AndroidへPushした後、バイナリに権限をつけるのを忘れてハマりました。 setuid/setgidを利用するため、パーミッションの4桁目を設定する必要があります。(Ubuntuなどでは u+s とかするやつですね。) setuid(4)/setgid(2)/stiky(1)となっているので、6755あたりをひとまず設定しておくとよさげ。
# chmod 6755 susample
# ls -la
-rwsrwsrwx root root 182440 2014-06-24 02:20 susample