Add Windows Kernel structs#1219
Add Windows Kernel structs#1219HackingFrogWithSunglasses wants to merge 5 commits intoqilingframework:devfrom
Conversation
elicn
left a comment
There was a problem hiding this comment.
Thanks for the contribution.
As mentioned on the previous PR you opened, the additional structures are not defined in a correct way. Please see BaseStruct documentation and how other Windows structures are defined to get the idea.
qiling/loader/pe.py
Outdated
|
|
||
| from unicorn import UcError | ||
| from unicorn.x86_const import UC_X86_REG_CR4, UC_X86_REG_CR8 | ||
| from unicorn.x86_const import UC_X86_REG_CR4, UC_X86_REG_CR8, UC_X86_REG_GS |
There was a problem hiding this comment.
UC_X86_REG_GS is imported but never used.
There was a problem hiding this comment.
I think this should be used to write the kernel structures pointers to the GS register with their correct offset but I didn't manage to get it working so I wrote to the value manually.
| kpcr_obj.Prcb = kprcb_addr # Writes _KPRCB pointer to Prcb field | ||
|
|
||
| # Writes KPCR pointer into GS:[0x18] | ||
| self.ql.mem.write_ptr(0x6000018, kpcr_addr) |
There was a problem hiding this comment.
Please refrain from using magic numbers; there is a constant for GS that can be used.
There was a problem hiding this comment.
This is not a magic number. That is the exact offset for the KPRCB pointer in Windows KM. I agree that the constant + offset should be used, though.
| self.ql.mem.map(kthread_addr, self.ql.mem.align_up(kthread_struct.sizeof()), info='[kthread]') | ||
|
|
||
| # Initialize an instance with key fields | ||
| kthread_obj = kthread_struct.volatile_ref(self.ql.mem, kthread_addr) |
There was a problem hiding this comment.
This structure is initialized with magic numbers whose origin is unclear.
Is there a place [a Qilign object] we can take the values from? Consistency is key.
There was a problem hiding this comment.
I am not sure which numbers you're referring to are magic here.
There was a problem hiding this comment.
Oh if you mean the 0x188 for GS, then same as above. Should be changed to constant + offset
There was a problem hiding this comment.
I actually referred to the kthread_obj fields values: 11, 0x1000, 0x1500, 0x2000?
qiling/loader/pe.py
Outdated
| kthread_obj.InitialStack = 0x1000 | ||
| kthread_obj.StackBase = 0x1500 | ||
| kthread_obj.StackLimit = 0x2000 | ||
| kthread_obj.MiscFlags |= 0x400 |
There was a problem hiding this comment.
The value of MiscFlags is OR-ed with the existing one, but what is it...? That field was never initialized.
There was a problem hiding this comment.
MiscFlags can be removed in this instance, I was using this for my own purpose and it won't be useful for Qiling generically.
qiling/loader/pe.py
Outdated
| # Writes KPRCB pointer into GS:[0x20] | ||
| self.ql.mem.write_ptr(0x6000020, kprcb_addr) | ||
|
|
||
| # @NOTE: Tests for writing structure pointers. |
There was a problem hiding this comment.
What this is about? Why is it so important it shouldn't be removed?
Also, Qiling debugging info should be logged as debug rather than warn.
There was a problem hiding this comment.
You can remove these debug statements, I just had those there for my local branch and forgot to remove them when I submitted PR.
| ('NestingLevel', ctypes.c_char), | ||
| ('ClockOwner', ctypes.c_char), | ||
| ('PendingTickFlags', ctypes.c_char), | ||
| ('PendingTick', ctypes.c_void_p), # POS 0 : BIT 1 |
There was a problem hiding this comment.
This is not how bit fields are defined.
To keep it simple, just keep the encapsulating field and do not define bit fields.
| pointer_type = native_type | ||
|
|
||
| _fields_ = ( | ||
| ('MxCsr', ctypes.c_ulong), |
There was a problem hiding this comment.
From the same reason mentioned above (avoiding structures definitions getting affected by the hosting arch), we should use only known size types, like c_uint32 and c_uint16 instead of long and short.
qiling/profiles/windows.ql
Outdated
| @@ -1,13 +1,17 @@ | |||
| [OS64] | |||
| heap_address = 0x500000000 | |||
| heap_address = 0xfffff76000000000 | |||
There was a problem hiding this comment.
Is there any specific reason for this change?
There was a problem hiding this comment.
No specific reason relevant to Qiling. Was for my own testing purposes.
qiling/profiles/windows.ql
Outdated
| entry_point = 0x140000000 | ||
| # KI_USER_SHARED_DATA = 0xfffff78000000000 | ||
| KI_USER_SHARED_DATA = 0x7ffe0000 | ||
| KI_USER_SHARED_DATA = 0xfffff78000000000 |
There was a problem hiding this comment.
Is there any specific reason you removed the existing value and took the commented one?
Qiling doesn't have a concept of virtual and physical addresses, and this is the main reason why the value was changed in the first place.
There was a problem hiding this comment.
No specific reason, again for my own testing.
HackingFrogWithSunglasses
left a comment
There was a problem hiding this comment.
I agree with the requested changes.
qiling/os/windows/structs.py
Outdated
| # Cross Platform and Multi Architecture Advanced Binary Emulation Framework | ||
| # | ||
|
|
||
| from calendar import c |
There was a problem hiding this comment.
Agree, can be removed.
Apply fixes per discussion on PR.
Apply fixes per discussion on PR.
HackingFrogWithSunglasses
left a comment
There was a problem hiding this comment.
👍
qiling/os/windows/structs.py
Outdated
|
|
||
| from enum import IntEnum | ||
| from functools import lru_cache | ||
| from pickletools import uint1 |
There was a problem hiding this comment.
Agree, can be removed.
|
|
||
| return PEB | ||
|
|
||
| class NT_TIB(struct.BaseStruct): |
There was a problem hiding this comment.
The output is not needed but please be aware that with certain kernel structures you cannot just have a "link" to them because they are undocumented. In this case the output can be deleted though.
qiling/loader/pe.py
Outdated
|
|
||
| from unicorn import UcError | ||
| from unicorn.x86_const import UC_X86_REG_CR4, UC_X86_REG_CR8 | ||
| from unicorn.x86_const import UC_X86_REG_CR4, UC_X86_REG_CR8, UC_X86_REG_GS |
There was a problem hiding this comment.
I think this should be used to write the kernel structures pointers to the GS register with their correct offset but I didn't manage to get it working so I wrote to the value manually.
| self.ql.mem.map(kthread_addr, self.ql.mem.align_up(kthread_struct.sizeof()), info='[kthread]') | ||
|
|
||
| # Initialize an instance with key fields | ||
| kthread_obj = kthread_struct.volatile_ref(self.ql.mem, kthread_addr) |
There was a problem hiding this comment.
I am not sure which numbers you're referring to are magic here.
| self.ql.mem.map(kthread_addr, self.ql.mem.align_up(kthread_struct.sizeof()), info='[kthread]') | ||
|
|
||
| # Initialize an instance with key fields | ||
| kthread_obj = kthread_struct.volatile_ref(self.ql.mem, kthread_addr) |
There was a problem hiding this comment.
Oh if you mean the 0x188 for GS, then same as above. Should be changed to constant + offset
Apply fixes per discussion on PR.
Apply fixes per discussion on PR.
elicn
left a comment
There was a problem hiding this comment.
I took the liberty to edit some of the files and apply the fixes myself.
Also added a few responses.
| self.ql.mem.map(kthread_addr, self.ql.mem.align_up(kthread_struct.sizeof()), info='[kthread]') | ||
|
|
||
| # Initialize an instance with key fields | ||
| kthread_obj = kthread_struct.volatile_ref(self.ql.mem, kthread_addr) |
There was a problem hiding this comment.
I actually referred to the kthread_obj fields values: 11, 0x1000, 0x1500, 0x2000?
|
|
||
| return PEB | ||
|
|
||
| class NT_TIB(struct.BaseStruct): |
There was a problem hiding this comment.
Yes, I am aware.. if there is an unformal documentation you can link to, that's perfectly fine.
|
That's absolutely fine as I don't have time myself to maintain this. Thanks! |
As per #1217 this is the WIndows kernel structures PR
Checklist
Which kind of PR do you create?
Coding convention?
Extra tests?
Changelog?
Target branch?
One last thing