Linux下修改進程名稱


catalog

1. 應用場景
2. 通過Linux prctl修改進程名
3. 通過修改進程argv[0]修改進程名
4. 通過bash exec命令修改一個進程的cmdline信息

 

1. 應用場景

1. 標識父子進程名稱,防止被誤殺
2. 構造假的進程名及參數,引導非法進入人員到蜜罐系統,取證
3. 惡意程序、木馬會通過"檫除"自己的進程名,使ps的時候顯示的是一個無名字的進程,同時刪除進程對應磁盤上的文件

Relevant Link:

http://blog.chinaunix.net/uid-29482215-id-4120748.html

 

2. 通過Linux prctl修改進程名

雖然Linux將所有資源對象都抽象為了文件,但是對一些特殊作用的文件特別定制了一些特別的API集合,對其進行特殊操作,prctl就是其中一個例子

prctl - operations on a process
#include <sys/prctl.h>
int prctl(int option, unsigned long arg2, unsigned long arg3,unsigned long arg4, unsigned long arg5);

prctl() is called with a first argument describing what to do (with values defined in <linux/prctl.h>), and further arguments with a significance depending on the first one. The first argument can be:

1. PR_CAPBSET_READ
2. PR_CAPBSET_DROP 
3. PR_SET_CHILD_SUBREAPER 
4. PR_GET_CHILD_SUBREAPER 
5. PR_SET_DUMPABLE 
6. PR_SET_ENDIAN 
7. PR_GET_ENDIAN 
8. PR_SET_FPEMU 
9. PR_GET_FPEMU 
10. PR_SET_FPEXC 
11. PR_GET_FPEXC 
12. PR_SET_KEEPCAPS 
13. PR_GET_KEEPCAPS 
14. PR_SET_NAME 
    1) Set the name of the calling thread, using the value in the location pointed to by (char *) arg2.  
    2) The name can be up to 16 bytes long, including the terminating null byte. (If the length of the string, including the terminating null byte, exceeds 16 bytes, the string is silently truncated.) 
    3) This is the same attribute that can be set via pthread_setname_np and retrieved using pthread_getname_np.  
    4) The attribute is likewise accessible via /proc/self/task/[tid]/comm, where tid is the name of the calling thread.
15. PR_GET_NAME 
16. PR_SET_NO_NEW_PRIVS 
17. PR_GET_NO_NEW_PRIVS 
18. PR_SET_PDEATHSIG 
19. PR_GET_PDEATHSIG 
20. PR_SET_PTRACER 
21. PR_SET_SECCOMP 
22. PR_GET_SECCOMP 
23. PR_SET_SECUREBITS 
24. PR_GET_SECUREBITS 
25. PR_SET_THP_DISABLE 
26. PR_GET_THP_DISABLE 
27. PR_GET_TID_ADDRESS 
28. PR_SET_TIMERSLACK 
29. PR_GET_TIMERSLACK 
30. PR_SET_TIMING 
31. PR_GET_TIMING 
32. PR_TASK_PERF_EVENTS_DISABLE 
33. PR_TASK_PERF_EVENTS_ENABLE 
34. PR_SET_TSC 
35. PR_GET_TSC 
36. PR_SET_UNALIGN
37. PR_GET_UNALIGN
38. PR_MCE_KILL 
39. PR_MCE_KILL_GET 
40. PR_SET_MM 
41. PR_MPX_ENABLE_MANAGEMENT, PR_MPX_DISABLE_MANAGEMENT

0x1: Code Example

/*
gcc changetitle.c -o changetitle
*/
#include <stdio.h>
#include <sys/prctl.h>

int main(int argc, char *argv[], char *envp[])
{
    char *new_name = "littlehann-program";
    
    getchar();
    prctl(PR_SET_NAME, new_name);
    getchar();

    return 0;
}

但是prctl修改的進程名,只能是16個字節(包括'\0'),同時,過ps -aux 查看,進程名稱並沒有改變,改變的只是/prco/$(PID)/stat和/prco/$(PID)/status的值,而/prco/$(PID)/cmdline並沒有改變

Relevant Link:

http://man7.org/linux/man-pages/man2/prctl.2.html
http://blog.csdn.net/dahailantian1/article/details/5950824
http://www.cppblog.com/beautykingdom/archive/2009/11/08/100419.aspx

 

3. 通過修改進程argv[0]修改進程名

/*
gcc test.c -o test
*/
#include <stdio.h>
#include <string.h>

extern char **environ;
int main(int argc , char *argv[])
{
    int i;

    printf("argc:%d\n" , argc);

    for (i = 0; i < argc; ++i)
    {
        printf("argv[%d](0x%x):%s\n" , i , (unsigned int)argv[i], argv[i]);
    }

    printf("evriron=0x%x\n" , (unsigned int)environ[0]);

    return 0;
}

通過代碼運行結果可以看出,我們只需要在進程啟動時修改argv[0]所指向的內存空間的內容,就可以修改進程名

1. 如果新名稱比argv[0]的長度小,我們可以直接修改,並把多余的部分請0
2. 如果新名稱比argv[0]長我們需要兩步 
    1) 申請新內存保存環境變量信息和argv[1...argc-1]參數信息
    2) 修改argv[0],將新名稱往后到environ的最后一項清0

0x1: Code Example

/*
gcc changetitle.c -o changetitle
*/
#include <unistd.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <stdlib.h>
#include <sys/prctl.h>

# 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;
}

Relevant Link:

http://blog.chinaunix.net/uid-29482215-id-4120748.html

 

4. 通過bash exec命令修改一個進程的cmdline信息

exec -l -a "littlehann-prog" bash
ps
ps -l 29116

Relevant Link: 

http://blog.ailms.me/2014/05/24/bash-exec-usage-example.html

 

Copyright (c) 2015 LittleHann All rights reserved

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM