Example #1
0
/*
 * Initializes the program counter and returns the number of instructions.
 */
void mapProgram(FILE* program) {
    Seq_T words = Seq_new(PROGRAM_HINT);

    int c = getc(program);
    while(c != EOF) {
        UM_Word temp = 0;
        temp = Bitpack_newu(temp, 8, 24, c);
        for(int bit = 16; bit >=0; bit -=8){
            int b = getc(program);
            temp = Bitpack_newu(temp, 8, bit, b);
        }

        UM_Word* instr;
        NEW(instr);
        *instr = temp;
        Seq_addhi(words, instr);
        c = getc(program);
    }

    mapSegment(memorySegments, 0);
    mapInstructions(Seq_length(words));
    int length = instructionLength();

    for(int locToLoad = 0; locToLoad < length; locToLoad++){
        UM_Word* value = (UM_Word*)Seq_get(words, locToLoad);
        loadInstruction(locToLoad, *value);
        FREE(value);
    }

    Seq_free(&words);
}
Example #2
0
/*
 * Creates memeory for the program to run and gets the instruction code along
 * with the registers.
 */
void build_and_execute_um(FILE* program){
    memorySegments = newMem();
    instantiateMem(memorySegments, INITIAL_SET_SIZE);
    initializeRegisters(registers, numRegisters);

    mapProgram(program);
    programCounter = 0;
    numInstructions = instructionLength(); 
    //programPointer = getInstructions(memorySegments);

    while(programCounter < numInstructions){
        UM_Word instruction = getInstruction(programCounter);
        Instruction instr = parseInstruction(instruction);
        execute_instruction(instr);
        if(instr.op == HALT) break;
    }

    freeMem(memorySegments);
}
BOOL InterceptGlobalFunction(FARPROC dwAddressToIntercept, FARPROC dwReplaced, FARPROC dwTrampoline, bool trampolineOnly, BOOL rvOnSkip)
{
    ENTER(dwAddressToIntercept, dwReplaced, dwTrampoline, trampolineOnly, rvOnSkip);
	if(!dwAddressToIntercept)
		return FALSE;

	enum { JMP_REL32 = 0xE9 };

	BYTE* pTargetHead = (BYTE*)dwAddressToIntercept;
	BYTE* pTargetTail = pTargetHead;
	BYTE* pTramp = (BYTE*)dwTrampoline;
	BYTE* pHook = (BYTE*)dwReplaced;

	// trampolines work by running a copy of the first few bytes of the target function
	// and then jumping to the remainder of the target function.
	// this totally breaks down if the first few bytes of the target function is a jump.
	// so, the first thing we do is detect if the target starts with a jump,
	// and if so, we follow where the jump goes instead of hooking the target directly.
	//if(tasflags.movieVersion >= 65)
	//{
		for(int i = 0; *pTargetTail == JMP_REL32; i++)
		{
			int diff = *(DWORD*)(pTargetTail+1) + 5;
			pTargetTail += diff;
			if(pTargetTail == pHook)
			{
				if(i == 0)
					LOG() << "already hooked. skipping.";
				else
					LOG() << "already hooked (from " << pTargetTail - diff  << " to " << pTargetTail
                          << ") although the hook chain is longer than expected. skipping.";
				return rvOnSkip;
			}
			else
			{
				if(i < 64)
					LOG() << "rejump detected in target (from " << pTargetTail - diff << " to " << pTargetTail
                          << "). following chain...";
				else
				{
					LOG() << "hook chain is too long. target function jumps to itself? skipping.";
					return rvOnSkip;
				}
			}
		}

		if(pTargetHead == pHook || pTramp == pHook || pTargetHead == pTramp)
		{
			LOG() << "bad input? target=" << pTargetHead << ", hook=" << pHook
                  << ", tramp=" << pTramp << ". skipping hook.";
			return rvOnSkip;
		}
	//}
	/*else // old version. if avast! is installed, this results in an incorrect trampoline which will crash the game.
	{
		if(*pTargetHead == JMP_REL32)
		{
			int diff = *(DWORD*)(pTargetHead+1) + 5;
			pTargetHead += diff;
			debugprintf("rejump detected (from 0x%X to 0x%X). attempting to remove...\n", dwAddressToIntercept, pTargetHead);
			dwAddressToIntercept = (FARPROC)pTargetHead;
		}
		pTargetTail = pTargetHead;
		if(pTargetHead == pHook)
		{
			debugprintf("already hooked (0x%X). skipping.\n", pTargetHead);
			return rvOnSkip;
		}
	}*/

	LOG() << "want to hook " << pTargetHead << " to call " << pHook
          << ", and want trampoline " << pTramp << " to call " << pTargetTail;

	if(*pTramp == JMP_REL32)
	{
		int diff = *(DWORD*)(pTramp+1) + 5;
		LOG() << "rejump detected in trampoline (from " << pTramp << " to " << pTramp + diff << ". giving up.";
		return rvOnSkip;
	}

	// we'll have to overwrite 5 bytes, which means we have to backup at least 5 bytes (up to next instruction boundary)
	int offset = 0;
	while(offset < 5)
		offset += instructionLength(pTargetTail + offset);

	DWORD dwOldProtect;

	// in the trampoline, write the first 5+ bytes of the target function followed by a jump to our hook
	VirtualProtect((void*)dwTrampoline, 5+offset, PAGE_EXECUTE_READWRITE, &dwOldProtect); 
	for(int i=0; i<offset; i++) 
		*pTramp++ = *pTargetTail++; 
	*pTramp++ = JMP_REL32;
	*((int*)pTramp) = (int)(pTargetTail - (pTramp + 4)); 
	VirtualProtect((void*)dwTrampoline, 5+offset, PAGE_EXECUTE, &dwOldProtect); 

	if(!trampolineOnly)
	{
		// overwrite the first 5 bytes of the target function with a jump to our hook
		VirtualProtect((void*)dwAddressToIntercept, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect); 
		*pTargetHead++ = JMP_REL32;
		*((signed int *)(pTargetHead)) = (int)(pHook - (pTargetHead +4)); 
		VirtualProtect((void*)dwAddressToIntercept, 5, PAGE_EXECUTE, &dwOldProtect); 
	}

	// flush the instruction cache to make sure the modified code is executed
	FlushInstructionCache(GetCurrentProcess(), NULL, NULL); 

	return TRUE; 
}
Example #4
0
/*
 * Executes the Instruction based on the opcode.
 */
static inline void execute_instruction(Instruction instr){
    switch(instr.op) {
        case MOVE:{
            conditionalMove(registers, instr.reg1, instr.reg2, instr.reg3);
            programCounter++;
            break;
        }
        case SEGLOAD:{
            UM_Word ID = registers[instr.reg2];
            UM_Word offset = registers[instr.reg3];
            UM_Word toStore = segmentedLoad(memorySegments, ID, offset);
            registers[instr.reg1] = toStore;
            programCounter++;
            break;
        }
        case SEGSTORE:{
            UM_Word ID = registers[instr.reg1];
            UM_Word offset = registers[instr.reg2];
            UM_Word value = registers[instr.reg3];
            segmentedStore(memorySegments, ID, offset, value);
            programCounter++;
            break;
        }
        case ADD:{
            addition(registers, instr.reg1, instr.reg2, instr.reg3);
            programCounter++;
            break;
        }
        case MULTIPLY:{
            multiplication(registers, instr.reg1, instr.reg2, instr.reg3);
            programCounter++;
            break;
        }
        case DIVIDE:{
            division(registers, instr.reg1, instr.reg2, instr.reg3);
            programCounter++;
            break;
        }
        case NAND:{
            bitwiseNAND(registers, instr.reg1, instr.reg2, instr.reg3);
            programCounter++;
            break;
        }
        case HALT: {
            programCounter = 0;
            break;
        }
        case MAP:{
            UM_Word length = registers[instr.reg3];
            registers[instr.reg2] = mapSegment(memorySegments, length);
            programCounter++;
            break;
        }
        case UNMAP:{
            UM_Word ID = registers[instr.reg3];
            unmapSegment(memorySegments, ID);
            programCounter++;
            break;
        }
        case OUTPUT:{
            output(registers, instr.reg3);
            programCounter++;
            break;
        }
        case INPUT:{
            input(registers, instr.reg3);
            programCounter++;
            break;
        }
        case LOADPROG:{
            UM_Word ID = registers[instr.reg2];
            if(ID != 0){
                loadProgram(memorySegments, ID);
                numInstructions = instructionLength(memorySegments);
                //programPointer = getInstructions(memorySegments);
            }
            programCounter = registers[instr.reg3];
            break;
        }
        case LOADVAL:{
            registers[instr.reg1] = instr.value;
            programCounter++;
            break;
        }
    }
}