Saturday, October 23, 2010

live essential 2011 messenger msgsres.dll ad-free beta

这个纯粹是为了凑发博数量:P

上一篇记录的东西大体没问题,一开始用的时候的确广告都没了,但是突然我发现聊天窗口的广告又出现了。。。于是各种囧。。。

这次简单地复了一遍流程,改一点测一点。

log如下:
1195 
 找到 SSConstrainer,layoutpos=top -> layoutpos=none
  主窗体广告消失。


1192
 adbannercont, layout=FillLayout() -> layoutpos=none

  聊天窗口动画广告还在,关掉动画后的文字广告已经不在了

 找到 adbannerregiontrident,删除 layout=FillLayout()


下载地址:http://sinaurl.cn/h40Mhk
有问题请sina微博 @sskaje
感谢 Messenger Plus!,Resource Hacker,微盘/SAE 的存储

Thursday, October 21, 2010

Windows Live Essential 2011 Messenger 去广告

上篇相关的文章:http://blog.sskaje.name/2009/09/msn.html

等了好久的uib decoder,终于在Messenger Plus! 4.90.0.392 中拿到了(获取前边已经有了,但是一直没敢再次尝试恐怖的live essential)。

操作流程差不多,区别如下:
这次有3个bin文件,920 4010 "Data_1192.bin",923 4010 "Data_1195.bin",925 4010 "Data_1197.bin"。

1195 修改:找到 SSConstrainer,layoutpos=top -> layoutpos=none
1192和1197大体相同都作三个修改:
1) adbannercont,该行 layout=FillLayout() -> layoutpos=none
2) 上边 layoutpos=none
3) 跟 2 同一行,去掉 layout=FillLayout()

保存,替换就行。
这次语言都是1033,直接替换就好。二进制文件可以 mail 我 sskaje (at) gmail dot com

================
这次在1192/1197上折腾死了,唉,唉

Tuesday, August 31, 2010

Problems with tracing location in callback-ed functions/methods

Problems with tracing location in callback-ed functions/methods

Exceptions thown in a function/method been called via 'call_user_func' or 'call_user_func_array', have key 'file' and 'line' disappeared in their first element (array[0]) from Exception::getTrace().
getTrace());
}

function callback() {
 call_user_func('test');
}

try {
 callback();
} catch (Exception $e) {
 var_dump($e->getTrace());
}
?>

G:\wwwroot\Test\Exception>php trace_func.php
#0  test() called at [G:\wwwroot\Test\Exception\trace_func.php:8]
array(1) {
  [0]=>
  array(4) {
    ["file"]=>
    string(40) "G:\wwwroot\Test\Exception\trace_func.php"
    ["line"]=>
    int(8)
    ["function"]=>
    string(4) "test"
    ["args"]=>
    array(0) {
    }
  }
}
#0  test()
#1  call_user_func(test) called at [G:\wwwroot\Test\Exception\trace_func.php:14]
#2  callback() called at [G:\wwwroot\Test\Exception\trace_func.php:18]
array(3) {
  [0]=>
  array(2) {
    ["function"]=>
    string(4) "test"
    ["args"]=>
    array(0) {
    }
  }
  [1]=>
  array(4) {
    ["file"]=>
    string(40) "G:\wwwroot\Test\Exception\trace_func.php"
    ["line"]=>
    int(14)
    ["function"]=>
    string(14) "call_user_func"
    ["args"]=>
    array(1) {
      [0]=>
      string(4) "test"
    }
  }
  [2]=>
  array(4) {
    ["file"]=>
    string(40) "G:\wwwroot\Test\Exception\trace_func.php"
    ["line"]=>
    int(18)
    ["function"]=>
    string(8) "callback"
    ["args"]=>
    array(0) {
    }
  }
}
Similar result given by debug_print_backtrace(), is this a bug or an unexpected feature ? XD

Wednesday, August 25, 2010

foreach 赋值引用 + refcount 引发的一个问题

第一个问题,封装了 mysqli_stmt 的bind_param方法,为了实现 $stmt->execute(array(typelist, var1, var2, ...)); 的操作。
<?php
  $values[0] = $info[0];
  foreach ($info[1] as $k=>$v) {
   $fields[] = "`{$k}`=?";
   $values[] = & $v;
  }

这个操作的结果显然是错误的。于是有了个下边的测试:
<?php
$array = array(
1,2,3,4,5
);

$to0 = array();
foreach ($array as $k=>$v) {
 $to0[$k] = & $v;
}
var_dump($to0);


$to1 = array();
foreach ($array as $k=>$v) {
 $to1[$k] = & $v;
 unset($v);
}
var_dump($to1);


$to2 = array();
foreach ($array as $k=>&$v) {
 $to2[$k] = & $v;
}
var_dump($to2);

/*
Output:

G:\wwwroot\Test>php reference3.php
array(5) {
  [0]=>
  &int(5)
  [1]=>
  &int(5)
  [2]=>
  &int(5)
  [3]=>
  &int(5)
  [4]=>
  &int(5)
}
array(5) {
  [0]=>
  &int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
  [3]=>
  int(4)
  [4]=>
  int(5)
}
array(5) {
  [0]=>
  &int(1)
  [1]=>
  &int(2)
  [2]=>
  &int(3)
  [3]=>
  &int(4)
  [4]=>
  &int(5)
}

*/


第一个问题结束
---------------------------------------------------------

第二个问题,
最上边代码后来的版本是这样的:
<?php
  $values[0] = $info[0];
  foreach ($info[1] as $k=>&$v) {
   $fields[] = "`{$k}`=?";
   $values[] = & $v;
  }
  unset($info);

  $stmt = $db->prepare($query);
  $ret = $stmt->execute($values);

结果传递多于一个字段时,execute报错。
假设foreach 循环结束后,$values 内容是:
array(5) {
  [0]=>
  &int(1)
  [1]=>
  &int(2)
  [2]=>
  &int(3)
  [3]=>
  &int(4)
  [4]=>
  &int(5)
}
而在execute()的时候,却变成了
array(5) {
  [0]=>
  int(1)
  [1]=>
  int(2)
  [2]=>
  int(3)
  [3]=>
  int(4)
  [4]=>
  &int(5)
}

除了最后一个元素外,其他的引用都消失了。。。
在几个点放上debug_zval_dump,一看便明白了。

foreach 循环结束的时候,$values 数组涉及到引用的元素,除了最后一个 refcount 为3,其余均为2. 因为对于其他的元素,$info 和 $values 两个数组的元素都对目标进行了引用,所以refcount为2,而最后一个,因为 foreach 的临时变量 $v 还对这个有引用,所以 refcount 是3.
当执行了 unset($info) 的操作后,所有的refcount均 -1,于是变成了 11112。
这个时候var_dump,自然会发现只有最后一个元素还处于引用的状态。

Monday, August 16, 2010

第一次完整流程体验wep破解

一个白天都在折腾bt4,直到下午才把usb persistent live 做好。
大致步骤:
live cd/dvd 启动 bt4;
1个4GB U盘,fdisk 分区成 2+2,fat32+ext3,激活1;
mount -o loop bt4 dvd iso, 复制内容到fat分区;
grub-install --no-floppy --root-directory=/PATH/TO/FIRST/PARTITION /dev/DEVICENAME;
done;
印象中就这几步,具体可以看看bt4官网的tutorials

破解过程其实都还简单,手头没教程,就只能自己折腾。
一开始遇到问题,所以后来先把 realtek的驱动装了,不过后来想想 iw scan时 nl80211 not found 的问题,应该不用装驱动;
iwlist wlan0 scanning,找到bssid,因为目标是在windows下就确定了的,所以根据essid,找到bssid,也就是mac,记下来就行;
airodump-ng 。。。。。 参数不记得了= =, --ivs --write test ..... 反正有一个 filter 用是 bssid,需要指定interface(最后一个参数),第一次抓了11466个包,不成,后来重搞,抓了20000+个,搞定了;
aircrack-ng 。。。。。 参数也不记得了,有个 -a 1 指定wep,有个指定ivs文件,最后结果大致入下:

                                                 Aircrack-ng 1.1 r1738


                                  [00:00:07] Tested 108182 keys (got 20290 IVs)

   KB    depth   byte(vote)
    0    1/ 33   13(25648) 4F(25392) 43(25280) 25(24912) D0(24836) 47(24800) AE(24696) 76(24544)
    1    0/ 11   57(27220) C4(26432) F8(26416) E3(25616) FB(24620) F6(24588) 04(24472) AC(24292)
    2    0/  1   92(29236) B8(25916) 84(25172) 8D(25092) 4E(24980) E6(24684) B1(24476) 41(23960)
    3    6/ 33   46(24548) 7C(24512) A6(24364) 72(24216) EA(24152) 14(23968) 27(23884) 64(23448)
    4    8/ 10   08(24404) C2(24332) 1E(24284) 11(24256) A7(24176) 30(24108) FC(24072) 02(23888)

                         KEY FOUND! [ 13:57:92:46:80 ]
        Decrypted correctly: 100%

Wednesday, July 21, 2010

乱七八糟

这是一篇给 @xklxkl 的作业。
实在不知道写什么,只能是想到啥写啥。
不要试图从中找逻辑,根本就没有逻辑。。。。。。

ID: sskaje

这个小标题应该是什么。。。:
1 尊重其他文化,但绝不愿主动尝试接受。
2 我是懒人,怎么简单怎么来,什么好用用什么,怎么好用怎么来。
--------------------------------------------------------------------------
写代码:
这是当前的吃饭工具,所以多写点,不过也只是列表。
非科班出身,从没指望做得多专业。不会数据结构和算法,不会软件工程,啥都不会各种不会,更多只是以知识面取胜,关键问题是没人会管知识面,尴尬。
曾经接触过的各种语言,我也不知道咋排序:
C:
曾经:学过,写过点简单的东西,OpenSSL相关;
现状:忘光了,除了基本语法。想捡起来,但不知道用来干嘛。
C++:
曾经:上课没好好学,曾经嵌入式课封装过一个简单的mysql client的lib;
现状:抱着抵制C++的想法,我只会回答“全忘了”。
ASM:
曾经:从win32逆向开始入手学汇编,只会x86的语法,at&t的都是现查,但是总共也没几次;
现状:还能简单地逆一些初级的crackme或一些注册验证简单的win32应用程序,coding是没戏的了,Ollydbg无敌,IDA Pro万能。
Perl:
曾经:三年前学过一点,但是后边不知道干啥,于是就忘了;
现状:语法应该还能记得一丁点吧。
Python:
曾经:第一次见应该快4年了,也只是很初级地奔着几个库查了点资料发现没有任何成果就放弃了;
现状:呃。。。
Matlab:
曾经:伟大的Matlab,信号系统必备,只是我实验课都是把考试系统黑了拿别人的答案改的 :x;
现状:用不上啊,为啥要学。
Java:
曾经:没学过,但是看过一点,写个第一次应用应该是三年前拿下某个高中的服务器的时候,测试写入文件能否执行的时候,不过当时报了语法错误,至少证明解析了;
现状:一年前反编译Zend Studio 7的注册部分,把算法跟出来,写了个keygen,但是,还是属于啥都不会的那种。
JS:
曾经:还算看得比较多吧;
现状:让我写可以,但是基本啥都不会,很多都需要现查。
Ruby/Erlang/Lua/VBS/VBA/VB/ASP:
曾经:看过;
现状:不会。
PHP:
曾经:从第一次接触到现在也快4年了吧,不曾尝试主动看C源码,但是尝试过自己Windows下从头开始编译,大致了解点,写PHP完全因为简单省事;
现状:快被逼进死胡同了。
SQL:
曾经:只说mysql,也算是写过sp,trigger,function的了;
现状:手册无敌。
Bat/Shell Script:
曾经:Dos下不会批处理还咋混——于是没混好;Shell Script没学过
现状:能写简单的,不指望有多好的逻辑。
[a-zA-Z]+ML:
曾经:你觉得这是语言么?
现状:你觉得这是语言么?
CSS:
曾经:同上;
现状:同上。
小结:
我本不想用代码吃饭,结果现在沦落到此地步,怎一个凄惨了得。然后,写代码的原因是目的性极强的,当初只是为了玩hts,各种诡异的题目不靠编程根本没法搞,不会写代码,搞安全也没戏。
有明确的目的,有阶段性的成就感,才有发展的动力啊。
-----------------------------------------------------------------
网络安全:
自认为是做安全出身,于是坚决抵制把安全当主业。
所谓安全,更多的只是一个看问题的“新”的角度。于是我总是习惯于换各种角度看问题,但是鉴于模拟信号没法完整遍历,所以,从不指望自己能面面俱到,想到哪儿算哪儿。
----------------------------------------------------------------
其他:
也没啥了。做安全的时候接触过实验室仅有的几台设备;学校的时候,简单研究过dns协议,于是做了个现在看来用户体验极差的ddns服务;前不久刚把hts的irc题目搞完了,于是又重新看了点irc的东西;……
----------------------------------------------------------------
总结:
做的东西实在太杂了,整理起来也太费劲,于是经常就想到什么写什么。
大二进的实验室,所以有时候接触的东西比身边的人多很多,同时也被一群人骂没情商,lol。
学校里混论坛比较多,做安全的时候也有自己的小圈子,于是各种原因认识了学校里形形色色的人,但是和身边的人反倒关系处得不好。现在依旧挂着论坛管理运维的职务,偶尔去学校网络中心也去顺道提供安全相关“咨询服务”。
修电脑的事情已经坚决不做了。
很喜欢做点自己想做的事情,但是尴尬的是现在不知道该做什么,不知道什么是自己真正想做的有兴趣的。于是就有了这个“暑假”。


-----------------------------------------------------------------

我是真不想看自己的简历了。。。。。。

Monday, June 28, 2010

HackThisSite: Programming 6 Bypass the image captcha

这是07年题目发布一来,解决耗时最长的一题,从07年年初到现在,这一晃。。。

题目地址在 http://www.hackthissite.org/missions/prog/6/

列表说明如下:
Bypass the image captcha

Bypass the image captcha This level is about OCR. Write a program which is able to read all the characters in a given image, and let it beat a captcha automatically. 

Difficulty rating: harder   Take this challenge!

题目大致是一个用 js+css 渲染的页面,上边画了一些文字,可以看这里
PHP Imagick 使用手记 这个是三年前学 php imagick 的时候做的,思路待会儿一并讲了。需要注册才能下附件,但是校外貌似没法注册 XD.
那就直接去上边给的关卡链接看吧。

