­

两个主题:躲避execve与分析/proc/目录

今天比较特别,讲两个主题,主要是为了承上启下,进行补充和过渡。

躲避execve,是在原来的文章的基础上补充一个小思路,分析/proc/目录 是为了下一篇讲解内存中修改函数做准备,要让大家提前知道这回事。

本公众号以原创干货为主,原创不易,大家如果喜欢本篇文章的话,记得点在看和转发朋友圈

1. 躲避execve的小思路

在之前文章中,我讲解过各种躲避execve监控的方法,如果有朋友没看到过,可以点下面文章链接熟悉一下:

无"命令"反弹shell-逃逸基于execve的命令监控(上)

linux无文件执行— fexecve 揭秘

本文的思路,类似文件复制重命名,躲避execve监控的关键点在于创建软链接,通过创建软链接的方式来混淆命令执行的路径。下面以whoami命令为例:

ln -s /bin/whoami /tmp/whoami_tmp

接着使用strace调试执行/tmp/whoami_tmp,看一下execve的系统调用:

strace -f /tmp/whoami_tmp

由于execve执行软链接,会自动执行目标文件,不会对软链接进行转换,从而实现了隐藏。

不要以为这就结束了!!!

虽然最后执行的时候混淆了,但是在执行ln命令的时候,还是暴露了命令路径,暴露了关键字。

可以对目录下的文件进行批量创建软连接:

