Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


[Help] How do you get the ret address from a function?
Goto page Previous  1, 2
 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming
View previous topic :: View next topic  
Author Message
tombana
Master Cheater
Reputation: 2

Joined: 14 Jun 2007
Posts: 456
Location: The Netherlands

PostPosted: Sat Jan 10, 2009 2:21 am    Post subject: Reply with quote

dnsi0 wrote:
tombana wrote:
And if you hook at the return (so if you replaced the RETN with a JMP) then it's also [esp].


I don't think that works... You still have to pop all those values from the stack.

Well, like BanMe showed, if you hook at the RET (so áfter the 'leave') then the program should have already restored the stack otherwise the return wouldn't be working properly. One problem might be that the function has multiple returns, so you would have to hook them all.

BanMe wrote:
Code:

__declspec(naked)void Hk_OpenThreadToken()
{
        DWORD RetAddress;     
        __asm
        {
              mov RetAddress,[esp]
              mov edi,edi
              push ebp
              mov ebp,esp
              jmp OpenThreadToken+5
        }
}

How would the compiler allocate stack space for RetAddress in this case? (I mean when the function has __declspec(naked)) Since you did [esp] I'm assuming the stack would still be the same as before the allocation of RetAddress.
Back to top
View user's profile Send private message
rapion124
Grandmaster Cheater Supreme
Reputation: 0

Joined: 25 Mar 2007
Posts: 1095

PostPosted: Sat Jan 10, 2009 8:35 am    Post subject: Reply with quote

I don't use a variable in the stack. I just push the [esp] value and then call another function with the __STDCALL calling convention, which does something with the return address and restores the stack.

I do this:
Code:

API_CODE:
//Hook here ([esp])
mov edi, edi
push ebp
mov ebp, esp
//Hook here ([esp+4])
...
pop ...
pop ...
leave
//Hook here ([esp])
ret x

Hook:
push [esp] //or [esp+4]
call PrintReturnAddress //__STDCALL
ret x //or trampoline back
[/code]
Back to top
View user's profile Send private message
BanMe
Master Cheater
Reputation: 0

Joined: 29 Nov 2005
Posts: 375
Location: Farmington NH, USA

PostPosted: Sat Jan 10, 2009 11:46 am    Post subject: Reply with quote

hmm i didnt think of it that way tombana.. i was quite tired when i wrote the example out.. removing the __declspec(naked) would prolly be the best course of action..

alternativly a Global or the smart use of push/pop Wink


another form of preamble is the SEH installation code which usually looks as such

Code:

push 0xdeadc0de//xyz code
call InstallSeh
push ebp
mov ebp,esp
xyzcode
pop ebp
UninstallSeh
ret

now this form of preamble is usually used in the "W" and "Ex" functions
so hooking here is pretty simple just rewrite the Push.. (no examples)..

heres a example of using push/pop to get what we need with the naked attribute using thr same example from above hooking the preamble
Code:

__declspec(naked)void Hk_OpenThreadToken()
{
          __asm
        {
              pop eax//gets esp
              push eax//restores it
              mov edi,edi
              push ebp
              mov ebp,esp
              jmp OpenThreadToken+5
        }
}
Back to top
View user's profile Send private message MSN Messenger
dnsi0
I post too much
Reputation: 0

Joined: 04 Jan 2007
Posts: 2674

PostPosted: Sat Jan 10, 2009 2:13 pm    Post subject: Reply with quote

these all have the header of
push ebp and mov ebp,esp

And why use mov edi,edi? its the same as nop. don't need it.

And also the code that Im trying to hook isn't like that.
It does not have the usual push ebp and mov ebp,esp.
It starts off with a mov eax,[value]
and ends with
leave
ret
Back to top
View user's profile Send private message
sponge
I'm a spammer
Reputation: 1

Joined: 07 Nov 2006
Posts: 6009

PostPosted: Sat Jan 10, 2009 3:35 pm    Post subject: Reply with quote

dnsi0 wrote:
these all have the header of
push ebp and mov ebp,esp

And why use mov edi,edi? its the same as nop. don't need it.

And also the code that Im trying to hook isn't like that.
It does not have the usual push ebp and mov ebp,esp.
It starts off with a mov eax,[value]
and ends with
leave
ret


There is an ENTER instruction or push ebp, mov ebp, exp somewhere. The proof is in the LEAVE instruction.

_________________
Back to top
View user's profile Send private message
BanMe
Master Cheater
Reputation: 0

Joined: 29 Nov 2005
Posts: 375
Location: Farmington NH, USA

PostPosted: Sat Jan 10, 2009 4:55 pm    Post subject: Reply with quote

mov edi,edi is a component of hotpatching research it eclicz wrote a nice paper on it.. ;p

and if ur function has a leave that means there is a enter somewhere probably a conditional jump that jumps to ur supposed start Smile

regard BanMe
Back to top
View user's profile Send private message MSN Messenger
tombana
Master Cheater
Reputation: 2

Joined: 14 Jun 2007
Posts: 456
Location: The Netherlands

PostPosted: Sun Jan 11, 2009 6:52 am    Post subject: Reply with quote

If there is a 'leave' I don't think there needs to be an 'enter'. In masm, just create a simple function with parameters and local variables and compile that. In olly you'll see that masm will generate a push ebp; mov ebp, esp; and at the end of the function it will do leave; retn;. The leave instruction will just do mov esp, ebp; pop ebp;.
Back to top
View user's profile Send private message
dnsi0
I post too much
Reputation: 0

Joined: 04 Jan 2007
Posts: 2674

PostPosted: Sun Jan 11, 2009 8:52 am    Post subject: Reply with quote

Thats not right...
I looked through the code and did not find it anywhere and don't tell me to look above cause above there is only a leave and ret

SO it looks like this:

leave
ret

mov eax.[some addy I forgot]
*rest of the code w/o and push ebp and mov ebp,esp
leave
ret.

I thought I got the wrong function so I put a bp on the mov eax,[addy]
and it hit the bp when I clicked on the button.
Back to top
View user's profile Send private message
sponge
I'm a spammer
Reputation: 1

Joined: 07 Nov 2006
Posts: 6009

PostPosted: Sun Jan 11, 2009 12:39 pm    Post subject: Reply with quote

tombana wrote:
If there is a 'leave' I don't think there needs to be an 'enter'. In masm, just create a simple function with parameters and local variables and compile that. In olly you'll see that masm will generate a push ebp; mov ebp, esp; and at the end of the function it will do leave; retn;. The leave instruction will just do mov esp, ebp; pop ebp;.
ENTER is the same thing as push ebp, mov ebp,esp. Notice the OR. Unless you were referring to BanMe.
_________________
Back to top
View user's profile Send private message
BanMe
Master Cheater
Reputation: 0

Joined: 29 Nov 2005
Posts: 375
Location: Farmington NH, USA

PostPosted: Mon Jan 12, 2009 8:39 am    Post subject: Reply with quote

dnsio you are not understanding what im saying...

im saying that code just doesnt clean stack for no reasong

so im not say look up.. im saying look for the controller function that determines that peice of code is called and stack is cleaned. it could be anywhere ...o0 it even could be virtual(with no real code except VirtualMemory with MEM_EXECUTE|MEM_WRITE..) usually its not ..
there u will find the ENTER... Smile

im going to show u something a lil different, maybe how to locate a Controller function maybe not..iono maybe it'll help.. heres my flow chartz of my sloution ..cause im to lazy to actually do it ..o0...

this is a dll o0
Upon First Load(maybe it should be injected (SuspendedPRocessStyle))
first off allocate a chunk of growable heap in a TLS or in DllMain o0
Create a thread at intervals EnumThreads in host and
CreateThreads for each Thread(also hide's them from the debugger)
each thread has a simple disassembler that stores eip's and maybe if you so desire some current registsers...(at specific eip's or range there off ) it does this by SupendingThread() GetThreadContext Dissasmbles backwards from eip to find function head ResumeThread Sleep(0);
then once function head found look for the tail(s)... ;)repeat as necassary
oh yea also use the heap to GetContext and store eip and register's (in a more compact fashion) ..sizeof(dword)+(numofRegistersStored*4)..

maybe this can help o0
Code:

unsigned int  GetFunctionLength(void *begin)
{
   void *end = GetFunctionEnd(begin);
   unsigned int delta = (unsigned int)((DWORD_PTR)end - (DWORD_PTR)begin);
   delta    += mlde32(end);
   return delta;
}

