많은 Win32 API는 특정 레이아웃이있는 구조체에 대한 포인터를 사용합니다. 이 중 큰 부분 집합은 호출되기 전에 구조체의 크기를 갖도록 첫 번째 DWORD를 초기화해야하는 일반적인 패턴을 따릅니다. 때로는 구조체를 쓸 메모리 블록이 필요하며, 메모리 블록은 먼저 NULL 포인터로 동일한 API를 호출하고 올바른 값을 찾기 위해 반환 값을 읽음으로써 결정되는 크기 여야합니다 크기. 일부 API는 구조체를 할당하고 그 포인터를 두 번째 호출로 할당 해제해야하는 포인터를 반환합니다.
단순한 문자열 표현에서 변환 가능한 개별 인수를 사용하여 한 번에 유용하게 호출 할 수있는 API 집합이 매우 작 으면 놀랄 일이 아닙니다.
우리가 아주 극단적으로 이동해야합니다,이 아이디어는 일반적으로 적용하려면 :
typedef void DynamicFunction(size_t argumentCount, const wchar_t *arguments[],
size_t maxReturnValueSize, wchar_t *returnValue);
DynamicFunction *GenerateDynamicFunction(const wchar_t *code);
당신은 GenerateDynamicFunction에 코드의 간단한 조각을 통과 할 것, 그리고 몇 가지 표준 상용구에서 그 코드를 래핑 것이며, 그런 다음 함수를 포함하는 C 컴파일러/링커를 호출하여 DLL을 만듭니다 (사용할 수있는 몇 가지 무료 옵션이 있음). 그런 다음 LoadLibrary
DLL을 사용하고 GetProcAddress
을 사용하여 함수를 찾은 다음 반환하십시오. 이 작업은 비용이 많이 들지만 반복적으로 사용하기 위해 한 번 수행하여 결과 DynamicFunctionPtr을 캐시합니다. 해시 테이블에 포인터를 유지하여 동적으로 수행 할 수 있습니다. 코드 스 니펫 자체가 입력합니다.
상용구는 다음과 같을 수 있습니다
#include <windows.h>
// and anything else that might be handy
void DynamicFunctionWrapper(size_t argumentCount, const wchar_t *arguments[],
size_t maxReturnValueSize, wchar_t *returnValue)
{
// --- insert code snipped here
}
그래서이 시스템의 사용 예는 다음과 같습니다
DynamicFunction *getUserName = GenerateDynamicFunction(
"GetUserNameW(returnValue, (LPDWORD)(&maxReturnValueSize))");
wchar_t userName[100];
getUserName(0, NULL, sizeof(userName)/sizeof(wchar_t), userName);
당신은 인자 수를 받아 GenerateDynamicFunction
함으로써이 문제를 개선 할 수, 그것은을 생성 할 수 있도록 랩퍼 시작 부분에서 올 Y 른 수의 인수가 전달되었는지 점검하십시오. 그리고 거기에 해시 테이블을 넣어서 각각의 코드 네피 닛에 대한 함수를 캐시하면 원래 예제에 가까워 질 수 있습니다. Call 함수는 API 이름 대신 코드 스 니펫을 사용하지만 그렇지 않은 경우 코드 스 니펫을 사용합니다. 해시 테이블에서 코드 스 니펫을 검색합니다. 존재하지 않으면 GenerateDynamicFunction을 호출하고 다음 번에 해시 테이블에 결과를 저장합니다. 그런 다음 함수에 대한 호출을 수행합니다. 사용 예제는 : 아이디어는 일반적인 보안 구멍이 어떤 종류의를 열어이었다 않는 한 물론
wchar_t userName[100];
Call("GetUserNameW(returnValue, (LPDWORD)(&maxReturnValueSize))",
0, NULL, sizeof(userName)/sizeof(wchar_t), userName);
이 중 하나를 수행 많은 점을 없을 것입니다. 예 : 웹 서비스로 Call
을 노출합니다. 원래의 아이디어에는 보안상의 의미가 있지만, 제안한 원래의 방식이 그다지 효과적이지 않으므로 간단하지 않습니다. 더 일반적으로 우리가 그것을 강력하게 만들수록 보안 문제가 더 심각해질 것입니다. 의견에 따라
업데이트 :
닷넷 프레임 워크는 문제를 해결하기 위해 정확하게 존재 호출/P라는 특징을 갖고있다. 따라서 이것을 물건에 대해 배우는 프로젝트로하고 있다면 p/invoke를보고 그것이 얼마나 복잡한지를 알 수 있습니다. 스크립트 언어로 .NET 프레임 워크를 타겟팅 할 수도 있습니다. 스크립트를 실시간으로 해석하거나 자신의 바이트 코드로 컴파일하는 대신 일리노이로 컴파일 할 수 있습니다. 또는 이미 .NET에서 사용할 수있는 많은 스크립팅 언어를 기존의 스크립팅 언어로 호스팅 할 수 있습니다.
문자열 대신 바이트 배열로 char *를 사용하고 있습니다. 내가 필요한 '실제'형식의 크기 (즉, 바이트 수)를 설명하는 '호출'함수에서 메타 데이터를 사용할 수 있다고 가정합니다. 이러한 의미에서 유형은 * 알려져 있습니다. 이들은 알려진 바이트 수입니다. –
일반적으로 전달 규칙은 다른 유형의 데이터 (특히 부동 소수점 인수)에 따라 다를 수 있으므로 호출하기 위해 바이트 수 이상이 필요합니다. 하지만 당신이 옳을지도 모르겠지만 win32 __stdcall은 스택에 모든 것을 넣을뿐입니다. – puetzk