Link to home
Start Free TrialLog in
Avatar of eleigh
eleigh

asked on

Accessing program counter / instruction pointer

How does one transfer the program counter / instruction pointer to a variable in C++?

I want to be able to:
1) obtain the current execution address
2) pass that address to another function (f)
3) in function (f), check the integrity of the calling function's code and/or modify it

This seems to require at least some assembly code. I presume that I could check the actual addresses in question in a disassembler and hard-code them into my program, but that would be tedious.

Relatedly:
1) How to obtain the start address of a function?
2) How to obtain the address of a label?

In C++ (VC5) I always get the error: 'illegal operation on bound member function expression' when I try to take the address of a function.
Avatar of NickRepin
NickRepin

#include <windows.h>
#include <iostream.h>
#include <stdio.h>

void a()
{
   cout<<"a() func"<<endl;
}

void aendmark() { }

void main(void)
{
   DWORD current_instruction_pointer;
   DWORD label_address;
   DWORD function_address;

   cout<<"Obtain current value of instruction pointer"<<endl;

   __asm {
label1:
      mov current_instruction_pointer,offset label1
   }

   cout<<"Obtain label address"<<endl;

   __asm {
      mov label_address,offset label2
   }


   cout<<"Obtain function address"<<endl;
   
   function_address=DWORD(a);

   cout<<current_instruction_pointer<<endl;
   cout<<label_address<<endl;
   cout<<function_address<<endl;

label2:
   exit(0);
}

Avatar of eleigh

ASKER

Good answer, thanks, except ... taking the address of a function in C++ only works when it's global (or perhaps when it's a member of a static class), but not when it's an ordinary class function (sorry, should have made that clearer before):

MyClass::func1()
{
  void *ptr1 = [address of this->func1()]
  void *ptr2 = [address of this->func2()]
}

MyClass::func2()
{
....
}
ASKER CERTIFIED SOLUTION
Avatar of NickRepin
NickRepin

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Sorry,   " A a; " in f1() is not necessary.
   
Sorry again, the code above returns not the address of the function itself, but the address of jmp instruction that points to this function. I'll fix this in minutes.
This code works fine for Borland compiler. For VC++ you have to use the following (note: you can use A::f1 instead of a.f1)

#include <windows.h>
#include <iostream.h>

// This is VC++ specific.
void fixVC(DWORD& addr)
{
#pragma pack(push,1)  
   typedef struct {
      char opcode;
      DWORD offset;
   } *pjmp;
#pragma pack(pop)
   pjmp jmp=(pjmp) addr;
   addr=addr+sizeof(*jmp)+jmp->offset;
}

class A
{
   public:
       void f1();

  typedef void (A::*pfunc) ();
};

void A::f1()
{
   union {
      A::pfunc p;
      DWORD addrf1;
   } u;
   u.p=A::f1;
   fixVC(u.addrf1);
   cout<<hex<<u.addrf1<<endl;

}

void main(void)
{
   A a;
   union {
      A::pfunc p;
      DWORD addrf1;
   } u;
   u.p=A::f1;
   fixVC(u.addrf1);
   cout<<hex<<u.addrf1<<endl;
   a.f1();
}
Avatar of eleigh

ASKER

Many thanks! I would have got there eventually with the assembly code, but your fixVC() I wouldn't have worked out for myself. (Sorry about rejecting your original answer: didn't realise I could just add a comment to an answer.)
nick, what if it is a virtual function?
Is it the new question?
Huh?  I'm just pointing out that the approach won't work with virtual functions.
Yes, but the author of question is satisfied with my answer. It seems that he uses non-virtual functions. As you can see, this Q is not about theoretical, but about concrete stuff - something like copy protection. Of course, we can extend the Q to virtual functions, virtual base classes etc, but what's for?
Are you sure he doesn't use virtual functions?  Are you sure he knows and is satisfied that it won't work for virtual functions.?  Could be, I don't know either....
I think, eleigh will add comment about this if he wants.
But it must be something extremely super very cool if there is a need to get a actual memory address of virtual function!
"extremely super very cool"?  Just "super very cool" wouldn't justify it, then?  alright.  You're probably right....
Avatar of eleigh

ASKER

OK, guys, I don't envisage needing the address of a virtual function so let's say we'll 'leave it as an exercise for the reader'. (One that's beyond me though: the address one ends up with is of the 'vcall' code which contains a jmp offset from edx. Haven't a clue how to take it from there, since the value of edx isn't defined unless you're calling the function.)
When do you end up with this "vcall code"?  with a virtual function?  If so you need to use the offset as an index in the the class's virtual function table.