Page 1 of 3 123 LastLast
Results 1 to 15 of 42

Thread: reversing wmprph.exe - the wmp12 richpreviewhandler

  1. #1

    reversing wmprph.exe - the wmp12 richpreviewhandler

    Hi ...

    My knowledge is not that good to impliment the change that I want for this program.
    Mission is to find the background color used in this program, whick is quite difficult since there are two windows involved here (AtlAxWin, which hosts the skin inside wmploc.dll called RICHPREVIEW.WSZ) and uses COLOR_WINDOW as background color.

    This I changed this and it now returns COLOR_3DFACE.

    The other window (RPHInnerParent) uses CreateSolidBrush to obtain the Background Color, but using Syy++ from Microsoft it shows that it returns a different color each time a new window is created (but what is the reason for this ?).

    The Readingpane in my instance is colored to use ARGB(255, 214, 214, 214) via the msstyles skin which works fine while previewing photos since the color does not get painted over, like with the wmp12 previewhandler who paints it with it's own Brush.

    I can prevent it from painting the background by jumping over, but then when the previewpane is sized it does not redraw the color I have ARGB(255, 214, 214, 214) and the white background show again.

    The disassembly looks like this :
    I guess this is where the action is.

    -------------------------------------------------------------------------

    loc_1002D3B: ; color
    push dword ptr [esi+1Ch]
    call ds:CreateSolidBrush
    mov [esi+6Ch], eax
    mov esi, [esi+28h]
    test esi, esi
    jz short loc_1002D5C

    test eax, eax
    jz short loc_1002D5

    push eax ; dwNewLong
    push 0FFFFFFF6h ; nIndex
    push esi ; hWnd
    call ds:SetClassLongW

    --------------------------------------------------------------------------

    This question is probably more suited for a skinning forum but then again they don't discuss dissassebler stuff there

    If we can solve this here it would be great.
    I can post the changes i've made if that'll clarify the point i'm at now?

    Thanks
    Last edited by xplora; January 3rd, 2011 at 02:41.

  2. #2
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Posts
    4,106
    Blog Entries
    5
    Hi

    I don't quite understand what you're trying to do, but I'll hazard a guess - if you were to patch the CreateSolidBrush call to use your ARGB value, then SetClassLongW should set the new GCL_HBRBACKGROUND to your modified background brush and should be used for the class upon resizing.

    Unfortunately 'push dword ptr [esi+1Ch]' is a 3 byte opcode and the new 'push ARGB' would be 5 bytes, so it looks like you'd need a redirected patch.

    Is that about the extent of it?

    Kayaker

  3. #3
    Yes the Class I think for this window (the one with CreateSolidBrush) does not specify a BackGround Color (COLOR_WINDOW+1) like the other window. So it uses CreateSolidBrush.

  4. #4

    Changed the Class Background easily over here for the inner window.

    Name:  window.jpg
Views: 359
Size:  34.3 KB

    Name:  Register Class.jpg
Views: 362
Size:  24.1 KB

    Here are a grab of the window ReadingPane, that shows the two windows with different background colors.

    The outer obviously is the one that has to be changed.
    From W32Dasm the inner one was changed, but for the outer there
    is nothing in RegisterClass to change.

    CF 45 EC 06 00 00 00 -> CF 45 EC 10 00 00 00
    I changed the 06 (COLOR_WINDOW) to 10 (COLOR_3DFACE).
    Last edited by xplora; January 3rd, 2011 at 04:04.

  5. #5

    Grab of W32Dasm with RegisterClass for Outer Window.

    Name:  W32Dasm2.jpg
Views: 359
Size:  41.6 KB

    All dword pointers ...

  6. #6
    Quote Originally Posted by xplora View Post
    Name:  W32Dasm2.jpg
