예제 #1
0
파일: hook.c 프로젝트: tario/rallhook
int get_instructions_size(void* code, int size) {
	_DecodedInst decodedInstructions[32];

	_OffsetType offset = 0;

	unsigned int decodedInstructionsCount;

	#ifdef __x86_64__
		_DecodeType dt = Decode64Bits;
	#elif __i386__
		_DecodeType dt = Decode32Bits;
	#else
		#error "unknown architecture"
	#endif

	distorm_decode(offset, code, size, dt, decodedInstructions, 32, &decodedInstructionsCount);

	int i;
	int totalsize = 0;
	int minsize = get_jmp_size();
	for (i = 0; i < decodedInstructionsCount; i++) {
		totalsize = totalsize + decodedInstructions[i].size;
		if (totalsize >= minsize) {
			return totalsize;
		}
	}

	return totalsize;

}
예제 #2
0
// Count instructions
BYTE* instructionCount(BYTE *func, int tcount) { 

#ifndef _WIN64
  _DecodeType dt = Decode32Bits;
#else
  _DecodeType dt = Decode64Bits;
#endif

#define MAX_INSTRUCTIONS 100

	_DecodeResult res;
	_DecodedInst di[MAX_INSTRUCTIONS];
	unsigned int dic = 0;

  res = distorm_decode(0, (const BYTE *) func, 15, dt, di, MAX_INSTRUCTIONS, &dic);
  if(res == DECRES_INPUTERR)
    dbg("ERROR: distorm_decode failed!");

  DWORD is = 0;
  for(DWORD i=0;i<dic;i++)
  {
    if(is >= tcount)
      return func+is;
    is += di[i].size;
  }
  return 0;
}
예제 #3
0
char* __cdecl GetDisasm(ULONG_PTR pAddress, int* retLen = NULL){ //just a helper doesnt set error code..

	_DecodeResult res;
	_DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
	unsigned int decodedInstructionsCount = 0;
	_DecodeType dt =  isX64 ? Decode64Bits : Decode32Bits;
	_OffsetType offset = 0;

	res = distorm_decode(offset,	// offset for buffer
		(const BYTE *) pAddress,	// buffer to disassemble
		50,							// function size (code size to disasm) 
		dt,							// x86 or x64?
		decodedInstructions,		// decoded instr
		MAX_INSTRUCTIONS,			// array size
		&decodedInstructionsCount	// how many instr were disassembled?
		);

	if (res == DECRES_INPUTERR)	return NULL;
	
	int bufsz = 120;
	char* tmp = (char*)malloc(bufsz);
	memset(tmp, 0, bufsz);
	_snprintf(tmp, bufsz-1 , "%10x  %-10s %-6s %s\n", 
			 pAddress, 
		     decodedInstructions[0].instructionHex.p, 
			 decodedInstructions[0].mnemonic.p, 
			 decodedInstructions[0].operands.p
	);

	if(retLen !=NULL) *retLen = decodedInstructions[0].size;

	return tmp;
}
예제 #4
0
int HookableBytes(ULONG_PTR Function){

	_DecodeResult res;
	_DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
	unsigned int decodedInstructionsCount = 0;
	_DecodeType dt =  isX64 ? Decode64Bits : Decode32Bits;
	_OffsetType offset = 0;

	res = distorm_decode(offset,	// offset for buffer
		(const BYTE *) Function,	// buffer to disassemble
		50,							// function size (code size to disasm) 
									// 50 instr should be _quite_ enough
		dt,							// x86 or x64?
		decodedInstructions,		// decoded instr
		MAX_INSTRUCTIONS,			// array size
		&decodedInstructionsCount	// how many instr were disassembled?
		);

	if (res == DECRES_INPUTERR) return 0;

	DWORD InstrSize = 0;

	for (UINT x = 0; x < decodedInstructionsCount; x++)
	{
		BYTE *pCurInstr = (BYTE *) (InstrSize + (ULONG_PTR)Function);
		if (InstrSize >= 15) break;
		if(UnSupportedOpcode(pCurInstr, g_NumberOfHooks)) break; 
		InstrSize += decodedInstructions[x].size;
	}

	return InstrSize;

}
예제 #5
0
STATUS
ShuDisassembleShellcode(
	IN PVOID DumpedShellcode,
	IN PVOID ShellcodeAddress,
	IN DWORD dwSize
	)
{
	_DecodeResult DecRes;
	_DecodedInst *DecodedInstructions;
	_DecodeType dt = Decode32Bits;
	_OffsetType offset;
	DWORD dwDecodedInstructionsCount;
	DWORD dwNext;
	DWORD i;
	CHAR szLogPath[MAX_PATH];
	CHAR szShellcodeDisassFile[MAX_PATH];
	ERRORINFO err;
	FILE *ShellcodeFile;

	offset = 0;
	dwDecodedInstructionsCount = 0;
	DecodedInstructions = (_DecodedInst *)LocalAlloc(LMEM_ZEROINIT, MAX_INSTRUCTIONS * sizeof(_DecodedInst));

	sprintf(szShellcodeDisassFile, "\\ShellcodeDisass.txt");
	strncpy( szLogPath, MCEDP_REGCONFIG.LOG_PATH, MAX_PATH);
	strncat(szLogPath, szShellcodeDisassFile, MAX_PATH);
	
	ShellcodeFile = fopen( szLogPath, "a");

	if ( ShellcodeFile == NULL )
	{
		REPORT_ERROR("fopen()", &err);
		LocalFree(DecodedInstructions);
		return MCEDP_STATUS_INTERNAL_ERROR;
	}

	while ( TRUE ) 
	{
		DecRes = distorm_decode(offset, (const unsigned char*)DumpedShellcode, dwSize, dt, DecodedInstructions, MAX_INSTRUCTIONS, (unsigned int *)&dwDecodedInstructionsCount);
		if (DecRes == DECRES_INPUTERR)
			return MCEDP_STATUS_GENERAL_FAIL;

		for ( i = 0; i < dwDecodedInstructionsCount; i++ ) 
			fprintf(ShellcodeFile, "%0*I64x (%02d) %-24s %s%s%s\n", dt != Decode64Bits ? 8 : 16, DecodedInstructions[i].offset + (DWORD)ShellcodeAddress, DecodedInstructions[i].size, (char*)DecodedInstructions[i].instructionHex.p, (char*)DecodedInstructions[i].mnemonic.p, DecodedInstructions[i].operands.length != 0 ? " " : "", (char*)DecodedInstructions[i].operands.p);

		if ( DecRes == DECRES_SUCCESS || dwDecodedInstructionsCount == 0 ) 
			break;

		dwNext = (unsigned long)(DecodedInstructions[dwDecodedInstructionsCount-1].offset - offset);
		dwNext += DecodedInstructions[dwDecodedInstructionsCount-1].size;
		DumpedShellcode =  (PVOID)((unsigned int)DumpedShellcode + dwNext);
		dwSize -= dwNext;
		offset += dwNext;
	}

	LocalFree(DecodedInstructions);
	fclose(ShellcodeFile);
	return MCEDP_STATUS_SUCCESS;
}
예제 #6
0
파일: x86dump.c 프로젝트: AlexWMF/vb6tracer
void x86dump(const uint8_t *addr, const char *msg)
{
    report("[x] Disassembling 0x%x: %z", addr, msg);

    while (1) {
        unsigned int used_instruction_count = 0; _DecodedInst ins;

        int ret = distorm_decode((uintptr_t) addr, addr, 16, Decode32Bits,
                &ins, 1, &used_instruction_count);
        if((ret != DECRES_SUCCESS && ret != DECRES_MEMORYERR) ||
                used_instruction_count != 1) {
            report("[-] Disassembly failed");
            return;
        }

        char extra[256];
        extra[0] = 0;

        if(*addr == 0xe8) {
            const uint8_t *fn = addr + *(const uint32_t *)(addr + 1) + 5;
            sprintf(extra, "; 0x%p %s", fn, symbol(fn));
        }
        else if(*addr == 0xff && addr[1] == 0x25) {
            const uint8_t *fn = **(const uint8_t ***)(addr + 2);
            sprintf(extra, "; 0x%p %s", fn, symbol(fn));
        }
        // b879e0817c   MOV EAX, 0x7c81e079
        // ffd0         CALL EAX
        else if(*addr == 0xb8 && addr[5] == 0xff && addr[6] == 0xd0) {
            const uint8_t *fn = *(const uint8_t **)(addr + 1);
            sprintf(extra, "; 0x%p %s", fn, symbol(fn));
        }

        char hex[33];
        sprintf(hex, "%-12s", ins.instructionHex.p);
        if(extra[0] != 0) {
            report("0x%x %z %z %z %z", addr, hex,
                ins.mnemonic.p, ins.operands.p, extra);
        }
        else {
            report("0x%x %z %z %z", addr, hex,
                ins.mnemonic.p, ins.operands.p);
        }

        switch (*addr) {
        case 0xc2: case 0xc3:
            return;

        case 0xff:
            switch (addr[1]) {
            case 0x25: case 0xe0: case 0xe1:
                return;
            }
        }

        addr += ins.size;
    }
}
예제 #7
0
STATUS
ShuDisassmbleRopInstructions(
	IN PVOID Address,
	OUT PCHAR szInstruction,
	IN DWORD dwSize
	)
{
	_DecodeResult DecRes;
	_DecodedInst *DecodedInstructions;
	_DecodeType dt = Decode32Bits;
	_OffsetType offset;
	CHAR szDecodedInst[1024];
	DWORD dwDecodedInstructionsCount;
	DWORD dwNext;
	DWORD i;

	offset = 0;
	dwDecodedInstructionsCount = 0;
	DecodedInstructions = (_DecodedInst *)LocalAlloc(LMEM_ZEROINIT, MAX_INSTRUCTIONS * sizeof(_DecodedInst));

	while ( TRUE ) 
	{
		
		DecRes = distorm_decode(offset, (const unsigned char*)Address, dwSize, dt, DecodedInstructions, MAX_INSTRUCTIONS, (unsigned int *)&dwDecodedInstructionsCount);
		if (DecRes == DECRES_INPUTERR)
			return MCEDP_STATUS_GENERAL_FAIL;

		for ( i = 0; i < dwDecodedInstructionsCount; i++ ) {

			SecureZeroMemory(szDecodedInst, 1024);
			sprintf(szDecodedInst, "%0*I64x (%02d) %-24s %s%s%s\n", dt != Decode64Bits ? 8 : 16, DecodedInstructions[i].offset + (DWORD)Address, DecodedInstructions[i].size, (char*)DecodedInstructions[i].instructionHex.p, (char*)DecodedInstructions[i].mnemonic.p, DecodedInstructions[i].operands.length != 0 ? " " : "", (char*)DecodedInstructions[i].operands.p);
			strcat( szInstruction , szDecodedInst);

			/* Using Decompose API with DF_STOP_ON_RET ? */
			if ( strstr((char*)DecodedInstructions[i].mnemonic.p, "RET") != NULL ||
				 strstr((char*)DecodedInstructions[i].operands.p, "RET") != NULL )
			{
				LocalFree(DecodedInstructions);
				return MCEDP_STATUS_SUCCESS;
			}
		}

		if ( DecRes == DECRES_SUCCESS || dwDecodedInstructionsCount == 0 ) 
			break;

		dwNext = (unsigned long)(DecodedInstructions[dwDecodedInstructionsCount-1].offset - offset);
		dwNext += DecodedInstructions[dwDecodedInstructionsCount-1].size;
		Address =  (PVOID)((unsigned int)Address + dwNext);
		dwSize -= dwNext;
		offset += dwNext;
	}

	LocalFree(DecodedInstructions);
	return MCEDP_STATUS_SUCCESS;
}
예제 #8
0
int NCodeHook<ArchT>::getMinOffset(const unsigned char* codePtr, unsigned int jumpPatchSize) {
	_DecodeResult result;
	_DecodedInst instructions[MaxInstructions];
	unsigned int instructionCount = 0;

	result = distorm_decode(0, codePtr, 20, ArchT::DisasmType, instructions, MaxInstructions, &instructionCount);
	if (result != DECRES_SUCCESS) return -1;

	unsigned int offset = 0;
	for (unsigned int i = 0; offset < jumpPatchSize && i < instructionCount; ++i) {
		if (isBranch((const char*)instructions[i].mnemonic.p)) return -1;
		offset += instructions[i].size;
	}
	// If we were unable to disassemble enough instructions we fail.
	if (offset < jumpPatchSize) return -1;

	return offset;
}
예제 #9
0
bool ProcessAccessHelp::disassembleMemory(BYTE * dataBuffer, SIZE_T bufferSize, DWORD_PTR startOffset)
{
    // Holds the result of the decoding.
    _DecodeResult res;

    // next is used for instruction's offset synchronization.
    // decodedInstructionsCount holds the count of filled instructions' array by the decoder.

    decodedInstructionsCount = 0;

    _OffsetType offset = startOffset;

    res = distorm_decode(offset, dataBuffer, (int)bufferSize, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount);

    /*	for (unsigned int i = 0; i < decodedInstructionsCount; i++) {
    #ifdef SUPPORT_64BIT_OFFSET
    		printf("%0*I64x (%02d) %-24s %s%s%s\n", dt != Decode64Bits ? 8 : 16, decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p);
    #else
    		printf("%08x (%02d) %-24s %s%s%s\n", decodedInstructions[i].offset, decodedInstructions[i].size, (char*)decodedInstructions[i].instructionHex.p, (char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].operands.length != 0 ? " " : "", (char*)decodedInstructions[i].operands.p);
    #endif

    	}*/

    if (res == DECRES_INPUTERR)
    {
#ifdef DEBUG_COMMENTS
        Scylla::debugLog.log(L"disassembleMemory :: res == DECRES_INPUTERR");
#endif
        return false;
    }
    else if (res == DECRES_SUCCESS)
    {
        //printf("disassembleMemory :: res == DECRES_SUCCESS\n");
        return true;
    }
    else
    {
#ifdef DEBUG_COMMENTS
        Scylla::debugLog.log(L"disassembleMemory :: res == %d", res);
#endif
        return true; //not all instructions fit in buffer
    }
}
예제 #10
0
ULONG CalcReplaceSize (ULONG_PTR pOrigFunction)
{
#define MAX_INSTRUCTIONS 15

	_DecodeResult res;
	ULONG ReplaceSize = 0;
	ULONG Index = 0;
	_DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
	unsigned int decodedInstructionsCount = 0;

#ifndef _WIN64
	_DecodeType dt = Decode32Bits;
#else 
	_DecodeType dt = Decode64Bits;
#endif

	_OffsetType offset = 0;
	res = distorm_decode(offset,	
											(const BYTE *) pOrigFunction,
											45,							
											dt,							
											decodedInstructions,		
											MAX_INSTRUCTIONS,		
											&decodedInstructionsCount	
											);

	if (res == DECRES_INPUTERR)
		return 0;

	
	for (Index; Index < decodedInstructionsCount; Index++)
	{
		if (ReplaceSize >= JMP_MIN_LENGTH)
			break;
			
		ReplaceSize += decodedInstructions[Index].size;
	}	
	
	return ReplaceSize;
}
예제 #11
0
VOID *CreateBridge(HOOK_INFO *hinfo)
{
	if (g_pBridgeBuffer == NULL) return NULL;

	UINT x = 0;
	_DecodeResult res;
	_DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
	unsigned int decodedInstructionsCount = 0;
	_DecodeType dt =  isX64 ? Decode64Bits : Decode32Bits;
	_OffsetType offset = 0;

	ULONG_PTR Function = hinfo->Function;
	int JumpSize = GetJumpSize(hinfo->hooktype);

	res = distorm_decode(offset,	// offset for buffer
		(const BYTE *) Function,	// buffer to disassemble
		50,							// function size (code size to disasm) 
									// 50 instr should be _quite_ enough
		dt,							// x86 or x64?
		decodedInstructions,		// decoded instr
		MAX_INSTRUCTIONS,			// array size
		&decodedInstructionsCount	// how many instr were disassembled?
		);

	if (res == DECRES_INPUTERR){
		sprintf(lastError, "Could not disassemble address %x", (UINT)Function);
		//dbgmsg(lastError);
		lastErrorCode = he_cantDisasm;
		return NULL;
	}

	DWORD InstrSize = 0;
	VOID *pBridge = (VOID *) &g_pBridgeBuffer[g_CurrentBridgeBufferSize];

	//copy full instructions from API to our trampoline.
	for (x ; x < decodedInstructionsCount; x++)
	{
		if (InstrSize >= JumpSize) break;

		BYTE *pCurInstr = (BYTE *) (InstrSize + (ULONG_PTR) Function);
		
		if(logLevel >=3){
			dbgmsg(3, "%s+%d \t %-10s %-6s %s", 
				 hinfo->ApiName,
				 InstrSize,
				 decodedInstructions[x].instructionHex.p, 
				 decodedInstructions[x].mnemonic.p, 
				 decodedInstructions[x].operands.p
			);
		}

		if( UnSupportedOpcode(pCurInstr, hinfo->index) ){
			dbgmsg(0, "CreatreBridge::UnSupportedOpcode found missed in pre-Validation?! needed=%d, hookable=%d, cur=%d, type=%s",
						JumpSize, hinfo->hookableBytes,InstrSize, GetHookName(hinfo->hooktype)
				   );
			DebugBreak(); 
			//if we leave here, g_CurrentBridgeBufferSize has been incremented and bytes copied to
			//the alloced g_pBridgeBuffer, but the API itself is untouched.
			return NULL; 
		}

		memcpy(&g_pBridgeBuffer[g_CurrentBridgeBufferSize], (VOID *) pCurInstr, decodedInstructions[x].size);

		g_CurrentBridgeBufferSize += decodedInstructions[x].size;
		InstrSize += decodedInstructions[x].size;
	}

	hinfo->OverwrittenInstructions = x;
	hinfo->OverwrittenBytes = InstrSize; //we will 0xCC this many in API latter for debugging sake...

	//to leave trampoline...
	hookType ht = isX64 ? ht_jmp : ht_pushret; //both absolute address jumps for safety...
	bool rv = WriteJump(&g_pBridgeBuffer[g_CurrentBridgeBufferSize], Function + InstrSize, ht, hinfo->index);
	g_CurrentBridgeBufferSize +=  GetJumpSize(ht);  

	if(!rv) return NULL;

	return pBridge;
}
예제 #12
0
파일: main.c 프로젝트: 340211173/hf-2011
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
	UNICODE_STRING pFcnName;
	
	// Holds the result of the decoding.
	_DecodeResult res;
	// Decoded instruction information.
	_DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
	// next is used for instruction's offset synchronization.
	// decodedInstructionsCount holds the count of filled instructions' array by the decoder.
	unsigned int decodedInstructionsCount = 0, i, next;
	// Default decoding mode is 32 bits, could be set by command line.
	_DecodeType dt = Decode32Bits;

	// Default offset for buffer is 0, could be set in command line.
	_OffsetType offset = 0;
	char* errch = NULL;

	// Buffer to disassemble.
	unsigned char *buf;
	int len = 100;

	// Register unload routine
	DriverObject->DriverUnload = DriverUnload;

	DbgPrint("diStorm Loaded!\n");

	// Get address of KeBugCheck
	RtlInitUnicodeString(&pFcnName, L"KeBugCheck");
	buf = (char *)MmGetSystemRoutineAddress(&pFcnName);
	offset = (unsigned) (_OffsetType)buf;

	DbgPrint("Resolving KeBugCheck @ 0x%08x\n", buf);
	// Decode the buffer at given offset (virtual address).

	while (1) {
		res = distorm_decode(offset, (const unsigned char*)buf, len, dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount);
		if (res == DECRES_INPUTERR) {
			DbgPrint(("NULL Buffer?!\n"));
			break;
		}

		for (i = 0; i < decodedInstructionsCount; i++) {
			// Note that we print the offset as a 64 bits variable!!!
			// It might be that you'll have to change it to %08X...
			DbgPrint("%08I64x (%02d) %s %s %s\n", decodedInstructions[i].offset, decodedInstructions[i].size, 
				 (char*)decodedInstructions[i].instructionHex.p,
				 (char*)decodedInstructions[i].mnemonic.p,
				 (char*)decodedInstructions[i].operands.p);
		}

		if (res == DECRES_SUCCESS || decodedInstructionsCount == 0) {
			break; // All instructions were decoded.
		}

		// Synchronize:
		next = (unsigned int)(decodedInstructions[decodedInstructionsCount-1].offset - offset);
		next += decodedInstructions[decodedInstructionsCount-1].size;

		// Advance ptr and recalc offset.
		buf += next;
		len -= next;
		offset += next;
	}

	DbgPrint(("Done!\n"));
	return STATUS_SUCCESS;
}
예제 #13
0
void Permutator::ProcessNode(Node* n, std::ofstream& gvFile)
{
	_DecodeResult res;
	unsigned int decodedInstructionsCount = 0;
	_DecodeType dt = Decode32Bits;
	_DecodedInst decodedInstructions[MAX_INSTRUCTIONS];

	std::string stateStyleStart = "[ style = \"filled\" penwidth = 1 fillcolor = \"white\" fontname = \"Courier New\" "
		"shape = \"Mrecord\" label =<<table border=\"0\" cellborder=\"0\" cellpadding=\"3\" bgcolor=\"white\">\"";
	std::string stateStyleEnd = "</table>> ];\n";

	std::string stateHeaderStart = "<tr><td bgcolor=\"black\" align=\"center\" colspan=\"2\"><font color=\"white\">";
	std::string stateHeaderEnd = "</font></td></tr>";

	std::string stateDataStart = "<tr><td align=\"left\">";
	std::string stateDataEnd = "</td></tr>";

	BYTE* instructions = n->GetInstructions();
	std::stringstream stream;
	stream << std::hex << n->GetOffset();
	std::string stateName = "\"0x" + stream.str() + "\"";

	try
	{
		gvFile.write(stateName.c_str(), stateName.length());
		gvFile.write(stateStyleStart.c_str(), stateStyleStart.length());
		gvFile.write(stateHeaderStart.c_str(), stateHeaderStart.length());
		gvFile.write(stateName.c_str(), stateName.length());
		gvFile.write(stateHeaderEnd.c_str(), stateHeaderEnd.length());
		while (1)
		{
			res = distorm_decode(n->GetOffset(), (const unsigned char*)instructions, n->GetSize(),
				dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount);
			if (res == DECRES_INPUTERR) {
				std::cerr << "ProcessNode: Disassembly error" << std::endl;
				return;
			}

			for (unsigned int i = 0; i < decodedInstructionsCount; ++i)
			{
				gvFile.write(stateDataStart.c_str(), stateDataStart.length());
				gvFile.write((char*)decodedInstructions[i].mnemonic.p, decodedInstructions[i].mnemonic.length);
				if (decodedInstructions[i].operands.length != 0)
				{
					gvFile.write(" ", 1);
					gvFile.write((char*)decodedInstructions[i].operands.p, decodedInstructions[i].operands.length);
				}
				gvFile.write(stateDataEnd.c_str(), stateDataEnd.length());
			}

			if (res == DECRES_SUCCESS) break;
		}
		gvFile.write(stateStyleEnd.c_str(), stateStyleEnd.length());

		for (unsigned int i = 0; i < n->GetChildren().size(); ++i)
		{
			ProcessNode(n->GetChildren().at(i), gvFile);
		}
	}
	catch (std::fstream::failure e)
	{
		std::cerr << "ProcessNode: Error while writing node information to graphviz file: " << e.what() << std::endl;
		return;
	}

	return;
}
예제 #14
0
void Permutator::__CreateGraph(BYTE* sectionData, _OffsetType blockOffset, DWORD dwSectionSize, _OffsetType parentOffset)
{
	_DecodeResult res;
	unsigned int decodedInstructionsCount = 0;
	_DecodeType dt = Decode32Bits;
	_OffsetType offsetEnd;
	_DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
	unsigned int i;
	QWORD tmpOffset = blockOffset;
	std::string mnemonic, operand;

	std::vector<Block> targets;
	std::queue<Block> blockQueue;
	bool skipFlag;
	bool disasmStopFlag;

	Block block;
	block.offset = blockOffset;
	block.parentOffset = parentOffset;
	blockQueue.push(block);

	while (!blockQueue.empty())
	{
		skipFlag = false;
		Block currentBlock = blockQueue.front();
		blockQueue.pop();

		for (std::vector<Block>::iterator it = targets.begin(); it != targets.end(); ++it)
		{
			if (((*it).offset == currentBlock.offset) && (*it).parentOffset == currentBlock.parentOffset)
			{
				skipFlag = true;
				break;
			}
		}
		if (skipFlag)
			continue;

// Disassembly part
		while (1)
		{
			disasmStopFlag = false;
			res = distorm_decode(currentBlock.offset, (const unsigned char*)(sectionData + currentBlock.offset),
				(DWORD)(dwSectionSize - currentBlock.offset),
				dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount);
			if (res == DECRES_INPUTERR)
			{
				free(sectionData);
				return;
			}

			for (i = 0; i < decodedInstructionsCount; ++i)
			{
				mnemonic = (reinterpret_cast<char*>(decodedInstructions[i].mnemonic.p));
				if (IsJump(mnemonic) ||
					mnemonic.compare("RET") == 0 ||
					mnemonic.compare("RETN") == 0 ||
					mnemonic.substr(0, 2).compare("DB") == 0)
				{
					disasmStopFlag = true;
					break;
				}

				if (mnemonic.compare("CALL") == 0)
				{
					std::string functionOperand = reinterpret_cast<char*> (decodedInstructions[i].operands.p);
					if (IsRegister(functionOperand) || !IsFunctionOperandValid(functionOperand))
						continue;

					QWORD functionOffset = std::stoll(functionOperand, nullptr, 0);
					graph.AddFunctionOffset(tmpOffset, functionOffset - tmpOffset);
				}

				tmpOffset += decodedInstructions[i].size;
			}
			if (disasmStopFlag)
				break;
		}

		offsetEnd = decodedInstructions[i].offset;
		DWORD blockSize = (DWORD)(offsetEnd + decodedInstructions[i].size - currentBlock.offset);
		currentBlock.blockSize = blockSize;

		// Set 1 to block places in dataBytes
		for (DWORD j = 0; j < blockSize; ++j)
		{
			dataBytes[currentBlock.offset + j] = 1;
		}

		targets.push_back(currentBlock);

		if (mnemonic.compare("RET") == 0 ||
			mnemonic.compare("RETN") == 0 ||
			mnemonic.substr(0, 2).compare("DB") == 0)
			continue;

		operand = reinterpret_cast<char*>(decodedInstructions[i].operands.p);
		operand.resize(decodedInstructions[i].operands.length);
		if (IsRegister(operand))
			continue;

		QWORD newOffset = std::stoll(operand, nullptr, 0);

		if (!CheckRange(newOffset))
		{
			std::cerr << "Offset out of CODE section!" << std::endl;
			continue;
		}

		Block positiveJumpBlock;
		positiveJumpBlock.offset = newOffset;
		positiveJumpBlock.parentOffset = currentBlock.offset;
		blockQueue.push(positiveJumpBlock);

		if (mnemonic.compare("JMP") == 0)
			continue;

		QWORD jumpFalseOffset = offsetEnd + decodedInstructions[i].size;

		if (!CheckRange(newOffset))
		{
			std::cerr << "Offset out of CODE section!" << std::endl;
			continue;
		}

		Block negativeJumpBlock;
		negativeJumpBlock.offset = jumpFalseOffset;
		negativeJumpBlock.parentOffset = currentBlock.offset;
		blockQueue.push(negativeJumpBlock);
	}
	
// Graph creation

	for (DWORD i = 0; i < targets.size(); ++i)
	{
		Block b = targets.at(i);
		Node* n = new Node();

		n->SetOffset((DWORD) b.offset);
		n->SetInstructions((BYTE*)(sectionData + b.offset), b.blockSize);
		graph.AddNode(n, (DWORD)b.parentOffset);
	}

	return;
}
예제 #15
0
void Permutator::_CreateGraph(BYTE* sectionData, _OffsetType blockOffset, DWORD dwSectionSize, _OffsetType parentOffset,
	std::vector<Block>& targets)
{
	_DecodeResult res;
	unsigned int decodedInstructionsCount = 0;
	_DecodeType dt = Decode32Bits;
	_OffsetType offset = blockOffset;
	_OffsetType offsetEnd;
	_DecodedInst decodedInstructions[MAX_INSTRUCTIONS];
	unsigned int i;
	QWORD tmpOffset = blockOffset;
	std::string mnemonic, operand;
	bool skipFlag;

	while (1)
	{
		res = distorm_decode(offset, (const unsigned char*)sectionData, dwSectionSize,
			dt, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount);
		if (res == DECRES_INPUTERR)
		{
			free(sectionData);
			return;
		}

		for (i = 0; i < decodedInstructionsCount; ++i)
		{ 
			mnemonic = (reinterpret_cast<char*>(decodedInstructions[i].mnemonic.p));
			if (IsJump(mnemonic) ||
				mnemonic.compare("RET") == 0 ||
				mnemonic.compare("RETN") == 0 ||
				mnemonic.substr(0, 2).compare("DB") == 0)
			{
				break;
			}

			if (mnemonic.compare("CALL") == 0)
			{
				std::string functionOperand = reinterpret_cast<char*> (decodedInstructions[i].operands.p);
				if (IsRegister(functionOperand) || !IsFunctionOperandValid(functionOperand))
					continue;

				QWORD functionOffset = std::stoll(functionOperand, nullptr, 0);
				graph.AddFunctionOffset(tmpOffset, functionOffset - tmpOffset);
			}

			tmpOffset += decodedInstructions[i].size;
		}

		// Main part of graph creation
		offsetEnd = decodedInstructions[i].offset;
		DWORD blockSize = (DWORD)(offsetEnd + decodedInstructions[i].size - offset);
		Node* node = new Node();

		// Set 1 to block places in dataBytes
		for (DWORD j = 0; j < blockSize; ++j)
		{
			dataBytes[blockOffset + j] = 1;
		}

		node->SetOffset((DWORD)offset);
		node->SetInstructions(sectionData, blockSize);

// Newly added code
		skipFlag = false;
		for (std::vector<Block>::iterator it = targets.begin(); it != targets.end(); ++it)
		{
			if (((*it).offset == node->GetOffset()) && (*it).parentOffset == parentOffset)
			{
				skipFlag = true;
				break;
			}
		}
		if (skipFlag)
			return;
		Block b;
		b.offset = node->GetOffset();
		b.parentOffset = parentOffset;
		targets.push_back(b);

		if (graph.AddNode(node, (DWORD)parentOffset))
		{
			return;
		}

		if (mnemonic.compare("RET") == 0 ||
			mnemonic.compare("RETN") == 0 ||
			mnemonic.substr(0, 2).compare("DB") == 0)
			return;

		operand = reinterpret_cast<char*>(decodedInstructions[i].operands.p);
		operand.resize(decodedInstructions[i].operands.length);
		if (IsRegister(operand))
			return;

		QWORD newOffset = std::stoll(operand, nullptr, 0);

		if (!CheckRange(newOffset))
		{
			std::cerr << "Offset out of CODE section!" << std::endl;
			return;
		}

		_CreateGraph(sectionData + blockSize + (newOffset - offsetEnd - decodedInstructions[i].size),
					 newOffset,
					 dwSectionSize - (DWORD)newOffset + (DWORD)offset,
					 node->GetOffset(),
					 targets);

		if (mnemonic.compare("JMP") == 0)
			return;

		QWORD jumpFalseOffset = offsetEnd + decodedInstructions[i].size;
		
		_CreateGraph(sectionData + jumpFalseOffset - offset,
			jumpFalseOffset,
			dwSectionSize - (DWORD)jumpFalseOffset + (DWORD)offset,
			node->GetOffset(),
			targets);

		break;
	}
}