分类目录归档:不是技术

在采集一些数据

本来打算写个crawler来做的,后来发现没有想象中那么简单,结果很可能是写程序占用的时间比手工采集还要多。

于是采用手工采集。其实效率也不算低,因为对于工具的使用越来越娴熟。

事实上,OA的极大发展,可以相当于智能程序带来的优势。

OA还是很重要的。

前天开始采集数据,前天21K,昨天43K,今天48K,我的目标是1M?

看来还是需要加快速度。

诡异的问题无处不在,对么

上周在本机上写的webapp,在IIS+php跑得很开心,今天想挪到网站空间里面,linux平台的

ImageTTFText

这个牛叉的函数显示不出文字来

查了一下,gd库和freetype都是支持的,字库文件是我自己上传的,还好吧……

不过,用相对路径

./simhei.ttf

,文字怎么也出不来,又用phpinfo确认了一下,gd和freetype都声明是支持的啊……

faint死了,最后还是在phpinfo里把绝对路径找出来再加上字库名,才解决了,大概是个bug么?

内核级Rootkit的加载和调试Zz

【导读】本文向读者介绍加载和调试内核级Rootkit的一些简易方法和工具,其中具体介绍了InstDrv和DebugView这两款小工具的使用。实际上,这些方法只适合于开发期间的简单调试,对于更加复杂的调试工作,我们可以使用SoftIce 或WinDbg之类的调试程序;对于“产品级”的Rootkit的加载,我们需要更加高级的技术,我们将会在后面的文章中详细介绍。

本文将向读者介绍如何将编译好的驱动程序运行起来并察看它的调试语句给出的消息。换句话说,我们要做的是最简单的调试工作。

一、驱动程序的加载和执行

当我们开发Rootkit的时候,经常需要改变其功能,这时经常重复加载、运行、测试、停止和卸载这一系列的动作。加载和运行驱动程序的方法很多,我们这里介绍的是最简单的一种——利用工具软件InstDrv。

InstDrv是一款非常小巧的工具,它的.zip压缩包只有189KB。该工具可以动态地加载、运行、停止和卸载内核级驱动程序。该工具可以从网上下载,为了读者方便使用,该工具可以到论坛

下载

下面我们以上篇《

内核级Rootkit技术入门

》文章中编译好的驱动程序为例子,来说明如何利用InstDrv加载和卸载内核级驱动程序。InstDrv有两种使用模式,一种模式称为交互模式,它是图形用户界面;另一种模式是命令行模式,在命令行中使用。下面我们首先介绍交互模式的使用方法。

 

先将InstDrv压缩包抽取到合适的目录,例如C:\。然后在在 C:\ InstDrv目录中会看到一个绿色的InstDrv图标,双击该图标打开此程序,如下图所示:

图1 InstDrv程序的交互模式

在交互模式下,首先在“Full path of the driver”下面的文字框中输入要加载的驱动程序的绝对路径,对于本例而言,该地址是C:\myrootkit\objchk_wxp_x86\i386\mydriver.sys,然后就可以利用文字框下面的“Install”、“Start”、“Stop”和“Remove”按钮分别进行驱动程序的安装、运行、停止和卸载操作了。

图2  运行我们的驱动程序

当我们单击“Install”和“Start”按钮后,利用Win0bj程序(

论坛下载地址

)可以在\Driver目录中看到我们的驱动程序mydriver,如下图所示:

图3 利用Win0bj程序查看驱动程序(注意加红色下划线部分)

现在开始介绍InstDrv的命令行模式下的使用方法。在该模式下,我们同样需要使用驱动程序的绝对路径。此外,还有几个选项可用,这些选项的作用如下所示:

 /i      该选项用于安装驱动程序

 /u      该选项用于卸载驱动程序

 /s      使用该选项后,不会弹出任何消息,即使出错也如此。

 /?      显式帮助信息

下面用一个例子来说明命令模式的用法:

