2008/3

SUID, SGID and sticky bit

stick bit以前表示要把这个可执行文件放到swap分区中来加快执行速度,现在这个显然用不着了,因为Linux/Unix的vm子系统会自动完成这种功能。为了“变废为宝”,这个sticky bit并没有被遗弃,现在它的功能是这样的:对于一个目录,如果它被设置了sticky bit,那么它里面的文件只能被文件所有者,目录所有者,或特权用户删除。最好的一个例子是/tmp目录,在Fedora上它的权限是:

$ ls -ld /tmp/
drwxrwxrwt 50 root root 20480 03-09 21:08 /tmp/
$ test -k /tmp
$ echo $?
0

我们可以看到最后一个x变成了t。而如果目录或者文件不具有x权限,那么t就会变成T,比如:

$ touch foo.txt
$ chmod +t foo.txt
$ ls -l foo.txt
-rw-rw-r-T 1 wangcong wangcong 0 03-09 23:53 foo.txt

suid和sgid类似,它们的符号是s或者S而不是t。suid的含义是让可执行文件执行时具有owner的权限,sgid的含义是让其具有owner所在group的权限。例如:

$ ls -l /bin/ping
-rwsr-xr-x 1 root root 41748 2007-04-06 /bin/ping

如果你用ls -l看,你会发现suid的s是在owner权限一组,sgid的s是在group权限一组。

sgid用到目录上的含义是:里面的新文件或者子目录会继承这个group id。而在Linux上,suid用在目录上是被忽略的。

参考资料:
1. http://www.zzee.com/solutions/linux-permissions.shtml#setuid
2. http://www.unixguide.net/hp/faq/5.1.9.shtml.
3. http://en.wikipedia.org/wiki/Sticky_bit
4. http://en.wikipedia.org/wiki/Setuid

为啥俺没女朋友?

今天和两个同学出去闲聊了一下午,那俩女人没别的,就会八卦,先把以前班里的同学全部八卦一遍,然后又八卦那些明星。最后,还不忘问我一个具有杀伤力的问题,你咋还没女朋友呢?我说:哎,别提了,俺们学校的女生@!#%&**&…(省略N个字)

其实仔细想想,那最多只是个客观原因,深层的原因究竟是啥呢?这是一个重大的问题。辗转反侧,深思良久,我觉得根本原因有这么几点:

1. 美女们喜欢帅哥,而我不是。

2. 美女们多数都学文科,而我不光学理而且学的是美女狠少的计算机专业。

3. 美女们90%以上的都使用QQ和Qzone,而我基本不用。

4. 还有一些美女(也)使用MSN,而我没有。

5. 上学的美女一般还喜欢上校内,而我不上。

6. 美女们99%的都用Windows,而我讨厌。

7. 美女们偶尔也会上上bbs,而我连这个都很少用,因为我喜欢usenet和mailing list。

8. 美女们要么不看书,要么看的书我多看不懂,而我看的书美女们都看不懂!

9. 追美女要经常送礼物,而我是穷书生一个。

10. 美女喜欢让你陪着逛街买东西,而我对此深恶痛绝。

11. 美女上网多是娱乐,偶尔玩玩,而我不光不娱乐,还一天24小时我12个小时都在线。

综上所述,我发现“改过自新”的希望很小,只能等着哪天天上掉下一个傻妞,傻儿叭叽地就愿意做我这么个geek的女朋友。

我抬头仰面45度……

Linux下的反调试技术

作者:西邮 王聪

如何防止自己的程序被调试器跟踪,这是一个很有趣的话题,也是反逆向工程中的一个重要话题。这里简单介绍一下Linux平台上的反调试技术。

(本文主要参考:http://blog.txipinet.com/2006/10/05/37-tecnicas-anti-debugging-sencillas-para-gnu-linux/
做人要厚道,转载请指明出处!

一. int3指令

Intel Software Developer’s Manual Volume 2A中提到:

The INT 3 instruction generates a special one byte opcode (CC) that is intended for
calling the debug exception handler. (This one byte form is valuable because it can be
used to replace the first byte of any instruction with a breakpoint, including other one
byte instructions, without over-writing other code).

int3是一个特殊的中断指令(从名字上也看得出来),专门用来给调试器使用。这时,我们应该很容易想到,要反调试,只要插入int3来迷惑调试器即可。不过,这会不会影响正常的程序?会!因为int3会在用户空间产生SIGTRAP。没关系,我们只要忽略这个信号就可以了。

include

include

void handler(int signo)
{}

int main(void)
{
signal(SIGTRAP, handler);
asm(“nopnt”
“int3nt”);
printf(“Hello from main!n”);
return 0;
}

二. 文件描述符

这是一个很巧妙的办法,不过它只对gdb之类的调试器有效。方法如下:

include

include

include

int main(void)
{
if(close(3) == -1) {
printf(“OKn”);
} else {
printf(“traced!n”);
exit(-1);
}
return 0;
}

gdb要调试这个程序时会打开一个额外的文件描述符来读这个可执行文件,而这个程序正是利用了这个“弱点”。当然,你应该能猜到,这个技巧对strace是无效的。

三. 利用getppid

和上面一个手法类似,不过这个更高明,它利用getppid来进行探测。我们知道,在Linux上要跟踪一个程序,必须是它的父进程才能做到,因此,如果一个程序的父进程不是意料之中的bash等(而是gdb,strace之类的),那就说明它被跟踪了。程序代码如下:

include

include

include

include

include

include

include

int get_name_by_pid(pid_t pid, char* name)
{
int fd;
char buf[1024] = {0};
snprintf(buf, 1024, “/proc/%d/cmdline”, pid);
if ((fd = open(buf, O_RDONLY)) == -1)
return -1;
read(fd, buf, 1024);
strncpy(name, buf, 1023);
return 0;
}

int main(void)
{
char name[1024];
pid_t ppid = getppid();
printf(“getppid: %dn”, ppid);

    if (get_name_by_pid(ppid, name))
    return -1;
if (strcmp(name, "bash") == 0 ||
    strcmp(name, "init") == 0)
        printf("OK!n");
else if (strcmp(name, "gdb") == 0 ||
    strcmp(name, "strace") == 0 ||
    strcmp(name, "ltrace") == 0)
    printf("Traced!n");
else
    printf("Unknown! Maybe traced!n");

return 0;

}

同样的手法,一个更简单的方式是利用session id。我们知道,不论被跟踪与否,session id是不变的,而ppid会变!下面的程序就利用了这一点。

include

include

include

int main(void)
{
printf(“getsid: %dn”, getsid(getpid()));
printf(“getppid: %dn”, getppid());

    if (getsid(getpid()) != getppid()) {
    printf("traced!n");
    exit(EXIT_FAILURE);
}
    printf("OKn");

return 0;

}

四. 利用环境变量

bash有一个环境变量叫$_,它保存的是上一个执行的命令的最后一个参数。如果在被跟踪的状态下,这个变量的值是会发生变化的(为什么?)。下面列出了几种情况:


argv[0] getenv(“_”)
shell ./test ./test
strace ./test /usr/bin/strace
ltrace ./test /usr/bin/ltrace
gdb /home/user/test (NULL)

所以我们也可以据此来判断。

include

include

include

int main( int argc, char *argv[])
{
printf(“getenv(): %sn”, getenv(““));
printf(“argv[0]: %sn”, argv[0]);

if(strcmp(argv[0], (char *)getenv("_"))) {
    printf("traced!n");
    exit(-1);
}

printf("OKn");
    return 0;

}

五. 利用ptrace

很简单,如果被跟踪了还再调用ptrace(PTRACE_TRACEME…)自然会不成功。

include

include

int main(void)
{
if ( ptrace(PTRACE_TRACEME, 0, 1, 0) < 0 ) {
printf("traced!n");
return 1;
}
printf("OKn");
return 0;
}

Happy hacking!

《老无所依》

不错的一部电影。和普通的电影不一样,在这个电影里,恶最终没有恶报,杀人狂最后依旧是逍遥法外,与杀人狂周旋的牛仔最后却死了,不过不是死到他手里。老警长对一切都力不从心,正如电影的名字所示……