📚 OpenRCE is preserved as a read-only archive. Launched at RECon Montreal in 2005. Registration and posting are disabled.








Flag: Tornado! Hurricane!

 Forums >>  Brainstorms - General  >>  How to solve this complex problem (calling funcs at runtime) ?

Topic created on: August 8, 2010 03:29 CDT by Usman .

Hello,
I am having a complex problem to solve. Currently stuck and found no way around.

I need to call every exported function of some WIN32 DLL or exposed function of a COM EXE/DLL under some interface at run time(No code generation).
I have extracted function signatures with complete details (i.e return type, all arguments in/out).Now all these types and exposed methods of those types, Interfaces and their exposed methods have been listed in some XML or any text file.

Now for every function i also listed its index or its address in XML or text file, so that When I need to call function i can make assembly call to that function with _asm { call address}.
Its very easy to call function which is taking pointer of some user defined Type e.g say ------------>void CallMethod(int x,int y, SomeUDT *pSomeUDT). Here "SomeUDT" is some user defined type say class or struct of which pointer as incoming parameter. I will scan its details from XML file(i.e what are data members against this type) and will declare a heap block of size (which I will calculate from summing its data types of data members). Next I will fill data on those blocks and will call function . Here void* only be needed to traverse the whole block and on need i will type cast it with some primitive types say with float or int (depends what kind of data i am filling in the block). and finally will call the function accordingly.

HERE THE PROBLEM IS WITH VOID*. It cannot be de-referenced. What if I am having object on recieving side SAy above method would be as
void CallMethod(int x,int y, SomeUDT objSomeUDT)  Now I cant call this function as I statted above.

The whole story i am listing here.

<Types>
   <MyType>
       <Methods name="CallMethod" Address="102">
         <params>
                <param type="int" name="x"/>
                <param type="int" name="y"/>
                <param type="SomeUDT" name="a_objSomeUDT"/>
         </params>                  
       </Methods>
   </MyType>
</Types>
<TypeDictionary>
   <Type name="SomeUDT">
       <dataMember name = "Data_1" type = "unsigned long*"/>
       <dataMember name = "Data_2" type = "unsigned short*"/>
       <dataMember name = "Data_3" type="SomeOtherUDT">
            <dataMember name="" type = "SomeOtherUDT">
                 <!--So on so forth--->
   </Type>
</TypeDictionary>

Now what I will do I will scan SomeUDT from type dictionary and calculate total size of data mamabers types and allocate a heap block with sum of its member's types. and finally fill the data accordingly. then will do

void *pBlockOfMem = malloc(sizeof(unsigned long+unsigned short+SomeOtherUDT));

unsigned long* pData_1 = (unsigned long*)pBooclOfMem;
*pData_1 = 20;
pData_1++;

unsigned short* pData_2 = (unsigned short*)pData_1;
*pData_2 = 150;
pData_2++;

so on for SomeOtherUDT as well. and fainally whole block will be filled.



_asm
{
               push pBooclOfMem
               call addressOfFunction                                   ; it will call function whose signature is "void CallMethod(int,int,SomeUDT* pSomeUDT)
}

But here if i have signature "void CallMethod(int,int,SomeUDT oSomeUDT)" .....obj as argument not pointer. Here Void* approach fails.

What's the exact and perfect solution to the above problem . I am stuck here. Need to solve with 100% accurate solution.


Regards
Usman

  vptrlx   August 14, 2010 05:40.20 CDT
What's the problem?
You can calculate the size -> if it's not a pointer, so you have to allocate this in the stack.
Just look a the code:

#include "stdlib.h"

typedef struct tag_HH{
int x;
int y;
void *z;
} HH, *pHH;
int __stdcall xxxx(int a, HH b, pHH c){
c->x = b.y;
return c->y;
}
int main(){
HH K;
pHH L;
L = (pHH)malloc(sizeof(HH));
K.x = 1;
K.y = 2;
K.z = L;
L->x = 3;
L->y = 4;
L->z = &K;
xxxx(1, K, L);
return 0;
}

it assembles as:
00411435  mov         eax,dword ptr [L]  
00411438  push        eax  //the last parameter - pointer
00411439  sub         esp,0Ch //allocate in stack
0041143C  mov         ecx,esp  //fill struct in stack
0041143E  mov         edx,dword ptr [K]  
00411441  mov         dword ptr [ecx],edx  
00411443  mov         eax,dword ptr [ebp-0Ch]  
00411446  mov         dword ptr [ecx+4],eax  
00411449  mov         edx,dword ptr [ebp-8]  
0041144C  mov         dword ptr [ecx+8],edx  
0041144F  push        1  //first param
00411451  call        xxxx (4111CCh)  

