int analyze_module(scanner_search* scanner, module_search* module_data, 
	std::vector<PatchInfo>& vPatchInfo,
	std::bitset<MAX_RELOC_OFFSET>& vRelocOffset,BOOL bIsWOW64)
{
	int hooks_found = 0;
	ZyanU64 runtime_address = module_data->remote_module_base + module_data->text_va;

	//local_loaded_text_section从文件中读的,local_copied_text_section扫描的PE
	std::uintptr_t local_loaded_text_section = module_data->local_loaded_module_buffer + module_data->text_raw;
	std::uintptr_t local_copied_text_section = module_data->copied_image_address + module_data->text_va;

	ZyanU8 previous_instruction_length{};

	if (!bIsWOW64 && !memcmp((PVOID)local_loaded_text_section,
		(PVOID)local_copied_text_section, module_data->text_size))
	{
		printf("相等,不分析!\r\n");
		return 0;
	}

	std::vector<DWORD> rvas;
	for (
		int compare_memory_result = compare_memory((const std::uint8_t*)local_loaded_text_section, (const std::uint8_t*)local_copied_text_section, module_data->text_size);
		compare_memory_result != -1;
		compare_memory_result = compare_memory((const std::uint8_t*)local_loaded_text_section, (const std::uint8_t*)local_copied_text_section, module_data->text_size, ++compare_memory_result)
		)
	{
		const auto rva = (std::uint32_t)(local_copied_text_section + compare_memory_result - module_data->copied_image_address);
		rvas.push_back(rva);
	}

	DWORD dwFirstRva = 0, dwInstructionLen = 0;
	for (const auto& rva : rvas)
	{
		ULONG_PTR ulAdrress = rva;
		if (bIsWOW64 && &vRelocOffset && vRelocOffset[ulAdrress]==1) //是重定位的地址，不继续反汇编分析
			continue;

		if (rva < dwFirstRva + dwInstructionLen) //比较的结果，不同之处在一条指令内，不继续反汇编分析
		{
			continue;
		}
		else
		{
			dwFirstRva = rva;
			runtime_address = module_data->remote_module_base;
			runtime_address += rva;
		}
			
		auto [status, instruction, operands] = scanner->disassembler->disassemble_instruction((void*)(module_data->copied_image_address + rva), /*(uint32_t)(module_data->text_size - offset)*/
			15);
		if (ZYAN_SUCCESS(status))
		{
			dwInstructionLen = instruction->length;
			std::string export_name = memory::pe_viewer::find_module_export_by_rva(module_data->copied_image_address, (uint32_t)(runtime_address - module_data->remote_module_base), bIsWOW64);

			switch (instruction->mnemonic)
			{
			case ZYDIS_MNEMONIC_JMP:
			{
				std::uintptr_t jmp_destination{};

				if (*reinterpret_cast<std::uint16_t*>(module_data->copied_image_address + rva) == 0x25FF)
				{
					jmp_destination = *reinterpret_cast<std::uintptr_t*>(module_data->copied_image_address + rva + instruction->length);
				}
				else
				{
					jmp_destination = scanner->disassembler->get_instruction_absolute_address(*instruction, operands, runtime_address);
				}

				std::string jmp_destination_formatted = find_module_name(scanner, jmp_destination);

				auto [copied_jmp, success] = memory::read_remote_memory<jmp_inst_array>(scanner->process_handle, jmp_destination);
				if (success == false) break;

				auto [absolute_jmp_status, absolute_jmp_instruction, absolute_jmp_operands] = scanner->disassembler->disassemble_instruction(&copied_jmp, sizeof(jmp_inst_array));

				if (ZYAN_SUCCESS(absolute_jmp_status) && absolute_jmp_instruction->mnemonic == ZYDIS_MNEMONIC_JMP)
				{
					//两级跳转,jmp xxx\jmp [xxx]
					std::uintptr_t absolute_jmp_destination{};

					if (copied_jmp.opcode[0] == 0xFF && copied_jmp.opcode[1] == 0x25)
					{
						absolute_jmp_destination = *reinterpret_cast<std::uintptr_t*>(&copied_jmp.opcode[absolute_jmp_instruction->length]);
					}
					else
					{
						absolute_jmp_destination = scanner->disassembler->get_instruction_absolute_address(*absolute_jmp_instruction, absolute_jmp_operands, jmp_destination);
					}

					std::string absolute_jmp_destination_formatted = find_module_name(scanner, absolute_jmp_destination);
					printf("[2] [%p] [%s!%s] [jmp %s]\n", (void*)runtime_address, module_data->module_name.c_str(), export_name.c_str(), absolute_jmp_destination_formatted.c_str());
				}
				else
				{
					//只有一级跳转
					printf("[1] [%p] [%s!%s] [jmp %s]\n", (void*)runtime_address, module_data->module_name.c_str(), export_name.c_str(), jmp_destination_formatted.c_str());
				}

				////恢复钩子
				if (jmp_destination_formatted.find(module_data->module_name)
					== jmp_destination_formatted.npos) //在自己模块里的不恢复
				{
					PatchInfo pi = { 0 };
					DWORD offset = rva - module_data->text_va;
					pi.pDestVOffset = module_data->text_va + offset;
					pi.pSourceROffset = module_data->text_raw + offset;

					pi.dwLen = /*instruction->length*/dwInstructionLen;
					vPatchInfo.push_back(pi);
					printf("恢复钩子!\r\n");
				}
				else
					printf("jmp在自己模块里,不恢复!\r\n");
				hooks_found++;

				break;
			}
			case ZYDIS_MNEMONIC_INT3:
			{
				std::string instruction_buffer = scanner->disassembler->format_instruction(*instruction, operands, runtime_address);
				printf("[0] [%p] [%s!%s] [%s]\n", (void*)runtime_address, module_data->module_name.c_str(), export_name.c_str(), instruction_buffer.c_str());
				break;
			}
			case ZYDIS_MNEMONIC_NOP:
			{
				std::string instruction_buffer = scanner->disassembler->format_instruction(*instruction, operands, runtime_address);
				printf("[0] [%p] [%s!%s] [%s]\n", (void*)runtime_address, module_data->module_name.c_str(), export_name.c_str(), instruction_buffer.c_str());
				break;
			}
			default:
			{
				break;
			}
			}
		}
	}

	return hooks_found;
}