以前给一些Windows机器开启了审计功能,可以在系统的安全日志里面看到一些东西,但是没有具体了解开启某一项审计到底能记录什么东西。
今天测试了一下只开“帐户登录”,用远程桌面登录上去,可以看到一个帐户登陆成功的日志,但是并没有记录从哪台机器登录的。再打开“登陆事件”,再次通过远程桌面登陆,系统安全性日志能够看到登录用户和登录机器的源IP。这时通过SMB访问共享的目录,日志中也有登录事件的日志,只是事件ID等信息和远程桌面登录并不一样。所以Windows系统要审计所有的登录,应该开启“登录事件”而不是只开“帐户登录”。需要区分不同类型的登录,可以对事件ID进行排序;-)。
use master
EXEC sp_dropextendedproc ‘xp_cmdshell’
EXEC sp_dropextendedproc ‘Sp_OACreate’
EXEC sp_dropextendedproc ‘Sp_OADestroy’
EXEC sp_dropextendedproc ‘Sp_OAGetErrorInfo’
EXEC sp_dropextendedproc ‘Sp_OAGetProperty’
EXEC sp_dropextendedproc ‘Sp_OAMethod’
EXEC sp_dropextendedproc ‘Sp_OASetProperty’
EXEC sp_dropextendedproc ‘Sp_OAStop’ (more…)
因为测试黑洞需要用到一个Linux下的发包工具,所以准备在IBM笔记本安装一个Linux。最近Ubuntu看上去很热的样子,于是从他官方网站下载了最新的5.10版本的ISO。光盘启动安装,直接敲回车会死掉,Goolge了一下,说是IBM R40e的ACPI有点问题,敲”linux acpi=off”就可以正常安装。但是到启动分区工具的时候花的时间太长了,前天尝试安装的时候看到硬盘灯亮了很长时间都没什么反应,就按电源开关把它终止了。今天耐心了点,等了N长时间,终于完成Ubuntu的安装。
因为关闭了ACPI,显示电源状态和关机有问题,感觉很不爽。于是把kernel/drivers/acpi/processor.ko删除,然后mkinitramfs -o initrd.img-2.6.12-9-386,编辑/boot/grub/menu.lst,把其中的acpi=off删除,重新启动。一切OK;-)
Dropbear是一个轻量级的SSH2服务器及客户端,很小;-)。
Server:dropbear/Client: dbclient
安装Server:
mkdir /etc/dropbear
dropbearkey -t rsa -f /etc/dropbear/dropbear_rsa_host_key
或
dropbearkey -t dss -f /etc/dropbear/dropbear_dss_host_key
用dropbearconvert 来转换openssh的key也可以
dropbearconvert openssh dropbear /etc/ssh/ssh_host_rsa_key /etc/dropbear/dropbear_rsa_host_key
原文的地址http://www.stearns.org/doc/iptables-u32.current.html
介绍
IPTables是一个比较灵活的模块化的防火墙。如果它当前不能够精确的检测具有某些特征的包,你可以选择自己写一个或者是修改一个现存的检测模块。但问题是我们大多数人并不是程序员,虽然有那么多开源的dd。
我们有一个选择是不需要写代码的。好心的Don Cohen写了个IPTables的模块,该模块从数据包中抽出你所感兴趣的一些字节,进行一些操作,看看得到的结果是否在指定的范围之内。比如,我可以获取IP头的Fragmentation信息,丢弃More Fragments标记以外所有的东西,看看它是否设置了这个标记。
根本不需要写任何的C代码
我在这里所要做的就是介绍核心概念,还加入了希望是足够多的带注释的例子,使你能够编写自己的检测模块。
我不会专注于介绍这些部分是什么,还有为什么你要检测它们;有很多的(警告:不好意思,再往前插入了我雇主的信息)资料在做这样的事情。如果你仅仅是需要一个数据包头的快速参考,请看tcpip.pdf。
所有在本文提到的字节位置是以0作为包的第一个字节来计算的。比如,在IP头中,字节“0”保存着4bit的“版本”和4bit的“IP头长度”,字节“1”保存的是“TOS”,等等。
检查2字节范围的值
u32最简单的形式是从Start开始获取4字节的块,用Mask作为掩码,所得的值再和Range作比较。下面是我们第一个例子所用的语法:
iptables -m u32 --u32 "Start&Mask=Range"
通常我们从感兴趣的最后的一个字节减去3而得到“start”值。所以,如果你想得到IP头的字节4和5(IPID),Start就是5-3=2。“Mask”用来 除去你不需要的部分(进行“与”操作),它是一个可以最大可以是0xFFFFFFFF的bitmask。为了得到我们的目标–字节4和5,我们要忽略字节2和3。我们就可以使用掩码0×0000FFFF。事实上我们选用一个短一点的,等值的0xFFFF来代替。
因此,检测2到256的IPID,iptable命令为:
iptables -m u32 --u32 "2&0xFFFF=0x2:0x0100"
从左到右读这个命令:“加载u32模块,对数据包执行以下u32检测:从字节2处获得4个字节(字节2和3是总长,字节4和5是IPID),应用掩码0×0000FFFF(它把前两个字节全部设为0,不改变后两个字节),看看所得的值(即IPID)是否在2和256之间;如果是这样,返回true,否则返回false。”
IPTables没有独立的模块来检查IPID,但这个跟“ip[2:2] >= 2 and ip[2:2] < = 256” 的tcpdump/bpf filter等价。
这个例子我舍去了动作,但你自己可以加上,如:
-j LOG --log-prefix "ID-in-2-256 "
-j DROP
或者其他的动作。你还可以加上其它的检测,正如我过一会所要做的。
Don提供了一个检验包总长大于或等于256的测试方法。包总长是IP头的字节2和3,所以我们的开始位置为3-3=0。因为我们要排除两个字节,掩码就是0xFFFF。最后得到的检测语句为:
iptables -m u32 --u32 "0&0xFFFF=0x100:0xFFFF"
它和以下的是一样的:
iptables -m length --length 256:65535
or the bpf filter
"len >= 256"
检查1字节范围的值
基本相同,只是用掩码0×000000FF(或者短一点的 0xFF)从u32的4字节中找出一个字节以适合我们的需求。比如说我想检测TTL区域,根据TTL小于3来找出对我们的机器使用tracerout命令的人。没错,有一个ttl的模块,但这只是让我们了解它也可以用u32来实现。
我想以IP头的第8个字节结束,所以开始位置为8-3=5。这就是检测语句:
iptables -m u32 --u32 "5&0xFF=0:3"
它和下面的是等价的:
iptables -m ttl --ttl-lt 4
or the bpf filter
"ip[8] < = 3"
一次考虑4个字节
为了检查完整的目的IP地址,我们将检查16-19字节。因为我们需要所有的4个字节,我们不需要掩码。假设目的地址是224.0.0.1:
iptables -m u32 --u32 "16=0xE0000001"
它和这个是一样的:
iptables -d 224.0.0.1/32
如果我们只考虑前3个字节(检查一个地址是否为一个特定C网段的一员),我们又要使用掩码了。我们选用的掩码是0xFFFFFF00,它扔掉了最后的八个bit。假如检查源地址(从12到15字节,尽管我们会用掩码来忽略第15字节)是否在192.168.15.0(0xC0A80F00)这个C类网段:
iptables -m u32 --u32 "12&0xFFFFFF00=0xC0A80F00"
它和下面的做相同的工作:
iptables -s 192.168.15.0/24
检查包头中靠前的字节
显然,如果我想看看TOS区域(IP头的字节1),我不能以1-3=-2开始。我们要做什么才能改为以0开始,找出我们需要的字节并且将它移到最后的位置以便于检测。这并不是我们实现的唯一方法,但它演示了一种马上就可以实现我们需求的技术。
为了得出TOS区域,我先让u32用0偏移量得到0-3字节。现在,我用掩码0×00FF0000找出字节1(在这数据块中的第二个字节)。我要把TOS值移到最右边的位置以方便比较。为了达到这个目的,我用来一个称为“按位右移”的技术。右移的符号是“>>”,它会把数据往右移动数字所指的位数。如果你对右移不熟悉,先看看来自Harper学院的指南。
我用“>>16”把TOS往右移动2字节(或者16位)。既然我们把TOS放到了正确的位置,我们把它和0×08进行比较(最大吞吐量):
iptables -m u32 --u32 "0&0x00FF0000>>16=0x08"
它和这个等价:
iptables -m ttl --tos 8
检查单个bit
我想看一下“More Fragments”标记,iptables没有用于检查该标记的现成模块(-f 匹配第二个以后的分片,但我想匹配除最后一个以外的所有分片)。字节6保存了这个,所以我从偏移量3开始并且忽略3到5字节。通常可以使用掩码0×000000FF,但我还要忽略最后一个字节中的一些bits。我想保留的只是第3个bit(0010 0000),因此我选用的掩码是(0×00000020)。现在我有两个选择:把这个bit移到最后位置进行比较,或者是把它留在当前位置做对比。
我要把它右移5位,如下:
iptables -m u32 --u32 "3&0x20>>5=1"
如果采用把这个bit留在原来的位置方法,就得小心选择右边的比较值。如果这个bit是正值,那么比较值也应该为0×20。
iptables -m u32 --u32 "3&0x20=0x20"
如果“More Fragments”是作了标记的,用这两种方法都会返回正值。
Combining tests
组合几种检测
如果你需要对每个包检查多于一个的特征,在不同的检测之间加上:
&&
前进到TCP头
这有点棘手。假设我要考虑一下TCP头的4-7字节(the TCP sequence number)。我们先用最简单的方法,再考虑一些其他改进的方法。
我们的第一个版本,假定IP头长度为20字节–通常这是个好的假设。我们的开始位置是TCP头的第4个字节,TCP头是紧接着IP头的。我们要检测的就是序列号是否为41(0×29),看起来就是这样:
iptables -m u32 --u32 "24=0x29"
对于IP头长度为20的包,这样做是没有问题的,但这还是有一些问题的。OK,我们一个个把他们搞掂。
首先,我们没有检查这个包是否为一正常的TCP包。这个是保存于IP头的字节9,所以我们要从字节6处开始抓取4个字节,丢弃字节6-8,检查它是否为6。下面这个新的规则首先检查它到底是不是TCP包,再检查序列号是否为41:
iptables -m u32 --u32 "6&0xFF=0x6 && 24=0x29"
第二个问题就是我们暂时忽略了IP头的长度。确实是这样,它的长度通常是20字节,但是用了IP options的话,它可以更长一些。
下一步,我们要得到IP头长度(在IP头有多少个4字节?通常是5)。我们把它乘以4,得到IP头的字节数。我们用这个数字表示需要跳过多少才能到达TCP头开始的地方,再跳过4字节即得到序列号。
为了得到头长度,我们需要把第一个字节:”0>>24″,但我们想要的只是低位的半位元组并且把它乘以4以得到头的真实字节数。做这个乘法,我们将要把它右移22位而不是24。做完这个,我们要用掩码0×3c代替以前用的0×0F。这个表达式就是:”0>>22&0×3C”。在没有options的IP头,这个表达式会返回20,正如我们所预料的。现在我们要告诉u32跳过数字对应的字节,用“@”操作符来做这件事。
iptables -m u32 --u32 "6&0xFF=0x6 && 0>>22&0x3C@4=0x29"
“@”得到它左边生成的数字并向前跳过相应的字节数(我们可以不止一次的做这样的事情–看下面TCP payload的部分)。它右边的4告诉u32取得4-7字节,但u32知道这是相当于它已经跳过了的20字节来说的。我们还是可以得到序列号,即使IP头因为options而增长了。hoho
最后的事情就是处理分片啦。当我们只是分析IP头的时候,这不会造成什么问题。IP设计为IP头只身不可分片,TCP头及application payload则是可能分片的。如果我们要处理第二个或更多的分片,我们在4-7字节可能是得不到序列号的。或许在TCP头的其他部分,甚至是在应用层的数据。
我们所要做的就是检查它是否为第一个分片(或者是一个没有分片的包,这里并不关心这个),这样我们查看的TCP头信息才是可靠的。我们检查大部分(丢弃前3个标记位)位于IP头6和7字节的fragment偏移量,确认它是0。表达式为:”4&0×1FFF=0″
最终得到的表达式(确定是否为TCP包,看看它是未分片包或第一个分片包,跳过IP头,检查TCP头的4-7字节是否等于41)是:
iptables -m u32 --u32 "6&0xFF=0x6 && 4&0x1FFF=0 && 0>>22&0x3C@4=0x29"
事实上,如果一个包是分片了的,我们还得考虑考虑一种情况。分片可能很小,我们需要检查的区域放到了后面的分片!在这种情况并不会出什么问题,因为每个IP包最小有68字节,即使IP头达到了它的最大值–60字节,TCP头的前8个字节也会包含在第一个分片。
当我们要对数据包作进一步的检查时,我们得依赖u32的一个特性。当我们试图请求某个超出了数据包大小的值时,u32会返回false。
检查UDP有效负荷的值
现在我们一起来考虑数据包的有效负荷,匹配UDP DNS查询的数据。在这里我们并不仅仅检查目的端口为53,我们还要检查有效负荷的字节2中的最高位,如果该位是设置了的话,这就是一个DNS查询。
我们先检查这是一个UDP包:"6&0xFF=17"。现在,我们用已经熟悉了的方法检查它是否为第一个分片:"4&0x1FFF=0"。
为了检查目的端口,我们从UDP头取得字节2和3(向前面的例子一样跳过IP头):"0>>22&0x3C@0&0xFFFF=53"。
如果这个数据包通过以上检查,我们回去检查有效负荷(记住我们要跳过可变长度的IP头和8字节的UDP头"0>>22&0x3C@8 ...")来确保这个一个DNS查询而不是一个响应。为了得到字节2的高位,我要用偏移量8来获取头4个字节的有效负荷,并且右移15位,把Query位放到最低位置,再弃去其它的位,然后使用掩码0×01:"0>>22&0x3C@8>>15&0x01=1"。
最后得到的语句就是:
iptables -m u32 --u32 "6&0xFF=17 && 4&0x1FFF=0 && 0>>22&0x3C@0&0xFFFF=53 && 0>>22&0x3C@8>>15&0x01=1"
噢,我们看到的有用信息太少了,垃圾成分太多;-)注意我们只使用了u32来实现整个事情;我们可以把”udp包”,”第一个/未分片包”和”53端口”这些检查用其它的模块来完成,最后得到这个可读性比较强的版本:
iptables -p udp --dport 53 \! -f -m u32 --u32 "0>>22&0x3C@8>>15&0x01=1"
在BBS瞎逛,收到一个Mail,问怎么配squid的认证,我说没用过Squid,不熟悉。后来他说可以给我机器的密码,就让他把密码发给我。ssh登录上去,看了一下,用的是RedHat自带的Squid,于是直接编辑/etc/squid/squid.conf。增加了
acl authuser proxy_auth REQUIRED
http_access allow authuser
auth_param basic program /usr/lib/ncsa_auth /etc/squid/passwd
然后htpasswd /etc/squid/passwd user增加用户
/etc/init.d/squid restart
完成;-)
#!/usr/bin/env python
# -*- coding: iso-8859-1 -*-
“”"ping.py
ping.py uses the ICMP protocol’s mandatory ECHO_REQUEST
datagram to elicit an ICMP ECHO_RESPONSE from a
host or gateway.
Copyright (C) 2004 - Lars Strand (lars strand at gnist org)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Must be running as root, or write a suid-wrapper. Since newer *nix
variants, the kernel ignores the set[ug]id flags on #! scripts for
security reasons
RFC792, echo/reply message:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Type | Code | Checksum |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identifier | Sequence Number |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Data …
+-+-+-+-+-
TODO:
- do not create socket inside ‘while’ (but if not: ipv6 won’t work)
- add support for broadcast/multicast
- add support for own payload string
CHANGELOG:
DONE –> bugfix from Filip Van Raemdonck mechanix debian org
DONE –> add more support for modules (raise instead of sys.exit)
DONE –> locale func names
DONE –> package def
DONE –> some code cleanup
“”"
import sys
import os
import struct
import array
import time
import select
import binascii
import math
import getopt
import string
import socket
# total size of data (payload)
ICMP_DATA_STR = 56
# initial values of header variables
ICMP_TYPE = 8
ICMP_TYPE_IP6 = 128
ICMP_CODE = 0
ICMP_CHECKSUM = 0
ICMP_ID = 0
ICMP_SEQ_NR = 0
# Package definitions.
__program__ = ‘ping’
__version__ = ‘0.5a’
__date__ = ‘2004/15/12′
__author__ = ‘Lars Strand
__licence__ = ‘GPL’
__copyright__ = ‘Copyright (C) 2004 Lars Strand’
def _construct(id, size, ipv6):
“”"Constructs a ICMP echo packet of variable size
“”"
# size must be big enough to contain time sent
if size < int(struct.calcsize("d")):
_error("packetsize to small, must be at least %d" % int(struct.calcsize("d")))
# construct header
if ipv6:
header = struct.pack('BbHHh', ICMP_TYPE_IP6, ICMP_CODE, ICMP_CHECKSUM, \
ICMP_ID, ICMP_SEQ_NR+id)
else:
header = struct.pack('bbHHh', ICMP_TYPE, ICMP_CODE, ICMP_CHECKSUM, \
ICMP_ID, ICMP_SEQ_NR+id)
# if size big enough, embed this payload
load = "-- IF YOU ARE READING THIS YOU ARE A NERD! --"
# space for time
size -= struct.calcsize("d")
# construct payload based on size, may be omitted ![]()
rest = ""
if size > len(load):
rest = load
size -= len(load)
# pad the rest of payload
rest += size * “X”
# pack
data = struct.pack(”d”, time.time()) + rest
packet = header + data # ping packet without checksum
checksum = _in_cksum(packet) # make checksum
# construct header with correct checksum
if ipv6:
header = struct.pack(’BbHHh’, ICMP_TYPE_IP6, ICMP_CODE, checksum, \
ICMP_ID, ICMP_SEQ_NR+id)
else:
header = struct.pack(’bbHHh’, ICMP_TYPE, ICMP_CODE, checksum, ICMP_ID, \
ICMP_SEQ_NR+id)
# ping packet *with* checksum
packet = header + data
# a perfectly formatted ICMP echo packet
return packet
def _in_cksum(packet):
“”"THE RFC792 states: ‘The 16 bit one’s complement of
the one’s complement sum of all 16 bit words in the header.’
Generates a checksum of a (ICMP) packet. Based on in_chksum found
in ping.c on FreeBSD.
“”"
# add byte if not dividable by 2
if len(packet) & 1:
packet = packet + ‘\0′
# split into 16-bit word and insert into a binary array
words = array.array(’h', packet)
sum = 0
# perform ones complement arithmetic on 16-bit words
for word in words:
sum += (word & 0xffff)
hi = sum >> 16
lo = sum & 0xffff
sum = hi + lo
sum = sum + (sum >> 16)
return (~sum) & 0xffff # return ones complement
def pingNode(alive=0, timeout=1.0, ipv6=0, number=sys.maxint, node=None, \
flood=0, size=ICMP_DATA_STR):
“”"Pings a node based on input given to the function.
“”"
# if no node, exit
if not node:
_error(”")
# if not a valid host, exit
if ipv6:
if socket.has_ipv6:
try:
info, port = socket.getaddrinfo(node, None)
host = info[4][0]
# do not print ipv6 twice if ipv6 address given as node
if host == node:
noPrintIPv6adr = 1
except:
_error(”cannot resolve %s: Unknow host” % node)
else:
_error(”No support for IPv6 on this plattform”)
else: # IPv4
try:
host = socket.gethostbyname(node)
except:
_error(”cannot resolve %s: Unknow host” % node)
# trying to ping a network?
if not ipv6:
if int(string.split(host, “.”)[-1]) == 0:
_error(”no support for network ping”)
# do some sanity check
if number == 0:
_error(”invalid count of packets to transmit: ‘%s’” % str(a))
if alive:
number = 1
# Send the ping(s)
start = 1; mint = 999; maxt = 0.0; avg = 0.0
lost = 0; tsum = 0.0; tsumsq = 0.0
# tell the user what we do
if not alive:
if ipv6:
# do not print the ipv6 twice if ip adress given as node
# (it can be to long in term window)
if noPrintIPv6adr == 1:
# add 40 (header) + 8 (icmp header) + payload
print “PING %s : %d data bytes (40+8+%d)” % (str(node), \
40+8+size, size)
else:
# add 40 (header) + 8 (icmp header) + payload
print “PING %s (%s): %d data bytes (40+8+%d)” % (str(node), \
str(host), 40+8+size, size)
else:
# add 20 (header) + 8 (icmp header) + payload
print “PING %s (%s): %d data bytes (20+8+%d)” % (str(node), str(host), \
20+8+size, size)
# trap ctrl-d and ctrl-c
try:
# send the number of ping packets as given
while start < = number:
lost += 1 # in case user hit ctrl-c
# create the IPv6/IPv4 socket
if ipv6:
# can not create a raw socket if not root or setuid to root
try:
pingSocket = socket.socket(socket.AF_INET6, socket.SOCK_RAW, \
socket.getprotobyname("ipv6-icmp"))
except socket.error, e:
print "socket error: %s" % e
_error("You must be root (uses raw sockets)" % os.path.basename(sys.argv[0]))
# IPv4
else:
# can not create a raw socket if not root or setuid to root
try:
pingSocket = socket.socket(socket.AF_INET, socket.SOCK_RAW, \
socket.getprotobyname("icmp"))
except socket.error, e:
print "socket error: %s" % e
_error("You must be root (%s uses raw sockets)" % os.path.basename(sys.argv[0]))
packet = _construct(start, size, ipv6) # make a ping packet
# send the ping
try:
pingSocket.sendto(packet,(node,1))
except socket.error, e:
_error("socket error: %s" % e)
# reset values
pong = ""; iwtd = []
# wait until there is data in the socket
while 1:
# input, output, exceptional conditions
iwtd, owtd, ewtd = select.select([pingSocket], [], [], timeout)
break # no data and timout occurred
# data on socket - this means we have an answer
if iwtd: # ok, data on socket
endtime = time.time() # time packet received
# read data (we only need the header)
pong, address = pingSocket.recvfrom(size+48)
lost -= 1 # in case user hit ctrl-c
# examine packet
# fetch TTL from IP header
if ipv6:
# since IPv6 header and any extension header are never passed
# to a raw socket, we can *not* get hoplimit field..
# I hoped that a socket option would help, but it's not
# supported:
# pingSocket.setsockopt(IPPROTO_IPV6, IPV6_RECVHOPLIMIT, 1)
# so we can't fetch hoplimit..
# fetch hoplimit
#rawPongHop = struct.unpack("c", pong[7])[0]
# fetch pong header
pongHeader = pong[0:8]
pongType, pongCode, pongChksum, pongID, pongSeqnr = \
struct.unpack("bbHHh", pongHeader)
# fetch starttime from pong
starttime = struct.unpack("d", pong[8:16])[0]
# IPv4
else:
# time to live
rawPongHop = struct.unpack("s", pong[8])[0]
# convert TTL from 8 bit to 16 bit integer
pongHop = int(binascii.hexlify(str(rawPongHop)), 16)
# fetch pong header
pongHeader = pong[20:28]
pongType, pongCode, pongChksum, pongID, pongSeqnr = \
struct.unpack("bbHHh", pongHeader)
# fetch starttime from pong
starttime = struct.unpack("d", pong[28:36])[0]
# valid ping packet received?
if not pongSeqnr == start:
pong = None
# NO data on socket - timeout waiting for answer
if not pong:
if alive:
print "no reply from %s (%s)" % (str(node), str(host))
else:
print "ping timeout: %s (icmp_seq=%d) " % (host, start)
# do not wait if just sending one packet
if number != 1 and start < number:
time.sleep(flood ^ 1)
start += 1
continue # lost a packet - try again
triptime = endtime - starttime # compute RRT
tsum += triptime # triptime for all packets (stddev)
tsumsq += triptime * triptime # triptime^2 for all packets (stddev)
# compute statistic
maxt = max ((triptime, maxt))
mint = min ((triptime, mint))
if alive:
print str(node) + " (" + str(host) +") is alive"
else:
if ipv6:
# size + 8 = payload + header
print "%d bytes from %s: icmp_seq=%d time=%.5f ms" % \
(size+8, host, pongSeqnr, triptime*1000)
else:
print "%d bytes from %s: icmp_seq=%d ttl=%s time=%.5f ms" % \
(size+8, host, pongSeqnr, pongHop, triptime*1000)
# do not wait if just sending one packet
if number != 1 and start < number:
# if flood = 1; do not sleep - just ping
time.sleep(flood ^ 1) # wait before send new packet
# the last thing to do is update the counter - else the value
# (can) get wrong when computing summary at the end (if user
# hit ctrl-c when pinging)
start += 1
# end ping send/recv while
# if user ctrl-d or ctrl-c
except (EOFError, KeyboardInterrupt):
# if user disrupts ping, it is most likly done before
# the counter get updates - if do not update it here, the
# summary get all wrong.
start += 1
pass
# compute and print som stats
# stddev computation based on ping.c from FreeBSD
if start != 0 or lost > 0: # do not print stats if 0 packet sent
start -= 1 # since while is ‘< ='
avg = tsum / start # avg round trip
vari = tsumsq / start - avg * avg
# %-packet lost
if start == lost:
plost = 100
else:
plost = (lost/start)*100
if not alive:
print "\n--- %s ping statistics ---" % node
print "%d packets transmitted, %d packets received, %d%% packet loss" % \
(start, start-lost, plost)
# don't display summary if 100% packet-loss
if plost != 100:
print "round-trip min/avg/max/stddev = %.3f/%.3f/%.3f/%.3f ms" % \
(mint*1000, (tsum/start)*1000, maxt*1000, math.sqrt(vari)*1000)
pingSocket.close()
def _error(err):
"""Exit if running standalone, else raise an exception
"""
if __name__ == '__main__':
print "%s: %s" % (os.path.basename(sys.argv[0]), str(err))
print "Try `%s --help' for more information." % os.path.basename(sys.argv[0])
sys.exit(1)
else:
raise Exception, str(err)
def _usage():
"""Print usage if run as a standalone program
"""
print """usage: %s [OPTIONS] HOST
Send ICMP ECHO_REQUEST packets to network hosts.
Mandatory arguments to long options are mandatory for short options too.
-c, --count=N Stop after sending (and receiving) 'N' ECHO_RESPONSE
packets.
-s, --size=S Specify the number of data bytes to be sent. The default
is 56, which translates into 64 ICMP data bytes when
combined with the 8 bytes of ICMP header data.
-f, --flood Flood ping. Outputs packets as fast as they come back. Use
with caution!
-6, --ipv6 Ping using IPv6.
-t, --timeout=s Specify a timeout, in seconds, before a ping packet is
considered 'lost'.
-h, --help Display this help and exit
Report bugs to lars [at] gnist org""" % os.path.basename(sys.argv[0])
if __name__ == '__main__':
"""Main loop
"""
# version control
version = string.split(string.split(sys.version)[0][:3], ".")
if map(int, version) < [2, 3]:
_error("You need Python ver 2.3 or higher to run!")
try:
# opts = arguments recognized,
# args = arguments NOT recognized (leftovers)
opts, args = getopt.getopt(sys.argv[1:-1], "hat:6c:fs:", \
["help", "alive", "timeout=", "ipv6", \
"count=", "flood", "packetsize="])
except getopt.GetoptError:
# print help information and exit:
_error("illegal option(s) -- " + str(sys.argv[1:]))
# test whether any host given
if len(sys.argv) >= 2:
node = sys.argv[-1:][0] # host to be pinged
if node[0] == ‘-’ or node == ‘-h’ or node == ‘–help’ :
_usage()
else:
_error(”No arguments given”)
if args:
_error(”illegal option — %s” % str(args))
# default variables
alive = 0; timeout = 1.0; ipv6 = 0; count = sys.maxint;
flood = 0; size = ICMP_DATA_STR
# run through arguments and set variables
for o, a in opts:
if o == “-h” or o == “–help”: # display help and exit
_usage()
sys.exit(0)
if o == “-t” or o == “–timeout”: # timeout before “lost”
try:
timeout = float(a)
except:
_error(”invalid timout: ‘%s’” % str(a))
if o == “-6″ or o == “–ipv6″: # ping ipv6
ipv6 = 1
if o == “-c” or o == “–count”: # how many pings?
try:
count = int(a)
except:
_error(”invalid count of packets to transmit: ‘%s’” % str(a))
if o == “-f” or o == “–flood”: # no delay between ping send
flood = 1
if o == “-s” or o == “–packetsize”: # set the ping payload size
try:
size = int(a)
except:
_error(”invalid packet size: ‘%s’” % str(a))
# just send one packet and say “it’s alive”
if o == “-a” or o == “–alive”:
alive = 1
# here we send
pingNode(alive=alive, timeout=timeout, ipv6=ipv6, number=count, \
node=node, flood=flood, size=size)
# if we made it this far, do a clean exit
sys.exit(0)
### end
在一个论坛上面看到有人说他把/bin/bash覆盖了,重启不能正常启动。hoho,启动脚本都是需要bash的,当然不能启动啦-_-#。给他回了个帖子,没有看到他说我的方法行不行。唉!早就料到是这样,所以我一般都不re贴的。
我尝试用Trustix 2.2重现一下他的问题,但是发现Trustix还是能够用root登录的。这也说明了Trustix的开发者考虑到了这个问题,root用户的shell是/sbin/bash,/bin/bash挂了,root还是可以登录。嗯…还是用我贴的那个办法来解决这个问题吧。
启动机器,出现Grub菜单的时候在菜单项上按’e',然后用方向键选上”kernel …”那一行,再按’e'。在后面加上” init=/bin/ash”(ash这个包一般都是安装了的,估计tcsh也可以吧,如果安装了的话),回车,按’b'启动。一会就可以看到’#'提示符啦。
mount /proc
mount / -o remount,rw
rpm -e bash --nodeps
mount /mnt/cdrom
rpm -ivh /mnt/cdrom/....../bash-xx.rpm
mount / -o remount,ro
/sbin/halt -p
按”Power”键吧,一切正常;-)
一台Linux的机器,在上面随意敲几下ps,居然出来一堆帮助信息。nnd,难道是我敲错了参数?再看,没错啊~~~再敲一遍,还是有问题。难道是……ps被替换了?rpm -qf /bin/ps,知道ps是procps包的。于是rpm -V procps,fk!果然是被人替换了,netstat也不能幸免。用find -ctime找了一下,发现/bin、/usr/bin下n多文件被改动过。把那些文件移动到一个新建的目录里面,从RH的ftp下载那些rpm包,rpm2cpio xxx.rpm | cpio -divm 把文件解出来,cp到相应的地方,但是rpm -V发现还是有问题:(。
受不了啦,嗯,机器上装了ClamAV,就用它scan一下吧。netstat: Linux.RST.B FOUND!汗!以前在某个BBS看到有人说装RH Linux的机器中了这个病毒,居然我也碰到了,运气不错啊。cp也染毒了,所以刚才cp过去的文件当然有问题啦。这个…怎么办呢?噢,/bin/mv还是可以用的,哈哈。经过一阵替换,OK。
netstat看一下,有几个陌生的端口。telnet看了一下,有一个是ssh后门吧。ps发现一个”smbd -D”的进程,这是有问题滴。
Google了一下,找到一些相关的东西。唉,日志都被删掉了,没意思啊。接着升级一下软件包、内核,hoho。
RSBAC(Rule Set Based Access Control)这东西看起来不错,但还没有用过,有空试试。
