第五部分了 空指针解引用是程序中常见的一类动态内存错误 啊 还是直接开始正文吧
当指针设置为NULL时 试图通过空指针对数据进行访问 导致程序运行错误 即指针为空却被当作地址去引用时 就会产生漏洞
这个函数首先ExAllocatePoolWithTag申请内存 在用完内存后 将内存置为NULL 在漏洞版本下 未检查刚才申请的内存是否为NULL 就直接引用指向内存地址
TriggerNullPointerDereference
先下断点
断下后发现第二个值还没有被覆盖为shellcode的地址
单步指向后发现已被覆盖
即我们将NullPointerDereference的第二个值(+0x4)控制为shellcode的地址即可 使用NtAllocateVirtualMemory分配0页内存将第二个值(+0x4)控制为shellcode的地址
在common.c中分配0页内存
利用成功
啊这个比上个好理解多了 空指针解引用导致的问题在这个漏洞中也很好利用 在刚开始了解的时候只知道能引发崩溃 不知道如何去利用 后面学习完了之后也就懂了利用的思路了 然后去看了看小刀师傅复现的一个内核漏洞 完全就不一样了哈哈哈
这里传送门
NTSTATUS
TriggerNullPointerDereference(
_In_ PVOID UserBuffer
)
{
ULONG UserValue
=
0
;
ULONG MagicValue
=
0xBAD0B0B0
;
NTSTATUS Status
=
STATUS_SUCCESS;
PNULL_POINTER_DEREFERENCE NullPointerDereference
=
NULL;
PAGED_CODE();
__try
{
/
/
/
/
Verify
if
the
buffer
resides
in
user mode
/
/
ProbeForRead(UserBuffer, sizeof(NULL_POINTER_DEREFERENCE), (ULONG)__alignof(UCHAR));
/
/
/
/
Allocate Pool chunk
/
/
NullPointerDereference
=
(PNULL_POINTER_DEREFERENCE)ExAllocatePoolWithTag(
NonPagedPool,
sizeof(NULL_POINTER_DEREFERENCE),
(ULONG)POOL_TAG
);
if
(!NullPointerDereference)
{
/
/
/
/
Unable to allocate Pool chunk
/
/
DbgPrint(
"[-] Unable to allocate Pool chunk\n"
);
Status
=
STATUS_NO_MEMORY;
return
Status;
}
else
{
DbgPrint(
"[+] Pool Tag: %s\n"
, STRINGIFY(POOL_TAG));
DbgPrint(
"[+] Pool Type: %s\n"
, STRINGIFY(NonPagedPool));
DbgPrint(
"[+] Pool Size: 0x%X\n"
, sizeof(NULL_POINTER_DEREFERENCE));
DbgPrint(
"[+] Pool Chunk: 0x%p\n"
, NullPointerDereference);
}
/
/
/
/
Get the value
from
user mode
/
/
UserValue
=
*
(PULONG)UserBuffer;
DbgPrint(
"[+] UserValue: 0x%p\n"
, UserValue);
DbgPrint(
"[+] NullPointerDereference: 0x%p\n"
, NullPointerDereference);
/
/
/
/
Validate the magic value
/
/
if
(UserValue
=
=
MagicValue)
{
NullPointerDereference
-
>Value
=
UserValue;
NullPointerDereference
-
>Callback
=
&NullPointerDereferenceObjectCallback;
DbgPrint(
"[+] NullPointerDereference->Value: 0x%p\n"
, NullPointerDereference
-
>Value);
DbgPrint(
"[+] NullPointerDereference->Callback: 0x%p\n"
, NullPointerDereference
-
>Callback);
}
else
{
DbgPrint(
"[+] Freeing NullPointerDereference Object\n"
);
DbgPrint(
"[+] Pool Tag: %s\n"
, STRINGIFY(POOL_TAG));
DbgPrint(
"[+] Pool Chunk: 0x%p\n"
, NullPointerDereference);
/
/
/
/
Free the allocated Pool chunk
/
/
ExFreePoolWithTag((PVOID)NullPointerDereference, (ULONG)POOL_TAG);
/
/
/
/
Set
to NULL to avoid dangling pointer
/
/
NullPointerDereference
=
NULL;
}
/
/
/
/
Secure Note: This
is
secure because the developer
is
checking
if
/
/
'NullPointerDereference'
is
not
NULL before calling the callback function
/
/
if
(NullPointerDereference)
{
NullPointerDereference
-
>Callback();
}
DbgPrint(
"[+] Triggering Null Pointer Dereference\n"
);
/
/
/
/
Vulnerability Note: This
is
a vanilla Null Pointer Dereference vulnerability
/
/
because the developer
is
not
validating
if
'NullPointerDereference'
is
NULL
/
/
before calling the callback function
/
/
NullPointerDereference
-
>Callback();
/
/
漏洞点
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
Status
=
GetExceptionCode();
DbgPrint(
"[-] Exception Code: 0x%X\n"
, Status);
}
return
Status;
}
NTSTATUS
TriggerNullPointerDereference(
_In_ PVOID UserBuffer
)
{
ULONG UserValue
=
0
;
ULONG MagicValue
=
0xBAD0B0B0
;
NTSTATUS Status
=
STATUS_SUCCESS;
PNULL_POINTER_DEREFERENCE NullPointerDereference
=
NULL;
PAGED_CODE();
__try
{
/
/
/
/
Verify
if
the
buffer
resides
in
user mode
/
/
ProbeForRead(UserBuffer, sizeof(NULL_POINTER_DEREFERENCE), (ULONG)__alignof(UCHAR));
/
/
/
/
Allocate Pool chunk
/
/
NullPointerDereference
=
(PNULL_POINTER_DEREFERENCE)ExAllocatePoolWithTag(
NonPagedPool,
sizeof(NULL_POINTER_DEREFERENCE),
(ULONG)POOL_TAG
);
if
(!NullPointerDereference)
{
/
/
/
/
Unable to allocate Pool chunk
/
/
DbgPrint(
"[-] Unable to allocate Pool chunk\n"
);
Status
=
STATUS_NO_MEMORY;
return
Status;
}
else
{
DbgPrint(
"[+] Pool Tag: %s\n"
, STRINGIFY(POOL_TAG));
DbgPrint(
"[+] Pool Type: %s\n"
, STRINGIFY(NonPagedPool));
DbgPrint(
"[+] Pool Size: 0x%X\n"
, sizeof(NULL_POINTER_DEREFERENCE));
DbgPrint(
"[+] Pool Chunk: 0x%p\n"
, NullPointerDereference);
}
/
/
/
/
Get the value
from
user mode
/
/
UserValue
=
*
(PULONG)UserBuffer;
DbgPrint(
"[+] UserValue: 0x%p\n"
, UserValue);
DbgPrint(
"[+] NullPointerDereference: 0x%p\n"
, NullPointerDereference);
/
/
/
/
Validate the magic value
/
/
if
(UserValue
=
=
MagicValue)
{
NullPointerDereference
-
>Value
=
UserValue;
NullPointerDereference
-
>Callback
=
&NullPointerDereferenceObjectCallback;
DbgPrint(
"[+] NullPointerDereference->Value: 0x%p\n"
, NullPointerDereference
-
>Value);
DbgPrint(
"[+] NullPointerDereference->Callback: 0x%p\n"
, NullPointerDereference
-
>Callback);
}
else
{
DbgPrint(
"[+] Freeing NullPointerDereference Object\n"
);
DbgPrint(
"[+] Pool Tag: %s\n"
, STRINGIFY(POOL_TAG));
DbgPrint(
"[+] Pool Chunk: 0x%p\n"
, NullPointerDereference);
/
/
/
/
Free the allocated Pool chunk
/
/
ExFreePoolWithTag((PVOID)NullPointerDereference, (ULONG)POOL_TAG);
/
/
/
/
Set
to NULL to avoid dangling pointer
/
/
NullPointerDereference
=
NULL;
}
/
/
/
/
Secure Note: This
is
secure because the developer
is
checking
if
/
/
'NullPointerDereference'
is
not
NULL before calling the callback function
/
/
if
(NullPointerDereference)
{
NullPointerDereference
-
>Callback();
}
DbgPrint(
"[+] Triggering Null Pointer Dereference\n"
);
/
/
/
/
Vulnerability Note: This
is
a vanilla Null Pointer Dereference vulnerability
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2020-11-4 21:09
被Ring3编辑
,原因: