bool CTSProcessor::LoadModule(LPCWSTR pszName) { if (m_pFilterModule == nullptr) { SetError(E_NOTIMPL, TEXT("モジュールは利用できません。")); return false; } if (IsModuleLoaded()) { if (IsStringEmpty(pszName)) { if (m_ModuleName.empty()) return true; } else { if (IsEqualFileName(m_ModuleName.c_str(), pszName)) return true; } } UnloadModule(); if (FAILED(m_pFilterModule->LoadModule(pszName))) return false; StringUtility::Assign(m_ModuleName, pszName); ClearError(); return true; }
Bool ModuleManager::LoadModule( const Char* pModuleName, const Char* pModuleDir ) { GD_ASSERT(pModuleName); GD_ASSERT(pModuleDir); Char fullPath[260]; if( IsModuleLoaded(pModuleName) ) return true; strcpy(fullPath, pModuleDir); strcat(fullPath, pModuleName); Handle libHandle = Core::OpenLibrary( fullPath ); if( !libHandle ) throw ModuleNotFoundException( pModuleName, Here ); Module* module = const_cast<Module*>(FindModule(pModuleName)); if( !module ) throw ModuleNotRegisteredException( pModuleName, Here ); module->mHandle = libHandle; module->mDynamicLoad = true; return true; }
int wmain(int argc, wchar_t *argv[]) { BOOL fLoaded = FALSE; // 将 locale 设置为默认, 以支持输出中文. setlocale(LC_ALL, ""); // .NET程序集名 PCWSTR pszModuleName = L"CSClassLibrary"; // 检察模块是否被加载. fLoaded = IsModuleLoaded(pszModuleName); wprintf(L"模块 \"%s\" %s被加载\n", pszModuleName, fLoaded ? L"" : L"没有"); // // 在.NET程序集中引用公共类。 // // 通过C++/CLI封装类CSSimpleObjectWrapper,调用.NET类CSSimpleObject CSSimpleObjectWrapper obj; obj.set_FloatProperty(1.2F); float fProp = obj.get_FloatProperty(); wprintf(L"Class: CSSimpleObject::FloatProperty = %.2f\n", fProp); wchar_t szStr[100]; HRESULT hr = obj.ToString(szStr, ARRAYSIZE(szStr)); if (SUCCEEDED(hr)) { wprintf(L"Class: CSSimpleObject::ToString => \"%s\"\n", szStr); } else { wprintf(L"CSSimpleObject::ToString 失败 w/hr 0x%08lx\n", hr); } // 你不能卸载.NET程序集 // 检查是否加载该模块 fLoaded = IsModuleLoaded(pszModuleName); wprintf(L"模块 \"%s\" %s被加载\n", pszModuleName, fLoaded ? L"" : L"没有"); return 0; }
Bool ModuleManager::UnregisterModule( Module* pModule ) { GD_ASSERT(pModule); if( !IsModuleLoaded(pModule->GetName()) ) return false; mModules.RemoveElement(*pModule); return true; }
/////////////////////////////////////////////////////////////////////////////// // RegisterModule Bool ModuleManager::RegisterModule( Module* pModule ) { GD_ASSERT(pModule); if( IsModuleLoaded(pModule->GetName()) ) return false; mModules.AddTail(*pModule); return true; }
BOOL CR_ModuleEx::DisAsm64() { if (!IsModuleLoaded() || !Is64Bit()) return FALSE; _CreateInfo64(); if (Info64()->Entrances().empty()) { _PrepareForDisAsm64(); } // disasm entrances bool needs_retry; do { // NOTE: Info64()->Entrances() may grow in _DisAsmAddr64 needs_retry = false; CR_Addr64Set addrs = Info64()->Entrances(); for (auto addr : addrs) { // check func stage auto stage = Info64()->GetFuncStage(addr); if (stage > 0) { continue; } needs_retry = true; _DisAsmAddr64(addr, addr); // get code func auto cf = Info64()->CodeFuncFromAddr(addr); assert(cf); // recurse all jumpees // NOTE: cf->Jumpees() may grow in _DisAsmAddr64 CR_Addr64Set jumpees; do { jumpees = cf->Jumpees(); for (auto jumpee : jumpees) { _DisAsmAddr64(addr, jumpee); } } while (jumpees.size() < cf->Jumpees().size()); } } while (needs_retry); return TRUE; } // CR_ModuleEx::DisAsm64
void CR_Module::DumpHeaders() { if (!IsModuleLoaded()) return; #ifdef _UNICODE printf("FileName: %ls, FileSize: 0x%08lX (%lu)\n", GetFileName(), GetFileSize(), GetFileSize()); #else printf("FileName: %s, FileSize: 0x%08lX (%lu)\n", GetFileName(), GetFileSize(), GetFileSize()); #endif if (DOSHeader()) { CrDumpDOSHeader(DOSHeader()); } if (FileHeader()) { CrDumpFileHeader(FileHeader()); } if (OptionalHeader32()) { CrDumpOptionalHeader32(OptionalHeader32(), CheckSum()); } else if (OptionalHeader64()) { CrDumpOptionalHeader64(OptionalHeader64(), CheckSum()); } if (SectionHeaders()) { DWORD size = NumberOfSections(); for (DWORD i = 0; i < size; ++i) { printf("\n### Section #%lu ###\n", i); CrDumpSectionHeader(SectionHeader(i)); } } }
BOOL CR_ModuleEx::_PrepareForDisAsm32() { if (!IsModuleLoaded() || !Is32Bit()) return FALSE; _CreateInfo32(); if (Info32()->Entrances().size()) { return TRUE; } // register entrances auto RVA = RVAOfEntryPoint(); CR_Addr32 va = VA32FromRVA(RVA); Info32()->Entrances().emplace(va); { auto codefunc = make_shared<CR_CodeFunc32>(); codefunc->Addr() = va; codefunc->Name() = "EntryPoint"; codefunc->StackArgSizeRange().Set(0); codefunc->FuncFlags() |= cr_FF_CDECL; Info32()->MapAddrToCodeFunc().emplace(va, codefunc); MapRVAToFuncName().emplace(RVA, codefunc->Name()); MapFuncNameToRVA().emplace(codefunc->Name(), RVA); } // exporting functions are entrances for (auto& e_symbol : ExportSymbols()) { va = VA32FromRVA(e_symbol.dwRVA); if (!AddressInCode32(va)) { continue; } Info32()->Entrances().emplace(va); MapRVAToFuncName().emplace(e_symbol.dwRVA, e_symbol.pszName); MapFuncNameToRVA().emplace(e_symbol.pszName, e_symbol.dwRVA); } return TRUE; } // CR_ModuleEx::_PrepareForDisAsm32
BOOL CR_ModuleEx::_DisAsmAddr64(CR_Addr64 func, CR_Addr64 va) { if (!IsModuleLoaded() || !Is64Bit()) return FALSE; // calculate int len; char outbuf[256]; CR_Addr64 addr; // add or retrieve the code function auto cf = Info64()->CodeFuncFromAddr(func); if (cf == NULL) { Info64()->MapAddrToCodeFunc().emplace(func, make_shared<CR_CodeFunc64>()); cf = Info64()->CodeFuncFromAddr(func); } assert(cf); if (func == va) { cf->Addr() = func; } auto pCode = CodeSectionHeader(); assert(pCode); DWORD rva = RVAFromVA64(va); LPBYTE input = m_pLoadedImage + rva; LPBYTE iend = m_pLoadedImage + pCode->RVA + pCode->SizeOfRawData; while (input < iend) { // add or retrieve op.code auto oc = Info64()->OpCodeFromAddr(va); if (oc == NULL) { Info64()->MapAddrToOpCode().emplace(va, make_shared<CR_OpCode64>()); oc = Info64()->OpCodeFromAddr(va); // set op.code address oc->Addr() = va; } assert(oc); if (oc->FuncAddrs().count(func) > 0) break; // add function address for this op.code oc->FuncAddrs().emplace(func); if (oc->FuncAddrs().size() > 1) { cf->FuncFlags() |= cr_FF_FUNCINFUNC; // function in function } if (oc->Codes().empty()) { // disassemble len = disasm(input, outbuf, sizeof(outbuf), 64, va, false, 0); // parse insn if (!len || input + len > iend) { len = 1; oc->Name() = "???"; oc->OpCodeType() = cr_OCT_UNKNOWN; // don't decompile if any unknown instruction. cf->FuncFlags() |= cr_FF_INVALID; } else { oc->Parse(outbuf); } // complement operand size oc->DeductOperandSizes(); // add asm codes to op.code oc->Codes().insert(oc->Codes().end(), input, &input[len]); } else { len = int(oc->Codes().size()); } BOOL bBreak = FALSE; switch (oc->OpCodeType()) { case cr_OCT_JCC: // conditional jump switch (oc->Operand(0)->GetOperandType()) { case cr_DF_IMM: addr = oc->Operand(0)->Value64(); cf->Jumpers().emplace(va); cf->Jumpees().emplace(addr); break; default: break; } break; case cr_OCT_JMP: // jump switch (oc->Operand(0)->GetOperandType()) { case cr_DF_IMM: if (func == va) { // func is jumper cf->FuncFlags() |= cr_FF_JUMPERFUNC; addr = oc->Operand(0)->Value64(); Info64()->Entrances().emplace(addr); cf->Callers().emplace(addr); auto newcf = Info64()->CodeFuncFromAddr(addr); if (newcf == NULL) { Info64()->MapAddrToCodeFunc().emplace( addr, make_shared<CR_CodeFunc64>()); newcf = Info64()->CodeFuncFromAddr(addr); } newcf->Addr() = addr; newcf->Callees().emplace(func); } else { addr = oc->Operand(0)->Value64(); cf->Jumpers().emplace(va); cf->Jumpees().emplace(addr); } break; case cr_DF_MEMIMM: if (func == va) { // func is jumper cf->FuncFlags() |= cr_FF_JUMPERFUNC; bBreak = TRUE; } break; default: break; } bBreak = TRUE; break; case cr_OCT_CALL: // call switch (oc->Operand(0)->GetOperandType()) { case cr_DF_IMM: // function call addr = oc->Operand(0)->Value64(); Info64()->Entrances().emplace(addr); cf->Callees().emplace(addr); { auto newcf = Info64()->CodeFuncFromAddr(addr); if (newcf == NULL) { Info64()->MapAddrToCodeFunc().emplace( addr, make_shared<CR_CodeFunc64>()); newcf = Info64()->CodeFuncFromAddr(addr); } newcf->Addr() = addr; newcf->Callers().emplace(func); } break; default: break; } break; case cr_OCT_RETURN: // return if (oc->Operands().size() && oc->Operand(0)->GetOperandType() == cr_DF_IMM) { cf->StackArgSizeRange().Set(oc->Operand(0)->Value64()); } else { if (func == va) { cf->FuncFlags() |= cr_FF_RETURNONLY; } } cf->Exits().insert(va); bBreak = TRUE; break; default: break; } if (bBreak) break; // move to next position input += len; va += len; } return TRUE; } // CR_ModuleEx::_DisAsmAddr64
BOOL CALLBACK OpenModuleDialogProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) { traceIn(OpenModuleDialogProc); switch(message) { case WM_INITDIALOG: { OSFindData findData; //todo: AppWarning(TEXT("fix this thingy please")); HANDLE hFind = OSFindFirstFile(TEXT("*.xxt"), findData); if(hFind) { do { findData.fileName[slen(findData.fileName)-4] = 0; if(!IsModuleLoaded(findData.fileName)) SendMessage(GetDlgItem(hwnd, IDC_MODULELIST), LB_ADDSTRING, 0, (LPARAM)findData.fileName); }while(OSFindNextFile(hFind, findData)); OSFindClose(hFind); SendMessage(GetDlgItem(hwnd, IDC_MODULELIST), LB_SETCURSEL, 0, 0); SendMessage(GetDlgItem(hwnd, IDC_MODULELIST), EM_LIMITTEXT, 250, 0); } break; } case WM_COMMAND: switch(LOWORD(wParam)) { case IDC_MODULELIST: if(HIWORD(wParam) == LBN_DBLCLK) PostMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDOK, BN_CLICKED), lParam); break; case IDOK: { DWORD dwCurSel = SendMessage(GetDlgItem(hwnd, IDC_MODULELIST), LB_GETCURSEL, 0, 0); if(dwCurSel != LB_ERR) { String strModuleName; strModuleName.SetLength(255); SendMessage(GetDlgItem(hwnd, IDC_MODULELIST), LB_GETTEXT, dwCurSel, (LPARAM)(CTSTR)strModuleName); if(!level->LoadLevelModule(strModuleName)) MessageBox(hwnd, String() << TEXT("Unable to open module '") << strModuleName << TEXT("'."), NULL, MB_OK); else { EndDialog(hwnd, IDOK); UpdateObjectTreeAndModules(); } } else MessageBox(hwnd, TEXT("You need to select a module first"), NULL, MB_OK); break; } case IDCANCEL: EndDialog(hwnd, IDCANCEL); break; } break; case WM_CLOSE: EndDialog(hwnd, IDCANCEL); break; } return FALSE; traceOut; }
bool CTSProcessor::GetModuleInfo(LPCWSTR pszModule, ModuleInfo *pInfo) const { if (pInfo == nullptr) return false; pInfo->DeviceList.clear(); Interface::IFilterModule *pModule = nullptr; if (IsModuleLoaded()) { if (IsStringEmpty(pszModule)) { if (m_ModuleName.empty()) pModule = m_pFilterModule; } else { if (IsEqualFileName(m_ModuleName.c_str(), pszModule)) pModule = m_pFilterModule; } } if (pModule == nullptr) { if (m_pFilterManager == nullptr) return false; if (FAILED(m_pFilterManager->CreateModule(&pModule))) return false; if (FAILED(pModule->LoadModule(pszModule))) { pModule->Release(); return false; } } HRESULT hr; int DeviceCount; hr = pModule->GetDeviceCount(&DeviceCount); if (SUCCEEDED(hr)) { for (int i = 0; i < DeviceCount; i++) { Interface::IFilterDevice *pDevice; hr = pModule->GetDevice(i, &pDevice); if (SUCCEEDED(hr)) { Interface::FilterDeviceInfo DeviceInfo; hr = pDevice->GetDeviceInfo(&DeviceInfo); if (SUCCEEDED(hr)) { ModuleDeviceInfo Info; Info.DeviceID = DeviceInfo.DeviceID; Info.Flags = DeviceInfo.Flags; Info.Name = DeviceInfo.Name; Info.Text = DeviceInfo.Text; ::SysFreeString(DeviceInfo.Name); ::SysFreeString(DeviceInfo.Text); int FilterCount; hr = pDevice->GetFilterCount(&FilterCount); if (SUCCEEDED(hr)) { for (int j = 0; j < FilterCount; j++) { BSTR Name; hr = pDevice->GetFilterName(j, &Name); if (FAILED(hr)) break; Info.FilterList.push_back(String(Name)); ::SysFreeString(Name); } } pInfo->DeviceList.push_back(Info); } pDevice->Release(); } if (FAILED(hr)) { pInfo->DeviceList.clear(); break; } } } if (pModule != m_pFilterModule) { pModule->UnloadModule(); pModule->Release(); } return SUCCEEDED(hr); }