cp -s /bin/* /tmp/

然后对 /tmp下的软链接批量添加后缀名即可,就不会暴露命令了。

之前有朋友说很简单,直接将bash复制一份,重命名即可,就算执行命令也无所谓呀,反正不知道是bash执行的

下面我来说一下,这种方式按我的猜想该怎么监控:

  1. 复制一份的bash,bash的MD5是不会变的,在安全基线中有进程文件哈希库:一个名字不是bash的文件哈希 和bash一样,你觉得可不可疑呢?其实这种监控方式也会对付软链接。
  2. 在之前讲的内容中,我们讲到patch命令解释器的方式,即使你改了bash名字,只要执行命令,还是会被HIDS知道是从bash解释器执行的。

2. 分析/proc/目录

接下来的文章中,我要讲解一下从linux进程内存中修改函数,需要给大家提前预习一下基础知识。

proc文件系统是一个伪文件系统,它提供内核数据结构的接口。通常安装在/过程。通常,它是由系统自动安装的,但是也可以使用以下命令手动安装:

mount -t proc proc /proc

proc文件系统中的大多数文件都是只读的,但是有些文件是可写的,允许更改内核变量。/proc目录下的文件很多,我们主要讲解如下文件/文件夹,其中pid是进程号,如果是想查看自身进程中的内容,可以将pid换成self。

/proc/[pid]/auxv /proc/[pid]/cmdline /proc/[pid]/comm /proc/[pid]/cwd /proc/[pid]/environ /proc/[pid]/exe /proc/[pid]/fd /proc/[pid]/limits /proc/[pid]/maps /proc/[pid]/root /proc/[pid]/stack /proc/[pid]/statm /proc/[pid]/status /proc/[pid]/syscall /proc/[pid]/wchan

auxv

/proc/[pid]/auxv包含传递给进程的 ELF解释器信息,格式是每一项都是一个 unsignedlong长度的 ID加上一个 unsignedlong长度的值。最后一项以连续的两个 0x00开头。举例如下:

[root@VM_0_13_centos ~]# hexdump -x /proc/28858/auxv    0000000 0021 0000 0000 0000    e000    90bf 7ffc 0000    0000010 0010 0000 0000 0000    fbff    1f8b 0000 0000    0000020 0006 0000 0000 0000 1000 0000 0000 0000    0000030 0011 0000 0000 0000 0064 0000 0000 0000    0000040 0003 0000 0000 0000    f040    6206 7f48 0000    0000050 0004 0000 0000 0000 0038 0000 0000 0000    0000060 0005 0000 0000 0000 0009 0000 0000 0000    0000070 0007 0000 0000 0000    b000    61e4 7f48 0000    0000080 0008 0000 0000 0000 0000 0000 0000 0000    0000090 0009 0000 0000 0000 2004 6207 7f48 0000    00000a0 000b 0000 0000 0000 0000 0000 0000 0000    00000b0 000c 0000 0000 0000 0000 0000 0000 0000    00000c0 000d 0000 0000 0000 0000 0000 0000 0000    00000d0 000e 0000 0000 0000 0000 0000 0000 0000    00000e0 0017 0000 0000 0000 0000 0000 0000 0000    00000f0 0019 0000 0000 0000 4269 90bd 7ffc 0000    0000100 001f 0000 0000 0000 4fea 90bd 7ffc 0000    0000110 000f 0000 0000 0000 4279 90bd 7ffc 0000    0000120 0000 0000 0000 0000 0000 0000 0000 0000    0000130   

解析这个文件可以参考这段代码(https://www.wienand.org/junkcode/linux/read-auxv.c)。

cmdline

/proc/[pid]/cmdline是一个只读文件,包含进程的完整命令行信息。举例如下:

[root@VM_0_13_centos ~]# ps -ef | grep 28858    root     28858 28568 0 22:56 pts/2 00:00:00 ping www.baidu.com    root     29047 2548 0 22:57 pts/4 00:00:00 grep --color=auto 28858    [root@VM_0_13_centos ~]# cat /proc/28858/cmdline    pingwww.baidu.com   

comm

/proc/[pid]/comm包含进程的命令名。举例如下:

[root@VM_0_13_centos ~]# cat /proc/28858/comm    ping

cwd

/proc/[pid]/cwd是进程当前工作目录的符号链接。举例如下:

[root@VM_0_13_centos ~]# ls -lt /proc/28858/cwd    lrwxrwxrwx 1 root root 0 Mar 29 22:58 /proc/28858/cwd -> /root

environ

/proc/[pid]/environ显示进程的环境变量。举例如下:

[root@VM_0_13_centos ~]# strings /proc/28858/environ    XDG_SESSION_ID=212367    rvm_bin_path=/usr/local/rvm/bin    HOSTNAME=VM_0_13_centos    PYENV_ROOT=/root/.pyenv    GEM_HOME=/usr/local/rvm/gems/ruby-2.5.5    TERM=xterm    SHELL=/bin/bash    HISTSIZE=3000    IRBRC=/usr/local/rvm/rubies/ruby-2.5.5/.irbrc    SSH_CLIENT=113.97.33.208 58836 22    MY_RUBY_HOME=/usr/local/rvm/rubies/ruby-2.5.5    SSH_TTY=/dev/pts/2    USER=root   

exe

/proc/[pid]/exe为实际运行程序的符号链接。举例如下:

[root@VM_0_13_centos ~]# ls -lt /proc/28858/exe    lrwxrwxrwx 1 root root 0 Mar 29 22:56 /proc/28858/exe -> /usr/bin/ping

fd

/proc/[pid]/fd是一个目录,包含进程打开文件的情况。举例如下:

[root@VM_0_13_centos ~]# ls -lt /proc/28858/fd    total 0    lrwx------ 1 root root 64 Mar 29 23:01 0 -> /dev/pts/2    lrwx------ 1 root root 64 Mar 29 23:01 1 -> /dev/pts/2    lrwx------ 1 root root 64 Mar 29 23:01 3 -> socket:[153313413]    lrwx------ 1 root root 64 Mar 29 23:01 6 -> /dev/pts/2    lrwx------ 1 root root 64 Mar 29 22:56 2 -> /dev/pts/2   

目录中的每一项都是一个符号链接,指向打开的文件,数字则代表文件描述符。

limits

/proc/[pid]/limits显示当前进程的资源限制。举例如下:

[root@VM_0_13_centos ~]# cat  /proc/28858/limits    Limit Soft Limit Hard Limit Units    Max cpu time              unlimited            unlimited            seconds    Max file size             unlimited            unlimited            bytes    Max data size             unlimited            unlimited            bytes    Max stack size            8388608              unlimited            bytes    Max core file size        0                    unlimited            bytes    Max resident set          unlimited            unlimited            bytes    Max processes             7282 7282                 processes    Max open files            100001 100002               files    Max locked memory         65536 65536                bytes    Max address space         unlimited            unlimited            bytes    Max file locks            unlimited            unlimited            locks    Max pending signals       7282 7282                 signals    Max msgqueue size         819200 819200               bytes    Max nice priority         0 0    Max realtime priority     0 0    Max realtime timeout      unlimited            unlimited            us   

SoftLimit表示 kernel设置给资源的值, HardLimit表示 SoftLimit的上限,而 Units则为计量单元。

maps

/proc/[pid]/maps显示进程的内存区域映射信息。举例如下:

[root@VM_0_13_centos ~]# cat  /proc/28858/maps     ......    7f4862059000-7f486205d000 rw-p 00000000 00:00 0    7f486206a000-7f486206c000 rw-p 00000000 00:00 0    7f486206c000-7f486206d000 r--p 00021000 fd:01 139988 /usr/lib64/ld-2.17.so    7f486206d000-7f486206e000 rw-p 00022000 fd:01 139988 /usr/lib64/ld-2.17.so    7f486206e000-7f486206f000 rw-p 00000000 00:00 0    7f486206f000-7f4862079000 r-xp 00000000 fd:01 143369 /usr/bin/ping    7f4862278000-7f4862279000 r--p 00009000 fd:01 143369 /usr/bin/ping    7f4862279000-7f486227a000 rw-p 0000a000 fd:01 143369 /usr/bin/ping    7f486227a000-7f486228d000 rw-p 00000000 00:00 0    7f4863ec6000-7f4863ee7000 rw-p 00000000 00:00 0 [heap]    7ffc90bb4000-7ffc90bd5000 rw-p 00000000 00:00 0 [stack]    7ffc90bfe000-7ffc90c00000 r-xp 00000000 00:00 0 [vdso]    ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]   

其中注意的一点是 [stack:<tid>]是线程的堆栈信息,对应于 /proc/[pid]/task/[tid]/路径。

root

/proc/[pid]/root是进程根目录的符号链接。举例如下:

[root@VM_0_13_centos ~]# ls -lt  /proc/28858/root    lrwxrwxrwx 1 root root 0 Mar 29 22:58 /proc/28858/root -> /   

stack

/proc/[pid]/stack显示当前进程的内核调用栈信息,只有内核编译时打开了 CONFIG_STACKTRACE编译选项,才会生成这个文件。举例如下:

[root@VM_0_13_centos ~]# cat  /proc/28858/stack    [<ffffffff81213465>] poll_schedule_timeout+0x55/0xb0    [<ffffffff812149ed>] do_sys_poll+0x4cd/0x580    [<ffffffff81214ba4>] SyS_poll+0x74/0x110    [<ffffffff81697809>] system_call_fastpath+0x16/0x1b    [<ffffffffffffffff>] 0xffffffffffffffff   

statm

/proc/[pid]/statm显示进程所占用内存大小的统计信息,包含七个值,度量单位是 pagepage大小可通过 getconf PAGESIZE得到)。举例如下:

[root@VM_0_13_centos ~]# cat  /proc/28858/statm    36867 404 315 10 0 111 0

各个值含义: a)进程占用的总的内存; b)进程当前时刻占用的物理内存; c)同其它进程共享的内存; d)进程的代码段; e)共享库(从 2.6版本起,这个值为 0); f)进程的堆栈; g) dirty pages(从 2.6版本起,这个值为 0)。

status

/proc/[pid]/status包含进程的状态信息。其很多内容与 /proc/[pid]/stat/proc/[pid]/statm,但是却是以一种更清晰地方式展现出来。举例如下:

[root@VM_0_13_centos ~]# cat  /proc/28858/status    Name:    ping    State:    S (sleeping)    Tgid: 28858    Ngid: 0    Pid: 28858    PPid: 28568    TracerPid: 0    Uid: 0 0 0 0    Gid: 0 0 0 0    FDSize: 256    Groups: 0    VmPeak: 147524 kB    VmSize: 147468 kB    VmLck: 0 kB    VmPin: 0 kB    VmHWM: 1616 kB    VmRSS: 1616 kB    RssAnon: 356 kB    RssFile: 1260 kB    RssShmem: 0 kB    VmData: 312 kB    VmStk: 132 kB    VmExe: 40 kB    VmLib: 4348 kB    VmPTE: 104 kB    VmSwap: 0 kB    Threads: 1    SigQ: 0/7282    SigPnd: 0000000000000000    ShdPnd: 0000000000000000    SigBlk: 0000000000000000    SigIgn: 0000000000000000    SigCgt: 0000000180002006    CapInh: 0000000000000000    CapPrm: 0000000000003000    CapEff: 0000000000000000    CapBnd: 0000001fffffffff    CapAmb: 0000000000000000    Seccomp: 0    Cpus_allowed: 1    Cpus_allowed_list: 0    Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001    Mems_allowed_list: 0    voluntary_ctxt_switches: 1881    nonvoluntary_ctxt_switches: 0

关于信号( signal)的信息: SigQ分为两部分(例如 0/7282),前面表示当前处在队列中的信号( 0),后面则表示队列一共可以存储多少信号( 7282); SigPnd表示当前线程 pending的信号,而 ShdPnd则表示整个进程 pending的信号; SigBlkSigIgnSigCgt分别表示对信号的处理是阻塞,忽略,还是捕获。(关于 Unix信号的相关知识,可以参考Unix: Dealing with signals)。

syscall

/proc/[pid]/syscall显示当前进程正在执行的系统调用。举例如下:

[root@VM_0_13_centos ~]# cat  /proc/28858/syscall    7 0x7ffc90bd2d00 0x1 0x3e3 0x5e80b9e6 0x0 0x0 0x7ffc90bd28d8 0x7f4861738bd0   

第一个值是系统调用号( 7代表 poll),后面跟着 6个系统调用的参数值(位于寄存器中),最后两个值依次是堆栈指针和指令计数器的值。如果当前进程虽然阻塞,但阻塞函数并不是系统调用,则系统调用号的值为 -1,后面只有堆栈指针和指令计数器的值。如果进程没有阻塞,则这个文件只有一个“ running”的字符串。

内核编译时打开了 CONFIG_HAVE_ARCH_TRACEHOOK编译选项,才会生成这个文件。

wchan

/proc/[pid]/wchan显示当进程 sleep时, kernel当前运行的函数。举例如下:

[root@VM_0_13_centos ~]# cat  /proc/28858/wchan    poll_schedule_timeout   

参考:http://man7.org/linux/man-pages/man5/proc.5.html https://github.com/NanXiao/gnu-linux-proc-pid-intro