现在的位置: 首页 > 综合 > 正文

ios下进程详细信息获取

2018年07月08日 ⁄ 综合 ⁄ 共 9128字 ⁄ 字号 评论关闭

最近弄了一个iphone5,看到网上的越狱教程,就顺便越狱了,并且下载了一套开发环境【注1】由于可以ssh登录,并且直接在手机上进行开发,这激起了我的兴趣——这不就是将手机变成一台linux服务器,然后在上面耍吗!{:lol:}
由于我只会c/c++,完全没有object-c基础和苹果其他开发软件基础,参考/var/mobile/Projects/StandardCLibrary/(详情见注1)项目,所以我先试着用c++写了一个helloword
嗯,效果还不错,可以直接运行。这让我一下找到了感觉,这和linux程序开发也没有太大的区别嘛
好了,既然这样那就进一步试一试,写个进程信息分析工具试一试!
注意到iphone系统根本没有/proc目录,所以很多以前linux下面的套路完全用不上了
只能使用sysctl接口来模拟,先拿到所有进程的列表再说【注2】好了,拿到列表了但是怎么获取进程内存信息呢?
这倒是个麻烦。首先参考了http://iosre.com/forum.php?mod=viewthread&tid=105&extra=page%3D1 英文的
大意讲了这么一件事情:我们一般使用的是虚拟地址(比如0x12345678 这个是所谓内存地址)虚拟地址会被系统映射到物理内存地址。物理内存是有分块的,每一个进程都有一个region,而每一个region又分为若干个page。
获取进程内存信息就落在region上了。
由于每个进程都有一个region,相互都是一对一的关系(不知道我的理解是不是错误的),所以只要拿到region信息就能够得到进程使用内存的详细信息。
OK下一步就是如何获取region信息了
当你包含了mach/mach.h头文件之后,就可以使用一个函数vm_region
说明一下,刚才提到的英文资料,里面给出的示例使用的是mach_vm_region函数。我试了一下,^&@#!的根本编译不过去,我#$%!
然后各种资料查询无果,翻墙无果。最后看头文件,找到了vm_region和上面的很像,再查这个函数,发现功能描述和上面一样,我只能呵呵了。
然后将mach_vm_read、mach_vm_write替换成了vm_read、vm_write。注意参数类型有点小小的变动,对应的修改一下,就可以用了。
makefile、签名文件和代码见【注3】
这里特别提一下签名文件ent.xml

 

ldid -Sent.xml obj/$(TOOL_NAME)

如果没有这个对文件进行签名,则程序只能打开wheel用户开启的进程(这个是普通用户)。任何其他进程,包括mobile用户的进程,都无法访问。vm_region会返回-1 errno显示错误5 kern error

好了,到这里,所有进程以及其内存使用详情现在都有了,下面我要开始分析这些内存数据,看看他们到底都是一些啥,以后会补充我的发现,待续……
你可以参考英文资料继续写一个游戏修改器,也可以利用这些信息进行更多的操作
【注1】:开发环境镜像:
http://yunpan.cn/cKF4nvseXsiWB  访问密码
d03e

安装参考命令:(注意安装前不要有任何gcc gdb等东东,如果有请先卸载,否则可能导致未知的问题)

  • cd /var/root/
  • tar xzvf iiphonedev_v5.1_ios81.tgz
  • cd /var/root/iphonedev/DEBS
  • dpkg -i *.deb
  • cd /var/root/iphonedev/
  • mv Projects /var/mobile/
  • rm -fr /var/theos
  • mv theos /var/

参考资料:
iPhone 或 iPad 安装 llvm-clang, THEOS 编译程序或插件, 更新支持 iOS SDK 8.1 arm64

【注2】
获取所有正在运行的进程列表信息,参考如下:

        int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL ,0};//调用CTL_KERN接口下的KERN_PROC功能,获取所有的进程信息(其实只有pid groupid uid session ruid lcid tty这七种信息)
        size_t len,count;
        PROCINF *kp = 0;
        int ret = 0;
        printf("%s(%d):%s uid %d\n",__FILE__,__LINE__,__FUNCTION__,getuid());
        ret = sysctl(mib, 4, 0, &len, NULL, 0);//获取信息长度 mib最后一个为0表明获取所有进程信息
        printf("%s(%d):%s %d %lu\n",__FILE__,__LINE__,__FUNCTION__,ret,len);
        if(ret<0){
                return;
        }
        count = (len+sizeof(PROCINF)-1)/sizeof(PROCINF);//按照结构体大小,进行对齐,得到真正的个数
        kp = new PROCINF[count];
        if(kp==0){
                printf("%s(%d):%s no more memory\n",__FILE__,__LINE__,__FUNCTION__);
                return;
        }
        memset(kp,0,len);
        ret = sysctl(mib, 4, kp, &len, NULL, 0);//获取全部的进程信息
        printf("%s(%d):%s %d %lu\n",__FILE__,__LINE__,__FUNCTION__,ret,len);
        count = len/sizeof(PROCINF);//这里有个坑,前后两次调用获取到的len可能并不一定相同,所以要重新计算count数量,方便后面遍历。否则count可能大于实际数量

