示例#1
0
static BOOL CALLBACK EnumSymbols(PSYMBOL_INFO SymInfo, ULONG SymbolSize, PVOID UserContext)
{
    SYMBOLINFO curSymbol;
    memset(&curSymbol, 0, sizeof(SYMBOLINFO));

    curSymbol.addr = (duint)SymInfo->Address;
    curSymbol.decoratedSymbol = (char*)BridgeAlloc(strlen(SymInfo->Name) + 1);
    curSymbol.undecoratedSymbol = (char*)BridgeAlloc(MAX_SYM_NAME);
    strcpy_s(curSymbol.decoratedSymbol, strlen(SymInfo->Name) + 1, SymInfo->Name);

    // Skip bad ordinals
    if(strstr(SymInfo->Name, "Ordinal"))
    {
        // Does the symbol point to the module base?
        if(SymInfo->Address == SymInfo->ModBase)
            return TRUE;
    }

    // Convert a mangled/decorated C++ name to a readable format
    if(!SafeUnDecorateSymbolName(SymInfo->Name, curSymbol.undecoratedSymbol, MAX_SYM_NAME, UNDNAME_COMPLETE))
    {
        BridgeFree(curSymbol.undecoratedSymbol);
        curSymbol.undecoratedSymbol = nullptr;
    }
    else if(!strcmp(curSymbol.decoratedSymbol, curSymbol.undecoratedSymbol))
    {
        BridgeFree(curSymbol.undecoratedSymbol);
        curSymbol.undecoratedSymbol = nullptr;
    }

    SYMBOLCBDATA* cbData = (SYMBOLCBDATA*)UserContext;
    cbData->cbSymbolEnum(&curSymbol, cbData->user);
    return TRUE;
}
void DescriptorToCode(SIG_DESCRIPTOR *Descriptor, char **Data, char **Mask)
{
	//
	// Allocate buffers for the resulting strings
	//
	size_t dataSize = Descriptor->Count * strlen("\\x00") + 1;
	size_t maskSize = Descriptor->Count * strlen("x") + 1;

	*Data = (char *)BridgeAlloc(dataSize);
	*Mask = (char *)BridgeAlloc(maskSize);

	for (ULONG i = 0; i < Descriptor->Count; i++)
	{
		if (Descriptor->Entries[i].Wildcard == 0)
		{
			char temp[16];
			sprintf_s(temp, "\\x%02X", (DWORD)Descriptor->Entries[i].Value);

			strcat_s(*Data, dataSize, temp);
			strcat_s(*Mask, maskSize, "x");
		}
		else
		{
			strcat_s(*Data, dataSize, "\\x00");
			strcat_s(*Mask, maskSize, "?");
		}
	}
}
void DescriptorToIDA(SIG_DESCRIPTOR *Descriptor, char **Data)
{
	//
	// Allocate buffers for the resulting strings.
	// Worst case scenario: all are 2 bytes (No wildcards)
	//
	size_t dataSize = Descriptor->Count * strlen("00 ") + 1;
	*Data			= (char *)BridgeAlloc(dataSize);

	for (ULONG i = 0; i < Descriptor->Count; i++)
	{
		if (Descriptor->Entries[i].Wildcard == 0)
		{
			char temp[16];
			sprintf_s(temp, "%02X ", (DWORD)Descriptor->Entries[i].Value);

			strcat_s(*Data, dataSize, temp);
		}
		else
		{
			strcat_s(*Data, dataSize, "? ");
		}
	}

	// Remove the final space
	if (strrchr(*Data, ' '))
		*strrchr(*Data, ' ') = '\0';
}
SIG_DESCRIPTOR *AllocDescriptor(ULONG Count)
{
	ULONG totalSize			= sizeof(SIG_DESCRIPTOR) + (sizeof(SIG_DESCRIPTOR_ENTRY) * Count);
	SIG_DESCRIPTOR *temp	= (SIG_DESCRIPTOR *)BridgeAlloc(totalSize);

	if (temp)
		temp->Count = Count;

	// Return value is gnored; BridgeAlloc will kill the program on failure
	return temp;
}
示例#5
0
FunctionPass::FunctionPass(duint VirtualStart, duint VirtualEnd, BBlockArray & MainBlocks)
    : AnalysisPass(VirtualStart, VirtualEnd, MainBlocks)
{
    // Zero values
    m_FunctionInfo = nullptr;
    m_FunctionInfoSize = 0;

    // This will only be valid if the address range is within a loaded module
    m_ModuleStart = ModBaseFromAddr(VirtualStart);

    if(m_ModuleStart != 0)
    {
        char modulePath[MAX_PATH];
        memset(modulePath, 0, sizeof(modulePath));

        ModPathFromAddr(m_ModuleStart, modulePath, ARRAYSIZE(modulePath));

        HANDLE fileHandle;
        DWORD fileSize;
        HANDLE fileMapHandle;
        ULONG_PTR fileMapVa;
        if(StaticFileLoadW(
                    StringUtils::Utf8ToUtf16(modulePath).c_str(),
                    UE_ACCESS_READ,
                    false,
                    &fileHandle,
                    &fileSize,
                    &fileMapHandle,
                    &fileMapVa))
        {
            // Find a pointer to IMAGE_DIRECTORY_ENTRY_EXCEPTION for later use
            ULONG_PTR virtualOffset = GetPE32DataFromMappedFile(fileMapVa, IMAGE_DIRECTORY_ENTRY_EXCEPTION, UE_SECTIONVIRTUALOFFSET);
            m_FunctionInfoSize = (ULONG)GetPE32DataFromMappedFile(fileMapVa, IMAGE_DIRECTORY_ENTRY_EXCEPTION, UE_SECTIONVIRTUALSIZE);

            // Unload the file
            StaticFileUnloadW(nullptr, false, fileHandle, fileSize, fileMapHandle, fileMapVa);

            // Get a copy of the function table
            if(virtualOffset)
            {
                // Read the table into a buffer
                m_FunctionInfo = BridgeAlloc(m_FunctionInfoSize);

                if(m_FunctionInfo)
                    MemRead(virtualOffset + m_ModuleStart, m_FunctionInfo, m_FunctionInfoSize);
            }
        }
    }
}
示例#6
0
void stackgetcallstack(duint csp, CALLSTACK* callstack)
{
    std::vector<CALLSTACKENTRY> callstackVector;
    stackgetcallstack(csp, callstackVector, true);

    // Convert to a C data structure
    callstack->total = (int)callstackVector.size();

    if(callstack->total > 0)
    {
        callstack->entries = (CALLSTACKENTRY*)BridgeAlloc(callstack->total * sizeof(CALLSTACKENTRY));

        // Copy data directly from the vector
        memcpy(callstack->entries, callstackVector.data(), callstack->total * sizeof(CALLSTACKENTRY));
    }
}
示例#7
0
bool ExHandlerGetInfo(EX_HANDLER_TYPE Type, EX_HANDLER_INFO* Info)
{
    std::vector<duint> handlerEntries;
    if(!ExHandlerGetInfo(Type, handlerEntries))
    {
        Info->count = 0;
        Info->addresses = nullptr;
        return false;
    }

    // Convert vector to C-style array
    Info->count = (int)handlerEntries.size();
    Info->addresses = (duint*)BridgeAlloc(Info->count * sizeof(duint));

    memcpy(Info->addresses, handlerEntries.data(), Info->count * sizeof(duint));
    return true;
}
示例#8
0
static DWORD WINAPI scriptLoadThread(void* filename)
{
    GuiScriptClear();
    GuiScriptEnableHighlighting(true); //enable default script syntax highlighting
    scriptIp = 0;
    std::vector<SCRIPTBP>().swap(scriptbplist); //clear breakpoints
    std::vector<int>().swap(scriptstack); //clear script stack
    bAbort = false;
    if(!scriptcreatelinemap((const char*)filename))
        return 0;
    int lines = (int)linemap.size();
    const char** script = (const char**)BridgeAlloc(lines * sizeof(const char*));
    for(int i = 0; i < lines; i++) //add script lines
        script[i] = linemap.at(i).raw;
    GuiScriptAdd(lines, script);
    scriptIp = scriptinternalstep(0);
    GuiScriptSetIp(scriptIp);
    return 0;
}
示例#9
0
void SymUpdateModuleList()
{
    // Build the vector of modules
    std::vector<SYMBOLMODULEINFO> modList;

    if(!SymGetModuleList(&modList))
    {
        GuiSymbolUpdateModuleList(0, nullptr);
        return;
    }

    // Create a new array to be sent to the GUI thread
    size_t moduleCount = modList.size();
    SYMBOLMODULEINFO* data = (SYMBOLMODULEINFO*)BridgeAlloc(moduleCount * sizeof(SYMBOLMODULEINFO));

    // Direct copy from std::vector data
    memcpy(data, modList.data(), moduleCount * sizeof(SYMBOLMODULEINFO));

    // Send the module data to the GUI for updating
    GuiSymbolUpdateModuleList((int)moduleCount, data);
}
示例#10
0
extern "C" DLL_EXPORT bool _dbg_memmap(MEMMAP* memmap)
{
    SHARED_ACQUIRE(LockMemoryPages);

    int pagecount = (int)memoryPages.size();
    memset(memmap, 0, sizeof(MEMMAP));
    memmap->count = pagecount;
    if(!pagecount)
        return true;

    // Allocate memory that is already zeroed
    memmap->page = (MEMPAGE*)BridgeAlloc(sizeof(MEMPAGE) * pagecount);

    // Copy all elements over
    int i = 0;

    for(auto & itr : memoryPages)
        memcpy(&memmap->page[i++], &itr.second, sizeof(MEMPAGE));

    // Done
    return true;
}
示例#11
0
文件: thread.cpp 项目: V10git/x64dbg
void ThreadGetList(THREADLIST* List)
{
    ASSERT_NONNULL(List);
    SHARED_ACQUIRE(LockThreads);

    //
    // This function converts a C++ std::unordered_map to a C-style THREADLIST[].
    // Also assume BridgeAlloc zeros the returned buffer.
    //
    List->count = (int)threadList.size();
    List->list = nullptr;

    if(List->count <= 0)
        return;

    // Allocate C-style array
    List->list = (THREADALLINFO*)BridgeAlloc(List->count * sizeof(THREADALLINFO));

    // Fill out the list data
    int index = 0;

    for(auto & itr : threadList)
    {
        HANDLE threadHandle = itr.second.Handle;

        // Get the debugger's active thread index
        if(threadHandle == hActiveThread)
            List->CurrentThread = index;

        memcpy(&List->list[index].BasicInfo, &itr.second, sizeof(THREADINFO));

        List->list[index].ThreadCip = GetContextDataEx(threadHandle, UE_CIP);
        List->list[index].SuspendCount = ThreadGetSuspendCount(threadHandle);
        List->list[index].Priority = ThreadGetPriority(threadHandle);
        List->list[index].WaitReason = ThreadGetWaitReason(threadHandle);
        List->list[index].LastError = ThreadGetLastErrorTEB(itr.second.ThreadLocalBase);
        index++;
    }
}
示例#12
0
bool ExHandlerGetInfo(EX_HANDLER_TYPE Type, EX_HANDLER_INFO* Info)
{
    bool ret = false;
    std::vector<duint> handlerEntries;

    switch(Type)
    {
    case EX_HANDLER_SEH:
        ret = ExHandlerGetSEH(handlerEntries);
        break;

    case EX_HANDLER_VEH:
        ret = ExHandlerGetVEH(handlerEntries);
        break;

    case EX_HANDLER_VCH:
        ret = ExHandlerGetVCH(handlerEntries, false);
        break;

    case EX_HANDLER_UNHANDLED:
        ret = ExHandlerGetUnhandled(handlerEntries);
        break;
    }

    // Check if a call failed
    if(!ret)
    {
        Info->count = 0;
        Info->addresses = nullptr;
        return false;
    }

    // Convert vector to C-style array
    Info->count = (int)handlerEntries.size();
    Info->addresses = (duint*)BridgeAlloc(Info->count * sizeof(duint));

    memcpy(Info->addresses, handlerEntries.data(), Info->count * sizeof(duint));
    return false;
}
示例#13
0
BRIDGE_IMPEXP bool BridgeSettingRead(int* errorLine)
{
    if(errorLine)
        *errorLine = 0;
    bool success = false;
    std::string iniData;
    HANDLE hFile = CreateFileW(szIniFile, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
    if(hFile != INVALID_HANDLE_VALUE)
    {
        DWORD fileSize = GetFileSize(hFile, nullptr);
        if(fileSize)
        {
            unsigned char utf8bom[] = { 0xEF, 0xBB, 0xBF };
            char* fileData = (char*)BridgeAlloc(sizeof(utf8bom) + fileSize + 1);
            DWORD read = 0;
            if(ReadFile(hFile, fileData, fileSize, &read, nullptr))
            {
                success = true;
                if(!memcmp(fileData, utf8bom, sizeof(utf8bom)))
                    iniData.assign(fileData + sizeof(utf8bom));
                else
                    iniData.assign(fileData);
            }
            BridgeFree(fileData);
        }
        CloseHandle(hFile);
    }
    if(success)  //if we failed to read the file, the current settings are better than none at all
    {
        EnterCriticalSection(&csIni);
        int errline = 0;
        success = settings.Deserialize(iniData, errline);
        if(errorLine)
            *errorLine = errline;
        LeaveCriticalSection(&csIni);
    }
    return success;
}
void MakeSigDialogExecute(HWND hwndDlg)
{
	int dataLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_SIGMAKE_EDIT1)) + 1;
	int maskLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_SIGMAKE_EDIT2)) + 1;

	char *data = (char *)BridgeAlloc(dataLen);
	char *mask = (char *)BridgeAlloc(maskLen);

	GetWindowText(GetDlgItem(hwndDlg, IDC_SIGMAKE_EDIT1), data, dataLen);
	GetWindowText(GetDlgItem(hwndDlg, IDC_SIGMAKE_EDIT2), mask, maskLen);

	//
	// Convert the string to a code descriptor
	//
	SIG_DESCRIPTOR *desc = nullptr;

	switch (Settings::LastType)
	{
	case SIG_CODE:	desc = DescriptorFromCode(data, mask);	break;
	case SIG_IDA:	desc = DescriptorFromIDA(data);			break;
	case SIG_PEID:	desc = DescriptorFromPEiD(data);		break;
	case SIG_CRC:	desc = DescriptorFromCRC(data);			break;
	}

	//
	// Scan
	//
	std::vector<duint> results;
	PatternScan(desc, results);

	//
	// Log it in the GUI
	//
	GuiReferenceDeleteAllColumns();
	GuiReferenceAddColumn(20, "Address");
	GuiReferenceAddColumn(100, "Disassembly");
	GuiReferenceSetRowCount((int)results.size());
	GuiReferenceSetProgress(0);

	int i = 0;
	for (auto& match : results)
	{
		DISASM_INSTR inst;
		DbgDisasmAt(match, &inst);

		char temp[32];
		sprintf_s(temp, "%p", (PVOID)match);

		GuiReferenceSetCellContent(i, 0, temp);
		GuiReferenceSetCellContent(i++, 1, inst.instruction);
	}

	_plugin_logprintf("Found %d references(s)\n", results.size());
	GuiReferenceSetProgress(100);
	GuiUpdateAllViews();

	//
	// Cleanup
	//
	BridgeFree(data);
	BridgeFree(mask);
	BridgeFree(desc);
}
void MakeSigDialogConvert(HWND hwndDlg, SIGNATURE_TYPE To, SIGNATURE_TYPE From)
{
	//
	// Don't convert if destination and source types are the same
	//
	if (To == From)
		return;

	int dataLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_SIGMAKE_EDIT1)) + 1;
	int maskLen = GetWindowTextLength(GetDlgItem(hwndDlg, IDC_SIGMAKE_EDIT2)) + 1;

	char *data = (char *)BridgeAlloc(dataLen);
	char *mask = (char *)BridgeAlloc(maskLen);

	GetWindowText(GetDlgItem(hwndDlg, IDC_SIGMAKE_EDIT1), data, dataLen);
	GetWindowText(GetDlgItem(hwndDlg, IDC_SIGMAKE_EDIT2), mask, maskLen);

	//
	// Convert string(s) to the incoming raw code descriptor
	//
	SIG_DESCRIPTOR *inDesc = nullptr;

	switch (From)
	{
	case SIG_CODE:	inDesc = DescriptorFromCode(data, mask);	break;
	case SIG_IDA:	inDesc = DescriptorFromIDA(data);			break;
	case SIG_PEID:	inDesc = DescriptorFromPEiD(data);			break;
	case SIG_CRC:	inDesc = DescriptorFromCRC(data);			break;
	}

	//
	// Free temporary allocations
	//
	BridgeFree(data);
	BridgeFree(mask);

	data = nullptr;
	mask = nullptr;

	//
	// Convert raw code to destination strings
	//
	switch (To)
	{
	case SIG_CODE:	DescriptorToCode(inDesc, &data, &mask);	break;
	case SIG_IDA:	DescriptorToIDA(inDesc, &data);			break;
	case SIG_PEID:	DescriptorToPEiD(inDesc, &data);		break;
	case SIG_CRC:	DescriptorToCRC(inDesc, &data, &mask);	break;
	}

	//
	// Update dialog
	//
	SetWindowText(GetDlgItem(hwndDlg, IDC_SIGMAKE_EDIT1), data ? data : "");
	SetWindowText(GetDlgItem(hwndDlg, IDC_SIGMAKE_EDIT2), mask ? mask : "");

	if (data)
		BridgeFree(data);

	if (mask)
		BridgeFree(mask);

	BridgeFree(inDesc);
}
示例#16
0
void stackgetcallstack(uint csp, CALLSTACK* callstack)
{
#if 1
    callstack->total = 0;
    if(!DbgIsDebugging() || csp % sizeof(uint)) //alignment problem
        return;
    if(!MemIsValidReadPtr(csp))
        return;
    std::vector<CALLSTACKENTRY> callstackVector;
    uint stacksize = 0;
    uint stackbase = MemFindBaseAddr(csp, &stacksize, false);
    if(!stackbase) //super-fail (invalid stack address)
        return;
    //walk up the stack
    uint i = csp;
    while(i != stackbase + stacksize)
    {
        uint data = 0;
        MemRead(i, &data, sizeof(uint));
        if(MemIsValidReadPtr(data) && MemIsCodePage(data, false)) //the stack value is a pointer to an executable page
        {
            uint size = 0;
            uint base = MemFindBaseAddr(data, &size);
            uint readStart = data - 16 * 4;
            if(readStart < base)
                readStart = base;
            unsigned char disasmData[256];
            MemRead(readStart, disasmData, sizeof(disasmData));
            uint prev = disasmback(disasmData, 0, sizeof(disasmData), data - readStart, 1);
            uint previousInstr = readStart + prev;
            BASIC_INSTRUCTION_INFO basicinfo;
            bool valid = disasmfast(disasmData + prev, previousInstr, &basicinfo);
            if(valid && basicinfo.call) //call
            {
                CALLSTACKENTRY curEntry;
                memset(&curEntry, 0, sizeof(CALLSTACKENTRY));

                StackEntryFromFrame(&curEntry, i, basicinfo.addr, data);
                callstackVector.push_back(curEntry);
            }
        }
        i += sizeof(uint);
    }
    callstack->total = (int)callstackVector.size();
    if(callstack->total)
    {
        callstack->entries = (CALLSTACKENTRY*)BridgeAlloc(callstack->total * sizeof(CALLSTACKENTRY));
        for(int i = 0; i < callstack->total; i++)
        {
            //CALLSTACKENTRY curEntry;
            //memcpy(&curEntry, &callstackVector.at(i), sizeof(CALLSTACKENTRY));
            //dprintf(fhex":" fhex ":" fhex ":%s\n", curEntry.addr, curEntry.to, curEntry.from, curEntry.comment);
            memcpy(&callstack->entries[i], &callstackVector.at(i), sizeof(CALLSTACKENTRY));
        }
    }
#else
    // Gather context data
    CONTEXT context;
    memset(&context, 0, sizeof(CONTEXT));

    context.ContextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER;

    if(SuspendThread(hActiveThread) == -1)
        return;

    if(!GetThreadContext(hActiveThread, &context))
        return;

    if(ResumeThread(hActiveThread) == -1)
        return;

    // Set up all frame data
    STACKFRAME64 frame;
    ZeroMemory(&frame, sizeof(STACKFRAME64));

#ifdef _M_IX86
    DWORD machineType = IMAGE_FILE_MACHINE_I386;
    frame.AddrPC.Offset = context.Eip;
    frame.AddrPC.Mode = AddrModeFlat;
    frame.AddrFrame.Offset = context.Ebp;
    frame.AddrFrame.Mode = AddrModeFlat;
    frame.AddrStack.Offset = csp;
    frame.AddrStack.Mode = AddrModeFlat;
#elif _M_X64
    DWORD machineType = IMAGE_FILE_MACHINE_AMD64;
    frame.AddrPC.Offset = context.Rip;
    frame.AddrPC.Mode = AddrModeFlat;
    frame.AddrFrame.Offset = context.Rsp;
    frame.AddrFrame.Mode = AddrModeFlat;
    frame.AddrStack.Offset = csp;
    frame.AddrStack.Mode = AddrModeFlat;
#endif

    // Container for each callstack entry
    std::vector<CALLSTACKENTRY> callstackVector;

    while(true)
    {
        if(!StackWalk64(
                    machineType,
                    fdProcessInfo->hProcess,
                    hActiveThread,
                    &frame,
                    &context,
                    StackReadProcessMemoryProc64,
                    SymFunctionTableAccess64,
                    StackGetModuleBaseProc64,
                    StackTranslateAddressProc64))
        {
            // Maybe it failed, maybe we have finished walking the stack
            break;
        }

        if(frame.AddrPC.Offset != 0)
        {
            // Valid frame
            CALLSTACKENTRY entry;
            memset(&entry, 0, sizeof(CALLSTACKENTRY));

            StackEntryFromFrame(&entry, (uint)frame.AddrFrame.Offset, (uint)frame.AddrReturn.Offset, (uint)frame.AddrPC.Offset);
            callstackVector.push_back(entry);
        }
        else
        {
            // Base reached
            break;
        }
    }

    // Convert to a C data structure
    callstack->total = (int)callstackVector.size();

    if(callstack->total > 0)
    {
        callstack->entries = (CALLSTACKENTRY*)BridgeAlloc(callstack->total * sizeof(CALLSTACKENTRY));

        // Copy data directly from the vector
        memcpy(callstack->entries, callstackVector.data(), callstack->total * sizeof(CALLSTACKENTRY));
    }
#endif
}
示例#17
0
extern "C" DLL_EXPORT int _dbg_getbplist(BPXTYPE type, BPMAP* bpmap)
{
    if(!bpmap)
        return 0;
    std::vector<BREAKPOINT> list;
    int bpcount = BpGetList(&list);
    if(bpcount == 0)
    {
        bpmap->count = 0;
        return 0;
    }

    int retcount = 0;
    std::vector<BRIDGEBP> bridgeList;
    BRIDGEBP curBp;
    unsigned short slot = 0;
    for(int i = 0; i < bpcount; i++)
    {
        memset(&curBp, 0, sizeof(BRIDGEBP));
        switch(type)
        {
        case bp_none: //all types
            break;
        case bp_normal: //normal
            if(list[i].type != BPNORMAL)
                continue;
            break;
        case bp_hardware: //hardware
            if(list[i].type != BPHARDWARE)
                continue;
            break;
        case bp_memory: //memory
            if(list[i].type != BPMEMORY)
                continue;
            break;
        default:
            return 0;
        }
        switch(list[i].type)
        {
        case BPNORMAL:
            curBp.type = bp_normal;
            break;
        case BPHARDWARE:
            curBp.type = bp_hardware;
            break;
        case BPMEMORY:
            curBp.type = bp_memory;
            break;
        }
        switch(((DWORD)list[i].titantype) >> 8)
        {
        case UE_DR0:
            slot = 0;
            break;
        case UE_DR1:
            slot = 1;
            break;
        case UE_DR2:
            slot = 2;
            break;
        case UE_DR3:
            slot = 3;
            break;
        }
        curBp.addr = list[i].addr;
        curBp.enabled = list[i].enabled;
        //TODO: fix this
        if(MemIsValidReadPtr(curBp.addr))
            curBp.active = true;
        strcpy_s(curBp.mod, list[i].mod);
        strcpy_s(curBp.name, list[i].name);
        curBp.singleshoot = list[i].singleshoot;
        curBp.slot = slot;
        if(curBp.active)
        {
            bridgeList.push_back(curBp);
            retcount++;
        }
    }
    if(!retcount)
    {
        bpmap->count = retcount;
        return retcount;
    }
    bpmap->count = retcount;
    bpmap->bp = (BRIDGEBP*)BridgeAlloc(sizeof(BRIDGEBP) * retcount);
    for(int i = 0; i < retcount; i++)
        memcpy(&bpmap->bp[i], &bridgeList.at(i), sizeof(BRIDGEBP));
    return retcount;
}