月度归档:2011 年三月

C# ArrayList的用法

System.Collections.ArrayList类是一个特殊的数组。通过添加和删除元素,就可以动态改变数组的长度。

一、优点

1. 支持自动改变大小的功能

2. 可以灵活的插入元素

3. 可以灵活的删除元素

4. 可以灵活访问元素

二、局限性

跟一般的数组比起来,速度上差些

三、添加元素

1.public virtual int Add(object value);

将对象添加到ArrayList的结尾处

ArrayList aList=new ArrayList();

aList.Add(“a”);

aList.Add(“b”);

aList.Add(“c”);

aList.Add(“d”);

aList.Add(“e”);

内容为abcde

2.public virtual void Insert(int index,object value);

将元素插入ArrayList的指定索引处

ArrayList aList=new ArrayList();

aList.Add(“a”);

aList.Add(“b”);

aList.Add(“c”);

aList.Add(“d”);

aList.Add(“e”);

aList.Insert(0,”aa”);

结果为aaabcde

3.public virtual void InsertRange(int index,ICollectionc);

将集合中的某个元素插入ArrayList的指定索引处

ArrayList aList=new ArrayList();

aList.Add(“a”);

aList.Add(“b”);

aList.Add(“c”);

aList.Add(“d”);

aList.Add(“e”);

ArrayList list2=new ArrayList();

list2.Add(“tt”);

list2.Add(“ttt”);

aList.InsertRange(2,list2);

结果为abtttttcde

四、删除

a)public virtual void Remove(object obj);

从ArrayList中移除特定对象的第一个匹配项,注意是第一个

ArrayList aList=new ArrayList();

aList.Add(“a”);

aList.Add(“b”);

aList.Add(“c”);

aList.Add(“d”);

aList.Add(“e”);

aList.Remove(“a”);

结果为bcde

2.public virtual void RemoveAt(intindex);

移除ArrayList的指定索引处的元素

aList.Add(“a”);

aList.Add(“b”);

aList.Add(“c”);

aList.Add(“d”);

aList.Add(“e”);

aList.RemoveAt(0);

结果为bcde

3.public virtual void RemoveRange(int index,int count);

从ArrayList中移除一定范围的元素。Index表示索引,count表示从索引处开始的数目

aList.Add(“a”);

aList.Add(“b”);

aList.Add(“c”);

aList.Add(“d”);

aList.Add(“e”);

aList.RemoveRange(1,3);

结果为ae

4.public virtual void Clear();

从ArrayList中移除所有元素。

五、排序

a)public virtual void Sort();

对ArrayList或它的一部分中的元素进行排序。

ArrayListaList=newArrayList();

aList.Add(“e”);

aList.Add(“a”);

aList.Add(“b”);

aList.Add(“c”);

aList.Add(“d”);

DropDownList1.DataSource=aList;//DropDown ListDropDownList1;

DropDownList1.DataBind();

结果为eabcd

ArrayList aList=new ArrayList();

aList.Add(“a”);

aList.Add(“b”);

aList.Add(“c”);

aList.Add(“d”);

aList.Add(“e”);

aList.Sort();//排序

DropDownList1.DataSource=aList;//DropDownListDropDownList1;

DropDownList1.DataBind();

结果为abcde

b)public virtual void Reverse();

将ArrayList或它的一部分中元素的顺序反转。

ArrayList aList=new ArrayList();

aList.Add(“a”);

aList.Add(“b”);

aList.Add(“c”);

aList.Add(“d”);

aList.Add(“e”);

aList.Reverse();//反转

DropDownList1.DataSource=aList;//DropDownListDropDownList1;

DropDownList1.DataBind();

结果为edcba

六、查找

a)public virtual int IndexOf(object);

b)public virtual int IndexOf(object,int);

c)public virtual int IndexOf(object,int,int);

返回ArrayList或它的一部分中某个值的第一个匹配项的从零开始的索引。没找到返回-1。

ArrayList aList=new ArrayList();

aList.Add(“a”);

aList.Add(“b”);

aList.Add(“c”);

aList.Add(“d”);

aList.Add(“e”);

intnIndex=aList.IndexOf(“a”);//1

nIndex=aList.IndexOf(“p”);//没找到,-1

d)public virtual int LastIndexOf(object);

e)public virtual int LastIndexOf(object,int);

f)public virtual int LastIndexOf(object,int,int);

返回ArrayList或它的一部分中某个值的最后一个匹配项的从零开始的索引。

ArrayList aList=new ArrayList();

aList.Add(“a”);

aList.Add(“b”);

aList.Add(“a”);//同0

aList.Add(“d”);

aList.Add(“e”);

intnIndex=aList.LastIndexOf(“a”);//值为2而不是0

g)public virtual bool Contains(objectitem);

确定某个元素是否在ArrayList中。包含返回true,否则返回false

七、获取数组中的元素

下面以整数为例,给出获取某个元素的值的方法

ArrayList aList=new ArrayList();

for(int i=0;i<10;i++)

aList.Add(i);

for(i=0;i<10;i++)

Textbox1.text+=(int)aList[i]+” “;//获取的方式基本与一般的数组相同,使用下标的方式进行

结果为:0 1 2 3 4 5 6 7 8 9

八、其他

1.public virtual intCapacity{get;set;}

获取或设置ArrayList可包含的元素数。

2.public virtual intCount{get;}

获取ArrayList中实际包含的元素数。

Capacity是ArrayList可以存储的元素数。Count是ArrayList中实际包含的元素数。Capacity总是大于或等于Count。如果在添加元素时,Count超过Capacity,则该列表的容量会通过自动重新分配内部数组加倍。

如果Capacity的值显式设置,则内部数组也需要重新分配以容纳指定的容量。如果Capacity被显式设置为0,则公共语言运行库将其设置为默认容量。默认容量为16。

在调用Clear后,Count为0,而此时Capacity切是默认容量16,而不是0

3.public virtual void TrimToSize();

将容量设置为ArrayList中元素的实际数量。

如果不向列表中添加新元素,则此方法可用于最小化列表的内存系统开销。

若要完全清除列表中的所有元素,请在调用TrimToSize之前调用Clear方法。截去空ArrayList会将ArrayList的容量设置为默认容量,而不是零。

ArrayList aList=new ArrayList();

aList.Add(“a”);

aList.Add(“b”);

aList.Add(“c”);

aList.Add(“d”);

aList.Add(“e”);//Count=5,Capacity=16,

aList.TrimToSize();//Count=Capacity=5;

java 枚举类[转]

枚举类型是JDK5.0的新特征。Sun引进了一个全新的关键字enum来定义一个枚举类。下面就是一个典型枚举类型的定义:

Java代码
public enum Color{
RED,BLUE,BLACK,YELLOW,GREEN
}

public enum Color{
RED,BLUE,BLACK,YELLOW,GREEN
}显然,enum很像特殊的class,实际上enum声明定义的类型就是一个类。而这些类都是类库中Enum类的子类 (java.lang.Enum<E>)。它们继承了这个Enum中的许多有用的方法。下面我们就详细介绍enum定义的枚举类的特征及其用 法。(后面均用Color举例)

1、Color枚举类是特殊的class,其枚举值(RED,BLUE…)是Color的类对象(类实例):
Color c=Color.RED;
而且这些枚举值都是public static final的,也就是我们经常所定义的常量方式,因此枚举类中的枚举值最好全部大写。

2、即然枚举类是class,当然在枚举类型中有构造器,方法和数据域。但是,枚举类的构造器有很大的不同:
(1) 构造器只是在构造枚举值的时候被调用。

Java代码
enum Color{
RED(255,0,0),BLUE(0,0,255),BLACK(0,0,0),YELLOW(255,255,0),GREEN(0,255,0);
//构造枚举值,比如RED(255,0,0)
private Color(int rv,int gv,int bv){
this.redValue=rv;
this.greenValue=gv;
this.blueValue=bv;
}

public String toString(){  //自定义的public方法
return super.toString()+”(“+redValue+”,”+greenValue+”,”+blueValue+”)”;
}

private int redValue;  //自定义数据域,private为了封装。
private int greenValue;
private int blueValue;
}

enum Color{
RED(255,0,0),BLUE(0,0,255),BLACK(0,0,0),YELLOW(255,255,0),GREEN(0,255,0);
//构造枚举值,比如RED(255,0,0)
private Color(int rv,int gv,int bv){
this.redValue=rv;
this.greenValue=gv;
this.blueValue=bv;
}

public String toString(){  //自定义的public方法
return super.toString()+”(“+redValue+”,”+greenValue+”,”+blueValue+”)”;
}

private int redValue;  //自定义数据域,private为了封装。
private int greenValue;
private int blueValue;
}      (2) 构造器只能私有private,绝对不允许有public构造器。这样可以保证外部代码无法新构造枚举类的实例。这也是完全符合情理的,因为我们知道枚举 值是public static final的常量而已。 但枚举类的方法和数据域可以允许外部访问。

Java代码
public static void main(String args[])
{
// Color colors=new Color(100,200,300);  //wrong
Color color=Color.RED;
System.out.println(color);  // 调用了toString()方法
}

public static void main(String args[])
{
// Color colors=new Color(100,200,300);  //wrong
Color color=Color.RED;
System.out.println(color);  // 调用了toString()方法
}

3、所有枚举类都继承了Enum的方法,下面我们详细介绍这些方法。
(1)  ordinal()方法: 返回枚举值在枚举类种的顺序。这个顺序根据枚举值声明的顺序而定。
Color.RED.ordinal();  //返回结果:0
Color.BLUE.ordinal();  //返回结果:1
(2)  compareTo()方法: Enum实现了java.lang.Comparable接口,因此可以比较象与指定对象的顺序。Enum中的compareTo返回的是两个枚举值的顺 序之差。当然,前提是两个枚举值必须属于同一个枚举类,否则会抛出ClassCastException()异常。(具体可见源代码)
Color.RED.compareTo(Color.BLUE);  //返回结果 -1
(3)  values()方法: 静态方法,返回一个包含全部枚举值的数组。
Color[] colors=Color.values();
for(Color c:colors){
System.out.print(c+”,”);
}//返回结果:RED,BLUE,BLACK YELLOW,GREEN,
(4)  toString()方法: 返回枚举常量的名称。
Color c=Color.RED;
System.out.println(c);//返回结果: RED
(5)  valueOf()方法: 这个方法和toString方法是相对应的,返回带指定名称的指定枚举类型的枚举常量。
Color.valueOf(“BLUE”);   //返回结果: Color.BLUE
(6)  equals()方法: 比较两个枚举类对象的引用。

Java代码
//JDK源代码:
public final boolean equals(Object other) {
return this==other;
}

//JDK源代码:
public final boolean equals(Object other) {
return this==other;
}
4、枚举类可以在switch语句中使用。

Java代码
Color color=Color.RED;
switch(color){
case RED: System.out.println(“it’s red”);break;
case BLUE: System.out.println(“it’s blue”);break;
case BLACK: System.out.println(“it’s blue”);break;
}

mongodb启动失败[转]

现象:
查看日志的内容如下
Tue Jan  4 09:51:37 MongoDB starting : pid=2794 port=27017 dbpath=/var/lib/mongodb 32-bit

** NOTE: when using MongoDB 32 bit, you are limited to about 2 gigabytes of data
**       see http://blog.mongodb.org/post/137788967/32-bit-limitations

Tue Jan  4 09:51:37 db version v1.6.5, pdfile version 4.5
Tue Jan  4 09:51:37 git version: 0eb017e9b2828155a67c5612183337b89e12e291
Tue Jan  4 09:51:37 sys info: Linux domU-12-31-39-01-70-B4 2.6.21.7-2.fc8xen #1 SMP Fri Feb 15 12:39:36 EST 2008 i686 BOOST_LIB_VERSION=1_37
**************
old lock file: /var/lib/mongodb/mongod.lock.  probably means unclean shutdown
recommend removing file and running –repair
see: http://dochub.mongodb.org/core/repair for more information
*************
Tue Jan  4 09:51:37 exception in initAndListen std::exception: old lock file, terminating
Tue Jan  4 09:51:37 dbexit:

Tue Jan  4 09:51:37 shutdown: going to close listening sockets…
Tue Jan  4 09:51:37 shutdown: going to flush oplog…
Tue Jan  4 09:51:37 shutdown: going to close sockets…
Tue Jan  4 09:51:37 shutdown: waiting for fs preallocator…
Tue Jan  4 09:51:37 shutdown: closing all files…
Tue Jan  4 09:51:37     closeAllFiles() finished

Tue Jan  4 09:51:37 dbexit: really exiting now

解决办法:
sudo rm /****/***/mongodb/mongodb.log
sudo rm /***/***/mongodb/mongod.lock
sudo /app/tools/mongodb/bin/mongod –repair –dbpath /app/mongodb/data –repairpath /tmp/mongodb


现象:
Sat Jan 29 12:35:35 MongoDB starting : pid=8298 port=27017 dbpath=/var/lib/mongodb 32-bit

** NOTE: when using MongoDB 32 bit, you are limited to about 2 gigabytes of data
**       see http://blog.mongodb.org/post/137788967/32-bit-limitations

Sat Jan 29 12:35:35 db version v1.6.5, pdfile version 4.5
Sat Jan 29 12:35:35 git version: 0eb017e9b2828155a67c5612183337b89e12e291
Sat Jan 29 12:35:35 sys info: Linux domU-12-31-39-01-70-B4 2.6.21.7-2.fc8xen #1 SMP Fri Feb 15 12:39:36 EST 2008 i686 BOOST_LIB_VERSION=1_37
Sat Jan 29 12:35:35 exception in initAndListen std::exception: Unable to create / open lock file for lockfilepath: /var/lib/mongodb/mongod.lock errno:13 Permission denied, terminating
Sat Jan 29 12:35:35 dbexit:

Sat Jan 29 12:35:35 shutdown: going to close listening sockets…
Sat Jan 29 12:35:35 shutdown: going to flush oplog…
Sat Jan 29 12:35:35 shutdown: going to close sockets…
Sat Jan 29 12:35:35 shutdown: waiting for fs preallocator…
Sat Jan 29 12:35:35 shutdown: closing all files…
Sat Jan 29 12:35:35     closeAllFiles() finished

Sat Jan 29 12:35:35 shutdown: removing fs lock…
Sat Jan 29 12:35:35 couldn’t remove fs lock errno:9 Bad file descriptor
Sat Jan 29 12:35:35 dbexit: really exiting now

解决方法:

  • Manually remove the lockfile: sudo rm /var/lib/mongodb/mongod.lock
  • Run the repair script: sudo -u mongodb /usr/bin/mongod -f /etc/mongodb.conf --repair.
    • You must run this command as the mongodb user. If you run it as root, then root will own files in /var/lib/mongodb/ that are necessary to run the mongodb daemon and therefore when the daemon trys to run later as the mongodb user, it won’t have permissions to start. In that case you’ll get this error: Unable to create / open lock file for lockfilepath: /var/lib/mongodb/mongod.lock errno:13 Permission denied, terminating.
    • On Ubuntu, you must specify the configuration file /etc/mongodb.conf using the -f flag. Otherwise it will look for the data files in the wrong place and you will see the following error: dbpath (/data/db/) does not exist, terminating.
  • Now you can start your MongoDB server with sudo start mongodb and verify it is running with sudo status mongodb and by trying to connect to it with mongo test.

Form.Close你知道多少? [转]

今天想做保存查询界面的功能,接着就让我重新认识了Form.Close。

需求:

想要做到在主界面中点击查询时,出现的查询界面所示条件与上次调用一致。

解决方法1:

参照别人的方法:

在主界面MainForm中声明QueryForm qf = null;

在MainForm的查询按钮方法内:

private void Query(object sender,EventArgs e)

{

if (qf == null)

{

qf = new QueryForm();

qf.StartPosition =FormStartPosition.CenterParent;

}

qf.ShowDialog();

this.navigatorPlus1.QuerySql =qf.Sql;

}

这样上次的查询条件就复原出来了。

令我感到神奇的是Form.Close()方法,彻底颠覆了我的认识,以前以为调用之后就在内存中释放掉了。

在查阅MSDN后,才觉得原来这么常用的方法,我也了解的不够,好好学习!!

——————————-MSDN——————————

Form.Close 方法

备注

窗体关闭后,关闭在该对象内创建的所有资源并且释放该窗体。通过处理 Closing 事件,并设置作为参数传递给事件处理程序的 CancelEventArgs 的 Cancel属性,可以防止在运行时关闭窗体。如果要关闭的窗体是应用程序的启动窗体,则该应用程序结束。

在以下两种情况下调用 Close 不会释放窗体:(1) 窗体是多文档界面 (MDI) 应用程序的一部分且是不可见的;(2) 您是使用 ShowDialog 显示的该窗体。在这些情况下,需要手动调用 Dispose 来将窗体的所有控件都标记为需要进行垃圾回收。

注意:

在显示为无模式窗口的 Form 上调用 Close 方法时,不能调用 Show 方法使窗体可见,因为窗体的资源已被释放。若要隐藏窗体然后又使其可见,请使用 Control.Hide 方法。

警告:

.NET Framework 2.0 之前,当调用 Application.Exit 方法以退出应用程序时,不会引发 Form.Closed 和 Form.Closing 事件。如果在必须执行的其中一个事件中有验证代码,则在调用 Exit 方法之前,应分别为每个打开的窗体调用 Form.Close 方法。

解决方法2:

因为上面的方法要每个界面都修改,如果工作量不大,可以考虑。但是我们程序里的查询界面太多了。。。不过幸好,查询界面都继承了Core.BaseForm。

在Core.BaseForm.FormClosing()方法中遍历界面所有控件,将其值保存到一临时文件中。

在Core.BaseForm.Load()方法中打开临时文件,遍历所有控件,为其赋值。

具体代码略。

总结:

Form.Close()这么常用的方法,我竟然也不熟悉。有机会细细体会下MS的设计。多看看别人的代码,或许你会有意想不到的收获!!

C# 退出应用程序的几种方法

this.close(); //方法退关闭当前窗口。
Application.Exit(); //方法退出整个应用程序。  (无法退出单独开启的线程)
Application.ExitThread(); //释放所有线程
Environment.Exit(0)       //可以退出单独开启的线程
From.close()exit(1)   //如果运行的是Form应用程序,可以调用From.close()exit(1) 表示异常退出exit(0)表示正常退出
Thread.Abort()    //退出线程可以调用
Process.close()    //退出进程可以调用   
System.Diagnostics.Process.GetCurrentProcess().Close();
return 退出当前方法

感言

最好的幸福是把一个人记住,

最好的快乐是有一个人在乎,

最好的辛苦是别人承认你的付出,

最好的朋友是时刻不忘记为对方祝福。

C# VS2005用API学习小例子[转]

1.判断当前系统活动窗口是否是指定的窗口

//找到系统当前活动的窗口的句柄
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();

//根据任务栏应用程序显示的名称找相应窗口的句柄
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

//获取指定句柄窗口的标题
[DllImport("User32.dll")]
static extern int GetWindowText(IntPtr handle, StringBuilder text, int MaxLen);

IntPtr findPtr = FindWindow(null, “AION Client”);//AION Client为游戏在任务栏的名称
StringBuilder text1 = new StringBuilder(50);//按要求找到的进程的标题
StringBuilder text2 = new StringBuilder(50);//当前活动进程的标题
GetWindowText(GetForegroundWindow(), text1, 50);
GetWindowText(findPtr, text2, 50);

if(text1.Equals(text2))

{

MessageBox.Show(“当前活动窗口是指定窗口”);

}

else

{

MessageBox.Show(“当前活动窗口不是指定窗口”);

}

2.设置指定窗口选中(激活)

private const int SW_RESTORE = 9;

[DllImport("user32.dll ")]
private static extern bool SetForegroundWindow(IntPtr hWnd);

[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

IntPtr findPtr = FindWindow(null, “AION Client”);//AION Client为游戏在任务栏的名称

if (findPtr.ToInt32() != 0)
{
ShowWindow(findPtr, SW_RESTORE); //将窗口还原,如果不用此方法,缩小的窗口不能激活
SetForegroundWindow(findPtr);//将指定的窗口选中(激活)

}

3.向指定的窗口的文本框发送字符和按键

private const uint SWP_SHOWWINDOW = 0×0040;

private const int MOUSEEVENTF_LEFTDOWN = 0×0002; //模拟鼠标左键按下
private const int MOUSEEVENTF_LEFTUP = 0×0004; //模拟鼠标左键抬起

//设置鼠标位置
[DllImport("user32.dll")]
private static extern bool SetCursorPos(int X, int Y);

//设置窗口位置
[DllImport("user32.dll")]
private static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndlnsertAfter, int X, int Y, int cx, int cy, uint Flags);

//模拟鼠标
[DllImport("user32.dll")]
private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, int dwExtraInfo);

//设置窗口位置和大小
SetWindowPos(findPtr, (IntPtr)(-1), 150, 100, 950, 750, SWP_SHOWWINDOW);
SetCursorPos(590, 445); //设置鼠标位置
mouse_event(MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0);
mouse_event(MOUSEEVENTF_LEFTUP, 0, 0, 0, 0);

System.Threading.Thread.Sleep(800);
SendKeys.Send(gameId);   //模拟键盘输入游戏ID
SendKeys.Send(“{TAB}”); //模拟键盘输入TAB
SendKeys.Send(gamePwd); //模拟键盘输入游戏密码
SendKeys.Send(“{ENTER}”); //模拟键盘输入ENTER

4.枚举指定窗口中的所有控件,有的游戏不能枚举,像魔兽等等,因为界面是画出来的,没有句柄概念

public delegate bool EnumChildWindowsProc(IntPtr hwnd, uint lParam);

[DllImport("user32.dll", EntryPoint = "EnumChildWindows")]
public static extern bool EnumChildWindows(IntPtr hWndParent, EnumChildWindowsProc lpEnumFunc, int lParam);

[DllImport("user32.dll", EntryPoint = "GetClassName")]
public static extern int GetClassName(IntPtr hwnd, StringBuilder lpClassName, int nMaxCount);

private void btnOk_Click(object sender, EventArgs e)
{
IntPtr nowPtr = FindWindow(null, “QQ游戏”);
EnumChildWindowsProc myEnumChild = new EnumChildWindowsProc(EumWinChiPro);
try
{
EnumChildWindows(nowPtr, myEnumChild, 0);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + “\r\n” + ex.Source + “\r\n\r\n” + ex.StackTrace.ToString());
}
lblMsg.Text = count.ToString();//显示指定窗口上有多少子控件

}

public   static   int   count;
public   static   bool     EumWinChiPro(IntPtr       hWnd,uint     lParam)
{
StringBuilder  s  =  new  StringBuilder(50);  //s即为控件的类名称
GetClassName(hWnd,   s,50);
count++;
return   true;
}

5.  获取指定窗口句柄相对屏幕中的位置

[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("User32.dll")]
private static extern bool ClientToScreen(IntPtr hwnd, ref Point lpPoint);

IntPtr findPtr = FindWindow(null, “QQ游戏”);

Point p = new Point (0);
ClientToScreen(findPtr, ref p);
MessageBox.Show(p.X+”,”+p.Y);

6.判断指定窗口是否是最大化

[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll")]
private static extern bool IsZoomed(IntPtr hWnd);

IntPtr findPtr = FindWindow(null, “QQ游戏”);

if (IsZoomed(findPtr))
{

MessageBox.Show(“最大化”);

}

else

{

MessageBox.Show(“最小化”);

}

如何知道LINUX系统是否被入侵?

因为*NIX系统经常承当着关键任务,所以它经常是入侵者攻击的首选目标。于是检测入侵、保护系统安全是管理者的最为重要的任务之一。那么,在没有其 它工具帮助的情况下,如何去判断系统当前的安全性?如何去发现入侵呢?下面给大家介绍一些常用到的检查方法,以LINUX和solaris为例:

1、检查系统密码文件

首先从明显的入手,查看一下passwd文件,ls –l /etc/passwd查看文件修改的日期。
输入命令 awk –F:’$3==0 {print }’ /etc/passwd来检查一下passwd文件中有哪些特权用户,系统中uid为0的用户都会被显示出来。顺便再检查一下系统里有没有空口令帐 户:awk –F: ‘length()==0 {print } ’/etc/shadow

2、查看一下进程,看看有没有奇怪的进程

重点查看进程:ps –aef | grep inetd
inetd是UNIX系统的守护进程,正常的inetd的pid都比较靠前,如果你看到输出了一个类似 inetd –s/tmp/.xxx之类的进程,着重看inetd–s后面的内容。在正常情况下,LINUX系统中的inetd服务后面是没有-s参数的,当然也没有 用inetd去启动某个文件;而solaris系统中也仅仅是inetd –s,同样没有用inetd去启动某个特定的文件;如果你使用ps命令看到inetd启动了某个文件,而你自己又没有用inetd启动这个文件,那就说明 已经有人入侵了你的系统,并且以root权限起了一个简单的后门。
输入ps –aef查看输出信息,尤其注意有没有以./xxx开头的进程。一旦发现异样的进程,经检查为入侵者留下的后门程序,立即运行kill –9 pid开杀死该进程,然后再运行ps–aef查看该进程是否被杀死;一旦此类进程出现杀死以后又重新启动的现象,则证明系统被人放置了自动启动程序的脚 本。这个时候要进行仔细查找:find/ -name 程序名–print,假设系统真的被入侵者放置了后门,根据找到的程序所在的目录,UNIX下隐藏进程有的时候通过替换ps文件来做,检测这种方法涉及到 检查文件完整性,一会我们再讨论这种方法。接下来根据找到入侵者在服务器上的文件目录,一步一步进行追踪。

3、检查系统守护进程
检查/etc/inetd.conf文件,输入:cat /etc/inetd.conf | grep –v“^#”,输出的信息就是你这台机器所开启的远程服务。一般入侵者可以通过直接替换in.xxx程序来创建一个后门,比如用/bin/sh替换掉 in.telnetd,然后重新启动inetd服务,那么telnet到服务器上的所有用户将不用输入用户名和密码而直接获得一个rootshell。

4、检查网络连接和监听端口
输入netstat -an,列出本机所有的连接和监听的端口,查看有没有非法连接。
输入netstat –rn,查看本机的路由、网关设置是否正确。
输入 ifconfig –a,查看网卡设置。

5、检查系统日志
命令last |more查看在正常情况下登录到本机的所有用户的历史记录。但last命令依赖于syslog进程,这已经成为入侵者攻击的重要目标。入侵者通常会停止 系统的syslog,查看系统syslog进程的情况,判断syslog上次启动的时间是否正常,因为syslog是以root身份执行的,如果发现 syslog被非法动过,那说明有重大的入侵事件。
在linux下输入ls –al /var/log
在solaris下输入 ls –al /var/adm
检查wtmp utmp,包括messgae等文件的完整性和修改时间是否正常,这也是手工擦除入侵痕迹的一种方法。

6、检查系统中的core文件
通过发送畸形请求来攻击服务器的某一服务来入侵系统是一种常规的入侵方法,典型的RPC攻击就是通过这种方式。这种方式有一定的成功率,也就是说它 并不能100%保证成功入侵系统,而且通常会在服务器相应目录下产生core文件,全局查找系统中的core文件,输入find / – namecore –exec ls –l {} \; 依据core所在的目录、查询core文件来判断是否有入侵行为。

7、检查系统文件完整性
检查文件的完整性有多种方法,通常我们通过输入ls –l 文件名来查询和比较文件,这种方法虽然简单,但还是有一定的实用性。但是如果ls文件都已经被替换了就比较麻烦。在LINUX下可以用rpm –V `rpm –qf 文件名`来查询,查询的结果是否正常来判断文件是否完整。在 LINUX下使用rpm来检查文件的完整性的方法也很多,这里不一一赘述,可以manrpm来获得更多的格式。
UNIX系统中,/bin/login是被入侵者经常替换作为后门的文件,接下来谈一下login后门 :
UNIX里,Login程序通常用来对telnet来的用户进行口令验证。入侵者获取login的源代码并修改,使它在比较输入口令与存储口令时先 检查后门口令。如果用户敲入后门口令,它将忽视管理者设置的口令让你长驱直入:这将允许入侵者进入任何账号,甚至是root目录。由于后门口令是在用户真 实登录并被日志记录到utmp和wtmP前产生的一个访问,所以入侵者可以登录获取shell却不会暴露该账号。管理者注意到这种后门后,使 用”strings”命令搜索login程序以寻找文本信息。许多情况下后门口令会原形毕露。入侵者又会开始加密或者更改隐藏口令,使strings命令 失效。所以许多管理者利用MD5校验和检测这种后门。UNIX系统中有md5sum命令,输入md5sum文件名检查该文件的md5签名。它的使用格式如 下:md5sum –b 使用二进制方式阅读文件;md5sum –c逆向检查MD5签名;md5sum –t 使用文本方式阅读文件。
在前面提到过守护进程,对于守护进程配置文件inetd.conf中没有被注释掉的行要进行仔细比较,举个简单的例子,如果你开放了telnet服 务,守护进程配置文件中就会有一句: telnet stream tcp nowait root/usr/sbin/in.telnetd in.telnetd

可以看到它所使用的文件是 /usr/sbin/in.telnetd,检查该文件的完整性,入侵者往往通过替换守护进程中允许的服务文件来为自己创建一个后门。
LINUX系统中的/etc/crontab也是经常被入侵者利用的一个文件,检查该文件的完整性,可以直接cat /etc/crontab,仔细阅读该文件有没有被入侵者利用来做其他的事情。
不替换login等文件而直接使用进程来启动后门的方法有一个缺陷,即系统一旦重新启动,这个进程就被杀死了,所以得让这个后门在系统启动的时候也启动起来。通常通过检查/etc/rc.d下的文件来查看系统启动的时候是不是带有后门程序。
说到这里,另外提一下,如果在某一目录下发现有属性为这样的文件:-rwsr-xr-x 1 root root xxx.sh,这个表明任何用户进来以后运行这个文件都可以获得一个rootshell,这就是setuid文件。运行 find –perm 4000–print对此类文件进行全局查找,然后删除这样的文件。

8、检查内核级后门
如果你的系统被人安装了这种后门,通常都是比较麻烦的,首先,检查系统加载的模块,在LINUX系统下使用lsmod命令,在solaris系统下 使用modinfo命令来查看。这里需要说明的是,一般默认安装的LINUX加载的模块都比较少,通常就是网卡的驱动;而solaris下就很多,没别的 办法,只有一条一条地去分析。对内核进行加固后,应禁止插入或删除模块,从而保护系统的安全,否则入侵者将有可能再次对系统调用进行替换。我们可以通过替 换create_module()和delete_module()来达到上述目的。另外,对这个内核进行加固模块时应尽早进行,以防系统调用已经被入侵 者替换。如果系统被加载了后门模块,但是在模块列表/proc/module里又看不到它们。出现这种情况,需要仔细查找/proc目录,根据查找到的文 件和经验来判断被隐藏和伪装的进程,当然目录也可能不是隐藏的。
手工的入侵检测行为对于系统安全来说只是治标而不治本,多半还是依靠管理者的技巧和经验来增强系统的安全性,没有,也不可能形成真正的安全体系,虽 然好过没有,可以检测和追踪到某些入侵行为,但如果碰上同样精通系统的入侵者就很难抓住踪迹了。搭建真正的安全体系需要配合使用入侵检测系统,一个优秀的 入侵检测系统辅以系统管理者的技巧和经验可以形成真正的安全体系,有效判断和切断入侵行为,真正保护主机、资料。