android程序名修改,[原创]Android修改进程名

本文详细分析了Android应用进程名称的设置过程,指出在Android中修改进程名称的方法与Linux类似,主要通过反射调用`setArgV0`方法和使用`prctl`系统调用来实现。博客还提供了相关的源码分析,展示了如何在Linux中修改进程名,并给出了示例代码。通过修改进程名,可以影响`ps`、`cmdline`和`/proc/<pid>/status`等输出,但进程的uid仍然是标识身份的重要依据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

通过分析Android应用进程的创建启动流程,知道设置应用进程的名称是在(这部分各个版本的系统实现都大同小异,还是看4.4的代码)http://androidxref.com/4.4_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java#handleBindApplication

private void handleBindApplication(AppBindData data) {

mBoundApplication = data;

mConfiguration = new Configuration(data.config);

mCompatConfiguration = new Configuration(data.config);

mProfiler = new Profiler();

mProfiler.profileFile = data.initProfileFile;

mProfiler.profileFd = data.initProfileFd;

mProfiler.autoStopProfiler = data.initAutoStopProfiler;

// send up app name; do this *before* waiting for debugger

Process.setArgV0(data.processName);

android.ddm.DdmHandleAppName.setAppName(data.processName,

UserHandle.myUserId());

thread-253676.htm

所以反射调用即可修改进程名,ddm应该是ddms调试用的,这个不改应该也可以。

try {

Method setArgV0 = Process.class.getDeclaredMethod("setArgV0", String.class);

setArgV0.setAccessible(true);

setArgV0.invoke(null,"com.tencent.mm");

} catch (Throwable e) {

e.printStackTrace();

}

thread-253676.htm

结合之前的linux修改进程名,

//字符串包括结尾符号\0不能超过16,而且这个只是改了proc/pid/stat/\status中的字符串

const char* new_name = "mytest";

prctl(PR_SET_NAME, new_name);

thread-253676.htm

或者这样可以改变ps、cmdline的进程名

/*

gcc changetitle.c -o changetitle

*/

#include

#include

#include

#include

#include

#include

# define MAXLINE 2048

extern char **environ;

static char **g_main_Argv = NULL; /* pointer to argument vector */

static char *g_main_LastArgv = NULL; /* end of argv */

void setproctitle_init(int argc, char **argv, char **envp)

{

int i;

for (i = 0; envp[i] != NULL; i++) // calc envp num

continue;

environ = (char **) malloc(sizeof (char *) * (i + 1)); // malloc envp pointer

for (i = 0; envp[i] != NULL; i++)

{

environ[i] = malloc(sizeof(char) * strlen(envp[i]));

strcpy(environ[i], envp[i]);

}

environ[i] = NULL;

g_main_Argv = argv;

if (i > 0)

g_main_LastArgv = envp[i - 1] + strlen(envp[i - 1]);

else

g_main_LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);

}

void setproctitle(const char *fmt, ...)

{

char *p;

int i;

char buf[MAXLINE];

extern char **g_main_Argv;

extern char *g_main_LastArgv;

va_list ap;

p = buf;

va_start(ap, fmt);

vsprintf(p, fmt, ap);

va_end(ap);

i = strlen(buf);

if (i > g_main_LastArgv - g_main_Argv[0] - 2)

{

i = g_main_LastArgv - g_main_Argv[0] - 2;

buf[i] = '\0';

}

//修改argv[0]

(void) strcpy(g_main_Argv[0], buf);

p = &g_main_Argv[0][i];

while (p < g_main_LastArgv)

*p++ = '\0';

g_main_Argv[1] = NULL;

//调用prctl

prctl(PR_SET_NAME,buf);

}

int main(int argc, char *argv[])

{

char argv_buf[MAXLINE] = {0}; // save argv paramters

int i;

for( i = 1; i < argc; i++)

{

strcat(argv_buf, argv[i]);

strcat(argv_buf, " ");

}

//修改argv[0]所指向的内存空间的内容

setproctitle_init(argc, argv, environ);

//调用prctl修改进程名

setproctitle("%s@%s %s", "littlehann-prog", "ip", argv_buf);

for (i = 0; environ[i] != NULL; i++)

free(environ[i]);

getchar();

return 0;

}

thread-253676.htm

对比下Android是如果实现的,http://androidxref.com/4.4_r1/xref/frameworks/native/libs/binder/ProcessState.cpp#305

首先把进程名覆盖了mArgV第一个数组,之后也是调用

prctl(PR_SET_NAME, (unsigned long) new_name, 0, 0, 0);

// Global variables

int mArgC;

const char* const* mArgV;

int mArgLen;

void ProcessState::setArgV0(const char* txt)

{

if (mArgV != NULL) {

strncpy((char*)mArgV[0], txt, mArgLen);

set_process_name(txt);

}

}

thread-253676.htm//http://androidxref.com/4.4_r1/xref/system/core/libcutils/process_name.c#37

void set_process_name(const char* new_name) {

#ifdef HAVE_ANDROID_OS

char propBuf[PROPERTY_VALUE_MAX];

#endif

if (new_name == NULL) {

return;

}

// We never free the old name. Someone else could be using it.

int len = strlen(new_name);

char* copy = (char*) malloc(len + 1);

strcpy(copy, new_name);

process_name = (const char*) copy;

#if defined(HAVE_PRCTL)

if (len < 16) {

prctl(PR_SET_NAME, (unsigned long) new_name, 0, 0, 0);

} else {

prctl(PR_SET_NAME, (unsigned long) new_name + len - 15, 0, 0, 0);

}

#endif

#ifdef HAVE_ANDROID_OS

// If we know we are not running in the emulator, then return.

if (running_in_emulator == 0) {

return;

}

// If the "running_in_emulator" variable has not been initialized,

// then do it now.

if (running_in_emulator == -1) {

property_get("ro.kernel.qemu", propBuf, "");

if (propBuf[0] == '1') {

running_in_emulator = 1;

} else {

running_in_emulator = 0;

return;

}

}

// If the emulator was started with the "-trace file" command line option

// then we want to record the process name in the trace even if we are

// not currently tracing instructions (so that we will know the process

// name when we do start tracing instructions). We do not need to execute

// this code if we are just running in the emulator without the "-trace"

// command line option, but we don't know that here and this function

// isn't called frequently enough to bother optimizing that case.

int fd = open(PROCESS_NAME_DEVICE, O_RDWR);

if (fd < 0)

return;

write(fd, process_name, strlen(process_name) + 1);

close(fd);

#endif

}

thread-253676.htm

从名字上猜应该mArgV应该就是main函数接收的argv,我们知道Android应用进程其实都是fork自zygote,而zygote的可执行文件就是app_process

http://androidxref.com/4.4_r1/xref/frameworks/base/cmds/app_process/app_main.cpp#169

int main(int argc, char* const argv[])

{

#ifdef __arm__

/*

* b/7188322 - Temporarily revert to the compat memory layout

* to avoid breaking third party apps.

*

* THIS WILL GO AWAY IN A FUTURE ANDROID RELEASE.

*

* http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=7dbaa466

* changes the kernel mapping from bottom up to top-down.

* This breaks some programs which improperly embed

* an out of date copy of Android's linker.

*/

char value[PROPERTY_VALUE_MAX];

property_get("ro.kernel.qemu", value, "");

bool is_qemu = (strcmp(value, "1") == 0);

if ((getenv("NO_ADDR_COMPAT_LAYOUT_FIXUP") == NULL) && !is_qemu) {

int current = personality(0xFFFFFFFF);

if ((current & ADDR_COMPAT_LAYOUT) == 0) {

personality(current | ADDR_COMPAT_LAYOUT);

setenv("NO_ADDR_COMPAT_LAYOUT_FIXUP", "1", 1);

execv("/system/bin/app_process", argv);

return -1;

}

}

unsetenv("NO_ADDR_COMPAT_LAYOUT_FIXUP");

#endif

// These are global variables in ProcessState.cpp

mArgC = argc;

mArgV = argv;

mArgLen = 0;

for (int i=0; i

mArgLen += strlen(argv[i]) + 1;

}

mArgLen--;

AppRuntime runtime;

const char* argv0 = argv[0];

// Process command line arguments

// ignore argv[0]

argc--;

argv++;

// Everything up to '--' or first non '-' arg goes to the vm

int i = runtime.addVmArguments(argc, argv);

// Parse runtime arguments. Stop at first unrecognized option.

bool zygote = false;

bool startSystemServer = false;

bool application = false;

const char* parentDir = NULL;

const char* niceName = NULL;

const char* className = NULL;

while (i < argc) {

const char* arg = argv[i++];

if (!parentDir) {

parentDir = arg;

} else if (strcmp(arg, "--zygote") == 0) {

zygote = true;

niceName = "zygote";

} else if (strcmp(arg, "--start-system-server") == 0) {

startSystemServer = true;

} else if (strcmp(arg, "--application") == 0) {

application = true;

} else if (strncmp(arg, "--nice-name=", 12) == 0) {

niceName = arg + 12;

} else {

className = arg;

break;

}

}

if (niceName && *niceName) {

setArgv0(argv0, niceName);

set_process_name(niceName);

}

runtime.mParentDir = parentDir;

if (zygote) {

runtime.start("com.android.internal.os.ZygoteInit",

startSystemServer ? "start-system-server" : "");

} else if (className) {

// Remainder of args get passed to startup class main()

runtime.mClassName = className;

runtime.mArgC = argc - i;

runtime.mArgV = argv + i;

runtime.start("com.android.internal.os.RuntimeInit",

application ? "application" : "tool");

} else {

fprintf(stderr, "Error: no class name or --zygote supplied.\n");

app_usage();

LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");

return 10;

}

}

thread-253676.htm

所以其实Android修改进程名和Linux其实是一样的。

这里就用最简单的方式反射调用setArgV0后,ps查看进程

# ps|grep ent.mm

u0_a122   2701  182   1013884 53440 ffffffff 400f773c S com.tencent.mm:push

u0_a91    8812  182   914212 42496 ffffffff 400f773c S com.tencent.mm

2701是mm的推送进程,8812为改名后的进程,可见进程名可以骗过了,uid还是出卖了自己。

argv、cmdline欺骗ps

# cat proc/8812/cmdline

com.tencent.mm

prctl(PR_SET_NAME, new_name);欺骗stat、status等。

# cat /proc/8812/status

Name:com.tencent.mm

State:S (sleeping)

Tgid:8812

Pid:8812

PPid:182

TracerPid:0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值