Os Melhores
Conteúdo popular
Mostrando conteúdo com a maior reputação em 11/05/2026 in todas as áreas
-
constexpr auto MSG_PremiumFireWork_Opcode = 0x3CA; struct MSG_PremiumFireWork { PacketHeader Header; int conn; int Motion; char Parm[16]; }; if (Volatile == 19) { MSG_UseItem3* pUseItem = reinterpret_cast<MSG_UseItem3*>(pMsg); MSG_PremiumFireWork stFireWork{}; memset(&stFireWork, 0, sizeof(MSG_PremiumFireWork)); stFireWork.Header.Size = sizeof(MSG_PremiumFireWork); stFireWork.Header.ID = conn; stFireWork.Header.Type = MSG_PremiumFireWork_Opcode; stFireWork.conn = conn; stFireWork.Motion = 100; memcpy(stFireWork.Parm, pUseItem->Parm, sizeof(stFireWork.Parm)); GridMulticast(pMob[conn].TargetX, pMob[conn].TargetY, (MSG_STANDARD*)&stFireWork, 0); if (Amount > 1) BASE_SetItemAmount(Item, Amount - 1); else memset(Item, 0, sizeof(STRUCT_ITEM)); return; }7 pontos
-
6 pontos
-
🚀 Confira as funções incríveis completamente gratuitas disponíveis no nosso hack! Com foco em performance, praticidade e diversão, você vai turbinar sua experiência como nunca antes! 🔥 🔹 Zerar Tempo de Recarga – Use suas skills o quanto quiser, sem esperar! 🔹 HP Cheio – Mantenha sua vida sempre no máximo. 🔹 MP Cheio – Nunca mais fique sem mana! 🔹 Bloquear Popup – Diga adeus àquelas telas chatas que aparecem no jogo. 🔹 Imã de Itens – Os itens virão direto até você! 🔹 Anti-AFK – Permaneça na sala mesmo se precisar se ausentar por um tempo. 🔹 Pula Diálogos – Corte direto para a ação, sem enrolação . 🔹 Rank SS – Substitui a pontuação da tela para garantir classificação SS. 🔹 Modo Streamer – Oculta textos e detalhes visuais do jogo. 🔹Imã de Monstros – Atrai todos os monstros até o jogador. 🆓 Atenção! Algumas das funcionalidades listadas estão disponíveis gratuitamente por tempo limitado. No futuro, as funções free poderão ser reduzidas, conforme o desenvolvimento do projeto. 📸 Screenshots: 🔧 Como usar: É simples e rápido começar a usar: 1- Baixe o cliente. 2- Abra o programa e clique em “Injetar”. 3- Inicie o Grand Chase normalmente. 4- Pressione [Insert] para exibir ou ocultar o menu. 5- Aproveite todos os recursos e domine o jogo! ⚠️ Aviso: Ao executar o cliente, sempre clique com o botão direito e selecione “Executar como administrador” para evitar problemas de permissão. Certifique-se também de que o Grand Chase não esteja em modo tela cheia, pois isso pode causar falhas durante a injeção. Se você utiliza Steam: Feche completamente a execução da steam e após isso execute a mesma como administrador, também de preferência a execução do Grandchase via atalho ao invés da execução direta na biblioteca da Steam. [Hidden Content] Erro ao injetar no GrandChase? Em alguns casos, é necessário desabilitar o Windows Defender, a proteção em tempo real e o antivírus instalado no sistema. Mesmo que nosso software não seja malicioso, os antivírus podem identificá-lo como uma ameaça falsamente (falso positivo), pois ele realiza operações avançadas de injeção na memória de outro processo — algo comum em cheats ou ferramentas legítimas de modificação de jogos. Isso faz com que algumas proteções bloqueiem o funcionamento correto do injetor ou até excluam arquivos essenciais automaticamente. Garantimos que o produto é seguro e limpo. Desativar temporariamente a proteção permite que a injeção ocorra corretamente. 🗓️ Hack Atualizado em: 17/06/20265 pontos
-
3 pontos
-
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); }3 pontos
-
3 pontos
-
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
-
2 pontos
-
2 pontos
-
Usei bastante esse bot lá em 2023, e como me solicitaram resolvi postar pra vocês usarem. Não vou me dar o trabalho de subir em algum repo, mas tá ai. Esse bot simula o cliente do wyd via web (sem ambiente 3d), pela web dá pra fazer várias coisas: - Logar em uma conta - Ligar macros - Deletar itens - Equipar Itens - Filtrar drop por ai vai. Sei que usa sveltekit(sem runas), .NET, ravendb e Docker in Docker para img do ovpn para usar VPN e burlar limite de IP (acho que é opcional sei lá). Não lembro pra qual servidor estava setado, se virem ai. Suponho que só de subir docker-compose funcione, desde que corrija a keytable e altere algum pacote ou outro pra versão correta do teu servidor. Essa base rodou muito tempo também pra inflar numero de jogador ativo em servidor, já que a movimentação dos bots acaba passando batido pelos players, e acabam achando que são players de verdade [Hidden Content]2 pontos
-
2 pontos
-
2 pontos
-
LINK ATUALIZADO 08/05/2026: [Hidden Content] PATROCINADORA streamingsbarato.com Diversos Serviços streamings com 70% OFF2 pontos
-
2 pontos
-
Fala guerreiros, aí vai um cheat free para o servidor Veteranos priston tale. Está com dúvida de como usar? veja o vídeo. [Hidden Content] [Hidden Content] Deseja ter acesso a mais funções e ser um deus no joguinho? na descrição do vídeo tem o meu contato. Você é dono de servidor e deseja mitigar os cheats no seu servidor? entre em contato, vou te apresentar um sistema de anticheat exclusivo.2 pontos
-
Não tem binários Windows exceto o wyd.exe Sugiro escanear com antivírus atualizado. Links para download: [Hidden Content] Link do Source do Cliente: [Hidden Content] Instalação WYD Linux mais simples e direta através do script bash install_wyd_linux.sh O script monta o ambiente sem forçar compilação, instala dependências e deixa o servidor pronto para configurar. Ele cria o mysql.txt para o servidor se conectar ao banco, com usuário, senha e nome do schema, e também atualiza o server.txt do cliente para apontar para o IP do servidor. No cliente, o server.txt define o endereço do servidor que o jogo vai usar. Na parte do servidor, o mysql.txt garante que DBSrv e TMSrv consigam acessar o MySQL com as credenciais certas. Decidi user um .txt no cliente para facilitar os testes. Bugs: Com certeza tem bastante, mas menos do que na versão original. As skills 9 e 10 estão implementadas (sinceramente nao testei todas ainda). Minha ideia é criar um gerenciamento via web, visto que a versão console (esta) não tem as mesmas informaçoes que a versão Windows. Toda a parte gráfica foi removida e roda direto pelo terminal. Tem um binário tmlinux (cliente). Pode ignorar. É só uma tentativa ousada de o cliente. O Cliver é 6000. Ao compilar no Windows ele cria o diretório que indica ser versão 7.69 Foi criado um arquivo ShimWin32 para tratar da compatibilidade e traduçao das chamadas WIn32 pra POSIX. A vantagem é que não preciso reescrever a lógica toda. O código continua igual, eu só traduzo a camada de API. Compile uma vez com o shim e pronto, roda em Linux mantendo tudo que funciona no Windows. Em resumo: setup feito sem precisar compilar agora; banco MySQL configurado automaticamente; mysql.txt criado para o WYD acessar o DB; server.txt do cliente ajustado para o IP certo. Assim, a configuração fica prática e você não precisa editar tudo na mão. Tem bugs comuns como inconsistência entre o ItemList.bin do cliente e o .csv do servidor. Estou corrigindo, mas não pretendo corrigir tudo porque tem muito item criado que acho desnecessário. O Cinto não equipa nessa source. Fiz a correçao na minha e libero quando tiver mais correçoes acumuladas. Tem script pra alterar o drop e xp por região. Acho que tá legal pra uma brincadeira mas não pra produção. Porém fiquem à vontade pra explorar e quem sabe compartilhar também. Tá bem suave, rodou de boa no meu celular Vivo X200 Pro no Gamehub e no Pocophone F1 rodando Fedora Mobility. Créditos: (Nomes encontrados no código) Se tiver mais alguém, basta avisar. Victor Klafke Charles TheHouse TRAE.AI GLM 5.1 Plus SexyCode BabyLove Outros2 pontos
-
ASSINATURAS ATUALIZADAS Patrocinadora: streamingsbarato.com [Hidden Content] [Hidden Content] [Hidden Content] [Hidden Content] Assinatura será atualizada todos os meses.2 pontos
-
/* 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 agora1 ponto
-
⚔️ 𝗦𝗼𝗯𝗿𝗲 𝗱𝗼 𝗦𝗲𝗿𝘃𝗶𝗱𝗼𝗿 🔸 Versão: Clássica 🔸 Experiência: Médio / Médio 🔸 Drop: Médio / Médio 🔸 Progressão dinâmica 🔸 Quests Mortais: Do Lv. 40 até o 351 🔸 Diversas mecânicas 🔥 𝗦𝗜𝗦𝗧𝗘𝗠𝗔𝗦 𝗘𝗫𝗖𝗟𝗨𝗦𝗜𝗩𝗢𝗦 O servidor foi construído para oferecer uma experiência diferenciada: 🔹 Codex 🔹 Mineração 🔹 Pescaria 🔹 Dungeon Guilda 🔹 Gemas Mágicas 🔹 Montarias Lendárias 🔹 Consumíveis Exclusivos 🔹 Arena para até 104 jogadores 🔹 Mercado Global 🔹 Painel Guilda 🔹 Loja de Guilda 🔹 Info do Jogador 🔹 World Bosses 🔹 LAN Reformulada 🔹 Guerra de Torres Reformulada 🔹 Guerra de Noatun Reformulada 🔹 Castelo de Loki 🔹 Sistema de Roleta 🔹 Passe de Batalha completo 🔹 VIP para qualidade de vida do jogador 🔹 Sistema de tradução em tempo real 🔹 Drop 100% refeito do zero 🏰 𝗖𝗢𝗠𝗨𝗡𝗜𝗗𝗔𝗗𝗘, 𝗚𝗨𝗜𝗟𝗗𝗔𝗦 𝗘 𝗟𝗢𝗡𝗚𝗔 𝗩𝗜𝗗𝗔 Poderíamos repetir o mesmo discurso de sempre... "Não somos um servidor de 3 meses" "Sem Pay2Win" "PvP balanceado" Mas você já cansou de ler isso. E a gente também. A diferença é simples: Aqui você não vai ouvir promessa, vai acontecer. Sem sistema quebrado Sem vantagem comprada Sem conteúdo que morre em semanas Aqui cada conquista é suada Cada guerra tem peso Cada jogador faz diferença Se você quer mais do mesmo, esse não é o seu servidor. Agora, se você quer um desafio de verdade... Bem vindo ao Mystic Destiny! Projetos & Oportunidades 🔸 Programa de Criadores de Conteúdo 🔸 Auxílio para Guildas 🔸 Vagas para Divulgadores Quer crescer junto com o servidor ? Aqui você tem espaço. 📷 𝗜𝗠𝗔𝗚𝗘𝗡𝗦 𝗗𝗢 𝗦𝗘𝗥𝗩𝗜𝗗𝗢𝗥 🔗 𝗘𝗡𝗧𝗥𝗘 𝗡𝗢𝗦 𝗖𝗔𝗡𝗔𝗜𝗦 𝗢𝗙𝗜𝗖𝗜𝗔𝗜𝗦 Site: [Hidden Content] Discord: [Hidden Content]1 ponto
-
🚨 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-22561 ponto
-
Server Mid-Hard Play-Win Server Classic Gameplay Hunt Based PT-BR and ENG CLIENT Opening 5/1/26 LINK REMOVIDO.1 ponto
-
⚔️WYD INFINITY ⚔️ 📅 Inaugurado dia: 01/05/2026 às 13h 📌 Informações Gerais Versão: 7.89 Dificuldade: Easy / Medium UP Rápido: Mortal/Arch UP Celestial: Easy até 120/UP 120 - 120+ Medium Contas por IP: (5) 🔥 "O Farm te prepara. O PVP te define." 📌 Sistemas Guerras de Guilds Arena Real Pesadelo celestial liberado Dominação de Bosses com espólios valiosos Droplist com filtro de drop Sistema de Honra Valioso e Diferenciado Sistema Guerra entre Reinos Player Info Ranking atualizado Sistema de Balanceamento PVP e PVE Baú de carga com 4 slots Resoluções Widescreen sem distorções Loja desvinculada: Progrida livremente Loja de Donate: Acesse de qualquer lugar Novidades de NPCs: recicladores e compositores Novos slots: colar, cinto, traje montaria Sistema Revigorante (proteção de montaria) Fada Dourada: agrupador de itens, filtro e macro de água Auto Grupo Anti-Hack · Anti-DDoS Servidor Estável 24/7 Entre outros... 🌐Redes Sociais 🌍 Site: [Hidden Content] 💬 Discord: [Hidden Content] 📸 Instagram: [Hidden Content] 📱 WhatsApp: [Hidden Content] 🌐Download: Download do Cliente : DOWNLOAD DO CLIENT Scan CLIENT Scan EXE Administrador por: G2K 📌 Imagens sobre o WYD INFINITY Campo iniciante de ARMIA: Sistemas: Painéis no servidor: NPC'S (Se compra em gold e itens)(Ambos são FARM) VALE ESCONDIDO (CONTÉM 3 ANDARES) CAPAS CELESTIAIS1 ponto
-
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
-
1 ponto
-
Olá galera, 🎮 Fatal Chase Cheats disponíveis: AutoKill – Mata automaticamente os mobs AutoBoss – Avança direto para o stage do boss ItemVac – Coleta os drops Automaticamente Serviços (sem precisar passar dados da conta): XP Hack → Sobe do nível 0 ao 85 em poucos minutos Complete Quest → Finaliza quests de matar monstros ou pegar chaves em segundos (sem precisar matar 1000+ monstros) [Hidden Content] [Hidden Content] 📌 Discord para suporte e mais informações: 0iiveira1 ponto
-
Fala rapaziada, beleza? Tenho visto muita gente tomando banimento por HWID no CrossFire e até no Valorant, então resolvi trazer um Spoofer funcional e gratuito pra vocês. 📌 O que é um Spoofer? Um spoofer é um programa que altera e mascara as informações do seu hardware (HWID, Disco, BIOS, GUID, etc.) para que os anti-cheats não consigam identificar sua máquina como “banida”. Ou seja, mesmo que você leve HWID ban, com o spoofer você consegue voltar a jogar sem precisar formatar ou trocar peças do PC. ⚙️ Funcionalidades do Spoofer ✔️ Spoof HWID ✔️ Spoof Discos ✔️ Spoof GUID ✔️ Spoof MAC ID ✔️ Spoof Hardware Information ✔️ Spoof PC Name ✔️ Spoof SMBIOS ✔️ Spoof System SKU ✔️ Spoof System Time ✔️ Spoof BIOS Information ✔️ Spoof Registry Settings ✔️ Delete Cache do Valorant ✔️ Check Registry Paths ✔️ Get System Informations 🖼️ Print do Spoofer Segue a interface para vocês verem como é simples e direto: 📋 Como usar Abra o spoofer como Administrador. Pressione 1 para SPOOF. Ele vai aplicar as mudanças automaticamente. Download:[Hidden Content] Scan: Clique Aqui1 ponto
-
Bom, gostaria de saber quais são as versões oficiais do WYD que já vazaram. Eu sei que existem as versões: 613, 6.56, 7.55 e 7.59. Então, gostaria de saber se existe alguma versão 7.48, 7.52 ou 7.54. E, caso exista, se alguém disponibilizaria para download?1 ponto
-
Um salve pra geral ! Bom, eu comprei essa base (das maos do ~rooh) tem um tempo e estou subindo ela no github para compartilhar com a comunidade, subirei tambem com algumas mudanças que fiz. A base é relativamente boa, e como estou aprendeendo a bricar na parte de programação tem me gerado bons desafios e aprendizados. Infelizmente, estou upando do jeito que peguei direto com quem me vendeu, sem algumas alterações de codigos que ja fiz, mas assim que conseguir editarei aqui colocando isso no github e com algumas alterações. # Fixs que fiz ! - - A interação em grande parte do cliente com a db usa atoi e as vezes retornava null. ! - - Ajustar a validação de janelas que tambem retornava null. ! - - Ajustar e validar as rows de algumas consultas na db( Não me lembro ao certo onde era o problema) tambem retorna null. Tem algumas coisas a mais que fiz, mas essas foram essenciais para que o server não "crashe" e derrube o cliente e/ou a TM. Espero que seja de grande valia para a comunidade e aprendizado de outros. LINK: [Hidden Content] SCAN RAR : [Hidden Content] SCAN .SLN CLIENT: [Hidden Content] SCAN .sln Server: [Hidden Content] Creditos: BnkBrum, SeiTbNao, Guga, BabyLoves, Arkanun1000 [W2PP] VKlafke, hiccupsman, andresantacruz, ErickAlcan, kevinkouketsu1 ponto
-
⚔️- 🔥👑Server [Chase Heroes]👑🔥 -⚔️ Vai com com Peryton e alice com set void e berkas. 💻 Venda – Servidor Oficial Chase Heroes (Cópia Autorizada) Estou vendendo uma cópia autorizada do servidor oficial Chase Heroes. com suporte a atualizações compativeis oficial do nosso cliente. 📦 Conteúdo incluso Set Void completo Personagens novos ativos e balanceados Alice Peryton ⚖️ Balanceamento completo Todos os personagens foram balanceados manualmente, um por um, por mim. Outras versões da Season V Pt.2 que circulam por aí são apenas cópias baseadas no meu trabalho. Todas as missões balanceadas até o End Game. 🔨 Sistema de Forja Forja com todos os itens necessários para progressão do jogo Créditos: GM Jean 💎 Sistema VIP Balanceado para funcionar junto com Free To Play, sem quebrar a progressão. ⚠️ Sistema de EXP do CLIENTE E SERVER CORRIGIDO (Maioria das versões encontrada na internet ta com sistema Bugado!) Agente Server Corrigido Ve os amigos online e da guilda sem bug. 🗺️ Missões incluídas Antigo Castelo Caseaje S1 Void 1 Profecia End Game / Conteúdo avançado Torre da Extinção Extermínio de Uria Fantasmas da Memória Rainha Gorgos O Eclipse Continente de Hariers 🌍 Extras Trivia e Frosland desbloqueados (caso queira balancear para jogar lá) Todos os desafios épicos Missões de eventos padrão 💰 Valores 🔥 R$ 400 ✔ Arquivos do Server + Cliente + Main Editor (ja da pra jogar offline ou no radmin, so nao consegue modificar o cliente) 🔥 R$ 600 ✔ Arquivos Server + Cliente + Surce Visual studio (cliente,server) + Main Editor + Sorted Oficial Season V Chase Heroes + Extrator de .ernas e compactador (criptografia cliente) 🔥 R$ 300 ✔ Instalação completa do servidor + Instalação dos programas comprados + Garantia de Suporte 1 Mês. Discord: elias_bdm ou [Hidden Content] INVENTARIO e PET COMPARTILHADO Guias Gerais do Grand Chase = 50$ Textos / 50$ Videos Versão editada por xXElias-GMXx versao mais atualizada Pacotao de programas e ferramentas administrativas Oficiais da Kog + Ferramentas da Comunidade Valor: 400R$ (Muitos dos arquivos n se encontra mais) Painel adm site oficial Chase Heroes v2 Valor: R$400,00 Comprei esse site a um tempo, porem tava cheio de bugs, arrumei tudo, virou outro. Recursos do painel: Statisticas do servidor: Player online/Vendas/uso do Hardware Adc cash e Vp Envio de itens rapido: Cria, edita e gerencia atalho de envio de itens rapidos (vips e baus ex) Gerencia Ids do servidor: Mapas/ Monstros/ Personagens/ Ver, editar e gerenciar / Gerênciador de contas: Editar lvl dos personagens / ver inventario / adc ou remover itens. Editar experiencia dos personagens e vitorias de PVP etc.. Cria Tokens, edita e gerencia. para serem resgataos no jogo Enviar coisas pelo correio Gerenciar guilds Aprovar/rejeitar1 ponto
-
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
-
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!1 ponto
-
Não existe cheat pago que seja 100% “anti-ban”. É claro que, quando o desenvolvedor mantém o cheat sempre atualizado conforme a versão do jogo e do anticheat, o risco de banimento pode diminuir. Porém, isso não elimina a possibilidade de ban, apenas torna a detecção mais difícil.1 ponto
-
Tinha essas dlls guardadas pra brincar as vezes, mas como já faz um tempo que não jogo mais WYD estarei disponibilizando pra vocês. Contém 5 dlls de whook compilado de projetos desconhecidos, alguns comandos funcionam em um e não em outros. O whook disponibilizado pelo shiroanimes neste tópico PARECE ser w1.dll. Os comandos mais usados são: #allon #move #fastkillon #rangeon #wallon #speedatkon #skill #soulon #fakeitem id nome (funciona apenas na w6.dll) #opencargo (em algumas dlls) #bau (em algumas dlls) #indexon #chat (em algumas dlls) #eraseon (em algumas dlls, terá que criar o .txt) Podem ter outras funções, basta testar. Algumas estão funcionando em servidores atuais e conhecidos, mas aqueles que criaram proteção depois do shiro disponibilizar aqui, fique tranquilo que não funcionará. A não ser que a proteção for somente no client 😃 Use por conta em risco! São projetos desconhecidos. Download [Hidden Content] SCAN1 ponto
-
struct STRUCT_MOB { char MobName[NAME_LENGTH]; // Nome do MOB/NPC/Player 1FDECA0 byte 0 a 15 dentro da STRUCT_MOB da TMSrv 1.7 char Clan; // Reino ou Grupo do MOB/NPC/Player 1FDECB0 byte 16 dentro da STRUCT_MOB da TMSrv 1.7 char Merchant; // Identificador da merchant 1FDECB1 byte 17 dentro da STRUCT_MOB da TMSrv 1.7 unsigned short Guild; // Identificador da Guild do MOB/NPC/Player 1FDECB2 byte 18 a 19 dentro da STRUCT_MOB da TMSrv 1.7 char Class; // Identificador da classe do MOB/NPC/Player 1FDECB4 byte 20 dentro da STRUCT_MOB da TMSrv 1.7 unsigned char Rsv; // AffectInfo 1FDECB5 byte 21 dentro da STRUCT_MOB da TMSrv 1.7 short Quest; // QuestInfo 1FDECB6 byte 22 a 23 dentro da STRUCT_MOB da TMSrv 1.7 int Coin; // Gold atual do MOB/NPC/Player 1FDECB8 byte 24 a 27 dentro da STRUCT_MOB da TMSrv 1.7 unsigned int Exp; // Experiencia atual do MOB/NPC/Player 1FDECBC byte 28 a 31 dentro da STRUCT_MOB da TMSrv 1.7 short SPX; // Ultima posição X salva com a Gema Estelar 1FDECC0 byte 32 a 33 dentro da STRUCT_MOB da TMSrv 1.7 short SPY; // Ultima posição Y salva com a Gema Estelar 1FDECC2 byte 34 a 35 dentro da STRUCT_MOB da TMSrv 1.7 STRUCT_SCORE BaseScore; // Status base 1FDECC4 byte 36 a 63 dentro da STRUCT_MOB da TMSrv 1.7 STRUCT_SCORE CurrentScore; // Status atual 1FDECE0 byte 64 a 91 dentro da STRUCT_MOB da TMSrv 1.7 STRUCT_ITEM Equip[MAX_EQUIP]; // Itens equipados no personagem 1FDECFC byte 92 a 219 dentro da STRUCT_MOB da TMSrv 1.7 STRUCT_ITEM Inventory[MAX_INVENTORY]; // Itens do inventario 1FDED7C byte 220 a 731 dentro da STRUCT_MOB da TMSrv 1.7 unsigned int LearnedSkill; // Skills Aprendidas - Dividido em 4 categorias (00 _ 00 _ 00 _ 00) 1FDEF7C byte 732 dentro da STRUCT_MOB da TMSrv 1.7 unsigned short ScoreBonus; // Pontos de Status (Força, Inteligencia, Dextreza, Constituição) 1FDEF80 byte 736 dentro da STRUCT_MOB da TMSrv 1.7 unsignes short SpecialBonus; // Pontos de Apreendizagem (Aprender Arma, Especial1, Especial2, Especial3) 1FDEF82 byte 738 dentro da STRUCT_MOB da TMSrv 1.7 unsignes short SkillBonus; // Pontos de Skill 1FDEF84 byte 740 dentro da STRUCT_MOB da TMSrv 1.7 char Critical; // Chance de Hits Criticos 1FDEF86 byte 742 dentro da STRUCT_MOB da TMSrv 1.7 char SaveMana; // 1FDEF87 byte 743 dentro da STRUCT_MOB da TMSrv 1.7 char SkillBar1[4]; // Salva o id de 4 skills da barra 1 //char SkillBar1[0]; 1FDEF88 byte 744 dentro da STRUCT_MOB da TMSrv 1.7 //char SkillBar1[1]; 1FDEF89 byte 745 dentro da STRUCT_MOB da TMSrv 1.7 //char SkillBar1[2]; 1FDEF8A byte 746 dentro da STRUCT_MOB da TMSrv 1.7 //char SkillBar1[3]; 1FDEF8B byte 747 dentro da STRUCT_MOB da TMSrv 1.7 char GuildLevel; // Identifica se o Player é membrou ou lider do clan 1FDEF8C byte 748 dentro da STRUCT_MOB da TMSrv 1.7 unsigned char Magic; // multiplicador de dano magico 1FDEF8D byte 749 dentro da STRUCT_MOB da TMSrv 1.7 char RegenHP; // Regeneração de HP 1FDEF8E byte 750 dentro da STRUCT_MOB da TMSrv 1.7 char RegenMP; // Regeneração de MP 1FDEF8F byte 751 dentro da STRUCT_MOB da TMSrv 1.7 char Resist[4]; // Identifica as resistencias Sagrado - Trovão - Fogo - Gelo //char Resist[0]; 1FDEF90 byte 752 dentro da STRUCT_MOB da TMSrv 1.7 //char Resist[1]; 1FDEF91 byte 753 dentro da STRUCT_MOB da TMSrv 1.7 //char Resist[2]; 1FDEF92 byte 754 dentro da STRUCT_MOB da TMSrv 1.7 //char Resist[3]; 1FDEF93 byte 755 dentro da STRUCT_MOB da TMSrv 1.7 } class CMob // 1724 size original da CMob 7.56 { public: //O size original da STRUCT_MOB na TMSrv 7.56 é 756 bytes STRUCT_MOB MOB; //0 - 755 //1FDECA0 addr inicial da pMob na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D84AC0 - STRUCT_MOB 100% Mapeada int Hold; //756 - 759 //1FDEF94 - CORRETO - TMSrv 7.57 7D84EC0 - 1024 - 1027 - 0x400 int ChatBlockTime; //760 - 763 //1FDEF98 - CORRETO - TMSrv 7.57 7D84EC4 int NightmareTicket; //764 - 767 //1FDEF9C (escritura do pesadelo para celestial+) - CORRETO - TMSrv 7.57 int Mileage; //768 - 771 //1FDEFA0 addr da Mileage na TMSrv 7.56 - CORRETO - TMSrv 7.57 //guarda a quantia de cash que tem na conta int unk_1FDEFA4; //772 - 775 //1FDEFA4 TMSrv 7.57 int Fame; //776 - 779 //1FDEFA8 addr da Fama na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D8514C int KefraTicket; //780 - 783 //1FDEFAC addr da KefraTicket na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D84ED8 int unk_1FDEFB0; //784 - 787 //1FDEFB0 alguma coisa haver com a fada do vale TMSrv 7.57 7D84EDC STRUCT_AFFECT SaveAffect[MAX_AFFECT]; //788 - 915 //1FDEFB4 - é uma STRUCT_AFFECT e é usada na save and quit talvez para salvar os affects do celestial ou algo assim - addr 004B859D char isChatBlock; //916 //1FDF034 - 0 chat sem bloqueio - 1 chat bloqueado - CORRETO - TMSrv 7.57 7D84FE0 - 1312 - 0x520 char CristalQuest; //917 //1FDF035 - CORRETO - TMSrv 7.57 7D84FE1 - 1313 - 0x521 //verificação do andamento da quest dos cristais chama a função 00414E70(CristalQuest, i) i = 0; i < 4; i++ //00414ED0 provavelmente a função que seta o uso do cristal (1 << i) & CristalQuest //(0: Não iniciou a quest - 1: usou o cristal Elime - 2: usou o cristal Silphed - 4: usou o cristal Thelion - 8: usou o cristal Noas) char isArchBlockedLvl; //918 //1FDF036 - CORRETO - TMSrv 7.57 7D84FE2 - 1314 - 0x522 char ArchLvlandFuryStone; //919 //1FDF037 - CORRETO - TMSrv 7.57 7D84FE3 - 1315 - 0x523 //valor vai de 1 a 8 - lvl do arch quando o celestial foi criado ate o 5 + resets pedra da furia 6 a 8 char unk_1FDF038; //920 //1FDF038 - relacionado a bloqueio de lvl char isBlockedLvl; //921 //1FDF039 - relacionado a bloqueio de lvl - CORRETO - TMSrv 7.57 7D84FE5 - 1317 - 0x525 char unk_1FDF03A; //922 //1FDF03A - relacionado a bloqueio de lvl char unk_1FDF03B; //923 //1FDF03B - relacionado a bloqueio de lvl char unk_1FDF03C; //924 //1FDF03C - relacionado a bloqueio de lvl char isHardCore; //925 //1FDF03D - Relacionado ao Hardcore - CORRETO - TMSrv 7.57 7D84FE9 - 1321 - 0x529 char soulType; //926 //1FDF03E - salva a config da Soul vai de 1 - 10 - CORRETO - TMSrv 7.57 7D84FEA - 1322 - 0x52A char isGodOrSub; //927 //1FDF03F - celestial:0 sub:1 - CORRETO - TMSrv 7.57 7D84FEB - //size da Struct que salva as infos do celestial e do sub é 68 bytes na 756 e 96 bytes na 757+ STRUCT_SUBCLASSINFO saveSubClassInfo[2];//932 - 1067 //1FDF044 - Salva as Infos do Cele e do Sub - CORRETO - TMSrv 7.57 7D84FF0 - int unk_1FDF0E0; //1088 - 1091 //1FDF0E0 - CORRETO - TMSrv 7.57 7D850C4 - STRUCT_AFFECT Affect[MAX_AFFECT]; //1204 - 1331 //1FDF154 addr da Affect na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85148 - 1672 - 1927 - 0x688 //Originalmente na TMSrv 7.56 tem 1332 bytes antes da variavel Mode ou seja do 0 ao 1331 - TMSrv 7.57 tem 2084 bytes antes da variavel Mode ou seja do 0 ao 2083 int Mode; //1332 - 1335 //1FDF1D4 addr da Mode na TMSrv1.7 - CORRETO - TMSrv 7.57 7D852E4 - 2084 - 2087 - 0x824 int Leader; //1336 - 1339 //1FDF1D8 addr da Leader na TMSrv1.7 - CORRETO - TMSrv 7.57 7D852E8 - 2088 - 2091 - 0x828 int Formation; //1340 - 1343 //1FDF1DC addr da Formation na TMSrv1.7 - CORRETO - TMSrv 7.57 7D852EC - 2092 - 2095 - 0x82C int RouteType; //1344 - 1347 //1FDF1E0 addr da RouteType na TMSrv1.7 - CORRETO - TMSrv 7.57 7D852F0 - 2096 - 2099 - 0x830 int LastX; //1348 - 1351 //1FDF1E4 addr da LastX na TMSrv1.7 - CORRETO - TMSrv 7.57 7D852F4 - 2100 - 2103 - 0x834 int LastY; //1352 - 1355 //1FDF1E8 addr da LastY na TMSrv1.7 - CORRETO - TMSrv 7.57 7D852F8 - 2104 - 2107 - 0x838 int LastTime; //1356 - 1359 //1FDF1EC addr da LastTime na TMSrv1.7 - CORRETO - TMSrv 7.57 7D852FC - 2108 - 2111 - 0x83C int LastSpeed; //1360 - 1363 //1FDF1F0 addr da LastSpeed na TMSrv1.7 - CORRETO - TMSrv 7.57 7D85300 - 2112 - 2115 - 0x840 int TargetX; //1364 - 1367 //1FDF1F4 addr da targetX na TMSrv1.7 - CORRETO - TMSrv 7.57 7D85304 - 2116 - 2119 - 0x844 int TargetY; //1368 - 1371 //1FDF1F8 addr da TargetY na TMSrv1.7 - CORRETO - TMSrv 7.57 7D85308 - 2120 - 2123 - 0x848 int NextX; //1372 - 1375 //1FDF1FC addr da NextX na TMSrv1.7 - CORRETO - TMSrv 7.57 7D8530C - 2124 - 2127 - 0x84C int NextY; //1376 - 1379 //1FDF200 addr da NextY na TMSrv1.7 - CORRETO - TMSrv 7.57 7D85310 - 2128 - 2131 - 0x850 int NextAction; //1380 - 1383 //1FDF204 addr da NextAction na TMSrv1.7 - CORRETO - TMSrv 7.57 7D85314 - 2132 - 2135 - 0x854 char Route[MAX_ROUTE]; //1384 - 1407 //1FDF208 addr da Route na TMSrv1.7 - CORRETO - TMSrv 7.57 7D85318 - 2136 - 2159 - 0x858 int WaitSec; //1408 - 1411 //1FDF220 addr da WaitSec na TMSrv1.7 - CORRETO - TMSrv 7.57 7D85330 - 2160 - 2163 - 0x870 int PosX; //1412 - 1415 //1FDF224 addr da PosX na TMSrv1.7 int PosY; //1416 - 1419 //1FDF228 addr da PosY na TMSrv1.7 int Segment; //1420 - 1423 //1FDF22C addr da Segment na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D8526C - 1964 - 1967 - 0x7AC int SegmentX; //1424 - 1427 //1FDF230 addr da SegmentX na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85270 - 1968 - 1971 - 0x7B0 int SegmentY; //1428 - 1431 //1FDF234 addr da SegmentY na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85274 - 1972 - 1975 - 0x7B4 int SegmentListX[MAX_SEGMENT]; //1432 - 1451 //1FDF238 addr da SegmentListX na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85278 - 1976 - 1995 - 0x7B8 int SegmentListY[MAX_SEGMENT]; //1452 - 1471 //1FDF24C addr da SegmentListY na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D8528C - 1996 - 2015 - 0x7CC int SegmentWait[MAX_SEGMENT]; //1472 - 1491 //1FDF260 addr da SegmentWait na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D852A0 - 2016 - 2035 - 0x7E0 int SegmentDirection; //1492 - 1495 //1FDF274 addr da SegmentRange na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D852B4 - 2036 - 2039 - 0x7F4 int SegmentProgress; //1496 - 1499 //1FDF278 addr da SegmentDirection na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D852B8 - 2040 - 2043 - 0x7F8 int GenerateIndex; //1500 - 1503 //1FDF27C addr da GenerateIndex na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D852BC - 2044 - 2047 - 0x7FC unsigned short CurrentTarget; //1504 - 1505 //1FDF280 addr da CurrentTarget na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D852C0 - 2048 - 2049 - 0x800 unsigned short EnemyList[MAX_ENEMY]; //1506 - 1513 //1FDF282 addr da EnemyList na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D852C2 - 2050 - 2057 - 0x802 short PartyList[MAX_PARTY]; //1514 - 1537 //1FDF28A addr da PartyList na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D852CA - 2058 - 2081 - 0x80A short unk_1FDF2A2; //1538 - 1539 //1FDF2A2 int WeaponDamage; //1540 - 1543 //1FDF2A4 addr da WeaponDamage na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85334 - 2164 - 2167 - 0x874 int Summoner; //1544 - 1547 //1FDF2A8 addr da Summoner na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85338 - 2168 - 2171 - 0x878 int PotionCount; //1548 - 1551 //1FDF2AC addr da PotionCount na TMSrv 7.56 TMSrv 7.57 7D8533C - 2172 - 2175 - 0x87C int GuildDisable; //1552 - 1555 //1FDF2B0 addr da GuildDisable na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85340 - 2176 - 2179 - 0x880 int DropBonus; //1556 - 1559 //1FDF2B4 addr da DropBonus na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85344 - 2180 - 2183 - 0x884 int ExpBonus; //1560 - 1563 //1FDF2B8 addr da ExpBonus na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85348 - 2184 - 2187 - 0x888 int Range; //1564 - 1567 //1FDF2BC addr da Range na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D8534C - 2188 - 2191 - 0x88C int unk_1FDF2C0; //1568 - 1571 //1FDF2C0 TMSrv 7.57 7D85350 - 2192 - 2195 - 0x890 int unk_1FDF2C4; //1572 - 1575 //1FDF2C4 TMSrv 7.57 7D85354 - 2196 - 2199 - 0x894 int MobFace; //1576 - 1579 //1FDF2C8 addr da MobFace na TMSrv 7.56 - CORRETO - TMSrv 7.57 7D85358 - 2200 - 2203 - 0x898 //Calculo é feito com MobFace % 10 < 5 Mortal ou Transformações do BM retorna 0 //> 5 verifica no Learn se tem soul se nao tiver retorna 1 //se tiver soul retorna 2 int QuestFlag; //1580 - 1583 //1FDF2CC recebe o valor 0 na CreateMob - Relacionado com QUESTs TMSrv 7.57 7D8535C - 2204 - 2207 - 0x89C BOOL KhepraLive; //1588 - 1591 //1FDF2D4 - CORRETO - TMSrv 7.57 7D85360 - 2208 - 2211 - 0x8A0 int unk_1FDF2D8; //1592 - 1595 //1FDF2D8 - CORRETO - TMSrv 7.57 7D85364 - 2212 - 2215 - 0x8A4 int unk_1FDF2DC; //1596 - 1599 //1FDF2DC - CORRETO - TMSrv 7.57 7D85368 - 2212 - 2215 - 0x8A8 int unk_1FDF2E0; //1600 - 1603 //1FDF2E0 - CORRETO - TMSrv 7.57 7D8536C - 2212 - 2215 - 0x8AC int ServerKingdom; //1584 - 1587 //1FDF2D0 - CORRETO - TMSrv 7.57 7D85380 - 2236 - 2239 - 0x8BC int ForceDamage; //1604 - 1607 //1FDF2E4 - CORRETO - TMSrv 7.57 7D85370 - 2224 - 2227 - 0x8B0 int TmpSpeed; //1644 - 1647 //1FDF30C - CORRETO - TMSrv 7.57 7D85374 - 2228 - 2231 - 0x8B4 int CurTime; //1648 - 1651 //1FDF310 - CORRETO - TMSrv 7.57 7D85378 - 2232 - 2235 - 0x8B8 int unk_7D85384; //Descobrir o que é parece um timer TMSrv 7.57 7D85384 - 2240 - 2243 - 0x8C0 int CountHpDamage; //1608 - 1611 //1FDF2E8 - CORRETO - TMSrv 7.57 7D85398 - 2264 - 2267 - 0x8D8 int countHP; //1612 - 1615 //1FDF2EC - CORRETO - TMSrv 7.57 7D8539C - 2268 - 2271 - 0x8DC int countMP; //1616 - 1619 //1FDF2F0 - CORRETO - TMSrv 7.57 7D853A0 - 2272 - 2275 - 0x8E0 int PerfBonus; //1620 - 1623 //1FDF2F4 - CORRETO - TMSrv 7.57 7D853A4 - 2276 - 2279 - 0x8E4 int AbsBonus; //1624 - 1627 //1FDF2F8 - CORRETO - TMSrv 7.57 7D853A8 - 2280 - 2283 - 0x8E8 int unk_1FDF2FC; //1628 - 1631 //1FDF2FC TMSrv 7.57 7D853AC - 2284 - 2287 - 0x8EC int SummonType; //1632 - 1635 //1FDF300 - CORRETO - TMSrv 7.57 7D853B0 - 2288 - 2291 - 0x8F0 int ItemUser; //1636 - 1639 //1FDF304 - CORRETO - TMSrv 7.57 7D853B4 - 2292 - 2295 - 0x8F4 int ItemSummoner; //1640 - 1643 //1FDF308 - CORRETO - TMSrv 7.57 7D853B8 - 2296 - 2299 - 0x8F8 short DamagePvP; // - CORRETO - TMSrv 7.57 7D853BC - 2300 - 2301 - 0x8FC short DefensePvP; // - CORRETO - TMSrv 7.57 7D853BE - 2302 - 2303 - 0x8FE short MobList[MAX_PARTY]; // - CORRETO - TMSrv 7.57 7D853C0 - 2304 - 2327 - 0x900 Proximo é o nAffectInfo int unk_1FDF314; //1652 - 1655 //1FDF314 - CORRETO - int ServerTowerId; //1656 - 1659 //1FDF318 - CORRETO - char Tab[MAX_TAB_LENGTH]; //1660 - 1687 //1FDF31C - CORRETO - TMSrv 7.57 - 1928 - 1953 - 0x788 (1FDF334 -> MAX_TAB_LENGTH - 2 = 0) (1FDF335 -> MAX_TAB_LENGTH - 1 = 0) define o fim do buffer do Tab int unk_1FDF338; //1688 - 1691 //1FDF338 - CORRETO - int unk_1FDF33C; //1692 - 1695 //1FDF33C - CORRETO - TMSrv 7.57 7D85388 - Possivelmente um Count int unk_1FDF340; //1696 - 1699 //1FDF340 - CORRETO - Possivelmente uma PosX int unk_1FDF344; //1700 - 1703 //1FDF344 - CORRETO - Possivelmente uma PosY int unk_1FDF348; //1704 - 1707 //1FDF348 - CORRETO - int nAffectInfo; //1708 - 1711 //1FDF34C - CORRETO - TMSrv 7.57 7D853D8 - 2328 - 2331 - 0x918 /* //0 off - 1 on Bit 0 : Controle de Mana (1 << 0) Bit 1 : Imunidade (1 << 1) Bit 2 : Encantar Gelo (1 << 2) Bit 3 : Possuido (1 << 3) Bit 4 : Toxina da Serpente (1 << 4) Bit 5 : Evasão Aprimorada (1 << 5) Bit 6 : Invisibilidade (1 << 6) Bit 7 : Velocidade (1 << 7) Bit 8 : (1 << 8) Bit 9 : Cancel (1 << 9) Bit 10 : Congelado (1 << 10) Bit 11 : Invuneravel (1 << 11) Bit 12 : Flash (1 << 12) */ short nSkillDalay; //1712 - 1713 //1FDF350 - CORRETO - TMSrv 7.57 7D853DC - 2332 - 2333 - 0x91C int Accuracy; //1716 - 1719 //1FDF354 - CORRETO - TMSrv 7.57 7D853E0 - 2334 - 2337 - 0x91E int Evasion; //1720 - 1723 //1FDF358 - CORRETO - TMSrv 7.57 7D853E4 - 2338 - 2343 - 0x922 }; struct STRUCT_SUBCLASSINFO { unsigned int saveLearnedSkill; // 1FDF044 - CORRETO - TMSrv 7.57 7D84FF0 - - - - salva o Learn do celestial/subcelestial unsigned int saveNLearnedSkill; // 757+ - CORRETO - TMSrv 7.57 7D84FF4 - - - - salva o Learn2 do celestial/subcelestial STRUCT_ITEM saveFace; // 1FDF048 - CORRETO - TMSrv 7.57 7D84FF8 - - - - salva Face do personagem STRUCT_SCORE saveBaseScore; // 1FDF050 - CORRETO - TMSrv 7.57 7D85000 - - - - salva a BaseScore long long saveExp; // 1FDF06C - CORRETO - TMSrv 7.57 7D85030 - salva a Exp (int na 756-) char saveSkillBar[20]; // 1FDF070 - CORRETO - TMSrv 7.57 7D85038 - salva a SkilBar1[4] e a SkillBar2[16] unsigned short saveScoreBonus; // 1FDF084 - CORRETO - TMSrv 7.57 7D8504C - salva os pontos de Score que ainda nao foram distribuidos unsigned short saveSkillBonus; // 1FDF086 - CORRETO - TMSrv 7.57 7D8504E - salva os pontos para compra de skills }; enum AFFECT_INFO { EMPTY_AFFECT = 0, MANACONTROL = 1, IMMUNE = 2, FREEZE = 4, BERSERKER = 8, POISON = 16, EVASION = 32, INVISIBLE = 64, VELOCITY = 128, IMMUNITY = 256, CANCEL = 512, FROZEN = 1024, //757+ INVULNERABLE = 2048, //757+ FLASH = 4096 //757+ }; int CMob::StandingByProcessor() //Função Ok { int rt = FALSE; //local 2 ebp-08 local 5 if (MOB.CurrentScore.MaxMp) { if (MOB.CurrentScore.Mp <= 0 && Mode != MOB_COMBAT) { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //0041724B - 004CCC8B MOB.CurrentScore.Mp--; } //0041725D - 004CCC9A int Face = MOB.Equip[FACE].Index; //local 3 ebp-0c local 8 if (Affect[0].Type != 24 && Face == 358) //Vinha { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //00417291 - 004CCCD5 if (RouteType == 5) { if (Leader <= MOB_EMPTY || Leader >= MAX_USER) { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //004172CD - 004CCD10 int otherFace = MOB.Equip[FACE].Index; //local 4 ebp-10 local 11 if (Affect[0].Type != 24 && (otherFace < 315 || otherFace > 346)) { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //0041730A - 004CCD51 int summoner = Summoner; //local 5 ebp-14 local 14 if (summoner <= MOB_EMPTY || summoner >= MAX_USER) { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //00417336 - 004CCD84 int isLeader = FALSE; //local 6 ebp-18 local 17 if (Leader == summoner) isLeader = TRUE; for (int i = 0; i < MAX_PARTY; ++i) //local 7 ebp-1c local 20 { if (pMob[Leader].PartyList[i] == summoner) isLeader = TRUE; } //00417392 - 004CCDE0 if (!isLeader) { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //004173A9 - 004CCDF9 if (Affect[0].Type == 24 && !Affect[0].Time) { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //004173D6 - 004CCE27 if (pUser[summoner].Mode == USER_PLAY) { int Distance = BASE_GetDistance(TargetX, TargetY, pMob[summoner].TargetX, pMob[summoner].TargetY); //local 8 ebp-20 local 23 if (Distance >= 20) { NextX = pMob[summoner].TargetX; NextY = pMob[summoner].TargetY; rt |= 2; return rt; } //00417472 - 004CCEC5 if (Distance > 2 && Distance < 20) { SegmentX = pMob[summoner].TargetX; SegmentY = pMob[summoner].TargetY; GetNextPos(0); rt |= 1; return rt; } } //004174CA - 004CCF1C else { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } //004174DB - 004CCF2F return rt; } //004174E3 - 004CCF37 if (!Leader) { int target = GetEnemyFromView(); //local 9 ebp-24 local 26 if (target && TargetX < (SegmentX + 12) && TargetX > (SegmentX - 12) && TargetY < (SegmentY + 12) && TargetY > (SegmentY - 12)) { target |= 0x10000000; return target; } } //00417569 - 004CCFBD if (RouteType == 6 && TargetX == SegmentX && TargetY == SegmentY) return 0; //004175A4 - 004CCFF8 if (SegmentX == TargetX && SegmentY == TargetY) { //004175F4 - 004CD028 if(WaitSec > 0 && RouteType != 6) { WaitSec -= 6; if (WaitSec > 0) { if (!RouteType && TargetX == SegmentListX[0] && TargetY == SegmentListY[0]) return 0; //00417650 - 004CD0A4 if (!(MOB.BaseScore.AttackRun & 0xF)) return 0; #ifdef CLIVER756- rt |= 16; #else rt |= 4096; //7.57+ #endif return rt; } //00417677 - 004CD0CA WaitSec = 0; } else //00417686 - 004CD0D9 { int SegWait = SegmentWait[SegmentProgress]; //local 10 ebp-28 local 29 if (SegWait > 0) { WaitSec = SegWait; return rt; } } //004176B3 - 004CD106 int setSeg = SetSegment(); //local 11 ebp-2c local 32 if (setSeg == 1) return rt; //004176C9 - 004CD11C if (setSeg == 2) { #ifdef CLIVER756- rt |= 1; #else rt |= 256; //7.57+ #endif return rt; } } //004176DD - 004CD132 GetNextPos(0); if (NextX == TargetX && NextY == TargetY) { SetSegment(); return rt; } rt |= 1; return rt; } //00417890 addr da BattleProcessor na TMSrv 7.56 - TMSrv 7.57 004CD190 int CMob::BattleProcessor() //Função Ok { int Face = MOB.Equip[FACE].Index; //local 2 ebp-08 local 5 if (Affect[0].Type != 24 && Face == 358) //vinha return 32; //004178E0 - 004CD1E2 SelectTargetFromEnemyList(); if (CurrentTarget == MOB_EMPTY) { Mode = MOB_PEACE; return 0; } //0041790A - 004CD20C if (RouteType == 5) { if (Leader <= MOB_EMPTY || Leader >= MAX_USER) return 32; int SummonerId = Summoner; //local 3 ebp-0c local 8 if (SummonerId <= MOB_EMPTY || SummonerId >= MAX_USER) return 32; int HP = MOB.CurrentScore.Hp; //local 4 ebp-10 local 11 if (HP <= 0) return 32; //00417989 - 004CD288 if (Affect[0].Type != 24 && (Face < 315 || Face > 346)) return 32; //004179B5 - 004CD2B3 int Summoned = FALSE; //local 5 ebp-14 local 14 if (Leader == SummonerId) Summoned = TRUE; //004179D1 - 004CD2CF for (int i = 0; i < MAX_PARTY; i++) //local 6 ebp-18 local 17 { if (pMob[Leader].PartyList[i] == SummonerId) Summoned = TRUE; } if (!Summoned) return 32; //00417A21 - 004CD31F int Distance = BASE_GetDistance(TargetX, TargetY, pMob[SummonerId].TargetX, pMob[SummonerId].TargetY); //local 7 ebp-1c local 20 if (Distance >= 20) { NextX = pMob[SummonerId].TargetX; NextY = pMob[SummonerId].TargetY; return 2; } } //00417AA0 - 004CD39E int Int = MOB.BaseScore.Int; //local 8 ebp-20 local 23 ebp-5c if (Int < rand() % 100) return 0x10000; //00417AC6 - 004CD3C4 int Dex = MOB.BaseScore.Dex; //local 9 ebp-24 local 26 ebp-68 int posX = pMob[CurrentTarget].TargetX; //local 10 ebp-28 local 29 ebp-74 int posY = pMob[CurrentTarget].TargetY; //local 11 ebp-2c local 32 ebp-80 int Range = BASE_GetMobAbility(&MOB, EF_RANGE); //local 12 ebp-30 local 35 ebp-8c int Distance = BASE_GetDistance(TargetX, TargetY, posX, posY); //local 13 ebp-34 local 38 ebp-98 //00417B3A - 004CD43E if (CheckKhepra()) Range = 26; //00417B4D - 004CD454 if (pMob[CurrentTarget].CheckKhepra() && (Face == 307 || Face == 245)) Range = 26; //00417B85 - 004CD48F if (RouteType != 5) { if(TargetX > (SegmentX + 30) || TargetX < (SegmentX - 30) || TargetY > (SegmentY + 30) || TargetY < (SegmentY - 30)) { //004CD4FF //7.57+ esse if é somente da 7.57 para frente if (unk_1FDF2D8 != 0) //0x8A4 - identificar o que é essa variavel na 7.57 { if (CurrentTarget == MOB_EMPTY) { for (int i = MOB_EMPTY; i < MAX_ENEMY; i++) //local 41 EnemyList[i] = MOB_EMPTY; //004CD556 Mode = MOB_PEACE; NextX = SegmentListX[0]; NextY = SegmentListY[0]; return 2; } } //00417BF5 - 004CD596 else //7.56 retirar o if e deixar so o conteudo do else { CurrentTarget = MOB_EMPTY; for (int i = MOB_EMPTY; i < MAX_ENEMY; i++) //local 14 ebp-38 local 44 EnemyList[i] = MOB_EMPTY; Mode = MOB_PEACE; GetNextPos(1); if (NextX == TargetX && NextY == TargetY) return 0; else return 16; } } } //00417C7B - 004CD629 if (Distance <= Range) { int _rand = rand() % 100; //local 15 ebp-3c ebp-0bc if (Range >= 4 && Distance <= 2 && _rand > Dex && MOB.BaseScore.AttackRun & 0xF) return 256; //00417CC4 - 004CD681 int _X = posX; //local 16 ebp-40 ebp-0c8 int _Y = posY; //local 17 ebp-44 ebp-0d4 int maxDist = SECBATTLE; //local 18 ebp-48 ebp-0e0 //00417CD7 - 004CD69D if (!CheckKhepra()) { int isHall = FALSE; //local 19 ebp-4c ebp-0ec if (TargetX >= 2341 && TargetX <= 2393 && TargetY >= 3907 && TargetY <= 3954 && unk_1FDF300) isHall = TRUE; //00417D3D - 004CD709 if (!isHall) BASE_GetHitPosition(TargetX, TargetY, &posX, &posY, (char*)pHeightGrid, maxDist); } //00417D70 - 004CD742 if (posX != _X || posY != _Y) return 256; else return 4096; } //00417D8E - 004CD768 return 1; }1 ponto
-
Fala, pessoal. Quis compartilhar uma ferramenta de apoio que desenvolvi para acompanhar o uso do editor de cena. Que você pode encontrar nesse link: A ideia desse projeto foi facilitar o trabalho com arquivos UITextureListN.bin, tanto na parte de conversão quanto na conferência dos registros atuais do arquivo. Em muitos casos, enquanto a gente vai ajustando recurso, caminho ou estrutura, acaba sendo útil ter uma ferramenta separada para visualizar rapidamente a lista do BIN e reconstruir o arquivo no formato correto. A ferramenta permite: - converter BIN para TXT - converter TXT para BIN - visualizar os registros do BIN carregado - pesquisar por índice, caminho e tipo - trabalhar com compatibilidade entre layouts 264 e 528 - usar BIN de referência para reconstrução mais segura Fiz isso como um utilitário de apoio ao fluxo de edição, justamente para complementar o trabalho no editor principal sem deixar o programa de cena mais poluído. Repositório: [Hidden Content] Se alguém quiser testar e dar feedback, vai ajudar bastante.1 ponto
-
Fala, pessoal. Queria compartilhar com vocês esse repositório do WYD FieldScene Studio Pro. Mesmo não sendo programador, o trabalho do Hamilton me inspirou bastante. A base do projeto e toda a ideia inicial me chamaram atenção justamente pelo quanto essa ferramenta veio pra ajudar quem mexe com interface e edição de painéis no WYD. Sem exagero algum, eu cheguei em 90 versoes em testes "ta comm tempo né" kkk A partir disso, tive a ideia de tentar tornar o programa mais acessível, principalmente para quem não tem monitor com resolução muito alta ou acaba sofrendo com a limitação de espaço na tela durante a edição. Além disso, fui buscando implementar melhorias de usabilidade, organização visual e praticidade no fluxo de trabalho, sempre tentando deixar a ferramenta mais confortável e funcional no uso do dia a dia. O objetivo não foi apagar a origem do projeto, mas sim evoluir em cima de uma base que já era boa, trazendo adaptações, correções e recursos que pudessem facilitar a vida de mais pessoas. Entre os pontos que busquei melhorar estão: - melhor adaptação para diferentes resoluções - visualização em escala 1:1 - conversão e ajuste entre resoluções - carregamento e compatibilidade de recursos - melhorias no uso geral do editor - remoção de fundo em imagens compatíveis - mais praticidade para edição, importação e visualização -o programa tem régua -arraste por mouse **OBS IMPORTANTE, É RECOMENDADO QUE QUANDO FOR SOLICITADO O CARREGAMENTO DE RECURSOS ABRA ATÉ A PASTA DO CLIENTE ONDE ESTÃO AS PASTAS UI, NUI E MESH, ASSIM O PROGRRAMA JÁ CARREGA AS 3 PASTAS NO LUGGAR DE ABRIR UMA POR VEZ, ALGUNS PAINEIS AS VEZES ESTAO FORA DA UI** e mais coisas que não me lembro agora haha Estou compartilhando porque pode ser útil para outras pessoas da área, e também porque acho justo reconhecer que essa iniciativa só existiu porque o trabalho original me motivou a tentar fazer algo também Repositório: [Hidden Content] Se alguém quiser testar, dar feedback ou sugerir melhorias, vai ser muito bem-vindo. E LEMBRANDDO CRÉDITOS TOTAIS AO HAMILTON DO CANAL HC CURSOS E TUTORIAIS1 ponto
-
ASSINATURAS ATUALIZADAS Patrocinadora: streamingsbarato.com [Hidden Content] [Hidden Content] [Hidden Content] [Hidden Content] Assinatura será atualizada todos os meses.1 ponto
-
Demonstração 1. Abra o CS2 2. depois de aberto, execute o Loader da FRCHEATS e logue em sua conta do fórum 3. Selecione a area CHEAT CS2 4.com CS2 aberto Clique em Injetar e aguarde a mensagem "Injetado com Sucesso" Após isso basta entrar em uma partida e apertar INSERT Bom jogo :) DOWNLOAD SENDSPACE: [Hidden Content]1 ponto
-
Há uma força misteriosa que atua aqui. Não sei explicar o que é, mas essa força nos reconecta de tempos em tempos. Fazendo nos resgatar uma antiga essência. "A vida mudou muito em pouco tempo e cada vez mais mudará mais... As areias continuam a brisar... Apagando lentamente cada pegada na linha do tempo."1 ponto
-
1 ponto
-
1 ponto
-
As regras são simples: ✅ Siga nossa página no Facebook e no Instagram ❤️ Curta o post 👥 Marque 1 amigo nos comentários Só isso! Não é mais necessário compartilhar. 🎉 Lembre-se: pode participar pelo Facebook, pelo Instagram ou pelos dois — quanto mais tarefas fizer, mais pontos acumula e mais chances tem de ganhar! Nossa vontade é que todo mundo participe e tenha uma chance real de ganhar. Esse sorteio é pra vocês que estão aqui desde o início acreditando nesse projeto! 🙏 🎁 São 20 ganhadores de R$ 200,00 em Infinity Points cada! 🔗 Acesse o link e participe agora: [Hidden Content] 📅 Sorteio encerra: 30/04/2026 ⚠️ Observação: No dia do sorteio será verificado manualmente se cada participante realmente curtiu o post, seguiu a página e marcou 1 amigo nos comentários. Quem não tiver feito nenhuma das duas será desclassificado. O sorteio será realizado ao vivo e gravado. ⚔️ "O farm te prepara. O PVP te define." ∞ G2K 🌐Redes Sociais 🌍 Site: [Hidden Content] 💬 Discord: [Hidden Content] 📸 Instagram: [Hidden Content] 📱 WhatsApp: [Hidden Content]1 ponto
-
1 ponto
-
Mano não ta dando para acessar as conta do prime vídeo direto pede um código para validar a senha Tem um indiota que ta trocando as senhas direto palhaço criança sem conduta não tem limite mulecagem, o prime tá pedindo código1 ponto
-
Olá WC, Conforme pedidos no meu último post do cheat de Grand Chase Season 2 Estou trazendo esse trainer para a Season Chaos. Espero que ajude vocês nas missões! Como Utilizar: 1- Abra o Grand Chase e entre no servidor 2- Abra o "Grand Chase Chaos Trainer by ObscureArt" como Administrador 3- Agora é só ativar as funções Funções: Multiplicador de Dano / Defesa: 1- Marcar a caixa para ativar o multiplicador 2- Colocar um número no edit "multiplicador" e apertar ENTER para aplicar 3- Clicar nos botões "Mais Dano" / "Menos Dano" Aumenta o multiplicador de 1 em 1 Dano base = 1 1 = 10 dano 2= 20 dano 3= 30 dano e assim por diante... Selecionar um número alto ex: 20000 resultará em One Hit. Perfect Mission - Atualiza a porcentagem de combo para 100% ao terminar o estágio, possibilitando +EXP +GP no fim da partida. (Similar ao RANK SS no Classic) Poções Infinitas - Atualiza e trava em 99 todas poções equipadas. (Desaparece ao relogar) Poções Zero Cooldown - Zera o Cooldown das poções. possibilitando *HP / MP Infinito* Monster Vac - Trava a posição de todos monstros do mapa em um ponto fixo. Valor fixado não foi testado em todas missões. IMAGEM ILUSTRATIVA: [Hidden Content] [Hidden Content] SCAN: VirusTotal Sobre detecções: Seu anti virus pode detectar um HackTool como arquivo perigoso, isso é normal. Edit: Trainer Atualizado1 ponto
-
Segue um print de um .FBX convertido do .MSH ag010101 convertido com o app e carregado no blender 5.0 .FBX convertido do .MSH bd010101 .ani no blender agora suportamos GLB/GLTF1 ponto
-
WEBCHEATS A P R E S E N T A ASSISTA A QUALQUER VÍDEO NOS SITES OFICIAIS DE VÍDEOS AULTOS +18 SEM PRECISAR PAGAR NADA! A plataforma a seguir consegue liberar todo e qualquer tipo de vídeos/filmes adultos restritos exclusivamente para assinantes. Você consegue assistir os conteúdos exclusivos sem precisa pagar nada mensalmente! COMO USAR A PLATAFORMA: A plataforma é bem autoexplicativa, não há muito segredo. Acesse o site do Mineiro (link no final do tópico); Vai aparecer diversos sites pornográficos, selecione o site que deseja assistir (Por exemplo, o site da Brad Montana); Em seguida você será redirecionado para adicionar o link do vídeo restrito; Pois bem, o próximo passo é acessar o site oficial da Brad Montana; Agora escolha um vídeo/filme premium, restrito somente para assinantes; Após escolher, copie o link do vídeo no campo de URL e retorne a plataforma do Mineiro; Retornando ao site do Mineiro, cole o link do vídeo no campo em que está sendo pedido; Depois, clique no botão "Quero assistir esse vídeo/filme". Caso queria entender melhor a explicação em vídeo, assista: 𝗢𝗯𝘀.: Quando você clicar no botão "Quero assistir esse vídeo/filme", vai aparecer alguns anúncios pedindo para você permitir a notificação. Basta você ficar recusando/bloqueando. A solicitação dessa notificação vai aparecer umas 6x depois que você recusar, basta ficar recusando que logo você será direcionado para assistir o vídeo em FULL HD. 𝗢𝗯𝘀.: Se você clicar em permitir, os anúncios vão deixar de aparecer. Lembre-se de remover a notificação depois, pois é muito chato. LINK DO SITE [Hidden Content] ESTE MATERIAL ERA EXCLUSIVAMENTE PARA MEMBROS VIP! USE COM MODERAÇÃO!1 ponto
-
Cheat de borboleta para o Site ZargothPT. No vídeo, na descrição do vídeo e no cheat vocês terão o tutorial de como estar utilizando. Download: [Hidden Content] Scan: [Hidden Content]1 ponto
-
Olá. Recentemente eu dei uma passada pela Web Cheats e fiquei muito feliz que o E-Mapas foi lembrado, alguns procurando, outros fazendo re-up. Até mesmo consegui baixar ele . Quem fez o E-Mapas deveria apanhar, o coisinha chata e enjoada hahahha . Graças a essa nostalgia, resolvi fazer uma segunda versão, uma decente, de acordo com meu atual nível na programação ( que não é grande coisa ) Porém, se vou "perder tempo" desenvolvendo algo, pq não já fazer o resto? Editores de itemlist, serverlist, wys, wyt, ... etc etc etc. Precisamos de um milhão de ferramentas para ajustar um servidor. Gostaria de evitar isso. Apresento a vocês o eWYD, deveria ser a segunda versão do E-Mapas, mas o escopo aumentou um pouco rsrs. Caso tenham as estruturas dos arquivos do jogo de forma mais organizada, por favor, poste aqui para que eu possa importar e criar novos menus para editar tudo relacionado ao jogo. Eu sei que tem o projeto TM, descompilações etc, mas facilitaria caso já tenham algo. Arquivos que já testei e vou fazer um import/export: - HeightMap - ItemHelp - *TextureList - MeshList - Trn/Fields ( vai ter uma aba para editar o mapa todo ) - WYS e WYT MSA eu só iniciei, mas pretendo colocar também. Animações eu não toquei. Bem, é isso =) O que for imagem, farei a exportação/importação para diversos formatos. O que for 3D vai ser exportado para obj+mtl+textura Inté+ ( O jogo pode ter morrido, mas farei aos poucos esse editor )1 ponto
Esta tabela de classificação está definida para São Paulo/GMT-03:00