Views: 359
Size:  41.6 KB

    All dword pointers ...
    If I insert my code in here and do a jump at the CreateSolidBrush call, it may work I think ...

  7. #7

    I need more info first ...

    Yeah i'm in way over my head with this one. Not sure this is ever going to work.
    Kayaker, you're right, but I do not have the knowledge to apply a redirected patch.
    Everytime th window needs to br updated it Calls CreateSolidBrush and it seems that
    brush is never the same - weird!

  8. #8

    Background of Window

    If only every program was as easy as this (sample program):

    in code:
    wcex.hbrBackground = (HBRUSH)(COLOR_3DFACE+1);

    in binary:
    :004019CB C744242C10000000 mov [esp+2C], 00000010

    But in wmprph.exe the wcex.hbrBackground is disabled according to IDA.
    Instead they created a SolidBrush and put it in a class.

    So i'm still looking to find out where to change that color (which is white).
    I can manage to change it to Black, but that's not nice.
    Also manage it to not Paint any color, but wthen the windows is resized,
    the color does not get updated and the white again shows.

    -----------------------------------------------------------------------
    wmprph.exe :
    I don't see anything about *wcex.hbrBackground* here?
    ----------------------------------------------------------------------

    * Reference To: USER32.GetClassInfoExW, Ord:010Dh
    |
    :0100291D FF1548120001 Call dword ptr [01001248]
    :01002923 85C0 test eax, eax
    :01002925 7563 jne 0100298A
    :01002927 A168120001 mov eax, dword ptr [01001268]
    :0100292C 68007F0000 push 00007F00
    :01002931 56 push esi
    :01002932 C745CC30000000 mov [ebp-34], 00000030
    :01002939 C745D003000000 mov [ebp-30], 00000003
    :01002940 8945D4 mov dword ptr [ebp-2C], eax
    :01002943 8975D8 mov dword ptr [ebp-28], esi
    :01002946 8975DC mov dword ptr [ebp-24], esi
    :01002949 895DE0 mov dword ptr [ebp-20], ebx
    :0100294C 8975E4 mov dword ptr [ebp-1C], esi

    * Reference To: USER32.LoadCursorW, Ord:01EBh
    |
    :0100294F FF154C120001 Call dword ptr [0100124C]
    :01002955 8945E8 mov dword ptr [ebp-18], eax
    :01002958 8D45CC lea eax, dword ptr [ebp-34]
    :0100295B 50 push eax
    :0100295C 8975EC mov dword ptr [ebp-14], esi
    :0100295F 8975F0 mov dword ptr [ebp-10], esi
    :01002962 897DF4 mov dword ptr [ebp-0C], edi
    :01002965 8975F8 mov dword ptr [ebp-08], esi

    * Reference To: USER32.RegisterClassExW, Ord:024Dh
    |
    :01002968 FF1550120001 Call dword ptr [01001250]
    :0100296E 6685C0 test ax, ax
    :01002971 7517 jne 0100298A

    -----------------------------------------------------------------------
    CreateSolidBrush :
    -----------------------------------------------------------------------

    * Reference To: GDI32.CreateSolidBrush, Ord:0054h
    |
    :01002D3E FF1560100001 Call dword ptr [01001060]
    :01002D44 89466C mov dword ptr [esi+6C], eax
    :01002D47 8B7628 mov esi, dword ptr [esi+28]
    :01002D4A 85F6 test esi, esi
    :01002D4C 740E je 01002D5C
    :01002D4E 85C0 test eax, eax
    :01002D50 740A je 01002D5C
    :01002D52 50 push eax
    :01002D53 6AF6 push FFFFFFF6
    :01002D55 56 push esi

    ----------------------------------------------------------------------

  9. #9
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Posts
    4,106
    Blog Entries
    5
    I still think you need to inject your own code to replace the parameter value pushed to CreateSolidBrush to the one you want.

    Google for "code cave" or "Inject code + Notepad" or anything similar to learn about the technique. The concept is simple enough, you need to find a location somewhere close to the CreateSolidBrush call that you can overwrite with a jump to a "code cave" (an unused block of bytes often found at the end of a code section), or create a completely new section in which to write your code.

    You then replace the bytes you overwrote so that code still executes, create the new parameter (push ARGB(255, 214, 214, 214)), and jump immediately back to call ds:CreateSolidBrush. The original 'push dword ptr [esi+1Ch]' of CreateSolidBrush is therefore never used.


    The following is a handy utility for this, but can be done with other tools as well.

    http://www.woodmann.com/collaborative/tools/index.php/Code_Snippet_Creator_(Iczelion)


    Look into that and come back if you have problems.

  10. #10
    That sounds like the best thing to do, I think I can handle it, thanks Kayaker ...
    Going to look into it

  11. #11
    Quote Originally Posted by Kayaker View Post
    I still think you need to inject your own code to replace the parameter value pushed to CreateSolidBrush to the one you want.

    Google for "code cave" or "Inject code + Notepad" or anything similar to learn about the technique. The concept is simple enough, you need to find a location somewhere close to the CreateSolidBrush call that you can overwrite with a jump to a "code cave" (an unused block of bytes often found at the end of a code section), or create a completely new section in which to write your code.

    You then replace the bytes you overwrote so that code still executes, create the new parameter (push ARGB(255, 214, 214, 214)), and jump immediately back to call ds:CreateSolidBrush. The original 'push dword ptr [esi+1Ch]' of CreateSolidBrush is therefore never used.


    The following is a handy utility for this, but can be done with other tools as well.

    http://www.woodmann.com/collaborative/tools/index.php/Code_Snippet_Creator_(Iczelion)


    Look into that and come back if you have problems.
    I'll be using this code:
    "invoke CreateSolidBrush,00FF8888h"
    Is this the correct way?

    I'm going to try the notepad tutorial first, just to get the feel for it,
    since i'm not getting the jumps right.

    thanks.

  12. #12
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Posts
    4,106
    Blog Entries
    5
    Quote Originally Posted by xplora View Post
    I'll be using this code:
    "invoke CreateSolidBrush,00FF8888h"
    Is this the correct way?
    You could do that, but then you'd have to return to the instruction *after* the original CreateSolidBrush call. There's really no need to use the full invoke when all you're doing is changing the one parameter.

    I think you'd only need something like this.

    Code:
    pushad
    pushfd
    
    // execute overwritten instructions where you patched in the jump
    // and any other code that needs to run
    
    push 00FF8888h
    
    popfd
    popad
    
    jmp to original call ds:CreateSolidBrush

    Note the bracketing push*/pop* instructions. Not strictly necessary with this simple patch, but it's usually a good idea to preserve the original registers and perhaps the flags within your patch (unless of course they *need* to contain new values for subsequent code to execute correctly).

    Note something else here, if you used the full invoke CreateSolidBrush in the patch, you'd also have to execute the mov [esi+6Ch], eax instruction to save the return value from within the patch, and then return to the original code at the instruction following that one.
    Why?
    Because the popad I suggested using at the end of the patch would restore the old eax before the new return value was saved... gotta be careful


    I don't know what the rest of the code looks like or where a good spot is to overwrite with the jump to your patch. Perhaps it might be easier to directly modify the value of [esi+1Ch] at an earlier point and just let the original 'push dword ptr [esi+1Ch]' instruction execute. Whatever works best.

    You should make sure that the CreateSolidBrush/SetClassLongW sequence is *only* being used by the window you want to affect. If it's used in a more global scope then you'll have to the check which hWnd is being handled and set an appropriate IF condition.

  13. #13
    Administrator dELTA's Avatar
    Join Date
    Oct 2000
    Location
    Ring -1
    Posts
    4,206
    Blog Entries
    5
    Quote Originally Posted by Kayaker View Post
    Code:
    pushad
    pushfd
    
    // execute overwritten instructions where you patched in the jump
    // and any other code that needs to run
    
    push 00FF8888h
    
    popfd
    popad
    
    jmp to original call ds:CreateSolidBrush
    I might absolutely have missed something completely here, but won't the push/pop sequence before the jump above just corrupt all registers and leave the first (or last, depending on how you see it) four bytes of data produced by the pushad instruction on the stack (thus becoming the value of the crColor parameter to the CreateSolidBrush function)?
    "Give a man a quote from the FAQ, and he'll ignore it. Print the FAQ, shove it up his ass, kick him in the balls, DDoS his ass and kick/ban him, and the point usually gets through eventually."

  14. #14
    |< x != '+' BanMe's Avatar
    Join Date
    Oct 2008
    Location
    Farmington NH
    Posts
    510
    Blog Entries
    4
    Actually the state of execution wouldnt be preserved by those pushes and pops,you are correct.

    code should be if executed just prior to call which is the most convient method.
    Code:
    ..somecode i cant see from example here..
    pop eax;get old color off of stack ?
    push 00FF8888h;
    jmp CallToCreateSolidBrush
    In the code above only ebp is modified.

    If done as xplora suggests after the call this makes the code alot different and provides me a better example to give..
    so after the call you have code like this.
    Code:
    :01002D44 89466C mov dword ptr [esi+6C], eax
    :01002D47 8B7628 mov esi, dword ptr [esi+28]
    you need 5 of those byte to overwrite with your jump to your code to change color. so you have to write that and nop the remaining bytes.

    So in the hook code you would have to duplicate those instructions and return just after your jmp.
    that code 'should' look like this:

    Code:
    pushad
    pushfd
    mov eax,[ebp+4];that pop would cause same effect you described o0.
    push eax
    call DeleteObject
    popad;restores eax to old handle
    popfd;restores any flags set in deleteobject
    push 00FF8888h
    call CreateSolidBrush
    mov dword ptr [esi+6C], eax
    mov esi, dword ptr [esi+28]
    jmp HookLocation+5(if u nopped it + 6 if not..)
    Now I think that is what Kayaker was thinking.. :d

    regards BanMe
    Last edited by BanMe; January 10th, 2011 at 21:09.
    No hate for the lost children;
    more love for the paths we walk,
    'words' shatter the truth we seek.
    from the heart and mind of Me
    me, to you.. down and across

    No more words from me, to you...
    Hate and love shatter the heart and Mind of Me.
    For the Lost Children;For the paths we walk; the real truth we seek!

  15. #15
    Administrator dELTA's Avatar
    Join Date
    Oct 2000
    Location
    Ring -1
    Posts
    4,206
    Blog Entries
    5
    Quote Originally Posted by BanMe View Post
    Actually the state of execution is preserved by those pushes and pops.
    Though they are not 'needed' if you are not modifying any registers or 'flags' with your code, though it is good practice to preserve the state of execution in injected code.
    Yes, I know what the instructions do. What I am referring to is the fact that the stack is not balanced within the injected code ("push 00FF8888h") before attempting to restore the system state from the stack again, and thus, you restore the wrong data, which in effect rather means corrupting the contents of all registers, and the parameter that you tried to modify in the first place.

    If the injected patch would leave the stack balanced, I would absolutely not have any objection, but this injected code doesn't, and thus you'd have to make a call to the function before the popfd/popad sequence in this injected code, right? This would of course in turn mean that you eradicate all register modifications that the called function might perform as part of its intended functionality, so no go there either really.

    So the solution is to either leave out the register preserving push/pop sequences completely, or to analyze the called function code to see which registers and flags it modifies, and restore all but these, but then you have at the same time eliminated the need for the restoration, since in this analysis you will also see that your own patch code does not modify any of them to begin with.

    Damn Kayaker, always trying to mock newbies by fooling them into doing the wrong things, all under the impression of just being a really helpful guy...
    "Give a man a quote from the FAQ, and he'll ignore it. Print the FAQ, shove it up his ass, kick him in the balls, DDoS his ass and kick/ban him, and the point usually gets through eventually."

Similar Threads

  1. OSX reversing
    By 0xf001 in forum Off Topic
    Replies: 9
    Last Post: August 25th, 2008, 18:14
  2. VM reversing
    By b3n in forum The Newbie Forum
    Replies: 20
    Last Post: August 16th, 2007, 09:51
  3. CGI reversing?
    By MalcolmXXX in forum Advanced Reversing and Programming
    Replies: 5
    Last Post: December 17th, 2003, 03:09
  4. IDA Pro reversing
    By Appendix in forum Advanced Reversing and Programming
    Replies: 1
    Last Post: April 30th, 2001, 16:55
  5. MFC reversing
    By Subaru in forum Advanced Reversing and Programming
    Replies: 3
    Last Post: January 1st, 2001, 14:32

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •