点击文章标题察看全部内容。
作品名称:你,或者你们,或者我们,或者我
创作时间:2008
展览: Shanghai eArts Festival 2008
展区:蓄与化——青年新媒体艺术作品展
展览时间:2008-10-18 ~ 2008-11-08
官方网站介绍页面:http://www.shearts.org/index.php/?p=591&lang=zh-cn (可能会失效)
Flv视频播放:

局部图案
全景图1
全景图2
点击文章标题察看全部内容。
作品名称:你,或者你们,或者我们,或者我
创作时间:2008
展览: Shanghai eArts Festival 2008
展区:蓄与化——青年新媒体艺术作品展
展览时间:2008-10-18 ~ 2008-11-08
官方网站介绍页面:http://www.shearts.org/index.php/?p=591&lang=zh-cn (可能会失效)
Flv视频播放:

局部图案
全景图1
全景图2
经历了近1个月的神秘倒计时,或许大家已经猜出来了,不过还是要正式申明。
很荣幸在本届上海电子艺术节( eArts Shanghai Festivial )中有我的作品。 下面是作品名和相关介绍:
作品名称:《你,或者你们,或者我们,或者我》
艺术家: 何为&陈士凯
作品类型: 网络信息装置
创作时间:2008年
作品概念:
搜索引擎作为现代网络最普遍的信息工具,起着便捷沟通用户与全网络的作用。如果我们将用户使用搜索引擎的过程定义为一种交流方式。那么可以说,用户由发问到引擎反馈,以机器为中介为反馈完成了整个问答的交流过程。用户在网络中的自行创作被捕捉作为引擎反馈的语素。为达到更优的反馈效果,用户的操作行为在无意间为引擎引用为缔造新反馈语序的依据。对话获取者是用户,而对话的创作革新者恰又是用户本身是如此应用反复类推的结果。看似借助机器和群体智慧的对话在用户操作及机器规则中完成的选择性的对话恰成为一种无选择性的自我对话。
作品以真实接入的社区搜索关键词为根基。试图探讨对蓄智慧一身的网络及搜寻演化可能及关于信息用户自体身份的迷失。跟踪的数据采用每前一天相应时段的信息以保证正常运行。
eArts将于2008-10-18,对,就是今天开展。下面是蓄与化——青年新媒体艺术作品展区的地址信息:
“蓄与化——青年新媒体艺术作品展”
活动时间:2008年10月18日 ~ 11月8日
活动地点:创智天地-创智天地广场
eArts官方网站:http://www.shearts.org/index.php/?page_id=15
最近为此准备已经好久没正常休息了,今天恐怕也没法好好睡觉。还是不多说了。如果对此感兴趣欢迎前来捧场~ 至于作品,我觉得质量上不会让各位失望的:-)
好了,以后有时间再好好总结下巴
最近想到该更新下自己网站了,好吧,就从那个我已经看不惯很久的msn space同步转发器开刀...
如果你是先通过space看到这篇文章的话,应该就能看到效果了。撇去显示效果不说,这里提一个有趣的问题:
换句话说,假设有下面这段html代码:
<p>this is a truncated html source<a href=\"some _fcksavedurl="\"some" URL\">some hyperlink</a>.<BR>
more text</p><p>one more</p>
出于某种需要,希望只显示(保留)这段代码的前n个字节。这样的需求其实不少见,最明显的就是在msn space文章同步的时候,我只希望对文章的大致内容转发过去,目前的做法就是截取文章的前1000字节。
如果仅仅是对一段普通文本进行这样的处理,那实在简单不过。直接截取即可。但是html却不同。
例如,对于上面的文字,如果截取的部分是:
今后将这段代码用于其它页面将出现不可能预见的问题。
考虑下面的代码:
<p>Some html code</p>
The following is a truncated article:<div><%=truncated_text%></div>
将上面被强制截断的代码片断填充到这段代码可能会让好好的html页面面目全非。
因此,我们需要"优雅"的去截断这段html。
造成上述问题的根本原因在于对html的强制截断忽略了html的结构信息,使得后面浏览器的分析操作出现紊乱。
因此,优雅的去进行html截断必须在截断后仍旧维持当前的html结构信息。
可能你会说,这还不简单,直接实现一个html parser或者用xml dom分析器来完成此事。的确可以,不过这样的效率和代价实在有点可怕了。因此,要完成这个优雅的截断操作,同时需要在执行效率以及资源消耗间做取舍。同时,尽量避免动辄用dom parser的恶俗。
寻找一种刚好能解决此问题,且保证效率较高并尽量避免滥用资源的途径是我们需要的。
相信在这个所谓的什么"web2.0" "web3.0?"的扯淡名词时代恐怕已经有人实现过类似的东西,所以这里仅说说我目前的实现方案。如果你知道有更好的办法,希望能和大家分享。
撇开具体实现,这个问题其实很简单,就是一个配对问题。用一个stack来跟踪html标签的使用情况,每个<tag>应该有一个对应的</tag>配对。因此我们只要扫描一遍html,堆栈上残留的元素就是没有配对的tag。这些tag就是因为我们的暴力截取而成为孤对的。因此我们只要在html代码末尾FILO的补上这些这些tag的对应/tag即可。
但是还有些细节问题。
同时,对于暴力截断的html代码,我们不能奢望它们正好截断在一对tag之间,就像上面给出的例子那样,对于末尾是
的情况,我们还首先需要将这些“残缺”的tag给删去,否则即使配对仍旧存在问题。
大致的思路就是这样,关键就是如何实现的问题了。这里我仅采用javascript的String.replace方法进行上述的html扫描。
实际上实现的困难在于如何去识别html的tag。这里的底线是不能用现有的dom parser。Javascript的正则式功能在这里就能派上大用处了。根据上面的分析,为了进行tag匹配的分析,我们需要识别出html中的所有tag。
他们存在下面几种形式
我们的任务是编写正则式去查找这些tag。并且捕获到tagname。这里用到了一个偏方,利用String.replace方法。
一般,很多人都这样用它some_str.replace(/some regexp/, "new text");
实际上,他有另一个形式:
some.replace(/some regexp/, function( match_text)
{
return "new text";
});
利用一个匿名函数进行替换...
实际上,这个replace是一个再好不过的基于正则式的查找操作手段。因为相比手写一个查找循环,他的迭代操作是在解析器内部实现的,效率肯定要高很多。同时据我所知,要写个循环依次查找每个匹配正则式的循环很不容易,貌似没法指定搜索的开始字符。
好了,到此关键问题解决了。试验证明用这个办法效率完全可以接受,同时完全没有使用任何第三方的东西。
是具体实现时候要注意考虑前面提到的所有特殊情况。
下面来看下效果,为了展示各种情况,另外给个例子:
经过处理后,变成了:
有了这个功能,相信在作诸如自动缩略文处理时候就会轻松许多。(此刻让我想起了某些blog强制把html转成纯文本作略文的办法...)
最后,给出一个测试代码。喜欢的可以直接拿去用。当然,留下原始作者信息
ftp://FTP_Visitor:visitor@ftp.csksoft.net/Public/Products/code_and_lib/wise_cut_csk.zip
转载请保留作者信息
来源: http://www.csksoft.net/blog
作者:陈士凯
Branch Trace Store(BTS)是目前广泛被intel CPU所提供的一种硬件辅助调试功能,因为在MSRA项目需要,所以作了一些基于它的应用。虽然Intel的CPU开发手册[1]提供了比较详细的使用方法,但是由于比较笼统,且缺少win32下的相关资料。所以我打算把其中的一些tricky的事情和大家分享下。这些内容当然也是我自己查找公开资料得到的,因此也不算什么秘密吧 :-)
BTS简单的说就是允许CPU将自己实际执行到的分支指令(jmp/jxx/call/int/etc.)的相关信息保存下来的功能。一般CPU都会保存每个分支指令的源地址和目标地址,该地址在保护模式下是虚拟地址形式表示的。利用这个功能,可以实时地了解当前CPU正在执行代码的实际流程情况,很多分析软件,如Intel的Vtune或者profiling库,如*nix平台下的perfmon[2]都用它来做一些程序性能分析。当然,还可以做很多其他有趣的事,比如逆向工程,具体我就不说了。
不过目前很少有资料具体介绍如何在win32下开启该功能并实现一个可用的BTS捕捉引擎。当然可以参考perfmon的代码,但BTS在其中只是很小一个部分,同时为了实现跨平台,对于新手来说难度较大。因此我这里重点介绍对于单核心的NetBurst构架的CPU(通俗地说就是P4这类)在win32下的具体实现细节。其他的构架,比如现在的Core Due,大家可以参考intel的开发手册举一反三。
实际上,上面所说的BTS只是intel对于分支指令信息捕获机制的一个分支,就P4而言,大致提供了下列几种分支指令的捕获手段
故名思意,该方式将记录最后几个分支信息,实际上NetBurst CPU中内建了若干个MSR寄存器用于记录Last Branch Record,称为LBR Stack。在该模式下运行的CPU会采用Round Robin的方式循环填充那几个MSR寄存器。
该方式常用在调试器的Call Stack分析上,我们这里就不涉及了
该方式和我们将介绍的Branch Trace Store大致类似,与LBR不同的是,CPU会把分支信息发送到系统总线上供第三方硬件在总线上接收数据。而BTS则直接将数据保存到由程序制定的内存单元中。我们这里也不讨论该方式。
简单的说,BTS就是将分支信息保存到了有程序(实际就是我们)制定的一块内存空间中。而当这块内存用尽时,CPU可以采用Round Robin的方式循环填充,这就和LBR类似,但可以指定内存块的大小来决定最大捕捉量。另一种处理方式是在内存快用尽的时候,一个事先由我们设定的处理中断将触发来完成对当前内存块中BTS数据的保存工作。这样就可以记录任意多的分支信息了。我们这里主要考虑的就是这种方式的BTS。
按照intel开发手册的描述,BTS开启后的CPU执行模式如下图所示:

每当CPU执行到一个分支指令后,它就会产生一个如上左图的BTS记录项。这里举个例子:
0x80001234 mov eax,[esp]
0x80001238 or eax,eax
0x80001240 jnz 0x80002000
0x80001245 nop
...
当执行上面这段执行,其中遇到了jnz指令,如果他的跳转条件成立,那么将产生一个从0x80001240到0x80002000的跳转,那么产生的BTS记录项就是{From:0x80001240,To:0x80002000,...}
对于P4的CPU,这个BTS记录项的结构如下:
struct BTS_ITEM_BLOCK_P4{
ULONG dwBranchFrom;
ULONG dwBranchTo;
ULONG dwFlags;
};
每次CPU执行到分支指令的时候,只要BTS开启,它就会产生一个如上结构得数据块,然后把它存储到事先定义好的一块内存当中去。而这块内存是比较灵活的,如上图所示,CPU需要知道这块内存的起始地址、结束地址、以及当记录到第几个记录时候需要触发一个中断程序来负责将现有的BTS记录保存下来防止内存溢出。当BTS记录存储到图中那个灰底色的“BTS记录#m”时,就会触发中断,可以发现它往往并不是整块记录内存的末端,具体原因就不解释了。
为了让CPU知道我们设置的内存空间的信息,需要提供一个叫做DS_BUFFER_MGR_BLOCK的结构来描述这块内存,他包括的内容如图所示,然后我们需要设置一个名为IA32_DS_AREA的MSR寄存器来指向这个DS_BUFFER_MGR_BLOCK数据的地址。
P4下DS_BUFFER_MGR_BLOCK的完整结构是:
注意上面黑体的条目,这些部分是BTS需要设置的,后面的是PEBS采用机制所需要的信息,这里我们忽略他们。这些条目需要设置成保存BTS内存的相关地址(虚拟内存地址)。
同时,还需要让CPU知道用于处理BTS溢出的中断号。目前的Local APIC控制器上有一个称为Performance Mon. Counter的寄存器项。当BTS记录项接近溢出时,就会通过这个记录项中存储的中断向量值去触发对应的中断程序。这个Performance Mon. Counter的格式如下图所示(图片来自intel手册):