instdrv /i /s C:\myrootkit\objchk_wxp_x86\i386\mydriver.sys

该命令的作用是安静地安装驱动程序,并运行它。上面的命令行中使用了选项/i ,InstDrv将以“自动运行”的方式来安装该驱动程序,这意味着每次系统重启后该驱动程序将自动运行。这一点与交互模式下的安装截然相反,在交互模式下安装的驱动程序,系统重启后它不会自动运行,相反,我们必须手工运行驱动程序。

对于InstDrv而言,如果直接在命令行中输入该程序名的话,它会切换到交互模式。此外,如果InstDrv以命令行模式运行时遇到错误的话,一般也会切换到交互模式。但如果我们使用了/s选项的话,它就不会这样做了。因此,/s选项的作用是用于安静的安装一个驱动程序。

二、查看调试语句的输出

大多数操作系统都提供了可用作调试之用的函数,例如在Linux下,可加载模块能用printk()函数来打印调试信息,以及Windows内核级日志函数,例如DbgPrint()等。我们可以在某行代码后面加上这些调试语句,例如:

DbgPrint(

消息字符串

);

当我们收到这样的消息时,至少说明某行代码已经执行,此外还能给出更多的描述信息。虽然这种调试方法计较简陋,但却很方便。像SoftIce 或WinDbg之类的调试程序的配置和使用是很麻烦的,尽管它们功能很强大。使用调试语句时,返回码能打印出来,对于出错情况也有较为详细的描述。我们可以利用这些函数给出驱动程序执行期间的重要信息,然后使用适当的调试消息捕获工具记录下这些消息,从而进行简单的调试。

我们这里介绍的是一个常见的调试语句捕获工具:Debug View,到51CTO论坛

下载

我们说过,这和一般程序不同,驱动程序消息不会显示在标准输出设备上,也就是说,我们在屏幕上看不到这则消息。下面我们还是以上篇“内核级Rootkit技术入门”文章中编译好的驱动程序为例子,来说明如何利用Debug View来记录调试消息。我们的驱动程序非常简单,它只是在内核运行时,利用调试语句给出一则消息:“I am a driver and I loaded!”,然后卸载时给出消息“MyUnload called”。下面具体介绍如何利用专门的工具Debug View查看这些调试消息。

DebugView是一款本地调试软件,它能捕获驱动程序的调试输出信息。DebugView不仅能够捕获用户模式的应用程序产生的调试输出,而且还能捕获Windows内核本身或/和内核模式设备驱动程序所产生的调试输出信息。对于后者,我们需要选中“Capture”菜单中的“Capture Kernel”选项,或者在工具栏中单击齿轮形状的“Capture Kernel”按钮(如果该按钮上有一个红色的叉,你就需要再按一下;否则说明已经设定为捕捉内核状态了),或者使用热键Ctrl+K。

DebugView也有命令行模式,但限于篇幅,我们在此只介绍在图形用户界面下的使用方法。Debug View程序无需安装,解压后便可直接使用。首先打开该程序,按照上面介绍的捕获系统内核驱动程序的方法设置,然后利用InstDrv安装并启动我们的驱动程序,这时我们就能捕获驱动程序发出的消息了,如下图所示:

图4  DebugView 从内核模式驱动程序捕获的输出信息

下面是工作中经常用到的功能,我们在此加以介绍:

插入注释

通过选择“Edit”菜单的“Append Comment”菜单项,我们就能在当前输出窗口中键入注释并回车,从而向输出中添加注释。

清屏

利用工具栏上的“clear”按钮能够清除当前程序产生的输出消息。

输出窗口内容的保存

我们要想将DebugView窗口中的内容保存成一个扩展名为.log的文件,可以选中 “File”菜单中的“Save”或“Save As”菜单项,或者使用组合键Ctrl+S。此外,我们开可以利用“Edit”中的“Copy”菜单项,或组合键Ctrl+C将选中的内容复制到剪贴板,然后保存在适当的地方。

将消息记录到文件中

为了将DebugView程序捕获的记录输出成为像我们在输出窗口看到的样子的文件,我们要使用“Files”菜单中的“Log to File”或“Log to File As”菜单项,或者工具栏中的“Log to File”按钮,或者使用组合键Ctrl+O也可以。然后设置文件的名称和最大尺寸等。如果选择了“wrap”选项,当文件尺寸达到其最大值时,DebugView将回卷到文件起始处。

如果选择了“Create New Log Every Day”项,DebugView就不再限制日志文件的尺寸,但它会为每天的日志新建一个文件,该文件的名称是你规定的文件名加上当前日期。

当记录活动仍在进行的时候,工具栏“Log to File”按钮中的箭头是绿色的,要停止记录,可以单击该按钮或者选择 “File” 菜单中的“Log to File”菜单项即可。如果记录文件达到最大尺寸,记录活动就会停下来,工具栏“log file”按钮中的箭头变成红色的。

三、小结

本文向读者介绍加载和调试内核级Rootkit的一些简易方法和工具,其中具体介绍了InstDrv和DebugView这两款小工具的使用。实际上,这些方法只适合于开发期间的简单调试,对于更加复杂的调试工作,我们可以使用SoftIce 或WinDbg之类的调试程序;对于“产品级”的Rootkit的加载,我们需要更加高级的技术,我们将在会面的文章中详细介绍。

内核级Rootkit技术入门Zz

【导读】本文介绍了Windows下的内核级Rootkit的最基础性的东西,以及利用驱动程序将代码导入到内核的方法。虽然我们还没有涉及到真正的Rootkit,但这些内容是我们掌握Rootkit的必经之路,就像我们要建一座6层的楼房,却不能撇开基础和低层而直接盖第六层一样!更多的内容,会在后续的文章中陆续介绍。

Rootkit是一种奇特的程序,它具有隐身功能:无论静止时(作为文件存在),还是活动时,(作为进程存在),都不会被察觉。换句话说,这种程序可能一直存在于我们的计算机中,但我们却浑然不知,这一功能正是许多人梦寐以求的——不论是计算机黑客,还是计算机取证人员。黑客可以在入侵后置入Rootkit,秘密地窥探敏感信息,或等待时机,伺机而动;取证人员也可以利用Rootkit实时监控嫌疑人员的不法行为,它不仅能搜集证据,还有利于及时采取行动。而本文的目的,就是同读者一起踏上Windows内核级Rootkit之旅!

一、背景知识

我们通常所说的智能机器,大至超级计算机,中到个人PC,小至智能手机,通常都有两部分组成:硬件和软件。并且,设备的智能是通过软件来实现的。所有软件中,有一种是必不可少的,那就是操作系统。操作系统可以简单理解为一组高度复用的核心程序,一方面,它要管理低层的硬件设备,另一方面,为上层其它程序提供一个良好的运行环境。真是同人不同命,同为软件,操作系统却享有至高无上的特权:它不仅管理硬件,而且其他所有软件也都受制于它。

因为在应用程序和硬件之间隔着操作系统,所以应用程序不能直接访问硬件,而是通过调用操作系统提供的接口来使用硬件。也就是说,对应用程序而言,硬件是不可见的。当然,凡事是没有绝对的,应用程序绕过操作系统来直接访问硬件也不是不可能的,但这样做会付出高昂的代价。设想一个软件开发商在开发一款功能丰富的软件,功能本身就够他头痛得了,现在他还得操心某个数据在某个磁道的某个簇上,某个字符在某品牌显示器上的颜色的二进制代码等等繁琐的事情,不用说财力和物力,单说开发周期就是无法容忍的。所以,现在的应用程序都是使用操作系统提供的简单明了的服务来访问系统的,因为毕竟没有谁愿意自讨苦吃。

二、内核的主要功能

从上文中我们已经了解,内核在系统中处于核心枢纽的地位,下面我们具体介绍内核中与Rootkit紧密相关的几个主要功能,更重要的是这些功能对Rootkit的意义所在:

进程管理

。进程可以简单理解为运行中的程序,它需要占用内存、CPU时间等系统资源。现在的操作系统大多支持多用户多任务,也就是说系统要并行运行多个程序。为此,内核不仅要有专门代码来负责为进程或线程分配CPU时间,另一方面还要开辟一段内存区域存放用来记录这些进程详细情况的数据结构。内核是怎么知道系统中有多少进程、各进程的状态等信息的?就是通过这些数据结构,换句话说它们就是内核感知进程存在的依据。因此,只要修改这些数据结构,就能达到隐藏进程的目的。

文件访问。文件系统是操作系统提供的最为重要的功能之一。内核中的驱动程序把设备的柱面、扇区等原始结构抽象成为更加易用的文件系统,并提供一个一致的接口供上层程序调用。也就是说,这部分代码完全控制着对硬盘的访问,通过修改内核的这部分代码,攻击者能够隐藏文件和目录。

安全控制

。对大部分操作系统来说,因为系统中同时存在多个进程,为了避免各进程之间发生冲突,内核必须对各进程实施有效的隔离措施。比如,在MS-Windows系统中,每个进程都被强制规定了具体的权限和单独的内存范围。因此,对攻击者而言,只要对内核中负责安全事务的代码稍事修改,整个安全机制就会全线崩溃。

内存管理

。现在的硬件平台(比如英特尔的奔腾系列处理器)的内存管理机制已经复杂到可以将一个内存地址转换成多个物理地址的地步。举例来说,进程A按照地址0x0030030读取内存,它得到值的是“飞机”;然而,进程B也是按照同样的地址0x0030030来读取内存,但它取得的值却是“大炮”。像上面这样,同一个地址指向截然不同的两个物理内存位置,并且每个位置存放不同的数据这种现象并不足以为怪——只不过是两个进程对虚拟地址到物理地址进行了不同的映射而已。如果这一点利用好了,我们可以让Rootkit躲避调试程序和取证软件的追踪。

上面介绍了内核的主要功能,以及它们对Rootkit的重大意义。说到这里,我们就要切入正题了,即:只要我们颠覆(即修改)了操作系统的核心服务(即内核),那么整个系统包括各种应用就完全处于我们的掌控之下了。要想颠覆内核,前提条件是能把我们的代码导入内核。具体请见下文。

三、将代码导入内核的方法

所有应用程序都是运行在用户模式下的,而操作系统是运行在内核模式下的,所以应用程序根本没有机会来修改内核程序。要想颠覆内核,前提是设法让我们的代码也运行在内核模式下,即将我们的代码导入内核。

设想一下当我们的代码通过驱动程序进入内核后的情形:我们的代码一旦在内核运行,就能访问内核的所有特权内存空间和系统进程——有了这样的内核级访问特权,我们就能任意修改系统中的任何代码和数据了!

将代码导入内核的方法很多,但我们要介绍的是利用设备驱动程序将代码导入内核的方式。内核驱动程序有多种叫法,有时候又称为内核驱动程序,或者可加载模块。我们之所以利用设备驱动程序将代码导入到内核,主要考虑到两点:

1.简单性。能够让我们的代码运行在内核模式之的方法有多种,例如把我们的代码做成设备驱动程序、设法修改正在内存运行的内核、覆盖硬盘中的内核映像等等。其中,利用设备驱动程序是最为简单的一种。

2.适用性。现在,绝大多数的操作系统都允许第三方的硬件厂商加载为其硬件产品制作的内核扩展,从而使得操作系统能够支持它们的硬件产品。这的确是一个双赢之举,只有这样,操作系统开发商才能不断巩固和扩大其用户群。因此,各个操作系统开发商不仅提供该系统下的开发设备驱动程序的详尽帮助文档,而且还提供了相应的开发工具包。