画出来的页面,字符按渐近线排序。从最内顺时针方向,每旋转10度一个字符;相邻两个文字到旋转中心之间的距离是有一定比例关系的。
于是思路有两个:
1 画图 + OCR
图片绘制很简单,html代码直接可以重写成php代码,然后生成图片就是了。但是唯一的麻烦是文字的识别。
一般OCR预处理图片的时候,都会对字符进行矫正,但是毕竟斜着的字符处理起来还是很麻烦,所以基本思路是“旋转”。取的是水平和垂直的四栏数据,旋转10度,再取,再旋转。。。
由于拿到的数据本身已经做过一些round类似的处理,整数数值已经不精确,不合适地旋转会让偏差更大。所以旋转的策略应该是,每次都对*原图*旋转,第一次旋转0°,第二次10°。。。
这样总比拿上次的结果再转10°的效果好。。。

剩下就是定位,然后截框,圈字符,识别。。。。
最早按这个思路做,然后折腾了好久识别率都不高。。。
(其实是当时截框的定位计算出了错,以后有时间可以再重新实现)

2 直接字符坐标定位
每个字符都有特定的组成,例如 1 有三个横线, 2 有一个弧线和两个横线。。。
关键的一点,弧线的弧度是不受旋转影响而产生误差的。所以有弧线的字符很容易判定出来。


不管哪种思路,第一步都是差不多的:
第一步,定位所谓的旋转中心。直接字面理解即可,或者把这个发散线当一个圆,那就是圆心。
有一个重要的参数,是上边提到的相邻两个字符中间位置到圆心距离的比例,1.005,不用问为什么,反正就是这个数了。这样一来,测得最内圈是99像素左右,最外圈的是 100 * 1.005^252 ~= 351 像素。

定义的数据结构如下:
Line {
int x1,
int y1,
int x2,
int y2
}
Arc {
int x,
int y,
int radius,
int sangle,
int anglelength
}
对于Line,(x1,y1) 和 (x2,y2) 之间的位置关系是不确定的,所以预处理最好调一下顺序。
对于Arc,这里是按照逆时针方向画的弧线,所有都是用角度单位表示,x,y是圆心坐标。

预处理第一步,根据定义的数据结构,可以遍历取到x方向和y方向的最小和最大的坐标,计入 edge 中。
所以有圆心位置为:
x方向: edge[x][max] - (edge[x][max] - edge[x][min]) / (1.005^18 + 1)
y方向: edge[y][max] - (edge[y][max] - edge[y][min]) / (1.005^18 + 1)

由于题目中的坐标已经不是精确值,所以这里建议不要再作 round 处理。


*从现在开始,以上述第二种思路来分析*。
第二步,根据圆心坐标,计算每个字符的中心位置。因为旋转角度是确定的,所以这个也很容易。
第三步,遍历所有的Line 和 Arc,根据中点位置,判定基于圆心笛卡尔坐标系的角度,进而可以分辨出是在哪条射线方向上,分组整理。
第四步,对每组的Line和Arc,再判定距离圆心的位置,就可以定位大致是第几层的字符。
第五步,按组、层识别字符。

后边的思路都很简单,最恶心的就是字符的识别,特征提取。
上边说了,有弧线的地方很容易搞定。真正开发中也的确如此。但是对于没有弧线的位置,于是就得恶心了,关键还得考虑排重和缺信息的情况。

Anyway, 这个题目已经搞定。只是由于识别率的不稳定,就在那儿直接循环暴力重试。。。

不过,第一次用 php 的 goto,真方便 XD

Sunday, June 13, 2010

leviathan.intruded.net

上午把这个过了,最容易的一台机器
ssh: leviathan.intruded.net
port: 10101
username: level1
password: leviathan

密码列表(blog里隐掉了)
level1: leviathan
level2: ********
level3: ********
level4: ********
level5: ********
level6: ********
level7: ********
level8: ********
----------------------------------
1
cat .backup/bookmarks.html | grep --color pass
<DT><A HREF="http://nahtaivel.intruded.net/passwordus.html" TEMP: "AFeSdWEf"ADD_DATE="1155384634" LAST_CHARSET="ISO-8859-1" ID="rdf:#$2wIU71">password to level2</A>
直接访问
********
----------------------------------
2
/wargame/check
下载下来打开,看到 sex secret god love
这个就是密码,验证,打开一个shell

level2@leviathan:/wargame$ ./check
password: sex secret god love
sh-3.1$ id
uid=1001(level2) gid=1001(level2) euid=1002(level3) groups=1001(level2)
********
----------------------------------
3
level3@leviathan:/wargame$ ln -s /home/level4/.passwd /tmp/file.log
level3@leviathan:/wargame$ ./prog
********
这个纯粹是猜出来的
直接运行提示 Cannot find /tmp/file.log
/tmp是可写不可读的状态

----------------------------------
4
/wargame
ida pro打开,直接伪代码看
int __cdecl do_stuff()
{
  int v1; // [sp+11Dh] [bp-Bh]@1
  int v2; // [sp+121h] [bp-7h]@1
  __int16 v3; // [sp+125h] [bp-3h]@1
  char v4; // [sp+127h] [bp-1h]@1
  char v5; // [sp+1Dh] [bp-10Bh]@1

  v1 = dword_8048737;
  v2 = dword_804873B;
  v3 = word_804873F;
  v4 = byte_8048741;
  fgets(&v5, 256, (FILE *)stdin);
  if ( strcmp(&v5, (const char *)&v1) )
  {
    puts("bzzzzzzzzap. WRONG");
  }
  else
  {
    puts("[You've got shell]!");
    seteuid(0x3ECu);
    system("/bin/sh");
  }
  return 0;
}

点开v1
.rodata:08048737 dword_8048737   dd 706C6E73h            ; DATA XREF: do_stuff+9 r
.rodata:0804873B dword_804873B   dd 746E6972h            ; DATA XREF: do_stuff+11 r
.rodata:0804873F word_804873F    dw 0A66h                ; DATA XREF: do_stuff+19 r
mysql出场了


mysql> select 0x706C6E73;
+------------+
| 0x706C6E73 |
+------------+
| plns       |
+------------+
1 row in set (0.00 sec)

mysql> select 0x746E6972;
+------------+
| 0x746E6972 |
+------------+
| tnir       |
+------------+
1 row in set (0.00 sec)

mysql> select 0x66;
+------+
| 0x66 |
+------+
| f    |
+------+
1 row in set (0.00 sec)

mysql> select reverse('ftnirplns');
+----------------------+
| reverse('ftnirplns') |
+----------------------+
| snlprintf            |
+----------------------+
1 row in set (0.00 sec)
密码是 ********

----------------------------------
5
这关是个算法题?
~/.Trash/bin

Ida pro 打开
int __cdecl main(char a1)
{
  int result; // eax@2
  FILE *v2; // eax@1
  int  r; // [sp+40h] [bp+0h]@1
  int v4; // [sp+3Ch] [bp-4h]@1
  char *v5; // [sp+30h] [bp-10h]@1
  FILE *v6; // [sp+20h] [bp-20h]@1
  unsigned int v7; // [sp+24h] [bp-1Ch]@3
  char v8; // [sp+2Fh] [bp-11h]@4
  signed int v9; // [sp+28h] [bp-18h]@4
  char *v10; // [sp+18h] [bp-28h]@11

  v4 =  r;
  v5 = &a1;
  v2 = fopen("/home/level6/.passwd", (const char *)&unk_80485E8);
  v6 = v2;
  if ( v2 )
  {
    fgets(buf, 256, v6);
    v7 = 0;
    while ( 1 )
    {
      v10 = buf;
      if ( v7 >= strlen(buf) - 1 )
        break;
      v8 = buf[v7];
      v9 = 0;
      while ( v9 <= 7 )
      {
        if ( v8 >= 0 )
          putchar(48);
        else
          putchar(49);
        v8 *= 2;
        ++v9;
      }
      putchar(32);
      ++v7;
    }
    result = putchar(10);
  }
  else
  {
    result = -1;
  }
  return result;
}
执行的结果是
00110110 01101100 01111001 01110110 01001100 01011000 01000011 01000001 00001010

做了个字典:
#include 
#include 

int main(char a1)
{
    char *buf = "01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int i=0;
    int t=0;
    char c;
    int j=0;

    for (; i<strlen(buf); i++, j++) {
        c = buf[i];
        printf("%c : ", c);
        t = 0;
        while ( t <= 7 ) {
            if ( c >= 0) {
                putchar('0');
            } else {
                putchar('1');
            }

            c *= 2;
            t++;
        }
        if (j%4 == 3) {
            printf(" \n");
        } else {
            printf(" \t");
        }
    }
}
/*
0 : 00110000    1 : 00110001    2 : 00110010    3 : 00110011
4 : 00110100    5 : 00110101    6 : 00110110    7 : 00110111
8 : 00111000    9 : 00111001    0 : 00110000    a : 01100001
b : 01100010    c : 01100011    d : 01100100    e : 01100101
f : 01100110    g : 01100111    h : 01101000    i : 01101001
j : 01101010    k : 01101011    l : 01101100    m : 01101101
n : 01101110    o : 01101111    p : 01110000    q : 01110001
r : 01110010    s : 01110011    t : 01110100    u : 01110101
v : 01110110    w : 01110111    x : 01111000    y : 01111001
z : 01111010    A : 01000001    B : 01000010    C : 01000011
D : 01000100    E : 01000101    F : 01000110    G : 01000111
H : 01001000    I : 01001001    J : 01001010    K : 01001011
L : 01001100    M : 01001101    N : 01001110    O : 01001111
P : 01010000    Q : 01010001    R : 01010010    S : 01010011
T : 01010100    U : 01010101    V : 01010110    W : 01010111
X : 01011000    Y : 01011001    Z : 01011010
*/
查表
00110110 01101100 01111001 01110110 01001100 01011000 01000011 01000001 00001010
********
----------------------------------
6
signed int __cdecl main(char a1)
{
  int  r; // [sp+230h] [bp+0h]@1
  int v3; // [sp+22Ch] [bp-4h]@1
  char *v4; // [sp+224h] [bp-Ch]@1
  char *v5; // [sp+18h] [bp-218h]@1
  int v7; // [sp+24h] [bp-20Ch]@5
  int v8; // [sp+1Ch] [bp-214h]@6

  v3 =  r;
  v4 = &a1;
  v5 = &a1;
  if ( a1 <= 1 )
  {
    puts("*** File Printer ***");
    printf("Usage: %s filename\n", **((_DWORD **)v5 + 1));
    return -1;
  }
  if ( access(*(const char **)(*((_DWORD *)v5 + 1) + 4), 0) )
  {
    puts("You cant have that file...");
    return 1;
  }
  snprintf((char *)&v7, 0x1FFu, "/bin/cat %s", *(_DWORD *)(*((_DWORD *)v5 + 1) + 4));
  system((const char *)&v7);
  return v8;
}
/var/tmp下有几个symlink,但是直接读还是不行。看了看命令的构造,很显然,需要从文件名上动手。
本想自己弄,结果发现/var/tmp下有了

level6@leviathan:/var/tmp$ /wargame/printfile ./\|cat\ /home/level7/.passwd
/bin/cat: ./: Is a directory
********

----------------------------------
7
level7@leviathan:/wargame$ ./sphinx
usage: ./sphinx <4 digit code>
level7@leviathan:/wargame$ ./sphinx 1111
Wrong
第一眼,想写个代码遍历 - -|||

IDA Pro

int __cdecl main(char a1)
{
  int result; // eax@5
  int  r; // [sp+30h] [bp+0h]@1
  int v3; // [sp+2Ch] [bp-4h]@1
  char *v4; // [sp+24h] [bp-Ch]@1
  char *v5; // [sp+10h] [bp-20h]@1
  int v6; // [sp+20h] [bp-10h]@1

  v3 =  r;
  v4 = &a1;
  v5 = &a1;
  v6 = 7123;
  if ( a1 != 2 )
  {
    printf("usage: %s<4 digit code>\n", **((_DWORD **)v5 + 1));
    exit(-1);
  }
  if ( atoi(*(const char **)(*((_DWORD *)v5 + 1) + 4)) == v6 )
  {
    seteuid(0x3EFu);
    result = system("/bin/sh");
  }
  else
  {
    result = puts("Wrong");
  }
  return result;
}

level7@leviathan:/$ /wargame/sphinx 7123
sh-3.1$ id
uid=1006(level7) gid=1006(level7) euid=1007(level8) groups=1006(level7)
脑残了,居然不相信7123是密码

啊啊啊啊a

********
----------------------------------

level8@leviathan:~$ cat CONGRATULATIONS
Well Done, you seem to have used *nix system before, now try something more serious. Your completion string is "Unix is easy!!!".

Saturday, June 12, 2010

使用mklink修改chrome/firefox缓存目录到ramdisk

Windows 7下,mklink为cmd的内部命令,参数如下

Creates a symbolic link.

MKLINK [[/D] | [/H] | [/J]] Link Target

/D Creates a directory symbolic link. Default is a file
symbolic link.
/H Creates a hard link instead of a symbolic link.
/J Creates a Directory Junction.
Link specifies the new symbolic link name.
Target specifies the path (relative or absolute) that the new link
refers to.



创建Ramdisk,分区符定为 Z:
建立目录 Z:\Chrome\Cache。
Administrator模式开启CMD,进入 C:\Users\sskaje\AppData\Local\Google\Chrome\User Data\Default
执行
mklink /J Cache z:\Chrome\Cache


social.microsoft.com的一帖子说,Junction 和 Symlink 区别在于,前者系统认为是一个实际目录,后者认为是一个快捷方式,但是貌似这个说法还不是很正确,没空研究,爱怎怎地吧。

效率考虑,我ramdisk的数据不往硬盘上同步,这就意味着重启系统,Z盘的这些目录就被干掉了。
于是开机就需要执行一次mkdir建目录。

代码如下

SET RAMDISKDRV=Z:

SET CHROME_CACHE_DIR="%USERPROFILE%\AppData\Local\Google\Chrome\User Data\Default\Cache"
SET CHROME_RAMDISK_DIR="%RAMDISKDRV%\Chrome\Cache"

rd /s /q %CHROME_CACHE_DIR%
mkdir %CHROME_RAMDISK_DIR%
mklink /J %CHROME_CACHE_DIR% %CHROME_RAMDISK_DIR%


如果嫌这样麻烦,可以改Chrome的启动参数,加 --user-data-dir=Z:\Chrome\Cache

Firefox直接 用 about:config 添加 browser.cache.disk.parent_directory 指到 Z:\Firefox 即可。

Friday, April 30, 2010

autossh + plink

/root/bin/plinkssh.sh:

#!/bin/sh
export AUTOSSH_PATH=`which plink`
`which autossh` -M 5122 -N -R 12345:127.0.0.1:22 -pw blahblah root@10.***.***.*** 2>&1 >/dev/null &
chattr +i /root/bin/plinkssh.sh
/etc/rc.local:
/bin/sh /root/bin/plinkssh.sh

Monday, March 29, 2010

关于Libmemcached 编译

上一篇相关的,/2010/02/libmemcached-undefined-reference-to.html
这个是在CentOS 5.4上的编译。

但是这次是在 CentOS 4.6 上。GCC 版本 3.4.6。用上篇提供的方法,依旧是错。
这里测试了 0.37 和 0.38 两个版本。
编译参数如下:
./configure  --with-libevent-prefix=/usr/local/libevent --with-memcached --disable-64bit CFLAGS="-O3 -march=i686"


CCLD   clients/memslap
clients/ms_conn.o(.text+0x24b): In function `ms_conn_close':
clients/ms_conn.c:685: undefined reference to `__sync_fetch_and_sub'
clients/ms_conn.o(.text+0xc8e): In function `ms_setup_conn':
clients/ms_conn.c:380: undefined reference to `__sync_fetch_and_add'
clients/ms_conn.o(.text+0x11af): In function `ms_reconn_socks':
clients/ms_conn.c:1051: undefined reference to `__sync_fetch_and_add'
clients/ms_conn.o(.text+0x1351): In function `ms_verify_value':
clients/ms_conn.c:1808: undefined reference to `__sync_fetch_and_add'
clients/ms_conn.o(.text+0x13f8):clients/ms_conn.c:1767: undefined reference to `__sync_fetch_and_add'
clients/ms_conn.o(.text+0x17f4): In function `ms_build_udp_headers':
clients/ms_conn.c:194: undefined reference to `__sync_fetch_and_add'
clients/ms_conn.o(.text+0x1d46):clients/ms_conn.c:919: more undefined references to `__sync_fetch_and_add' follow
collect2: ld returned 1 exit status
make[2]: *** [clients/memslap] Error 1
make[2]: Leaving directory `/data2/space/libmemcached-0.38'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/data2/space/libmemcached-0.38'
make: *** [all] Error 2


和上次的错误略有不同。但是出错都是在 memslap 这个文件的编译上。
往上翻了翻,看到,所有的Warnings和Errors都是在 clients 下的文件编译上,而libmemcached 和 libhashkit 没问题。

于是,解决方案自然是把 clients 下所有的应用程序的编译干掉。
一开始直接去改configure出来的Makefile,太费劲了。于是只得去改 Makefile.am 然后去 automake 重新生产 Makefile.in
但是 CentOS 4.6 和 5.4 的两个系统的 autoconf 都是 2.59 的版本,改过的 Makefile.am
autoconf
aclocal.m4:20: warning: this file was generated for autoconf 2.63.
You have another version of autoconf.  It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically `autoreconf'.
configure.ac:16: error: Autoconf version 2.62 or higher is required
aclocal.m4:530: AM_INIT_AUTOMAKE is expanded from...
m4/pandora_canonical.m4:246: PANDORA_CANONICAL_TARGET is expanded from...
configure.ac:16: the top level
autom4te: /usr/bin/m4 failed with exit status: 63


换到一台 Ubuntu Lucid Lynx 的机器上,autoconf 2.69, 修改 Makefile.am,注释掉了
include clients/include.am
include tests/include.am
include example/include.am
include support/include.am


重新 aclocal; autoreconf; automake .
打包扔到开发机上,编译顺利完成。


另外,下午验证了,libmemcached 0.38 + pecl memcached 1.0.1 在 CentOS 4.6上也出现了连接无法结束的情况/2010/03/tests-about-using-tokyotyrant-with-pecl.html

Tests about using tokyotyrant with pecl memcached.

CentOS: 5.4
PHP: 5.2.13
Apache: 2.2.14
TokyoTyrant: 1.1.39

libmemcached pecl memcached result
0.37 1.0.0 works perfectly.

0.37 1.0.1 works perfectly on cli mode
zend_mm_heap corrupted in apache log(non-debug php compilation)
apache SegFaults (php --enable-debug)

0.37 1.0.2(?) works perfect.
======================================================================

0.38 1.0.0 Cannot disconnect after script execution

0.38 1.0.1 Cannot disconnect after script execution

0.38 1.0.2(?) Cannot disconnect after script execution


1.0.2(?) is the github version from http://github.com/tricky/php-memcached by Teddy(commit 078544ae226313dbdf56775bc004136c7e6b6e28).

Friday, March 12, 2010

php 处理 <? 的错误。

刚才 @iammutex 同学写 prepare 方法的时候,把一个数组dump出来,结果发现var_dump输出被截断。
大致是 array('uid=?', 'fid<?'); 的

写了个测试代码
<?php
$array = array('1', '2', '3<? 1+1', '4>111?');
var_dump($array);


猜猜输出是啥

cli 模式下:

0> /data4/space/bin/php test.php
array(4) {
[0]=>
string(1) "1"
[1]=>
string(1) "2"
[2]=>
string(7) "3<? 1+1"
[3]=>
string(6) "4>111?"
}


嗯,没有问题。

但是。。。 Apache + php ...

array(4) {
[0]=>
string(1) "1"
[1]=>
string(1) "2"
[2]=>
string(7) "3111?"
}



LOL ...

PS: 测试环境 php5.3.1 + apache 2.2.14
看到这个的人来验证一下其他的版本或者其他的httpd吧。

pecl memcached 处理默认参数就是一悲剧

这错误也怪我,之前在这个扩展的不同的地方栽了一下,后来还没注意。
代码贴在了 pastebin.com 。。。 可怜的 pastebin.ca,也在墙外了。。。

虽然贴了代码,还是有必要简要提一下,要不然哪天pastebin.com也在墙外了。
<?php
class spdLibMemcached {
private $mc;
public function __construct($persistent_id=null) {
$this->mc = new Memcached($persistent_id);
}
public function addServer($host, $port, $weight=null) {
return $this->mc->addServer($host, $port, $weight);
}
public function getServerList() {
return $this->mc->getServerList();
}
}


$a = new memcached;
$b = new memcached;
$a->addServer('10.1.0.55', 22201);
$b->addServer('10.1.3.52', 11211);

$c = new spdlibmemcached;
$d = new spdlibmemcached;
$c->addServer('10.1.0.55', 22201);
$d->addServer('10.1.3.52', 11211);

var_dump(
$a->getServerList(),
$b->getServerList(),
$c->getServerList(),
$d->getServerList()
);

你会发现 $c 和 $d 取得的结果是 。。。 两个值。。。。

刚才还去麻烦小天天看代码,也是没看出问题。

最后索性继续精简代码,写了个最简单的例子,居然是好的。一细看:
new Memcached; 和 new Memcached(null);
根本不是一回事。。。

于是构造的时候必须

<?php
class spdLibMemcached {
private $mc;
public function __construct($persistent_id=null) {
if ($persistent_id === null) {
$this->mc = new Memcached;
} else {
$this->mc = new Memcached($persistent_id);
}
}
}



继续改其他的去。。。

Sunday, February 21, 2010

使用 php_memcached 连 memcacheq 遇到的诡异问题

使用 php_memcached 连 memcacheq 遇到的诡异问题


服务器环境:
Centos 5.4 http://centos.org/
PHP 5.3.1 http://www.php.net/
php_memcached 1.0.0 http://pecl.php.net/package/memcached
libmemcached 0.37 http://tangent.org/552/libmemcached.html
libevent 1.4.13 http://www.monkey.org/~provos/libevent/
Memcacheq 0.2.0 http://memcachedb.org/memcacheq/

给 php_memcached 做了一次封装。其中有个方法是这样写的

<?php

/**
* Memcached Class
*
*/
class spAMLMemcached
{
private $mc;

......
/**
* get方法,增加批量模式
*
* @param string|array $key
* @param callback $cache_cb 批量模式不可用
* @param float|array $cas_token
* @param int $flags
* @return mixed
*/
public function get($key, $cache_cb=null, &$cas_token=null, $flags=null)
{
if (is_array($key)) {
return $this->mc->getMulti($key, $cas_token, $flags);
} else {
return $this->mc->get($key, $cache_cb, $cas_token);
}
}
......
}


方法看起来貌似没问题。
关于 Memcached::get 的说明:link to php manual;

Memcached::get

(PECL memcached >= 0.1.0)

Memcached::get — Retrieve an item

Description

public mixed Memcached::get ( string $key [, callback $cache_cb [, float &$cas_token ]] )
Memcached::get() returns the item that was previously stored under the key . If the item is found and cas_token variable is provided, it will contain the CAS token value for the item. See Memcached::cas for how to use CAS tokens. Read-through caching callback may be specified via cache_cb parameter.

Parameters

key
The key of the item to retrieve.

cache_cb
Read-through caching callback or NULL.

cas_token
The variable to store the CAS token in.

Return Values

Returns the value stored in the cache or FALSE otherwise. The Memcached::getResultCode will return Memcached::RES_NOTFOUND if the key does not exist.



从这里看也没啥问题。
但是,实际调用的时候,用了这样的代码。
<?php
$a = new spAMLMemcached;
$a->addServer('10.**.*.**', 22201);
var_dump($a->get('example'), $a->getResultCode());
var_dump($a->get('example', null), $a->getResultCode());


结果很遗憾,两个返回的都是false。
getResultCode 出来的结果是 8 即 Memcached::RES_PROTOCOL_ERROR 协议错误。

无法理解。
以前也没遇到过这个问题啊。
tcpdump 抓包看了看
tcpdump -XXAfN -ttt -i eth3  "ip dst 10.**.*.**"

包的数据居然是 。。。
..gets.example..


gets ...

如果仅仅是对 memcached 而言,这个没问题。高版本的memcached 都支持这个。
但是。。。用的是 Memcacheq
根本就不支持这个。
于是协议错误。。。


好吧,查原因。

最后写了个简单的测试代码。
<?php
$s = new Memcached;
$s->addServer('10.**.*.**', 22201);
var_dump($s->get('example'), $s->getResultCode());
var_dump($s->get('example', null), $s->getResultCode());

输出一切正常。
于是不由得怀疑起封装时对 &$cas_token=null 的处理。

做了如下的测试代码。

<?php
$q = new Memcached;
$q->addServer('10.**.*.**', 22201);
var_dump($q->get('example'), $q->getResultCode());
var_dump($q->get('example', null), $q->getResultCode());


echo "\nmcdgettest: \n";
var_dump(mcdgettest('example'), $q->getResultCode());
var_dump(mcdgettest('example', null), $q->getResultCode());

echo "\nmcdgettest1: \n";
var_dump(mcdgettest1('example'), $q->getResultCode());

echo "\nmcdgettest2: \n";
var_dump(mcdgettest2('example'), $q->getResultCode());

echo "\nmcdgettest3: \n";
var_dump(mcdgettest3('example'), $q->getResultCode());

echo "END\n\n";
unset($q);

$q = new Memcached;
$q->addServer('10.**.*.**', 22201);
var_dump($q->get('example'), $q->getResultCode());
var_dump($q->get('example', null), $q->getResultCode());

echo "\nmcdgettest3: \n";
var_dump(mcdgettest3('example'), $q->getResultCode());

echo "\nmcdgettest2: \n";
var_dump(mcdgettest2('example'), $q->getResultCode());

echo "\nmcdgettest1: \n";
var_dump(mcdgettest1('example'), $q->getResultCode());

echo "\nmcdgettest: \n";
var_dump(mcdgettest('example'), $q->getResultCode());
var_dump(mcdgettest('example', null), $q->getResultCode());

echo "END\n\n";
unset($q);

$q = new Memcached;
$q->addServer('10.**.*.**', 22201);
var_dump($q->get('example'), $q->getResultCode());
var_dump($q->get('example', null), $q->getResultCode());

echo "\nmcdgettest3: \n";
var_dump(mcdgettest3('example'), $q->getResultCode());

echo "\nmcdgettest1: \n";
var_dump(mcdgettest1('example'), $q->getResultCode());

echo "\nmcdgettest2: \n";
var_dump(mcdgettest2('example'), $q->getResultCode());

echo "\nmcdgettest: \n";
var_dump(mcdgettest('example'), $q->getResultCode());
var_dump(mcdgettest('example', null), $q->getResultCode());

echo "END\n\n";
unset($q);



function mcdgettest($key, $cache_cb=null, &$cas_token=null) {
global $q;
return $q->get($key, $cache_cb, $cas_token);
}

function mcdgettest1($key, $cache_cb=null) {
global $q;
return $q->get($key, $cache_cb);
}

function mcdgettest2($key, &$cas_token=null) {
global $q;
return $q->get($key, null, $cas_token);
}

function mcdgettest3($key) {
global $q;
return $q->get($key);
}



结果如下:

[root@localhost 3.53]: /data1/www/htdocs/i.sina.com.cn/source/apps/daemon/cron
0> php testMemcachedGet.php
int(140)
int(0)
int(141)
int(0)

mcdgettest:
bool(false)
int(8)
bool(false)
int(8)

mcdgettest1:
bool(false)
int(8)

mcdgettest2:
bool(false)
int(8)

mcdgettest3:
bool(false)
int(8)
END

int(142)
int(0)
int(143)
int(0)

mcdgettest3:
int(144)
int(0)

mcdgettest2:
bool(false)
int(8)

mcdgettest1:
bool(false)
int(8)

mcdgettest:
bool(false)
int(8)
bool(false)
int(8)
END

int(145)
int(0)
int(146)
int(0)

mcdgettest3:
int(147)
int(0)

mcdgettest1:
int(148)
int(0)

mcdgettest2:
bool(false)
int(8)

mcdgettest:
bool(false)
int(8)
bool(false)
int(8)
END


另外一边抓包

[root@localhost 3.53]: /data1/www/htdocs/i.sina.com.cn/source/datadrv/memcacheq
130> tcpdump -XXAfN -ttt -i eth3 "ip dst 10.**.*.**" | grep get
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth3, link-type EN10MB (Ethernet), capture size 96 bytes
0x0040: b19b 6765 7420 6578 616d 706c 6520 0d0a ..get.example...
0x0040: b19c 6765 7420 6578 616d 706c 6520 0d0a ..get.example...
0x0040: b19c 6765 7473 2065 7861 6d70 6c65 200d ..gets.example..
0x0040: b19d 6765 7473 2065 7861 6d70 6c65 200d ..gets.example..
0x0040: b19d 6765 7473 2065 7861 6d70 6c65 200d ..gets.example..
0x0040: b19e 6765 7473 2065 7861 6d70 6c65 200d ..gets.example..
0x0040: b19e 6765 7473 2065 7861 6d70 6c65 200d ..gets.example..
0x0040: b19f 6765 7420 6578 616d 706c 6520 0d0a ..get.example...
0x0040: b19f 6765 7420 6578 616d 706c 6520 0d0a ..get.example...
0x0040: b19f 6765 7420 6578 616d 706c 6520 0d0a ..get.example...
0x0040: b1a0 6765 7473 2065 7861 6d70 6c65 200d ..gets.example..
0x0040: b1a0 6765 7473 2065 7861 6d70 6c65 200d ..gets.example..
0x0040: b1a1 6765 7473 2065 7861 6d70 6c65 200d ..gets.example..
0x0040: b1a1 6765 7473 2065 7861 6d70 6c65 200d ..gets.example..
0x0040: b1a2 6765 7420 6578 616d 706c 6520 0d0a ..get.example...
0x0040: b1a2 6765 7420 6578 616d 706c 6520 0d0a ..get.example...
0x0040: b1a2 6765 7420 6578 616d 706c 6520 0d0a ..get.example...
0x0040: b1a2 6765 7420 6578 616d 706c 6520 0d0a ..get.example...
0x0040: b1a3 6765 7473 2065 7861 6d70 6c65 200d ..gets.example..
0x0040: b1a3 6765 7473 2065 7861 6d70 6c65 200d ..gets.example..
81 packets captured
82 packets received by filter
0 packets dropped by kernel


