flat assembler
Message board for the users of flat assembler.

Index > Windows > very basic thunk - does not work on x64

Author
Thread Post new topic Reply to topic
wisepenguin



Joined: 30 Mar 2005
Posts: 129
wisepenguin 28 Mar 2009, 13:53
hello,
as an exercise i thought i would try and see if i can create a simple Thread class, with the ThreadProc as the member function - using a thunk. But now I have windows xp 64, i thought i would update my ancient code to help me learn x86-64 assembly.

the problem is my code works on windows xp32, but not on windows xp x64, and i do not understand why.

i have simplified down the code as much as possible and removed the class to show a minimal not working program. this is not for production code, just an exercise to help me learn.

the code below is trying to dynamically generate some code which calls a user defined function - ThreadProc in this example. I have removed all of the thunking code to try and get a minimal "broken" example.

i checked the intel/amd 64 manuals prior to this for each instruction and believe i am ok with using a 64bit destination - i would be grateful if anybody can point out any errors that i am making or solutions.

Code:
#include <windows.h>
#include <stdio.h>

// http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q127904&

typedef DWORD (WINAPI *AllocatedCode)(LPVOID param);

DWORD WINAPI ThreadProc(LPVOID param)
{
 printf("ThreadProc\n");
  return 0;
}

int main()
{
     DWORD oldProtection = NULL;
 LPVOID pCodeBase = VirtualAlloc(NULL, 64, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
      VirtualProtect(pCodeBase, 64, PAGE_WRITECOPY, &oldProtection);
  
#ifdef _M_AMD64
 // mov rax, 1234567890abcdefh
       // jmp rax
  BYTE* pCodeBaseByte = (BYTE*) pCodeBase;
    BYTE* pMovByte = pCodeBaseByte;
     WORD* pMov = (WORD*) pMovByte;
      
    BYTE* pDestinationByte = pCodeBaseByte + 2;
 DWORD_PTR* pDestination = (DWORD_PTR*) pDestinationByte;
    
    BYTE* pJmpByte = pCodeBaseByte + 10;
        WORD* pJmp = (WORD*) pJmpByte;
      
    *pMov = 0x48b8;
     *pDestination = (DWORD_PTR) & ThreadProc;
       *pJmp = 0xe0ff;
#else
    // mov eax, 12345678h
       // jmp eax
  BYTE* pCodeBaseByte = (BYTE*) pCodeBase;
    BYTE* pMov = pCodeBaseByte;
 
    BYTE* pDestinationByte = pCodeBaseByte + 1;
 DWORD_PTR* pDestination = (DWORD_PTR*) pDestinationByte;
    
    BYTE* pJmpByte = pCodeBaseByte + 5;
 WORD* pJmp = (WORD*) pJmpByte;
      
    *pMov = 0xb8;
       *pDestination = (DWORD_PTR) & ThreadProc;
       *pJmp = 0xe0ff;
#endif
   VirtualProtect(pCodeBase, 64, PAGE_EXECUTE_READWRITE, &oldProtection);
  FlushInstructionCache(GetCurrentProcess(), pCodeBase, 64);
  
    AllocatedCode allocatedCode = (AllocatedCode) pCodeBase;
    allocatedCode((LPVOID)1956);
        
    getchar();
  
    VirtualFree(pCodeBase, 0, MEM_RELEASE);
     
    return 0;
}
    


thanks for your time. have a good day
Post 28 Mar 2009, 13:53
View user's profile Send private message Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20448
Location: In your JS exploiting you and your system
revolution 28 Mar 2009, 14:03
And this is assembly related somehow?

Perhaps you meant to post in the heap?
Post 28 Mar 2009, 14:03
View user's profile Send private message Visit poster's website Reply with quote
wisepenguin



Joined: 30 Mar 2005
Posts: 129
wisepenguin 28 Mar 2009, 14:17
hello,
i will surely move it to the heap if thats the best place for it, but i thought the thunk code would classify it as assembly.

thanks
Post 28 Mar 2009, 14:17
View user's profile Send private message Reply with quote
comrade



Joined: 16 Jun 2003
Posts: 1150
Location: Russian Federation
comrade 29 Mar 2009, 03:06
This is assembly rleated because he is injected instructions into the program.

Those instructions are x86 instructions - the encodings on x86-64 are slightly different and mean different things.
Post 29 Mar 2009, 03:06
View user's profile Send private message Visit poster's website AIM Address Yahoo Messenger MSN Messenger ICQ Number Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20448
Location: In your JS exploiting you and your system
revolution 29 Mar 2009, 04:41
comrade wrote:
This is assembly rleated because he is injected instructions into the program.

Those instructions are x86 instructions - the encodings on x86-64 are slightly different and mean different things.
That is not a very convincing argument. Pushing hex codes around is not assembly. Working with mnemonics and converting source code into binary is assembly.
Post 29 Mar 2009, 04:41
View user's profile Send private message Visit poster's website Reply with quote
wisepenguin



Joined: 30 Mar 2005
Posts: 129
wisepenguin 29 Mar 2009, 09:25
hello,
if a mod doesn't mind would they be able to move this to the heap, as heap may be a better place for this code ?

i compiled the code with fasm 1.67.36 - using use32 for x86, and use64 for the x64 code. the code is in the comments above but i used

Code:
use64
mov rax, 1234567890abcdefh
jmp rax    


for the 64bit version.

i had a fresh look this morning and to my relief i have got the code working - although im quite ashamed i made such an obvious mistake.

the byte order of the mov instruction was the wrong way around - i had the x64 prefix 2nd. the fix is

Code:
*pMov = 0xb848;    


with this now working, hopefully i can get the full thread class thunk working and be on my way to learning more about x64 architecture.

have a good day

ps. offtopic. comrade i liked your vc6 page. i too use vc6 to this day and much prefer it - its great. i also like the simple hex editor within it. i use vc6 on windows xp64.
Post 29 Mar 2009, 09:25
View user's profile Send private message Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 29 Mar 2009, 09:26
Quote:
Pushing hex codes around is not assembly. Working with mnemonics and converting source code into binary is assembly.

If that is your definition of "assembly", and this board should (except for Heap) should be assembly only, then it would be very limited scope.
Post 29 Mar 2009, 09:26
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20448
Location: In your JS exploiting you and your system
revolution 29 Mar 2009, 10:30
vid wrote:
Quote:
Pushing hex codes around is not assembly. Working with mnemonics and converting source code into binary is assembly.

If that is your definition of "assembly", and this board should (except for Heap) should be assembly only, then it would be very limited scope.
Do you really consider something like that above assembly? In my mind it is C with some hex constants. No disrespect to the original poster but there is no assembly code happening in there, sorry but it just does not fit my idea of assembly.

Now if there was some sort of _asm section (like some compilers support) with some assembly code being assembled then that would be different. Or even a separate assembly file that produces the hex codes (could be with display or something similar) then that would also be assembly.
Post 29 Mar 2009, 10:30
View user's profile Send private message Visit poster's website Reply with quote
vid
Verbosity in development


Joined: 05 Sep 2003
Posts: 7105
Location: Slovakia
vid 29 Mar 2009, 12:36
revolution: In my opinion, run-time generation of opcodes is related to assembly enough to remain here.

Wisepenguin: why don't you try using debugger and trace the code to see what fails? FDBG should work for you,
Post 29 Mar 2009, 12:36
View user's profile Send private message Visit poster's website AIM Address MSN Messenger ICQ Number Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 29 Mar 2009, 12:42
vid wrote:
revolution: In my opinion, run-time generation of opcodes is related to assembly enough to remain here.

I support this point of view. Initially this forum was intended to be fasm-only, but now I think it's better for us to allow more wide machine-code related topics.
Post 29 Mar 2009, 12:42
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 20448
Location: In your JS exploiting you and your system
revolution 29 Mar 2009, 13:00
Hehe, okay I am overpowered by you two. I shall take my tail and put it between my legs and turn around.
Post 29 Mar 2009, 13:00
View user's profile Send private message Visit poster's website Reply with quote
wisepenguin



Joined: 30 Mar 2005
Posts: 129
wisepenguin 29 Mar 2009, 13:26
hi vid,
wow - what a useful project. i simply didn't know or quite possibly forgot about FDBG. i ended up using NTSD all yesterday and stepping through it but was too blind to notice the error.

however, this morning with fresh eyes i noticed the error was that i mixed up the byte order for the mov instruction and prefix. the correction is posted a few replies above.

a big thanks to all of the FDBG contributors, and Tomasz for FASM.
Post 29 Mar 2009, 13:26
View user's profile Send private message Reply with quote
ramguru



Joined: 26 Feb 2005
Posts: 19
Location: who cares...
ramguru 20 Jul 2009, 11:13
not so long time ago I've converted this thunk code to assembly in x64bit code:

Code:
struct HM
 hWnd dq ? ; handle of control
..
ends

struct WndProcThunk
      RcxMov dw ?        ; mov rcx, pThis
 RcxImm dq ?        ; 
       RaxMov dw ?        ; mov rax, target
        RaxImm dq ?        ; 
       RaxJmp dw ?        ; jmp rax
ends

proc DummyProc uses rsi, hWin, uMsg, wParam, lParam

 mov    [hWin], rcx
  mov    [uMsg], rdx
  mov    [wParam], r8
 mov    [lParam], r9
    
 ; allocate two structures for saving unique properties
      mov    r10, sizeof.HM           ; control properties
        add    r10, sizeof.WndProcThunk ; thunk code

    invoke VirtualAlloc, 0, r10, MEM_COMMIT, PAGE_EXECUTE_READWRITE
    
     mov    rcx, [hWin]
  mov    [HM.hWnd + rax], rcx

     mov    rsi, rax
     add    rsi, sizeof.HM
    
       mov    rcx, ContolProc  
    
    mov    WORD [rsi +0], 0B948h
        mov    [rsi +2], rax
        mov    WORD [rsi+10], 0B848h
        mov    [rsi+12], rcx
        mov    WORD [rsi+20], 0E0FFh
        
    invoke SetWindowLongPtr, [hWin], GWL_WNDPROC, rsi

       mov    r9,      [lParam]
    mov    r8,      [wParam]
    mov    rdx,     [uMsg]
      mov    rcx,     [hWin]
      call   rsi
  
    ret

endp

proc ControlProc hWin, uMsg, wParam, lParam
  
    mov    rbx, rcx
     ; now --> QWORD [HM.hwnd + rbx] - real control handle

endp
    
Post 20 Jul 2009, 11:13
View user's profile Send private message Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.