虽然我们已经找到将我们的代码导入到内核模式的路径,但还有一个问题需要回答:除了与硬件打交道的代码外,其它代码是否也能写进设备驱动程序?答案是肯定的。尽管这里的“设备”一词容易误导我们,实际上任何代码都可以写成设备驱动程序。

迄今为止,我们已经回答了利用设备驱动程序来打造内核级别的Rootkit可行性问题,也就是说,内核级Rootkit大门已经打开了一扇,为了打开另一扇,我们要解决的是“how to”的问题。并且,我们第一个必须解决的“how to”问题就是如何编写Windows设备驱动程序。

四、Windows设备驱动程序

下面我们介绍如何在Windows XP平台上开发一个简单的设备驱动程序。在此过程中,我们要用到设备驱动程序开发包DDK。需要注意的是,微软为不同的Windows版本提供了不同的DDK。就目前来说,我们可以使用Windows 2003 DDK,因为该版本能够支持Windows 2000、Windows XP和Windows 2003等三个平台下的设备驱动程序的开发。

1. 驱动程序源文件

首先在C盘根目录下新建一个目录,本例为C:\myrootkit,此后向相应文件都存放在该目录之下。然后可以在VC++下建立一个C源文件,让其内容如下所示:

//一个简单的驱动程序实例

#include

ntddk.h

NTSTATUS DriverEntry ( IN  PDRIVER_OBJECT theDriverObject,

IN  PUNICODE_STRING theRegistryPath )

{

DbgPrint(

I am a driver!

);

return STATUS_SUCCESS;

}

之后,将其保存在我们的C:\myrootkit目录下,并且该文件命名为mydriver.c。下面对上面的代码作简要的解释:

DriverEntry是该驱动程序的入口点,即当该驱动程序启动时,操作系统会首先调用该函数。它相当于一般C/C++程序中的main或Winmain函数。另外,我们看到DriverEntry的两个参数中都含有一个关键词IN,说明这两个参数只能用于输入。第一个参数指向应被初始化的当前驱动程序的驱动对象;第二个参数是设备服务键的键名。

该驱动程序实在太简单了,它只是在内核运行时,利用调试语句给出一则消息:“I am a driver!”。不过,和一般程序不同,该消息不会显示在标准输出设备上,也就是说,我们在屏幕上看不到这则消失,关于调试输出的处理我们会在后文中加以详细介绍。

有一点需要指出,那就是上面的驱动程序没有设置卸载例程。尽管卸载例程不是必需的,但有时它却非常有用:启动驱动程序时,系统会将参数theDriverObject传递给该驱动程序的主函数,这个参数指向的数据结构含有许多函数指针,其中一个指针称为“unload routine”。如果我们设置该指针,就能从内存中卸载驱动程序;如果不设置该指针的话,除非重新启动机器,否则无法将载入内存的驱动程序卸载掉。同时,驱动程序在开发过程中,会不断添加或改变功能,所以要经常装载以及卸载它们。为了避免每次测试新版本的驱动程序时都必须重启系统,我们应当设置“unload routine”指针。事实上,设置该指针并不是什么难事:先建立一个卸载例程,就可以设置该卸载指针了。

现在以前面的驱动程序为例,介绍如何为其添加卸载例程:

//一个简单的驱动程序实例

#include

ntddk.h

// 这里是我们的卸载函数

VOID MyUnload( IN PDRIVER_OBJECT DriverObject )

{

DbgPrint(

MyUnload called\n

);

}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT theDriverObject,

IN PUNICODE_STRING theRegistryPath)

{

DbgPrint(

I am a driver and I loaded!

);

// 初始化DriverObject对象中指向卸载函数的指针

theDriverObject-

DriverUnload  =  MyUnload;

return STATUS_SUCCESS;

}

这样一来,我们用重启系统就能方便地装载和卸载驱动程序了。

2. SOURCES文件

要想构建设备驱动程序,仅有驱动程序源文件还是不够的,我们还需另外两个文件:SOURCES和MAKEFILE文件。

我们先来介绍SOURCES文件,此文件的名称必须使用大写字母,并且不带任何扩展名,它的内容应当包含:

TARGETNAME=MYDRIVER

TARGETPATH=OBJ

TARGETTYPE=DRIVER

SOURCES=mydriver.c

其中,第一个变量TARGETNAME的作用是为我们的驱动程序命名。在本例中,我们的设备驱动程序在编译后被命名为MYDRIVER。需要注意的是,变量TARGETNAME指定的名称会被嵌入到二进制代码之中,所以在写Rootkit时,千万不要用该变量为其指定容易被人猜中的名称。即使把二进制文件本身改名,但其内部的名字是无法改变的。最好用一些迷惑性较强的名称来为这些Rootkit命名,方法是根据系统中已有的驱动程序名,在此基础上少做手脚,一个上佳的Rootkit名便诞生了。

第二个变量TARGETPATH的作用是指定驱动程序编译后的存放位置,该变量通常设为OBJ。一般来说,驱动程序文件被放在目录objchk_xxx/i386下面,例如本文驱动程序,作者在Windows XP下构建后的文件将位于C:\myrootkit\objchk_wxp_x86\i386。

第三个变量TARGETTYPE用来指定要编译的文件类型。对于设备驱动程序,该变量设为DRIVER。

第四个变量SOURCES用来指定源文件。该变量可以指定多个源文件,这时每行一个文件,并且除最后一行外,在每行末尾都要放上一个反斜杠,如下例所示:

SOURCES=  myfile1.c \

myfile2.c \

myfile3.c    /*注意,最后一行没有反斜杠*/

除了上面几个必选的变量外,还有一些可选变量。变量INCLUDES便是可选变量之一,它用以规定寻找包含文件的目录。现举例说明:

NCLUDES = c:\my_includes \

..\..\inc \

c:\other_includes

如果需要链接库的话,我们还需要变量TARGETLIBS。例如,有时我们要用到NDIS库,这时在SOURCES文件就应当包含如下一行:

TARGETLIBS=$(BASEDIR)\lib\w2k\i386\ndis.lib

或者:

TARGETLIBS=$(DDK_LIB_PATH)\ndis.lib

当然,ndis.lib在你自己系统上的位置可能有所不同,你可以根据实际情况将上面的路径加以调整。其中,变量$(BASEDIR)规定DDK的安装目录$(DDK_LIB_PATH);变量$(DDK_LIB_PATH)则规定了库文件的默认安装位置。

3. MAKEFILE文件

和SOURCES文件一样,MAKEFILE文件的名称也必须使用大写字母,同时也不能带任何扩展名,它的内容一般为:

!INCLUDE $(NTMAKEENV)\makefile.def

注意的是,要在Windows中建立不带扩展名的文件,可以利用dos命令行下的EDIT命令或copy con命令。此外,SOURCES和MAKEFILE文件必须与驱动程序的源代码位于同一个目录下。

4. 构建过程

准备好SOURCES、MAKEFILE以及C源代码文件后,我们就可以构建驱动程序了。在此之前,我们先说明一下DDK的两种构建环境:checked和free构建环境。其中前者一般在开发过程中使用,为了便于调试,它会在生成的驱动程序中添加一些调试信息,这会使得驱动程序体积较大。开发测试完成后,当我们需要发布产品级的驱动程序时,就可以利用free构建环境来生成驱动程序。

从DDK中单击checked-build environment,打开如图1所示的命令窗口:

图1

然后,利用cd命令将工作目录切换到C:\myrootkit目录下面:

cd C:\myrootkit

接着在命令提示符下输入命令build开始构建,如图2所示:

图2

如果没有收到任何错误消息,而是类似下图所示的提示,则说明我们的第一个设备驱动程序已经大功告成了!

