Solved

Calling inline assembly directly

Posted on 2003-10-30
18
415 Views
Last Modified: 2012-06-27
Howdy,

Basically, I need a way to get the memory address of the first instruction in an __asm block.  Here's an example of what I'm talking about:

void ThisFunctionNeverGetsCalledDirectly()
{
  __asm
  {
     mov eax, 1
     add eax, 2
     jmp MEMADDRESS
  }
  printf("This never gets executed because the asm block jumps back to where it was called from");
}

Basically, at runtime I'm going to change the instruction at MEMADDRESS-1 to jmp to the first statement, "mov eax, 1"(obviously just a placeholder for now).  The rest of the asm block runs, then jmps back to MEMADDRESS and the program will proceed as normal.

The only problem is I need to find the address of that first instruction in order to make the jmp to it.  I don't want to call ThisFunctionNeverGetsCalledDirectly() because __asm modifies all the registers, the stack pointer,etc.  The point is I want the assembly code to execute seamlessly as though it actually existed between MEMADDRESS-1 and MEMADDRESS.

Thanks for the help.
0
Comment
Question by:aerelorn
  • 6
  • 4
  • 3
  • +3
18 Comments
 
LVL 48

Expert Comment

by:AlexFM
ID: 9648882
This is not fixed address, function is allocated on stack. Possibly this is [ESP], but all your idea looks strange, try to describe what you want to do. Maybe thete are another ways.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 9648892
Why don't you want to use label:

__asm
{
start:
    mov eax, 1
    add eax, 2
    jmp start
}
0
 
LVL 6

Expert Comment

by:GloomyFriar
ID: 9649223
HGLOBAL WINAPI MyGlobalAlloc(UINT uFlags, SIZE_T dwBytes)
{
    PDWORD pRetAddr = (PDWORD)((&pRetAddr) + 2);
    pRetAddr = (PDWORD)*pRetAddr;
}

pRetAddr is the return address.
But don't forget to clear the stack before jmp.
Some kind of protection code?
Good luck.
0
 
LVL 22

Accepted Solution

by:
grg99 earned 500 total points
ID: 9649769
Pls ignore all the valiant attempts above.  Try this:

void * ThisFunctionReturnsTheNumberYouWant()
{
  __asm
  {
    lea    eax,Here
    jmp  Ret

Here:
     mov eax, 1
     add eax, 2
     jmp MEMADDRESS

Ret:
  }
//  printf("This never gets executed because the asm block jumps back to where it was called from");
}

0
 
LVL 48

Expert Comment

by:AlexFM
ID: 9650018
Hi grg99,
I forgive you "the valiant attempts" and remind you again - take your points here:

http://oldlook.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_20766073.html

Good luck.
0
 
LVL 8

Expert Comment

by:Exceter
ID: 9650724
>> //  printf("This never gets executed because the asm block jumps back to where it was called from");

This would never get called anyway because it is commented out. :-)

Sorry grg99, I couldn't resist.
Exceter
0
 
LVL 22

Expert Comment

by:grg99
ID: 9650854
>Hi grg99,
>I forgive you "the valiant attempts" and remind you again - take your points here:

>http://oldlook.experts-exchange.com/Programming/Programming_Languages/Cplusplus/Q_20766073.html

>Good luck.

The EE user interface being like it is, I don't see any hint or button on that question that says "TAKE YOUR POINTS".
Also it's a bit curious why one would have to TAKE one's points.  You'd think that could be done automatically.


0
 
LVL 8

Expert Comment

by:Exceter
ID: 9650957
>> The EE user interface being like it is, I don't see any hint or button on that question that says "TAKE YOUR POINTS".

It says that in the question title.

>> Also it's a bit curious why one would have to TAKE one's points.  You'd think that could be done automatically.

I won't get into it here but, if you are interested, you can create a thread in referecne to this in the expert input TA.

Exceter
0
 
LVL 22

Expert Comment

by:grg99
ID: 9651090
>> The EE user interface being like it is, I don't see any hint or button on that question that says "TAKE YOUR POINTS".

>It says that in the question title.

I know it says that.... but HOW, Fawlty, HOW?  

I know, it was posted at the Town Hall, in the barricaded bathroom in the basement,
in the filing cabinet with "STAY OUT. RABID COUGAR" emblazened.

 

0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 
LVL 8

Expert Comment

by:Exceter
ID: 9651153
>> I know it says that.... but HOW, Fawlty, HOW?  

All you have to do is post. AlexFM will then accept your comment as the answer to the question. It's been standard proceedure around here for quite awhile.

Exceter
0
 
LVL 23

Expert Comment

by:brettmjohnson
ID: 9651639
void ThisFunctionNeverGetsCalledDirectly()
{
 __asm
 {
  Here:
    mov eax, 1
    add eax, 2
    lea ebx, Here
    jmp [ebx]
 }
 printf("This never gets executed because the asm block jumps back to where it was called from");
}
0
 

Author Comment

by:aerelorn
ID: 9651986
Okay, evidently I haven't explained this well enough.  I posted it right before I went to bed hoping to have an answer by morning, but I was too tired to be clear.  Please ignore everything I said above, it wouldn't work.

Here's what I'm starting with.  This is code in my executable.  The memory address(for this example 0040000) is found after my program loads:

00400000  MOV EAX,DWORD PTR SS:[ESP+2C]
00400004  ADD EAX,10h
00400007  PUSH EAX

What I want to do is execute a block of instructions seamlessly between the ADD and the PUSH.  I figured I could do this by overwriting the original instructions like so:


00400000  NOP
00400001  NOP
00400002  JMP SOMEMEMORYADDRESS
00400007  PUSH EAX

SOMEMEMORYADDRESS+0 MOV EAX,DWORD PTR SS:[ESP+2C]
SOMEMEMORYADDRESS+4 ADD EAX,10h
SOMEMEMORYADDRESS+7 Insert my code here
SOMEMEMORYADDRESS+X jmp 00400007


Right now the only way I can think to do this is to:

1. Reserve an area of memory for my custom code
2. Copy a hand-assembled version of the code to that location
3. Set the final instruction, "JMP 00400007" because 00400007 isn't known at compile time(like I thought when I initially posted)
4. Overwrite the original memory with the 2 NOP's and the JMP to the reserved mem area


That should work(if it won't, somebody please correct me).  The part I'm trying to avoid is the hand-assembled part.  I was hoping there's some way I can trick the compiler into doing it for me.

Hopefully this is a bit clearer.
0
 

Author Comment

by:aerelorn
ID: 9652193
I went and re-read the previous comments, and am thinking that the following modification of  grg99's code would work.  


void ThisFunctionReturnsTwoPointers(void* Begin, void* End)
{
  __asm
  {
    lea  Begin,BeginLabel
    lea  End,EndLabel
    jmp  Ret

BeginLabel:
     mov EAX,DWORD PTR SS:[ESP+2C]
     add EAX,10h
     mov eax, 1
     add eax, 2
     //more of my code here
EndLabel:

Ret:
  }
}


In my main program:

#define JMP 0xE9
#define NOP 0x90

DWORD ReturnAddress,Temp;
void* Mem,Begin,End;
DWORD Length;
BYTE jmp=JMP;
BYTE nop=NOP;

ReturnAddress = GetReturnAddress();              //this would be the 00400007 from above
ThisFunctionReturnsTwoPointers(Begin, End);       //gets begin and end of asm block
Length = (DWORD)Begin - (DWORD)End;
Mem = malloc(Length + 5);
CopyMemory(Mem, Begin, Length);              //copy the asm code to my reserved block
CopyMemory(Mem + Length, (void*)&jmp, 1);       //add the jmp code
CopyMemory(Mem + Length + 1, (void*)&ReturnAddress, 4); //add the jmp address

//change original code
CopyMemory((void*)(ReturnAddress - 7), (void*)&nop, 1);
CopyMemory((void*)(ReturnAddress - 6), (void*)&nop, 1);
CopyMemory((void*)(ReturnAddress - 5), (void*)&jmp, 1);
Temp=(DWORD)Begin;
CopyMemory((void*)(ReturnAddress - 4), (void*)&Temp, 4);



Could someone look over this and confirm that it would work and does what I want?
0
 

Author Comment

by:aerelorn
ID: 9654972
Okay, I was able to get a variant on what's above working.  Thanks grg99, I didn't know lea could be used on labels like that.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 9655844
grg99,

In the question you helped me I wrote: take your points here... and you could read this after receiving e-mail notification. Possibly you missed this e-mail or didn't read my comment. Usually this works without adding any special features to EE.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 9655870
By the way, I saved this page and will read it carefully to improve my rudimentary Assembly knowledge.
0
 

Author Comment

by:aerelorn
ID: 9655999
I'm not sure if you'll read this again AlexFM, but if you do here's the final version of the code so you can see how it all fit together:

#define JMP 0xE9
#define NOP 0x90
#define REPLACEADDR 0x0050D5DD
#define RETADDR 0x0050D5F6

void SetupFunction()
{
      DWORD BeginLabel,EndLabel;
      __asm
      {
            lea  eax,BeginLabel
            mov  Begin,eax
            lea  eax,EndLabel
            mov  End,eax
                jmp  EndLabel

            BeginLabel:
            mov eax,DWORD PTR SS:[ESP+0x2C]      
            add eax,10h
            //more of my code here
            nop  //placeholders for jmp
            nop  //placeholders for jmp
            nop  //placeholders for jmp
            nop  //placeholders for jmp
            nop  //placeholders for jmp
            EndLabel:
      }
      DWORD ReplaceAddr,RetAddr,Length;
      long Offset;
      BYTE jmp=JMP,nop=NOP;

      RetAddr=RETADDR;
      ReplaceAddr=REPLACEADDR;
      Length=End-Begin;

      hProcess=OpenProcess(PROCESS_ALL_ACCESS,false,hProcessId);

      Offset=RetAddr-(Begin+Length);
        //add jmp instruction
      WriteProcessMemory(hProcess,(void*)(Begin+Length-5),(void*)&jmp,sizeof(jmp),NULL);
       
       //add the jmp address
       WriteProcessMemory(hProcess,(void*)(Begin+Length-4),(void*)&Offset,sizeof(Offset),NULL);

      //change original code
      Offset=Begin-ReplaceAddr;
      WriteProcessMemory(hProcess,(void*)(ReplaceAddr-7),&nop,sizeof(nop),NULL);
      WriteProcessMemory(hProcess,(void*)(ReplaceAddr-6),&nop,sizeof(nop),NULL);
      WriteProcessMemory(hProcess,(void*)(ReplaceAddr-5),&jmp,sizeof(jmp),NULL);
      WriteProcessMemory(hProcess,(void*)(ReplaceAddr-4),&Offset,sizeof(Offset),NULL);
}

void ClearFunction()
{
      DWORD ReplaceAddr;
      ReplaceAddr=REPLACEADDR;
      WriteProcessMemory(hProcess,(void*)(ReplaceAddr-7),(void*)(Begin+1),7,NULL);
}

Cheers.
0
 
LVL 48

Expert Comment

by:AlexFM
ID: 9656045
Thanks.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The goal of the video will be to teach the user the difference and consequence of passing data by value vs passing data by reference in C++. An example of passing data by value as well as an example of passing data by reference will be be given. Bot…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

11 Experts available now in Live!

Get 1:1 Help Now