【注3】
Makefile

TARGET := iphone:clang

THEOS_PLATFORM_SDK_ROOT_armv6 = /var/theos/sdks/iPhoneOS5.1.sdk
THEOS_PLATFORM_SDK_ROOT_armv7 = /var/theos/sdks/iPhoneOS6.1.sdk
THEOS_PLATFORM_SDK_ROOT_arm64 = /var/theos/sdks/iPhoneOS7.1.sdk 

SDKVERSION_armv6 = 5.1
SDKVERSION_armv7 = 6.1
SDKVERSION_arm64 = 7.1

TARGET_IPHONEOS_DEPLOYMENT_VERSION_armv6 = 5.1
TARGET_IPHONEOS_DEPLOYMENT_VERSION_armv7 = 6.1
TARGET_IPHONEOS_DEPLOYMENT_VERSION_arm64 = 7.1

IPHONE_ARCHS = armv7 #armv6 arm64 #iphone 5使用7 iphone4使用 6

LOCAL_OBJ_PATH = obj

export THEOS=/var/theos
include $(THEOS)/makefiles/common.mk

TOOL_NAME = test
test_FILES = main.cpp

include $(THEOS_MAKE_PATH)/tool.mk

cmd:    stage
        echo $(THEOS_STAGING_DIR)
        @pwd
        @if [ -d obj ];then echo "already has obj directory";else mkdir obj;fi
        @if [ -f .theos/obj/armv7/$(TOOL_NAME) ];then cp .theos/obj/armv7/$(TOOL_NAME) ./obj/;fi
        @if [ -f .theos/obj/armv7/$(TOOL_NAME) ];then ldid -Sent.xml obj/$(TOOL_NAME);fi

mian.cpp

#include <stdio.h>
#include <memory.h>
#include <map>
#include <list>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/mount.h>
#include <mach/mach.h>
#include <string>
typedef struct _tag_Process_Info_{
_tag_Process_Info_(){
nUid = -1;
nPid = -1;
nPpid = -1;
nPgid = -1;
nSessionID = -1;
nJobc = -1;
*(int*)strStatus = 0;
memset(strTT,0,sizeof(strTT));
memset(strTime,0,sizeof(strTime));
}
int nUid;//user id
pid_t nPid;//Process ID
pid_t nPpid;//Parent Process ID
pid_t nPgid;//Process Group Number
int nSessionID;
int nJobc;//job control count
char strStatus[4];
char strTT[8];//control terminal name (two letter abbreviation)
char strTime[16];//accumulated CPU time, user + system (alias cputime)
ProArgs clsArgs;//command and arguments
}PINF;

void getprocinf(pid_t pid,PINF* pinf)
{
<span style="white-space:pre">	</span>int mib[3];
<span style="white-space:pre">	</span>mib[0] = CTL_KERN;
<span style="white-space:pre">	</span>mib[1] = KERN_ARGMAX;
<span style="white-space:pre">	</span>size_t size = 0;
<span style="white-space:pre">	</span>size_t len = 4;
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>int ret = sysctl(mib, 2, &size, &len, NULL, 0);
<span style="white-space:pre">	</span>printf("%s(%d):%s ret = %d size %lu\n",__FILE__,__LINE__,__FUNCTION__,ret,size);


<span style="white-space:pre">	</span>mib[0] = CTL_KERN;
<span style="white-space:pre">	</span>mib[1] = KERN_PROCARGS2;
<span style="white-space:pre">	</span>mib[2] = pid;
<span style="white-space:pre">	</span>char* buf = new char[size];
<span style="white-space:pre">	</span>memset(buf,0,size);
<span style="white-space:pre">	</span>if(buf){
<span style="white-space:pre">		</span>ret = sysctl(mib, 3, buf, &size, NULL, 0);
<span style="white-space:pre">		</span>printf("%s(%d):%s ret = %d size %lu\n",__FILE__,__LINE__,__FUNCTION__,ret,size);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>pinf->clsArgs.nArgc = *(int*)buf;
<span style="white-space:pre">	</span>char* pcmd = buf+sizeof(int);
<span style="white-space:pre">	</span>pinf->clsArgs.strProcPathName = pcmd;
<span style="white-space:pre">	</span>len = strlen(pcmd);
<span style="white-space:pre">	</span>len += (4-(len%4));
<span style="white-space:pre">	</span>pcmd += len;
<span style="white-space:pre">	</span>if(pinf->clsArgs.nArgc>0){
<span style="white-space:pre">		</span>pinf->clsArgs.lstArgv.resize(*(int*)buf);
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>for(int i=0;i<pinf->clsArgs.nArgc;i++)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>printf("%s(%d):%s argv[%d]=%s\n",__FILE__,__LINE__,__FUNCTION__,i,pcmd);
<span style="white-space:pre">		</span>pinf->clsArgs.lstArgv[i] = pcmd;
<span style="white-space:pre">		</span>pcmd += strlen(pcmd);
<span style="white-space:pre">		</span>while(*pcmd == 0 && (pcmd<buf+size))
<span style="white-space:pre">			</span>pcmd++;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>while(*pcmd != 0)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>printf("%s(%d):%s env[%d]=%s\n",__FILE__,__LINE__,__FUNCTION__,
<span style="white-space:pre">			</span>pinf->clsArgs.nEnvc,pcmd);
<span style="white-space:pre">		</span>pinf->clsArgs.lstEnv.push_back(string(pcmd));
<span style="white-space:pre">		</span>pinf->clsArgs.nEnvc++;
<span style="white-space:pre">		</span>pcmd += strlen(pcmd);
<span style="white-space:pre">		</span>while(*pcmd == 0 && (pcmd<buf+size))
<span style="white-space:pre">			</span>pcmd++;
<span style="white-space:pre">	</span>}
<span style="white-space:pre">	</span>delete[]buf;
}

int main(int argc,char*argv[])
{
        size_t i;
	int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL ,0};
	size_t len,count;
	PROCINF *kp = 0;
	int ret = 0;
	
	printf("%s(%d):%s uid %d\n",__FILE__,__LINE__,__FUNCTION__,getuid());
	ret = sysctl(mib, 4, 0, &len, NULL, 0);//获取信息长度 mib最后一个为0表明获取所有进程信息
	printf("%s(%d):%s %d %lu\n",__FILE__,__LINE__,__FUNCTION__,ret,len);
	if(ret<0){
		return;
	}
	count = (len+sizeof(PROCINF)-1)/sizeof(PROCINF);
	kp = new PROCINF[count];
	if(kp==0){
		printf("%s(%d):%s no more memory\n",__FILE__,__LINE__,__FUNCTION__);
		return;
	}
	memset(kp,0,len);
	ret = sysctl(mib, 4, kp, &len, NULL, 0);//获取全部的进程信息
	printf("%s(%d):%s %d %lu\n",__FILE__,__LINE__,__FUNCTION__,ret,len);
	count = len/sizeof(PROCINF);
	if(ret == 0){
		for(i=0;i<count;i++)
		{
			PINF info;
			info.nPid = kp[i].kp_proc.p_pid;
			getprocinf(kp[i].kp_proc.p_pid,&info);
			mach_port_t task;
			kern_return_t kret = task_for_pid(mach_task_self(),kp[i].kp_proc.p_pid,&task);
			printf("%d %s %02X %u\n",kp[i].kp_proc.p_pid,kp[i].kp_proc.p_comm,
				kp[i].kp_proc.p_stat&0xFF,task);
			if(kret == KERN_SUCCESS){
				mach_port_name_array_t name = 0;
				mach_msg_type_number_t namelen = 0;
				mach_port_type_array_t types = 0;
				mach_msg_type_number_t typelen = 0;
				kret = mach_port_names(task,&name,&namelen,&types,&typelen);
				if(kret == KERN_SUCCESS)
				{
					printf("%s(%d):%s %p %u %p %u\n",__FILE__,__LINE__,__FUNCTION__,
						name,namelen,types,typelen);
				}
				vm_address_t address = 0;
				vm_size_t size = 0;
				vm_region_basic_info_64 info;
				mach_msg_type_number_t ct = VM_REGION_BASIC_INFO_COUNT_64;
				mach_port_t object_name;
				while (vm_region(task, &address, &size, VM_REGION_BASIC_INFO, 
					(vm_region_info_t)&info, &ct, &object_name) == KERN_SUCCESS)
				{
					vm_prot_t protection = info.protection;
					if(memcmp(kp[i].kp_proc.p_comm,"sftp-server",4)==0){
						printf("%s(%d):%s address %08X %d size %u\n",__FILE__,__LINE__,__FUNCTION__,
							address,protection,size);
						char* data=0;
						mach_msg_type_number_t datalen = size;
						{
							//kret = vm_read(task,address,size,(vm_offset_t*)&data,&datalen);
							if(kret == KERN_SUCCESS){
								printf("%s(%d):%s address %08X %d size %u\n",__FILE__,__LINE__,__FUNCTION__,
									address,protection,size);
							}else{
								printf("%s(%d):%s address %08X size %u\n",__FILE__,__LINE__,__FUNCTION__,
									(unsigned int)data,datalen);
							}
						}
					}
					address += size;
				}
			}else{
				printf("%s(%d):%s error(%d):%s %d\n",__FILE__,__LINE__,__FUNCTION__,
					kret, mach_error_string(kret),mach_host_self());
			}
		}
	}
	if(kp){
		delete[]kp;
	}
	printf("%s(%d):%s\n",__FILE__,__LINE__,__FUNCTION__);
}

ent.xml

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
        <key>com.apple.springboard.debugapplications</key>
        <true/>
        <key>get-task-allow</key>
        <true/>
        <key>proc_info-allow</key>
        <true/>
        <key>task_for_pid-allow</key>
        <true/>
        <key>run-unsigned-code</key>
        <true/>
</dict>
</plist>



【上篇】
【下篇】

抱歉!评论已关闭.