Bitsum Community Forum

General Category => PECompact, PESuite, PEBundle, and other developer tools => Topic started by: MrManlyMan on December 12, 2009, 02:53:44 PM

Title: what are the restrictions for writing plugins?
Post by: MrManlyMan on December 12, 2009, 02:53:44 PM
Hi,

  I'm trying to write a codec plugin in c.  I'm having trouble specifically with the Decode.  I've avoided any globals or constants and external references.  I'm pulling api calls through pLoadLibrary/pGetProcAddress.  Am I missing anything?  I'm trying to get values from the registry its somewhat working but I'm getting strange behavior after getting the first key.

Thanks.
Title: Re: what are the restrictions for writing plugins?
Post by: Jeremy Collake on December 12, 2009, 04:38:18 PM
Its hard to say what the problem is without seeing the code. If you would like to post your code here, publicly, then perhaps I or someone could tell you the problem.
Title: Re: what are the restrictions for writing plugins?
Post by: Jeremy Collake on December 12, 2009, 04:44:20 PM
... it sounds like you've got the basic principle down, that your decoder must be able to stand-alone, contiguous, and not have external references. That's why I suggest posting the code, it will be easier than going through theoretical conditions. You can email it to me if it is private.
Title: Re: what are the restrictions for writing plugins?
Post by: MrManlyMan on December 12, 2009, 09:15:13 PM
Thanks so much for taking a look.  Here it is:

#include "stdafx.h"
#include "pec2codec_template.h"
#include "..\pec2codecsdk.h"
#include "Codec_0_EntryPoints.h"

/////////////////////////////////////////////////////////////////////////////////////
//
// GetCodecName
//
// Return the wide-characte rname of this CODEC.
//
//

static const char * stringtable[] =
{
"user32.dll",
"MessageBoxA",
"SOFTWARE\\Microsoft\\Cryptography",
"MachineGuid",
"SOFTWARE\\MyComputer\\MySoftware\\1.0",
"user",
"Advapi32.dll",
"RegOpenKeyExA",
"RegQueryValueExA",
"RegCloseKey",
"WTF",
"OMG"
};


DWORD WINAPI GetCodecName(PWCHAR pwszName, DWORD dwBufSize)
{
if(dwBufSize<=wcslen(CODEC_NAME))
{
if(pwszName)
{
*pwszName=NULL;
}
return wcslen(CODEC_NAME)+1;
}
else if(!dwBufSize)
{
return wcslen(CODEC_NAME)+1;
}
wcscpy(pwszName,CODEC_NAME);
return wcslen(pwszName);
}


DWORD WINAPI GetCodecAuthor(PWCHAR pwszAuthor, DWORD dwBufSize)
{
if(dwBufSize<=wcslen(CODEC_AUTHOR))
{
if(pwszAuthor)
{
*pwszAuthor=NULL;
}
return wcslen(CODEC_AUTHOR)+1;
}
else if(!dwBufSize)
{
return wcslen(CODEC_AUTHOR)+1;
}
wcscpy(pwszAuthor,CODEC_AUTHOR);
return wcslen(pwszAuthor);
}

#define CODEC_VERSION_MAJOR 1
#define CODEC_VERSION_MINOR 0
#define CODEC_VERSION (CODEC_VERSION_MAJOR*100)+CODEC_VERSION_MINOR

DWORD WINAPI GetCodecVersion(PDWORD pdwSDKVersion)
{
if(pdwSDKVersion)
{
*pdwSDKVersion=PEC2_CODEC_SDK_VERSION;
}
return CODEC_VERSION;
}

/////////////////////////////////////////////////////////////////////////////////////
//
//  Encode function
//
//  This codec simply copies the data from the source to the destination
//  and appends a flag. It actually expands the data, which is a perfectly
//  legal result no matter what the expansion size is. Of course, a compression
//  function would return a buffer smaller than the original (provided compression
//  succeeds).
//

DWORD WINAPI Encode( LPVOID lpvSource, DWORD dwLength, LPVOID lpvDest, DWORD *pdwDestSize, DWORD dwLevel, PFNCodecCallback Callback )
{
int nR;
PCODEC_0_HEADER pBlockHeader=(PCODEC_0_HEADER)lpvDest;

nR = sizeof(CODEC_0_HEADER) + dwLength;
//
// make sure destination buffer is big enough to handle our header
// expansion of the source data. If not, return PEC2_CODEC_ERROR_INSUFFICIENT_BUFFER
// so that the caller will allocate more and reinvoke.
//
if (*pdwDestSize<nR)
{
*pdwDestSize=nR;
return PEC2_CODEC_ERROR_INSUFFICIENT_BUFFER;
}

pBlockHeader->dwDecodedSize = dwLength;
pBlockHeader->dwSignature = CODEC_0_SIGNATURE;

int i;
for ( i=0; i<sizeof(stringtable)/sizeof(stringtable[0]); i++ )
{
strcpy( pBlockHeader->strings[i], stringtable[i] );
}

//
// copy source data to destination buffer
//
memcpy( (char*)(pBlockHeader+1),lpvSource,dwLength);

return nR;
}

typedef
int (*MessageBoxA_t)(   
    __in_opt HWND hWnd,
    __in_opt LPCSTR lpText,
    __in_opt LPCSTR lpCaption,
    __in UINT uType);

typedef
LSTATUS
(*RegOpenKeyExA_t) (
    __in HKEY hKey,
    __in_opt LPCSTR lpSubKey,
    __in_opt DWORD ulOptions,
    __in REGSAM samDesired,
    __out PHKEY phkResult
    );