图3

五、小结

到目前为止,本文介绍了Windows下的内核级Rootkit的最基础性的东西,以及利用驱动程序将代码导入到内核的方法。虽然我们还没有涉及到真正的Rootkit,但这些内容是我们掌握Rootkit的必经之路,就像我们要建一座6层的楼房,却不能撇开基础和低层而直接盖第六层一样!更多的内容,会在后续的文章中陆续介绍。

我有多少个写网络日志的地方?

昨天Suki问我这个问题,我想了一下。很多很多。

某年春节,chinaren开始做在线日记,当时写过两篇,由于操作不方便,转到Holedox的BBS上去了。

那么Holedox的polo版也算一个吧。

groups,开始的时候是看到Mandy在用,于是自己也弄了一个,没什么人看的,当时是大四左右吧,把毕业的照片搞点上去,然后polo9.yeah.net重定向,前几天把这个改了,估计以后也不在上面写了。

再下来就是04年装google工具条之后,发现blogger能写不能看,于是在上面写,

http://polo9.blogspot.com

,就好像写完纸条之后塞到一个瓶子里一样。貌似现在blogspot又不能访问了。

同时也在blogbus,就是现在这里写。

http://zhengrenchi.blogbus.com

,目前来说,就这里写得最多了。

msn推出spaces之后,05年我也开通了一个,但是由于msn加了好多同事,于是屏蔽很多,变成一个半开放的spaces。

http://simonzh.spaces.live.com

今年年初用另一个msn account,开了一个全封闭的spaces:

http://no-trump.spaces.live.com

,目的就是只写不看,两个月有一篇就偷笑了。

再下来就是在bokee上设了一个放无聊时候写小游戏的:

http://ffshow.bokee.com

跟软件ffshow毫无关系,本来就是想用flash啥啥的。不过bokee的blog做得超烂,放几个swf在上面搞得暴慢无比。

能想起来的就只有这些了。

开始把一些代码改为AJAX

其实AJAX一点也不难,不过问题是,这种模式会涉及一个设计上的问题。

就好像你打算用flash做全站一样,AJAX如果在一开始没有设计良好,以后的再改动会是初次开发60%的工作量。

把pandora写了70%了

http://zhengrenchi.blogbus.com/files/1162451682.swf

代码一共花了不到4个小时,但自己玩了加起来都有5个小时了。

方块类游戏写起来是很简单的,判断也容易,不过美工要做好才行。

规则就是,

四个或以上颜色相同的点击可以消去。

点右边的三色炸弹可以消掉所有同颜色的,但要扣分。

升级后会出现更多颜色,也有机会看到消除行和消除列的炸弹。

(这些炸弹其实也不是什么好事……)

每次操作之后底部增加一行(按addline除外)

分形的云彩

分形的云彩其实很多程序都做过了,我只是在Flash里面实现了一下。上周花了一天弄了一下Flash里面关于BitmapData的方法。

今天重又试了一下,还好,很顺利的作出来了。

突然又想做一个滤镜,把alpha做一个类似于反正切曲线的转换。那些变换矩阵只能填充固定数字,不能使用变量,因此只能是线性变换,于是反正切的变换没做出来。

于是要求降低一点,做一条斜率稍大的直线,然后在0和255的地方压平了。

效果还好,然后把一个太阳加了上去,看上去怪怪的……

明天做云层的移动,还有变形。

云层的移动需要考虑几点:一个是风向,左向右向前向后向,估计要用到仿射变换的滤镜了。

变形……这个一直没想好该怎么变。

这一年来的流氓软件很泛滥

那些按照点击数来评估网站价值的原则应该被抛弃了。

强制性的点击从来都不是真实价值的体现,一如Tencent,根本不能称为一流门户。因为其首页只能在那小小的窗口里面强制性地露一脸。

快点把这些造流氓、垃圾的无耻者送进监狱吧。这世界太恐怖了。