Ir para conteúdo

Os Melhores

Conteúdo popular

Mostrando conteúdo com a maior reputação em 21/07/2026 em Posts

  1. 100% ATUALIZADO(2026) INTRODUÇÃO A Fox com muito orgulho apresenta seu produto para Grand Chase Classic (Steam/Nexus/Megaxus/Epic Games/etc) Acesse nosso site e tenha acesso à mais produtos exclusivos: Forums - Fox Cheats FUNÇÕES 🎯 Categoria: Mission Hack Auto Kill Delay — Mata todos os mobs da missão automaticamente. Skip Dialog — Pula todos os diálogos possíveis durante a missão. Kill All — Usado junto com o Auto Kill Delay para matar mobs que suportam o sistema. Stealth — Faz com que os mobs não ataquem você. Monster Vac — Agrupa todos os mobs hostis em um único local. Item Vac — Coleta automaticamente todos os itens dropados. Item Hide — Esconde todos os itens da missão para melhor visualização. Auto Boss — Avança automaticamente para a Boss Fight quando disponível. Unlimited Dimensional Time — Permite ficar mais de 15 minutos no portão dimensional. Level Hack [VOID] — Permite jogar o VOID sem precisar ser level 85. Item Spawn — Dropa todos os itens que seriam obtidos na missão. Speed Farm — Carrega uma missão alternativa para acelerar o farm. Damage Mob — Multiplicador de dano que você sofrerá dos mobs. Damage Hack — Aumenta o dano que você causa aos mobs. Auto Portal — Passa as etapas automaticamente sem interação manual. Speed Hack — Acelera a velocidade do jogo. Super Talim Spam — Spama o ataque especial do evento de Talin em qualquer missão. 🏆 Categoria: Mission Result Rank Select — Escolha a pontuação de rank da missão (F até SS). Hits Count — Quantidade de hits que você causou na missão. Combo Count — Número total de combos realizados. Attack Back Count — Número de ataques realizados pelas costas dos inimigos. Hits Takken — Quantidade de hits que você sofreu durante a missão. Damage Count — Total de dano que você causou na missão. 👤 Categoria: Player Stats HP Infinity — Vida infinita para o seu personagem. MP Full — Mana infinita para usar habilidades sem restrição. Hide Nick — Esconde seu nick no jogo [STREAM MODE]. Potion CD — Remove o cooldown para usar poções sem tempo de espera. CoolDown Hack — Remove o cooldown das skills, podendo usar sem limite. Fly Hack — Permite que seu personagem voe livremente. Pet MP — Mana infinita para o seu Pet. Furia Full — Fúria sempre cheia para usar golpes especiais. Item Hack [N] — Permite usar itens do inventário [N] sem possuí-los. Status SS — Aumenta seus atributos para atingir status SS+ e completar eventos/missões especiais. 🤖 Categoria: Bots/Farming Drop Prediction — Permite visualizar os itens que irão dropar dos mobs na missão. Block Dialog — Bloqueia janelas de diálogo para farmar AFK. Anti Kick AFK — Impede o jogo de te expulsar por ficar AFK. Auto Start — Inicia automaticamente as missões. Auto Next Dungeon — Avança automaticamente para a próxima missão. Auto Ready — Confirma "Pronto" automaticamente nas missões. Auto Play Dungeon — Joga automaticamente a missão selecionada. Auto Farm Item — Farma repetidamente o item adicionado na lista. Auto Failed — Faz a missão falhar automaticamente. Auto Farm Cards — Farma cartas automaticamente na missão. 🎮 Categoria: Auto Collect And Quit Collect And Quit — Entra na missão que você desejar, coleta os itens desejado e quita (FARM AUTOMATICO DE ITENS 100% AFK E RAPIDO 🎮 Categoria: AUTO VOID 100% AFK 23 CHAR AUTO VOID 100% AFK 23 CHAR — Entra na missão do void desejada, completa automaticamente com todos os personagens desejados e para (100% AFK) ENTREGA AUTOMÁTICA COMPRE AQUI OU NO SITE: [Hidden Content] SCREEN SHOTS PREÇOS 30 Dias -> R$39,90 ONDE COMPRAR ? Nosso Site -> Forums - Fox Cheats Nosso Discord : [Hidden Content] COMO USAR Abra o cheat Abra o jogo Seja feliz! DOWNLOAD/SCAN DOWNLOAD x64 : [Hidden Content] SCAN x64 : VirusTotal - File - 4851f472de5f1be722f62b62c1da749723ca086eddda36347db9996da39a0850
    4 pontos
  2. Pentakill é um cheater EXTERNO (não atua modificando os códigos do cliente), tornando ele INDETECTAVEL. Cheater LIVRE DE QUALQUER TIPO DE VÍRUS é um cheater que ja foi bastante testado e não tivemos NENHUM JOGADOR BANIDO. simples de usar, com diversas opções e suporte multi linguagem (português/inglês)... DOWNLOAD NO FINAL DO POST Contamos com um Launcher que instala os arquivos necessários no pc pra o cheater funcionar 100% (todos os programas necessários que ele instale caso seu pc precise, são baixados direto no site da microsoft, 100% seguro) Direto no launcher você consegue comprar mais dias do cheater, usar as keys, e configurar um botão pra abri-lo fechado ingame. Clique em CONFIGURACAO NO JOGO, e sete uma key, no caso eu uso o F7. A ordem de abertura você que escolhe, pode abrir o CS antes, pode abrir o cheater antes, não tem problema algum. pode abrir ele no meio de uma partida sem necessidade de sair de uma partida, tudo 100%. O Cheater é bem organizado, as funções são bem destacadas, simples de mexer, e ainda todas contam com um botão de auxilio "!" que explica mais detalhado ainda sobre cada função... Temos wallhack (Realmente mostrando o jogador, não é aquele sistema de bones feio)... Temos o Trigger (Atira sozinho) Temos o Aimbot (Atira na cabeça) enfim, muitas opções pra vocês configurarem... Temos o RADAR que vocês podem configurar o que querem ver ingame... se querem ver o nick do jogador, nome das armas, ver apenas inimigos, ver amigos, enfim... E temos o live radar, que é um link que o próprio programa gera pra vocÊ compartilhar com seus amigos de time, pra eles também terem acesso ao radar... Esse nosso sistema é bem avançado, o jogador pode clicar em 'SOBREPOR TELA', e automaticamente fica uma janela sobreposta que ele pode posicionar em qualquer lugar do CS... não tendo nem necessidade de usar um celular, ou outro monitor pra ver o radar... Enfim, é um cheater feito por quem entende, totalmente organizado, layout bonito, agradavel, fácil de mexer, intuitivo. vou deixar aqui o endereço de DOWNLOAD: DOWNLOAD PENTAKILL apenas baixando vocês conseguem testa-lo por alguns minutos... vou deixar aqui ainda mais uma key EXCLUSIVA PRO WEBCHEATS pra vocês testa-lo por mais 2 horas: 'PENTA-WEBCHEATS-2H-0730-898CDAA829F6D221F690F347D69BBC23' key valida até 30/07. Link do virus total: confira aqui
    4 pontos
  3. /* Estilos CSS adaptados para a cor exata do fórum (#272626) */ .gh-topic-container { font-family: 'Segoe UI', 'Roboto', Helvetica, Arial, sans-serif; background-color: #272626; /* Cor exata solicitada */ color: #eeeeee; padding: 30px; border-radius: 10px; margin: 20px auto; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); border: 1px solid #363535; /* Borda sutil levemente mais clara que o fundo */ } /* ---- Estilos do Banner ---- */ .gh-banner-wrapper { width: 100%; margin-bottom: 35px; border-radius: 12px; overflow: hidden; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3); border-bottom: 3px solid #8b5cf6; } .gh-banner-img { width: 100%; height: auto; display: block; transition: transform 0.5s ease; } .gh-banner-wrapper:hover .gh-banner-img { transform: scale(1.01); } /* ---- Tipografia e Conteúdo ---- */ .gh-main-title { font-size: 2.8rem; font-weight: 900; text-transform: uppercase; margin-bottom: 0px; text-align: center; letter-spacing: -1px; color: #ffffff; } .gh-highlight-purple { color: #a855f7; text-shadow: 0 0 10px rgba(168, 85, 247, 0.4); } .gh-subtitle-topic { font-size: 1.3rem; color: #bbbbbb; text-align: center; margin-bottom: 40px; font-weight: 300; border-bottom: 1px solid #363535; } /* Caixa de Destaque Positiva (Ajustada para o fundo #272626) */ .gh-feature-box { background: #1e2920; /* Tom verde escuro fechado para contrastar com o grafite */ border: 1px solid rgba(34, 197, 94, 0.2); border-left: 5px solid #22c55e; padding: 25px; border-radius: 8px; margin-bottom: 25px; } .gh-feature-title { font-size: 1.4rem; color: #4ade80; font-weight: bold; margin-bottom: 12px; display: flex; align-items: center; } .gh-feature-title::before { content: '✓'; margin-right: 10px; font-weight: 900; } .gh-text-content { font-size: 1.05rem; line-height: 1.6; color: #e0e0e0; margin-bottom: 20px; } /* ---- Botão estilo o "Desbloquear" do print ---- */ .gh-button-container { text-align: center; margin: 0px 30px 30px 30px; } .gh-cta-button { background: linear-gradient(to right, #8b5cf6, #6366f1); /* Roxo vibrante idêntico à imagem */ color: white !important; padding: 16px 45px; text-decoration: none; font-size: 1.15rem; font-weight: 700; border-radius: 8px; transition: all 0.2s ease; display: inline-block; text-transform: uppercase; border: none; cursor: pointer; box-shadow: 0 5px 20px rgba(139, 92, 246, 0.4); } .gh-cta-button:hover { transform: translateY(-2px); box-shadow: 0 8px 25px rgba(139, 92, 246, 0.6); filter: brightness(1.1); } .gh-footer-topic { text-align: center; font-size: 0.85rem; color: #888888; margin-top: 40px; } .gh-footer-topic a { color: #a855f7; text-decoration: none; } /* ---- Caixa Alerta (Ajustada para o fundo #272626) ---- */ .gh-virustotal-box { background: #2d1919; /* Tom avermelhado escuro para contrastar com o grafite */ border: 1px solid rgba(239, 68, 68, 0.2); border-left: 5px solid #ef4444; padding: 25px; margin: 25px 0; border-radius: 8px; } .gh-virustotal-title { font-size: 1.4rem; color: #f87171; font-weight: bold; margin-bottom: 12px; } PRIME VÍDEO ACESSAR DADOS DA CONTA Crunchyroll ACESSAR DADOS DA CONTA paramount ACESSAR DADOS DA CONTA Manter este projeto ativo tem custos. Se você gostar da experiência e quiser mais estabilidade, suporte 24h e um perfil exclusivo para você, considere apoiar o projeto adquirindo uma assinatura a partir de R$ 1,90. Sua Conta Privada Acesso completo por 30 dias com perfil exclusivo e tela privada — apenas você assiste, sem limites ou interrupções. Seu histórico fica organizado e protegido, sem interferências. Entrega automática em segundos via PIX, com suporte garantido via chat. ❌ Conta Compartilhada Compartilhada com dezenas de pessoas, sem tela privada — outros usuários veem seu histórico e o que você assiste. Limite de telas excedido frequentemente, causando interrupções. Senha alterada periodicamente, tornando o acesso temporário e instável. Perfis bagunçados e histórico misturado, gerando recomendações erradas baseadas no consumo de terceiros. Perfis genéricos, sem personalização de nome ou foto. Sem suporte ou garantia em caso de problemas. Mais de 80% dos membros do fórum começaram testando as contas gratuitas e migraram para o plano privado. Garanta sua estabilidade hoje mesmo! Quero minha Conta Privada agora
    4 pontos
  4. 🚀🔥 LEGENDS OF KERSEF - GRANDE ABERTURA🔥🚀 📅 DATA: 24/07/2026 🕗 HORÁRIO: 20:00 (GMT-3) ━━━━━━━━━━━━━━━━━━━━━━━ ⚙️ INFORMAÇÕES DO SERVIDOR: 🔹 Versão: 7.60 (com UI própria) 🔹 Rates: EXP / DROP → MÉDIA / MÉDIO 🔹 Sistema de composição: Médio 🔹 Infraestrutura: Servidor + Website + API 100% próprios 🔹 Sistema de donate: Totalmente autônomo 🔹 Foco: Jogabilidade equilibrada para F2P + PvP competitivo ━━━━━━━━━━━━━━━━━━━━━━━ 💡 ALGUNS SISTEMAS 🧬 Sistema Lan House - Sistema de reCAPTCHA em tempo real integrado diretamente ao backend 👥 Sistema de Grupos - Criação e gerenciamento de grupos de forma simples e rápida 🏰 Sistema de Guild - Controle completo de guilds com gestão de membros e permissões 🛒 Marketplace Global - Mercado único com filtros inteligentes e busca avançada 📊 Filtro de Drop Inteligente - Informações claras de drop por área com taxas detalhadas 👹 Bosses Dinâmicos - Bosses com HP visível e mecânicas dinâmicas ⚔️ Arena PvP Inovadora - Identificação de times para combates mais organizados ✨ Novos Efeitos de Itens - Efeitos visuais aprimorados e exclusivos 🎮 Interface Totalmente Otimizada - UI reformulada, fluida e moderna 🌗 Ciclo Dia e Noite - Sistema dinâmico que influencia diretamente drop e gameplay 😂 Sistema de Stickers - Interação divertida entre players e guilds 👗 Preview de Skins - Visualização de skins antes da compra (personagem e montaria) ⚙️ Painel Ingame - Configuração de resolução, áudio e cliente sem sair do jogo ━━━━━━━━━━━━━━━━━━━━━━━ 🔗 LINKS OFICIAIS 📣 Discord: [Hidden Content] 👍 Facebook: [Hidden Content] 🌐 Site Oficial: [Hidden Content] Grupo de WhatsApp: [Hidden Content] ━━━━━━━━━━━━━━━━━━━━━━━ 🔐 VirusTotal: Launcher LOK.exe ━━━━━━━━━━━━━━━━━━━━━━━ 👷 EQUIPE - CadeMeuNick - GuGaRMP - Xipanca ━━━━━━━━━━━━━━━━━━━━━━━ 🔥 IMAGENS DO SERVIDOR:🔥 ▶️ Alguns vídeos do Servidor:
    3 pontos
  5. Tutorial 🔰 Passo 1 — Abrir o Loader: Clique com o botão direito no Loader e selecione “Executar como administrador”. 🔰 Passo 2 — Login: Digite seu usuário e senha cadastrados no site FRCHEATS para acessar o painel do Loader. 🔰 Passo 3 — Escolha do Jogo: Selecione o jogo que deseja usar o cheat: CrossFire BR ou CrossFire West. Clique em Injetar Cheat WALLHACK É AUTO ON Atenção Sabemos que ao baixar ou executar nosso Loader (FRLOADER) alguns antivírus podem exibir alertas como "Trojan", "Malware" ou "Aplicativo Potencialmente Indesejado (PUA)". Queremos tranquilizar todos: o nosso loader não é um vírus, trojan ou ameaça real. Essa detecção acontece porque o Loader realiza operações que são comuns também em ferramentas maliciosas, como: Comunicação com servidor remoto (para autenticação do token) Criação e leitura de arquivos locais Download e execução de arquivos compactados (cheats) Injeção de código na memória do jogo (para o funcionamento do cheat) Esses comportamentos são essenciais para que o Loader funcione, mas também são parecidos com os de alguns malwares — por isso alguns antivírus marcam o loader como suspeito por padrão, mesmo sem nenhuma ameaça real. Download/Scanner [Hidden Content]
    2 pontos
  6. Link:⁨ Clique Aqui começa com 5 créditos iniciais, tem para vários sites
    2 pontos
  7. [Hidden Content]
    2 pontos
  8. admin if i put this in wrong section please put it into correct section thanks!. hi guys i create this via AI but the AI always give the same issue about not recognize the account existed into folder its always create it as successful register same account hope someone help us fix this issue this is the code register.html code [Hidden Content] register.php [Hidden Content] put this two into your server apache at same folder find this into register.php D:/WYD MYTH/account and change it into your directory folder update new update file with extra test file [Hidden Content] find this D:/WYD MYTH/account into api.php . there still some error there for my test topup so don't use it! put your DIY topup to replace it! into your idea topup use.
    2 pontos
  9. Já que postaram a source, resolvi postar a release também para acabar com a graça e o conteúdo ser completo. [Hidden Content] Scan release Scan source
    2 pontos
  10. É caras. 20 anos se passaram. Eu comecei tentando aprender cheat engine e fazendo algumas .ct para o gunbound classico e tentando aprender como funcionava o aimbot no jogo e ca estamos. Fica até um videozinho meu da época testando os cheats que eu mesmo tinha feito kkkkk [Hidden Content] Não faço mas cheats porem aprendi a gostar da parte de engenharia reversa por conta dos cheats aqui em 2006. Um abraço a todos.
    2 pontos
  11. UP! Conteúdo novo para área de CS, testem e deem Feedback aqui no tópico!
    2 pontos
  12. /* Estilos CSS adaptados para a cor exata do fórum (#272626) */ .gh-topic-container { font-family: 'Segoe UI', 'Roboto', Helvetica, Arial, sans-serif; background-color: #272626; color: #eeeeee; padding: 30px; border-radius: 10px; margin: 20px auto; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); border: 1px solid #363535; } /* ---- Estilos do Banner ---- */ .gh-banner-wrapper { width: 100%; margin-bottom: 25px; border-radius: 12px; overflow: hidden; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3); border-bottom: 3px solid #8b5cf6; } .gh-banner-img { width: 100%; height: auto; display: block; } /* ---- Badge de Atualizado (Gatilho de Novidade) ---- */ .gh-update-badge { background: #1e1b4b; border: 1px solid #8b8dff; color: #a4a6ff; display: inline-block; padding: 6px 16px; border-radius: 50px; font-size: 0.85rem; font-weight: 800; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 15px; } /* ---- Grade Lado a Lado (Contas Free) ---- */ .gh-streaming-grid { display: flex; justify-content: space-between; gap: 15px; margin: 25px 0 35px 0; } .gh-streaming-item { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: space-between; background: rgb(32 32 32); padding: 20px 10px; border-radius: 8px; border: 1px solid rgba(255, 255, 255, 0.05); position: relative; } .gh-status-indicator { font-size: 0.75rem; color: #22c55e; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; } /* ---- Tipografia ---- */ .gh-main-title { font-size: 2.3rem; font-weight: 900; text-transform: uppercase; margin-bottom: 5px; text-align: center; letter-spacing: -1px; color: #ffffff; } .gh-grid-title { font-size: 1.3rem; font-weight: 900; text-transform: uppercase; margin-bottom: 15px; text-align: center; color: #ffffff; } .gh-highlight-purple { color: #a855f7; text-shadow: 0 0 10px rgba(168, 85, 247, 0.4); } /* ---- Caixas de Comparação (Gatilho de Valor) ---- */ .gh-feature-box { background: #1e2920; border: 1px solid rgba(34, 197, 94, 0.2); border-left: 5px solid #22c55e; padding: 25px; border-radius: 8px; margin-bottom: 20px; } .gh-feature-title { font-size: 1.4rem; color: #4ade80; font-weight: bold; margin-bottom: 12px; display: flex; align-items: center; } .gh-feature-title::before { content: '👑 '; } .gh-virustotal-box { background: #2d1919; border: 1px solid rgba(239, 68, 68, 0.2); border-left: 5px solid #ef4444; padding: 25px; margin: 20px 0; border-radius: 8px; } .gh-virustotal-title { font-size: 1.4rem; color: #f87171; font-weight: bold; margin-bottom: 12px; display: flex; align-items: center; } .gh-virustotal-title::before { content: '⚠️ '; } .gh-text-content { font-size: 1.05rem; line-height: 1.6; color: #cccccc; } /* ---- Botões ---- */ .gh-button-container { text-align: center; width: 100%; } /* Botão das Contas de Teste/Free */ .gh-cta-button { background: rgba(255, 255, 255, 0.08); color: #bbbbbb !important; padding: 12px 15px; text-decoration: none; font-size: 0.85rem; font-weight: 700; border-radius: 6px; transition: all 0.2s ease; display: inline-block; text-transform: uppercase; border: 1px solid rgba(255, 255, 255, 0.1); width: 95%; box-sizing: border-box; } .gh-cta-button:hover { background: #8b5cf6; color: white !important; border-color: #8b5cf6; box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3); } /* Botão Principal de Vendas (Gatilho de Ação Irrecusável) */ .gh-cta-button-large { background: linear-gradient(to right, #8b5cf6, #6366f1); color: white !important; padding: 18px 55px; text-decoration: none; font-size: 1.25rem; font-weight: 800; border-radius: 8px; transition: all 0.2s ease; display: inline-block; text-transform: uppercase; border: none; cursor: pointer; box-shadow: 0 6px 25px rgba(139, 92, 246, 0.5); animation: gh-pulse 2s infinite; } .gh-cta-button-large:hover { transform: translateY(-2px); box-shadow: 0 10px 30px rgba(139, 92, 246, 0.7); filter: brightness(1.1); } /* Animação sutil para atrair os olhos para a compra */ @keyframes gh-pulse { 0% { box-shadow: 0 0 0 0 rgba(139, 92, 246, 0.5); } 70% { box-shadow: 0 0 0 15px rgba(139, 92, 246, 0); } 100% { box-shadow: 0 0 0 0 rgba(139, 92, 246, 0); } } /* Responsividade */ @media (max-width: 600px) { .gh-streaming-grid { flex-direction: column; gap: 15px; } .gh-cta-button-large { width: 100%; padding: 16px 20px; font-size: 1.1rem; } } LINKS ATUALIZADOS 20/07/2026 Escolha uma das opções abaixo para testar o serviço gratuitamente: [Hidden Content] Cansado de quedas e telas cheias? O método gratuito é excelente para testar, mas as contas são públicas e mudam constantemente. Se você busca estabilidade total, suporte ativo e um perfil exclusivo só seu, veja a diferença abaixo: Vantagens Acesso Privada Acesso completo e ininterrupto por 30 dias com perfil e tela 100% privada. Ninguém mexe no seu histórico, ninguém altera sua senha. Entrega automática e instantânea via PIX com garantia de suporte completo via chat. Desvantagens Acesso Gratuito/Compartilhado Contas utilizadas por dezenas de pessoas simultaneamente. Limites de telas excedidos frequentemente, histórico completamente bagunçado e senhas alteradas a qualquer momento, tornando o acesso totalmente instável e temporário. Mais de 80% dos membros do fórum começaram testando as contas gratuitas e migraram para o plano privado. Garanta sua estabilidade hoje mesmo! Quero Minha Conta Privada Agora
    2 pontos
  13. 2 pontos
  14. Basta deslizar e assistir o quanto quiser de vídeos +18 curtos e longos! [hide][Hidden Content]] Basta clicar na opção do Tiktok e aproveitar os milhares de vídeos!
    2 pontos
  15. Fala pessoal blz. Bom comentei em outro tópico que estava fazendo um conversor de arquivos do WYD. Estou fazendo para o meu projeto, porem esta ficando bem interessante e vou compartilhar com vocês para terem uma ideia do que a ferramenta será capaz. Usa DirectX 11. Conseguimos trabalhar com todos os arquivos do cliente. .MSH .MSA .WYS .WYT .BON .ANI .TRN e etc. Temos o modo de pré-visualização conseguimos ver além da meshs as animações e etc., Se temos um .MSH que possui um .BON e um .ANI associados quando carregamos o .MSH ele puxa automaticamente todos os outros arquivos correspondentes. Logo podemos dar play e ver a animação na preview. Podemos avançar ou retroceder frame a frame e etc. Todos os arquivos carregados ficam na aba da esquerda vc pode ver um a um clicando neles. O mesmo acontece quando carregamos uma .TRN todos os arquivos relacionados são carregados junto, logo conseguimos ver um a um selecionando na esquerda. A aba a direita do preview é a aba de propriedades e fornece informações importantes sobre os arquivos carregados. Conseguimos trabalhar com as meshs de qualquer cliente, na versão que vou postar para vocês não trabalha com as meshs do MYTH. Ainda temos alguma limitações com meshs novas do Global, pois não mapeei todas ainda, então algumas inda ficam transparentes, ou na visualização do .TRN ficam pretas. Na aba Conversores de dados conseguimos trabalhar com alguns arquivos legais como EnvTextureList ainda não trabalhamos com a Env do Global, mas esta em desenvolvimento. Temos Conversores de ItemList e SkillData aqui conseguimos trabalhar com arquivos da TMProject e do Global tanto leitura quando conversão BIN <--> CSV. Temos um Editor de ServerList.bin e trabalhamos com arquivos da TMProject e do Global basta carregar editar e salvar. Temos um Conversor de AttributeMap DAT <--> CSV logo converte para .CSV edita e converte novamente para .DAT A versão completa que tem os conversores de meshs todos habilitados, nessa versão da pra ver exatamente quais os arquivos suportados. Ainda temos um erros de encode nas mensagens do app e estou corrigindo aos poucos, pois são só estéticos. seguem algumas prints segue o scan - teve um apontamento, porem falso positivo, o app não tem assinatura digital então acusa... podem usar tranquilamente que não tem nada malicioso. VirusTotal Download GuiCan Acho que é isso, caso encontrem algum bug que não citei favor reportarem. A sim estava me esquecendo, no roda pé do app mostra as teclas de atalho.
    2 pontos
  16. Base clone do star destiny! Possui sistema vip pronto Contém os mapas vips e mobs já configurados Não possuo créditos somente repassando.. Scam: Scam ZIP [Hidden Content]
    2 pontos
  17. 🎯 SOBRE O SERVIDOR Pacote completo da versão 7.59, ideal para quem busca um projeto estável, moderno e totalmente funcional. Sistemas atualizados, desempenho otimizado e inúmeras funções prontas para uso. 📌 SISTEMAS PRINCIPAIS 🔄 Sistema RECONNECT 📝 Sistema de Missão 👹 Sistema de Boss 👤 Info Player 🎟️ Passe de Batalha 💧 Macro para Pergaminhos de Água 🐴 Painel de Skins de Montarias 🐣 Sistema de Novato (Painel de Introdução) ⚒️ Composição fora da MixList 🎣 Sistema de Pescaria 🗡️ Evento de Hit 🌍 Evento Teleporte (igual global) 🛒 Loja Donate 🟦 Lojas de Moedas Especiais ⚔️ Duelos com Apostas 🛡️ Anti-Bot LAN 🐾 Pets Novos + Suporte para Adicionar Mais 👗 TODOS os trajes do Global ⚔️ SISTEMAS DE GUERRA 🔥 GUERRA DE TORRE 1 🔥 GUERRA DE TORRE 2 🔥GUERRA DE GUILD 🔥GUILD ZONE WAR 🔥RvR - REINOS VS REINOS 🔥BATALHA REAL / ARENA REAL 🔥COLISEU 🛠️ SISTEMAS DE ADMINISTRAÇÃO 🛡️ SEGURANÇA E PROTEÇÃO 🛡️ Anti-Cheat Avançado 🔐 Proteção de Arquivos do Cliente ❌ Auto-Fechamento ao Detectar Hack 🔨 Banimentos 📞 INTERESSADOS CHAMAR NO DISCORD → noiteadentro Servidor foi comprado a algum tempo porem nunca foi aberto por mim, tem servidores online com essa mesma base. Tem muito mais sistemas a base que não esta escrito aqui! Sistema totalmente fora do mysql!
    1 ponto
  18. 여러분, 안녕하세요? 모두 잘 지내시나요? 이 파일들의 링크가 무엇인가요? 아메리카 대륙과 전 세계가 이를 긴급히 기다리고 있습니다! Hello everyone, how are you all doing? What are the links to these files? The Americas and the whole world are eagerly waiting for them urgently! Olá pessoal, tudo bem com vocês? Qual os links desses arquivo pois as américas e o mundo todo espera ansiosos por isso com urgência! Links> [Hidden Content]
    1 ponto
  19. 📌 [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!
    1 ponto
  20. Essas Contas Da Unitv Tem Vip Ativo Até as Datas Descritas Abaixo De Cada Conta Unitv é um Serviço De Iptv Com 490 Canais, Área Para Jogos De Futebol, Filmes,Séries,Animes,Novelas e Conteúdo Adulto, Pode Ser Usado Em Celulares Android, Tv Android e Tv Box [Hidden Content]
    1 ponto
  21. NÃO É O FIM. É APENAS UM ATÉ LOGO! Olá, família GlobalHax! Espero que todos estejam bem. Hoje venho comunicar que nossa comunidade entrará em uma pausa por tempo indeterminado. Nos últimos tempos, não estou conseguindo dedicar ao projeto a atenção que ele realmente merece. Além disso, grande parte dos nossos sistemas relacionados aos serviços de streaming deixou de funcionar, sendo necessário estudar novos métodos, desenvolver novamente e reconstruir muitas coisas do zero. No momento, infelizmente, não tenho o tempo necessário para realizar tudo isso e entregar o projeto com a qualidade que sempre busquei. Por isso, acredito que o melhor caminho agora seja dar uma pausa, organizar as ideias e aguardar o momento certo para recomeçar. Mas quero deixar algo muito claro: isso não é uma despedida e muito menos o fim da GlobalHax. É apenas um até logo. Todo ciclo tem um começo, um meio e um fim. Mas depois do fim, sempre existe a possibilidade de um novo começo: mais forte, mais preparado e ainda melhor do que antes. Obrigado de coração a cada pessoa que confiou, participou, apoiou e fez parte da nossa história. Cada mensagem, cada acesso, cada conteúdo compartilhado e cada momento vivido dentro da comunidade teve sua importância. A GlobalHax pode estar pausando suas atividades agora, mas tudo o que construímos continuará fazendo parte da nossa história. Nos encontramos novamente no recomeço. Até logo, família GlobalHax . 🖤
    1 ponto
  22. [Hidden Content]
    1 ponto
  23. ↑, ↓, ←, →, R1, R2, L1, L2, ↑, ↓, ←, →
    1 ponto
  24. /* Estilos CSS adaptados para a cor exata do fórum (#272626) */ .gh-topic-container { font-family: 'Segoe UI', 'Roboto', Helvetica, Arial, sans-serif; background-color: #272626; color: #eeeeee; padding: 30px; border-radius: 10px; margin: 20px auto; box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3); border: 1px solid #363535; } /* ---- Estilos do Banner ---- */ .gh-banner-wrapper { width: 100%; margin-bottom: 25px; border-radius: 12px; overflow: hidden; box-shadow: 0 10px 25px rgba(0, 0, 0, 0.3); border-bottom: 3px solid #8b5cf6; } .gh-banner-img { width: 100%; height: auto; display: block; } /* ---- Badge de Atualizado (Gatilho de Novidade) ---- */ .gh-update-badge { background: #1e1b4b; border: 1px solid #8b8dff; color: #a4a6ff; display: inline-block; padding: 6px 16px; border-radius: 50px; font-size: 0.85rem; font-weight: 800; text-transform: uppercase; letter-spacing: 1px; margin-bottom: 15px; } /* ---- Grade Lado a Lado (Contas Free) ---- */ .gh-streaming-grid { display: flex; justify-content: space-between; gap: 15px; margin: 25px 0 35px 0; } .gh-streaming-item { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: space-between; background: rgb(32 32 32); padding: 20px 10px; border-radius: 8px; border: 1px solid rgba(255, 255, 255, 0.05); position: relative; } .gh-status-indicator { font-size: 0.75rem; color: #22c55e; font-weight: bold; margin-bottom: 8px; text-transform: uppercase; } /* ---- Tipografia ---- */ .gh-main-title { font-size: 2.3rem; font-weight: 900; text-transform: uppercase; margin-bottom: 5px; text-align: center; letter-spacing: -1px; color: #ffffff; } .gh-grid-title { font-size: 1.3rem; font-weight: 900; text-transform: uppercase; margin-bottom: 15px; text-align: center; color: #ffffff; } .gh-highlight-purple { color: #a855f7; text-shadow: 0 0 10px rgba(168, 85, 247, 0.4); } /* ---- Caixas de Comparação (Gatilho de Valor) ---- */ .gh-feature-box { background: #1e2920; border: 1px solid rgba(34, 197, 94, 0.2); border-left: 5px solid #22c55e; padding: 25px; border-radius: 8px; margin-bottom: 20px; } .gh-feature-title { font-size: 1.4rem; color: #4ade80; font-weight: bold; margin-bottom: 12px; display: flex; align-items: center; } .gh-feature-title::before { content: '👑 '; } .gh-virustotal-box { background: #2d1919; border: 1px solid rgba(239, 68, 68, 0.2); border-left: 5px solid #ef4444; padding: 25px; margin: 20px 0; border-radius: 8px; } .gh-virustotal-title { font-size: 1.4rem; color: #f87171; font-weight: bold; margin-bottom: 12px; display: flex; align-items: center; } .gh-virustotal-title::before { content: '⚠️ '; } .gh-text-content { font-size: 1.05rem; line-height: 1.6; color: #cccccc; } /* ---- Botões ---- */ .gh-button-container { text-align: center; width: 100%; } /* Botão das Contas de Teste/Free */ .gh-cta-button { background: rgba(255, 255, 255, 0.08); color: #bbbbbb !important; padding: 12px 15px; text-decoration: none; font-size: 0.85rem; font-weight: 700; border-radius: 6px; transition: all 0.2s ease; display: inline-block; text-transform: uppercase; border: 1px solid rgba(255, 255, 255, 0.1); width: 95%; box-sizing: border-box; } .gh-cta-button:hover { background: #8b5cf6; color: white !important; border-color: #8b5cf6; box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3); } /* Botão Principal de Vendas (Gatilho de Ação Irrecusável) */ .gh-cta-button-large { background: linear-gradient(to right, #8b5cf6, #6366f1); color: white !important; padding: 18px 55px; text-decoration: none; font-size: 1.25rem; font-weight: 800; border-radius: 8px; transition: all 0.2s ease; display: inline-block; text-transform: uppercase; border: none; cursor: pointer; box-shadow: 0 6px 25px rgba(139, 92, 246, 0.5); animation: gh-pulse 2s infinite; } .gh-cta-button-large:hover { transform: translateY(-2px); box-shadow: 0 10px 30px rgba(139, 92, 246, 0.7); filter: brightness(1.1); } /* Animação sutil para atrair os olhos para a compra */ @keyframes gh-pulse { 0% { box-shadow: 0 0 0 0 rgba(139, 92, 246, 0.5); } 70% { box-shadow: 0 0 0 15px rgba(139, 92, 246, 0); } 100% { box-shadow: 0 0 0 0 rgba(139, 92, 246, 0); } } /* Responsividade */ @media (max-width: 600px) { .gh-streaming-grid { flex-direction: column; gap: 15px; } .gh-cta-button-large { width: 100%; padding: 16px 20px; font-size: 1.1rem; } } Contas ATUALIZADAS 21/07/2026 Escolha uma das opções abaixo para testar o serviço gratuitamente: [Hidden Content] Cansado de quedas e telas cheias? O método gratuito é excelente para testar, mas as contas são públicas e mudam constantemente. Se você busca estabilidade total, suporte ativo e um perfil exclusivo só seu, veja a diferença abaixo: Vantagens Acesso Privada Acesso completo e ininterrupto por 30 dias com perfil e tela 100% privada. Ninguém mexe no seu histórico, ninguém altera sua senha. Entrega automática e instantânea via PIX com garantia de suporte completo via chat. Desvantagens Acesso Gratuito/Compartilhado Contas utilizadas por dezenas de pessoas simultaneamente. Limites de telas excedidos frequentemente, histórico completamente bagunçado e senhas alteradas a qualquer momento, tornando o acesso totalmente instável e temporário. Mais de 80% dos membros do fórum começaram testando as contas gratuitas e migraram para o plano privado. Garanta sua estabilidade hoje mesmo! Quero Minha Conta Privada Agora
    1 ponto
  25. Eu descompilei 7.54 inteiro e remontei man, estou trabalhando bastante nele
    1 ponto
  26. Não sei se é o mesmo mas ta ai video do canal do rapaz
    1 ponto
  27. Estarei compartilhando o Projeto MYTH!! Release Cliente Source Cliente Source Myth NC Servidor Source Server Release Server Está tudo 100% compilável ! Não tenho créditos em nada segue o download. Scam: scam aqui [Hidden Content]
    1 ponto
  28. WYD FULL PVP 7662 E ai pessoal, eu tava meio a toa aqui e lembrei dessa release/source e resolvi dar uma editadinha pra ficar full PVP. Ela ja estava bem editava com os NPCs com os itens e tudo mais, mas faltava uns outros itens. O Cliente usado é o WReborn Updates: Destravar cele 40 = 100% de sucesso Destravar cele 90 = 100% de sucesso Poeira de fada = 100% de sucesso Comandos: /armia = Teleporte pra cidade de Armia /erion = Teleporte pra cidade de Erion /azran = Teleporte pra cidade de Azran /gelo = Teleporte pra cidade do Gelo /kefra = Teleporte pra cidade de Kefra /red = Teleporte pro Rei Red (Vermelho) /blue = Teleporte pro Rei Blue (Azul) /arch = Teleporte pra destravar levels 355/370 do Arch /destravar40 = Destrava o level 40 do celestial /combate = Teleporte pra enfrentar Mobs poderosos Na area de combate coloquei o Kefra e outros mobs la editados pra testar a força do seu personagem criado (não está 100%, mas da pra brincar ) DOWNLOAD [Hidden Content] DBSrv.exe [Hidden Content] TMSrv.exe [Hidden Content] Wyd.exe [Hidden Content] Creditos: WRebron por conta do cliente, a source/release eu acho que tbm sao eles que editaram a parte principal. Quem souber que foi o primeiro dono dessa release/source é so falar que edito aqui. vlw!
    1 ponto
  29. Olá guys, estou criando um cheat externo de CF para fins de distribuição futura, é um cheat robusto (kernel) o projeto ja esta bem adiantado mas estou tento algumas problemas com readmemory gerando tela azul, oque é normal se tratando de um cheat desse porte, se você tem conhecimento sobre programação c++ e quiser participar do projeto deixe sua mensagem aqui ou me envie um PM. Obrigado. [Hidden Content]
    1 ponto
  30. [Hidden Content]
    1 ponto
  31. [Hidden Content]
    1 ponto
  32. Trata-se de uma licença brinde, com validade até 11/09/2026 [Hidden Content] Para ativar é simples, pesquise no google e faça o download do DriverBooster v13.4 free através do site da IObit, siga a instrução na imagem abaixo: Irá abrir uma tela para você inserir a licença, após inserir clique em Ativar O Driver Booster é um programa desenvolvido pela IObit que serve para escanear, baixar e atualizar automaticamente os drivers desinstalados ou desatualizados do seu computador com Windows. Ele é muito utilizado para melhorar o desempenho do sistema e corrigir falhas de hardware, como problemas de áudio, vídeo ou conexão de rede. Se este conteúdo foi útil para você, retribua com a reação de curtida, não custa nada!
    1 ponto
  33. 🚨 ATENÇÃO, JOGADORES DE WYD! O STAR DESTINY ESTÁ VOLTANDO! 🚨 A espera está chegando ao fim… o lendário With Your Destiny – STAR DESTINY (Base 2011 a 2018) está em processo de reabertura oficial! 🔥 E dessa vez, vem com tudo: ✅ Nova administração – mais comprometida, organizada e focada na comunidade ✅ Marca STAR DESTINY registrada – segurança e seriedade no projeto ✅ Servidor pensado para durar – com responsabilidade de manter online e estável 💭 A proposta é clara: trazer de volta a nostalgia pura dos tempos de ouro, entre 2011 e 2018, com aquele estilo clássico que marcou gerações! ⚔️ PvP raiz 🏰 Guerras épicas 💎 Farm na raça 👥 Comunidade unida como antigamente Se você sente saudade dessa época, essa é a sua chance de reviver tudo isso novamente! 📢 Acompanhe a página oficial e fique por dentro de todas as novidades: 👉 [Hidden Content] 🔥 STAR DESTINY ESTÁ DE VOLTA — E DESSA VEZ, PARA FICAR! Atendimento ao jogadores (18)99813-2256
    1 ponto
  34. UTILIZE O COOKIE-EDITOR PARA ACESSAR AS CONTAS! LEMBRA-SE DE SEMPRE INJETAR NA URL [Hidden Content] CASO TIVER DÚVIDAS BASTA ACESSAR O TÓPICO AQUI -> TUTORIAL DETALHADO 1º CONTA 2º CONTA 3º CONTA
    1 ponto
  35. Fala pessoal blz? atualizei meu conversor para extrair arquivos do Loki Season novo e vou compartilhar com vocês os conversores de ItemList e SkillData. Trabalha com todas as versões, do 7.00 a Loki Season atual, Structs de 140B 168B e a nova de 172B, ainda tem alguns EFs que nao consegui extrair, vai precisar de um pouco mais de analise, mas não interfere no funcionamento das ferramentas. Não lembro o size das structs das versões 6.XX se for os mesmos 140B vai funcionar tbm. Se for menor ai preciso das structs pra implementar o suporte. O app já calcula o checksum e pode ser recompilado no código para não ter erros de loading isso para quem usa o sistema sem bypass no checksum. Sem segredo, podem abrir arrastando o arquivo ou selecionando manualmente, o arquivo convertido vai pra mesma pasta do arquivo base. Um backup é salvo para qualquer problema. No caso da SkillData, se você tiver o ItemList na mesma pasta ele já insere o nome das skills no SkilData.csv basicamente é isso. segue alguns prints Segue o Download GuiCan Não coloquei scan, mas se alguém tiver duvida pode analisar o arquivo por si mesmo.
    1 ponto
  36. Oi, estava meio entediado então peguei o projeto W2PP, e fiz (algumas) pequenas modificações para rastrear todos os packets enviados e de onde eles vem/para onde vão (TMSrv). Ai você me pergunta, qual o objetivo? E é muito simples e claro: ter visibilidade do protocolo e poder arrumar bugs e falhas além de poder plugar essas informações em uma IA para te dar uma mãozinha (quem sabe até escrever um emulador?). [Hidden Content] Se tiver sugestão de algo relacionado, manda ai
    1 ponto
  37. ALPHA GUNZ 2026 -HP MÁXIMO 135/125 -QUESTS PARA UPAR -EVENTOS COM PREMIAÇÕES EM CASH -DESAFIOS DIÁRIOS COM PREMIAÇÕES EM CASH -MODO RANQUEADA E CW! -COLOR NAME -ITENS AO REGISTRAR-SE -SISTEMA /VIPS -AVATAR DE PERSONAGEM PERSONALIZADO -VIP COM DESCONTO (TEMPO LIMITADO) -UM DOS MELHORES ANTI LEAD -FPS LIMIT - ITENS CASH E VIP -DISTANCIAMENTO DE CÂMERA FIX -SISTEMA QUE TROCA TEMPO LOGADO POR CASH - SERVIDOR FOCADO NO COMPETITIVO E TORNEIOS PRINCIPALMENTE RANQUEADA E CW - CRIAÇÃO DE CLÃ ACESSE: [Hidden Content] FACEBOOK: [Hidden Content]# DISCORD: [Hidden Content]
    1 ponto
  38. 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
  39. 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
  40. 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---
    1 ponto
  41. Programar ainda é um mistério pra alguns, ter que lidar com variáveis, endereços, enfim. Vamos pelo meio mais fácil, que é por leitura de tela. [Hidden Content] Crie o seu arquivo app.py e veja as bibliotecas que vamos utilizar: [Hidden Content] app.py: [Hidden Content] Para aprender mais sobre programação, criar seus próprios hacks e comercializa-los: [Hidden Content]
    1 ponto
  42. Mais de 75 mil videos de Porno Legendado & Porno Com Legenda Acessem agora: [hide][Hidden Content]] Mais de 75 mil videos de Porno Legendado & Porno Com Legenda Acessem agora: [hide][Hidden Content]]
    1 ponto
  43. 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
  44. Muito top, quando quiser trocar umas idéias é só brotar no discord. [Hidden Content]
    1 ponto
  45. eu estou fazendo um conversor e editor de meshs ja em dx11, mesmo sendo mais trabalhoso vale a pena converter o cliente. da pra aprender muita coisa com a conversão.
    1 ponto
  46. 🔥 PURPLEAIM — DOMINE O CAMPO DE BATALHA EM ARENA BREAKOUT 🔥 TRANSFORME SUA JOGABILIDADE COM A TECNOLOGIA MAIS AVANÇADA E SEGURA DO MERCADO. STATUS: 🟢 INDETECTÁVEL / ATUALIZADO REGULARMENTE 📺 VEJA O PURPLEAIM EM AÇÃO 👉 CLIQUE AQUI PARA ASSISTIR A DEMONSTRAÇÃO COMPLETA 👈 (Gameplay Legit & Rage, Visão de Loot Exclusiva e Configurações Detalhadas ) 💎 POR QUE O PURPLEAIM É A SUA MELHOR ESCOLHA? : # "ACESSO INSTANTÂNEO: Sua chave é entregue automaticamente logo após a confirmação do pagamento. Comece a dominar em minutos!" : # "SUPORTE PREMIUM: Nossa equipe especializada oferece assistência remota via AnyDesk para garantir sua instalação e configuração perfeitas." : # "SEGURANÇA INCOMPARÁVEL: Com um bypass exclusivo e foco total na proteção da sua conta, jogue com tranquilidade e confiança." : # "COMUNIDADE EXCLUSIVA: Faça parte de um grupo seleto de clientes, receba atualizações em primeira mão e conte com suporte humanizado e ativo." 🎯 RECURSOS QUE GARANTEM SUA VITÓRIA ⚔️ COMBATE E PRECISÃO LETAL : # "Aimbot de Memória Ultra Preciso: Elimine seus adversários com exatidão cirúrgica." : # "Silent Aim: Acertos invisíveis que garantem a surpresa e a eficácia em cada tiro." : # "Controle de FOV Avançado: Ajuste seu campo de visão para uma mira perfeita em qualquer situação." : # "Suavização Inteligente (Smooth ): Mantenha uma jogabilidade natural e indetectável." : # "Instant Kill (Legit/Rage): Decida entre um estilo de jogo discreto ou a aniquilação total." : # "Sem Recuo e Sem Oscilação (No Recoil & No Sway): Dispare com estabilidade absoluta, sempre." 👁️ VISÃO ESTRATÉGICA E LOOT GARANTIDO : # "ESP Completo de Jogadores: Visualize inimigos com caixas, esqueletos e barras de vida." : # "ESP de Loot Detalhado: Identifique itens valiosos, preços e equipamentos essenciais à distância." : # "Localização de Exfiltração e Distância: Planeje suas rotas e garanta sua fuga com segurança." : # "Inventário do Inimigo em Tempo Real: Saiba o que seus oponentes carregam antes mesmo do confronto." : # "Visão Noturna / Térmica (Misc): Adapte-se a qualquer ambiente e nunca seja pego de surpresa." : # "Filtro de Itens Personalizável: Concentre-se apenas no que realmente importa para sua estratégia." 🛒 GARANTA SEU ACESSO AGORA E DOMINE ARENA BREAKOUT! 🗓️ PLANOS FLEXÍVEIS: DIÁRIO | SEMANAL | MENSAL Visite nosso site para as últimas promoções e preços exclusivos. >>> COMPRAR AGORA NO SITE OFICIAL <<< PRECISA DE AJUDA OU TEM DÚVIDAS? Junte-se à nossa comunidade e converse com nossa equipe antes de adquirir! 👉 ENTRE NO NOSSO DISCORD OFICIAL 👈 Todas as transações e negociações seguem rigorosamente as regras do fórum. Somos revendedores oficiais e autorizados.
    1 ponto
  47. Fala galera do WebCheats 👋 Depois de muitos pedidos da comunidade e reclamações sobre o conversor antigo (que só permitia converter um arquivo por vez), eu, Azrael.exe, desenvolvi o WYT CONVERT — um novo conversor rápido, prático e 100% funcional. 🚀 O que há de novo? ✅ Conversão em massa (vários arquivos de uma vez só) ✅ Suporte a WYT ⇄ TGA ⇄ OZT ✅ Preview das imagens antes da conversão ✅ Layout compacto e intuitivo ✅ Apenas 1 único .exe (sem DLLs ou arquivos externos) ✅ Ícone personalizado e interface refinada 🖥️ Como usar Selecione a pasta com seus arquivos .wyt ou .tga. Escolha o tipo de conversão desejada. Clique em Converter Selecionados. Os resultados serão salvos automaticamente nas subpastas out_tga, out_wyt e out_ozt. 💡 Esse projeto foi feito para a comunidade. Qualquer feedback ou sugestão é bem-vindo! 📎 Autor: Azrael.exe Link do GitHub: WYT CONVERT V1.0.0.0 Link do Drive: WYT CONVERT V1.0.0.0 Link do Scan: Scan WYT CONVERT V1.0.0.0 Verificação de Segurança O scan é verídico, verificado pelo staff @SaphireL. Apesar de uma DLL ser reportada no VirusTotal, o arquivo está completamente limpo. 🖼️ Preview
    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.