typedef
WINADVAPI
LSTATUS
(*RegQueryValueExA_t) (
    __in HKEY hKey,
    __in_opt LPCSTR lpValueName,
    __reserved LPDWORD lpReserved,
    __out_opt LPDWORD lpType,
    __out_bcount_part_opt(*lpcbData, *lpcbData) __out_data_source(REGISTRY) LPBYTE lpData,
    __inout_opt LPDWORD lpcbData
    );

typedef
WINADVAPI
LSTATUS
(*RegCloseKey_t) (
    __in HKEY hKey
    );


#define BUFFER_SIZE 8192

DWORD WINAPI Decode_Small(LPVOID lpvSource, LPVOID lpvDest, PEC2_DECODE_EXTRA * lpExtraData)
{
PCODEC_0_HEADER h = (PCODEC_0_HEADER)lpvSource;

//
// import functions
//
HMODULE user32_dll = lpExtraData->pLoadLibraryA( h->strings[0] );
MessageBoxA_t pMessageBoxA = (MessageBoxA_t)lpExtraData->pGetProcAddress( user32_dll, h->strings[1] );

HMODULE Advapi32_dll = lpExtraData->pLoadLibraryA( h->strings[6] );
RegOpenKeyExA_t pRegOpenKeyExA = (RegOpenKeyExA_t)lpExtraData->pGetProcAddress( Advapi32_dll, h->strings[7] );
RegQueryValueExA_t pRegQueryValueExA = (RegQueryValueExA_t)lpExtraData->pGetProcAddress( Advapi32_dll, h->strings[8] );
RegCloseKey_t pRegCloseKey = (RegCloseKey_t)lpExtraData->pGetProcAddress( Advapi32_dll, h->strings[9] );

//
// create buffer for machine, user, and product id
//
DWORD size = BUFFER_SIZE;
DWORD n = 0;
BYTE * buffer = (BYTE*)lpExtraData->pVirtualAlloc( NULL, size, MEM_COMMIT, PAGE_READWRITE );
if ( !buffer )
return -1;

HKEY hkey;

//
// retrieve machine id from registry
//
size = BUFFER_SIZE - n;
if ( pRegOpenKeyExA( HKEY_LOCAL_MACHINE, h->strings[2], 0, KEY_QUERY_VALUE, &hkey ) != ERROR_SUCCESS ) return -1;
if ( pRegQueryValueExA( hkey, h->strings[3], 0, NULL, buffer+n, &size ) != ERROR_SUCCESS ) return -1;
if ( pRegCloseKey( hkey ) != ERROR_SUCCESS ) return -1;
n += size;

//
// retrieve current user id from registry
//
size = BUFFER_SIZE - n;
if ( pRegOpenKeyExA( HKEY_LOCAL_MACHINE, h->strings[4], 0, KEY_QUERY_VALUE, &hkey ) != ERROR_SUCCESS ) return -1;
if ( pRegQueryValueExA( hkey, h->strings[5], 0, NULL, buffer+n, &size ) != ERROR_SUCCESS ) return -1;
if ( pRegCloseKey( hkey ) != ERROR_SUCCESS ) return -1;
n += size;

pMessageBoxA( NULL, (char*)buffer, h->strings[0], MB_OK );

return -1;
}

DWORD WINAPI GetDecodeSmallFuncSize()
{
unsigned char *pStart=(unsigned char *)&Decode_Small;
unsigned char *pEnd=(unsigned char *)&GetDecodeSmallFuncSize;
return (pEnd-pStart);
}


Title: Re: what are the restrictions for writing plugins?
Post by: Jeremy Collake on December 12, 2009, 10:09:36 PM
At a cursory glance, I see no glaring errors. So, its hard to say the problem without running it through a debugger. You appear to have obeyed all necessary constraints. There is the possibility of a registry handle leak in failure conditions, but that's not at all relevant, and this isn't final code or a college test, lol. It may be some implementation error in your code I'm not immediately seeing. I am out of time for now.

If you have the registered version of PECompact, you can use the pec2ldr_debug.dll loader host to help you more easily debug a compressed program. If you don't have it, maybe I can email it to you so you can trace through things in a debugger. You will just need to email me and tell me from what company you are coming from so I can ensure you are legit.

Email me at jeremy@bitsum.com ..



Title: Re: what are the restrictions for writing plugins?
Post by: Jeremy Collake on December 15, 2009, 09:13:47 AM
The user here reported that after switching to assembly, he had no problems. This suggest that the a possible problem was in the compiler settings. The compiler may have had a feature turned on that called out to a CRT function (i.e. buffer security check) from the decoder.
Title: Re: what are the restrictions for writing plugins?
Post by: safred on January 05, 2011, 10:10:17 AM
I ran into the same issues, calling system API in my codec DecodeSmall function would work a couple of times, and then crash. The problem got solved when I changed the "Calling Convention" option to "__stdcall (/Gz)" in Visual Studio's Project Property page -> Configuration Properties -> C/C++ -> Advanced.
Thought this might help.
Title: Re: what are the restrictions for writing plugins?
Post by: Jeremy Collake on January 06, 2011, 01:46:13 PM
Yes, and this is something I should have made clear in the documentation, the calling convention MUST be stdcall, else the results could be anything from half-working to crashing all the time. This is the standard Windows  API calling convention (by and large) so it is implicit to some degree, but it is NOT the default C/C++ calling convention, so does need specifically declared in the function prototype OR project compiler configuration.