由于APIC芯片寄存器映射到了物理内存空间0xFEE00000H处,因此,对于其中寄存器的读写操作可以像标准内存操作那样进行。不过,由于采用虚拟内存的操作系统环境下,需要将该空间映射到对应的虚拟内存地址下,同时要避免操作系统的缓存行为。该部分细节我会在后面介绍。对于APIC芯片和LVT的一些具体细节可以参考intel手册[3]。
以上便是整个BTS工作的框架,如果不考虑具体的操作系统环境,对于他们的设置不存在很大的难度。不过由于OS引入了各类抽象机制或者保护手段,所以有一些tricky的问题需要处理。下面我讲介绍一个具体的实现流程。
经过上面的分析,对于Win32下进行BTS捕捉,需要进行如下的操作
下面我就每个过程的关键问题具体展开介绍,同时给出些示例代码(不保证能运行)。同时,因为涉及到了底层的硬件控制,这里的代码自然就是在Kernel模式下执行的,如果对WinDDK的开发不熟悉,可以先参考相关文献。
这部分就不具体介绍了,直接可以使用内核的ExAllocatePool来分配内存单元,需要注意的是,对所分配的内存必须位于系统的Nonpage pool中。在这里假设所创建的内存空间用符号pBtsBuffer表示:
对于DS_BUFFER_MGR_BLOCK的设置只需要关注BTS部分,假设已经分配了2000个BTS记录的内存空间,且希望当记录到第1900项时触发中断,那么初始化代码可以是:
DS_BUFFER_MGR_BLOCK *pDSBlk = <some allocating code>;
pDSBlk->pBTSBufferBase = pBtsBuffer;
pDSBlk->pBTSBufferIndex = pDSBlk->pBTSBufferBase;
pDSBlk->pBTSMaxSize = &pBtsBuffer[2000];
pDSBlk->pBTSIntThresold = &pBtsBuffer[1900];
在设置好了数据后,就要将DS_BUFFER_MGR_BLOCK的地址写入IA32_DS_AREA :
其中, IA32_DS_AREA为值:0x600
在Windows下添加中断处理程序的具体方式这里就不介绍了,可以参照Undocumented Windows NT[4]。这里需要注意几个问题:
对于BTS的开关操作,将在后续介绍。对于清除Performance Mon. Counter寄存器的屏蔽位,可以通过简单的对其进行重设达到效果,因此可以参考后面介绍的方法。
下面给出一个简单的中断处理过程代码:
void __declspec( naked ) BTS_handler(void)
{
//保存当前线程状态,恢复内核模式相关寄存器
__asm
{
cli
pushad
pushfd
push fs
push ds
push es
push gs
mov ebx,0x30
mov eax,0x23
mov fs,bx
mov ds,ax
mov es,ax
}
//关闭BTS,具体见后文
__asm{
mov ecx,MSR_DEBUGCTL
RDMSR
mov tmp_old_msr_bts,eax
xor eax,eax
WRMSR
}
//相关操作,如保存BTS到磁盘
//结束中断处理--------------------------------------
pDSBlk->pBTSBufferIndex = pDSBlk->pBTSBufferBase; //重设BTS记录指针
//开启BTS,具体见后文
__asm
{
//restore BTS
mov ecx,MSR_DEBUGCTL
mov eax,tmp_old_msr_bts
WRMSR
}
//清除local apic中preformance mon. counter的屏蔽位,具体间后文
local_apic->lvt_pc.mask=0;
//发送eoi指令字
local_apic->eoi.eoi = 0;
//恢复当前线程环境
__asm{
sti
pop gs
pop es
pop ds
pop fs
popfd
popad
iretd
}
}
其中,对于BTS的开启关闭,将在后文介绍。这里主要讨论对于local apic的操作。在前一章中已经知道,pc中将该芯片的寄存器映射到了物理地址的0xFEE00000H处。而按照Microsoft Windows Internals[5]中的描述,该地址在windows中被映射到了虚拟地址:0xFFFFD000H处。
经过我的验证,的确如此,但是估计因为内核的保护机制,对这块映射的内存地址并不能直接操作。首先是对于很多寄存器,比如发送EOI的EOI寄存器,对它的写入操作将导致BSOD。同时,我也发现内核采取了缓存的手段。
这里采用来自Micah Richert[6]的方法。同时感谢他提供的local apic结构声明[7]。不通过windows内核映射的空间,而是直接重新将那块物理地址进行映射:
注意其中的黑体参数。今后便可以直接操作local_apic 。同时,Micah Richert定义了很完善的local apic寄存器结构,可以直接用结构体定义完成操作。
按照intel手册的描述,在中断完成后需要发送eoi指令,否则该中断将得不到再次触发。具体做法就是给local apic中的eoi寄存器清零。具体代码见上文。
对于中断服务程序的安装(注册)可以参考很多现有的文章,比如[4]。其中,我选用了ID为0x28的中断,因为win32中该中断项往往是闲置的。具体的手段就是修改IDT表,这部分内容这里不再涉及。
在完成中断的安装后,需要设置Performance Mon. Counter 寄存器。比如我设置int 0x28为BTS溢出中断,那么Performance Mon. Counter需要如下设置:
对于NetBurst构架下,将通过MSR_DEBUGCTL MSR进行BTS的开关操作,下图为该MSR我们所关心的位:

换句话说,我们只需要往该MSR中写入0x1c即可开启BTS。而清零则可关闭。
//开启BTS
mov ecx,MSR_DEBUGCTL
mov eax,0x1c
WRMSR
//关闭BTS
mov ecx,MSR_DEBUGCTL
xor eax,eax
WRMSR
上述办法仅针对但核心的P4处理器有效。如果面对多核环境或者多处理器环境,需要分别设置每个逻辑处理单元的local apic。同时可能要考虑潜在的竞争情况。
通过上述办法捕捉到的BTS将包含整个系统的分支信息,其中不但混杂着用户态、内核态(甚至虚拟化技术的Hypervisor模式),同时不同线程也将混合在一起。因此对于实用的分析,需要作额外的处理。比如要知道线程切换的信息。这里可以参考Pjf关于线程切换信息的捕获方式[8]。
另一个需要注意的问题是如果直接在中断处理程序中进行对BTS写入文件将严重影响当前线程的执行。同时如果执行在不同的线程上下文中将使得诸如ZwWriteFile等导致系统锁死。
经过上述的设置过程,即可实现win32下的BTS功能开启。目前BTS已经广泛的存在intel各系列CPU中。同时也被其他各类CPU所采用。除了目前性能分析软件使用外,BTS对系统分析、逆向工程等均有很大
[1] Chapter 18.6, Intel 64 and IA-32 Architectures Software Developer’s Manual, Volume 3B: System Programming Guide, Part 2
[2] perfmon2, the hardware-based performance monitoring interface for Linux, http://perfmon2.sourceforge.net
[3] Chapter 9.4, Intel 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A: System Programming Guide, Part 1
[4] Prasad Dabak, Sandeep Phadke, Milind Borate, Undocumented Windows NT, Chapter 10
[5] Mark E. Russinovich and David A. Solomon, Microsoft Windows Internals, 4th Edition
[6] Micah Richert, http://www.snl.salk.edu/~micah/
[7] Micah Richert, RTInterrupt, http://www.snl.salk.edu/~micah/RTInterrupt/
今年是我所在的计算机系50周年庆,同时作为即将毕业的学生。能为自己系设计纪年衫十分荣幸,而且该系衫是免费向我们发放的:-)
下面是效果图,衣服我猜最近应该能拿到了,期待一下。不过之前没设计过纪念衫,专业人士就别拍我了...
本次采用2色印刷,所以色彩上还是比较有限制的


反面
什么使用权我就不要了,需要的直接拿源文件去吧
http://www.csksoft.net/data/cs-tshirt-src_v2_csk.rar
很久就打算重新设计网站的logo以便相互交换链接用。但估计是事情太多,同时也太懒。终于在2年后做出了新logo...


