Beispiel #1
0
uint32_t dasm_print_instruction(uint32_t eip, uint8_t *data, uint32_t size, char *str)
{
	INSTRUCTION inst;

	// step 2: fetch instruction-
	uint32_t instrsize = get_instruction(&inst, data, MODE_32);
	if( instrsize == 0 )
	{
//		printf("invalid instruction\n");
		return 0;
	}

	str[81] = '\0';
	memset(str, 0x20, 81);

	int i; 
	for (i=0;i<instrsize;i++)
	{
		snprintf(str+i*2, 36-2*i, "%02X", data[i]);
	}
	memset(str+strlen(str), 0x20, 81-strlen(str));



	// step 3: print it
	get_instruction_string(&inst, FORMAT_INTEL, 0, str+32, 31);


	return instrsize;
}
Beispiel #2
0
int get_single_instruction(BYTE* bytes, char* str, size_t bufsize){
    INSTRUCTION inst;
    int len = 0;
    len = get_instruction(&inst, bytes, MODE_32);
    get_instruction_string(&inst, FORMAT_ATT, 0, str, bufsize);
    return len;
}
Beispiel #3
0
/**	---------------------------------------------------------------------------
	\brief	calculate instruction length of Addr 

	\param	
	\return			
	\code
	\endcode		
-----------------------------------------------------------------------------*/
int GetInstructionLength(BYTE* Addr)
{

#ifdef _USE_LIBDASM_LIB		
	
	INSTRUCTION instr = {0};	
	int Len = get_instruction(&instr, 
						Addr,
						MODE_32);
	// check illegal opcode
	if (0 == Len)
	{
		_ASSERTE(!"get_instruction");
		return -1;
	}

	#ifdef _DEBUG
	char string[256] = {0};
	get_instruction_string(&instr, FORMAT_INTEL, 0, string, sizeof(string));
	_tprintf(TEXT("%s\n"), string);
	#endif
	
	return Len;		

#else

	DISASSEMBLER   Disassembler;
	INSTRUCTION *  Instruction = NULL;	
	if (TRUE != InitDisassembler(&Disassembler, ARCH_X86))
	{
		_ASSERTE(!"InitDisassembler");
		return -1;
	}

	ULONG Flags = DISASM_DISASSEMBLE | DISASM_DECODE | DISASM_STOPONERROR | 
					DISASM_STOPONANOMALY | DISASM_STOPONRETURN;
	Instruction = GetInstruction(&Disassembler, 
							(ULONG)Addr, 
							(PBYTE)Addr,
							Flags);
	if (!Instruction) 
	{
		_ASSERTE(!"GetInstruction");
		CloseDisassembler(&Disassembler);

		return -1;
	}

	#ifdef _DEBUG 
	DumpInstruction(Instruction, TRUE, TRUE);
	#endif
	

	int Len = Instruction->Length;
	CloseDisassembler(&Disassembler);
	return Len;

#endif//_USE_LIBDASM_LIB
}
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
	
	}
	
}
Beispiel #5
0
//////////////////////////////////////////////////////////////////////////
// CPU运行,是一个循环
int CPURun()
{
	WORD cs=-1;
	while (1)
	{
		if (debugHelp==1&&OutDisam==1 && (eCPU.cs==cs || cs==(WORD)-1)){
			get_instruction(&inst, (BYTE *)evIP + MemoryStart, MODE_16);
			get_instruction_string(&inst, FORMAT_INTEL, 0, szCode, 300);
			fprintf(fp, "%4x:%4x : %s\n", eCPU.cs, eCPU.ip, szCode);
			fflush(fp);
			cs = eCPU.cs;
				
		}
		

		//MessageBox(NULL, szCode, NULL, NULL);

		debugHelp = 1;

		ExecIns();		
		FlashRAM();
		ExecInt();		
#ifdef _VM_DEBUG_
		if (eCPU.ip==0xa6ba && eCPU.cs==0x1cd)
		{
			__asm nop							//这里方便自己调试程序			
		}
		if (eCPU.ip==0x169 && eCPU.cs==0x8a00)
		{
			__asm nop							//这里方便自己调试程序			
		}
		if (eCPU.ip==0x3d7 && eCPU.cs==0x1e10)
		{
			__asm nop							//这里方便自己调试程序			
		}
#endif
	}	
	return 0;
}
Beispiel #6
0
int main(int argc, char **argv)
{
    INSTRUCTION inst;   // declare struct INSTRUCTION
    unsigned char *data;
    int i, c = 0, bytes, format = FORMAT_INTEL, mode = MODE_32, size, len;
    char string[256];

    if (argc < 2)
    {
        printf("\nSimple x86 disassembler example\n");
        printf("Compiled with libdasm %d.%d.%d.%d\n\n",
            LIBDASM_VERSION_MAJOR,
            LIBDASM_VERSION_MINOR1,
            LIBDASM_VERSION_MINOR2,
            LIBDASM_VERSION_MINOR3);
        printf("Usage: %s <file> [-a|-i] [bytes]\n"
               "  file    file to be disassembled (required)\n"
               "  -a      format: ATT (optional)\n"
               "  -i      format: INTEL (optional, default)\n"
               "  bytes   show raw instruction data (optional, default 8)\n\n",
               argv[0]);
        exit (1);
    }
    data = read_file(&size, argv[1]);

    bytes = 8;
    if (argc > 2)
    {
        if (argv[2][0] == '-')
        {
            switch(argv[2][1])
            {
                case 'a':
                    format = FORMAT_ATT;
                    break;
                case 'i':
                    format = FORMAT_INTEL;
                    break;
            }
            if (argc > 3)
            {
                bytes = atoi(argv[3]);
            }
        }
        else
        {
            bytes = atoi(argv[2]);
        }
    } 

    signal(SIGSEGV, sighandler);

    while (c < size)
    {
        /*
         * get_instruction() has the following parameters:
         *
         * - &inst is a pointer to struct INSTRUCTION
         * - data + c is pointer to data to be disassembled
         * - disassemble in 32-bit mode: MODE_32 
         */
        len = get_instruction(&inst, data + c, mode);

        // Illegal opcode or opcode longer than remaining buffer
        if (!len || (len + c > size))
        {
            printf("%.8x  ", c);
            if (bytes)
            {
                printf("%.2x  ", data[c]);
                for (i = 1; i < bytes*2 - 1; i++)
                {
                    printf(" ");
                }
            }
            if (format == FORMAT_INTEL)
            {
                printf("db 0x%.2x\n", *(data + c));
            }
            else
            {
                printf(".byte 0x%.2x\n", *(data + c));
            }
            c++;
            continue;
        }

        /*
         * Print absolute offset and raw data bytes up to 'bytes'
         * (not needed, but looks nice).
         *
         */
        printf("%.8x  ", c);
        if (bytes)
        {
            for (i = 0; i < MIN(bytes, len); i++)
            {
                printf("%.2x", data[c + i]);
            }
            printf("  ");
            for (i = MIN(bytes, len); i < bytes*2 - len; i++)
            {
                printf(" ");
            }
        }
        /*
         * Print the parsed instruction, format using user-supplied
         * format. We could of course format the instruction in some
         * other way by accessing struct INSTRUCTION members directly.
         */
        get_instruction_string(&inst, format, (DWORD)c, string, sizeof(string));
        printf("%s\n", string);

        c += len;
    } 

    return 0;
}
// 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
	}
	
}
    static DWORD WINAPI debug_A(LPVOID lpParam)
    {
	 para *a = (para *)lpParam;
	CONTEXT thread_context;
	bool key_execption;
	DEBUG_EVENT debugevent;
	FILE *ERRORfile=fopen("ERROELOG.TXT", "a+");
	HANDLE openthread;
	HANDLE openprocess;
	int exception_key=0;
	INSTRUCTION inst;
	char *memery_context = (char*)malloc(sizeof(char));
	char *memory_context = (char*)malloc(sizeof(char));

//**************************************************************************************************************************************

	bool debug_creat_init = DebugActiveProcess(a->pi.dwProcessId);
	if(!debug_creat_init)
	{
	printf("[*]调试器附加失败!错误代码:%d 请检查系统状况!\n",GetLastError());
	fprintf(ERRORfile, "调试器附加失败,请检查系统状况!\n");
	getchar();
	fprintf(ERRORfile,"====================================================================================================调试结束\n");
	return 0;
	}
	printf("[!]调试器附加成功!开始进行调试循环\n");
	while(GetTickCount()-a->start_time<=a->wait_time)
	{
		if(WaitForDebugEvent(&debugevent,1000))//INFINITE一直等待调试事件的发生
		{
			if(debugevent.dwDebugEventCode!=EXCEPTION_DEBUG_EVENT)//不是调试异常事件
			{
				ContinueDebugEvent(debugevent.dwProcessId,debugevent.dwThreadId,DBG_CONTINUE);//释放所有的线程
				continue;
			}
			if((openthread =OpenThread(THREAD_ALL_ACCESS,FALSE,debugevent.dwThreadId))==NULL)
			{
				printf("附加进程出错,错误代码:%d",GetLastError());
				fprintf(ERRORfile, "附加进程出错,错误代码:%d",GetLastError());
				getchar();
				fprintf(ERRORfile,"====================================================================================================调试结束\n");
				return 0;
			}
			thread_context.ContextFlags=CONTEXT_FULL;
			if(GetThreadContext(openthread,&thread_context)==0)
			{
			printf("获取进程信息失败! 错误代码:%d\n",GetLastError());
			fprintf(ERRORfile, "获取进程信息失败!\n");
			getchar();
			fprintf(ERRORfile,"====================================================================================================调试结束\n");
			return 0;
			}
			switch (debugevent.u.Exception.ExceptionRecord.ExceptionCode)
			{
			case CREATE_THREAD_DEBUG_EVENT:
				printf("[*]调试开始,调试事件CREATE_THREAD_DEBUG_EVENT\n");
				break;
			case EXCEPTION_ACCESS_VIOLATION:
					key_execption=true;
					printf("[!]软件错误!非法访问(EXCEPTION_ACCESS_VIOLATION)!\n");
					fprintf(ERRORfile, "[*]软件错误!非法访问(EXCEPTION_ACCESS_VIOLATION)!\n");
					break;
			case EXCEPTION_INT_DIVIDE_BY_ZERO:
				key_execption=true;
				printf("[!]软件错误!原因EXCEPTION_INT_DIVIDE_BY_ZERO");
				fprintf(ERRORfile, "[*]软件错误!原因EXCEPTION_INT_DIVIDE_BY_ZERO");
				break;
			case EXCEPTION_STACK_OVERFLOW:
				key_execption=true;
				printf("[!]软件错误!原因EXCEPTION_STACK_OVERFLOW");
				fprintf(ERRORfile, "[*]软件错误!原因EXCEPTION_STACK_OVERFLOW");
			case EXIT_PROCESS_DEBUG_EVENT:
				printf("[!]软件退出调试器!\n");
				break;
			default:
				key_execption=FALSE;
				ContinueDebugEvent(debugevent.dwProcessId,debugevent.dwThreadId,DBG_CONTINUE);
			}

			if(key_execption)//异常逆向
			{
				exception_key++;
				if((openprocess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,debugevent.dwProcessId))==NULL)
				{
				printf("[!]错误!进程附加失败!\n");
				fprintf(ERRORfile, "[!]错误!进程附加失败!\n");
				return -1;
				}

				ReadProcessMemory(openprocess,(void*)thread_context.Eip,memery_context,32,NULL);
				printf("*******************************************************************************\n");
				get_instruction(&inst,(BYTE *)memery_context,MODE_32);
				get_instruction_string(&inst,FORMAT_INTEL,0,memory_context,64);
				printf("[*]发现异常\n CPU:  EIP [%x] EAX [%x] EBX [%x] ECX [%x] EDX [%x]\n ",thread_context.Eip,thread_context.Eax,thread_context.Ebx,thread_context.Ecx,thread_context.Edx);
				printf("[*]ESI [%x] EDI [%x] EBP [%x]\n",thread_context.Esi,thread_context.Edi,thread_context.Ebp);
				printf("[*]异常内存 %x",memery_context);

				fprintf(ERRORfile,"[*]发现异常\n CPU:  EIP [%x] EAX [%x] EBX [%x] ECX [%x] EDX [%x]\n ",thread_context.Eip,thread_context.Eax,thread_context.Ebx,thread_context.Ecx,thread_context.Edx);
				fprintf(ERRORfile,"[*]ESI [%x] EDI [%x] EBP [%x]\n",thread_context.Esi,thread_context.Edi,thread_context.Ebp);
				fprintf(ERRORfile,"[*]异常内存 %x",memery_context);
				key_execption=FALSE;
				printf("[*]异常分析完成!\n");
				printf("*******************************************************************************\n");
			}
			ContinueDebugEvent(debugevent.dwProcessId,debugevent.dwThreadId,DBG_CONTINUE);
			printf("剩余调试时间:  %d",GetTickCount()-a->start_time);
		}
	}
	printf("[*]进程  调试完成,花费时间:%dms,发现异常数目为:%d\n",a->wait_time,exception_key);
	printf("[*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*]\n");
	fprintf(ERRORfile,"[*]进程  调试完成,花费时间:%dms,发现异常数目为:%d\n",a->wait_time,exception_key);
	fprintf(ERRORfile,"[*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*][*]\n");
        return 0;
   }