DLL 내보내기 함수를 보다 쉽게 동적으로 호출(VC++)
당신은 이 글을 마음대로 전재할 수 있지만, 전재할 때 원본 링크와 저자를 명기해 주십시오. 감사합니다.
일반적으로 DLL 내보내기 함수를 동적으로 호출하는 방법은 다음과 같습니다.
그러나 호출할 함수가 너무 많으면, 이 방법은 너무 많은 typedef, 너무 많은 GetProcAddress, 너무 많은 함수 바늘로 흐르는 것을 피하기 어렵다.본고에서 이러한 동적 호출을 더욱 간편하게 하는 통용적인 해결 방법을 제시할 것이다.먼저 우리 함수의 성명을 보아라.
C++ 코드
BOOL __cdecl DllCall(PCTSTR lpszDll, // DLL
PCSTR lpszFunc, //
int argc, //
PVOID pRet, //
...); //
MessageBoxA의 경우 다음을 사용합니다.
C++ 코드
int ret;
DllCall(_T("user32.dll"), "MessageBoxA", 4, &ret,
NULL, "Hello, World!", "Hello", MB_ICONINFORMATION | MB_YESNO);
매개 변수의 MessageBoxIndirectA를 바꾸면 다음과 같습니다.
C++ 코드
MSGBOXPARAMSA param;
ZeroMemory(¶m, sizeof(MSGBOXPARAMSA));
param.cbSize = sizeof(MSGBOXPARAMSA);
param.dwLanguageId = GetSystemDefaultLangID();
param.dwStyle = MB_ICONINFORMATION;
param.lpszCaption = "Hello";
param.lpszText = "Hello, World";
int ret;
DllCall(_T("user32.dll"), "MessageBoxIndirectA", 1, &ret, ¶m);
구현의 원리는 어셈블리 코드를 동적으로 생성하는 것이다. 즉, 이와 같은 부분이다.
C++ 코드
__declspec(naked) DWORD __cdecl DllCallProc(void)
{
__asm
{
push argn
...
push arg2
push arg1
call proc
ret
};
}
다음은 DllCall의 코드를 보여 줍니다. 모든 변수 함수 (예: sprintf) 와 차이가 많지 않습니다.C++ 코드
BOOL __cdecl DllCall(PCTSTR lpszDll,
PCSTR lpszFunc,
int argc,
PVOID pRet,
...)
{
va_list arglist;
int ret;
va_start(arglist, pRet);
ret = vDllCall(lpszDll, lpszFunc, argc, pRet, arglist);
va_end(arglist);
return ret;
}
가장 관건적인 것은 vDllCall의 코드입니다. 다음과 같습니다. C++ 코드
#pragma pack(push, 1)
typedef struct {
BYTE op;
DWORD_PTR dwValue;
} OPCODE, *POPCODE;
#pragma pack(pop)
typedef DWORD (__cdecl * DLLCALL)(void);
BOOL __cdecl CRfidNfc::vDllCall(PCTSTR lpszDll,
PCSTR lpszFunc,
int argc,
PVOID pRet,
va_list arglist)
{
HMODULE hDll = LoadLibrary(lpszDll);
if (NULL == hDll)
return FALSE;
FARPROC proc = GetProcAddress(hDll, lpszFunc);
if (NULL == proc)
return FALSE;
HANDLE hHeap = GetProcessHeap();
POPCODE p = (POPCODE)HeapAlloc(hHeap, 0, sizeof(OPCODE) * (argc + 2));
int i;
for (i = argc - 1; i >= 0; --i)
{
// push arg[i]
p[i].op = 0x68;
p[i].dwValue = va_arg(arglist, DWORD_PTR);
}
// call proc
p[argc].op = 0xe8;
p[argc].dwValue = (INT_PTR)proc - (INT_PTR)&p[argc + 1];
// ret
p[argc + 1].op = 0xc3;
p[argc + 1].dwValue = 0x90909090; // nop nop nop nop
DLLCALL pfn = (DLLCALL)p;
DWORD ret = pfn();
HeapFree(hHeap, 0, p);
FreeLibrary(hDll);
if (NULL != pRet)
*(PDWORD)pRet = ret;
return TRUE;
}
포인터 p는 DLLCALL 유형의 함수 포인터로 변환하여 동적으로 생성된 호출 코드입니다.마지막으로 네 가지 추가 설명이 필요합니다.
http://www.titilima.cn/show-275-1.html
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
다양한 언어의 JSONJSON은 Javascript 표기법을 사용하여 데이터 구조를 레이아웃하는 데이터 형식입니다. 그러나 Javascript가 코드에서 이러한 구조를 나타낼 수 있는 유일한 언어는 아닙니다. 저는 일반적으로 '객체'{}...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.