void *GetFunctionEnd(void *func)
{
   void *block = func;
   TreeTrunk Tree;
   Tree.MemTotalSize = 256;
   Tree.MemStart = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,Tree.MemTotalSize);
   if(Tree.MemStart != NULL)
   {
      Tree.MemTotalSize = HeapSize(GetProcessHeap(),0,Tree.MemStart);
      if(Tree.MemTotalSize != -1)
      {
         Tree.NumTotalEntry = Tree.MemTotalSize/4;
         Tree.NumEntry = 0;
         //   ptr now points to the end of this block
         void *silenttree = GetBranchListFromBlock(block, &Tree);
         if(Tree.NumEntry == 0) return silenttree;
         DWORD Prev = NULL;
         for(DWORD i = 0; i < Tree.NumEntry; i++)
         {   
            DWORD sz = i * sizeof(DWORD);
            DWORD Limb = (*(DWORD*)Tree.MemStart + sz);
            //   Skip branches that jump into a block we've already
            //   processed. 
            if(Limb < *(DWORD*)silenttree || Limb == Prev)
               continue;
            silenttree = GetFunctionEnd(&Limb);
            Prev     = Limb;
         }
         return silenttree;
      }
      HeapFree(GetProcessHeap,0,Tree.MemStart);
      return NULL;
   }
   return NULL;
}
void *GetBranchListFromBlock(void *block, TreeTrunk *Tree)
{
   UCHAR *ptr = (UCHAR *)block;
   //   If we reach an end-point, then this block is complete
   while(!IsEndPoint(ptr, block))
   {
      //   Record all branching instructions that we encounter
      void *address = GetBranchAddress(ptr);
      if(address)
      {         
         *((DWORD*)Tree->MemStart + (Tree->NumEntry * 4)) = *(DWORD*)address;
         Tree->NumEntry++;   
      }
      //   Next instruction
      ptr += mlde32(ptr);
   }
   return ptr;
}


void *GetBranchAddress(UCHAR *instr)
{
   long offset = 0;
   //   This code will determine what type of branch it is, and
   //   determine the address it will branch to.
   switch(*instr)
   {
   case INSTR_SHORTJMP:
   case INSTR_RELJCX:
      offset  = (long)(*(char *)(instr + 1));
      offset += 2;   
      break;
   case INSTR_RELJMP:
      offset  = *(long *)(instr + 1);
      offset += 5;
      break;
   case INSTR_NEAR_PREFIX:
      if(*(instr + 1) >= INSTR_NEARJCC_BEGIN && *(instr + 1) <= INSTR_NEARJCC_END)
      {
         offset  = *(long *)(instr + 2);
         offset += 5;
      }
      break;
   default:
      //   Check to see if it's in the valid range of JCC values.
      //   e.g. ja, je, jne, jb, etc..
      if(*instr >= INSTR_SHORTJCC_BEGIN && *instr <= INSTR_SHORTJCC_END)
      {
         offset  = (long)*((char *)(instr + 1));
         offset += 2;
      }
      break;
   }

   if(offset == 0) return NULL;
   return instr + offset;
}

bool IsEndPoint(UCHAR *instr, void *curblock)
{
   void *address;
   long offset;
   switch(*instr)
   {
   case INSTR_RET:
   case INSTR_RETN:
   case INSTR_RETFN:
   case INSTR_RETF:
      return true;
      break;

   //   The following two checks, look for an instance in which
   //   an unconditional jump returns us to a previous block,
   //   thus creating a pseudo-endpoint.
   case INSTR_SHORTJMP:
      offset  = (long)(*(char *)(instr + 1));
      address = instr + offset;
      if(address <= curblock) return true;
      break;
   case INSTR_RELJMP:
      offset  = *(long *)(instr + 1);
      address = instr + offset;
        if(address <= curblock) return true;
      break;
   default:
      return false;
      break;
   }

   return false;
}

code is a rework of darawk origanil (i dont like CRT CLR CXYZ..)C++ and asm..and with a lil work it can be reusable for this..
so now that we collect this huges store of information lets store it in some fashion so that they can be indexed and matched up to records the next time the dll loads..
so this time we now have a set of records that matches up with the new thread we can choose to gather more information about code using code coveraging or gather better records Wink.. or do both..
now we need some way of using it graphically...
o0

regards BanMe
Back to top
View user's profile Send private message MSN Messenger
dnsi0
I post too much
Reputation: 0

Joined: 04 Jan 2007
Posts: 2674

PostPosted: Mon Jan 12, 2009 5:59 pm    Post subject: Reply with quote

sorry... what is a heap?
Ive looked at msdn but didn't get the diff between a heap and normal mem..
Back to top
View user's profile Send private message
BanMe
Master Cheater
Reputation: 0

Joined: 29 Nov 2005
Posts: 375
Location: Farmington NH, USA

PostPosted: Mon Jan 12, 2009 6:07 pm    Post subject: Reply with quote

that was not so nice sorry dnsi0 Smile
but i think this is a oppurtunity to write a plugin for CE Smile

so im gonna start it..
others are welcome to help im going to post what i got tommorow xD

regards BanMe
Back to top
View user's profile Send private message MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General programming All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
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


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites