FB_02.基于tcp通信实现类su调用

admin 2024年2月16日00:08:24评论16 views字数 7822阅读26分4秒阅读模式

主要内容:

  • 在超级Root权限进程中创建socket server监听连接

  • 基于socket通信实现一个简单的类似su程序的调用功能

本节达到的目的:

  • 系统没有su程序但是也能执行和su差不多的功能效果

1.实现原理

adbd中建立一个socket serverApp通过发送socket连接,并发送需要执行的shell命令。adbd中的socket server收到客户端发送的shell命令之后,执行system函数来调用相应的shell命令。由于adbd具备超级root权限,所以App发送执行的命令最终也是常说中的Root权限情况下执行命令。

2.adbd中创建socket server

(1).创建shell_socket_service.h文件

在路径"systemcoreadbdaemon"下创建"shell_socket_service.h"头文件。内容如下:

#pragma once

#
if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
void create_shell_socket_service();
#endif

(2).创建shell_socket_service.cpp文件

在路径"systemcoreadbdaemon"下创建"shell_socket_service.cpp"源文件。内容如下:

#if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
#include <unistd.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <sys/sendfile.h>
#include <fcntl.h>
#include <socket.h>
#include <cinttypes>
#include <wait.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/uio.h>
#include <unistd.h>
#include <cerrno>
#include <pthread.h>
#include <stdio.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  

#
include <android/log.h>

#
include "shell_socket_service.h"

#
define FRIDA_INJECT_TAG  "ss_server"
// #define NOT_DEBUG_SOCKET 1
#ifdef NOT_DEBUG_SOCKET
#define MYLOGDX(...)
#define MYLOGEX(...)
#else

#
define MYLOGDX(...)  __android_log_print(ANDROID_LOG_DEBUG, FRIDA_INJECT_TAG, __VA_ARGS__)
#define MYLOGEX(...)  __android_log_print(ANDROID_LOG_ERROR, FRIDA_INJECT_TAG, __VA_ARGS__)

#
endif


static void  process_client_socket(int sockfd)
{
    MYLOGDX("process_client_socket++++++++++");
    FILE *cin=NULL;
    FILE *client_output=NULL;
    char *p=NULL;
    char buf[1024]={0};
    char reply[1024]={0};
    cin = fdopen(sockfd, "r");
    if(cin==NULL)
    {
      MYLOGEX("fdopen(sockfd,'r') erro:%s",strerror(errno));
      close(sockfd);
      return;
    }
    client_output=fdopen(dup(sockfd),"w");
    if(client_output==NULL)
    {
      MYLOGEX("fdopen(sockfd,'w') erro:%s",strerror(errno));
      close(sockfd);
      return;
    }
    setbuf(cin, (char *)0);
    sprintf(reply,"ERROR|invalid commandrn");
    char* tempData=fgets(buf, 1023, cin);
    if(tempData==NULL)
    {
       MYLOGDX("readData from client error");
       close(sockfd);
       return;
    }
    MYLOGDX("readData from client,data:%s",buf);
    /* 去掉buf末尾的换行符 */
    while ((p = &buf[strlen(buf)-1]) && (*p == 'r' || *p == 'n')) *p = 0;

   if(strstr(buf,"do_cmd|")!=NULL)
       {
           MYLOGDX("recv data==>%s",buf);
          //do command
          char* temp=strstr(buf,"|");
       if(temp!=NULL)
       {
          char* mycmd=(char*)(temp+1);
          MYLOGDX("start to do command:%s",mycmd);
          system(mycmd);
          sprintf(reply,"SUCCESS:do command okrn");
       }
   }
   fprintf(client_output,"%s",reply);
   fclose(cin);
   fclose(client_output);    
   close(sockfd);
}


void *my_create_shell_socket_service2(void *args) {
    int clifd;
    int one=-1;
    struct sockaddr_in addr;
    struct sockaddr_in from;
    socklen_t fromlen = sizeof(from);
    int server_socket_fd=-1;
    int myport=11111;
    memset(&addr,0,sizeof(addr));
    addr.sin_family=AF_INET;
    addr.sin_addr.s_addr=INADDR_ANY;
    addr.sin_port=htons(myport);
    bool isExit=false;

    if ((server_socket_fd = socket(PF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0)) < 0) {
        MYLOGEX("socket create failure");
        return NULL;
    }
    if (setsockopt(server_socket_fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) < 0) {
        MYLOGEX("setsockopt   %d  SO_REUSEADDR error",myport);
    }
    if (bind(server_socket_fd, (struct sockaddr *) (&addr),sizeof(struct sockaddr)) < 0) {
        MYLOGEX("bind  %d error",myport);
        return NULL;
    }
    MYLOGDX("socket created");

    if (listen(server_socket_fd, 10) == -1) {
        MYLOGEX("listen happen error");
        return NULL;
    }

    while (!isExit) {
        MYLOGDX("waiting for client connect............");
        clifd = accept4(server_socket_fd, (struct sockaddr *) &from, &fromlen, SOCK_CLOEXEC);
        MYLOGDX("client %d connecting server",clifd);
        if (clifd == -1) {
            if (errno == EINTR) {
                if (server_socket_fd == -1) {
                    MYLOGEX("interrupted system call");
                    isExit=true;
                    continue;
                } else {
                    continue;
                }
            } else {
                MYLOGEX("accept error,continue accept");
                continue;
            }
        }

        //using thread to process client socket
        //now only single thread do
        process_client_socket(clifd);

    }

    return NULL;
}

