2007年8月7日
#
2007年7月2日
#
using System;
using System.Runtime.InteropServices;
namespace MouseMoving
{
class Mouse
{
struct NativePOINT {
public int x;
public int y;
}
[Flags]
enum MouseEventFlag : uint
{
Move = 0x0001,
LeftDown = 0x0002,
LeftUp = 0x0004,
RightDown = 0x0008,
RightUp = 0x0010,
MiddleDown = 0x0020,
MiddleUp = 0x0040,
XDown = 0x0080,
XUp = 0x0100,
Wheel = 0x0800,
VirtualDesk = 0x4000,
Absolute = 0x8000
}
struct NativeRECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport("user32.dll")]
private static extern bool SetCursorPos(int X, int Y);
[DllImport("user32.dll")]
private static extern void mouse_event(MouseEventFlag flags, int dx, int dy, uint data, UIntPtr extraInfo);
[DllImport("user32.dll")]
private static extern bool GetCursorPos(out NativePOINT Point);
[DllImport("user32.dll")]
private static extern IntPtr FindWindow(string strClass, string strWindow);
[DllImport("user32.dll")]
private static extern IntPtr FindWindowEx(HandleRef hwndParent, int hwndChildAfter, string strClass, string strWindow);
[DllImport("user32.dll")]
private static extern bool GetWindowRect(HandleRef hwnd, out NativeRECT rect);
[DllImport("user32.dll")]
private static extern bool ClipCursor( ref NativeRECT rect);
public int X
{
get
{
NativePOINT PrivateMousePoint;
if (GetCursorPos(out PrivateMousePoint) != true)
{
PrivateMousePoint.x = -1;
}
return PrivateMousePoint.x;
}
set
{
if (value < 0)
return;
SetCursorPos(value, this.Y);
}
}
public int Y
{
get
{
NativePOINT PrivateMousePoint;
if (GetCursorPos(out PrivateMousePoint) != true)
{
PrivateMousePoint.y = -1;
}
return PrivateMousePoint.y;
}
set
{
if (value < 0)
return;
SetCursorPos(this.X, value);
}
}
public void Click()
{
mouse_event(MouseEventFlag.LeftDown, this.X, this.Y, 0, UIntPtr.Zero);
mouse_event(MouseEventFlag.LeftUp, this.X, this.Y, 0, UIntPtr.Zero);
}
public void DoubleClick()
{
Click();
Click();
}
public void RightClick()
{
mouse_event(MouseEventFlag.RightDown, this.X, this.Y, 0, UIntPtr.Zero);
mouse_event(MouseEventFlag.RightUp, this.X, this.Y, 0, UIntPtr.Zero);
}
public void MoveToFormCenter(string formCaption)
{
NativeRECT rect;
IntPtr hwnd = FindWindow(null, formCaption);
if (hwnd == IntPtr.Zero)
{
throw new Exception("Form " + formCaption + " not found!");
}
GetWindowRect(new HandleRef(this, hwnd), out rect);
X = (rect.left + rect.right) / 2;
Y = (rect.top + rect.bottom) / 2;
}
public void MoveToFormTitle(string formCaption)
{
NativeRECT rect;
IntPtr hwnd = FindWindow(null, formCaption);
if (hwnd == IntPtr.Zero)
{
throw new Exception("Form " + formCaption + " not found!");
}
GetWindowRect(new HandleRef(this, hwnd), out rect);
X = (rect.left + rect.right) / 2;
Y = rect.top + 10;
}
public void LockMouse()
{
NativeRECT rect;
rect.left = X;
rect.right = X + 1;
rect.top = Y;
rect.bottom = Y + 1;
ClipCursor(ref rect);
}
public void UnLockMouse()
{
NativeRECT rect;
rect.left = 0;
rect.right = int.MaxValue;
rect.top = 0;
rect.bottom = int.MaxValue;
ClipCursor(ref rect);
}
}
}
//说是写,还不如说是翻译更合适。给比我还懒的人用。里面有个FindWindowEx没用,不过扩充的时候也许你会用到,这里就暂时保留了。
2007年5月31日
#
从早晨上班到现在,收到14封email(与我无关的已经排除在外),发出9封email,开会1次
不过这不是最疯狂的情况,曾经有一次早晨一来就收到30多封email
狂想:如果收发email的数量扩大10倍,我的薪水就能扩大10倍了。
2007年5月28日
#
朋友的机器总是中autorun.inf病毒,这种病毒没什么技术含量。就是把自己写在autorun.inf里,然后写个隐藏文件在根目录或recycled目录下。
我的机器有norton,并且关闭了自动运行功能,因此这个对我无效。
不过对于绝大部分人来说,这类病毒是有效的。
对于不想装,或者不能装杀毒软件的人来说,有一个很简单的办法。
1.新建一个guest用户
2.对系统盘建立一个新的磁盘配额项,对这个guest用户设置配额为1k
平时自己用,使用普通用户。需要用移动存储设备的时候,用这个guest用户进去操作。
这样根本不需要管哪个文件有毒,尽管运行就是。反正,你的系统盘不会有任何损伤。
当然,你也可以对所有的盘设置配额,不过那样就不方便拷贝文件了。至少也应该留一个分区出来。
既然他们写出没有技术含量的程序糊弄我们,我们就这样,用同样没有技术含量的东西糊弄他们。
如果你足够流氓的话,还可以把记事本拷贝到u盘里去,改成和病毒一样的名字,几乎所有的垃圾病毒都回认为记事本就是它自己。(貌似这个还是有一点技术含量的,大部分操作者是不知道怎样显示并且删除系统文件的。)
2007年4月30日
#
2007年4月21日
#
今天的培训课很无聊,就在课上玩了这个keygenme,下载地址为:http://www.crackmes.de/users/hexic/crack_me/download
软件很小,怎么找断点就不说了,用眼睛直接瞪也能瞪出来。
下面给出关键点和注册机,注册机在vs2005下编译通过
lw549
RX-00000185-TZ
用户名转换为00000185
00403231 31 41 47 34 54 33 43 58 38 5A 46 37 1AG4T3CX8ZF7
00403241 52 39 35 51 R95Q
密码表
关键call
0040116F |. E8 EE000000 CALL KeyGenMe.00401262
关键函数
00401262 /$ 55 PUSH EBP
00401263 |. 8BEC MOV EBP,ESP
00401265 |. 60 PUSHAD
00401266 |. 33C0 XOR EAX,EAX
00401268 |. 33D2 XOR EDX,EDX
0040126A |. B9 10000000 MOV ECX,10
0040126F |. A0 54324000 MOV AL,BYTE PTR DS:[403254] ; 第一个字符
00401274 |. F6F1 DIV CL ; 第一个字符整除16
00401276 |. 8AD4 MOV DL,AH ; 余数给dl
00401278 |. 8A82 35324000 MOV AL,BYTE PTR DS:[EDX+403235] ; 密码表的第余数个数给al, ah不变仍然是余数
0040127E |. 8A15 A4324000 MOV DL,BYTE PTR DS:[4032A4] ; 密码第一位与al相等
00401284 |. 38D0 CMP AL,DL
00401286 |. 0F85 E8000000 JNZ KeyGenMe.00401374
0040128C |. 33C0 XOR EAX,EAX
0040128E |. A0 55324000 MOV AL,BYTE PTR DS:[403255] ; 第二个字符
00401293 |. F6F1 DIV CL ; 与密码的第一个字符整除
00401295 |. 8AD4 MOV DL,AH ; 余数给dl
00401297 |. 8A82 35324000 MOV AL,BYTE PTR DS:[EDX+403235] ; 密码表的第余数个数给al, ah不变仍然是余数
0040129D |. 8A15 A5324000 MOV DL,BYTE PTR DS:[4032A5] ; 与密码第二个字符一致
004012A3 |. 38D0 CMP AL,DL
004012A5 |. 0F85 C9000000 JNZ KeyGenMe.00401374
004012AB |. A0 A6324000 MOV AL,BYTE PTR DS:[4032A6]
004012B0 |. 2C 2D SUB AL,2D ; 密码的第三个字符必须为2d,既为-
004012B2 |. 0F85 BC000000 JNZ KeyGenMe.00401374
004012B8 |. 33D2 XOR EDX,EDX
004012BA |. 33C0 XOR EAX,EAX
004012BC |> 33C9 /XOR ECX,ECX
004012BE |. 8A8A 54324000 |MOV CL,BYTE PTR DS:[EDX+403254] ; 循环用户名,逐个相加
004012C4 |. 0AC9 |OR CL,CL
004012C6 |. 74 05 |JE SHORT KeyGenMe.004012CD
004012C8 |. 03C1 |ADD EAX,ECX
004012CA |. 42 |INC EDX
004012CB |.^ EB EF \JMP SHORT KeyGenMe.004012BC
004012CD |> 50 PUSH EAX ; /<%.8X>
004012CE |. 68 46324000 PUSH KeyGenMe.00403246 ; |Format = "%.8X"
004012D3 |. 68 C0324000 PUSH KeyGenMe.004032C0 ; |s = KeyGenMe.004032C0
004012D8 |. E8 E1000000 CALL <JMP.&user32.wsprintfA> ; \wsprintfA 这个不需要解释
004012DD |. 83C4 0C ADD ESP,0C
004012E0 |. 33C9 XOR ECX,ECX
004012E2 |. EB 11 JMP SHORT KeyGenMe.004012F5
004012E4 |> 8A81 C0324000 /MOV AL,BYTE PTR DS:[ECX+4032C0] ; 用户名求和转化成的字符串
004012EA |. 8A91 A7324000 |MOV DL,BYTE PTR DS:[ECX+4032A7] ; 密码
004012F0 |. 38D0 |CMP AL,DL
004012F2 |. 75 06 |JNZ SHORT KeyGenMe.004012FA
004012F4 |. 41 |INC ECX
004012F5 |> 83F9 08 CMP ECX,8 ; 比较8个字符,用户名转换以后就是8个字符
004012F8 |.^ 75 EA \JNZ SHORT KeyGenMe.004012E4
004012FA |> 83F9 08 CMP ECX,8
004012FD |. 75 75 JNZ SHORT KeyGenMe.00401374
004012FF |. 33C0 XOR EAX,EAX
00401301 |. A0 AF324000 MOV AL,BYTE PTR DS:[4032AF]
00401306 |. 2C 2D SUB AL,2D ; 【004032AF】为0x2D,也就是密码的第12个字符为-
00401308 |. 75 6A JNZ SHORT KeyGenMe.00401374
0040130A |. 33C0 XOR EAX,EAX
0040130C |. B9 10000000 MOV ECX,10
00401311 |. 8B1D B8324000 MOV EBX,DWORD PTR DS:[4032B8] ; 用户名的长度
00401317 |. 8A83 52324000 MOV AL,BYTE PTR DS:[EBX+403252] ; 用户名倒数第二个字符
0040131D |. F6F1 DIV CL ; 第四个字符整除0x10,即16
0040131F |. 8AD4 MOV DL,AH ; 余数给dl
00401321 |. 8A82 35324000 MOV AL,BYTE PTR DS:[EDX+403235] ; 密码表第余数个字符
00401327 |. 8A15 B0324000 MOV DL,BYTE PTR DS:[4032B0] ; 与【004032B0】要一致,这个值是密码的一部分
0040132D |. 38D0 CMP AL,DL
0040132F |. 75 43 JNZ SHORT KeyGenMe.00401374
00401331 |. 33C0 XOR EAX,EAX
00401333 |. 8A83 53324000 MOV AL,BYTE PTR DS:[EBX+403253] ; 用户名最后一个字符
00401339 |. F6F1 DIV CL ; 与上面的操作一致
0040133B |. 8AD4 MOV DL,AH
0040133D |. 8A82 35324000 MOV AL,BYTE PTR DS:[EDX+403235]
00401343 |. 8A15 B1324000 MOV DL,BYTE PTR DS:[4032B1] ; 与【004032B1】要一致,这个值是密码的一部分
00401349 |. 38D0 CMP AL,DL
0040134B |. 75 27 JNZ SHORT KeyGenMe.00401374
0040134D |. 68 30100000 PUSH 1030 ; /Style = MB_OK|MB_ICONEXCLAMATION|MB_SYSTEMMODAL
00401352 |. 68 59304000 PUSH KeyGenMe.00403059 ; |Title = "WoW, Very Good Job."
00401357 |. 68 2D304000 PUSH KeyGenMe.0040302D ; |Text = "Well Done Cracker !!!. Now, Code a KeyGen.?"
0040135C |. FF75 08 PUSH DWORD PTR SS:[EBP+8] ; |hOwner
0040135F |. E8 72000000 CALL <JMP.&user32.MessageBoxA> ; \MessageBoxA
00401364 |. 66:C705 C9324>MOV WORD PTR DS:[4032C9],0FFFF
0040136D |. C605 CB324000>MOV BYTE PTR DS:[4032CB],1
00401374 |> 61 POPAD
00401375 |. C9 LEAVE
00401376 \. C2 0400 RETN 4
// KGKeyGenMe_1_cLoNeTrOnE.cpp : 定义控制台应用程序的入口点。
#include "stdafx.h"
#include "string.h"
int _tmain(int argc, _TCHAR* argv[])
{
char UserName[255] = {0};
char table[] = {"1AG4T3CX8ZF7R95Q"};
int UserNameSum;
unsigned UserNameLength;
char c1,c2,c3,c4;
int LoopCount;
do
{
printf("input UserName, quit to exit:");
scanf("%s",&UserName);
UserNameLength = strlen(UserName);
if (strcmp(UserName, "quit") == 0) return 1;
UserNameSum = 0;
for(int i = 0; i < UserNameLength; i++)
UserNameSum += UserName[i];
c1 = table[UserName[0] % 16];
c2 = table[UserName[1] % 16];
c3 = table[UserName[UserNameLength-2] % 16];
c4 = table[UserName[UserNameLength-1] % 16];
printf("%c%c-%0.8X-%c%c\n", c1, c2, UserNameSum , c3, c4);
}
while (true);
}
2007年4月16日
#
昨天上课,提到了string的==和Equals的问题,当时没有实验条件,讨论也就停留在表面层次。今天调试一下,得到如下结果。
private void Button7_Click(object sender, EventArgs e)
{
string a;
string b;
a = "hello";
b = "hello";
//第一步,测试 a==b
/*
a = "hello";
00000033 8B 05 DC 30 3E 02 mov eax,dword ptr ds:[023E30DCh]
00000039 8B F8 mov edi,eax
b = "hello";
0000003b 8B 05 DC 30 3E 02 mov eax,dword ptr ds:[023E30DCh]
00000041 8B D8 mov ebx,eax
* 这里编译器做了优化,无论比较值还是比较地址,都是相等的,因此,此测试没有什么意义
*/
if (a == b)
{
MessageBox.Show("a==b");
}
else
{
MessageBox.Show("a!=b");
}
//第二步,绕开编译器的优化,测试 a==b
string c = "hello world";
/*
00000089 8B FE mov edi,esi
0000008b 6A 05 push 5
0000008d 8B 4D B4 mov ecx,dword ptr [ebp-4Ch]
00000090 33 D2 xor edx,edx
00000092 39 09 cmp dword ptr [ecx],ecx
00000094 E8 AB F7 FB 77 call 77FBF844 //SubString
00000099 89 45 AC mov dword ptr [ebp-54h],eax
0000009c 8B 55 AC mov edx,dword ptr [ebp-54h]
0000009f 8B CF mov ecx,edi
000000a1 E8 22 2D FF 77 call 77FF2DC8 //比较过程,下面有详细描述
000000a6 8B F8 mov edi,eax
000000a8 85 FF test edi,edi
000000aa 0F 94 C0 sete al
000000ad 0F B6 C0 movzx eax,al
000000b0 8B D8 mov ebx,eax
000000b2 85 DB test ebx,ebx
000000b4 75 11 jne 000000C7
*
Call Stack
* > mscorlib.dll!string.EqualsHelper(string strA, string strB = "hello") + 0x20 bytes
mscorlib.dll!string.Equals(string a, string b) + 0x1a bytes
mscorlib.dll!string.operator ==(string a, string b) + 0x5 bytes
从这里可以看到 “==”已经被override了
这里可以看到,是根据字符串内容比较的,不是比较地址
0000007d 8B 02 mov eax,dword ptr [edx]
0000007f 3B 01 cmp eax,dword ptr [ecx]
00000081 75 0D jne 00000090
*/
if (a == c.Substring(0, 5))
{
MessageBox.Show("a == c.Substring(0, 5)");
}
else
{
MessageBox.Show("a != c.Substring(0, 5)");
}
}
private void button8_Click(object sender, EventArgs e)
{
string a = "hello";
string b = null;
/*
* Call Stack
> mscorlib.dll!string.EqualsHelper(string strA = "hello", string strB = "hello")
mscorlib.dll!string.Equals(string value) + 0x10 bytes
*/
if (a.Equals("hello"))
{
MessageBox.Show("a.Equals(\"hello\")");
}
else
{
MessageBox.Show("not a.Equals(\"hello\")");
}
if (a.Equals(null))
{
MessageBox.Show("a.Equals(null)");
}
else
{
MessageBox.Show("not a.Equals(null)");
}
if (a.Equals(b))//Get an exception in 2005, not equal in Orcas
{
MessageBox.Show("a.Equals(b)");
}
else
{
MessageBox.Show("not a.Equals(b)");
}
if (((string)null).Equals(null))//Get an exception
{
MessageBox.Show("null.Equals(null)");
}
else
{
MessageBox.Show("not null.Equals(null)");
}
if (b.Equals(b))//Get an exception
{
MessageBox.Show("b.Equals(b)");
}
else
{
MessageBox.Show("not b.Equals(b)");
}
}
结论,两者没有本质区别,最终都是调用mscorlib.dll!string.EqualsHelper
细微的差别还是有的,那就是调用Equals的类不能为空。貌似这句话是废话,hoho.
从效率上讲,==多调用一层函数,充其量是多了两个move,和一个call,可以忽略不计。
不过在2005下调用Equals时,参数不能为null,否则会抛异常,没跟踪,记住就可以了,具体原因自己看汇编吧。
以上列出的是Orcas的编译结果。
2007年4月13日
#
2007年4月9日
#
这个周末写了n多注册机,其中包括一个keyfile验证的。分析算法这东西就像一层窗户纸,一旦捅破,剩下的只是时间问题了。
上周六捉回来的8条小鱼已经顺利地生活了一周了,周六给他们换了全新的野外水。:)
不过也有恶心的事,遇到了抢劫的,幸运的是,他们没敢动手。估计是看我比较壮吧,老子石头都准备好了,丫的没动手。
当时我紧紧盯住其中一个,后面3个是他同伙。真的动起手来,我肯定是先放倒他再说,其他三个来不及过来(距离10米开外)。
虽然没抢我,不过我还是疑惑是不是应该报警?准备下周末带菜刀去那里看他们还在不在。
2007年4月6日
#
Software Design Engineer in Test (SDET)
Discover Life on the Last Line of Defense
As a Software Design Engineer in Test (SDET), you’ll own it, break it, fix it, and own it again. You’ll ensure a product’s quality by making sure it performs as users expect it to. Part of the fun is how creative you can be devising ways to manipulate, crush, and sabotage software into submission—while creating innovative testing technologies along the way.
Ultimately, as an SDET it’s your input that can make the difference between joy and frustration for the customers. Since you’re keen on how things work, and making them work better, you’ll work hand in hand with the Program Managers and Software Design Engineers to design, develop, and maintain automation systems for use in development and testing cycles. Using the tools you create, you’ll pour over source code for trouble spots, debugging and isolating problems, and executing creative tests to find new bugs while regression testing recent fixes.
Qualifications:
| • |
Fluency in C/C++/C#/VB.NET and experience designing and developing tool architecture |
| • |
Ability to solve complex problems and write automation systems and device drivers |
| • |
Ability to author test plans and cases, conduct security and stress tests, and debug at source level after identifying, investigating, and prioritizing bugs |
| • |
Demonstrated skills in negotiation and conflict management |
| • |
Demonstrated interest in customer advocacy derived from a holistic understanding of the product from the code level to delivery |
2007年4月4日
#
第一次用goole输入法,写了这么多,一直没选词,直接输入拼音然后空格就可以了。对于多年的智能abc5.22的fans来说,google输入法就是一个智能abc的超级升级版。使用上几乎不需要改变输入习惯。当然有些特色的东西是没有了,比如笔画输入,比如取词的第一个字或最后一个字。还有v输入特殊字符。
不过这不影响我将google输入法作为首选输入法,因为用它输入实在是太流畅了。 ^0^
这样说有点做广告的嫌疑,呵呵。说一下最近的收获。
由于需要调试某些东西,以前我可以用ollydbg或者dasm之类的工具,不过公司不让用盗版,只好用免费的WinDbg. 对于这个词有些陌生,不过装上以后意外地发现居然几乎完全兼容dos版的debug,呵呵,这让我对它的好感油然而生。
不过在使用过程中发现要完全掌握这个东西,对目前的我来说,是在是太难了。最简单的,比如Shift+F11,就是运行到返回,或者说是Step Out,它自动生成的代码我就根本看不懂。“bp /1 /c @$csp @$ra;g”,从大的方面看,是设置一个断点,然后执行。但是那个断点到底是设置到哪里了,我实在想不明白。
下面说一下WinDbg比其他工具好的地方。我认为最大的优点就是调试符号功能,让我能看到系统中那些未命名的函数。虽然ollydbg也有这个功能,但比较下来,还是WinDbg的符号功能更强大。不过WinDbg也有不好的地方,就是显示参数的时候只显示3个,如果超过3个,对不起,您老自己到栈上找吧,如果少于3个,它照样当作3个去取。
总的来说,我认为WinDbg在调试Window API方面是首选,在分析程序方面还是用OllyDbg吧。
最近玩了几个cm,写出了注册机,不过算法都比较简单,总算告别爆破手阶段了 ^_^
2007年3月12日
#
貌似这里的数据又丢失了,还好最近没写什么东西,发点图片,猜猜我在做什么,呵呵。
声明:未PS ^.^


2007年1月15日
#
上周六吃了一次传说中的“仁”。
第一口,非常臭。
第二口,有点甜。
第三口,太甜了。
……
最后,总结:不是很喜欢,也不是很讨厌
o(n_n)o
2006年11月5日
#
8月1日正式离职,计划用3个月时间找工作。三个月过去了,感觉自己当初做这个决定是非常正确的,在这期间,也曾怀疑自己是不是不应该太贸然辞职,毕竟原公司几乎不用工作,薪水也算凑合。现在到了总结的时候了,一句话,不把自己逼到绝路上,是看不到自己的缺点,也挖掘不出自己的潜力的。
计划和实施几乎完全吻合:
第一个月在上海找,第二个月去石家庄陪老婆,第三个月再回上海。
结果在石家庄的时候,朋友们给我找了几个工作,基本上感觉都还不错。如果我在石家庄的话,肯定去了,可惜看到老婆公司加班太严重,只好让她辞职。
10月1期间回到上海,继续找工作
10月中旬找到了现在的公司,11.1上班
期间到很多公司面试,甚至还差点去北京工作(做p2p软件),感觉经过这些经历,对当前的软件行业有了更深的了解,用Delphi的公司太少了,用bcb的几乎没有,用vc的还有一部分,而最多的是java和dotnet(我目前就在用dotnet),数据库方面,凡是用java的,都要求oracle,没有经验基本上连面试的机会都没有。
也想过去一些用汇编的公司做自己感兴趣的方面(主要是病毒分析和防破解),但是个人感觉这是一条不归路,还是作为业余爱好吧,在盛大面试的时候,某人就对我说,“成天看汇编代码,实在太烦”。经过慎重考虑,发现自己不过是叶公好龙罢了,与世隔绝的生活其实不是我想要的,我就是一俗人。
新公司是做外包的,虽然工作比以前辛苦多了,但收获也不少,趁自己还年轻,多接触一些事情当然是好事。
当年大家开始工作的时候,一部分人选择了从事coder以外的事情,这些人有的是因为自己能力非凡,不屑coding,有的是能力太差,无法coding,就在这些“能力差”的人当中,有些已经成了老板,手下有n多“高手”为他coding,而那些当年比他牛的人,仍然在写垃圾代码的大有人在。说这个例子无非是想说明一个道理:一扇门不通的时候,另外一扇门会打开,成功未必就是好事,失败也未必是坏事。当一扇门向你打开的时候,不要着急走进去,再去看看别的门,你能轻易打开的门,别人也一样轻易打开。
2006年9月14日
#
居然说我的心理年龄为33岁,汗!
你的成熟度是 117.857142857143%, 你的心理处在成年时期。你成熟、稳健、老练、实际,能够合情合理地处理现实人生、理想的种种矛盾,比较理智地看待完美与缺陷,获得与丧失。清楚地认识自己,能清明地分辨可能与不能,可为与不可为。但这种状态稍有偏失,你就会走进保守与停滞,也容易导致的将是创造性和人生乐趣的丧失。
==========================================
比较赞同最后一句。前面的部分赞同。在处理现实和理想的矛盾方面,我还不够理智。
成熟、稳健、老练、实际,貌似都不够。
地址
http://www.hunbei.com.cn/flash/flash_play.asp?id=2770