文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Android设备上非root的抓包实现方法(Tcpdump方法)

2022-06-06 06:57

关注

通常我们在Android应用中执行某个命令时会使用“Runtime.getRuntime().exec("命令路径")”这种方式,但是当我们执行抓包操作时,使用这条命令无论如何都不行,通过下面代码打印结果发现,该命令一定要在root权限下才能执行。


BufferedReader brW = new BufferedReader(new InputStreamReader(p.getErrorStream()));
while((str = brW.readLine()) != null)
Log.d("cwmp", "w:"+str);

但是我们的Android设备(包括机顶盒、手机等)通常并没有root过,apk的最高权限也只是system权限,这该怎么解决?首先我们要知道,方法总比问题多,在Android设备的/system/bin路径下,我们会看到很多二进制文件,这些二进制文件可以获得root权限。因此,我们可以通过C语言来实现抓包功能,通过NDK把该C代码交叉编译成二进制文件置于/system/bin路径下,并赋予其root权限,此时,这个二进制文件就具备了抓包能力了。现在问题又来了,我们现在是想通过apk去调用这个抓包指定,抓包完成后又该怎么通知apk呢?其实,Android可以通过socket使底层与framework层进行通信,具体请参考Android中使用socket使底层和framework通信的实现方法。

接下来我们将贴出关键实现代码。

1、编写socket服务端代码fstiService.cpp,生成可执行脚本fstiService


#define SOCKET_NAME "fstiService"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "itv_assistance", __VA_ARGS__)
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/un.h>
#include <cutils/sockets.h>
#include <android/log.h>
#include <unistd.h>
#include <time.h>
#include <sys/time.h>
#include <pthread.h>
pthread_t thread[2];
char s_time[10]; //抓包时间子串
char s_command[256]; //抓包指令子串
//抓包指令:system("/system/bin/tcpdump -v -w /sdcard/te.pcap");
//获取进程tcpdump的进程号
int getPid() {
//for Linux C
//FILE *fp = popen("ps -e | grep \'tcpdump\' | awk \'{print $1}\'", "r");
//for Android(ARM)
//FILE *fp = popen("ps | grep \'tcpdump\'", "r");
FILE *fp = popen("ps | grep \'tcpdump\'", "r");
char buff[1024] = { 0 };
while (NULL != fgets(buff, sizeof(buff), fp))
;
//取消换行符(10)
buff[strlen(buff) - 1] = '\0';
pclose(fp);
char dst[5] = { 0 };
char *p = buff;
char *q = dst;
//每一行进程信息的第二个字符串为进程号
while (*p != ' ')
p++;
while (*p == ' ')
p++;
while (*p != ' ')
*(q++) = *(p++);
*(q++) = '\0';
return atoi(dst);
}
//截取子串(抓包时间(秒):抓包命令)
void substring(char *time, char *command, char *src) {
char *p = src;
char *q = time;
char *s = command;
while (*p != '/')
*(q++) = *(p++);
*(q++) = '\0';
//如果Tcpdump命令已添加环境变量,则添加下行代码
//否则删除下一行代码,client传递的参数格式必须为: num/tcpdump所在路径
p++;
while (*p)
*(s++) = *(p++);
*(s++) = '\0';
}
//抓包线程
void *thread1(void *arg) {
system(s_command);
}
void *thread2(void *arg) {
int i_time = atoi(s_time);
int begin = time((time_t*) NULL);
while (1) {
if (time((time_t*) NULL) - begin < i_time) {
//printf("当前时间(s):%ld\n", time((time_t*)NULL));
continue;
} else {
int n = kill(getPid(), SIGKILL);
LOGD("the kill process result is n=%d", n);
break;
}
}
return 0;
}
//创建子线程
void thread_create() {
int temp;
memset(&thread, 0, sizeof(thread));
if ((temp = pthread_create(&thread[0], NULL, thread1, NULL)) != 0)
LOGD("create tcpdump thread failure");
else
LOGD("create tcpdump thread success");
if ((temp = pthread_create(&thread[1], NULL, thread2, NULL)) != 0)
LOGD("create count thread failure");
else
LOGD("create count thread success");
}
void thread_wait() {
if (thread[0] != 0) {
pthread_join(thread[0], NULL);
LOGD("tcpdump thread has terminated");
}
if (thread[1] != 0) {
//pthread_join(thread[1], NULL);
printf("counter thread has terminated");
}
}

int main() {
int connect_number = 6;
int fdListen = -1, new_fd = -1;
int ret;
struct sockaddr_un peeraddr;
socklen_t socklen = sizeof(peeraddr);
int numbytes;
char buff[256];
//这一步很关键,就是获取init.rc中配置的名为 "fstiService" 的socket
//获取已绑定的socket,返回-1为错误情况
fdListen = android_get_control_socket(SOCKET_NAME);
if (fdListen < 0) {
LOGD("failed to get socket '" SOCKET_NAME "' errno %d", errno);
exit(-1);
}

ret = listen(fdListen, connect_number);
LOGD("listen result %d", ret);
if (ret < 0) {

perror("listen");
exit(-1);
}

new_fd = accept(fdListen, (struct sockaddr *) &peeraddr, &socklen);
LOGD("accept_fd %d", new_fd);
if (new_fd < 0) {
LOGD("%d", errno);
perror("accept error");
exit(-1);
}
//循环等待Socket客户端发来消息
while (1) {

if ((numbytes = recv(new_fd, buff, sizeof(buff), 0)) == -1) {
LOGD("%d", errno);
perror("recv");
continue;
}
LOGD("the parameter received from socket client is %s", buff);
if(strcmp(buff, "exit") != 0){
substring(s_time, s_command, buff);
thread_create();
thread_wait();
}
char result[10] = "successp";

int sendR = send(new_fd, result, strlen(result), 0);
//apk退出后,buff中仍然缓存之前的调用命令,此时会额外再执行一次抓包,固下面代用重写buff中数据
strcpy(buff, "exit");
if (sendR == -1) {
perror("send");
close(new_fd);
exit(0);
}
}
close(new_fd);
close(fdListen);
return 0;
}

2、配置init.rc文件,添加如下配置


service fstiService /system/bin/fstiService
socket fstiService stream 777 system system
class main

此处配置了一个名为“fstiService”的服务,Android设备开机会自动启动并运行/system/bin/fstiService这个脚本文件。服务端代码完成后,我们需要将其编译成可执行脚本fstiService,Android.mk内容如下:


LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#指定该模块在所有版本下都编译
LOCAL_MODULE_TAGS :=optional
LOCAL_MODULE := fstiService
LOCAL_SRC_FILES := fstiService.cpp
LOCAL_LDLIBS := -llog
#编译成动态库
#include $(BUILD_SHARED_LIBRARY)
#编译成可执行文件
include $(BUILD_EXECUTABLE)

3、Android客户端代码


public class SocketClient {
private final String SOCKET_NAME = "fstiService";
private LocalSocket client = null;
private LocalSocketAddress address = null;
private boolean isConnected = false;
private int connectTime = 1;
public SocketClient(){
client = new LocalSocket();
//A socket in the Android reserved namespace in /dev/socket. 
//Only the init process may create a socket here
address = new LocalSocketAddress(SOCKET_NAME, LocalSocketAddress.Namespace.RESERVED);
new ConnectSocketThread().start();
}

public String sendMsg(String msg){
if(!isConnected)
return "Connect failure";
try{
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
PrintWriter out = new PrintWriter(client.getOutputStream());
out.println(msg);
out.flush();
return in.readLine();
}catch(IOException e){
e.printStackTrace();
}
return "Nothing Return";
}

private class ConnectSocketThread extends Thread{
@Override
public void run() {
while(!isConnected && connectTime <= 3){
try{
sleep(1000);
Log.d("itv_assistance", "Try to connect socket; ConnectTime: "+connectTime);
client.connect(address);
isConnected = true;
}catch(Exception e){
connectTime++;
isConnected = false;
Log.d("itv_assistance", "Connect Failure");
}
}
}
}

public void closeSocket(){
try{
client.close();
}catch(IOException e){
e.printStackTrace();
}
}
}

  至此,基于非root的Android设备上的抓包实现方法就完成了,接下来就是编译系统进行测试了,这步我没有亲自去做,而是把fstiService脚本及init.rc配置文件的操作交给合作厂商来做了,apk是我们自己做的,经测试一切OK。

点击下载源码:http://xiazai.jb51.net/201611/yuanma/AndroidFstiService(jb51.net)

以上所述是小编给大家介绍的Android设备上非root的抓包实现方法(Tcpdump方法),实现一个模拟后台数据登入的效果,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程网网站的支持!

您可能感兴趣的文章:vc++实现的tcp socket客户端和服务端示例基于C#的socket编程的TCP异步的实现代码Java Socket编程实例(四)- NIO TCP实践Java Socket编程实例(三)- TCP服务端线程池Java Socket编程实例(一)- TCP基本使用linux抵御DDOS攻击 通过iptables限制TCP连接和频率C#基于TCP协议的服务器端和客户端通信编程的基础教程java实现一个简单TCPSocket聊天室功能分享Android使用socket创建简单TCP连接的方法Android实现TCP客户端接收数据的方法C++ boost::asio编程-异步TCP详解及实例代码


阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-移动开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