2008年8月27日星期三

在程序中动态调用API函数

这是KsSafetyCenter中的一个技术,代码的注释比较少,自己看着理解吧^。^,算是我自己一次大的开源吧。。
目前仅仅是STDCALL的函数调用,其它类型的函数调用大家可以自己写出。
代码可能有错,欢迎指出。


// 注:代码必须用VC编译,否则像DEV C++这样的编译器不会通过编译的。



//----------------------------------------KsRunFunc.h----------------------------------//
/* 作者:Lightning(kxsystem@163.com) */
/* 转载和使用请声明,谢谢 */
#define FUNC_NAME_LENGTH 64 // 函数名最大长度
#define FUNC_PARAM_MAX 16 // 参数个数最大值

#define KSPARAM_DWORD 0x0 // 参数类型
#define KSPARAM_STRING 0x1





// KS是我的代号kxsystem的简写。

// 信息头
struct KSFUNC_CALL
{
KSFUNC_CALL* pNext; // 可以用一个链表将所有调用过的函数连接起来,便于制作"调用堆栈"
DWORD dwSize; // 本结构大小,包括后面缓冲区大小
BOOL bRaiseError; // 出错了吗??
BOOL bIsKernel; // 内核模式? 现在还没有使用.
char pszFuncName[FUNC_NAME_LENGTH]; // 函数名
DWORD pfn; // 函数指针
DWORD hModule;// 模块句柄
DWORD dwReturn; // 返回值
int nParamCount; // 参数个数
char cTypeOfParams[FUNC_PARAM_MAX]; // 参数类型
DWORD dwRVAs[FUNC_PARAM_MAX]; // 参数地址偏移,使用时需要加上GetBuffer()
PBYTE GetBuffer(){ return (PBYTE)(this+1); } // 返回本结构以后的内存区.
};

#ifndef _KERNEL

DWORD htoi(const char* szHex)
{
DWORD temp;
sscanf(szHex, "%x", &temp);

return temp;
}



下面这个函数的代码很难理解,我又比较L,与主要技术无关,主要是对字符串的解析.具体代码就不列出了.

主要的功能为:解析字符串,将函数地址,函数模块,函数名,函数参数及其偏移地址,以及是否对参数进行取值等信息写入到KSFUNC_CALL结构中.



BOOL InitFunctionCall( char* lpString, KSFUNC_CALL* fc)
{


}



#endif

DWORD CallFunction(KSFUNC_CALL* fc)
{


DWORD Addr=fc->pfn;
int nCount=fc->nParamCount;
DWORD dwPop=nCount*sizeof(DWORD) ;
DWORD dwRet;
DWORD Value;
__try
{

for(int b=fc->nParamCount-1;b>=0 ;b--)
{
Value=(DWORD)(fc->GetBuffer()+fc->dwRVAs[b]);
if(fc->cTypeOfParams [b]==KSPARAM_DWORD)
{
Value=*(DWORD*)Value;
}

_asm mov edx,Value
_asm push edx
}
_asm
{
mov eax,Addr
call eax
// add esp,dwPop
mov dwRet,eax
}
fc->dwReturn =dwRet;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
fc->bRaiseError =TRUE;
}

return dwRet;
}





有了以上的头文件,其它的就简单得多了,下面是一个简单的console程序。



#include
#include
#include "KsRunFunc.h"



int main()
{
char st[0x100];
memset(st,0,0x100);
KSFUNC_CALL* p=(KSFUNC_CALL*)st;

if(InitFunctionCall("user32.dll!MessageBoxA(0,\"Hello World!\",\"App\",0);",p))
{
printf("Function Name=%s\n",p->pszFuncName);
printf("Function Module=0x%0X\n",p->hModule);
printf("Function Address=0x%0X\n",p->pfn);
if(p->nParamCount !=0)
{
for(int b=0;bnParamCount ;b++)
{
if(p->cTypeOfParams [b]==KSPARAM_DWORD)
printf("Function Parameter %d = 0x%0X\n",b+1,*(DWORD*)(p->GetBuffer()+p->dwRVAs[b]) );
else
printf("Function Parameter %d = %s\n",b+1,(char*)(p->GetBuffer()+p->dwRVAs[b]));
}
}
printf("Return =0x%0X",CallFunction(p));
}



getchar();

return 0;
}

没有评论: