Nov 2
上一篇谈到:“典型的情况是某些非法内存访问,Glibc会open("/dev/tty",...),write()一些错误信息,然后open("/proc/self/maps", ...)把进程的内存映射表输出。还有一个更常见的情况,那就是用qsort。GCC的qsort实现,会主动open(/proc/meminfo),获取一些信息,通过这些信息来最优化排序时的内存管理。” 通过执行
strace ./a.out 2>&1 | grep open
可以看到进程执行的open系统调用。

对于这类情况,ptrace监控进程open系统调用,并获取文件名,检查文件名是否合法,如果合法,予以放行,这样就可以避免上述RE被误判为RF的情况了。

说起来很简单,但是具体做起来就有点麻烦。不过可以从我写woj-land的时候参考的ptrace教程《Playing with ptrace, 玩转ptrace》入手。这篇非常不错,强烈推荐有兴趣的同学学习学习:

Playing with ptrace, Part I — 玩转ptrace(一) http://www.kgdb.info/gdb/playing_with_ptrace_part_i/
Playing with ptrace, Part II — 玩转ptrace(二) http://www.kgdb.info/gdb/playing_with_ptrace_part_ii/

上篇以write系统调用为例,介绍了write系统调用的等价汇编码(当然是早期的了,现在的pc上linux貌似不用0x80了)、截获write系统调用,获取write系统调用的参数和返回值、甚至反转write系统调用的输出。具体的看原文了。

在这里,我需要peek的是read系统调用的参数。以x86为例,一个最简单的read系统调用:
read("/proc/meminfo", O_RDONLY)
,大致等同于
movl $5, %eax  ;open的系统调用编号
movl $filename, %ebx ;文件名地址(这里不一定对)
movl $0, %ecx ;open的flags: O_RDONLY
int $0x80
也就是说,可以通过获取x86 CPU寄存器的值来取得系统调用的参数,具体代码如下:
user_regs_struct regs;
ptrace(PTRACE_GETREGS, child, NULL, &regs);
syscall_id = regs.orig_eax; //因为eax也是用来填写函数返回值的,所以该struct额外增加了一个orig_eax
params[0]  = regs.ebx;
params[1]  = regs.ecx;
union u{ unsigned long val; char chars[sizeof(long)]; }data;
data.val = ptrace(PTRACE_PEEKDATA, child, params[0],  NULL);

注意:虽然ebx中存放的是地址,但是不是用户程序可以直接读取的,需要通过ptrace的PTRACE_PEEKDATA命令来获取。该命令一次可以获取sizeof(long)个字节的内容,如果要获取字符串的所有内容,就得通过循环来完成。

此外,为了保证代码能够在x86_64架构下通过编译,需要把上述代码做个小修改:
#if __WORDSIZE == 32
syscall_id = regs.orig_eax;
params[0]  = regs.ebx;
params[1]  = regs.ecx;
#else
syscall_id = regs.orig_rax;
params[0] = regs.rdi;
params[1] = regs.rsi;
#endif


通过这种方式,能够识别出open系统调用打开的文件,在保证系统安全的情况下,改善了Judge的识别能力。

更具体的代码可以参见:
http://code.google.com/p/woj-land/source/browse/trunk/code/judge/judge.h?spec=svn150&r=150#671
Nov 1
因为这两个东西占了地方,每次选盘符时总需要往下拉滚动条,很不爽。在网上搜到3篇文章,这里转载记录一下。

http://bbs.pcbeta.com/viewthread.php?tid=729301
http://bbs.pcbeta.com/viewthread.php?tid=729310
http://bbs.pcbeta.com/viewthread.php?tid=733262

“库” @  [HKEY_CLASSES_ROOT\CLSID\{031E4825-7B94-4dc3-B131-E946B44C8DD5}]
“家庭组” @  [HKEY_CLASSES_ROOT\CLSID\{B4FB3F98-C1EA-428d-A78A-D1F5659CBA93}]

修改注册表这里,需要右键->权限,给Administrators “完全控制” 的权限。

如果需要去掉这两项的显示,分别把键值 ShellFolder\Attributes 由原来的 b080010d 改为 b090010d,然后注销(其实Kill掉explorer也行)就行了。如果不想去掉显示,那么修改 SortOrderIndex 键值(默认是0x42、0x43),改到0x52或者更大,就会排到“计算机”后面了。

点击在新窗口中浏览此图片
Oct 29

闲谈 Restricted Function 不指定

felix021 @ 2010-10-29 21:02 [IT » 软件] 评论(4) , 引用(0) , 阅读(19119) | Via 本站原创
这个词组在ACM/ICPC的各大OJ出现频率还是很高的,意思是使用了“受限制的函数”。

而且几乎没有准确的文档可以定义什么是"Restricted Function"(RF,非彼“RF”)。因为开发者也很郁闷。一个大致可以接受的解释是,任何可能威胁到系统安全的代码都不应该被执行。更严格一点,任何解题所不需要用到的函数都不应该调用。但是这两个解释都不够准确。

作为一个需要编译并运行用户任意代码的系统,必然需要对用户的代码/程序进行额外的处理,过滤可能对服务器产生危险的操作。在woj-land ( http://code.google.com/p/woj-land ) 的实现中,是采用运行时监控程序的执行,通过ptrace来拦截并检查每一个系统调用,如果发现系统调用不在白名单中,即出现RF。具体的代码可参见:http://code.google.com/p/woj-land/source/browse/trunk/code/judge/rf_table.h

白名单机制是最安全的了,但是有缺陷。

首先是很难考虑到所有的情况。举例来说,你用C语言写的A+B来测试的话,需要的系统调用只有几个。大多数情况下能够满足要求,但是有时候却发现不对。比如说SYS_futex这个系统调用,如果不被允许,glibc写的程序在执行时可能会出问题。

其次是过于严格,导致部分常用且不影响系统安全的函数被限制死。比如说fflush,只需要用到SYS_lseek调用即可。

再次是有些异常情况。一个典型的情况是使用 qsort(arr, N, sizeof(arr), cmp); 这样的代码。实际上应当是sizeof(int),不小心写错了,访问出错。典型的情况是某些非法内存访问,Glibc会open("/dev/tty",...),write()一些错误信息,然后open("/proc/self/maps", ...)把进程的内存映射表输出。还有一个更常见的情况,那就是用qsort。GCC的qsort实现,会主动open(/proc/meminfo),获取一些信息,通过这些信息来最优化排序时的内存管理。于是本来应该是运行时错误(段访问异常),即Runtime Error(SIGSEGV)的情况也被误判为Restricted Function了。

終り.

闲谈 Restricted Function #2
Oct 26
首先在MATLAB的程序文件中找到如下文件:atlas_Athlon.dll(AMD系列的请用这个,其他的CPU也有相应的问题件),这是对应处理器的数值运算优化文件,然后按如下步骤进行:

  1、右击我的电脑,选择属性,在"高级"选项卡中点击"环境变量" ,在系统变量下添加:
    变量名:BLAS_VERSION
    变量值:C:\Matlab7\bin\win32\atlas_Athlon.dll
    如果你安装在D盘,前面就改成D:\Matlab7\bin\win32\atlas_Athlon.dll

  2、右击MATLAB7.0的图标,属性,在兼容性 设置里面选择[√]以兼容模式运行这个程序,并选择 Vista Service Pack 2。

再次运行Matlab7 应该就OK了。
Oct 22

灵魂守恒定律 不指定

felix021 @ 2010-10-22 23:54 [IT » 程序设计] 评论(2) , 引用(0) , 阅读(7702) | Via 本站原创
一切都是从,那道蚂蚁题,开始的
那题中的蚂蚁有20只,爬在长的木棒一根
左边蚂蚁10只向右爬
右边蚂蚁10只向左爬
蚂蚁爬的速度都相同
一碰头各自原速调头
然后就问,这些个蚂蚁,要碰多少次头才会从木棒上都掉下去

一说起这个问题,可能很多人有看过编程之美4.7 蚂蚁爬杆的问题:有一根27厘米长的细长木杆,在第3厘米、7厘米、11厘米、17厘米、23厘米这五个位置 处各有一只蚂蚁。木杆很细,不能同时通过2只蚂蚁。开始时候,蚂蚁的头朝左还是朝右是任意的,他们只会朝前走或者掉头,但是不会后退。当任意2只蚂蚁碰头后时,2只蚂蚁会同时掉转头朝反方向走。架设蚂蚁每秒钟可以走一厘米的距离。编写程序,求所有蚂蚁都离开木杆的最短时间和最长时间。

留一些空间不剧透,有兴趣的同学可以先想想然后再往下看。
Oct 16

删除文件夹 不指定

felix021 @ 2010-10-16 12:58 [IT » 软件] 评论(0) , 引用(0) , 阅读(4603) | Via 本站原创
删除文件夹的时候,windows干的第一件事情貌似是计算所有的文件数量和大小,然后可以在删除过程中告诉你还要多久。有的时候小文件太多,这个过程相当漫长(比如用不了又卸不了的matlab安装文件夹)。这时候用命令提示符 rd /s /q DIRNAME 来删除就不那么罗嗦了。

更进一步,可以修改HK_CLASS_ROOT\Folder\Shell\,增加 一个 DELETE/command, cmd /c rd /s "%1",就可以直接从右键这样删了。

点击在新窗口中浏览此图片
Sep 30

PHP/Javascript 汉字转拼音 不指定

felix021 @ 2010-9-30 17:42 [IT » 其他] 评论(4) , 引用(0) , 阅读(7515) | Via 本站原创
PHP:
print_r(convert_pinyin("足"));
输出:
Array
(
    [0] => zu
    [1] => ju
)

JS就不用说了,直接用上pinyin.js就好

下载文件 (已下载 7284 次)

p.s.
使用的是WinXP的IME生成器(imegen)将全拼的码表(c:\windows\system32\WINPY.MB)解开得到mabiao.txt,然后处理成一个json。
Sep 30
看了下百度百科对UTF-8的说明,随手写的,基本能用。

比较诡异的是本来UTF8getchar想用strncpy的,但是这个函数有坑....

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>

#define alloc(type, size) ((type *)malloc(sizeof(type) * size))

struct UTF8char
{
    unsigned short length;
    char data[7];
};

unsigned UTF8getcharlen(const char *s)
{
    unsigned char t = (unsigned char) s[0];
    if (t < 0x80) //0xxx xxxx
        return 1;
    else if (t < 0xe0) //110x xxxx
        return 2;
    else if (t < 0xf0) //1110 xxxx
        return 3;
    else if (t < 0xf8) //1111 0xxx
        return 4;
    else if (t < 0xfc) //1111 10xx
        return 5;
    else if (t < 0xfe) //1111 110x
        return 6;
    else //0xff
        return 1;
}

int UTF8getchar(UTF8char *c, const char *s)
{
    int i;
    c->length = UTF8getcharlen(s);
    for (i = 0; i < c->length && s[i] != 0; i++)
        c->data[i] = s[i];
    c->data[i] = 0;
    return (i == c->length);
}

int UTF8cmp(const UTF8char *c, const char *s)
{
    return strncmp(c->data, s, c->length);
}

int main()
{
    char linebuf[4096];
    UTF8char c;

    scanf("%s", linebuf);

    int reti = UTF8getchar(&c, linebuf);
    assert(reti != 0);

    printf("%d %s\n", c.length, c.data);
    return 0;
}
分页: 31/103 第一页 上页 26 27 28 29 30 31 32 33 34 35 下页 最后页 [ 显示模式: 摘要 | 列表 ]