Or are you experiencing troubles with size calculation? It can easily be done with recursion;

  Usman     August 14, 2010 08:07.48 CDT
This i saw and observed in case of Pointer. I know exact size of my struct. But i don't need corresponding pointer(*) to that type to be pass to that function. I need to object to be pass (Only I have size info for that object which is to be created and I DONT KNOW WHAT TYPE OF THAT OBJ IS ) You can't declare "HH" on compile time.At runtime only I'll have size of that type , and I dont know what HH is at runtime. As type details (members of struct) is just a bunch of strings and HH itself. At runtime I need to get the type of HH and then to declare that object on stack and then nned to pass on. In case of pointer at reciving end, you can allocate block of memory and fill values and push the pointer and that's it. But in case of object , first you cant dereferenced void* so u need actuall HH object. U can think of as several stucts will com from fill and i need to allocate memory and fill the data for those types. BTW every time I need to allocate object of corresponding type.(e.g HH in tis case which actully not the part of code ). AT RUNTIME WE'll JUDGE WHAT TYPE IT IS AND AT RUNTIME WE'LL CALL THE FUNCTION.

  vptrlx   August 14, 2010 09:33.14 CDT
I still can't get the thing:
1) You know the object size, say it is N
2) When you have a pointer argument -- you do something like

push N
call MyAllocateMemory
mov [eax], 1
mov [eax+4], 2
...
push eax
call func

or something similar
3) So why can't you do so in case of object argument:

sub esp, N
lea eax, [esp]
mov [eax], 1
mov [eax+4], 2
...
call func

?

  Usman     August 14, 2010 10:05.47 CDT
Respectfully...
Look here
struct WESContext  
{
    int name,
    long Priority,
    BSTR MachineName
    BSTR IpAddress
    ...
}

Now this is the type I've got from XML.
AS a string WESContext I got, first How can I create the object of this WESContext on stack by calculating size by summing up all bytes from "name" to "IpAddress". WESContext is just string, I need to create its object on stack. How a string can be converted to certain Type..?

Its not .NET or Java where you have support of reflection APIs where you pass type as string and can get corresponding object at runtime. Here u need to call function at assembler level , which I have done by allocating block of memory and pusing void* on stack without KNOWING the type to which it belongs, just filled data set. When it just called pointer automatically pointed to a block of memory whatever type it was.

Remember I don't know what "WESContext" is This chunk of struct never allocated or WRITTEN in currently executing EXE/DLL. I am calling functions of other EXE's/DLLs of whome code is not available to me. Just I am getting types as strings of details(i mean parameters and their types). I allocate blocks of unknown types and just fill them up with some data set. If corresponding signature contains pointer, that VOID* automatically type casted to that type(whatever not known at runtime).

1 - Now in case of object, OK I created blovk of memory. right.

2-  Now I can't dereference VOID*.
3-  How to push allocated heap block of pointer which would become then object of corresponding type?

I think now u got ..? If again confusion, do let me know i'll then clarify more.

  vptrlx   August 14, 2010 15:10.15 CDT
So you have a problem calculating sizeof(WESContext) because you have WESContext as a string.
If you wish to make everything precisely - the way to calculate it is to scan it as the compiler does - look through member type definitions and if it is int, add 4, if it is some other type like BSTR - calculate its size recursively and so on, not forgetting about alignments.

If you just want something with semi-random fields -- do something like

push edi
mov edi, esp // or mov dword ptr ds:[SavedESP], esp

sub esp, 5000
call function

mov esp, edi //or mov esp, dword ptr ds:[SavedESP]
pop edi

where 5000 is definitely greater then the object size.

Other parameters may be affected by this operation - but you don't care about their values, am i right?

  Usman     August 14, 2010 18:45.13 CDT
You've got half of the problem..:-)
Not only sizeof(WESContext) was the problem, which you suggested to calculate.(Infact I had idea)

More over the additional big problem is to create object of WESContext on stack. Now you agree and noticed that WESContext is STRING of whome size I have calculated. But Now you know that here object of WESContext cannot be made as heap block of memory(No doubt we now have calculated the size), still it cannot be allocated as heap block because I NEED TO CREATE OBJECT ON STACK (like we created on heap and just filled), NOT POINTER POINTING TO HEAP ALLOCATED BLOCK.

