Exetools

Exetools (https://forum.exetools.com/index.php)
-   Source Code (https://forum.exetools.com/forumdisplay.php?f=46)
-   -   [C] Winapi Call Dynamically and easily (https://forum.exetools.com/showthread.php?t=18714)

0xall0c 03-19-2018 17:30

[C] Winapi Call Dynamically and easily
 
This Small Function Let You call winapi dynamically, without having to define function definition, or writing nonsense wrappers.

Code:

void* DynCall(void *ptr, ...)
{
        char* function;
        char* library;
        va_list va;
        void *p;
        int i = 0;
        DWORD argBuf[32];
        DWORD ret;
        HANDLE lib;

        va_start(va, ptr);
        library = ptr;
        function = va_arg(va, void*);
        p = va_arg(va, void *);
        if(!(lib = GetModuleHandleA(library)))
                lib = _LoadLibraryA(library);
        if (!lib)
                error("Cant load libarary %s", library);
        void *funcAddress = _GetProcAddress(lib, function);
        if (!funcAddress)
                error("Cant Find Dynamic Address %s", function);
        for (; p != 0xb33f; p = va_arg(va, void *)) {
                argBuf[i++] = p;
        }
       
        for (i--; i >= 0; i--)
        {
                p = argBuf[i];
                _asm {
                        push p
                }
        }
        va_end(va);
        _asm {
                push lb
                jmp funcAddress
        lb:
                mov ret, eax
        }
        return ret;
}

Example :

Code:

DWORD dwResult = DynCall("ntdll.dll","NtUnmapViewOfSection",
                                        PI.hProcess,
                                        (LPVOID)(NtHeader->OptionalHeader.ImageBase),0xb33f
                                );

Dont forget to add one extra paramater at end i.e 0xb33f

I think it will be useful to someone.

Pansemuckl 03-19-2018 18:25

Using this with a wrong number of arguments OR screwing up stack (e.g. using wrong calling convention) ... good luck debugging this!

0xall0c 03-19-2018 20:12

when you dont know, number of arguments or calling convention of the function, you should not call that function,

its not for a commercial application (approx no maintainance), its for different scenarios.

vic4key 04-03-2018 19:18

I think the parameter number of arguments is better than 0xb33f. Ex. void* DynCall(void *ptr, int nargs, ...).
More, need checking for 32/64-bit and calling convention (32-bit can be __stdcall, __cdecl, ... 64-bit can be C-D-8-9 ordered registers, ...).

0xall0c 04-04-2018 17:34

yes number of arguments would be better, it will help in debugging,
(you can modify the function, i have just given a way to call winapi pure dynamically, which i wa not able to find anywhere)

also the function was written for 32bit, no 64bit support
but as you posted i got a requirement to port it in 64 bit
(coincidence!!)

dosprog 04-04-2018 19:01

It's likely not a good idea.
Any of imported functions must be correctly declared individulally,
and thus must be called normally.
In addition - without of using __asm directive.
In addition2 - repeated calls will be performed much faster.
In addition3 - [less or more] universal solution for x32/x64.

..It's likely not a good idea but it works..

--Add--

Add 1st argument of function as enum {C_CALL,STD_CALL}
and produce separate __asm code for this conventions ?



--Add2--

Quote:

Originally Posted by 0xall0c (Post 112705)
Example :

Code:

DWORD dwResult = DynCall("ntdll.dll","NtUnmapViewOfSection",
                                        PI.hProcess,
                                        (LPVOID)(NtHeader->OptionalHeader.ImageBase),0xb33f
                                );

Dont forget to add one extra paramater at end i.e 0xb33f

This example rewritten without of DynCall():
Quote:

DWORD(__stdcall*_NtUnmapViewOfSection)(DWORD,DWORD);

void main(void)
{
DWORD result;

if(!(_NtUnmapViewOfSection=(DWORD(__stdcall*)(DWORD,DWORD))GetProcAddress(LoadLibrary("ntdll.dll"),"NtUnmapViewOfSection")))goto dos_exit;

result=_NtUnmapViewOfSection(0,0);

dos_exit:;
}



0xall0c 04-05-2018 01:55

this code resolves problem when you don't want imports to be created in an executables, you can use getprocaddress and loadlibrary obviously, but using them and declaring each function prototype is very frustrating.

mcp 04-05-2018 03:07

@0xalloc: I don't understand what problem this solves in the first place? In which cases do you call an API while at the same time not knowing its function signature? I mean, you cannot even correctly call any API without knowing its signature, i.e., how many bytes to push/pop off the stack?

0xall0c 04-05-2018 16:14

Quote:

Originally Posted by mcp (Post 112893)
@0xalloc: I don't understand what problem this solves in the first place? In which cases do you call an API while at the same time not knowing its function signature? I mean, you cannot even correctly call any API without knowing its signature, i.e., how many bytes to push/pop off the stack?

in c/c++ you need to define function prototype first, with this no prototypes are needed.

0xall0c 04-05-2018 16:16

Quote:

Originally Posted by dosprog (Post 112890)
It's likely not a good idea.
Any of imported functions must be correctly declared individulally,
and thus must be called normally.
In addition - without of using __asm directive.
In addition2 - repeated calls will be performed much faster.
In addition3 - [less or more] universal solution for x32/x64.

..It's likely not a good idea but it works..

--Add--

Add 1st argument of function as enum {C_CALL,STD_CALL}
and produce separate __asm code for this conventions ?



--Add2--


This example rewritten without of DynCall():




see the function prototype you defined, when there are lot functions to call, that's an extra headache.

mcp 04-05-2018 16:35

Quote:

Originally Posted by 0xall0c (Post 112898)
in c/c++ you need to define function prototype first, with this no prototypes are needed.

Right, but you cannot invoke an API without knowing its prototype! So that means you know the prototype already when using the "DynCall" mechanism. So the only thing it saves you is a one-line typedef? But you loose type correctness for all API arguments...that seems like a very bad trade-off.

Pansemuckl 04-05-2018 16:44

Quote:

Originally Posted by 0xall0c (Post 112899)
see the function prototype you defined, when there are lot functions to call, that's an extra headache.

Not if you're using variadic templates (C++ 11)...
It produces even simpler, smaller and clean code.

0xall0c 04-05-2018 17:25

Quote:

Originally Posted by mcp (Post 112900)
Right, but you cannot invoke an API without knowing its prototype! So that means you know the prototype already when using the "DynCall" mechanism. So the only thing it saves you is a one-line typedef? But you loose type correctness for all API arguments...that seems like a very bad trade-off.

trade-off is bad or not is subjective to where it is used.

0xall0c 04-05-2018 17:27

Quote:

Originally Posted by Pansemuckl (Post 112901)
Not if you're using variadic templates (C++ 11)...
It produces even simpler, smaller and clean code.

i didn't used variadic templates before. thank you for pointing out.
:)

mcp 04-05-2018 18:44

Quote:

Originally Posted by 0xall0c (Post 112902)
trade-off is bad or not is subjective to where it is used.

Well, it's pretty uncontroversial that losing type correctness for your API calls *is* bad for overall correctness of your program. The amount of work you're saving is marginal, and at the same time you have to deal with the dangers of type system violations. How is that not a bad trade-off? And we haven't even talked about the loss of readability of DynCall vs regular API calls...


All times are GMT +8. The time now is 18:49.

Powered by vBulletin® Version 3.8.8
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Always Your Best Friend: Aaron, JMI, ahmadmansoor, ZeNiX