Пример #1
0
bool IATSearch::findIATAdvanced( DWORD_PTR startAddress, DWORD_PTR* addressIAT, DWORD* sizeIAT )
{
    BYTE *dataBuffer;
    DWORD_PTR baseAddress;
    SIZE_T memorySize;

    findExecutableMemoryPagesByStartAddress(startAddress, &baseAddress, &memorySize);

    if (memorySize == 0)
        return false;

    dataBuffer = new BYTE[memorySize];

    if (!readMemoryFromProcess((DWORD_PTR)baseAddress, memorySize,dataBuffer))
    {
#ifdef DEBUG_COMMENTS
        Scylla::debugLog.log(L"findAPIAddressInIAT2 :: error reading memory");
#endif
        return false;
    }

    std::set<DWORD_PTR> iatPointers;
    DWORD_PTR next;
    BYTE * tempBuf = dataBuffer;
    while(decomposeMemory(tempBuf, memorySize, (DWORD_PTR)baseAddress) && decomposerInstructionsCount != 0)
    {
        findIATPointers(iatPointers);

        next = (DWORD_PTR)(decomposerResult[decomposerInstructionsCount - 1].addr - baseAddress);
        next += decomposerResult[decomposerInstructionsCount - 1].size;
        // Advance ptr and recalc offset.
        tempBuf += next;

        if (memorySize <= next)
        {
            break;
        }
        memorySize -= next;
        baseAddress += next;
    }

    if (iatPointers.size() == 0)
        return false;

    filterIATPointersList(iatPointers);

    *addressIAT = *(iatPointers.begin());
    *sizeIAT = (DWORD)(*(--iatPointers.end()) - *(iatPointers.begin()) + sizeof(DWORD_PTR));

    //Scylla::windowLog.log(L"IAT Search Advanced: Found %d (0x%X) possible IAT entries.", iatPointers.size(), iatPointers.size());
    //Scylla::windowLog.log(L"IAT Search Advanced: Possible IAT first " PRINTF_DWORD_PTR_FULL L" last " PRINTF_DWORD_PTR_FULL L" entry.", *(iatPointers.begin()), *(--iatPointers.end()));

    delete [] dataBuffer;

    return true;
}
void runPlugin(static HANDLE hProcess, PUNRESOLVED_IMPORT unresolvedImport, unsigned int eip){

	DWORD_PTR invalidApiAddress = 0;
	INSTRUCTION inst;
	int max_instruction_size = sizeof(UINT8)*15;
	LPVOID instruction_buffer = (LPVOID)malloc(max_instruction_size);
	int instruction_size;
	char buffer[200];

	while (unresolvedImport->ImportTableAddressPointer != 0){ //last element is a nulled struct
		
		printf("Unresolved : 0x%08x\n", unresolvedImport->InvalidApiAddress);

		invalidApiAddress = unresolvedImport->InvalidApiAddress;
		readMemoryFromProcess(hProcess, invalidApiAddress, max_instruction_size, instruction_buffer);

		instruction_size = get_instruction(&inst, (BYTE *)instruction_buffer, MODE_32);
		get_instruction_string(&inst, FORMAT_ATT, 0, buffer, sizeof(buffer));
		printf("INS: %s\n",buffer);

		if(inst.type == INSTRUCTION_TYPE_PUSH){
			    //pushl $0x770fdfa4 
			 char *pch = strstr (buffer,"0x");
			 //printf("ADDRESS: %s\n",pch);
			 unsigned int correct_address = (unsigned int)strtoul(pch,NULL,16);
			 printf("ADDRESS: %08x\n",correct_address);
			 bool res = writeMemoryToProcess(hProcess, (DWORD_PTR)(unresolvedImport->ImportTableAddressPointer), sizeof(correct_address), &correct_address);
			 printf("writeMemoryToProcess result %d\n" , res);
		}else{
			if(inst.type == INSTRUCTION_TYPE_JMP){
				// jmp 0x73d3673d
			    //printf("ADDRESS: %s\n",pch);

			   unsigned int correct_address = ( (unsigned int)strtoul(strstr(buffer, "jmp") + 4 + 2, NULL, 16)) + invalidApiAddress;
			
			  //printf("ADDRESS: %08x\n",correct_address);
			  bool res =  writeMemoryToProcess(hProcess, (DWORD_PTR)(unresolvedImport->ImportTableAddressPointer), sizeof(correct_address), &correct_address);
			  //printf("writeMemoryToProcess result %d\n" , res);
			}
		}

		//if libdasm fails to recognize the insruction bypass this instruction
		if(instruction_size == 0){
			invalidApiAddress = invalidApiAddress + 1;
			continue;
		}

		unresolvedImport++; //next pointer to struct
	
	}
	
}
Пример #3
0
DWORD_PTR IATSearch::findAPIAddressInIAT(DWORD_PTR startAddress)
{
    const size_t MEMORY_READ_SIZE = 200;
    BYTE dataBuffer[MEMORY_READ_SIZE];

    DWORD_PTR iatPointer = 0;
    int counter = 0;

    // to detect stolen api
    memoryAddress = 0;
    memorySize = 0;

    do
    {
        counter++;

        if (!readMemoryFromProcess(startAddress, sizeof(dataBuffer), dataBuffer))
        {
#ifdef DEBUG_COMMENTS
            Scylla::debugLog.log(L"findAPIAddressInIAT :: error reading memory " PRINTF_DWORD_PTR_FULL, startAddress);
#endif
            return 0;
        }

        if (decomposeMemory(dataBuffer, sizeof(dataBuffer), startAddress))
        {
            iatPointer = findIATPointer();
            if (iatPointer)
            {
                if (isIATPointerValid(iatPointer, true))
                {
                    return iatPointer;
                }
            }
        }

        startAddress = findNextFunctionAddress();
        //printf("startAddress %08X\n",startAddress);
    } while (startAddress != 0 && counter != 8);

    return 0;
}
Пример #4
0
bool IATSearch::isIATPointerValid(DWORD_PTR iatPointer, bool checkRedirects)
{
    DWORD_PTR apiAddress = 0;

    if (!readMemoryFromProcess(iatPointer,sizeof(DWORD_PTR),&apiAddress))
    {
#ifdef DEBUG_COMMENTS
        Scylla::debugLog.log(L"isIATPointerValid :: error reading memory");
#endif
        return false;
    }

    //printf("Win api ? %08X\n",apiAddress);

    if (isApiAddressValid(apiAddress) != 0)
    {
        return true;
    }
    else
    {

        if (checkRedirects)
        {
            //maybe redirected import?
            //if the address is 2 times inside a memory region it is possible a redirected api
            if (apiAddress > memoryAddress && apiAddress < (memoryAddress+memorySize))
            {
                return true;
            }
            else
            {
                getMemoryRegionFromAddress(apiAddress, &memoryAddress, &memorySize);
            }
        }
    }

    return false;
}
Пример #5
0
bool IATSearch::findIATStartAndSize(DWORD_PTR address, DWORD_PTR * addressIAT, DWORD * sizeIAT)
{
    BYTE *dataBuffer = 0;
    DWORD_PTR baseAddress = 0;
    DWORD baseSize = 0;

    getMemoryBaseAndSizeForIat(address, &baseAddress, &baseSize);

    if (!baseAddress)
        return false;

    dataBuffer = new BYTE[baseSize * (sizeof(DWORD_PTR)*3)];

    if (!dataBuffer)
        return false;

    ZeroMemory(dataBuffer, baseSize * (sizeof(DWORD_PTR)*3));

    if (!readMemoryFromProcess(baseAddress, baseSize, dataBuffer))
    {
#ifdef DEBUG_COMMENTS
        Scylla::debugLog.log(L"findIATStartAddress :: error reading memory");
#endif
        delete [] dataBuffer;
        return false;
    }

    //printf("address %X memBasic.BaseAddress %X memBasic.RegionSize %X\n",address,memBasic.BaseAddress,memBasic.RegionSize);

    *addressIAT = findIATStartAddress(baseAddress, address, dataBuffer);

    *sizeIAT = findIATSize(baseAddress, *addressIAT, dataBuffer, baseSize);

    delete [] dataBuffer;

    return true;
}
// Entry point of the plugin
// This function will be called PINdemonium
void runPlugin(static HANDLE hProcess, PUNRESOLVED_IMPORT unresolvedImport, unsigned int eip){
	
	//local variable
	int max_instruction_size = sizeof(UINT8)*15;
	int insDelta;
	char buffer[2048];
	int j,instruction_size;
	INSTRUCTION inst;
	DWORD_PTR invalidApiAddress = 0;
	MEMORY_BASIC_INFORMATION memBasic = {0};
	LPVOID instruction_buffer = (LPVOID)malloc(max_instruction_size);
		
	while (unresolvedImport->ImportTableAddressPointer != 0) //last element is a nulled struct
	{

		bool resolved = false;

		insDelta = 0;
		invalidApiAddress = unresolvedImport->InvalidApiAddress;
		//get the starting IAT address to be analyzed yet
		
		for (j = 0; j <  1000; j++)
		{
			//if we cannot query the invalidApiAddress then bypass the analysis of this address
			SIZE_T result = VirtualQueryEx(hProcess,(LPVOID)invalidApiAddress, &memBasic, sizeof(MEMORY_BASIC_INFORMATION));
			if (!result || memBasic.State != MEM_COMMIT || memBasic.Protect == PAGE_NOACCESS)
			{
				//if the memory region pointed by invalidApiAddress isn't mapped break the for loop and check the next unresolved import
				break;
			}
			//read the memory pointed by invalidApiAddress of the external process in order to disassembke the first instruction found
			//we read 15 bytes because in the x86varchitectures the instructions are guaranteed to fit in 15 bytes
			readMemoryFromProcess(hProcess, invalidApiAddress, max_instruction_size, instruction_buffer);
			//disassemble the first instruction in the buffer
			//instruction_size will contains the length of the disassembled instruction (0 if fails)
			instruction_size = get_instruction(&inst, (BYTE *)instruction_buffer, MODE_32);
			//if libdasm fails to recognize the insruction bypass this instruction
			if(instruction_size == 0){
				invalidApiAddress = invalidApiAddress + 1;
				insDelta = insDelta + 1;
				continue;
			}
			get_instruction_string(&inst, FORMAT_ATT, 0, buffer, sizeof(buffer));
			//check if it is a jump		
			if (strstr(buffer, "jmp"))
			{				
				//calculate the correct answer (add the invalidApiAddress to the destination of the jmp because it is a short jump)
				unsigned int correct_address = ( (unsigned int)std::strtoul(strstr(buffer, "jmp") + 4 + 2, NULL, 16)) + invalidApiAddress;
				/*	
				printf("\n\n---------------- MINI REP --------------\n");
				printf("INST %s: \n", buffer);
				printf("INVALID API :  %08x \n", invalidApiAddress);
				printf("INST DELTA %d \n", insDelta);
				printf("IAT POINTER : %p\n", unresolvedImport->ImportTableAddressPointer);
				printf("CORRECT ADDR : %08x\n", correct_address);
				//printf("SIZE OF CORRECT ADDR: %d\n", sizeof(correct_address));
				printf("---------------- END MINI REP --------------\n\n");
				*/
				//if the target address is in a memory space dedicated to dlls we have finished our check
				if(correct_address >= 0x50000000 && correct_address <= 0x7f000000){
					//subtract the stolen API executed
					correct_address = correct_address - insDelta;
					writeMemoryToProcess(hProcess, (DWORD_PTR)(unresolvedImport->ImportTableAddressPointer), sizeof(correct_address), &correct_address);
					//unresolved import probably resolved
					resolved = true;
					break;
				}
				//follow the target address of the jmp and continue the search
				//we don't have to increase the INSDelta beccause the jmp itself is not a stolen API (instruction belonging to the dll)
				else{
					invalidApiAddress = correct_address;
					continue;
				}
				
			}
			//if not increment the delta for the next fix (es : if we have encountered 4 instruction before the correct jmp we have to decrement the correct_address by 16 byte)
			insDelta = insDelta + instruction_size;
			//check the next row inthe IAT
			invalidApiAddress = invalidApiAddress + instruction_size;
		}
		/*
		//if we cannot resolve the import fix it with a dummy address so scylla isn't able to resolve the API and it will remove the unresolved import
		// this functionality is optional (set the flag nullify_unknown_iat_entry_flag as true with command line) because it can break the program
 		if(!resolved){
			unsigned int correct_address = 0x0;
			writeMemoryToProcess(hProcess, (DWORD_PTR)(unresolvedImport->ImportTableAddressPointer), sizeof(correct_address), &correct_address);
 			resolved = false;
 		}
		*/
		unresolvedImport++; //next pointer to struct
	}
	
}
Пример #7
0
bool ProcessAccessHelp::readMemoryPartlyFromProcess(DWORD_PTR address, SIZE_T size, LPVOID dataBuffer)
{
    DWORD_PTR addressPart = 0;
    DWORD_PTR readBytes = 0;
    DWORD_PTR bytesToRead = 0;
    MEMORY_BASIC_INFORMATION memBasic = {0};
    bool returnValue = false;

    if (!hProcess)
    {
#ifdef DEBUG_COMMENTS
        Scylla::debugLog.log(L"readMemoryPartlyFromProcess :: hProcess == NULL");
#endif
        return returnValue;
    }

    if (!readMemoryFromProcess(address, size, dataBuffer))
    {
        addressPart = address;

        do
        {
            if (!VirtualQueryEx(ProcessAccessHelp::hProcess,(LPCVOID)addressPart,&memBasic,sizeof(memBasic)))
            {
#ifdef DEBUG_COMMENTS
                Scylla::debugLog.log(L"readMemoryPartlyFromProcess :: Error VirtualQueryEx %X %X err: %u", addressPart,size, GetLastError());
#endif
                break;
            }

            bytesToRead = memBasic.RegionSize;

            if ( (readBytes+bytesToRead) > size)
            {
                bytesToRead = size - readBytes;
            }

            if (memBasic.State == MEM_COMMIT)
            {
                if (!readMemoryFromProcess(addressPart, bytesToRead, (LPVOID)((DWORD_PTR)dataBuffer + readBytes)))
                {
                    break;
                }
            }
            else
            {
                ZeroMemory((LPVOID)((DWORD_PTR)dataBuffer + readBytes),bytesToRead);
            }


            readBytes += bytesToRead;

            addressPart += memBasic.RegionSize;

        } while (readBytes < size);

        if (readBytes == size)
        {
            returnValue = true;
        }

    }
    else
    {
        returnValue = true;
    }

    return returnValue;
}