THE SAME WAY OBJECT WOULD BE CREATED ON STACK AS WE CREATED ON HEAP but here how can we allocate that block on STACK and CAN FILL THAT BLOCK AS IT IS AS IT WAS BEING FILLED IN CASE OF HEAP BLOCKED FILLED?

See here a function which one needs to be called.

CreateTag(BSTR a_TagName,unsigned long a_size, WESContext a_wesContext)

Now this is the function which one to be called at runtime. OK

WE pushed a_TagName,a_size

_asm
{
     mov eax, a_TagName
     push eax

     mov eax, a_size
     push eax
    
     push .....                    //Here WESContext     OBJECT TO BE PUSHED
}

If we prepare block of memory such as

void *pWESContext = (void*)malloc(sizeOf(WESContext));
here I can't do this

_asm
{
   push params....
   push *(pWESContext)   ;nor assembler allows and nor compiler will allow this
}

PROBMLEM IS YOU MUST HAVE BLOCK OF MEMORY AS IT WAS ON HEAP.BUT HERE SHOULD NOW ON STACK AND MUST BE FILLED, YOU CANT EXACTLY GO FOR THIS AS YOU GONE ON HEAP.

I think now you fully understood the picture.

  vptrlx   August 15, 2010 14:28.17 CDT
Do you care about real values you pass to the function?
I.e. in your example CreateTag(BSTR a_TagName,unsigned long a_size, WESContext a_wesContext) do you want a_size to be exactly 531, for example? If so, the only way is to calculate the size. And if in addition you want WESContext to be something meaningful, you have to do the work that Compiler does: for example, if it is C++, and WESContxt is a class, not a struct, so you have to create something like vftbl, etc� In a few words write a compiler :)

And if you don't care - you can just subtract a value which you believe is greater than the size of struct as i pointed above. There is nothing bad if it's bigger - so your "parameters frame" in the stack will move down a little bit.
So your stack will look like this on the call:

param_1
param_2
Param_3
......
param_n
unused value
unused value
unused value
....
unused value
something <--- esp before function call

  RabidCicada     August 19, 2010 09:56.05 CDT
Usman,
You don't have a technical limitation.  You just have to see the problem in the right light.

Calculating the Size isn't a problem at all as if you know the contents you know the size.

To put the object on the stack do this:
1.Push enough space onto the stack for the full object.  If the object is 531 bytes big then push 531 bytes onto the stack.
2.Write the values directly to the stack in the appropriate locations.  Basically, ptrWESContext = AddrOf(stack location).  Then ptrWESContext->dataelement = value;
3.BE aware that you need to emulate the class as stated by vptrlx if it is a class.  You do this by creating a function table, and in the case of a virtual class a vftable.

4.The real problem is that you will have to implement functions representative of the real ones if you are not going to redirect to the real one.

Note: Registration is required to post to the forums.

There are 31,328 total registered users.


Recently Created Topics
[help] Unpacking VMP...
Mar/12
Reverse Engineering ...
Jul/06
let 'IDAPython' impo...
Sep/24
set 'IDAPython' as t...
Sep/24
GuessType return une...
Sep/20
About retrieving the...
Sep/07
How to find specific...
Aug/15
How to get data depe...
Jul/07
Identify RVA data in...
May/06
Question about memor...
Dec/12


Recent Forum Posts
Finding the procedur...
rolEYder
Question about debbu...
rolEYder
Identify RVA data in...
sohlow
let 'IDAPython' impo...
sohlow
How to find specific...
hackgreti
Problem with ollydbg
sh3dow
How can I write olly...
sh3dow
New LoadMAP plugin v...
mefisto...
Intel pin in loaded ...
djnemo
OOP_RE tool available?
Bl4ckm4n


Recent Blog Entries
halsten
Mar/14
Breaking IonCUBE VM

oleavr
Oct/24
Anatomy of a code tracer

hasherezade
Sep/24
IAT Patcher - new tool for ...

oleavr
Aug/27
CryptoShark: code tracer ba...

oleavr
Jun/25
Build a debugger in 5 minutes

More ...


Recent Blog Comments
nieo on:
Mar/22
IAT Patcher - new tool for ...

djnemo on:
Nov/17
Kernel debugger vs user mod...

acel on:
Nov/14
Kernel debugger vs user mod...

pedram on:
Dec/21
frida.github.io: scriptable...

capadleman on:
Jun/19
Using NtCreateThreadEx for ...

More ...


Imagery
SoySauce Blueprint
Jun 6, 2008

[+] expand

View Gallery (11) / Submit