原始的logo因为本人没有任何经验,尺寸都不是标准的.. 这次应该还看得过去。
或者
或者
下面是一个指向我主网站的logo代码示例:
效果:
如果你有自己的Blog或者网站等,十分欢迎相互交换链接。具体方式可以联系我(见 关于)。
我会将你网站的logo和链接置于blog中的友情链接中。
在此感谢所有关心和鼓励我和本网站的朋友们
请注明原文出处: http://www.csksoft.net/blog/post/demo_scene_tip1.html
Demo Scene我就不想再介绍了,对他还不了解或者听说过但不明白原理和背景的可以参考我以前写的一些文章:
Demo Scene:Principles,Techniques,and Tools (http://www.csksoft.net/blog/post/154.html)
模块音乐(Mod)的制作和使用,Demo程序的主体之一 (http://www.csksoft.net/blog/post/intro2track_music.html)
目前国内Demo Scene基本处在0起步的阶段,已经有了一些小团体打算去参加欧洲的比赛,但是还没有一定的规模。同时,对于制作这类程序网上也没有系统的资料。使得制作Demo Scene被看成一种高深的事情。
下面我就说说目前在Windows平台下,使用最常用的开发工具(Visual C++)如何来制作一个符合64kb demo的程序框架和常用技巧。当然这只是一些次要手法,最核心的还是3d引擎、mod音乐的设计。因为那些资料很好找。所以就不再涉及。
我将介绍下面几个方面的技术:
1.如何产生体积最小的程序
2.如何不使用C运行库开发程序
3.如何实现高速GDI绘图
4.对于NT5.0提供的LayeredWindow的使用--不规则窗体、窗口的AlphaBlend渲染、鼠标事件穿透
5.如何将所有数据(代码、图片等)整合在一个C文件中
6.其他的一些编译技巧
7.一个完整的示例程序代码
Scene Demo中有一个项目为4kb-intro 或者 64kb-intro。 他要求Demo的程序体积必须小于或者正好等于4/64kb。而往往正是这类Demo程序在国内流传最广。因为大家都认为那么小的体积能播放长时间的高品质3d动画和音乐是不可思议得。甚至有人将45分钟的demo动画看成是avi视频,45分钟的音乐算作44KHz采样的wav。计算出将他们压缩到64kb完全是不可能的(见farbrausch的作品: the product 中的说明字幕)。当然这只是忽悠外行的吓人话。其实写过游戏引擎的人都知道那只是通过实时渲染的到的,而音乐本身就是体积在12kb左右的mod音乐序列(见我以前写过的文章)。
目前很多机器都已安装最新版本的DirectX,而OpenGL是windows的默认库之一。这样Demo Scene设计者一般就不需要自己去编写基本的3d引擎。动画部分几个基本特效的代码不会超过30kb(这里假设开发者具有较高的设计素质),而一些复杂网格模型的纹理贴图即时采用bmp保存,也在100kb-300kb左右。加上mod音乐和其播放引擎。一个64kb DemoScence程序的原始体积一般应在600kb。而不是通过用等效为avi文件计算方法算出的几个G的天文数字。
不过,问题就产生了,实际程序体积只有64kb。在这600kb->64kb还是有相当距离的。如何尽可能的去减少这部分文件大小,以及其中伴随的一些技巧就是本文所要讨论的。
....

请点击文章查看完整内容
这个游戏已经好久没有维护了,就连我也差点忘记自己还制作过这个游戏。不过没想到的是一直还有玩家在尝试过关,虽然和刚发布时候相比已经冷清很多。考虑到今后自己可能没有时间再出后续版本,同时对很多人来说,这个游戏的第二版或许难度高了些。也有人写信给我怀疑第二版根本无法通过。因此,我花了点时间,自己作为一名闯关者,把这个游戏过了一遍。下面就是我本人的过关方法,这个攻略应该说是“官方”版本了,也就是我出题时希望挑战者采取的方法。
虽然是面向初学者的游戏,挑战2还是有一定深度和可玩性的。没尝试过的朋友不妨借助这篇文章自己体验下:-)
高手挑战是我在发布自己网站之后不久制作的一款网页闯关游戏,原本只是为了好玩随便制作了下,但出乎我意料的是他的第一版在网络上大受欢迎。
接着我制作了这个游戏的第二个版本,他的难度和前一版相比有很大的提升,不再是简单的设计一些基础的操作能力。而是涉及互联网相关技术(HTTP协议/HTML/CSS/XML/RPC/FLASH/JavaScript等)、图像处理、音频处理、基本的反汇编调试技术、基本的网络安全技术、原始数据恢复等方面。同时游戏有不单单简单的考察这些知识,而是通过巧妙组织具有很强的趣味性。
游戏的URL是:http://www.csksoft.net/netcompet2/
与2005年年初发布,目前累计有50多人通过挑战,参与者9240人,通过率 <= 0.5%
通过上面数据,可以看出游戏还是具有一定的难度的。为了防止通过者将答案散步在网上,我对游戏也作了一定的处理,比如最终闯关成功认证时候需要验证码,而验证码是由之前闯关时游戏者收集到的验证码碎片通过特定的计算公式得出的。而验证码碎片以及计算公式对于不同玩家是不相同的。另外,游戏系统会纪录每个游戏者的游戏进度,一方面可以帮助游戏者下次登陆后能自动进入上一次的关卡继续游戏,同时也能在一定程度上防止提前进入没有通过的关卡(防止直接从网上看到答案)。
虽然这些手段不能非常有效地阻止答案泄露,但一定程度上还是有作用的。因此从游戏发布至今将近3年中,通过者寥寥无几,网上也很难找到比较完善的通关策略。
一共14关,每一关就是一个页面,游戏者需要做的就是通过当前关卡提供的信息,找到下一关的页面地址。
在通关过程中需要收集5个验证码片断
最终,通关者需要将收集来的验证码片断通过游戏提供的工具组合成最终的验证码,并通过最终的验证。此时闯关成功。
下面介绍的方法是我自己亲自操作得来的,因此可以保证100%的正确性。
但是需要注意的是,就像上面提到的,具体的数据和方法对于每个人都存在差异,因此不可能照搬得来。
本游戏在中途关卡也做过调整,这次公布的方法包括了调整前后的差别。
地址:http://www.csksoft.net/netcompet2/gamearea/start2.htm
这一关的线索在网页源代码中,通过提示察看其中的CSS文件stdStyle.css
会发现如下代码:
deefr3c.htm就是下一关地址
获得验证码碎片:CT02
地址:http://www.csksoft.net/netcompet2/gamearea/deefr3c.htm
这关是一个ASCII变换问题,由提示中给出的关系:@LE -> htm
通过查找ASCII码表可知,@与h,L与t,E与m他们的ASCII值均相差40,因此,可以只需要将本关给出的字符串:+L=J=G?J9E.@LE,一次把每个字符的ASCII值加40,遍可以获得下一关的地址。
上述计算可以手工查表计算,也可以编写程序获得。这里推荐利用我Flash网站的即时代码执行功能编程计算得到。下面是计算本关答案的ReformScript代码:
var src_text;
var dest_text;
src_text = "+L=J=G?J9E.@LE";
dest_text = "";
for (i=0;i<src_text.length;i++)
{
cur_ascii = src_text.charCodeAt(i);
if (src_text.substr(i,1) != ".") {
cur_ascii += 40;
}
dest_text+= String.fromCharCode(cur_ascii);
}
msgout(dest_text);
将上述代码复制入Flash网站并执行,获得结果:Stereogram.htm
地址:http://www.csksoft.net/netcompet2/gamearea/Stereogram.htm
按照提示的说明,下载页面上的图片文件:stere.jpg
下一关的信息就藏在该文件中,根据jpg的定义,其中允许保留创建程序的字段信息。可以通过16进制察看器观察。这里采用windows/DOS系统自带的debug工具。
在debug中输入如下指令:
此时,该文件头部长度为0x100字节的数据显示如下:
-d100 L100
13D4:0100 FF D8 FF E0 00 10 4A 46-49 46 00 01 02 01 00 48 ......JFIF.....H
13D4:0110 00 48 00 00 FF E1 34 2C-45 78 69 66 00 00 4D 4D .H....4,Exif..MM
13D4:0120 00 2A 00 00 00 08 00 07-01 12 00 03 00 00 00 01 .*..............
13D4:0130 00 01 00 00 01 1A 00 05-00 00 00 01 00 00 00 62 ...............b
13D4:0140 01 1B 00 05 00 00 00 01-00 00 00 6A 01 28 00 03 ...........j.(..
13D4:0150 00 00 00 01 00 02 00 00-01 31 00 02 00 00 00 1B .........1......
13D4:0160 00 00 00 72 01 32 00 02-00 00 00 14 00 00 00 8D ...r.2..........
13D4:0170 87 69 00 04 00 00 00 01-00 00 00 A4 00 00 00 D0 .i..............
13D4:0180 00 00 00 48 00 00 00 01-00 00 00 48 00 00 00 01 ...H.......H....
13D4:0190 43 53 4B 53 4F 46 54 20-53 74 65 72 65 6F 69 63 CSKSOFT Stereoic
13D4:01A0 20 4B 65 79 3A 44 72 65-61 6D 69 6E 67 43 68 69 Key:DreamingChi
13D4:01B0 6C 64 2E 68 74 6D 20 42-65 20 43 61 72 65 00 00 ld.htm Be Care..
13D4:01C0 00 00 00 03 A0 01 00 03-00 00 00 01 00 01 00 00 ................
13D4:01D0 A0 02 00 04 00 00 00 01-00 00 02 42 A0 03 00 04 ...........B....
13D4:01E0 00 00 00 01 00 00 01 AE-00 00 00 00 00 00 00 06 ................
13D4:01F0 01 03 00 03 00 00 00 01-00 06 00 00 01 1A 00 05 ................
注意上述红字部分,得到字符串DreamingChild.htm
此时,大部分玩家会以为下一关的地址就是http://www.csksoft.net/netcompet2/gamearea/DreamingChild.htm
虽然上述链接的确会进入一个关卡,但显示为3.5关。这是一个陷阱,此时需要回到第三关页面,在html代码中找到注释的代码:
<!--
别忘了这里!
<TitleName>.<ExtName>
Asc(<NewName>(n))=Asc(<TitleName>(n))+1 'where n ranges from 1 to Length(<TitleName>)
FinalData:<NewName>.<ExtName>
-->
说明下一关的正确地址是需要通过对前面得出的字符串作一定变换得来的,阅读伪代码,很容易知道这也是一个ASCII变换问题。可以通过修改之前给出的ReformScript代码计算出本关答案:
var src_text;
var dest_text;
src_text = "DreamingChild";
dest_text = "";
for (i=0;i<src_text.length;i++)
{
cur_ascii = src_text.charCodeAt(i);
cur_ascii += 1;
dest_text+= String.fromCharCode(cur_ascii);
}
msgout(dest_text);
执行上述代码,得到结果:EsfbnjohDijme,因此,下一关地址为EsfbnjohDijme.htm
地址:http://www.csksoft.net/netcompet2/gamearea/EsfbnjohDijme.htm
这一关页面中,要求闯关者输入正确的密码以便进入下一关。
当然这不可能要求闯关者去猜测出密码,破解的思路是查看页面代码,会发现如下的JavaScript:
很明显,这段代码是用于判断输入的密码是否正确,而程序仅仅是通过将输入的密码pass和由函数GetPassWord()给出的正确密码进行比较。因此,破解的思路就是设法获取GetPassWord()函数的返回值或者查看函数代码。
继续分析页面源代码,会发现GetPassWord函数是由GetPassWord.asp文件给出的:
尝试下载该文件,发现其中的内容是代码:
十分令人吃惊的代码,因此,所需要的密码就是Stereoic。在输入密码后,便自动进入了下一关。
地址:http://www.csksoft.net/netcompet2/gamearea/hardDays.htm
这关涉及Flash的逆向工程和破解。
页面上Flash逐渐显示着下一关的地址,然而显示到中途却停止了。无法看到下一关地址的后半部分。此时需要通过对swf文件进行逆向工程,分析并提取其中的素材来获得答案。
分析本关页面,当前现实的flash文件是mainStg.swf,将它下载至本地后,使用相关的逆向工程工具分析,这里采用SWFDecompiler。
分析其中第一祯的代码:
发现具有下一关地址信息的flash文件并不是mainStg.swf,而是另一个文件:nextlevel.swf。因此将nextlevel.swf下载到本地,利用SWFDecompiler提取其中的图片资源,下一关的地址便出现了:

地址:http://www.csksoft.net/netcompet2/gamearea/dejvsdewd.htm
这关没有任何技术难度,伪造了IE5.0的404默认显示页面。如果足够细心,就能发现。下一关地址使用白色字体存在于这个"404错误"的页面里,用ctrl+a反色显示就能发现
地址:http://www.csksoft.net/netcompet2/gamearea/eng-sfcd.htm
同样也是没有难度的关,页面中需要填完整的句子是
因为在这句话中,26个英文字母都出现了,所以常用于测试字体显示效果。在windows中的英文字体浏览就使用了这句话。
这关答案就是dog.htm
地址:http://www.csksoft.net/netcompet2/gamearea/dog.htm
这关只需要下载那段录音,使用相关音频处理工具,比如以前的cooledit,将播放速率降低即可。将听到的单词记下来,就是下一关地址
地址:http://www.csksoft.net/netcompet2/gamearea/goodday.html
这一关首先需要下载我编写的Stereoic程序,同时要借助一些调试工具。
通过如下命令行来执行StereoPower:
此时会弹出一个消息框,其中有与下一关相关的字符串:bmbouvsjohstbhbz
同时注意到页面中的文字:
CAESAR实际上就是上面获得的字符串,它实际也是一个ASCII变换处理,同样,利用上面的ReformScript做修改,就能获得下一关地址:
var src_text;
var dest_text;
src_text = "bmbouvsjohstbhbz";
dest_text = "";
for (i=0;i<src_text.length;i++)
{
cur_ascii = src_text.charCodeAt(i);
cur_ascii -= 1;
dest_text+= String.fromCharCode(cur_ascii);
}
msgout(dest_text);
获得的结果是:alanturingrsagay
所以答案就是alanturingrsagay.htm
同时,这一关还需要收集验证码碎片,但很多闯关者都会忽略。
获得验证码碎片的方法是需要修改Stereoic.exe的资源文件,可以用EXESCOPE或者Visual C++的资源编辑器修改。找到其中的图案设置对话框,会发现Visible=FALSE属性的按钮,将它设为可见,保存修改

运行程序,点击那个按钮,从弹出的提示中知道StereoPower.exe的一个调用格式:
StereoPower.exe -p [fileSrc] [fileDest]
不过这次是需要获得程序的进程返回值,可以用Ollydbg或者Visual C++作为调试器调用程序获得,或者自己编写程序。这里给出相关的C代码片断:
STARTUPINFO sinfo;
PROCESS_INFORMATION pinfo;
DWORD Exitcode;
ZeroMemory(&sinfo,sizeof(STARTUPINFO));
sinfo.cb=sizeof(sinfo);
sinfo.dwFlags=STARTF_USESHOWWINDOW;
sinfo.wShowWindow=SW_SHOW;
CreateProcess(NULL,"StereoPower.exe /?",NULL,NULL,FALSE,
NORMAL_PRIORITY_CLASS,NULL,NULL,&sinfo,&pinfo);
WaitForSingleObject(pinfo.hProcess, INFINITE);
GetExitCodeProcess(pinfo.hProcess,&Exitcode);
最终,程序的进程返回值会保存在变量Exitcode中,他就是本关的验证码碎片
新地址:http://www.csksoft.net/netcompet2/gamearea/alanturingrsagay.htm
废弃地址:http://nofrost.nease.net/alanturingrsagay.htm
关于这一关地址的变更以及废弃的关卡解法参考:http://www.csksoft.net/blog/post/48.html
这一关是常识问题,答案是ajax。
地址:http://www.csksoft.net/netcompet2/gamearea/ajax.htm
这关涉及数据分析技巧,下载页面中的那个二进制数据后,首先用16进制编辑器打开,察看数据。这里仍旧采用debug程序
-N bin.dat
-L100
-d100 l100
13D4:0100 73 61 6D 70 6C 65 2E 62-6D 70 00 00 00 00 00 00 sample.bmp......
13D4:0110 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D4:0120 00 00 30 30 30 30 30 30-31 30 30 30 40 30 30 30 ..0000001000@000
13D4:0130 31 36 31 31 37 31 30 00-00 00 00 00 00 00 00 00 1611710.........
13D4:0140 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D4:0150 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D4:0160 00 00 00 00 00 00 6D 61-69 6E 64 61 74 61 2E 6A ......maindata.j
13D4:0170 70 67 00 00 00 00 00 00-00 00 00 00 00 00 00 00 pg..............
13D4:0180 00 00 00 00 00 00 00 00-30 30 30 31 36 31 32 37 ........00016127
13D4:0190 34 36 40 30 30 30 30 30-36 32 34 31 31 00 00 00 46@0000062411...
13D4:01A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D4:01B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D4:01C0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D4:01D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D4:01E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
13D4:01F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
该文件类似于一种打包文件格式。在文件头部给出了该文件中所包含的2个文件,他们的文件名就是上面的红字部分。
接下来的任务就是确定这2个文件在此打包文件中的位置和大小。分析上面的蓝字部分。
可以猜测出,@符号前面的数字为本文件在此打包文件中的起始位置(偏移量),@后面的数字自然就是文件长度。不过需要注意的是这里的数字都是8进制格式的,这一点比较难发现。
对上述数字作进制转化:
0000001000(Oct) -> 512(Dec) -> 0x200
0001611710(Oct) -> 463816(Dec) -> 0x713C8
0001612746(Oct) -> 464358(Dec) -> 0x715E6
0000062411(Oct) -> 25865(Dec) -> 0x6509
接下来把相关的数据单独提取保存就能得到sample.bmp和maindata.jpg这2个文件。
这里给出已经提取出来的版本:http://www.csksoft.net/data/netcompetII_solution/bin.rar
接下来分析sample.bmp。按照图片的提示,同时需要联系第一版本的高手挑战。猜测这个bmp中有隐藏数据。因此需要使用我网站上提供的picmixer工具,将隐写在bmp中的数据提取出来。picmixer的下载地址是:ftp://FTP_Visitor:visitor@ftp.csksoft.net/Public/Products/APP/picmixer.rar
或者在Flash网站中的作品区也能找到下载。
对bmp中隐写数据的提取,能得到文件SerialNum.txt。他的内容为:
打开另外一个文件maindata.jpg,里面就是下一关的地址
地址:http://www.csksoft.net/netcompet2/gamearea/decoder.htm
这一关与之前要求输入密码类似,但察看源代码发现没有任何线索。
实际上他考察了对SQL注入漏洞的了解,用经典的注入代码:
作为用户名和密码,就能十分轻松的过关。
本关验证码碎片:jTv
地址:http://www.csksoft.net/netcompet2/gamearea/package.htm
这一关实际上要求以下面的HTTP header来请求页面:http://www.csksoft.net/netcompet2/gamearea/package.asp
请求的页面会检查这2个字段,如果不满足一些必要的信息,就会拒绝显示内容。解决办法可以利用诸如FlashGet等下载工具中定义这2个字段的数据来访问网页实现。或者可以自己编写http客户端程序。
如果能成功获取请求页面的数据,下一关地址便可得到。
地址:http://www.csksoft.net/netcompet2/gamearea/ffeewwdd.htm
这一关主要涉及程序的调试和逆向工程技巧,主要任务是破解用于合成最终验证码的程序。
该程序需要输入用户名和序列号后才能使用,但是对于闯关者来说不可能知道自己的序列号是什么,因此需要通过相关的技巧,要么获取序列号,要么强行绕过程序的检验。
这里分别介绍这2种办法。
1.获取正确的序列号
当然有足够精力的话可以逆向工程来分析序列号算法,自己写注册机,但是对于本程序,只需要用最简单的内存搜索即可。
先随便输入用户名和序列号,比如:

然后在该程序进程内存中搜索随便输入的序列号,这里是cskcskcsk。采用的工具可以使Ollydbg或者WinHex,下面是WinHex的搜索结果:

会发现在cskcskcsk字符串下方的就是正确的注册码,因为本程序采用的是十分危险的明文校验,所以可以用这样简单的办法获取
此办法操作简单,有效,因此是推荐的做法。不过也可以直接通过修改跳转指令破解注册码验证来实现对程序功能的应用。
这里给出一种破解办法,具体思路省略。
使用Ollydbg分析程序,找到如下部分:
00402CDC . E8 F3980000 call 0040C5D4
上述部分为验证注册码是否正确的片段,在执行call指令前,就能发现堆栈顶部就是正确的注册码,因此可以通过对此处的拦截实现注册机。也可以修改第二处红色部分,即je跳转,将它修改为强制跳转jmp。就实现了绕过注册码检测的功能。
这里给出采用上述破解办法修改的程序:http://www.csksoft.net/data/netcompetII_solution/SerialChk_cracker.rar
最终,就出现了验证码合成的界面:

填入上面收集到的验证码碎片后,就能获取最终验证码。最后只需通过系统验证便宣告过关:

终于写完了这篇“攻略”。说实话,在3年后我自己重新玩这个游戏也被困住了。很多东西我自己也生疏了,难道这几年来我在退步?不管如何,写完这篇文章代表这个游戏已经告一段落。看着那么长的攻略,觉得那些通关的朋友真的很不容易。毕竟要揣摩别人的心思比技术本身要难得多。
对于很多人而言,这个游戏还是有难度的。希望通过这篇文章,不但是介绍过关的思路,我更是希望能让更多人了解这些领域的相关知识和趣味。
最后说明的事如果对文章中有不理解的部分,请自行网上查找,本人不负责解答。如果有任何错误,希望能告诉我,我会立刻修正。