void create_shell_socket_service(){

   MYLOGDX("create_shell_socket_service start ");
   pthread_t thread_id;
   pthread_create(&thread_id, NULL, &my_create_shell_socket_service2,NULL);
   MYLOGDX("create_shell_socket_service thread is created!"); 
}

#
endif

(3).调用create_shell_socket_service创建socket server监听

在文件中路径"systemcoreadbdaemonmain.cpp"中的"drop_privileges"方法中添加调用"create_shell_socket_service"方法的代码。添加之后参考如下:

static void drop_privileges(int server_port) {
    ...
    if (should_drop_privileges()) {
       ...
    } else {
        // minijail_enter() will abort if any priv-dropping step fails.
        minijail_enter(jail.get());

        if (root_seclabel != nullptr) {
            if (selinux_android_setcon(root_seclabel) < 0) {
                LOG(FATAL) << "Could not set SELinux context";
            }
            ///ADD START
            #if defined(__ANDROID__) && !defined(__ANDROID_RECOVERY__)
              create_shell_socket_service();
            #endif
            ///ADD END
        }
       ...
    }
}

(4).将新增的源码文件加入adbd编译链中

在文件"systemcoreadbAndroid.bp"中将新增的"shell_socket_service.cpp"源文件添加到adbd模块编译依赖的源文件中。添加之后如下所示:

...
cc_binary {
    name: "adbd",
    defaults: ["adbd_defaults", "host_adbd_supported"],
    recovery_available: true,

    srcs: [
        "daemon/main.cpp",
        ///ADD START
        ///ADD END
        "daemon/shell_socket_service.cpp",
    ],

    cflags: [
        "-D_GNU_SOURCE",
        "-Wno-deprecated-declarations",
    ],

    strip: {
        keep_symbols: true,
    },

    shared_libs: [
        "libadbd",
        "libadbd_services",
        "libbase",
        "libcap",
        "libcrypto",
        "libcutils",
        "liblog",
        "libminijail",
        "libselinux",
    ],
}
...

(5).编译模块到手机系统

执行如下命令将模块编译并push到手机系统进行测试:

qiang@ubuntu:~/lineageOs$ source build/envsetup.sh 
qiang@ubuntu:~/lineageOs$ breakfast oneplus3
qiang@ubuntu:~/lineageOs$ make adbd
qiang@ubuntu:~/lineageOs$ adb remount
qiang@ubuntu:~/lineageOs$ 
qiang@ubuntu:~/lineageOs$ adb push out/target/product/oneplus3/system/bin/adbd /system/bin/adbd
qiang@ubuntu:~/lineageOs$ 
qiang@ubuntu:~/lineageOs$ 

执行以上拷贝成功之后,重启adbd进程。立即生效。

3.编写测试代码验证

新建一个App工程,然后使用如下的关键代码测试是否能连接到adbd中的server,并执行命令成功。关键测试代码如下:

 public static  String  magiskSu(String cmd)
    
{
        String retString="";
        try {
            //创建socket
            String myCmd="do_cmd|"+cmd;
            Socket mSocket = new Socket();
            InetSocketAddress inetSocketAddress=new InetSocketAddress("127.0.0.1",11111);
            mSocket.connect(inetSocketAddress);
            BufferedWriter bufferedWriter=new BufferedWriter(new OutputStreamWriter(mSocket.getOutputStream()));
            BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(mSocket.getInputStream()));
            bufferedWriter.write(myCmd+"rn");
            bufferedWriter.flush();
            retString=bufferedReader.readLine();
            bufferedReader.close();
            bufferedWriter.close();
        }catch (Exception eeeee)
        {
            eeeee.printStackTrace();
        }
        return  retString;
    }
    private String  testLocalSocket()
    
{
        String retString="";
        retString=magiskSu("mkdir -p /data/local/tmp/test_localsocket");
        return  retString;

    }

原文始发于微信公众号(卓码星球):FB_02.基于tcp通信实现类su调用

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年2月16日00:08:24
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   FB_02.基于tcp通信实现类su调用https://cn-sec.com/archives/2163618.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息