Ir para conteúdo

Os Melhores

Conteúdo popular

Mostrando conteúdo com a maior reputação em 23/05/2026 em Posts

  1. 📌 [LANÇAMENTO] FoxMap Studio V1 — Open Source O editor de mapas mais completo para WYD Fala galera da WebCheats! Se você administra ou está desenvolvendo um servidor de With Your Destiny, sabe o quão trabalhoso e limitado costuma ser o processo de criação e edição de mapas usando ferramentas antigas. Pensando nisso, foi desenvolvido o FoxMap Studio V1, uma ferramenta revolucionária que vai mudar completamente a forma como você customiza o seu servidor! Assista ao vídeo demonstrativo completo e veja a ferramenta em ação: 👉 [Hidden Content] 🔥 O que faz o FoxMap Studio ser diferente? O FoxMap Studio foi criado do zero para ser intuitivo, rápido e extremamente poderoso. Chega de sofrer com ferramentas travadas que exigem reinicializações constantes ou processos manuais complexos. [Hidden Content] [Hidden Content] [/hide] 🌟 Principais Recursos: Edição Visual Completa: Interface limpa, moderna e totalmente interativa para você focar no que realmente importa: a criatividade do seu mapa. Modificações em Tempo Real: Veja cada alteração de terreno, texturas e objetos acontecer instantaneamente na sua tela. Editor Avançado de Terrenos e Alturas: Suba montanhas, crie vales e ajuste o relevo do mapa com pincéis dinâmicos e precisos. Pintura Dinâmica de Texturas: Aplique e misture diferentes texturas de solo diretamente no mapa de forma suave e rápida. Importação e Posicionamento de Objetos 3D: Adicione construções, decorações, portais e elementos de cenário de maneira extremamente simples (com suporte a arquivos .glb/.gltf e conversão inteligente para o formato do cliente). Gestão de Atributos do Mapa: Configure zonas de PvP, áreas seguras (No-PvP), zonas de drop ou teleportes diretamente pela interface do estúdio. Integração Direta com o Cliente: Teste e salve suas alterações diretamente nos arquivos do jogo de forma prática. 📺 Veja o Passo a Passo no Vídeo! No vídeo oficial, mostramos desde a interface de login da plataforma WYD Fox Studio até a criação prática de um cenário completo: Como abrir e carregar os mapas existentes do seu cliente. Utilização das ferramentas de pintura de terreno e elevação de mesh. Importação e rotação livre de objetos e decorações 3D no cenário. Aplicação de efeitos climáticos e iluminação personalizada no mapa. Conversão e salvamento automático dos arquivos para rodar perfeitamente no jogo. Assista aqui: Como Criar Mapas Customizados para WYD — FoxMap Studio 🚀 Como ter acesso? [Hidden Content] A ferramenta conta com uma versão de testes gratuita para você conhecer o potencial do editor. Desenvolvedor: Foxdemo / WYD Fox Studio Para suporte, atualizações constantes e mais ferramentas da nossa suíte de desenvolvimento (Editores de Itens, NPCs, Monstros e Quests em breve!), entre no nosso Discord oficial (link disponível na descrição do vídeo do YouTube). Deixe seu comentário abaixo dizendo o que achou da ferramenta ou qual recurso você gostaria de ver nas próximas atualizações!
    4 pontos
  2. Conteúdo da MARTINA OLIVEIRA, conhecida também como BEIÇOLA DO PRIVACY, PRIVACY DELA GRATIS + Videos vazados totalmente pelada, mostrando e fazendo de tudo. Sem frescura e nem anuncios, basta clicar no link e dar play no video, para ver o Privacy gratis é só se cadastrar. PRIVACY OFICIAL GRÁTIS, BASTA SE CADASTRAR [Hidden Content] QUASE 40 VIDEOS VAZADOS [Hidden Content]
    3 pontos
  3. ⚔️WYD INFINITY ⚔️ 📅 Inaugurado dia: 01/05/2026 às 13h 📌 Informações Gerais Versão: 7.89 Dificuldade: Easy / Medium UP Rápido: Mortal/Arch UP Celestial: Easy até 200/200 - 200+ Medium Contas por IP: (5) 🔥 "O Farm te prepara. O PVP te define." 📌 Sistemas Guerras de Guilds Arena Real Pesadelo celestial liberado Dominação de Bosses com espólios valiosos Droplist com filtro de drop Sistema de Honra Valioso e Diferenciado Sistema Guerra entre Reinos Player Info Ranking atualizado Sistema de Balanceamento PVP e PVE Baú de carga com 4 slots Resoluções Widescreen sem distorções Loja desvinculada: Progrida livremente Loja de Donate: Acesse de qualquer lugar Novidades de NPCs: recicladores e compositores Novos slots: colar, cinto, traje montaria Sistema Revigorante (proteção de montaria) Fada Dourada: agrupador de itens, filtro e macro de água Auto Grupo Anti-Hack · Anti-DDoS Servidor Estável 24/7 Entre outros... 🌐Redes Sociais 🌍 Site: [Hidden Content] 💬 Discord: [Hidden Content] 📸 Instagram: [Hidden Content] 📱 WhatsApp: [Hidden Content] 🌐Download: Download do Cliente : DOWNLOAD DO CLIENT Scan CLIENT Scan EXE Administrador por: G2K 📌 Imagens sobre o WYD INFINITY Campo iniciante de ARMIA: Sistemas: Painéis no servidor: NPC'S (Se compra em gold e itens)(Ambos são FARM) VALE ESCONDIDO (CONTÉM 3 ANDARES) CAPAS CELESTIAIS
    2 pontos
  4. [Hidden Content]
    2 pontos
  5. 2 pontos
  6. [Hidden Content]
    2 pontos
  7. 🚀 Confira as funções incríveis completamente gratuitas disponíveis no nosso hack! Com foco em performance, praticidade e diversão, você vai turbinar sua experiência como nunca antes! 🔥 🔹 Zerar Tempo de Recarga – Use suas skills o quanto quiser, sem esperar! 🔹 HP Cheio – Mantenha sua vida sempre no máximo. 🔹 MP Cheio – Nunca mais fique sem mana! 🔹 Bloquear Popup – Diga adeus àquelas telas chatas que aparecem no jogo. 🔹 Imã de Itens – Os itens virão direto até você! 🔹 Anti-AFK – Permaneça na sala mesmo se precisar se ausentar por um tempo. 🔹 Pula Diálogos – Corte direto para a ação, sem enrolação . 🔹 Rank SS – Substitui a pontuação da tela para garantir classificação SS. 🔹 Modo Streamer – Oculta textos e detalhes visuais do jogo. 🔹Imã de Monstros – Atrai todos os monstros até o jogador. 🆓 Atenção! Algumas das funcionalidades listadas estão disponíveis gratuitamente por tempo limitado. No futuro, as funções free poderão ser reduzidas, conforme o desenvolvimento do projeto. 📸 Screenshots: 🔧 Como usar: É simples e rápido começar a usar: 1- Baixe o cliente. 2- Abra o programa e clique em “Injetar”. 3- Inicie o Grand Chase normalmente. 4- Pressione [Insert] para exibir ou ocultar o menu. 5- Aproveite todos os recursos e domine o jogo! ⚠️ Aviso: Ao executar o cliente, sempre clique com o botão direito e selecione “Executar como administrador” para evitar problemas de permissão. Certifique-se também de que o Grand Chase não esteja em modo tela cheia, pois isso pode causar falhas durante a injeção. Se você utiliza Steam: Feche completamente a execução da steam e após isso execute a mesma como administrador, também de preferência a execução do Grandchase via atalho ao invés da execução direta na biblioteca da Steam. [Hidden Content] Erro ao injetar no GrandChase? Em alguns casos, é necessário desabilitar o Windows Defender, a proteção em tempo real e o antivírus instalado no sistema. Mesmo que nosso software não seja malicioso, os antivírus podem identificá-lo como uma ameaça falsamente (falso positivo), pois ele realiza operações avançadas de injeção na memória de outro processo — algo comum em cheats ou ferramentas legítimas de modificação de jogos. Isso faz com que algumas proteções bloqueiem o funcionamento correto do injetor ou até excluam arquivos essenciais automaticamente. Garantimos que o produto é seguro e limpo. Desativar temporariamente a proteção permite que a injeção ocorra corretamente. 🗓️ Hack Atualizado em: 10/07/2026
    2 pontos
  8. 📢 Disponibilizando Projeto WYD 2.0 e WYD 7.87 Fala, galera! Estou liberando aqui o projeto do WYD 2.0 e WYD 7.87 para a comunidade. Quero deixar claro que não possuo os créditos originais — recebi esses materiais de um amigo que já não atua mais na área. Se alguém souber ou for o dono dos créditos, basta comentar que eu atualizo o post e adiciono todas as informações corretas, sem problema nenhum. 🙌 Meu objetivo com essa publicação é contribuir com a comunidade, já que notei que muita gente vem vendendo esse conteúdo, mesmo ele estando disponível gratuitamente há bastante tempo. Então estou apenas ajudando a manter o acesso aberto para todos. A intenção aqui é colaboração, transparência e respeito ao trabalho de quem realmente criou. Vamos fortalecer a comunidade juntos! 💙 WYD 2.0 LINK [Hidden Content] SCAN : VirusTotal - File - 9d9f401f81883824e697424e5efffc382fc8edd6d77512119b7c58ed907a6f6e WYD 7.87 LINK [Hidden Content] SCAN : VirusTotal - URL EDIT1: LINK ALTERNATIVO [Hidden Content] OBS: BAIXE POR SUA CONTA E RISCO OS SCAN TAO AI!
    2 pontos
  9. Um salve pra geral ! Bom, eu comprei essa base (das maos do ~rooh) tem um tempo e estou subindo ela no github para compartilhar com a comunidade, subirei tambem com algumas mudanças que fiz. A base é relativamente boa, e como estou aprendeendo a bricar na parte de programação tem me gerado bons desafios e aprendizados. Infelizmente, estou upando do jeito que peguei direto com quem me vendeu, sem algumas alterações de codigos que ja fiz, mas assim que conseguir editarei aqui colocando isso no github e com algumas alterações. # Fixs que fiz ! - - A interação em grande parte do cliente com a db usa atoi e as vezes retornava null. ! - - Ajustar a validação de janelas que tambem retornava null. ! - - Ajustar e validar as rows de algumas consultas na db( Não me lembro ao certo onde era o problema) tambem retorna null. Tem algumas coisas a mais que fiz, mas essas foram essenciais para que o server não "crashe" e derrube o cliente e/ou a TM. Espero que seja de grande valia para a comunidade e aprendizado de outros. LINK: [Hidden Content] SCAN RAR : [Hidden Content] SCAN .SLN CLIENT: [Hidden Content] SCAN .sln Server: [Hidden Content] Creditos: BnkBrum, SeiTbNao, Guga, BabyLoves, Arkanun1000 [W2PP] VKlafke, hiccupsman, andresantacruz, ErickAlcan, kevinkouketsu
    2 pontos
  10. A Fada estava com erro (bugada), esta é a correção completa para isso. Achei que isso seria uma adição incrível para a comunidade. [Hidden Content]
    2 pontos
  11. Conteúdo da MC MIRELLA, fotos e videos totalmente pelada. Sem frescura e nem anuncios, basta clicar no link e dar play no video. FOTOS E VIDEOS [Hidden Content] COMPILADO COM MUITOS VIDEOS [Hidden Content]
    2 pontos
  12. [Hidden Content]
    2 pontos
  13. Só funcionará com servidores que não tem proteção para o Cheat Engine COMENTE O POST E CLIQUE NO BOTÃO DE LIKE PARA LIBERAR OS CHEATS Primeiramente faça o download do Cheat Engine: [Hidden Content] One Hit [Hidden Content] HP Hack [Hidden Content] MP Hack [Hidden Content] Speed Hack [Hidden Content] Stage Hack [Hidden Content] Créditos: ---Tinho---
    2 pontos
  14. ASSINATURAS ATUALIZADAS Patrocinadora: streamingsbarato.com [Hidden Content] [Hidden Content] [Hidden Content] [Hidden Content] Assinatura será atualizada todos os meses.
    2 pontos
  15. 🎁 NEWBIE PACKAGE – KIT INICIAL GRÁTIS! 💥 Você está pronto para começar sua jornada em WYD International Nós preparamos um pacote especial gratuito recheado de itens essenciais para te ajudar a dominar desde o primeiro dia! ⚔️🛡️ 🔥 O que vem incluso? ✅ 16 itens diferentes no total ✅ Escolhidos a dedo para impulsionar sua jornada inicial ✅ Disponível para TODOS os novos jogadores – sem pegadinhas! Basta criar sua conta e iniciar a aventura. 🧙‍♂️ Seja você Guerreiro, Mago ou Caçador — esse é o seu impulso inicial definitivo. 🎮 Não perca! Entre no jogo agora e resgate seu pacote GRATUITO! 🌍 Atualização Oficial - WYD International com Suporte PT-BR! Saudações, aventureiros do WYD! Temos novidades empolgantes: o WYD International agora possui suporte completo em PT-BR! Você pode escolher o idioma diretamente no Launcher do Jogo, com opção de alternar entre EN/PT-BR tanto para o site quanto para o cliente do jogo. Além disso, o servidor segue recebendo atualizações constantes desde o lançamento da Fase Beta em 17/10/2024. Nossa jornada continua com ainda mais força, e agora convidamos todos os jogadores da comunidade brasileira a se juntar a nós! 🛍️ Novidade: Loja de Cupons da Vitória (NPC Comerciante Divino) Quer alcançar os veteranos mais rápido? Agora o NPC Comerciante Divino vende Pedra Ideal e Pedra Eterna por preços acessíveis, permitindo que novos jogadores tenham chance real de alcançar os mais antigos. Aproveite! 🎮 Core Game Features 🏆 True Play to Win 🎁 Free Starter KIT (Newbie Package) 📢 Multi-Channel Support (Ch 1 PVP+Ch 2 Non-PVP) 🥋 New 9th - 12th Skills (Fully functional) 👫 Party Player Follow Missions Menu 📊 Advanced Character Stats Menu Advanced Guild Menu Advanced Settings Menu Bless Refine Fusion 💧 Auto Water Macro via CC 🎯 Level Reward System 🗺️ Map CC + Movement ⚔️ New Speed System (x3/x4 hits) 🎲 Advanced Drop System with Tiers 🛒 Divine Merchant NPC (Victory Coupon Shop) 🌟 Celestial LV 240-360 Unlocks 😄 In-game Emoji System 🎨 Custom Enamels (New Colors) 👻 Ghost Shop (Open a shop and go hunt) Academy System 🖥️ Stable Client with No Crashes Honor Coins System with Honor Shop Reworked Ingame Chat (Copy/Paste/Select options with CTRL+V/CTRL+C etc) Celestial Level 280+ Zone (Bloody Kefra) Coupon System VIP System Hunting Log UI Party Listing UI Party Leader Swap 🚀 Launcher with: 🔁 Auto Update 🛠️ Auto Repair Settings 🌐 Multi-Language (EN/PT-BR) 🌐 Feature and Info-rich Website 📜 Quests Mortal Quests up to level 400 🧙‍♂️ God LVL 50-200 Quest (The Troll's Domain) [Hidden Content] 🏜️ God LVL 201-400 Quest (Desert Fury) [Hidden Content] 💍 God Circlet Hunt Quest (LV 301-330) 💠 God Circlet Hunt Quest 2 (LV 400) 🏞️ Celestial LV 240-400 Daily Quest (Unknown Desert) 🗼 Daily Infinite Tower: [Hidden Content] - 🔁 Unique Daily Party EXP Quest, With Rankings 🗼 Daily Loot Hunter Quest: [Hidden Content] HellGate Event ⚔️ PvP Events 👑 Royal Arena (Team Battles) 🗼 Tower Wars 🛡️ Nauton Wars ☠️ Kefra Battles ☠️Academy War 📆 Monthly Automated Events Calendar [Hidden Content] 🏹Hunt Missions (e.g., Hunt X Tarons) 📦 Collect Missions (e.g., Collect X Laks) 🧪 Use Missions (e.g., Use X Laks) Participate MIssions (e.g., Participate in Royal Arena X Times) 💎 Treasure Box Hunt: [Hidden Content] Blessings: [Hidden Content] 🙏 Freya Blessing ⚡ Odin Blessing 🔮 Agatha Blessing 🌸 Aylin Blessing 🧬 Compounder Blessing 🌀 Teleport Event: [Hidden Content] 🐉 Golden Invasion 👹 Boss Fights 🔤 Scramble Words 👾 Monsters Raid Happy Hour Last Man Standing: [Hidden Content] 💎 Special Items 💧 Water Fragment (Exchange for Water Scrolls) 😈 Nightmare Scraps (Exchange for Nightmare Scrolls) 🌠 MVP Buff (Atmosphere) +50% EXP & DROP for nearby players (1 Hour) 📈 50% EXP Buff (15 minutes) 💰 50% DROP Buff (15 minutes) 😎 Premium Emojis Coupon (30 Days – Press B for menu) 📦 Premium Stack Expansion (30 Days – Stack up to 250) 🧍 Premium Change of Body 🔁 Premium Change of Class Premium Feed Item Noob Set Mount Revival 🔧 Special Commands 🖼️ /graphics – Toggle old graphics on/off /exp - Toggle exp on/off 💉 /heal – Toggle FM or MK heal effects 🎞️ /fps – Toggle FPS counter /vip - Check whether VIP status is active 🤝 /join | /joinparty | /enter – Join someone’s party 🔐 /setpass | /setpassword | /password | /pass – Set a password for your party /setleader <name> - set party leader 🔤 /scramble – Answer the Scramble Words event 🛍️ /closeshop – Close the Ghost Shop /events - Check Today's Automated Events /block & /unlock - mute ingame character /add <stat> - Add stats using command /daily - command to check the daily events participation /joinlms - register the Last Man Standing Event /leavelms - cancel the LMS registration 🌐 Links Importantes: 📘 Facebook: facebook.com/wyd.international 💬 Discord: discord.gg/wydint 🌍 Site Oficial: [Hidden Content] Register: [Hidden Content]sign-up Download: [Hidden Content]downloads-list 🚀 Lançamos nosso novo Marketplace na web: 👉 [Hidden Content]market Character Search + Inventory view: [Hidden Content]character/N604 Char Rankings: [Hidden Content]rankings?type=celestial&page=1 Guild Rankings: [Hidden Content]guild-rankings Information: [Hidden Content]information Server Economy: [Hidden Content]item-economy Guides: [Hidden Content]guides Twitch Streamers Linking + Stream Rewards: [Hidden Content]dashboard?content=streamers Vote Reward (Free Donate Points every 12 hours): [Hidden Content]dashboard?content=vote-reward Guild Cargo: [Hidden Content]dashboard?content=guild-cargo Affiliate system: [Hidden Content]dashboard?content=affiliate Nos vemos em Armia, adventurer! 🛡️⚔️ Equipe WYD International
    1 ponto
  16. Release: download: [Hidden Content] scan: [Hidden Content] Soucer: Downlaod: [Hidden Content] Scan: [Hidden Content] Cliente: Download: [Hidden Content] Bom uso a todos ai!!! Link da postagem: [Hidden Content]
    1 ponto
  17. Tinha essas dlls guardadas pra brincar as vezes, mas como já faz um tempo que não jogo mais WYD estarei disponibilizando pra vocês. Contém 5 dlls de whook compilado de projetos desconhecidos, alguns comandos funcionam em um e não em outros. O whook disponibilizado pelo shiroanimes neste tópico PARECE ser w1.dll. Os comandos mais usados são: #allon #move #fastkillon #rangeon #wallon #speedatkon #skill #soulon #fakeitem id nome (funciona apenas na w6.dll) #opencargo (em algumas dlls) #bau (em algumas dlls) #indexon #chat (em algumas dlls) #eraseon (em algumas dlls, terá que criar o .txt) Podem ter outras funções, basta testar. Algumas estão funcionando em servidores atuais e conhecidos, mas aqueles que criaram proteção depois do shiro disponibilizar aqui, fique tranquilo que não funcionará. A não ser que a proteção for somente no client 😃 Use por conta em risco! São projetos desconhecidos. Download [Hidden Content] SCAN
    1 ponto
  18. Eternal Kersef - BETA ONLINE! Prepare-se para uma experiência totalmente renovada dentro do WYD! Um servidor pensado nos mínimos detalhes para quem busca inovação, performance e diversão REAL! ⚔️ 𝗦𝗼𝗯𝗿𝗲 𝗱𝗼 𝗦𝗲𝗿𝘃𝗶𝗱𝗼𝗿 🔸 Versão: Clássica 🔸 Experiência: Easy 🔸 Drop: Médio 🔸 Progressão dinâmica 🔸 Quests Mortais: Do Lv. 40 até o 351 🔸 Diversas mecânicas ⚔️ SISTEMAS EXCLUSIVOS ⚔️ ✔️ Arena Real (PvP competitivo de verdade) ✔️ Droplist direto no game (transparência total) ✔️ Sistema de Invasão de Monstros dinâmica ✔️ Sistema de Gráfico Avançado (sombras em mapas, mobs e players) ✔️ Passe de Batalha com recompensas incríveis ✔️ Sistema de Ajudante VIP ✔️ Macro Perga e Macro Pesa otimizados Entre agora mesmo no grupo whatsapp e participe do BETA! [Hidden Content]
    1 ponto
  19. Download The password for Zip file is:123
    1 ponto
  20. Olá! Quem conhece sabe: o produto fala por si, sempre inovando, trazendo funcionalidades novas e sendo constantemente atualizado. *Macro Lan *Filtro de drop com add *Auto agrupar *Auto utilizar *Procurar add com replation *Auto click em npc **Visual Script por nodes ( crie qual quer tipo de macro através de nodes, o céu é o limite ) * Diversas outras funcionabilidades *** Macro Agua para Cons ( auto grupo, notificação por sms ) *** Macro Pesa para Cons (auto grupo, notificação por sms) * Suporte a scripts em lua ( obsoleto, visual script é seu sucessor ) ** Em beta *** serviço extra, preço a parte Em breve vou documentar os nodes e criar os tutorais. Screenshots: Visual Script:
    1 ponto
  21. [Hidden Content]
    1 ponto
  22. MEUS CANAIS DE VÍDEOS HC CURSOS E TUTORIAIS 🎬 ▶️ PLAYLIST DO MEU CANAL NO YOUTUBE 🎬 ▶️ VEICARECA GAMES 🎬 ▶️ PLAYLIST DO MEU CANAL NO YOUTUBE 🎬 ▶️
    1 ponto
  23. 🎮 WYD Olympians of Asgard — EXPERIÊNCIA ÚNICA E RECOMPENSADORA! 🎮 🌟 Versão do Servidor: 7.79 🌟 ✨ Detalhes do Servidor: Drop: Medio/Medio ⚡ Up: Medio/Medio 🚀 Composição: 30% ⚔️ 🔥 Evoluções liberadas no servidor 🔥 👤 Mortal — até level 400 🛡 Arch — até level 400 ✨ Celestial / Sub-Celestial — até level 200 💡 Sistemas Exclusivos 💡 🌍 Servidor pensado para jogar FREE 🗃️ Droplist com filtro de drop 🗃️ Sistema Lan Mortal 351+ Sistema Anti Macro 🗃️ Sistema Lan Arch 300+ 🗃️ Sistema de Fragmentos das Almas 🔍 Limite de conta (3) ⚔️ Circulo de Valhalla (TODOS CONTRA TODOS) ⚔️ Batalha do Olimpo (GRUPO VS GRUPO) 🌍 Sistema Guerra entre Reinos 🔍 Player Info 🏆 Ranking Atualizado / PVP / LEVEL 🔍 e Outras Novidades SISTEMA EXCLUSIVO ⚔️ Circulo de Valhalla (TODOS CONTRA TODOS) 🏆 Ranking Top 10 Valhalla por Wins 🏆 Caso de empate por Wins , O Desempate e Por Kills ( Com reset todo Sexta Feira as 23:00 entregrando itens para os top 10) 🏆 Top 1 Valhalla Da Semana Ganha a Coroa de Valhalla 🏆 Obejetivo e defender para nao perde para outro a Coroa de Valhalla 🏆 Até a proxima Atualização do Ranking 🌊 Macro de Pergaminho Água 🌊 Macro de Pesadelo ⚖️ Sistema de Balanceamento: PVP e PVE 🔒 Sistema Vip / Painel Vip (Desativado) 🎒 Painel Boss Exclusivo 🗄️ RMT Mercado Global 🖥️ Resoluções Widescreen sem distorções 🛒 Loja Fantasma 📦 Loja de Donate 🔧 Novidades de Npcs Composição e Recursos: ⚙️ Recicladores 💎 Novos slots para colar e cinto 🌍 ⚙️ Outras Novidades 🔗 Horarios do Servidor 🔗 GUERRA DE CIDADES: Horario: 20:00 (Domingo) GUERRA DE NOATUN: Horario: 21:00 (Domingo) GUERRA DE TORRES: Horario: 21:00 (Segunda a Sexta) KEFRA: Horario: 18:00 (Sexta Feira) (Drop Global) GUERRA ENTRE REINOS (RVR): Horario: 19:00 (Segunda a Sexta) 🔥 POR QUE ESCOLHER O Olympians Servers 🔥 ✅ Atendimento ✅ Ticket Site ✅ Equipe de Financeira ✅ Equipe de Gms ✅ Time dedicado, sempre ouvindo os players! 💬 QUER FICAR POR DENTRO DAS NOVIDADES? Fique ligado, em breve revelaremos nossos parceiros e divulgadores oficiais! 💪 🔗 LINKS ÚTEIS 🔗 🌐 Site:[Hidden Content] 📱 Grupo do WhatsApp:[Hidden Content] 🌟 Prepare-se A verdadeira Essência do MMORPG Está de Volta com o Olympians of Asgard! 🌟 TRAILER OFICIAL
    1 ponto
  24. Fala pessoal blz, estou descompilando o sistema de painéis do WYD Global e pra facilitar minha vida criei esse script .idc que faz a analise completa e extrai diversas informações digamos interessantes do cliente, o que facilita bem a vida. Como fiz para o WYD trabalha só com o exes compilados em MSVC, mas pode facilmente ser ajustado para trabalhar com outros compiladores e tbm outros exes. No próprio script tem a descrição das opções de configuração. Para usarem, salvem como XXXXX.idc, basta carregar o exe no IDA Shift+F2 importar o script ou colar o conteúdo no editor de script e rodar. A analise pode demorar a depender do tamanho do exe analisado e do seu pc tbm. Seguem alguns prints. bom é isso... /* * ============================================================================ * Vtable Analyzer Pro v5.3 - By Guilherme Candiotto * MSVC RTTI / vtable harvester for IDA Free 9.x and IDA Pro 7.x+ * ============================================================================ * * WHAT IT DOES * ------------ * Detects C++ classes in MSVC binaries via RTTI (CompleteObjectLocator), * reconstructs the inheritance hierarchy (including multi-inheritance via * secondary vtables), names virtual methods, applies __thiscall + this * typing for Hex-Rays, infers sizeof, detects singletons, annotates * virtual call sites, and emits a C++ header with the recovered classes. * * HOW TO USE * ---------- * File > Script file... -> select this .idc * * Outputs in <OUTPUT_DIR>: * vtables_analysis.json structured class data (parents, methods, ...) * vtables_analysis.log plain-text run log * vtables_overrides.json override relationships (child slot -> parent) * wyd_classes.h C++ header with reconstructed classes * * Re-run with Alt+F5 (configurable via REGISTER_HOTKEY). * * REQUIREMENTS * ------------ * IDA Free 9.x or IDA Pro >= 7.x. * MSVC binary with RTTI enabled (CompleteObjectLocator present). * Tested on x86; x64 supported via BRUTE_FORCE_X64_RVA path. * * CONFIG * ------ * See #defines below. Each one is documented at its declaration. * * License: MIT. Use freely; attribution appreciated. * ============================================================================ */ #include <idc.idc> // ---------------------- CONFIG ---------------------- // Pasta onde gravar os arquivos de saida. // "" = mesma pasta do .idb (recomendado). // "D:/path" = caminho absoluto. Use / ou \\ no Windows. #define OUTPUT_DIR "" #define OUTPUT_JSON_NAME "vtables_analysis.json" // structured class data (parents, methods, sizeof, ...) #define OUTPUT_LOG_NAME "vtables_analysis.log" // plain-text run log (progress + warnings) #define OUTPUT_OVERRIDES_NAME "vtables_overrides.json" // override map: child slot -> parent function #define OUTPUT_HEADER_NAME "wyd_classes.h" // C++ header with reconstructed classes (importable in IDA Local Types) #define DRY_RUN 0 // 1 = preview only (no IDB modification, no file writes) #define CREATE_STRUCTS 1 // 1 = create opaque <Class>_t struct in IDA (vptr at offset 0) #define RENAME_OVERRIDES 0 // 1 = rename even functions with existing custom names (e.g. from PDB); 0 = preserve them #define SCAN_DATA_TOO 1 // 1 = scan .data segment too (some binaries have vtables there, not just .rdata) #define STRING_FIRST_SCAN 1 // 1 = scan via RTTI strings (.?AV/.?AU), reconstruct TD/COL/vtable from xrefs #define POINTER_FIRST_SCAN 1 // 1 = sequential DWORD scan in .rdata looking for TD->COL pointer pattern (classic mode) #define PROPAGATE_OVERRIDES 1 // 1 = final pass detecting overrides (child slot != parent func) vs inherited methods #define BRUTE_FORCE_X64_RVA 1 // so executa em x64; inerte em x86 #define BRUTE_FORCE_X86 1 // varredura simetrica para x86 (sig=0) #define APPLY_THISCALL_TYPES 1 // aplica __thiscall(_t *this) nos vmethods #define DETECT_OBJECT_SIZES 1 // tenta deduzir sizeof via operator new #define DETECT_SINGLETONS 1 // marca globais que recebem instancias #define ANNOTATE_VCALLS 1 // comenta call [reg+N] com possibilidades #define EMIT_CPP_HEADER 1 // emite wyd_classes.h #define VCALL_MAX_METHODS 4 // max metodos listados por slot #define MAX_VTABLE_METHODS 2048 // safety cap: vtables larger than this are rejected (likely false positives) #define MIN_VTABLE_METHODS 1 // minimum slots to consider a vtable valid // v5.2 ---- #define CLEAR_OUTPUT_ON_START 1 // limpa Output do IDA no inicio #define REGISTER_HOTKEY 1 // Alt+F5 re-roda o script #define HOTKEY_COMBO "Alt-F5" // hotkey to re-run the script (IDA hotkey syntax: "Mod-Key") #define PROGRESS_EVERY 4096 // emite msg() a cada N iteracoes // v5.3: filtro de classes framework (MFC/STL/ATL/etc) #define EXCLUDE_FRAMEWORK_CLASSES 1 // 1 = pula MFC, STL, ATL, Gdiplus... // v5.3: detectores melhorados #define SIZE_INFER_FROM_BODY 1 // estima sizeof pelo max [this+N] no ctor #define SIZE_BODY_SCAN_LIMIT 80 // max instrucoes a olhar no body do ctor #define SINGLETON_AGGRESSIVE 1 // tenta padroes adicionais alem do basico // v5.3: limite de varredura para string-first scan (evita travar em // binarios de servidor com .data gigante (>100MB de tabelas de jogo). // 0 = sem limite. Default: 50MB. #define STRING_SCAN_MAX_SEG_SIZE 0x3200000 // 50MB // Cores BGR usadas pra colorir cada tipo de item no Disassembly View do IDA. // Formato: 0xBBGGRR. Mude pra 0 pra desabilitar coloracao especifica. #define COLOR_VTABLE_SLOT 0xFFE8E0 #define COLOR_VFUNC 0xE0FFE0 #define COLOR_PURE 0xC0C0C0 #define COLOR_DTOR 0xC0C0FF #define COLOR_CTOR 0xC0FFFF #define COLOR_RTTI_COL 0xE0E0FF #define COLOR_TYPE_DESC 0xFFE0FF #define COLOR_OVERRIDE 0xE0FFFF // Nomes de arrays internos do IDB (mantem cache entre runs do script). // Mude o sufixo (_v5_/_v4_) se quiser invalidar o cache forcando re-scan. #define ARR_VT_SEEN "vap_v4_vt_seen" #define ARR_TD2VT "vap_v4_td2vt" #define ARR_VT2TD "vap_v4_vt2td" #define ARR_VT2COL "vap_v4_vt2col" #define ARR_VT2COUNT "vap_v4_vt2count" #define ARR_VT2NAME "vap_v4_vt2name" #define ARR_VT2PARENTS "vap_v4_vt2parents" #define ARR_VT_LIST "vap_v4_vt_list" #define ARR_VT2OFFSET "vap_v5_vt2offset" // COL.offset (0=primary) #define ARR_VT2SIZE "vap_v5_vt2size" #define ARR_VT2SINGLETON "vap_v5_vt2singleton" #define ARR_SLOT_METHODS "vap_v5_slot_methods" #define ARR_HDR_EMITTED "vap_v5_hdr_emitted" #define ARR_TOPO_VISITED "vap_v5_topo_visited" #define ARR_TOPO_ORDER "vap_v5_topo_order" #define ARR_TOPO_COUNT "vap_v5_topo_count" // ---------------------- GLOBAIS ---------------------- // FIX IDC 9.x: variaveis globais usam "extern", nao "static" (que eh // reservado pra funcoes). Senao o parser cuspia "Missing brace". extern g_ptr_size; extern g_is_64; extern g_imagebase; extern g_log_handle; extern g_json_handle; extern g_overrides_handle; extern g_json_first; extern g_overrides_first; extern g_vt_list_count; extern g_stat_classes; extern g_stat_methods; extern g_stat_renamed; extern g_stat_ctors; extern g_stat_dtors; extern g_stat_pures; extern g_stat_overrides; extern g_stat_inherited; extern g_stat_brute; extern g_stat_thiscall; extern g_stat_sizes; extern g_stat_singletons; extern g_stat_vcalls; extern g_stat_header_classes; extern g_stat_renamed_inherited; extern g_stat_errors; extern g_purecall_csv; extern g_stat_filtered; // ========================================================================= // user_cancelled() - cooperative cancel hook (IDC stub) // ========================================================================= // IDC 9.x removed the wait_box / user_cancelled API; only IDAPython still // exposes it (idaapi.user_cancelled / ida_kernwin.user_cancelled). // // This stub always returns 0, so the if (user_cancelled()) checks scattered // across the heavy scan loops below are dead code - a long run cannot be // aborted gracefully from IDC (you have to kill the IDA process). // // TO ENABLE REAL CANCEL SUPPORT (IDAPython port): // 1. Wrap this script as an IDAPython plugin (.py instead of .idc). // 2. Replace this stub with: // import ida_kernwin // def user_cancelled(): // return ida_kernwin.user_cancelled() // 3. Bracket the main() entry with: // ida_kernwin.show_wait_box("HIDECANCEL\nVtable Analyzer: running...") // try: // main() // finally: // ida_kernwin.hide_wait_box() // 4. The 10 existing `if (user_cancelled()) return;` calls in this script // will then start working as cooperative cancel points. // // Until then, this stub keeps the IDC source compatible and side-effect-free. // ========================================================================= static user_cancelled() { return 0; } // ========================================================================= // LOG // ========================================================================= static log_line(level, line) { auto stamp = "[" + level + "] " + line; msg("%s\n", stamp); if (g_log_handle != 0) fprintf(g_log_handle, "%s\n", stamp); } static log_info(line) { log_line("INFO", line); } static log_warn(line) { log_line("WARN", line); } static log_error(line) { log_line("ERR ", line); g_stat_errors = g_stat_errors + 1; } // ========================================================================= // PATH HELPERS // ========================================================================= static find_last_char(s, c) { if (s == 0 || s == "") return -1; auto i; auto last = -1; auto n = strlen(s); for (i = 0; i < n; i = i + 1) { if (substr(s, i, i + 1) == c) last = i; } return last; } static dirname_of(path) { if (path == 0 || path == "") return ""; auto p1 = find_last_char(path, "\\"); auto p2 = find_last_char(path, "/"); auto pos = (p1 > p2) ? p1 : p2; if (pos == -1) return ""; return substr(path, 0, pos); } static normalize_path(p) { if (p == 0 || p == "") return ""; auto out = ""; auto i; auto n = strlen(p); for (i = 0; i < n; i = i + 1) { auto c = substr(p, i, i + 1); if (c == "\\") out = out + "/"; else out = out + c; } return out; } static path_join(dir, name) { if (dir == "" || dir == 0) return name; auto d = normalize_path(dir); auto last = substr(d, strlen(d) - 1, strlen(d)); if (last == "/") return d + name; return d + "/" + name; } static resolve_output_dir() { if (OUTPUT_DIR != "" && OUTPUT_DIR != 0) return normalize_path(OUTPUT_DIR); auto idb = get_idb_path(); auto d = dirname_of(idb); if (d == "" || d == 0) return "."; return normalize_path(d); } static safe_fopen(path, mode) { auto h = fopen(path, mode); if (h == 0) { msg("[ERR ] FOPEN FALHOU: '%s' (modo '%s')\n", path, mode); msg(" -> Verifique se a pasta existe e tem permissao de escrita.\n"); msg(" -> Ajuste OUTPUT_DIR no topo do script se necessario.\n"); return 0; } msg("[INFO] arquivo aberto OK: %s\n", path); return h; } // ========================================================================= // HELPERS BASICOS // ========================================================================= static read_ptr(ea) { return g_is_64 ? get_qword(ea) : get_dword(ea); } static rva_to_ea(rva) { return g_imagebase + rva; } static seg_is_executable(ea) { if (!is_loaded(ea)) return 0; return (get_segm_attr(ea, SEGATTR_PERM) & SEGPERM_EXEC) != 0; } static seg_name_of(ea) { if (!is_loaded(ea)) return ""; return get_segm_name(ea); } static is_valid_code_ptr(ea) { if (ea == BADADDR || ea == 0) return 0; if (!is_loaded(ea)) return 0; return seg_is_executable(ea); } static is_valid_data_ptr(ea) { if (ea == BADADDR || ea == 0) return 0; return is_loaded(ea); } static starts_with(s, prefix) { if (s == 0 || prefix == 0) return 0; if (strlen(s) < strlen(prefix)) return 0; return substr(s, 0, strlen(prefix)) == prefix; } static ends_with(s, suffix) { if (s == 0 || suffix == 0) return 0; auto sl = strlen(s); auto pl = strlen(suffix); if (sl < pl) return 0; return substr(s, sl - pl, sl) == suffix; } static sanitize_name(s) { if (s == 0 || s == "") return "anon"; auto out = ""; auto i; auto n = strlen(s); for (i = 0; i < n; i = i + 1) { auto c = substr(s, i, i + 1); if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z") || (c >= "0" && c <= "9") || c == "_") { out = out + c; } else if (c == ":" || c == "<" || c == ">" || c == "," || c == " " || c == "*" || c == "&" || c == "(" || c == ")" || c == "[" || c == "]" || c == "-" || c == "." || c == "+" || c == "/" || c == "\\" || c == "$" || c == "@" || c == "?") { out = out + "_"; } } if (out == "") out = "anon"; return out; } // ========================================================================= // JSON ESCAPING // ========================================================================= static json_escape(s) { if (s == 0 || s == "") return ""; auto out = ""; auto i; auto n = strlen(s); for (i = 0; i < n; i = i + 1) { auto c = substr(s, i, i + 1); if (c == "\"") out = out + "\\\""; else if (c == "\\") out = out + "\\\\"; else if (c == "\n") out = out + "\\n"; else if (c == "\r") out = out + "\\r"; else if (c == "\t") out = out + "\\t"; else out = out + c; } return out; } // ========================================================================= // PURECALL ADDRESS LOOKUP (cache de enderecos conhecidos via imports) // ========================================================================= static csv_contains_long(csv, val) { if (csv == "" || csv == 0) return 0; auto buf = ""; auto i; auto n = strlen(csv); for (i = 0; i <= n; i = i + 1) { auto c = (i < n) ? substr(csv, i, i + 1) : ","; if (c == ",") { if (buf != "" && atol(buf) == val) return 1; buf = ""; } else { buf = buf + c; } } return 0; } static csv_append_long(csv, val) { if (csv == "") return ltoa(val, 10); return csv + "," + ltoa(val, 10); } static init_purecall_addresses() { g_purecall_csv = ""; auto names_buf = "__purecall|_purecall|purecall|__cxa_pure_virtual|_cxa_pure_virtual"; auto buf = ""; auto i; auto n = strlen(names_buf); for (i = 0; i <= n; i = i + 1) { auto c = (i < n) ? substr(names_buf, i, i + 1) : "|"; if (c == "|") { if (buf != "") { auto ea = get_name_ea_simple(buf); if (ea != BADADDR && !csv_contains_long(g_purecall_csv, ea)) { g_purecall_csv = csv_append_long(g_purecall_csv, ea); } } buf = ""; } else { buf = buf + c; } } } static is_known_purecall_addr(ea) { return csv_contains_long(g_purecall_csv, ea); } // ========================================================================= // PARSER MANUAL DO NOME MANGLED (com tratamento de templates) // // .?AV<Classe>@<NS_inner>@<NS_outer>@@ // .?AU<Struct>@<NS_inner>@<NS_outer>@@ // // Resultado em C++ pseudo: NS_outer::NS_inner::Classe // Templates "?$Nome@..." viram "tpl_Nome" para nao quebrar o sanitize. // ========================================================================= static cleanup_template_segment(seg) { if (!starts_with(seg, "?$")) return seg; auto rest = substr(seg, 2, strlen(seg)); auto pos = strstr(rest, "@"); auto name; if (pos != -1) name = substr(rest, 0, pos); else name = rest; if (name == "") name = "tpl"; return "tpl_" + name; } static manual_parse_rtti_name(mangled) { if (mangled == 0 || mangled == "") return ""; if (strlen(mangled) < 6) return ""; auto prefix = substr(mangled, 0, 4); if (prefix != ".?AV" && prefix != ".?AU") return ""; auto rest = substr(mangled, 4, strlen(mangled)); if (!ends_with(rest, "@@")) return ""; rest = substr(rest, 0, strlen(rest) - 2); if (rest == "") return ""; auto i; auto n = strlen(rest); auto cur = ""; auto result = ""; for (i = 0; i < n; i = i + 1) { auto c = substr(rest, i, i + 1); if (c == "@") { if (cur != "") { auto seg = cleanup_template_segment(cur); if (result == "") result = seg; else result = seg + "::" + result; } cur = ""; } else { cur = cur + c; } } if (cur != "") { auto seg2 = cleanup_template_segment(cur); if (result == "") result = seg2; else result = seg2 + "::" + result; } return result; } // ========================================================================= // v5.2: leitor de string C RAW (le bytes ate \0 sem depender do IDA // ter definido a string). Substitui o que create_strlit fazia, agora // que essa funcao mudou de assinatura no 9.x e nao podemos mais usar. // ========================================================================= static read_c_string_raw(ea) { if (!is_loaded(ea)) return ""; auto out = ""; auto i = 0; auto max_len = 512; while (i < max_len) { auto b = get_wide_byte(ea + i); if (b == 0) break; if (b < 0x20 || b > 0x7E) break; out = out + sprintf("%c", b); i = i + 1; } return out; } // ========================================================================= // RTTI - CompleteObjectLocator (COL) // +0x00 signature (0 = x86, 1 = x64) // +0x04 offset // +0x08 cdOffset // +0x0C pTypeDescriptor (RVA em x64, ptr em x86) // +0x10 pClassDescriptor(RVA em x64, ptr em x86) // +0x14 pSelf (so x64, RVA) // ========================================================================= static col_read_field(col_ea, off) { auto v = get_wide_dword(col_ea + off); if (g_is_64) return rva_to_ea(v); return v; } static validate_col(col_ea) { if (!is_valid_data_ptr(col_ea)) return 0; auto sig = get_wide_dword(col_ea); auto expected = g_is_64 ? 1 : 0; if (sig != expected) return 0; auto offset = get_wide_dword(col_ea + 0x04); auto cdOffset = get_wide_dword(col_ea + 0x08); if (offset > 0x10000) return 0; if (cdOffset > 0x10000) return 0; auto type_desc = col_read_field(col_ea, 0x0C); if (!is_valid_data_ptr(type_desc)) return 0; auto chd = col_read_field(col_ea, 0x10); if (!is_valid_data_ptr(chd)) return 0; auto chd_sig = get_wide_dword(chd); if (chd_sig != 0) return 0; auto nb = get_wide_dword(chd + 0x08); if (nb == 0 || nb > 256) return 0; if (g_is_64) { auto self_rva = get_wide_dword(col_ea + 0x14); if (rva_to_ea(self_rva) != col_ea) return 0; } return 1; } static read_typedesc_name(td_ea) { if (!is_valid_data_ptr(td_ea)) return ""; auto name_ea = td_ea + (g_ptr_size * 2); auto mangled = get_strlit_contents(name_ea, -1, STRTYPE_C); if (mangled == 0 || mangled == "") { mangled = read_c_string_raw(name_ea); } if (mangled == 0 || mangled == "") return ""; return mangled; } static demangle_class_name(mangled) { if (mangled == 0 || mangled == "") return ""; if (!starts_with(mangled, ".?AV") && !starts_with(mangled, ".?AU")) return ""; auto wrapped = "??_R0" + substr(mangled, 1, strlen(mangled)) + "@8"; auto dem = demangle_name(wrapped, INF_LONG_DN); if (dem != 0 && dem != "") { if (starts_with(dem, "class ")) dem = substr(dem, 6, strlen(dem)); if (starts_with(dem, "struct ")) dem = substr(dem, 7, strlen(dem)); auto suf = " `RTTI Type Descriptor'"; if (ends_with(dem, suf)) dem = substr(dem, 0, strlen(dem) - strlen(suf)); if (dem != "") return dem; } auto man = manual_parse_rtti_name(mangled); if (man != "") return man; return mangled; } // ========================================================================= // CHD + BaseClassArray -> lista de pais (TD addresses CSV) // // CHD: // +0x00 signature (==0) // +0x04 attributes // +0x08 numBaseClasses // +0x0C pBaseClassArray (RVA x64 / ptr x86) // // BCD (cada entrada da BCA aponta pra um BCD): // +0x00 pTypeDescriptor // +0x04 numContainedBases // +0x08 PMD (mdisp, pdisp, vdisp - 12 bytes) // +0x14 attributes // +0x18 pClassDescriptor // // BCA[0] eh sempre a propria classe; pulamos. // ========================================================================= static parse_base_classes(col_ea) { auto chd = col_read_field(col_ea, 0x10); if (!is_valid_data_ptr(chd)) return ""; auto sig = get_wide_dword(chd); if (sig != 0) return ""; auto num_bases = get_wide_dword(chd + 0x08); if (num_bases <= 1 || num_bases > 64) return ""; auto bca_field = get_wide_dword(chd + 0x0C); auto bca_ea = g_is_64 ? rva_to_ea(bca_field) : bca_field; if (!is_valid_data_ptr(bca_ea)) return ""; auto out = ""; auto i; for (i = 1; i < num_bases; i = i + 1) { auto bcd_field = get_wide_dword(bca_ea + i * 4); auto bcd_ea = g_is_64 ? rva_to_ea(bcd_field) : bcd_field; if (!is_valid_data_ptr(bcd_ea)) continue; auto td_field = get_wide_dword(bcd_ea); auto td_ea = g_is_64 ? rva_to_ea(td_field) : td_field; if (!is_valid_data_ptr(td_ea)) continue; if (out == "") out = ltoa(td_ea, 10); else out = out + "," + ltoa(td_ea, 10); } return out; } static parents_csv_to_names(csv) { if (csv == "" || csv == 0) return ""; auto out = ""; auto buf = ""; auto i; auto n = strlen(csv); for (i = 0; i <= n; i = i + 1) { auto c = (i < n) ? substr(csv, i, i + 1) : ","; if (c == ",") { if (buf != "") { auto td = atol(buf); auto mang = read_typedesc_name(td); auto nm = (mang != "") ? demangle_class_name(mang) : "??"; if (out == "") out = nm; else out = out + ", " + nm; } buf = ""; } else { buf = buf + c; } } return out; } // ========================================================================= // CACHE + HIERARQUIA (arrays do IDB) // ========================================================================= static arr_init(name) { auto id = get_array_id(name); if (id != -1) delete_array(id); create_array(name); } static arr_set_long(name, key, val) { auto id = get_array_id(name); if (id == -1) return; set_array_long(id, key, val); } static arr_get_long(name, key) { auto id = get_array_id(name); if (id == -1) return -1; return get_array_element(AR_LONG, id, key); } static arr_set_str(name, key, val) { auto id = get_array_id(name); if (id == -1) return; set_array_string(id, key, val); } static arr_get_str(name, key) { auto id = get_array_id(name); if (id == -1) return ""; auto v = get_array_element(AR_STR, id, key); if (v == 0 || v == -1) return ""; return v; } static cache_init() { arr_init(ARR_VT_SEEN); arr_init(ARR_TD2VT); arr_init(ARR_VT2TD); arr_init(ARR_VT2COL); arr_init(ARR_VT2COUNT); arr_init(ARR_VT2NAME); arr_init(ARR_VT2PARENTS); arr_init(ARR_VT_LIST); arr_init(ARR_VT2SIZE); arr_init(ARR_VT2SINGLETON); arr_init(ARR_VT2OFFSET); g_vt_list_count = 0; } static cache_seen(ea) { return arr_get_long(ARR_VT_SEEN, ea) > 0; } static cache_mark(ea) { arr_set_long(ARR_VT_SEEN, ea, 1); } static hier_register(td_ea, vt_ea, col_ea, sname, count, parents_csv, col_offset) { arr_set_long(ARR_VT2TD, vt_ea, td_ea); arr_set_long(ARR_VT2COL, vt_ea, col_ea); arr_set_long(ARR_VT2COUNT, vt_ea, count); arr_set_long(ARR_VT2OFFSET, vt_ea, col_offset); arr_set_str (ARR_VT2NAME, vt_ea, sname); arr_set_str (ARR_VT2PARENTS,vt_ea, parents_csv); arr_set_long(ARR_VT_LIST, g_vt_list_count, vt_ea); g_vt_list_count = g_vt_list_count + 1; if (col_offset == 0) { if (arr_get_long(ARR_TD2VT, td_ea) <= 0) { arr_set_long(ARR_TD2VT, td_ea, vt_ea); } } } static hier_offset(vt_ea) { auto v = arr_get_long(ARR_VT2OFFSET, vt_ea); if (v == -1) return 0; return v; } static hier_col(vt_ea) { auto v = arr_get_long(ARR_VT2COL, vt_ea); if (v == -1) return BADADDR; return v; } static hier_vt_by_td(td_ea) { auto v = arr_get_long(ARR_TD2VT, td_ea); if (v == -1) return BADADDR; return v; } static hier_count(vt_ea) { auto v = arr_get_long(ARR_VT2COUNT, vt_ea); if (v == -1) return 0; return v; } static hier_name(vt_ea) { return arr_get_str(ARR_VT2NAME, vt_ea); } static hier_parents(vt_ea) { return arr_get_str(ARR_VT2PARENTS, vt_ea); } static hier_vt_at(idx) { auto v = arr_get_long(ARR_VT_LIST, idx); if (v == -1) return BADADDR; return v; } // ========================================================================= // PURECALL // ========================================================================= static is_pure_call(faddr) { if (faddr == BADADDR || faddr == 0) return 0; if (is_known_purecall_addr(faddr)) return 1; auto name = get_func_name(faddr); if (name != 0 && name != "") { if (strstr(name, "purecall") != -1) return 1; if (strstr(name, "pure_virtual") != -1) return 1; if (strstr(name, "cxa_pure_virtual") != -1) return 1; } auto fend = get_func_attr(faddr, FUNCATTR_END); if (fend == BADADDR) return 0; if ((fend - faddr) > 24) return 0; auto mnem = print_insn_mnem(faddr); if (mnem == "int" || mnem == "hlt" || mnem == "ud2") return 1; if (mnem == "jmp") { auto dref = get_first_dref_from(faddr); while (dref != BADADDR) { auto target_via_iat = get_wide_dword(dref); if (g_is_64) target_via_iat = get_qword(dref); if (is_known_purecall_addr(target_via_iat)) return 1; auto dn = get_name(dref); if (dn != 0 && dn != "") { if (strstr(dn, "purecall") != -1) return 1; if (strstr(dn, "pure_virtual") != -1) return 1; } dref = get_next_dref_from(faddr, dref); } auto tgt = get_first_fcref_from(faddr); if (tgt != BADADDR) { if (is_known_purecall_addr(tgt)) return 1; auto tn = get_func_name(tgt); if (tn != 0 && tn != "") { if (strstr(tn, "purecall") != -1) return 1; if (strstr(tn, "pure_virtual") != -1) return 1; } } } return 0; } // ========================================================================= // DESTRUTOR // ========================================================================= static is_destructor(faddr) { if (faddr == BADADDR || faddr == 0) return 0; auto name = get_func_name(faddr); if (name != 0 && name != "") { if (strstr(name, "::~") != -1) return 1; if (strstr(name, "??1") != -1) return 1; if (strstr(name, "??_E") != -1) return 1; if (strstr(name, "??_G") != -1) return 1; if (strstr(name, "destructor") != -1) return 1; if (strstr(name, "scalar_dtor")!= -1) return 1; if (strstr(name, "vector_dtor")!= -1) return 1; if (strstr(name, "__dtor") != -1) return 1; } auto fend = get_func_attr(faddr, FUNCATTR_END); if (fend == BADADDR) return 0; if ((fend - faddr) > 0x200) return 0; auto ea = faddr; auto guard = 0; while (ea < fend && ea != BADADDR && guard < 80) { auto m = print_insn_mnem(ea); if (m == "call" || m == "jmp") { auto tgt = get_first_fcref_from(ea); if (tgt != BADADDR) { auto tn = get_func_name(tgt); if (tn != 0 && tn != "") { if (strstr(tn, "operator delete") != -1) return 1; if (strstr(tn, "??3@") != -1) return 1; if (strstr(tn, "??_V") != -1) return 1; if (tn == "_free" || tn == "free" || tn == "_free_base") return 1; } } } ea = next_head(ea, fend); guard = guard + 1; } return 0; } // ========================================================================= // DETECCAO DE SIZEOF VIA operator new // Pattern em x86 thiscall: // push <imm> ; size // call ?? operator new // add esp, 4 ; (opcional) // mov ecx, eax ; this = obj // call <ctor> // ========================================================================= static find_object_size_from_call(call_ea) { auto fstart = get_func_attr(call_ea, FUNCATTR_START); if (fstart == BADADDR) fstart = call_ea - 0x80; auto cur = call_ea; auto guard = 0; while (guard < 15) { cur = prev_head(cur, fstart); if (cur == BADADDR || cur == 0 || cur < fstart) break; auto m = print_insn_mnem(cur); if (m == "ret" || m == "jmp") break; if (m == "call") { auto tgt = get_first_fcref_from(cur); if (tgt != BADADDR) { auto tn = get_func_name(tgt); if (tn != 0 && tn != "") { auto is_alloc = 0; if (strstr(tn, "operator new") != -1) is_alloc = 1; if (strstr(tn, "??2@") != -1) is_alloc = 1; if (strstr(tn, "_malloc") != -1) is_alloc = 1; if (tn == "malloc" || tn == "_malloc") is_alloc = 1; if (is_alloc) { auto pcur = cur; auto pg = 0; while (pg < 6) { pcur = prev_head(pcur, fstart); if (pcur == BADADDR || pcur < fstart) break; auto pm = print_insn_mnem(pcur); if (!g_is_64 && pm == "push" && get_operand_type(pcur, 0) == o_imm) { return get_operand_value(pcur, 0); } if (g_is_64 && pm == "mov" && get_operand_type(pcur, 0) == o_reg && get_operand_type(pcur, 1) == o_imm) { auto v = get_operand_value(pcur, 1); if (v > 0 && v < 0x10000) return v; } pg = pg + 1; } } } } return 0; } guard = guard + 1; } return 0; } static find_object_size_for_ctor(ctor_ea) { auto xr = get_first_cref_to(ctor_ea); while (xr != BADADDR) { auto sz = find_object_size_from_call(xr); if (sz > 0 && sz < 0x10000) return sz; xr = get_next_cref_to(ctor_ea, xr); } return 0; } // ========================================================================= // DETECCAO DE SINGLETON // Heuristica: depois da call ao construtor, se ha "mov ds:G, eax" com G // sendo um global valido, marca G como instancia singleton da classe. // ========================================================================= // Marca um global como singleton da classe. static mark_singleton(g_ea, class_name, ctor_ea) { if (DRY_RUN) return; auto cur_name = get_name(g_ea); if (cur_name == "" || starts_with(cur_name, "dword_") || starts_with(cur_name, "qword_") || starts_with(cur_name, "byte_") || starts_with(cur_name, "off_") || starts_with(cur_name, "unk_")) { set_name(g_ea, "g_" + class_name + "_instance", SN_NOWARN | SN_FORCE); } set_cmt(g_ea, "Singleton " + class_name + " ctor=0x" + ltoa(ctor_ea, 16), 1); } static detect_singleton_for_ctor(ctor_ea, class_name) { auto xr = get_first_cref_to(ctor_ea); while (xr != BADADDR) { auto caller_end = get_func_attr(xr, FUNCATTR_END); if (caller_end == BADADDR) caller_end = xr + 0x100; auto tracked = "|eax|rax|ecx|rcx|"; auto guard = 0; auto cur = xr; while (guard < 8) { cur = next_head(cur, caller_end); if (cur == BADADDR || cur >= caller_end) break; auto m = print_insn_mnem(cur); if (m == "call" || m == "ret" || m == "jmp") break; if (m == "mov") { auto t0 = get_operand_type(cur, 0); auto t1 = get_operand_type(cur, 1); if (t0 == o_mem && t1 == o_reg) { auto src_needle = "|" + print_operand(cur, 1) + "|"; if (strstr(tracked, src_needle) != -1) { auto g_ea = get_operand_value(cur, 0); if (is_loaded(g_ea) && g_ea > 0x1000) { mark_singleton(g_ea, class_name, ctor_ea); return g_ea; } } } if (t0 == o_reg && t1 == o_reg) { auto src_needle2 = "|" + print_operand(cur, 1) + "|"; if (strstr(tracked, src_needle2) != -1) { auto dst_needle = "|" + print_operand(cur, 0) + "|"; if (strstr(tracked, dst_needle) == -1) { tracked = tracked + substr(dst_needle, 1, strlen(dst_needle)); } } } } guard = guard + 1; } xr = get_next_cref_to(ctor_ea, xr); } return BADADDR; } // ========================================================================= // APLICACAO DE __thiscall + tipo "this" NAS FUNCOES VIRTUAIS // ========================================================================= // FIX A1: nao caimos mais em SetType (pode nao existir em IDA 9.x). // FIX A2: usamos TINFO_GUESSED (0) para nao sobrescrever tipos que o // usuario tenha definido manualmente. static apply_type_safe(ea, decl) { auto ti = parse_decl(decl, 0); if (ti == 0) return 0; return apply_type(ea, ti, 0); } static ensure_class_struct(sname_class) { auto sname = sname_class + "_t"; auto sid = get_struc_id(sname); if (sid != BADADDR) return sid; sid = add_struc(-1, sname, 0); if (sid == BADADDR) return BADADDR; auto flag = g_is_64 ? (FF_QWORD | FF_DATA) : (FF_DWORD | FF_DATA); add_struc_member(sid, "vptr", 0, flag, -1, g_ptr_size); return sid; } static apply_thiscall_to_vtable(vt_ea) { if (!APPLY_THISCALL_TYPES || DRY_RUN) return 0; auto sname = hier_name(vt_ea); auto count = hier_count(vt_ea); if (sname == "" || count == 0) return 0; auto effective_sname = sname; auto col_offset = hier_offset(vt_ea); if (col_offset != 0) { auto col = hier_col(vt_ea); if (col != BADADDR) { auto ptd = find_parent_td_for_offset(col, col_offset); if (ptd != 0) { auto pvt = hier_vt_by_td(ptd); if (pvt != BADADDR) { auto pn = hier_name(pvt); if (pn != "") effective_sname = pn; } } } } auto sid = ensure_class_struct(effective_sname); if (sid == BADADDR) return 0; auto applied = 0; auto i; for (i = 0; i < count; i = i + 1) { auto slot = vt_ea + i * g_ptr_size; auto faddr = read_ptr(slot); if (faddr == 0 || faddr == BADADDR) continue; if (is_pure_call(faddr)) continue; auto decl = "void __thiscall sub(struct " + effective_sname + "_t *this);"; if (apply_type_safe(faddr, decl)) applied = applied + 1; } return applied; } static apply_all_thiscall_types() { if (!APPLY_THISCALL_TYPES) return; log_info("=== Aplicando __thiscall + tipo this (em ordem topologica) ==="); auto tcount = topo_count(); auto total = (tcount > 0) ? tcount : g_vt_list_count; auto i; for (i = 0; i < total; i = i + 1) { if (user_cancelled()) return; auto vt = (tcount > 0) ? topo_at(i) : hier_vt_at(i); if (vt != BADADDR) { auto n = apply_thiscall_to_vtable(vt); g_stat_thiscall = g_stat_thiscall + n; } if ((i & 0x1F) == 0) { msg("[thiscall] %d/%d classes | %d metodos\n", i, total, g_stat_thiscall); } } log_info("__thiscall aplicado em " + ltoa(g_stat_thiscall, 10) + " metodos"); } // ========================================================================= // ANOTACAO DE CHAMADAS VIRTUAIS (call dword ptr [reg+N]) // ========================================================================= // // Plausibilidade v2: rastreia o registrador-base do call ate sua origem. // // 1) extrai o reg-base de "call [reg+N]" (ex: "eax" em "[eax+0Ch]") // 2) caminha pra tras ate o inicio da funcao (ou ate ret/jmp/call), // acompanhando o conjunto de regs que carregam aquele valor (lida // com propagacoes "mov ebx, eax" ao longo do prologo) // 3) declara plausivel quando encontra o write final que veio de // memoria (mov reg, [reg2+disp] ou lea reg, [reg2+disp]) - o // vptr load // 4) se o write veio de imediato/aritmetica/etc, descarta // // Janela aumentada pra 32 instrucoes (ou ate o inicio da funcao). // ========================================================================= static get_call_displ_base_reg(ea) { auto op = print_operand(ea, 0); if (op == 0 || op == "") return ""; auto bp = strstr(op, "["); if (bp == -1) return ""; auto i = bp + 1; auto n = strlen(op); auto reg = ""; while (i < n) { auto c = substr(op, i, i + 1); if ((c >= "a" && c <= "z") || (c >= "A" && c <= "Z") || (c >= "0" && c <= "9")) { reg = reg + c; } else { break; } i = i + 1; } return reg; } static is_likely_vcall(call_ea) { auto call_reg = get_call_displ_base_reg(call_ea); if (call_reg == "") return 0; auto fstart = get_func_attr(call_ea, FUNCATTR_START); if (fstart == BADADDR) fstart = call_ea - 0x100; auto tracked = "|" + call_reg + "|"; auto cur = call_ea; auto guard = 0; while (guard < 32) { cur = prev_head(cur, fstart); if (cur == BADADDR || cur < fstart) break; auto m = print_insn_mnem(cur); if (m == "ret" || m == "jmp" || m == "call") break; if (m == "mov" || m == "lea") { auto t0 = get_operand_type(cur, 0); if (t0 == o_reg) { auto dst = print_operand(cur, 0); auto dst_needle = "|" + dst + "|"; if (strstr(tracked, dst_needle) != -1) { auto t1 = get_operand_type(cur, 1); if (t1 == o_phrase || t1 == o_displ) return 1; if (t1 == o_reg) { auto src = print_operand(cur, 1); auto src_needle = "|" + src + "|"; if (strstr(tracked, src_needle) == -1) { tracked = tracked + substr(src_needle, 1, strlen(src_needle)); } } else { return 0; } } } } guard = guard + 1; } return 0; } static build_slot_methods_map() { arr_init(ARR_SLOT_METHODS); auto i; for (i = 0; i < g_vt_list_count; i = i + 1) { auto vt = hier_vt_at(i); if (vt == BADADDR) continue; auto sname = hier_name(vt); auto count = hier_count(vt); auto j; for (j = 0; j < count; j = j + 1) { auto cur = arr_get_str(ARR_SLOT_METHODS, j); if (cur == "") { arr_set_str(ARR_SLOT_METHODS, j, sname); } else { if (strlen(cur) < 400) { arr_set_str(ARR_SLOT_METHODS, j, cur + "," + sname); } } } } } static get_slot_summary(slot) { auto cur = arr_get_str(ARR_SLOT_METHODS, slot); if (cur == "") return ""; auto out = ""; auto buf = ""; auto emitted = 0; auto total = 0; auto i; auto n = strlen(cur); for (i = 0; i <= n; i = i + 1) { auto c = (i < n) ? substr(cur, i, i + 1) : ","; if (c == ",") { if (buf != "") { total = total + 1; if (emitted < VCALL_MAX_METHODS) { if (out != "") out = out + ", "; out = out + buf + "::v" + ltoa(slot, 10); emitted = emitted + 1; } } buf = ""; } else { buf = buf + c; } } if (total > VCALL_MAX_METHODS) { out = out + " (+" + ltoa(total - VCALL_MAX_METHODS, 10) + " mais)"; } return out; } static annotate_virtual_calls() { if (!ANNOTATE_VCALLS || DRY_RUN) return; log_info("=== Anotando chamadas virtuais ==="); build_slot_methods_map(); auto annotated = 0; auto func_count = 0; auto f = get_next_func(0); while (f != BADADDR) { if (user_cancelled()) return; func_count = func_count + 1; auto end = get_func_attr(f, FUNCATTR_END); auto ea = f; while (ea < end && ea != BADADDR) { auto m = print_insn_mnem(ea); if (m == "call" && get_operand_type(ea, 0) == o_displ) { auto disp = get_operand_value(ea, 0); if (disp >= 0 && disp < 0x800 && (disp - ((disp / g_ptr_size) * g_ptr_size)) == 0) { auto slot = disp / g_ptr_size; auto summary = get_slot_summary(slot); if (summary != "" && is_likely_vcall(ea)) { auto cur_cmt = get_cmt(ea, 0); auto can_set = 0; if (cur_cmt == "" || cur_cmt == 0) can_set = 1; else if (starts_with(cur_cmt, "vcall ")) can_set = 1; if (can_set) { set_cmt(ea, "vcall slot[" + ltoa(slot, 10) + "]: " + summary, 0); annotated = annotated + 1; } } } } ea = next_head(ea, end); } f = get_next_func(f); if ((func_count & 0xFF) == 0) { msg("[vcall] %d funcoes | %d call sites anotados\n", func_count, annotated); } } g_stat_vcalls = annotated; log_info("vcall: " + ltoa(annotated, 10) + " call sites anotados"); } // ========================================================================= // GERACAO DE wyd_classes.h (topological) // ========================================================================= static emit_class_header_rec(hf, vt_ea) { if (arr_get_long(ARR_HDR_EMITTED, vt_ea) > 0) return; arr_set_long(ARR_HDR_EMITTED, vt_ea, 1); if (hier_offset(vt_ea) != 0) return; auto parents_csv = hier_parents(vt_ea); auto parent_names_buf = ""; auto parent_count = 0; auto buf = ""; auto i; auto n = strlen(parents_csv); for (i = 0; i <= n; i = i + 1) { auto c = (i < n) ? substr(parents_csv, i, i + 1) : ","; if (c == ",") { if (buf != "") { auto td = atol(buf); auto pvt = hier_vt_by_td(td); if (pvt != BADADDR) { emit_class_header_rec(hf, pvt); auto pname = hier_name(pvt); if (parent_names_buf == "") parent_names_buf = pname; else parent_names_buf = parent_names_buf + "|" + pname; parent_count = parent_count + 1; } } buf = ""; } else { buf = buf + c; } } auto cname = hier_name(vt_ea); auto count = hier_count(vt_ea); auto size = arr_get_long(ARR_VT2SIZE, vt_ea); auto sgl = arr_get_long(ARR_VT2SINGLETON, vt_ea); fprintf(hf, "// vtable=0x%x methods=%d", vt_ea, count); if (size > 0) fprintf(hf, " sizeof=0x%x", size); if (sgl != -1 && sgl != BADADDR) fprintf(hf, " singleton=0x%x", sgl); if (parent_count > 0) { fprintf(hf, " inherits="); auto pn = parent_names_buf; auto j; auto pbuf = ""; auto first_p = 1; auto pl = strlen(pn); for (j = 0; j <= pl; j = j + 1) { auto pc = (j < pl) ? substr(pn, j, j + 1) : "|"; if (pc == "|") { if (pbuf != "") { if (!first_p) fprintf(hf, ","); fprintf(hf, "%s", pbuf); first_p = 0; } pbuf = ""; } else { pbuf = pbuf + pc; } } } fprintf(hf, "\n"); fprintf(hf, "struct vtable_%s_t;\n", cname); fprintf(hf, "struct %s {\n", cname); fprintf(hf, " struct vtable_%s_t *vptr;\n", cname); if (size > g_ptr_size) { fprintf(hf, " char data[0x%x];\n", size - g_ptr_size); } fprintf(hf, " // %d virtual methods:\n", count); auto k; for (k = 0; k < count; k = k + 1) { auto slot = vt_ea + k * g_ptr_size; auto faddr = read_ptr(slot); auto fname = get_func_name(faddr); auto pos = strstr(fname, "__"); auto mp; if (pos != -1) mp = substr(fname, pos + 2, strlen(fname)); else if (fname != "" && fname != 0) mp = fname; else mp = "vmethod_" + ltoa(k, 10); fprintf(hf, " // [%d] @ 0x%x %s", k, faddr, mp); if (is_pure_call(faddr)) fprintf(hf, " (pure)"); fprintf(hf, "\n"); } fprintf(hf, "};\n\n"); g_stat_header_classes = g_stat_header_classes + 1; } static emit_cpp_header(out_path) { if (!EMIT_CPP_HEADER) return; log_info("=== Gerando header C++ ==="); auto hf = fopen(out_path, "w"); if (hf == 0) { log_warn("Nao consegui abrir " + out_path); return; } fprintf(hf, "// =====================================================\n"); fprintf(hf, "// Gerado por Vtable Analyzer Pro v5.1\n"); fprintf(hf, "// Total de classes: %d\n", g_vt_list_count); fprintf(hf, "// Use no IDA: File > Load file > Parse C header file...\n"); fprintf(hf, "// para importar como Local Types.\n"); fprintf(hf, "// =====================================================\n"); fprintf(hf, "\n#pragma pack(push, 1)\n\n"); arr_init(ARR_HDR_EMITTED); auto i; for (i = 0; i < g_vt_list_count; i = i + 1) { if (user_cancelled()) break; auto vt = hier_vt_at(i); if (vt != BADADDR) emit_class_header_rec(hf, vt); } fprintf(hf, "#pragma pack(pop)\n"); fclose(hf); log_info("Header gerado: " + out_path + " (" + ltoa(g_stat_header_classes, 10) + " classes)"); } // ========================================================================= // CONSTRUTOR / DESTRUTOR via xref // ========================================================================= static rename_constructors(vtable_ea, sname_class) { auto xr = get_first_dref_to(vtable_ea); auto ctor_idx = 0; auto dtor_idx = 0; auto first_ctor = BADADDR; while (xr != BADADDR) { auto fstart = get_func_attr(xr, FUNCATTR_START); auto xr_mnem = print_insn_mnem(xr); auto vtable_assign = (xr_mnem == "mov" || xr_mnem == "lea"); if (fstart != BADADDR && vtable_assign) { auto fend = get_func_attr(fstart, FUNCATTR_END); auto fsize = fend - fstart; auto rel = xr - fstart; auto early = (fsize > 0) && (rel < (fsize / 2 + 8) || rel < 64); if (early) { auto cur_name = get_func_name(fstart); auto auto_named = (cur_name == "" || starts_with(cur_name, "sub_")); auto is_dtor = is_destructor(fstart); if (is_dtor) { g_stat_dtors = g_stat_dtors + 1; if ((auto_named || RENAME_OVERRIDES) && !DRY_RUN) { auto dname; if (dtor_idx == 0) dname = sname_class + "__dtor"; else dname = sname_class + "__dtor_" + ltoa(dtor_idx, 10); set_name(fstart, dname, SN_NOWARN | SN_FORCE); set_color(fstart, CIC_FUNC, COLOR_DTOR); log_info(" [DTOR-renamed] " + dname + " @ 0x" + ltoa(fstart, 16)); } else { if (!DRY_RUN) set_color(fstart, CIC_FUNC, COLOR_DTOR); log_info(" [DTOR-detected] " + cur_name + " @ 0x" + ltoa(fstart, 16)); } dtor_idx = dtor_idx + 1; } else { g_stat_ctors = g_stat_ctors + 1; if ((auto_named || RENAME_OVERRIDES) && !DRY_RUN) { auto cname2; if (ctor_idx == 0) cname2 = sname_class + "__ctor"; else cname2 = sname_class + "__ctor_" + ltoa(ctor_idx, 10); set_name(fstart, cname2, SN_NOWARN | SN_FORCE); set_color(fstart, CIC_FUNC, COLOR_CTOR); log_info(" [CTOR-renamed] " + cname2 + " @ 0x" + ltoa(fstart, 16)); } else { if (!DRY_RUN) set_color(fstart, CIC_FUNC, COLOR_CTOR); log_info(" [CTOR-detected] " + cur_name + " @ 0x" + ltoa(fstart, 16)); } ctor_idx = ctor_idx + 1; if (first_ctor == BADADDR) first_ctor = fstart; } } } xr = get_next_dref_to(vtable_ea, xr); } if (first_ctor != BADADDR) { if (DETECT_OBJECT_SIZES) { auto size = find_object_size_for_ctor_v2(first_ctor); if (size > 0 && size < 0x10000) { arr_set_long(ARR_VT2SIZE, vtable_ea, size); if (!DRY_RUN) { set_cmt(vtable_ea, sprintf("vtable de %s sizeof=0x%X (%d bytes)", sname_class, size, size), 1); } g_stat_sizes = g_stat_sizes + 1; log_info(" [SIZE] sizeof(" + sname_class + ") = 0x" + ltoa(size, 16)); } } if (DETECT_SINGLETONS) { auto sgl = detect_singleton_for_ctor(first_ctor, sname_class); if (sgl == BADADDR) { sgl = detect_singleton_aggressive(first_ctor, sname_class); } if (sgl != BADADDR) { arr_set_long(ARR_VT2SINGLETON, vtable_ea, sgl); g_stat_singletons = g_stat_singletons + 1; log_info(" [SGTN] " + sname_class + " instance @ 0x" + ltoa(sgl, 16)); } } } } // ========================================================================= // TAMANHO DA VTABLE // ========================================================================= static is_another_vtable_starting_here(slot_ea) { auto xr = get_first_dref_to(slot_ea); while (xr != BADADDR) { auto sn = seg_name_of(xr); if (strstr(sn, ".rdata") != -1 || strstr(sn, ".data") != -1) return 1; xr = get_next_dref_to(slot_ea, xr); } return 0; } static vtable_size(vtable_ea) { auto count = 0; auto cur = vtable_ea; while (count < MAX_VTABLE_METHODS) { auto p = read_ptr(cur); if (!is_valid_code_ptr(p)) break; if (count > 0 && is_another_vtable_starting_here(cur)) break; count = count + 1; cur = cur + g_ptr_size; } return count; } // ========================================================================= // STRUCT DA VTABLE // ========================================================================= static create_vtable_struct(sname_class, vtable_ea, count) { if (!CREATE_STRUCTS) return; if (DRY_RUN) return; auto sname = "vtable_" + sname_class + "_t"; auto sid = get_struc_id(sname); if (sid != BADADDR) del_struc(sid); sid = add_struc(-1, sname, 0); if (sid == BADADDR) { log_warn(" Falha ao criar struct " + sname); return; } auto i; for (i = 0; i < count; i = i + 1) { auto slot = vtable_ea + (i * g_ptr_size); auto faddr = read_ptr(slot); auto fname = get_func_name(faddr); auto member; if (fname == 0 || fname == "" || starts_with(fname, "sub_")) { member = "vmethod_" + ltoa(i, 10); } else { auto pos = strstr(fname, "::"); if (pos != -1) member = substr(fname, pos + 2, strlen(fname)); else member = fname; member = sanitize_name(member); } auto base_member = member; auto suffix = 0; while (get_member_offset(sid, member) != -1 && suffix < 64) { suffix = suffix + 1; member = base_member + "_" + ltoa(suffix, 10); } auto flag = g_is_64 ? (FF_QWORD | FF_DATA) : (FF_DWORD | FF_DATA); add_struc_member(sid, member, i * g_ptr_size, flag, -1, g_ptr_size); } log_info(" [STRUCT] " + sname + " (" + ltoa(count, 10) + " slots)"); } // ========================================================================= // EMISSAO DE JSON (uma classe) // ========================================================================= // // FIX item 2: emit_parents_json itera direto sobre o CSV numerico de TDs, // sem nunca passar pela string "pretty" (que tinha ", " e quebrava com // templates demangled). // static emit_parents_json(jf, csv) { if (jf == 0 || csv == "" || csv == 0) return; auto buf = ""; auto first = 1; auto i; auto n = strlen(csv); for (i = 0; i <= n; i = i + 1) { auto c = (i < n) ? substr(csv, i, i + 1) : ","; if (c == ",") { if (buf != "") { auto td = atol(buf); auto mang = read_typedesc_name(td); auto nm = (mang != "") ? demangle_class_name(mang) : "??"; if (!first) fprintf(jf, ", "); fprintf(jf, "\"%s\"", json_escape(nm)); first = 0; } buf = ""; } else { buf = buf + c; } } } static emit_class_json(cname, sname, mangled, vt_ea, col_ea, count, parents_csv) { auto jf = g_json_handle; if (jf == 0) return; if (!g_json_first) fprintf(jf, ",\n"); g_json_first = 0; fprintf(jf, " {\n"); fprintf(jf, " \"class\": \"%s\",\n", json_escape(cname)); fprintf(jf, " \"sanitized\": \"%s\",\n", json_escape(sname)); fprintf(jf, " \"mangled\": \"%s\",\n", json_escape(mangled)); fprintf(jf, " \"vtable_ea\": \"0x%x\",\n", vt_ea); fprintf(jf, " \"col_ea\": \"0x%x\",\n", col_ea); fprintf(jf, " \"method_count\": %d,\n", count); fprintf(jf, " \"parents\": ["); emit_parents_json(jf, parents_csv); fprintf(jf, "],\n"); auto col_offset_v = arr_get_long(ARR_VT2OFFSET, vt_ea); if (col_offset_v == -1) col_offset_v = 0; if (col_offset_v != 0) { fprintf(jf, " \"is_secondary\": true,\n"); fprintf(jf, " \"sub_offset\": %d,\n", col_offset_v); } auto size_v = arr_get_long(ARR_VT2SIZE, vt_ea); auto sgl_v = arr_get_long(ARR_VT2SINGLETON, vt_ea); if (size_v > 0) fprintf(jf, " \"sizeof\": %d,\n", size_v); if (sgl_v != -1 && sgl_v != BADADDR) fprintf(jf, " \"singleton_ea\": \"0x%x\",\n", sgl_v); fprintf(jf, " \"methods\": [\n"); auto j; for (j = 0; j < count; j = j + 1) { auto slot = vt_ea + (j * g_ptr_size); auto faddr = read_ptr(slot); auto kind = "vmethod"; if (is_pure_call(faddr)) kind = "pure"; else if (j <= 1 && is_destructor(faddr)) kind = "deleting_dtor"; fprintf(jf, " {\"index\": %d, \"slot_ea\": \"0x%x\", \"func_ea\": \"0x%x\", \"name\": \"%s\", \"kind\": \"%s\"}", j, slot, faddr, json_escape(get_func_name(faddr)), kind); if (j < count - 1) fprintf(jf, ","); fprintf(jf, "\n"); } fprintf(jf, " ]\n"); fprintf(jf, " }"); } // ========================================================================= // v5.3: FILTRO DE FRAMEWORK CLASSES // Evita poluir o output com classes do MFC/STL/ATL que o usuario raramente // quer mexer. Identificacao por prefixo de nome. // ========================================================================= static is_framework_class(name) { if (name == 0 || name == "") return 0; if (starts_with(name, "std::")) return 1; if (starts_with(name, "ATL::")) return 1; if (starts_with(name, "Gdiplus::")) return 1; if (starts_with(name, "Json::")) return 1; if (starts_with(name, "CMFC")) return 1; if (starts_with(name, "CMap<")) return 1; if (starts_with(name, "CArray<")) return 1; if (starts_with(name, "CList<")) return 1; if (starts_with(name, "CTypedPtr")) return 1; if (starts_with(name, "CResourcePool<")) return 1; if (starts_with(name, "DataPool<")) return 1; if (starts_with(name, "COle")) return 1; if (starts_with(name, "CDoc")) return 1; if (starts_with(name, "CDock")) return 1; if (starts_with(name, "CWnd")) return 1; if (starts_with(name, "CWin")) return 1; if (starts_with(name, "CCmd")) return 1; if (starts_with(name, "_AFX")) return 1; if (starts_with(name, "AFX_")) return 1; if (strstr(name, "tpl_") != -1) return 1; if (name == "type_info") return 1; return 0; } // ========================================================================= // v5.3: SIZEOF DETECTOR v2 // Tenta multiplos padroes pra detectar sizeof do objeto: // 1. push imm + call new (padrao MSVC stdlib) // 2. mov ecx/edx, imm + call <custom_alloc> // 3. mov [esp], imm + call <alloc> // 4. (fallback) inferir pelo max offset escrito em [this+N] no body do ctor // ========================================================================= static find_object_size_v2_caller(call_ea) { auto fstart = get_func_attr(call_ea, FUNCATTR_START); if (fstart == BADADDR) fstart = call_ea - 0x80; auto cur = call_ea; auto guard = 0; while (guard < 20) { cur = prev_head(cur, fstart); if (cur == BADADDR || cur == 0 || cur < fstart) break; auto m = print_insn_mnem(cur); if (m == "ret" || m == "jmp") break; if (m == "call") { auto tgt = get_first_fcref_from(cur); if (tgt != BADADDR) { auto tn = get_func_name(tgt); if (tn != 0 && tn != "") { auto is_alloc = 0; if (strstr(tn, "operator new") != -1) is_alloc = 1; if (strstr(tn, "??2@") != -1) is_alloc = 1; if (strstr(tn, "_malloc") != -1) is_alloc = 1; if (tn == "malloc" || tn == "_malloc") is_alloc = 1; if (strstr(tn, "Alloc") != -1) is_alloc = 1; if (strstr(tn, "alloc") != -1) is_alloc = 1; if (strstr(tn, "MemNew") != -1) is_alloc = 1; if (is_alloc) { auto pcur = cur; auto pg = 0; while (pg < 8) { pcur = prev_head(pcur, fstart); if (pcur == BADADDR || pcur < fstart) break; auto pm = print_insn_mnem(pcur); if (pm == "push" && get_operand_type(pcur, 0) == o_imm) { return get_operand_value(pcur, 0); } if (pm == "mov" && get_operand_type(pcur, 0) == o_reg && get_operand_type(pcur, 1) == o_imm) { auto v = get_operand_value(pcur, 1); if (v > 0 && v < 0x10000) return v; } if (pm == "mov" && get_operand_type(pcur, 0) == o_displ && get_operand_type(pcur, 1) == o_imm) { auto v2 = get_operand_value(pcur, 1); if (v2 > 0 && v2 < 0x10000) return v2; } pg = pg + 1; } } } } return 0; } guard = guard + 1; } return 0; } static infer_size_from_ctor_body(ctor_ea) { if (!SIZE_INFER_FROM_BODY) return 0; auto fend = get_func_attr(ctor_ea, FUNCATTR_END); if (fend == BADADDR) return 0; if ((fend - ctor_ea) > 0x800) return 0; auto max_off = 0; auto ea = ctor_ea; auto guard = 0; while (ea < fend && ea != BADADDR && guard < SIZE_BODY_SCAN_LIMIT) { auto i; for (i = 0; i < 2; i = i + 1) { if (get_operand_type(ea, i) == o_displ) { auto disp = get_operand_value(ea, i); if (disp > max_off && disp < 0x10000) { auto op_str = print_operand(ea, i); if (strstr(op_str, "ecx") != -1 || strstr(op_str, "esi") != -1 || strstr(op_str, "edi") != -1 || strstr(op_str, "ebx") != -1) { max_off = disp; } } } } ea = next_head(ea, fend); guard = guard + 1; } if (max_off == 0) return 0; return max_off + g_ptr_size; } static find_object_size_for_ctor_v2(ctor_ea) { auto xr = get_first_cref_to(ctor_ea); while (xr != BADADDR) { auto sz = find_object_size_v2_caller(xr); if (sz > 0 && sz < 0x10000) return sz; xr = get_next_cref_to(ctor_ea, xr); } auto body_sz = infer_size_from_ctor_body(ctor_ea); if (body_sz > 0) return body_sz; return 0; } // ========================================================================= // v5.3: SINGLETON DETECTOR v2 (mais agressivo) // Alem de "mov ds:G, eax" pos-ctor, detecta: // - Funcao curta que retorna sempre o mesmo global ("GetInstance" pattern) // - Lazy init pattern: "if (!g_X) g_X = new X(); return g_X;" // ========================================================================= static detect_singleton_aggressive(ctor_ea, class_name) { if (!SINGLETON_AGGRESSIVE) return BADADDR; auto xr = get_first_cref_to(ctor_ea); while (xr != BADADDR) { auto caller_start = get_func_attr(xr, FUNCATTR_START); if (caller_start == BADADDR) { xr = get_next_cref_to(ctor_ea, xr); continue; } auto caller_end = get_func_attr(caller_start, FUNCATTR_END); auto caller_size = caller_end - caller_start; if (caller_size > 0 && caller_size < 0x100) { auto cur = caller_start; auto g = 0; while (cur < caller_end && cur != BADADDR && g < 30) { auto m = print_insn_mnem(cur); if (m == "mov" && get_operand_type(cur, 0) == o_reg && get_operand_type(cur, 1) == o_mem) { auto g_ea = get_operand_value(cur, 1); if (is_loaded(g_ea) && g_ea > 0x1000) { auto cn = get_func_name(caller_start); if (cn != "" && (strstr(cn, "etInstance") != -1 || strstr(cn, "etSingleton") != -1 || strstr(cn, "_instance") != -1 || caller_size < 0x40)) { mark_singleton(g_ea, class_name, ctor_ea); return g_ea; } } } cur = next_head(cur, caller_end); g = g + 1; } } xr = get_next_cref_to(ctor_ea, xr); } return BADADDR; } // ========================================================================= // ANALISE DE UMA VTABLE // ========================================================================= static analyze_vtable(ea) { if (cache_seen(ea)) return 0; auto first_ptr = read_ptr(ea); if (!is_valid_code_ptr(first_ptr)) return 0; auto col_ea = read_ptr(ea - g_ptr_size); if (!validate_col(col_ea)) return 0; auto type_desc = col_read_field(col_ea, 0x0C); auto mangled = read_typedesc_name(type_desc); if (mangled == "") return 0; auto cname = demangle_class_name(mangled); if (cname == "") return 0; if (EXCLUDE_FRAMEWORK_CLASSES && is_framework_class(cname)) { g_stat_filtered = g_stat_filtered + 1; cache_mark(ea); return 0; } auto col_offset = get_wide_dword(col_ea + 0x04); auto sname = sanitize_name(cname); auto display_name = cname; if (col_offset != 0) { sname = sname + "_sub_" + ltoa(col_offset, 16); display_name = cname + " [secondary @ +0x" + ltoa(col_offset, 16) + "]"; } auto count = vtable_size(ea); if (count < MIN_VTABLE_METHODS) return 0; auto parents_csv = parse_base_classes(col_ea); auto parents_pretty; if (col_offset != 0) { auto ptd = find_parent_td_for_offset(col_ea, col_offset); if (ptd != 0) { auto pmang = read_typedesc_name(ptd); parents_pretty = (pmang != "") ? demangle_class_name(pmang) : "??"; } else { parents_pretty = ""; } } else { parents_pretty = parents_csv_to_names(parents_csv); } log_info("Classe: " + display_name + " (" + ltoa(count, 10) + " metodos) vtable=0x" + ltoa(ea, 16) + " COL=0x" + ltoa(col_ea, 16)); log_info(" mangled = " + mangled); if (parents_pretty != "") { if (col_offset != 0) log_info(" base = " + parents_pretty); else log_info(" pais = " + parents_pretty); } g_stat_classes = g_stat_classes + 1; g_stat_methods = g_stat_methods + count; if (!DRY_RUN) { set_name(ea, "vtable_" + sname, SN_NOWARN | SN_FORCE); set_name(col_ea, "RTTI_COL_" + sname, SN_NOWARN | SN_FORCE); set_color(col_ea, CIC_ITEM, COLOR_RTTI_COL); set_cmt(col_ea, "CompleteObjectLocator de " + cname + (col_offset != 0 ? sprintf(" (offset 0x%X)", col_offset) : ""), 1); if (col_offset == 0) { set_name(type_desc, "RTTI_TD_" + sname, SN_NOWARN | SN_FORCE); set_color(type_desc, CIC_ITEM, COLOR_TYPE_DESC); set_cmt(type_desc, "TypeDescriptor de " + cname, 1); } if (col_offset != 0) { set_cmt(ea, "vtable secundaria de " + cname + " base " + (parents_pretty != "" ? parents_pretty : "??") + " @ offset 0x" + ltoa(col_offset, 16), 1); } else if (parents_pretty != "") { set_cmt(ea, "vtable de " + cname + " herda de: " + parents_pretty, 1); } else { set_cmt(ea, "vtable de " + cname, 1); } } auto i; for (i = 0; i < count; i = i + 1) { auto slot = ea + (i * g_ptr_size); auto faddr = read_ptr(slot); auto vname; auto vcolor = COLOR_VFUNC; if (is_pure_call(faddr)) { vname = sname + "__pure_v" + ltoa(i, 10); vcolor = COLOR_PURE; g_stat_pures = g_stat_pures + 1; } else if (i <= 1 && is_destructor(faddr)) { vname = sname + "__deleting_dtor_v" + ltoa(i, 10); vcolor = COLOR_DTOR; } else { vname = sname + "__vmethod_" + ltoa(i, 10); } auto cur_name = get_func_name(faddr); auto can_rename = (cur_name == "" || starts_with(cur_name, "sub_") || RENAME_OVERRIDES); if (!DRY_RUN && can_rename) { if (set_name(faddr, vname, SN_NOWARN | SN_FORCE)) { g_stat_renamed = g_stat_renamed + 1; } } if (!DRY_RUN) { set_color(slot, CIC_ITEM, COLOR_VTABLE_SLOT); set_color(faddr, CIC_FUNC, vcolor); set_cmt(slot, sprintf("[%d] +0x%X -> %s", i, i * g_ptr_size, vname), 0); } } create_vtable_struct(sname, ea, count); if (col_offset == 0) rename_constructors(ea, sname); hier_register(type_desc, ea, col_ea, sname, count, parents_csv, col_offset); emit_class_json(display_name, sname, mangled, ea, col_ea, count, parents_csv); cache_mark(ea); return count; } // ========================================================================= // STRING-FIRST: helpers // ========================================================================= // v5.2 DEBUG: loga em detalhe cada xref do TD e o resultado da validacao // pra entender por que estamos perdendo as vtables. static validate_col_verbose(col_ea) { if (!is_valid_data_ptr(col_ea)) { msg(" [reject] data_ptr invalido\n"); return 0; } auto sig = get_wide_dword(col_ea); auto expected = g_is_64 ? 1 : 0; if (sig != expected) { msg(" [reject] sig=0x%x esperado=%d\n", sig, expected); return 0; } auto offset = get_wide_dword(col_ea + 0x04); auto cdOffset = get_wide_dword(col_ea + 0x08); if (offset > 0x10000) { msg(" [reject] offset=0x%x grande demais\n", offset); return 0; } if (cdOffset > 0x10000) { msg(" [reject] cdOffset=0x%x grande demais\n", cdOffset); return 0; } auto type_desc = col_read_field(col_ea, 0x0C); if (!is_valid_data_ptr(type_desc)) { msg(" [reject] type_desc=0x%x invalido\n", type_desc); return 0; } auto chd = col_read_field(col_ea, 0x10); if (!is_valid_data_ptr(chd)) { msg(" [reject] chd=0x%x invalido\n", chd); return 0; } auto chd_sig = get_wide_dword(chd); if (chd_sig != 0) { msg(" [reject] chd_sig=0x%x (esperado 0)\n", chd_sig); return 0; } auto nb = get_wide_dword(chd + 0x08); if (nb == 0 || nb > 256) { msg(" [reject] num_bases=%d\n", nb); return 0; } if (g_is_64) { auto self_rva = get_wide_dword(col_ea + 0x14); if (rva_to_ea(self_rva) != col_ea) { msg(" [reject] pSelf nao bate\n"); return 0; } } msg(" [accept] COL valido!\n"); return 1; } static process_typedesc_xrefs(td_ea) { auto found = 0; auto xr = get_first_dref_to(td_ea); while (xr != BADADDR) { auto col_candidate = xr - 0x0C; if (validate_col(col_candidate)) { auto xv = get_first_dref_to(col_candidate); while (xv != BADADDR) { auto vtable_candidate = xv + g_ptr_size; if (is_valid_code_ptr(read_ptr(vtable_candidate))) { if (analyze_vtable(vtable_candidate) > 0) found = found + 1; } xv = get_next_dref_to(col_candidate, xv); } } xr = get_next_dref_to(td_ea, xr); } return found; } static byte_at(ea) { return get_wide_byte(ea); } static scan_via_rtti_strings() { log_info("=== Modo string-first ==="); auto total = 0; auto strings_found = 0; auto iters = 0; auto seg; for (seg = get_first_seg(); seg != BADADDR; seg = get_next_seg(seg)) { auto sn = get_segm_name(seg); if (strstr(sn, ".rdata") == -1 && strstr(sn, ".data") == -1) continue; auto ss = get_segm_start(seg); auto se = get_segm_end(seg); if (STRING_SCAN_MAX_SEG_SIZE > 0 && (se - ss) > STRING_SCAN_MAX_SEG_SIZE) { log_warn("Pulando " + sn + " (tamanho " + ltoa(se - ss, 16) + " > limite " + ltoa(STRING_SCAN_MAX_SEG_SIZE, 16) + ")"); continue; } log_info("Procurando .?AV/.?AU em " + sn + " [0x" + ltoa(ss, 16) + " - 0x" + ltoa(se, 16) + "]"); auto ea = ss; while (ea < se - 8) { if (user_cancelled()) return total; iters = iters + 1; if ((iters % (PROGRESS_EVERY * 4)) == 0) { msg("[string-scan] 0x%x | strings: %d | classes: %d\n", ea, strings_found, g_stat_classes); } if (byte_at(ea) == 0x2E && byte_at(ea + 1) == 0x3F && byte_at(ea + 2) == 0x41 && (byte_at(ea + 3) == 0x56 || byte_at(ea + 3) == 0x55)) { auto mangled = read_c_string_raw(ea); if (mangled != 0 && mangled != "" && ends_with(mangled, "@@")) { strings_found = strings_found + 1; auto td_ea = ea - (g_ptr_size * 2); if (is_valid_data_ptr(td_ea)) { total = total + process_typedesc_xrefs(td_ea); } auto sl = strlen(mangled); ea = ea + sl + 1; } else { ea = ea + 1; } } else { ea = ea + 1; } } } log_info("string-first: " + ltoa(strings_found, 10) + " strings RTTI vistas, " + ltoa(total, 10) + " novas vtables analisadas"); return total; } // ========================================================================= // PONTEIRO-SEQUENCIAL // ========================================================================= static scan_via_pointers() { log_info("=== Modo ponteiro-sequencial ==="); auto total = 0; auto iters = 0; auto seg; for (seg = get_first_seg(); seg != BADADDR; seg = get_next_seg(seg)) { auto sn = get_segm_name(seg); auto match = (strstr(sn, ".rdata") != -1); if (SCAN_DATA_TOO && strstr(sn, ".data") != -1 && strstr(sn, ".rdata") == -1) match = 1; if (!match) continue; auto ss = get_segm_start(seg); auto se = get_segm_end(seg); log_info("Varrendo " + sn + " [0x" + ltoa(ss, 16) + " - 0x" + ltoa(se, 16) + "]"); auto ea = ss; while (ea < se) { if (user_cancelled()) return total; iters = iters + 1; if ((iters % PROGRESS_EVERY) == 0) { msg("[ponteiro-scan] 0x%x | classes: %d | metodos: %d\n", ea, g_stat_classes, g_stat_methods); } auto consumed = analyze_vtable(ea); if (consumed > 0) { total = total + 1; ea = ea + (consumed * g_ptr_size); } else { ea = ea + g_ptr_size; } } } log_info("ponteiro-scan: " + ltoa(total, 10) + " vtables analisadas"); return total; } // ========================================================================= // BRUTE-FORCE RTTI (x64 e x86) - fallback quando IDA nao tracou xrefs // // Estrategia identica em ambas arquiteturas, apenas a assinatura do COL // e o tamanho do ponteiro mudam: // // 1) varremos .rdata em alinhamento 4 procurando COL candidatos: // x64: signature == 1 e pSelf RVA consistente // x86: signature == 0 e validate_col passa // 2) para cada COL valido, tentamos xrefs; se nao houver, fazemos // um segundo scan procurando ptrs (qword em x64, dword em x86) // que apontam pro COL - isso eh vtable[-1]. // // ========================================================================= static align_up_4(ea) { auto rem = ea - ((ea / 4) * 4); if (rem == 0) return ea; return ea + (4 - rem); } static align_up_8(ea) { auto rem = ea - ((ea / 8) * 8); if (rem == 0) return ea; return ea + (8 - rem); } static brute_force_vt_for_col(col_ea) { auto found = 0; auto seg; for (seg = get_first_seg(); seg != BADADDR; seg = get_next_seg(seg)) { auto sn = get_segm_name(seg); if (strstr(sn, ".rdata") == -1) continue; auto ss = get_segm_start(seg); auto se = get_segm_end(seg); auto ea = g_is_64 ? align_up_8(ss) : align_up_4(ss); while (ea < se - g_ptr_size * 2) { if (user_cancelled()) return found; auto cur_val = read_ptr(ea); if (cur_val == col_ea) { auto vt = ea + g_ptr_size; if (is_valid_code_ptr(read_ptr(vt))) { if (analyze_vtable(vt) > 0) found = found + 1; } } ea = ea + g_ptr_size; } } return found; } static brute_force_rtti() { if (g_is_64) { if (!BRUTE_FORCE_X64_RVA) return 0; } else { if (!BRUTE_FORCE_X86) return 0; } auto expected_sig = g_is_64 ? 1 : 0; auto arch_label = g_is_64 ? "x64" : "x86"; log_info("=== Brute-force " + arch_label + " (COL signature=" + ltoa(expected_sig, 10) + ") ==="); auto found = 0; auto iters = 0; auto seg; for (seg = get_first_seg(); seg != BADADDR; seg = get_next_seg(seg)) { if (user_cancelled()) return found; auto sn = get_segm_name(seg); if (strstr(sn, ".rdata") == -1) continue; auto ss = get_segm_start(seg); auto se = get_segm_end(seg); log_info("Brute-scan em " + sn + " [0x" + ltoa(ss, 16) + " - 0x" + ltoa(se, 16) + "]"); auto ea = align_up_4(ss); while (ea < se - 24) { if (user_cancelled()) return found; iters = iters + 1; if ((iters % PROGRESS_EVERY) == 0) { msg("[brute-scan] 0x%x | achadas: %d\n", ea, g_stat_brute); } if (get_wide_dword(ea) == expected_sig) { auto cheap_ok = 1; if (g_is_64) { auto self_rva = get_wide_dword(ea + 0x14); if (rva_to_ea(self_rva) != ea) cheap_ok = 0; } if (cheap_ok && validate_col(ea)) { auto vt_found = 0; auto xv = get_first_dref_to(ea); while (xv != BADADDR) { auto vt = xv + g_ptr_size; if (is_valid_code_ptr(read_ptr(vt))) { if (analyze_vtable(vt) > 0) { vt_found = vt_found + 1; found = found + 1; g_stat_brute = g_stat_brute + 1; } } xv = get_next_dref_to(ea, xv); } if (vt_found == 0) { auto extra = brute_force_vt_for_col(ea); found = found + extra; g_stat_brute = g_stat_brute + extra; } } } ea = ea + 4; if ((ea & 0xFFFF) == 0) { } } } log_info("brute " + arch_label + ": " + ltoa(found, 10) + " novas vtables"); return found; } static brute_force_x64() { return brute_force_rtti(); } // ========================================================================= // PROPAGACAO DE OVERRIDES // // Para cada classe com pais, percorre o primeiro pai (ancestral imediato) // e compara slot a slot: // - Mesmo func ptr -> METODO HERDADO (apenas registra) // - Func ptr difere -> OVERRIDE (comenta no slot e na funcao) // // Tambem emite vtables_overrides.json com as relacoes encontradas. // ========================================================================= static emit_override_json(child_name, child_vt, slot_idx, parent_name, parent_func, child_func) { auto of = g_overrides_handle; if (of == 0) return; if (!g_overrides_first) fprintf(of, ",\n"); g_overrides_first = 0; fprintf(of, " {\"child\": \"%s\", \"slot\": %d, \"parent\": \"%s\", \"parent_func\": \"0x%x\", \"child_func\": \"0x%x\"}", child_name, slot_idx, parent_name, parent_func, child_func); } static first_parent_td(parents_csv) { if (parents_csv == "" || parents_csv == 0) return 0; auto pos = strstr(parents_csv, ","); auto first = (pos != -1) ? substr(parents_csv, 0, pos) : parents_csv; return atol(first); } static find_parent_td_for_offset(col_ea, target_offset) { if (target_offset == 0) return 0; auto chd = col_read_field(col_ea, 0x10); if (!is_valid_data_ptr(chd)) return 0; auto num_bases = get_wide_dword(chd + 0x08); if (num_bases <= 1 || num_bases > 64) return 0; auto bca_field = get_wide_dword(chd + 0x0C); auto bca_ea = g_is_64 ? rva_to_ea(bca_field) : bca_field; if (!is_valid_data_ptr(bca_ea)) return 0; auto i; for (i = 1; i < num_bases; i = i + 1) { auto bcd_field = get_wide_dword(bca_ea + i * 4); auto bcd_ea = g_is_64 ? rva_to_ea(bcd_field) : bcd_field; if (!is_valid_data_ptr(bcd_ea)) continue; auto mdisp = get_wide_dword(bcd_ea + 0x08); if (mdisp == target_offset) { auto td_field = get_wide_dword(bcd_ea); return g_is_64 ? rva_to_ea(td_field) : td_field; } } return 0; } // ========================================================================= // TOPOLOGICAL SORT (pais antes de filhos) // ========================================================================= static topo_dfs(vt_ea, count) { if (arr_get_long(ARR_TOPO_VISITED, vt_ea) > 0) return count; arr_set_long(ARR_TOPO_VISITED, vt_ea, 1); auto parents = hier_parents(vt_ea); auto buf = ""; auto i; auto n = strlen(parents); for (i = 0; i <= n; i = i + 1) { auto c = (i < n) ? substr(parents, i, i + 1) : ","; if (c == ",") { if (buf != "") { auto td = atol(buf); auto pvt = hier_vt_by_td(td); if (pvt != BADADDR) count = topo_dfs(pvt, count); } buf = ""; } else { buf = buf + c; } } arr_set_long(ARR_TOPO_ORDER, count, vt_ea); return count + 1; } static topo_build() { arr_init(ARR_TOPO_VISITED); arr_init(ARR_TOPO_ORDER); arr_init(ARR_TOPO_COUNT); auto count = 0; auto i; for (i = 0; i < g_vt_list_count; i = i + 1) { if (user_cancelled()) break; auto vt = hier_vt_at(i); if (vt != BADADDR) count = topo_dfs(vt, count); } arr_set_long(ARR_TOPO_COUNT, 0, count); log_info("Topological order: " + ltoa(count, 10) + " classes"); return count; } static topo_at(idx) { auto v = arr_get_long(ARR_TOPO_ORDER, idx); if (v == -1) return BADADDR; return v; } static topo_count() { auto v = arr_get_long(ARR_TOPO_COUNT, 0); if (v == -1) return 0; return v; } static propagate_overrides() { if (!PROPAGATE_OVERRIDES) return; if (g_vt_list_count == 0) return; auto tcount = topo_count(); if (tcount == 0) return; log_info("=== Passada de overrides em ordem topologica (" + ltoa(tcount, 10) + " classes) ==="); auto i; for (i = 0; i < tcount; i = i + 1) { if (user_cancelled()) return; auto vt_ea = topo_at(i); if (vt_ea == BADADDR) continue; auto parents_csv = hier_parents(vt_ea); if (parents_csv == "") continue; auto col_offset = hier_offset(vt_ea); auto parent_td; if (col_offset == 0) { parent_td = first_parent_td(parents_csv); } else { auto col_ea2 = hier_col(vt_ea); if (col_ea2 == BADADDR) continue; parent_td = find_parent_td_for_offset(col_ea2, col_offset); } if (parent_td == 0) continue; auto parent_vt = hier_vt_by_td(parent_td); if (parent_vt == BADADDR) { continue; } auto child_name = hier_name(vt_ea); auto parent_name = hier_name(parent_vt); auto own_count = hier_count(vt_ea); auto parent_count = hier_count(parent_vt); auto limit = (parent_count < own_count) ? parent_count : own_count; auto j; for (j = 0; j < limit; j = j + 1) { auto cslot = vt_ea + j * g_ptr_size; auto pslot = parent_vt + j * g_ptr_size; auto cfunc = read_ptr(cslot); auto pfunc = read_ptr(pslot); if (cfunc == pfunc) { g_stat_inherited = g_stat_inherited + 1; if (!DRY_RUN) { auto pname = get_func_name(pfunc); auto child_pattern = child_name + "__vmethod_" + ltoa(j, 10); if (pname == child_pattern) { auto canonical = parent_name + "__vmethod_" + ltoa(j, 10); if (set_name(pfunc, canonical, SN_NOWARN | SN_FORCE)) { g_stat_renamed_inherited = g_stat_renamed_inherited + 1; pname = canonical; } } set_cmt(cslot, sprintf("[%d] HERDADO de %s (-> %s)", j, parent_name, pname), 0); } } else { g_stat_overrides = g_stat_overrides + 1; if (!DRY_RUN) { auto pname2 = get_func_name(pfunc); set_cmt(cslot, sprintf("[%d] OVERRIDE de %s::%s", j, parent_name, pname2), 0); set_color(cslot, CIC_ITEM, COLOR_OVERRIDE); auto cfn = get_func_name(cfunc); auto rep = "Override de " + parent_name + "::" + pname2; auto existing = get_func_cmt(cfunc, 1); auto can_set_func_cmt = 0; if (existing == "" || existing == 0) can_set_func_cmt = 1; else if (starts_with(existing, "Override de ")) can_set_func_cmt = 1; if (can_set_func_cmt) set_func_cmt(cfunc, rep, 1); } emit_override_json(child_name, vt_ea, j, parent_name, pfunc, cfunc); } } } log_info("Overrides: " + ltoa(g_stat_overrides, 10) + " Herdados: " + ltoa(g_stat_inherited, 10)); } // ========================================================================= // MAIN // ========================================================================= static main() { if (CLEAR_OUTPUT_ON_START) { process_ui_action("msglist:Clear", 0); } msg("\n========================================\n"); msg("Vtable Analyzer Pro v5.3 - iniciando...\n"); msg("========================================\n"); if (REGISTER_HOTKEY) { add_idc_hotkey(HOTKEY_COMBO, "main"); msg("[INFO] Hotkey %s registrada para re-rodar o script\n", HOTKEY_COMBO); } g_is_64 = (get_inf_attr(INF_LFLAGS) & LFLG_64BIT) ? 1 : 0; g_ptr_size = g_is_64 ? 8 : 4; g_imagebase = get_imagebase(); g_json_first = 1; g_overrides_first = 1; g_vt_list_count = 0; g_stat_classes = 0; g_stat_methods = 0; g_stat_renamed = 0; g_stat_ctors = 0; g_stat_dtors = 0; g_stat_pures = 0; g_stat_overrides = 0; g_stat_inherited = 0; g_stat_brute = 0; g_stat_thiscall = 0; g_stat_sizes = 0; g_stat_singletons = 0; g_stat_vcalls = 0; g_stat_header_classes = 0; g_stat_renamed_inherited = 0; g_purecall_csv = ""; g_stat_filtered = 0; g_stat_errors = 0; auto out_dir = resolve_output_dir(); auto json_path = path_join(out_dir, OUTPUT_JSON_NAME); auto log_path = path_join(out_dir, OUTPUT_LOG_NAME); auto overrides_path = path_join(out_dir, OUTPUT_OVERRIDES_NAME); auto header_path = path_join(out_dir, OUTPUT_HEADER_NAME); msg("[INFO] Pasta de saida: %s\n", out_dir); msg("[INFO] JSON esperado em: %s\n", json_path); msg("[INFO] LOG esperado em: %s\n", log_path); msg("[INFO] OVERRIDES esperado em: %s\n", overrides_path); msg("[INFO] HEADER esperado em: %s\n", header_path); g_log_handle = safe_fopen(log_path, "w"); if (g_log_handle == 0) { msg("[WARN] Log em arquivo desabilitado, continuando so com console.\n"); } log_info("===================================================="); log_info(" Vtable Analyzer Pro v5.3 - IDA Free 9.x"); log_info("===================================================="); log_info("Arquitetura : " + (g_is_64 ? "x64" : "x86")); log_info("Ptr size : " + ltoa(g_ptr_size, 10)); log_info("Image base : 0x" + ltoa(g_imagebase, 16)); log_info("Pasta saida : " + out_dir); log_info("Dry run : " + (DRY_RUN ? "SIM" : "NAO")); log_info("Cria struct : " + (CREATE_STRUCTS ? "SIM" : "NAO")); log_info("Sobrescreve : " + (RENAME_OVERRIDES ? "SIM" : "NAO")); log_info("Ponteiro-scan: " + (POINTER_FIRST_SCAN ? "SIM" : "NAO")); log_info("String-scan : " + (STRING_FIRST_SCAN ? "SIM" : "NAO")); log_info("Overrides : " + (PROPAGATE_OVERRIDES ? "SIM" : "NAO")); log_info("Brute x64 : " + (BRUTE_FORCE_X64_RVA ? "SIM" : "NAO") + (g_is_64 ? "" : " (inerte em x86)")); log_info("Brute x86 : " + (BRUTE_FORCE_X86 ? "SIM" : "NAO") + (g_is_64 ? " (inerte em x64)" : "")); log_info("__thiscall : " + (APPLY_THISCALL_TYPES ? "SIM" : "NAO")); log_info("Sizeof obj : " + (DETECT_OBJECT_SIZES ? "SIM" : "NAO")); log_info("Singletons : " + (DETECT_SINGLETONS ? "SIM" : "NAO")); log_info("VCall annotat: " + (ANNOTATE_VCALLS ? "SIM" : "NAO")); log_info("CPP header : " + (EMIT_CPP_HEADER ? "SIM" : "NAO")); log_info("Excl framewrk: " + (EXCLUDE_FRAMEWORK_CLASSES ? "SIM" : "NAO")); log_info("Size inferenc: " + (SIZE_INFER_FROM_BODY ? "SIM" : "NAO")); log_info("Singl agressv: " + (SINGLETON_AGGRESSIVE ? "SIM" : "NAO")); cache_init(); init_purecall_addresses(); if (g_purecall_csv != "") { log_info("purecall enderecos conhecidos: " + g_purecall_csv); } g_json_handle = safe_fopen(json_path, "w"); if (g_json_handle != 0) { fprintf(g_json_handle, "{\n"); fprintf(g_json_handle, " \"meta\": {\n"); fprintf(g_json_handle, " \"arch\": \"%s\",\n", g_is_64 ? "x64" : "x86"); fprintf(g_json_handle, " \"ptr_size\": %d,\n", g_ptr_size); fprintf(g_json_handle, " \"imagebase\": \"0x%x\",\n", g_imagebase); fprintf(g_json_handle, " \"tool\": \"vtable_analyzer_pro_v5.2\",\n"); fprintf(g_json_handle, " \"stats_note\": \"methods=total slots; pures/inherited/overrides sao subconjuntos disjuntos de methods\"\n"); fprintf(g_json_handle, " },\n"); fprintf(g_json_handle, " \"classes\": [\n"); } g_overrides_handle = safe_fopen(overrides_path, "w"); if (g_overrides_handle != 0) { fprintf(g_overrides_handle, "{\n \"overrides\": [\n"); } if (POINTER_FIRST_SCAN) scan_via_pointers(); if (STRING_FIRST_SCAN) scan_via_rtti_strings(); if ((g_is_64 && BRUTE_FORCE_X64_RVA) || (!g_is_64 && BRUTE_FORCE_X86)) brute_force_rtti(); topo_build(); propagate_overrides(); apply_all_thiscall_types(); annotate_virtual_calls(); emit_cpp_header(header_path); if (g_json_handle != 0) { fprintf(g_json_handle, "\n ],\n"); fprintf(g_json_handle, " \"stats\": {\n"); fprintf(g_json_handle, " \"classes\": %d,\n", g_stat_classes); fprintf(g_json_handle, " \"methods\": %d,\n", g_stat_methods); fprintf(g_json_handle, " \"renamed\": %d,\n", g_stat_renamed); fprintf(g_json_handle, " \"ctors\": %d,\n", g_stat_ctors); fprintf(g_json_handle, " \"dtors\": %d,\n", g_stat_dtors); fprintf(g_json_handle, " \"pures\": %d,\n", g_stat_pures); fprintf(g_json_handle, " \"overrides\": %d,\n", g_stat_overrides); fprintf(g_json_handle, " \"inherited\": %d,\n", g_stat_inherited); fprintf(g_json_handle, " \"brute_x64\": %d,\n", g_stat_brute); fprintf(g_json_handle, " \"thiscall\": %d,\n", g_stat_thiscall); fprintf(g_json_handle, " \"sizes\": %d,\n", g_stat_sizes); fprintf(g_json_handle, " \"singletons\":%d,\n", g_stat_singletons); fprintf(g_json_handle, " \"vcalls\": %d,\n", g_stat_vcalls); fprintf(g_json_handle, " \"hdr_class\": %d,\n", g_stat_header_classes); fprintf(g_json_handle, " \"renamed_inherited\": %d,\n", g_stat_renamed_inherited); fprintf(g_json_handle, " \"methods_concrete\": %d,\n", g_stat_methods - g_stat_pures); fprintf(g_json_handle, " \"filtered\": %d,\n", g_stat_filtered); fprintf(g_json_handle, " \"errors\": %d\n", g_stat_errors); fprintf(g_json_handle, " }\n}\n"); fclose(g_json_handle); } if (g_overrides_handle != 0) { fprintf(g_overrides_handle, "\n ]\n}\n"); fclose(g_overrides_handle); } log_info("===================================================="); log_info(" RESUMO"); log_info(" Classes encontradas : " + ltoa(g_stat_classes, 10)); log_info(" Metodos virtuais : " + ltoa(g_stat_methods, 10)); log_info(" Funcoes renomeadas : " + ltoa(g_stat_renamed, 10)); log_info(" Construtores : " + ltoa(g_stat_ctors, 10)); log_info(" Destrutores : " + ltoa(g_stat_dtors, 10)); log_info(" Purecalls : " + ltoa(g_stat_pures, 10)); log_info(" Overrides marcados : " + ltoa(g_stat_overrides, 10)); log_info(" Metodos herdados : " + ltoa(g_stat_inherited, 10)); log_info(" Brute x64 : " + ltoa(g_stat_brute, 10)); log_info(" __thiscall : " + ltoa(g_stat_thiscall, 10)); log_info(" Sizes detectados : " + ltoa(g_stat_sizes, 10)); log_info(" Singletons : " + ltoa(g_stat_singletons, 10)); log_info(" VCall sites : " + ltoa(g_stat_vcalls, 10)); log_info(" Classes no header : " + ltoa(g_stat_header_classes, 10)); log_info(" Renorm. herdados : " + ltoa(g_stat_renamed_inherited, 10)); log_info(" Metodos concretos : " + ltoa(g_stat_methods - g_stat_pures, 10)); log_info(" Filtradas (framework): " + ltoa(g_stat_filtered, 10)); log_info(" Erros : " + ltoa(g_stat_errors, 10)); log_info("===================================================="); log_info("JSON : " + json_path); log_info("OVERRIDES : " + overrides_path); log_info("HEADER : " + header_path); log_info("LOG : " + log_path); log_info(""); log_info("=== ARQUIVOS GERADOS ==="); auto check_h; check_h = fopen(json_path, "r"); if (check_h != 0) { fseek(check_h, 0, 2); log_info(sprintf(" JSON : %d bytes", ftell(check_h))); fclose(check_h); } else { log_info(" JSON : NAO GERADO"); } check_h = fopen(overrides_path, "r"); if (check_h != 0) { fseek(check_h, 0, 2); log_info(sprintf(" OVERRIDES : %d bytes", ftell(check_h))); fclose(check_h); } else { log_info(" OVERRIDES : NAO GERADO"); } check_h = fopen(header_path, "r"); if (check_h != 0) { fseek(check_h, 0, 2); log_info(sprintf(" HEADER : %d bytes", ftell(check_h))); fclose(check_h); } else { log_info(" HEADER : NAO GERADO"); } if (g_log_handle != 0) fclose(g_log_handle); msg("\n=== Vtable Analyzer Pro v5.3 finalizado ===\n"); msg("Classes=%d Metodos=%d Renomeadas=%d Ctors=%d Dtors=%d Pures=%d Overrides=%d\n", g_stat_classes, g_stat_methods, g_stat_renamed, g_stat_ctors, g_stat_dtors, g_stat_pures, g_stat_overrides); msg("ThisCall=%d Sizes=%d Singletons=%d VCalls=%d HdrClasses=%d\n", g_stat_thiscall, g_stat_sizes, g_stat_singletons, g_stat_vcalls, g_stat_header_classes); }
    1 ponto
  25. CHASE HEROES — NOVA ERA DOS HEROES COMEÇOU ! 14/05/2026 [ ON ] Grand Chase Heroes - Servidor Season 5 PT 3 CADASTRO DE CONTAS NO LAUCHER A O CADASTRAR GANHE BONUS PARA COMEÇAR ALGUNS TOKENS PARA ACELERAR SUA EVOLUÇÃO KitPergaMistico SUPORTE-INICIANTE INICIANTEHEROES HARKYON-KIT-FREE ( APENAS OS 50 PRIMEIROS KIT-BERKAS001 BAUDECARTAENDGAME1 Chase_Heroes#143415 ( SET MAGI ) GLADIADOR2026 ( VISUAL GLADIADOR ) NO SERVIDOR GRAND CHASE HEROES ALGUNS CHAR TOMARAM ALGUNS REWORKS EM SUAS HABILIDADES LIRE MUDANÇAS EM VIDEO ARME MUDANÇAS EM VIDEO LASS MUDANÇAS EM VIDEO ⚡ PERSONAGENS EM DESTAQUE ✔️ Lin — META ✔️ Ryan — Todas classes buffadas ✔️ Elesis — Todas classes buffadas ✔️ Ronan - Buffado ✔️ Uno — Buffado ✔️ Azin — Buffado ✔️ Jin — Buffado ✔️ Zero — Buffado ✔️ Dio — Balanceado ✔️ Veigas — Balanceado ✔️ Holy - Buffado ✔️ Mari - Buffado ✔️ Ai - Balanceado ✔️ Peryton - Buffado TODOS OS CHARS ATE DECANE E AI KALLIA E IRIS EM TRABALHO TAMBEM TEMOS CONTEUDOS PARA DONATE 🔥 ALGUMAS OUTROS INFORMAÇÃO 🔥 ⚔️ Level Máximo 101 🎮 Farme de CASH através de Mini Games no Launcher 🎉 Eventos dos GMs constantemente ativos 💬 Eventos exclusivos no Discord valendo CASH 📖 Guias Evolutivos disponíveis no Discord 🛡️ Staff extremamente ativa e sempre presente no chat ✨ ITENS E CONTEÚDOS EXCLUSIVOS ✨ 🔹 Títulos Exclusivos PLACA JONNY THUG Pierc do Void Pierc do Renak - Necessário Craftar Apenas Uma Vez Pode ser utilizado em TODOS os personagens ⚖️BALANCEAMENTO CONFORME VOCÊS PEDEM ⚖️ No Chase Heroes o feedback dos jogadores realmente importa. Estamos constantemente ajustando personagens, skills e conteúdos para deixar o servidor mais divertido e equilibrado. DISCORD : CLICA AQUI Atraves do Discord você tem acesso ao Cadastro e Download
    1 ponto
  26. Pack Grátis - MC RAPOSINHA | Michelle Rabbit MC RAPOSINHA Download Pack: [Hidden Content] MICHELLE RABBIT Download Pack: [Hidden Content]
    1 ponto
  27. struct STRUCT_MOB { char MobName[NAME_LENGTH]; // Nome do MOB/NPC/Player 1FDECA0 byte 0 a 15 dentro da STRUCT_MOB da TMSrv 1.7 char Clan; // Reino ou Grupo do MOB/NPC/Player 1FDECB0 byte 16 dentro da STRUCT_MOB da TMSrv 1.7 char Merchant; // Identificador da merchant 1FDECB1 byte 17 dentro da STRUCT_MOB da TMSrv 1.7 unsigned short Guild; // Identificador da Guild do MOB/NPC/Player 1FDECB2 byte 18 a 19 dentro da STRUCT_MOB da TMSrv 1.7 char Class; // Identificador da classe do MOB/NPC/Player 1FDECB4 byte 20 dentro da STRUCT_MOB da TMSrv 1.7 unsigned char Rsv; // AffectInfo 1FDECB5 byte 21 dentro da STRUCT_MOB da TMSrv 1.7 short Quest; // QuestInfo 1FDECB6 byte 22 a 23 dentro da STRUCT_MOB da TMSrv 1.7 int Coin; // Gold atual do MOB/NPC/Player 1FDECB8 byte 24 a 27 dentro da STRUCT_MOB da TMSrv 1.7 unsigned int Exp; // Experiencia atual do MOB/NPC/Player 1FDECBC byte 28 a 31 dentro da STRUCT_MOB da TMSrv 1.7 short SPX; // Ultima posição X salva com a Gema Estelar 1FDECC0 byte 32 a 33 dentro da STRUCT_MOB da TMSrv 1.7 short SPY; // Ultima posição Y salva com a Gema Estelar 1FDECC2 byte 34 a 35 dentro da STRUCT_MOB da TMSrv 1.7 STRUCT_SCORE BaseScore; // Status base 1FDECC4 byte 36 a 63 dentro da STRUCT_MOB da TMSrv 1.7 STRUCT_SCORE CurrentScore; // Status atual 1FDECE0 byte 64 a 91 dentro da STRUCT_MOB da TMSrv 1.7 STRUCT_ITEM Equip[MAX_EQUIP]; // Itens equipados no personagem 1FDECFC byte 92 a 219 dentro da STRUCT_MOB da TMSrv 1.7 STRUCT_ITEM Inventory[MAX_INVENTORY]; // Itens do inventario 1FDED7C byte 220 a 731 dentro da STRUCT_MOB da TMSrv 1.7 unsigned int LearnedSkill; // Skills Aprendidas - Dividido em 4 categorias (00 _ 00 _ 00 _ 00) 1FDEF7C byte 732 dentro da STRUCT_MOB da TMSrv 1.7 unsigned short ScoreBonus; // Pontos de Status (Força, Inteligencia, Dextreza, Constituição) 1FDEF80 byte 736 dentro da STRUCT_MOB da TMSrv 1.7 unsignes short SpecialBonus; // Pontos de Apreendizagem (Aprender Arma, Especial1, Especial2, Especial3) 1FDEF82 byte 738 dentro da STRUCT_MOB da TMSrv 1.7 unsignes short SkillBonus; // Pontos de Skill 1FDEF84 byte 740 dentro da STRUCT_MOB da TMSrv 1.7 char Critical; // Chance de Hits Criticos 1FDEF86 byte 742 dentro da STRUCT_MOB da TMSrv 1.7 char SaveMana; // 1FDEF87 byte 743 dentro da STRUCT_MOB da TMSrv 1.7 char SkillBar1[4]; // Salva o id de 4 skills da barra 1 //char SkillBar1[0]; 1FDEF88 byte 744 dentro da STRUCT_MOB da TMSrv 1.7 //char SkillBar1[1]; 1FDEF89 byte 745 dentro da STRUCT_MOB da TMSrv 1.7 //char SkillBar1[2]; 1FDEF8A byte 746 dentro da STRUCT_MOB da TMSrv 1.7 //char SkillBar1[3]; 1FDEF8B byte 747 dentro da STRUCT_MOB da TMSrv 1.7 char GuildLevel; // Identifica se o Player é membrou ou lider do clan 1FDEF8C byte 748 dentro da STRUCT_MOB da TMSrv 1.7 unsigned char Magic; // multiplicador de dano magico 1FDEF8D byte 749 dentro da STRUCT_MOB da TMSrv 1.7 char RegenHP; // Regeneração de HP 1FDEF8E byte 750 dentro da STRUCT_MOB da TMSrv 1.7 char RegenMP; // Regeneração de MP 1FDEF8F byte 751 dentro da STRUCT_MOB da TMSrv 1.7 char Resist[4]; // Identifica as resistencias Sagrado - Trovão - Fogo - Gelo //char Resist[0]; 1FDEF90 byte 752 dentro da STRUCT_MOB da TMSrv 1.7 //char Resist[1]; 1FDEF91 byte 753 dentro da STRUCT_MOB da TMSrv 1.7 //char Resist[2]; 1FDEF92 byte 754 dentro da STRUCT_MOB da TMSrv 1.7 //char Resist[3]; 1FDEF93 byte 755 dentro da STRUCT_MOB da TMSrv 1.7 } class CMob // 1724 size original da CMob 7.56 { public: //O size original da STRUCT_MOB na TMSrv 7.56 é 756 bytes STRUCT_MOB MOB; //0 - 755 //1FDECA0 addr inicial da pMob na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D84AC0 - STRUCT_MOB 100% Mapeada int Hold; //756 - 759 //1FDEF94 - CORRETO - TMSrv 7.57 7D84EC0 - 1024 - 1027 - 0x400 int ChatBlockTime; //760 - 763 //1FDEF98 - CORRETO - TMSrv 7.57 7D84EC4 int NightmareTicket; //764 - 767 //1FDEF9C (escritura do pesadelo para celestial+) - CORRETO - TMSrv 7.57 int Mileage; //768 - 771 //1FDEFA0 addr da Mileage na TMSrv 7.56 - CORRETO - TMSrv 7.57 //guarda a quantia de cash que tem na conta int unk_1FDEFA4; //772 - 775 //1FDEFA4 TMSrv 7.57 int Fame; //776 - 779 //1FDEFA8 addr da Fama na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D8514C int KefraTicket; //780 - 783 //1FDEFAC addr da KefraTicket na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D84ED8 int unk_1FDEFB0; //784 - 787 //1FDEFB0 alguma coisa haver com a fada do vale TMSrv 7.57 7D84EDC STRUCT_AFFECT SaveAffect[MAX_AFFECT]; //788 - 915 //1FDEFB4 - é uma STRUCT_AFFECT e é usada na save and quit talvez para salvar os affects do celestial ou algo assim - addr 004B859D char isChatBlock; //916 //1FDF034 - 0 chat sem bloqueio - 1 chat bloqueado - CORRETO - TMSrv 7.57 7D84FE0 - 1312 - 0x520 char CristalQuest; //917 //1FDF035 - CORRETO - TMSrv 7.57 7D84FE1 - 1313 - 0x521 //verificação do andamento da quest dos cristais chama a função 00414E70(CristalQuest, i) i = 0; i < 4; i++ //00414ED0 provavelmente a função que seta o uso do cristal (1 << i) & CristalQuest //(0: Não iniciou a quest - 1: usou o cristal Elime - 2: usou o cristal Silphed - 4: usou o cristal Thelion - 8: usou o cristal Noas) char isArchBlockedLvl; //918 //1FDF036 - CORRETO - TMSrv 7.57 7D84FE2 - 1314 - 0x522 char ArchLvlandFuryStone; //919 //1FDF037 - CORRETO - TMSrv 7.57 7D84FE3 - 1315 - 0x523 //valor vai de 1 a 8 - lvl do arch quando o celestial foi criado ate o 5 + resets pedra da furia 6 a 8 char unk_1FDF038; //920 //1FDF038 - relacionado a bloqueio de lvl char isBlockedLvl; //921 //1FDF039 - relacionado a bloqueio de lvl - CORRETO - TMSrv 7.57 7D84FE5 - 1317 - 0x525 char unk_1FDF03A; //922 //1FDF03A - relacionado a bloqueio de lvl char unk_1FDF03B; //923 //1FDF03B - relacionado a bloqueio de lvl char unk_1FDF03C; //924 //1FDF03C - relacionado a bloqueio de lvl char isHardCore; //925 //1FDF03D - Relacionado ao Hardcore - CORRETO - TMSrv 7.57 7D84FE9 - 1321 - 0x529 char soulType; //926 //1FDF03E - salva a config da Soul vai de 1 - 10 - CORRETO - TMSrv 7.57 7D84FEA - 1322 - 0x52A char isGodOrSub; //927 //1FDF03F - celestial:0 sub:1 - CORRETO - TMSrv 7.57 7D84FEB - //size da Struct que salva as infos do celestial e do sub é 68 bytes na 756 e 96 bytes na 757+ STRUCT_SUBCLASSINFO saveSubClassInfo[2];//932 - 1067 //1FDF044 - Salva as Infos do Cele e do Sub - CORRETO - TMSrv 7.57 7D84FF0 - int unk_1FDF0E0; //1088 - 1091 //1FDF0E0 - CORRETO - TMSrv 7.57 7D850C4 - STRUCT_AFFECT Affect[MAX_AFFECT]; //1204 - 1331 //1FDF154 addr da Affect na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85148 - 1672 - 1927 - 0x688 //Originalmente na TMSrv 7.56 tem 1332 bytes antes da variavel Mode ou seja do 0 ao 1331 - TMSrv 7.57 tem 2084 bytes antes da variavel Mode ou seja do 0 ao 2083 int Mode; //1332 - 1335 //1FDF1D4 addr da Mode na TMSrv1.7 - CORRETO - TMSrv 7.57 7D852E4 - 2084 - 2087 - 0x824 int Leader; //1336 - 1339 //1FDF1D8 addr da Leader na TMSrv1.7 - CORRETO - TMSrv 7.57 7D852E8 - 2088 - 2091 - 0x828 int Formation; //1340 - 1343 //1FDF1DC addr da Formation na TMSrv1.7 - CORRETO - TMSrv 7.57 7D852EC - 2092 - 2095 - 0x82C int RouteType; //1344 - 1347 //1FDF1E0 addr da RouteType na TMSrv1.7 - CORRETO - TMSrv 7.57 7D852F0 - 2096 - 2099 - 0x830 int LastX; //1348 - 1351 //1FDF1E4 addr da LastX na TMSrv1.7 - CORRETO - TMSrv 7.57 7D852F4 - 2100 - 2103 - 0x834 int LastY; //1352 - 1355 //1FDF1E8 addr da LastY na TMSrv1.7 - CORRETO - TMSrv 7.57 7D852F8 - 2104 - 2107 - 0x838 int LastTime; //1356 - 1359 //1FDF1EC addr da LastTime na TMSrv1.7 - CORRETO - TMSrv 7.57 7D852FC - 2108 - 2111 - 0x83C int LastSpeed; //1360 - 1363 //1FDF1F0 addr da LastSpeed na TMSrv1.7 - CORRETO - TMSrv 7.57 7D85300 - 2112 - 2115 - 0x840 int TargetX; //1364 - 1367 //1FDF1F4 addr da targetX na TMSrv1.7 - CORRETO - TMSrv 7.57 7D85304 - 2116 - 2119 - 0x844 int TargetY; //1368 - 1371 //1FDF1F8 addr da TargetY na TMSrv1.7 - CORRETO - TMSrv 7.57 7D85308 - 2120 - 2123 - 0x848 int NextX; //1372 - 1375 //1FDF1FC addr da NextX na TMSrv1.7 - CORRETO - TMSrv 7.57 7D8530C - 2124 - 2127 - 0x84C int NextY; //1376 - 1379 //1FDF200 addr da NextY na TMSrv1.7 - CORRETO - TMSrv 7.57 7D85310 - 2128 - 2131 - 0x850 int NextAction; //1380 - 1383 //1FDF204 addr da NextAction na TMSrv1.7 - CORRETO - TMSrv 7.57 7D85314 - 2132 - 2135 - 0x854 char Route[MAX_ROUTE]; //1384 - 1407 //1FDF208 addr da Route na TMSrv1.7 - CORRETO - TMSrv 7.57 7D85318 - 2136 - 2159 - 0x858 int WaitSec; //1408 - 1411 //1FDF220 addr da WaitSec na TMSrv1.7 - CORRETO - TMSrv 7.57 7D85330 - 2160 - 2163 - 0x870 int PosX; //1412 - 1415 //1FDF224 addr da PosX na TMSrv1.7 int PosY; //1416 - 1419 //1FDF228 addr da PosY na TMSrv1.7 int Segment; //1420 - 1423 //1FDF22C addr da Segment na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D8526C - 1964 - 1967 - 0x7AC int SegmentX; //1424 - 1427 //1FDF230 addr da SegmentX na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85270 - 1968 - 1971 - 0x7B0 int SegmentY; //1428 - 1431 //1FDF234 addr da SegmentY na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85274 - 1972 - 1975 - 0x7B4 int SegmentListX[MAX_SEGMENT]; //1432 - 1451 //1FDF238 addr da SegmentListX na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85278 - 1976 - 1995 - 0x7B8 int SegmentListY[MAX_SEGMENT]; //1452 - 1471 //1FDF24C addr da SegmentListY na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D8528C - 1996 - 2015 - 0x7CC int SegmentWait[MAX_SEGMENT]; //1472 - 1491 //1FDF260 addr da SegmentWait na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D852A0 - 2016 - 2035 - 0x7E0 int SegmentDirection; //1492 - 1495 //1FDF274 addr da SegmentRange na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D852B4 - 2036 - 2039 - 0x7F4 int SegmentProgress; //1496 - 1499 //1FDF278 addr da SegmentDirection na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D852B8 - 2040 - 2043 - 0x7F8 int GenerateIndex; //1500 - 1503 //1FDF27C addr da GenerateIndex na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D852BC - 2044 - 2047 - 0x7FC unsigned short CurrentTarget; //1504 - 1505 //1FDF280 addr da CurrentTarget na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D852C0 - 2048 - 2049 - 0x800 unsigned short EnemyList[MAX_ENEMY]; //1506 - 1513 //1FDF282 addr da EnemyList na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D852C2 - 2050 - 2057 - 0x802 short PartyList[MAX_PARTY]; //1514 - 1537 //1FDF28A addr da PartyList na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D852CA - 2058 - 2081 - 0x80A short unk_1FDF2A2; //1538 - 1539 //1FDF2A2 int WeaponDamage; //1540 - 1543 //1FDF2A4 addr da WeaponDamage na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85334 - 2164 - 2167 - 0x874 int Summoner; //1544 - 1547 //1FDF2A8 addr da Summoner na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85338 - 2168 - 2171 - 0x878 int PotionCount; //1548 - 1551 //1FDF2AC addr da PotionCount na TMSrv 7.56 TMSrv 7.57 7D8533C - 2172 - 2175 - 0x87C int GuildDisable; //1552 - 1555 //1FDF2B0 addr da GuildDisable na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85340 - 2176 - 2179 - 0x880 int DropBonus; //1556 - 1559 //1FDF2B4 addr da DropBonus na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85344 - 2180 - 2183 - 0x884 int ExpBonus; //1560 - 1563 //1FDF2B8 addr da ExpBonus na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85348 - 2184 - 2187 - 0x888 int Range; //1564 - 1567 //1FDF2BC addr da Range na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D8534C - 2188 - 2191 - 0x88C int unk_1FDF2C0; //1568 - 1571 //1FDF2C0 TMSrv 7.57 7D85350 - 2192 - 2195 - 0x890 int unk_1FDF2C4; //1572 - 1575 //1FDF2C4 TMSrv 7.57 7D85354 - 2196 - 2199 - 0x894 int MobFace; //1576 - 1579 //1FDF2C8 addr da MobFace na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85358 - 2200 - 2203 - 0x898 //Calculo é feito com MobFace % 10 < 5 Mortal ou Transformações do BM retorna 0 //> 5 verifica no Learn se tem soul se nao tiver retorna 1 //se tiver soul retorna 2 int QuestFlag; //1580 - 1583 //1FDF2CC recebe o valor 0 na CreateMob - Relacionado com QUESTs TMSrv 7.57 7D8535C - 2204 - 2207 - 0x89C BOOL KhepraLive; //1588 - 1591 //1FDF2D4 - CORRETO - TMSrv 7.57 7D85360 - 2208 - 2211 - 0x8A0 int unk_1FDF2D8; //1592 - 1595 //1FDF2D8 - CORRETO - TMSrv 7.57 7D85364 - 2212 - 2215 - 0x8A4 int unk_1FDF2DC; //1596 - 1599 //1FDF2DC - CORRETO - TMSrv 7.57 7D85368 - 2212 - 2215 - 0x8A8 int unk_1FDF2E0; //1600 - 1603 //1FDF2E0 - CORRETO - TMSrv 7.57 7D8536C - 2212 - 2215 - 0x8AC int ServerKingdom; //1584 - 1587 //1FDF2D0 - CORRETO - TMSrv 7.57 7D85380 - 2236 - 2239 - 0x8BC int ForceDamage; //1604 - 1607 //1FDF2E4 - CORRETO - TMSrv 7.57 7D85370 - 2224 - 2227 - 0x8B0 int TmpSpeed; //1644 - 1647 //1FDF30C - CORRETO - TMSrv 7.57 7D85374 - 2228 - 2231 - 0x8B4 int CurTime; //1648 - 1651 //1FDF310 - CORRETO - TMSrv 7.57 7D85378 - 2232 - 2235 - 0x8B8 int unk_7D85384; //Descobrir o que é parece um timer TMSrv 7.57 7D85384 - 2240 - 2243 - 0x8C0 int CountHpDamage; //1608 - 1611 //1FDF2E8 - CORRETO - TMSrv 7.57 7D85398 - 2264 - 2267 - 0x8D8 int countHP; //1612 - 1615 //1FDF2EC - CORRETO - TMSrv 7.57 7D8539C - 2268 - 2271 - 0x8DC int countMP; //1616 - 1619 //1FDF2F0 - CORRETO - TMSrv 7.57 7D853A0 - 2272 - 2275 - 0x8E0 int PerfBonus; //1620 - 1623 //1FDF2F4 - CORRETO - TMSrv 7.57 7D853A4 - 2276 - 2279 - 0x8E4 int AbsBonus; //1624 - 1627 //1FDF2F8 - CORRETO - TMSrv 7.57 7D853A8 - 2280 - 2283 - 0x8E8 int unk_1FDF2FC; //1628 - 1631 //1FDF2FC TMSrv 7.57 7D853AC - 2284 - 2287 - 0x8EC int SummonType; //1632 - 1635 //1FDF300 - CORRETO - TMSrv 7.57 7D853B0 - 2288 - 2291 - 0x8F0 int ItemUser; //1636 - 1639 //1FDF304 - CORRETO - TMSrv 7.57 7D853B4 - 2292 - 2295 - 0x8F4 int ItemSummoner; //1640 - 1643 //1FDF308 - CORRETO - TMSrv 7.57 7D853B8 - 2296 - 2299 - 0x8F8 short DamagePvP; // - CORRETO - TMSrv 7.57 7D853BC - 2300 - 2301 - 0x8FC short DefensePvP; // - CORRETO - TMSrv 7.57 7D853BE - 2302 - 2303 - 0x8FE short MobList[MAX_PARTY]; // - CORRETO - TMSrv 7.57 7D853C0 - 2304 - 2327 - 0x900 Proximo é o nAffectInfo int unk_1FDF314; //1652 - 1655 //1FDF314 - CORRETO - int ServerTowerId; //1656 - 1659 //1FDF318 - CORRETO - char Tab[MAX_TAB_LENGTH]; //1660 - 1687 //1FDF31C - CORRETO - TMSrv 7.57 - 1928 - 1953 - 0x788 (1FDF334 -> MAX_TAB_LENGTH - 2 = 0) (1FDF335 -> MAX_TAB_LENGTH - 1 = 0) define o fim do buffer do Tab int unk_1FDF338; //1688 - 1691 //1FDF338 - CORRETO - int unk_1FDF33C; //1692 - 1695 //1FDF33C - CORRETO - TMSrv 7.57 7D85388 - Possivelmente um Count int unk_1FDF340; //1696 - 1699 //1FDF340 - CORRETO - Possivelmente uma PosX int unk_1FDF344; //1700 - 1703 //1FDF344 - CORRETO - Possivelmente uma PosY int unk_1FDF348; //1704 - 1707 //1FDF348 - CORRETO - int nAffectInfo; //1708 - 1711 //1FDF34C - CORRETO - TMSrv 7.57 7D853D8 - 2328 - 2331 - 0x918 /* //0 off - 1 on Bit 0 : Controle de Mana (1 << 0) Bit 1 : Imunidade (1 << 1) Bit 2 : Encantar Gelo (1 << 2) Bit 3 : Possuido (1 << 3) Bit 4 : Toxina da Serpente (1 << 4) Bit 5 : Evasão Aprimorada (1 << 5) Bit 6 : Invisibilidade (1 << 6) Bit 7 : Velocidade (1 << 7) Bit 8 : (1 << 8) Bit 9 : Cancel (1 << 9) Bit 10 : Congelado (1 << 10) Bit 11 : Invuneravel (1 << 11) Bit 12 : Flash (1 << 12) */ short nSkillDalay; //1712 - 1713 //1FDF350 - CORRETO - TMSrv 7.57 7D853DC - 2332 - 2333 - 0x91C int Accuracy; //1716 - 1719 //1FDF354 - CORRETO - TMSrv 7.57 7D853E0 - 2334 - 2337 - 0x91E int Evasion; //1720 - 1723 //1FDF358 - CORRETO - TMSrv 7.57 7D853E4 - 2338 - 2343 - 0x922 }; struct STRUCT_SUBCLASSINFO { unsigned int saveLearnedSkill; // 1FDF044 - CORRETO - TMSrv 7.57 7D84FF0 - - - - salva o Learn do celestial/subcelestial unsigned int saveNLearnedSkill; // 757+ - CORRETO - TMSrv 7.57 7D84FF4 - - - - salva o Learn2 do celestial/subcelestial STRUCT_ITEM saveFace; // 1FDF048 - CORRETO - TMSrv 7.57 7D84FF8 - - - - salva Face do personagem STRUCT_SCORE saveBaseScore; // 1FDF050 - CORRETO - TMSrv 7.57 7D85000 - - - - salva a BaseScore long long saveExp; // 1FDF06C - CORRETO - TMSrv 7.57 7D85030 - salva a Exp (int na 756-) char saveSkillBar[20]; // 1FDF070 - CORRETO - TMSrv 7.57 7D85038 - salva a SkilBar1[4] e a SkillBar2[16] unsigned short saveScoreBonus; // 1FDF084 - CORRETO - TMSrv 7.57 7D8504C - salva os pontos de Score que ainda nao foram distribuidos unsigned short saveSkillBonus; // 1FDF086 - CORRETO - TMSrv 7.57 7D8504E - salva os pontos para compra de skills }; enum AFFECT_INFO { EMPTY_AFFECT = 0, MANACONTROL = 1, IMMUNE = 2, FREEZE = 4, BERSERKER = 8, POISON = 16, EVASION = 32, INVISIBLE = 64, VELOCITY = 128, IMMUNITY = 256, CANCEL = 512, FROZEN = 1024, //757+ INVULNERABLE = 2048, //757+ FLASH = 4096 //757+ }; int CMob::StandingByProcessor() //Função Ok { int rt = FALSE; //local 2 ebp-08 local 5 if (MOB.CurrentScore.MaxMp) { if (MOB.CurrentScore.Mp <= 0 && Mode != MOB_COMBAT) { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //0041724B - 004CCC8B MOB.CurrentScore.Mp--; } //0041725D - 004CCC9A int Face = MOB.Equip[FACE].Index; //local 3 ebp-0c local 8 if (Affect[0].Type != 24 && Face == 358) //Vinha { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //00417291 - 004CCCD5 if (RouteType == 5) { if (Leader <= MOB_EMPTY || Leader >= MAX_USER) { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //004172CD - 004CCD10 int otherFace = MOB.Equip[FACE].Index; //local 4 ebp-10 local 11 if (Affect[0].Type != 24 && (otherFace < 315 || otherFace > 346)) { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //0041730A - 004CCD51 int summoner = Summoner; //local 5 ebp-14 local 14 if (summoner <= MOB_EMPTY || summoner >= MAX_USER) { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //00417336 - 004CCD84 int isLeader = FALSE; //local 6 ebp-18 local 17 if (Leader == summoner) isLeader = TRUE; for (int i = 0; i < MAX_PARTY; ++i) //local 7 ebp-1c local 20 { if (pMob[Leader].PartyList[i] == summoner) isLeader = TRUE; } //00417392 - 004CCDE0 if (!isLeader) { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //004173A9 - 004CCDF9 if (Affect[0].Type == 24 && !Affect[0].Time) { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //004173D6 - 004CCE27 if (pUser[summoner].Mode == USER_PLAY) { int Distance = BASE_GetDistance(TargetX, TargetY, pMob[summoner].TargetX, pMob[summoner].TargetY); //local 8 ebp-20 local 23 if (Distance >= 20) { NextX = pMob[summoner].TargetX; NextY = pMob[summoner].TargetY; rt |= 2; return rt; } //00417472 - 004CCEC5 if (Distance > 2 && Distance < 20) { SegmentX = pMob[summoner].TargetX; SegmentY = pMob[summoner].TargetY; GetNextPos(0); rt |= 1; return rt; } } //004174CA - 004CCF1C else { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //004174DB - 004CCF2F return rt; } //004174E3 - 004CCF37 if (!Leader) { int target = GetEnemyFromView(); //local 9 ebp-24 local 26 if (target && TargetX < (SegmentX + 12) && TargetX > (SegmentX - 12) && TargetY < (SegmentY + 12) && TargetY > (SegmentY - 12)) { target |= 0x10000000; return target; } } //00417569 - 004CCFBD if (RouteType == 6 && TargetX == SegmentX && TargetY == SegmentY) return 0; //004175A4 - 004CCFF8 if (SegmentX == TargetX && SegmentY == TargetY) { //004175F4 - 004CD028 if(WaitSec > 0 && RouteType != 6) { WaitSec -= 6; if (WaitSec > 0) { if (!RouteType && TargetX == SegmentListX[0] && TargetY == SegmentListY[0]) return 0; //00417650 - 004CD0A4 if (!(MOB.BaseScore.AttackRun & 0xF)) return 0; #ifdef CLIVER756- rt |= 16; #else rt |= 4096; //7.57+ #endif return rt; } //00417677 - 004CD0CA WaitSec = 0; } else //00417686 - 004CD0D9 { int SegWait = SegmentWait[SegmentProgress]; //local 10 ebp-28 local 29 if (SegWait > 0) { WaitSec = SegWait; return rt; } } //004176B3 - 004CD106 int setSeg = SetSegment(); //local 11 ebp-2c local 32 if (setSeg == 1) return rt; //004176C9 - 004CD11C if (setSeg == 2) { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } } //004176DD - 004CD132 GetNextPos(0); if (NextX == TargetX && NextY == TargetY) { SetSegment(); return rt; } rt |= 1; return rt; } //00417890 addr da BattleProcessor na TMSrv 7.56 - TMSrv 7.57 004CD190 int CMob::BattleProcessor() //Função Ok { int Face = MOB.Equip[FACE].Index; //local 2 ebp-08 local 5 if (Affect[0].Type != 24 && Face == 358) //vinha return 32; //004178E0 - 004CD1E2 SelectTargetFromEnemyList(); if (CurrentTarget == MOB_EMPTY) { Mode = MOB_PEACE; return 0; } //0041790A - 004CD20C if (RouteType == 5) { if (Leader <= MOB_EMPTY || Leader >= MAX_USER) return 32; int SummonerId = Summoner; //local 3 ebp-0c local 8 if (SummonerId <= MOB_EMPTY || SummonerId >= MAX_USER) return 32; int HP = MOB.CurrentScore.Hp; //local 4 ebp-10 local 11 if (HP <= 0) return 32; //00417989 - 004CD288 if (Affect[0].Type != 24 && (Face < 315 || Face > 346)) return 32; //004179B5 - 004CD2B3 int Summoned = FALSE; //local 5 ebp-14 local 14 if (Leader == SummonerId) Summoned = TRUE; //004179D1 - 004CD2CF for (int i = 0; i < MAX_PARTY; i++) //local 6 ebp-18 local 17 { if (pMob[Leader].PartyList[i] == SummonerId) Summoned = TRUE; } if (!Summoned) return 32; //00417A21 - 004CD31F int Distance = BASE_GetDistance(TargetX, TargetY, pMob[SummonerId].TargetX, pMob[SummonerId].TargetY); //local 7 ebp-1c local 20 if (Distance >= 20) { NextX = pMob[SummonerId].TargetX; NextY = pMob[SummonerId].TargetY; return 2; } } //00417AA0 - 004CD39E int Int = MOB.BaseScore.Int; //local 8 ebp-20 local 23 ebp-5c if (Int < rand() % 100) return 0x10000; //00417AC6 - 004CD3C4 int Dex = MOB.BaseScore.Dex; //local 9 ebp-24 local 26 ebp-68 int posX = pMob[CurrentTarget].TargetX; //local 10 ebp-28 local 29 ebp-74 int posY = pMob[CurrentTarget].TargetY; //local 11 ebp-2c local 32 ebp-80 int Range = BASE_GetMobAbility(&MOB, EF_RANGE); //local 12 ebp-30 local 35 ebp-8c int Distance = BASE_GetDistance(TargetX, TargetY, posX, posY); //local 13 ebp-34 local 38 ebp-98 //00417B3A - 004CD43E if (CheckKhepra()) Range = 26; //00417B4D - 004CD454 if (pMob[CurrentTarget].CheckKhepra() && (Face == 307 || Face == 245)) Range = 26; //00417B85 - 004CD48F if (RouteType != 5) { if(TargetX > (SegmentX + 30) || TargetX < (SegmentX - 30) || TargetY > (SegmentY + 30) || TargetY < (SegmentY - 30)) { //004CD4FF //7.57+ esse if é somente da 7.57 para frente if (unk_1FDF2D8 != 0) //0x8A4 - identificar o que é essa variavel na 7.57 { if (CurrentTarget == MOB_EMPTY) { for (int i = MOB_EMPTY; i < MAX_ENEMY; i++) //local 41 EnemyList[i] = MOB_EMPTY; //004CD556 Mode = MOB_PEACE; NextX = SegmentListX[0]; NextY = SegmentListY[0]; return 2; } } //00417BF5 - 004CD596 else //7.56 retirar o if e deixar so o conteudo do else { CurrentTarget = MOB_EMPTY; for (int i = MOB_EMPTY; i < MAX_ENEMY; i++) //local 14 ebp-38 local 44 EnemyList[i] = MOB_EMPTY; Mode = MOB_PEACE; GetNextPos(1); if (NextX == TargetX && NextY == TargetY) return 0; else return 16; } } } //00417C7B - 004CD629 if (Distance <= Range) { int _rand = rand() % 100; //local 15 ebp-3c ebp-0bc if (Range >= 4 && Distance <= 2 && _rand > Dex && MOB.BaseScore.AttackRun & 0xF) return 256; //00417CC4 - 004CD681 int _X = posX; //local 16 ebp-40 ebp-0c8 int _Y = posY; //local 17 ebp-44 ebp-0d4 int maxDist = SECBATTLE; //local 18 ebp-48 ebp-0e0 //00417CD7 - 004CD69D if (!CheckKhepra()) { int isHall = FALSE; //local 19 ebp-4c ebp-0ec if (TargetX >= 2341 && TargetX <= 2393 && TargetY >= 3907 && TargetY <= 3954 && unk_1FDF300) isHall = TRUE; //00417D3D - 004CD709 if (!isHall) BASE_GetHitPosition(TargetX, TargetY, &posX, &posY, (char*)pHeightGrid, maxDist); } //00417D70 - 004CD742 if (posX != _X || posY != _Y) return 256; else return 4096; } //00417D8E - 004CD768 return 1; }
    1 ponto
  28. @ Grego Comprei uma conta disney em [Hidden Content] por conta deste post, e agora fica pedindo o código para confirmar a tela ou se estou fora de casa, já tem uma semana suporte n responde, nem email, nem whatsapp, usei o serviço apenas uma vez... Não recomendo. [edit] Comentei no discord da wc falando do problema, e me fizeram o reembolso.
    1 ponto
  29. Fala, pessoal. Queria compartilhar com vocês esse repositório do WYD FieldScene Studio Pro. Mesmo não sendo programador, o trabalho do Hamilton me inspirou bastante. A base do projeto e toda a ideia inicial me chamaram atenção justamente pelo quanto essa ferramenta veio pra ajudar quem mexe com interface e edição de painéis no WYD. Sem exagero algum, eu cheguei em 90 versoes em testes "ta comm tempo né" kkk A partir disso, tive a ideia de tentar tornar o programa mais acessível, principalmente para quem não tem monitor com resolução muito alta ou acaba sofrendo com a limitação de espaço na tela durante a edição. Além disso, fui buscando implementar melhorias de usabilidade, organização visual e praticidade no fluxo de trabalho, sempre tentando deixar a ferramenta mais confortável e funcional no uso do dia a dia. O objetivo não foi apagar a origem do projeto, mas sim evoluir em cima de uma base que já era boa, trazendo adaptações, correções e recursos que pudessem facilitar a vida de mais pessoas. Entre os pontos que busquei melhorar estão: - melhor adaptação para diferentes resoluções - visualização em escala 1:1 - conversão e ajuste entre resoluções - carregamento e compatibilidade de recursos - melhorias no uso geral do editor - remoção de fundo em imagens compatíveis - mais praticidade para edição, importação e visualização -o programa tem régua -arraste por mouse **OBS IMPORTANTE, É RECOMENDADO QUE QUANDO FOR SOLICITADO O CARREGAMENTO DE RECURSOS ABRA ATÉ A PASTA DO CLIENTE ONDE ESTÃO AS PASTAS UI, NUI E MESH, ASSIM O PROGRRAMA JÁ CARREGA AS 3 PASTAS NO LUGGAR DE ABRIR UMA POR VEZ, ALGUNS PAINEIS AS VEZES ESTAO FORA DA UI** e mais coisas que não me lembro agora haha Estou compartilhando porque pode ser útil para outras pessoas da área, e também porque acho justo reconhecer que essa iniciativa só existiu porque o trabalho original me motivou a tentar fazer algo também Repositório: [Hidden Content] Se alguém quiser testar, dar feedback ou sugerir melhorias, vai ser muito bem-vindo. E LEMBRANDDO CRÉDITOS TOTAIS AO HAMILTON DO CANAL HC CURSOS E TUTORIAIS
    1 ponto
  30. Há muito tempo, desenvolvi este editor, mas ele estava desatualizado. Agora, estou compartilhando a versão mais recente, atualizada com a última atualização do WYD Global, v763 (15/03/2025). Atualização 16/03/2025: Foi adicionado suporte para versão 759,763 e 769. Foi adicionado a exibição de ícones. Atualização 19/03/2025: Foi adicionado suporte para ExtraItem.bin para aqueles que não sabem todo item da itemlist que estiver dentro da extraitem.bin será substituído pelo mesmo. Download:
    1 ponto
  31. [Atualizaçao] 26/07/2026 Estou usando a Source do TMProject-Free Aqui tem bastante informaçao sobre o fork. [Hidden Content] Tem as sources e releases. Atualizo com frequência. Os itens abaixo foram descontinuados. Sugiro escanear com antivírus atualizado. Links para download: [Hidden Content] Link do Source do Cliente: [Hidden Content] Instalação WYD Linux mais simples e direta através do script bash install_wyd_linux.sh O script monta o ambiente sem forçar compilação, instala dependências e deixa o servidor pronto para configurar. Ele cria o mysql.txt para o servidor se conectar ao banco, com usuário, senha e nome do schema, e também atualiza o server.txt do cliente para apontar para o IP do servidor. No cliente, o server.txt define o endereço do servidor que o jogo vai usar. Na parte do servidor, o mysql.txt garante que DBSrv e TMSrv consigam acessar o MySQL com as credenciais certas. Decidi user um .txt no cliente para facilitar os testes. Bugs: Com certeza tem bastante, mas menos do que na versão original. As skills 9 e 10 estão implementadas (sinceramente nao testei todas ainda). Minha ideia é criar um gerenciamento via web, visto que a versão console (esta) não tem as mesmas informaçoes que a versão Windows. Toda a parte gráfica foi removida e roda direto pelo terminal. Tem um binário tmlinux (cliente). Pode ignorar. É só uma tentativa ousada de o cliente. O Cliver é 6000. Ao compilar no Windows ele cria o diretório que indica ser versão 7.69 Foi criado um arquivo ShimWin32 para tratar da compatibilidade e traduçao das chamadas WIn32 pra POSIX. A vantagem é que não preciso reescrever a lógica toda. O código continua igual, eu só traduzo a camada de API. Compile uma vez com o shim e pronto, roda em Linux mantendo tudo que funciona no Windows. Em resumo: setup feito sem precisar compilar agora; banco MySQL configurado automaticamente; mysql.txt criado para o WYD acessar o DB; server.txt do cliente ajustado para o IP certo. Assim, a configuração fica prática e você não precisa editar tudo na mão. Tem bugs comuns como inconsistência entre o ItemList.bin do cliente e o .csv do servidor. Estou corrigindo, mas não pretendo corrigir tudo porque tem muito item criado que acho desnecessário. O Cinto não equipa nessa source. Fiz a correçao na minha e libero quando tiver mais correçoes acumuladas. Tem script pra alterar o drop e xp por região. Acho que tá legal pra uma brincadeira mas não pra produção. Porém fiquem à vontade pra explorar e quem sabe compartilhar também. Tá bem suave, rodou de boa no meu celular Vivo X200 Pro no Gamehub e no Pocophone F1 rodando Fedora Mobility. Créditos: (Nomes encontrados no código) Se tiver mais alguém, basta avisar. Victor Klafke Charles TheHouse TRAE.AI GLM 5.1 Plus SexyCode BabyLove Outros
    1 ponto
  32. 1 ponto
  33. ATENÇÃO! O CHEAT FICARÁ FREE ATÉ 01/05/2026,APROVEITE! Fala seus arr0mbados, trago para a comunidade um WALLHACK INDETECTÁVEL, já faz ANOS que utilizo e nunca desatualizou, joguem com responsabilidade! Sem enrolação, vamos direto ao ponto! 1 - EXECUTE O SEU POINT BLANK E LOGUE NA SUA CONTA; 2 - ATIVE O MODO JANELA (PARA O MELHOR FUNCIONAMENTO DO CHEAT, EVITANDO TRAVAMENTOS); 3 - EXECUTE O ARQUIVO "WALL PREMIUM - LOADER PB" COMO ADMINISTRADOR E FECHE A JANELA DO NAVEGADOR QUE ABRIRÁ; 4 - VOLTE PARA O POINT BLANK, O WALLHACK JÁ ESTARÁ ATIVO (OBS: NÃO EXISTE A OPÇÃO PARA ATIVAR/DESATIVAR). WALLHACK PREMIUM VITALÍCIO APENAS R$25,00 >> CLIQUE AQUI PARA COMPRAR! <<
    1 ponto
  34. Alguém consegue o login desse site [Hidden Content]
    1 ponto
  35. MEUS CANAIS DE VÍDEOS HC CURSOS E TUTORIAIS 🎬 ▶️ PLAYLIST DO MEU CANAL NO YOUTUBE 🎬 ▶️ VEICARECA GAMES 🎬 ▶️ PLAYLIST DO MEU CANAL NO YOUTUBE 🎬 ▶️ 🎮 Fala, galera! Sejam bem-vindos ao canal! Se você joga WYD (With Your Destiny) e está cansado daquele editor de painéis antigo, ultrapassado e cheio de limitações… ESSE VÍDEO É PARA VOCÊ! 🔥 📌 Eu estava desenvolvendo um projeto que seria VENDIDO, mas resolvi COMPARTILHAR DE GRAÇA com a comunidade. Porque todo mundo merece uma ferramenta digna, né? 🖌️ **O que esse editor tem de especial?** ✅ Interface gráfica MODERNA e atualizada ✅ Trabalha DIRETAMENTE nos painéis com a imagem (nada de ficar decorando códigos!) ✅ Muito mais rápido e intuitivo ✅ Compatível com os painéis do WYD ✅ Ideal para criar, editar e organizar seus painéis de forma profissional 💡 Chega de sofrer com ferramentas jurássicas! Aqui você vai ver na prática como esse editor transforma o trabalho com painéis. 👇 **DOWNLOAD:** 🔗 📁 CLIQUE AQUI PARA BAIXAR O EDITOR NA DESCRIÇÃO DO VÍDEO ⚠️ **Importante:** A ferramenta é totalmente gratuita, mas se quiser apoiar o canal, deixe aquele like e se inscreva! Isso ajuda demais a trazer mais conteúdos exclusivos. 💬 Dúvidas ou sugestões? Manda aí nos comentários! 🔔 Se inscreva no canal e ative o sininho para não perder nenhum conteúdo sobre WYD e ferramentas exclusivas! #WYD #WYDGlobal #EditorDePainéis #MMORPGRetrô #WYDBrasil #FerramentasWYD
    1 ponto
  36. Alguem consegue o login desse [Hidden Content]
    1 ponto
  37. ASSINATURAS ATUALIZADAS Patrocinadora: streamingsbarato.com [Hidden Content] [Hidden Content] [Hidden Content] [Hidden Content] Assinatura será atualizada todos os meses.
    1 ponto
  38. 1 ponto
  39. Funções AIMBOT (extremamente configurável) ESP (Configurável) Memoria (básico = RICO DE BAN) Etapas de instalação e configuração Leia ou tomará BAN Passo 1: Configurar as opções de inicialização do Steam 1. Abra o Steam e acesse sua Biblioteca. 2. Clique com o botão direito do mouse no jogo (BloodStrike) e selecione Propriedades. 3. Na guia Geral , encontre Opções de Inicialização 4. Copie e cole este comando exatamente como está: cmd /min /C "set __COMPAT_LAYER=RUNASINVOKER && start "" %command%" Isso força o jogo a ser executado sem privilégios de administrador, impedindo varreduras profundas de processos. Etapa 2: UMBRA - Instalação e Gerenciamento 1. Execute o arquivo UMBRA.exe (como administrador, se exigido pelo seu sistema). 2. Na janela do UMBRA, você será solicitado a selecionar o caminho do jogo. Navegue até o seguinte diretório e selecione a pasta ou o executável principal: C:\Program Files (x86)\Steam\steamapps\common\BLOODSTRIKE (Ajuste o caminho se você tiver o Steam instalado em uma unidade ou local diferente.) Funções adicionais: - Reparar: Se encontrar problemas, você pode executar o UMBRA novamente, selecionar o mesmo caminho e usar o botão Reparar para verificar a integridade dos arquivos de cheats. - Desinstalar: Se desejar remover completamente o cheat, execute o UMBRA, selecione o caminho e clique em Desinstalar . Isso removerá todos os arquivos relacionados de forma segura. Etapa 3: Iniciar e carregar 1. Inicie o jogo normalmente pelo Steam (as opções de inicialização já devem estar configuradas). 2. Aguarde 10 segundos após o início do jogo. 3. Entre no LOOBY (principal) 4. digite `load` no console do jogo (se visível) ou no prompt de comando 5. Aguarde até que todos os recursos sejam inicializados corretamente. DOWNLOAD [Hidden Content] SCAN AQUI
    1 ponto
  40. Fala pessoal blz? estou entrando de ferias da oficina e vou dar uma focada no meu emulador novamente, entao refiz o sistema de log padrao e vou disponibilizar aqui caso alguem tenha interesse em usar ou melhorar. Segue o link do Projeto: GitHub GuiCan na main tem uma implementação simples so para teste e poderem ver como funciona. ficou bem bacana pode ser expandida conforme a necessidade e aprimorada tem sistema de rotação de logs quando chega ao tamanha maximo do arquivo depois de X dias os arquivos sao zipados e se tiver configurado pode ser feito upload para algum servidor ftp se sua escolha para guardar backups apos X dias os logs antigos sao removidos. basicamente é isso.
    1 ponto
  41. cara, grátis até hoje não vi nenhum metodo, mas tem o site [Hidden Content] que tem algumas opções de acesso compartilhado com preço acessivel, vale a pena dar uma olhada. tmj
    1 ponto
  42. 1 ponto
  43. Pack com vídeos da Letícia Reed. Basta curtir o tópico para revelar o conteúdo. [hide][Hidden Content]]
    1 ponto
  44. Bom, já que postaram o conteudo incompleto e nem todos tem o client, source e release, estarei postando os arquivos completinhos pra vocês, façam bom uso e estudem bastante, pois nessa source possui bastante bugs! Tudo que fazemos volta para nós nessa vida. Release Source Client Scan Release Scan Source Scan Client
    1 ponto
  45. Contas Xbox | Algumas com Game Pass Ultimate [Hidden Content] SEJA UM VIP EXTREME Acesso à Área VIP com alguns conteúdos exclusivos: Canva PRO, PrimeVídeo e Engajamento Rede Social. VIP EXTREME Doador Comunidade Emblema Selo de Verificado nos Comentários Seu Username com Efeito Seu Username com a Cor Vermelha Um cargo TeamIcon Exclusiva VIP Extreme Animado Todos seus Comentários destacados com Borda Vermelha Direito de Trocar Nickname Gratuitamente apenas uma única vez Acesso à Área VIP com alguns conteúdos exclusivos: Canva PRO, PrimeVídeo e Engajamento Rede Social. Poder Moderativo: Visualizar Mensagens Ocultas/Desaprovadas pela Moderação ADQUIRA SEU VIP AGORA MESMO:
    1 ponto
  46. ATUALIZADO 29/09/2025: [Hidden Content] PATROCINADORA streamingsbarato.com Diversos Serviços streamings com 70% OFF
    1 ponto
  47. Apply for Beta Access: [Hidden Content] Discord: [Hidden Content]
    1 ponto
  48. [Hidden Content] Bom proveito.
    1 ponto
Esta tabela de classificação está definida para São Paulo/GMT-03:00
×
×
  • Criar Novo...

Informação Importante

Nós fazemos uso de cookies no seu dispositivo para ajudar a tornar este site melhor. Você pode ajustar suas configurações de cookies , caso contrário, vamos supor que você está bem para continuar.