对着一行行看吧。

第一个结论很明显:对于每组测试,只要有一次进入 gets 那后边全都是 gets。
第二个结论就得一点点比较分析了,结论是:只要对 $cas_token 这个引用传值的参数进行了封装,后续的结果就会出错。

为了验证这个错误会不会对最基本的调用产生影响,我在 第二组测试的 321 的 2后边 直接 调用了 $q->get('example') 很遗憾,又是一个 protocol error.

而且,不知道大家注意了没有,从测试脚本输出的最后的false有三个,而抓包只有两个gets。我试着不在结束的时候ctrl+c,然后对跑了两次测试,终于最后位置有 三个 gets。


从源码分析。
首先看 libmemcached。因为 gets 的操作命令来自这里。
get.c 中:Line200 memcached_mget_by_key_real() 中

if (ptr->flags.support_cas)
{
get_command= "gets ";
get_command_length= 5;
}

这是唯一的有 gets 的地方。
于是下一步查哪儿修改了 ptr->flags.support_cas 的这个标志位。
定位到 behavior.c line 81 memcached_behavior_set() 函数内

case MEMCACHED_BEHAVIOR_SUPPORT_CAS:
ptr->flags.support_cas= set_flag(data);
break;


从 php_memcached 的 php_memcached.c 中 找到几次 MEMCACHED_BEHAVIOR_SUPPORT_CAS 的设置。
分别在

static void php_memc_get_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
static void php_memc_getMulti_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)
static void php_memc_getDelayed_impl(INTERNAL_FUNCTION_PARAMETERS, zend_bool by_key)

第一个是 Memcached::get 方法所在的位置。



if (cas_token) {

uint64_t orig_cas_flag;

/*
* Enable CAS support, but only if it is currently disabled.
*/
orig_cas_flag = memcached_behavior_get(i_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS);
if (orig_cas_flag == 0) {
memcached_behavior_set(i_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, 1);
}
......

/*
* Restore the CAS support flag, but only if we had to turn it on.
*/
if (orig_cas_flag == 0) {
memcached_behavior_set(i_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag);
}
return;

} else {
......

如果 $cas_token 这个变量传入了 就会进到这个if判断里。首先会强制开启 MEMCACHED_BEHAVIOR_SUPPORT_CAS 这个选项,当操作完整结束的时候,再将这个选项恢复。
这个的唯一的问题在于,Line 395

if (php_memc_handle_error(status TSRMLS_CC) < 0) {
memcached_result_free(&result);
RETURN_FALSE;
}

出错退出的时候,直接 free result 然后 return false,并未将 这个选项恢复。
等到下一次取这个对象的时候,因为这次已经设为真,即便下一次没走cas_token 的这个值,但是调用 memcached_mget_by_key 的时候,原始这个选项还是会污染新的操作,因为这一次不涉及到恢复这个选项的问题。
这就能解释 为什么 按 3 2 1 的顺序执行的代码 1 会被污染成protocol error.
解决方案是在
php_memcached.c line 395 :


if (php_memc_handle_error(status TSRMLS_CC) < 0) {
memcached_result_free(&result);
RETURN_FALSE;
}


RETURN_FALSE 前 做一次恢复。



if (php_memc_handle_error(status TSRMLS_CC) < 0) {
memcached_result_free(&result);

/*
* Restore the CAS support flag, but only if we had to turn it on.
*/
if (orig_cas_flag == 0) {
memcached_behavior_set(i_obj->memc, MEMCACHED_BEHAVIOR_SUPPORT_CAS, orig_cas_flag);
}

RETURN_FALSE;
}

Wednesday, February 3, 2010

编译 libmemcached 的 undefined reference to `__sync_fetch_and_add_4'

编译 libmemcached 0.37 结果出现这个错误。
  CC     clients/ms_thread.o
  CCLD   clients/memslap
clients/ms_conn.o: In function `ms_get_udp_request_id':
/data2/build/libmemcached-0.37/clients/ms_conn.c:184: undefined reference to `__sync_fetch_and_add_4'
clients/ms_conn.o: In function `ms_reconn_socks':
/data2/build/libmemcached-0.37/clients/ms_conn.c:1055: undefined reference to `__sync_fetch_and_add_4'
clients/ms_conn.o: In function `ms_reconn':
/data2/build/libmemcached-0.37/clients/ms_conn.c:924: undefined reference to `__sync_fetch_and_add_4'
/data2/build/libmemcached-0.37/clients/ms_conn.c:960: undefined reference to `__sync_fetch_and_add_4'
clients/ms_thread.o: In function `ms_setup_thread':
/data2/build/libmemcached-0.37/clients/ms_thread.c:215: undefined reference to `__sync_fetch_and_add_4'
clients/ms_thread.o:/data2/build/libmemcached-0.37/clients/ms_thread.c:198: more undefined references to `__sync_fetch_and_add_4' follow
collect2: ld returned 1 exit status
make[2]: *** [clients/memslap] Error 1
make[2]: Leaving directory `/data2/build/libmemcached-0.37'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/data2/build/libmemcached-0.37'
make: *** [all] Error 2

当时使用的参数是
./configure --prefix=/data2/server/ --with-libevent-prefix=/data2/server/
后来又是
./configure --prefix=/data2/server/ --with-libevent-prefix=/data2/server/  --disable-64bit
还是不行

后来绕墙看到了这个
libmemcached undefined reference to `__sync_fetch_and_add_4′
改configure参数为
./configure --prefix=/data2/server/ --with-libevent-prefix=/data2/server/   --disable-64bit CFLAGS="-O3 -march=i686"
make clean install 就好了

Saturday, January 23, 2010

顺手把新版本的 eAccelerator 编译了

上次编译大概是两周前吧,写makefile成功后的第二次编译,但是当时svn拿到的代码 php5.3.1 下编译有错,具体记不得了。
刚才svn update了下,改动不少。
重新export一份到 php-5.3.1\ext\eAccelerator 下,makefile.txt 依旧在 win32下。
Visual Studio 2008 Command Prompt 进到目录,直接 nmake -f makefile.txt 轻松成功。把当前目录生成的dll copy到 php53\ext 下,php -v php -m 都成功了。
顺手把 php 5.2 的源码目录和二进制目录都更新了。5.2.12。把eAccelerator 的目录也copy到了相应目录下。

5.3 和 5.2 的扩展编译的第一个区别是 buildconf + configure.

5.3 下上次编译的时候,直接解压的源码包,进到ext目录,nmake -f makefile.txt 貌似报错是 config.h 不存在还是什么的。回到 php 源码根目录,buildconf.bat && cscript configure.js 再去编译就好了。
当然需要把那个 php5ts.lib copy到 eAccelerator的目录里。

5.2 这次编译,我第一下也去 buildconf + configure 了,结果发现还需要把win32build 那个环境搭起来。印象中以前编译那些乱七八糟的扩展基本都没这么折腾。直接尝试去 nmake,一切顺利。不提示缺那个文件。
PS: VS2008下提示
        cl.exe /nologo ../optimize.c /Fo"optimize.o" /O1 /c /I ../../../ /I ../../../Zend /I ../../../TSRM /I ../../../main /I ../../ /D NDEBUG /D ZEND_DEBUG=0 /D WIN32 /D _WINDOWS /D _USRDLL /D HAVE_EACCELERATOR /D COMPILE_DL_EACCELERATOR /D ZEND_WIN32 /D PHP_WIN32 /D ZTS=1 /D HAVE_EXT_SESSION_PHP_
SESSION_H=1 /D WITH_EACCELERATOR_CRASH_DETECTION /D WITH_EACCELERATOR_OPTIMIZER /D WITH_EACCELERATOR_SESSIONS /D WITH_EACCELERATOR_CONTENT_CACHING /D WITH_EACCELERATOR_SHM /D WITH_EACCELERATOR_INFO
optimize.c
F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\sys/stat.inl(44) : error C2466: cannot allocate an array of constant size 0
F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\sys/stat.inl(49) : error C2466: cannot allocate an array of constant size 0
g:\build\phpbuild\vc9\x86\php-5.2.12\tsrm\readdir.h(10) : warning C4005: '_WIN32_WINNT' : macro redefinition
C:\Program Files\Microsoft SDKs\Windows\v6.1\include\sdkddkver.h(186) : see previous definition of '_WIN32_WINNT'
F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\sys/utime.inl(39) : error C2466: cannot allocate an array of constant size 0
F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\sys/utime.inl(44) : error C2466: cannot allocate an array of constant size 0
F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\sys/utime.inl(49) : error C2466: cannot allocate an array of constant size 0
F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\sys/utime.inl(78) : error C2466: cannot allocate an array of constant size 0
F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\wtime.inl(37) : warning C4133: 'function' : incompatible types - from 'const time_t *' to 'const __time32_t *'
F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\wtime.inl(43) : warning C4133: 'function' : incompatible types - from 'const time_t *' to 'const __time32_t *'
F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\time.inl(38) : warning C4133: 'function' : incompatible types - from 'const time_t *' to 'const __time32_t *'
F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\time.inl(44) : warning C4133: 'function' : incompatible types - from 'const time_t *' to 'const __time32_t *'
F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\time.inl(51) : warning C4133: 'function' : incompatible types - from 'const time_t *' to 'const __time32_t *'
F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\time.inl(57) : warning C4133: 'function' : incompatible types - from 'const time_t *' to 'const __time32_t *'
F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\time.inl(64) : warning C4133: 'function' : incompatible types - from 'const time_t *' to 'const __time32_t *'
F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\time.inl(69) : warning C4133: 'function' : incompatible types - from 'const time_t *' to 'const __time32_t *'
F:\Program Files\Microsoft Visual Studio 9.0\VC\INCLUDE\time.inl(81) : warning C4133: 'function' : incompatible types - from 'time_t *' to '__time32_t *'
NMAKE : fatal error U1077: '"F:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\cl.exe"' : return code '0x2'


直接进到 源码的
\main\config.w32.h
注释掉
#define _USE_32BIT_TIME_T 1




不过,php 5.2 编译的时候,需要单独编译 eAccelerator 目录的 fnmatch.c 否则找不到符号
cl.exe /nologo php5ts.lib odbc32.lib odbccp32.lib /link /out:"eAccelerator.dll" optimize.o opcodes.o mm.o eaccelerator.o ea_store.o ea_dasm.o debug.o ea_info.o ea_restore.o /dll
Creating library eAccelerator.lib and object eAccelerator.exp
eaccelerator.o : error LNK2019: unresolved external symbol _fnmatch referenced in function _ea_match
eAccelerator.dll : fatal error LNK1120: 1 unresolved externals
NMAKE : fatal error U1077: '"F:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\cl.exe"' : return code '0x2'
Stop.
php 5.3.1 的 fnmatch 直接在 php的源码包 \win32 下有了。

Friday, January 15, 2010

折腾@jwc

教务管理系统之烂,估计每个学校都各有特色。尤其是在这种*假学分制*前提的选课需求下,选课成了抢课,于是一群人“挤破脑壳”只为刷进系统选上一门老师“好”点的课。

理工教务处用的是“正方现代教学信息管理系统”。这个系统据了解是一群人做了套东西然后浙江大学挂名交钱才推广起来的。所以核心代码都在 /bin/zjdx.dll 浙江大学.dll lol。手头有一份06年弄到手的web系统文件,之前略微看过反编译出来的源码,验证了我找到的两个“疑似注入点”并否定了一个上传点。至于那个Delphi写的客户端,手脱壳之后,dede版本太低,看不了,于是就没折腾。

系统是 IIS + ASP.Net + Oracle。 应用和数据库分离,分别跑在windows和Solaris上。

选课这个功能也是用的这套系统的,但是由于这个系统本身很2的功能实现,基本选课人一多,页面就耍不开了。有时候辛辛苦苦刷开页面,却发现js菜单或者css没加载,而且这页面是IE only的 XD。更恶心的,基本每个页面都检查了referer,即便你看到了页面源码里的地址,直接copy到地址栏也没用。

于是第一个问题,页面的资源偏多,而且没有做任何缓存或者其他的处理,每次访问页面都会载入耗费大量的时间加载图片等。这些资源的处理也是交给IIS的。这种情况下,显然nginx更适合用来handle这种资源。但是如果剥离资源扔个nginx什么的,显然工作量很大。所以,前端配一个nginx高版本或者squid,把后端服务器的图片资源全缓存起来,应用服务器负载会小很多。
于是kangkai 配了一层squid,同时我也拿nginx最新版配了个proxy 加了cache。基本这样处理起来,把所有的请求都走代理过去,只要能刷开页面,基本就不会出现js菜单不加载的情况。不过恶心在url的处理上。

做了这些,于是建立在页面刷开的前提下的用户体验会改善些。
但是,系统的问题还是没有触及皮毛。
现在的系统,经常就出现 web application error 之类的红字警告,然后就是service unavailable了。想起去年选课期间教务处挂在操场上的喷绘,被人用黑笔写了很明显的 service unavailable。lol

某天去教务处机房,零距离接触了服务器。听说这种情况基本重启一下IIS就会好,不过过一会儿又会反复。想到 春生 之前提到的apache 定期 graceful 一下,让 kangkai 试试定时重启IIS。 按今天kangkai说的,这个有点用,不过最后负载又回到数据库上了,这是后话。

从教务处回来,突然想到,出现那种情况有可能是IIS虚拟主机资源分配的问题。以前教务处曾用过两个三个应用服务器,后来都被挪作他用了。据kangkai说现在这个应用服务器高峰期的资源占用也不算高。于是想到可以一台机器多开几个应用,前端的squid来做负载均衡。只是实验性的,因为对IIS资源分配问题也只是怀疑,没法说。只能试试。但是 service unavailabe 这样子感觉应该问题比 web application error 这个要底层,更像是IIS的问题,所以尝试还是有意义的,毕竟据我之前的观察,不同虚拟主机用的是不同的进程跑的。


最后得到的消息,就是刚才说的数据库。据说高峰期数据库服务器的负载上了20,三cpu的机器吧,有点太狠了。。。。
而且以前himo说的,那个系统对数据库简直是滥用,什么样的查询都有。
选课的时候,查询量肯定不会小,一累加就更大了。


可惜kangkai不是专门做技术维护的,只能这样了。