Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
 Аватар для iDReeM
64 / 68 / 18
Регистрация: 21.10.2015
Сообщений: 228

Адрес конца dll

23.04.2017, 11:42. Показов 2231. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
всем ку. Интересует метод получения адресса конца длл (адреса на котором виртуальная память модуля заканчивается) или же, размер модуля в целом чтобы посчитать начало+размер = конец.

Дилема: имеется игруля.exe, у нее есть защита.dll, защита.dll медленно сканирует виртуальную память процесса в поисках лишнего, на пример указателей на память игруля.exe там, где их быть не должно.

Задача: имеется орава хуков, остановил свое внимание на VirtualQuery,
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//начало модуля
DWORD BaseAddressYouModule = NULL;
//концовка модуля
DWORD EndAddress = NULL;
 
typedef SIZE_T (WINAPI* VirtualQuery_Hide)(_In_opt_ LPCVOID, _Out_writes_bytes_to_(dwLength, return) PMEMORY_BASIC_INFORMATION, _In_ SIZE_T);
VirtualQuery_Hide VirtualQuery_Hook;
 
SIZE_T WINAPI MyVirtualQuery(_In_opt_ LPCVOID lpAddress, _Out_writes_bytes_to_(dwLength, return) PMEMORY_BASIC_INFORMATION lpBuffer, _In_ SIZE_T dwLength) 
{
    DWORD lpAddress_scan = reinterpret_cast<DWORD>(lpAddress);
    DWORD len = reinterpret_cast<DWORD>(dwLength);
 
    //если адресс >= начало модуля && (адресс + размер) <= конец модуля
    //который надо игнорировать.
    if (lpAddress_scan >= BaseAddressYouModule && (lpAddress_scan + len)  <= EndAddress)
    {
        //ставим ошибку неверный аргумент. 
        //Отрицаем всякое существование памяти по указанному адресу
        SetLastError(ERROR_INVALID_PARAMETER);
        //если функция завершается ошибкой - возвращается ноль. 
        return NULL;
    }
    //если нас не касается Возвращаем оригинал
    return VirtualQuery_Hook(lpAddress, lpBuffer, dwLength);
}
необходимо получить хотябы размер модуля, чтобы хук фурыкал как задумано. костыли принимаются.
Благодарю за внимание.
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
23.04.2017, 11:42
Ответы с готовыми решениями:

Задать адрес функции внутри DLL
Подскажите, пожалуйста, как сделать так, чтобы после сборки DLL нужная мне функция всегда была по одному адресу, например, 10001000, если...

Как подгрузить dll в определенный адрес?
ну как все мы знаем при инжекте dll она погружается в адресное пространство которое выделяется приложением а как вот можно реализовать...

Как получить адрес функции в DLL
Я пишу расширение для текстового редактора исходников от которого у меня нет. Суть в том что перед тем сохранить текст в файл он должен...

4
232 / 135 / 19
Регистрация: 10.11.2015
Сообщений: 305
23.04.2017, 13:08
Лучший ответ Сообщение было отмечено iDReeM как решение

Решение

iDReeM, CreateToolhelp32Snapshot(TH32CS_SNAPMODU LE, PID). Поле modBaseSize в структуре MODULEENTRY32 это виртуальный размер.
0
 Аватар для iDReeM
64 / 68 / 18
Регистрация: 21.10.2015
Сообщений: 228
23.04.2017, 13:25  [ТС]
спасибо.
0
232 / 135 / 19
Регистрация: 10.11.2015
Сообщений: 305
23.04.2017, 13:32
Traversing the Module List - пример перечисления модулей
0
 Аватар для iDReeM
64 / 68 / 18
Регистрация: 21.10.2015
Сообщений: 228
23.04.2017, 15:57  [ТС]
я уже вдуплил че и как с процессами и модулями.

если кому пригодится:

cProcess.h
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
#pragma once
#include <windows.h>
#include <vector>
#include <tlhelp32.h>
#include <dwmapi.h>
#include <psapi.h>
#pragma comment(lib, "dwmapi.lib")
#include "cModule.h"
#include "cUtilit.h"
 
#define DEFAULT_ACCESS  PROCESS_VM_READ |PROCESS_VM_WRITE | \
                        PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION
 
 
 
 
class cProcess
{
public:
    cProcess();
    ~cProcess();
    bool                        Attach(const std::string&,DWORD dwFlagAccess = DEFAULT_ACCESS);
    void                        Detach();
    cModule*                    GetModule(const std::string&);
     
    bool                        Read(DWORD_PTR, LPVOID, DWORD);
    template<typename T>  T     Read(DWORD_PTR  dwAddress, const T& Default = T())
    {
        T tRet;
        if (!Read(dwAddress, &tRet, sizeof(T)))
        {
            return Default;
        }
        return tRet;
    }
    
    bool                        Write(DWORD_PTR, LPCVOID, DWORD);
    void                        Write(DWORD_PTR, char*);
    template<typename T>  bool  Write(DWORD_PTR  dwAddress, const T& Value)
    {
        return Write(dwAddress, &Value, sizeof(T));
    }
    
    DWORD_PTR                   Pointer(DWORD_PTR, size_t, ...);
    DWORD_PTR                   Pointer(DWORD_PTR, size_t, DWORD []);
 
    DWORD_PTR                   FindPattern(DWORD_PTR, DWORD, char*, char*);
    DWORD_PTR                   FindPattern(const std::string&, char*, char*);
    DWORD_PTR                   FindPattern(const std::string&, const char*);
    DWORD_PTR                   FindPattern(DWORD_PTR, DWORD, const char*);
 
    HANDLE                      GetHandle() const;
    DWORD                       GetProcId() const;
    std::vector<cModule*>       GetModuleList() const;
    bool                        IsValidHandle() const;
    bool                        valid();
private:
    DWORD                       GetProcessIdByName(const std::string&);
    bool                        DumpModList();
    bool                        DataCompare(const BYTE*, const BYTE*, const char*);
    bool                        DataCompare(const BYTE*, const char*);
    int                         SizeOfArray(char *);
private:
    HANDLE                      m_hProcess = NULL;
    DWORD                       m_dwProcessId = NULL;
    std::vector<cModule*>       m_pModList;
};

cProcess.cpp
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
#include "cProcess.h"
 
 
 
cProcess::cProcess()
{
    cUtilit::Priviledge(); 
}
bool       cProcess::Attach(const std::string& szNameExe,DWORD dwFlagAccess/* = DEFAULT_ACCESS*/)
{
    Detach();
    if (szNameExe.empty())
        return false;
    m_dwProcessId = GetProcessIdByName(szNameExe);
    if (!m_dwProcessId)
        return false;
 
    m_hProcess = OpenProcess(dwFlagAccess, FALSE, m_dwProcessId);
 
    if (!m_hProcess)
        return false;
    return DumpModList();
}
void       cProcess::Detach()
{
    if (m_hProcess)
        CloseHandle(m_hProcess);
 
    m_hProcess = NULL;
    m_dwProcessId = NULL;
 
    if (!m_pModList.empty())
    {
        for (auto& slot : m_pModList)
        {
            delete slot;
            slot = nullptr;
        }
    }
}
 
bool       cProcess::Read(DWORD_PTR  dwAddress, LPVOID lpBuffer, DWORD dwSize)
{
    SIZE_T Out = NULL;
    return (ReadProcessMemory(m_hProcess, (LPCVOID)dwAddress, lpBuffer, dwSize, &Out) == TRUE);
}
bool       cProcess::Write(DWORD_PTR dwAddress, LPCVOID lpBuffer, DWORD dwSize)
{
    SIZE_T Out = NULL;
    return (WriteProcessMemory(m_hProcess, (LPVOID)dwAddress, lpBuffer, dwSize, &Out) == TRUE);
}
void       cProcess::Write(DWORD_PTR dwAddress, char *pBYTE)
{
    __int32 iSize = SizeOfArray(pBYTE);
    for (__int32 i = 0; i < iSize; i++)
        Write<BYTE>(dwAddress + i, pBYTE[i]);
}
 
DWORD_PTR  cProcess::Pointer(DWORD_PTR BaseAddress, size_t numOffsets, ...)
{
    va_list args;
    va_start(args, numOffsets);
    if (!ReadProcessMemory(m_hProcess, (LPCVOID)BaseAddress, &BaseAddress, sizeof(BaseAddress), NULL))
        return 0;
 
    for (size_t i = 0; i < numOffsets; i++)
    {
        DWORD offset = va_arg(args, DWORD);
        if (!ReadProcessMemory(m_hProcess, (LPVOID)(BaseAddress + offset), &BaseAddress, sizeof(BaseAddress), nullptr))
            return 0;
 
    }
    va_end(args);
    return BaseAddress;
}
DWORD_PTR  cProcess::Pointer(DWORD_PTR BaseAddress, size_t numOffsets, DWORD Offsets[])
{
    DWORD pointer = BaseAddress;
    DWORD pTemp;
    DWORD pointerAddr;
    for (size_t i = 0; i < numOffsets; i++)
    {
        if (i == 0)
            ReadProcessMemory(m_hProcess, (LPCVOID)pointer, &pTemp, 4, NULL);
        
        pointerAddr = pTemp + Offsets[i];
        ReadProcessMemory(m_hProcess, (LPCVOID)pointerAddr, &pTemp, 4, NULL);
    }
    return pointerAddr;
}
 
DWORD_PTR  cProcess::FindPattern(DWORD_PTR dwAddress, DWORD size, char* pattern, char* mask)
{
    MEMORY_BASIC_INFORMATION mbi = { 0 };
    DWORD offset = 0;
    while (offset < size)
    {
        VirtualQueryEx(m_hProcess, (LPCVOID)(dwAddress + offset), &mbi, sizeof(MEMORY_BASIC_INFORMATION));
        if (mbi.State != MEM_FREE)
        {
            byte* buffer = new byte[mbi.RegionSize];
            ReadProcessMemory(m_hProcess, mbi.BaseAddress, buffer, mbi.RegionSize, NULL);
            for (size_t i = 0; i < mbi.RegionSize; i++)
            {
                if (DataCompare(buffer + i, (byte*)pattern, mask))
                {
                    delete[] buffer;
                    return (DWORD_PTR)mbi.BaseAddress + i;
                }
            }
            delete[] buffer;
        }
        offset += mbi.RegionSize;
    }
    return 0;
}
DWORD_PTR  cProcess::FindPattern(const std::string& module, char* pattern, char* mask)
{
    return FindPattern(GetModule(module)->GetImage(), GetModule(module)->GetSize(), pattern, mask);
}
DWORD_PTR  cProcess::FindPattern(DWORD_PTR dwAddress, DWORD size, const char* pattern)
{
    MEMORY_BASIC_INFORMATION mbi = { 0 };
    DWORD offset = 0;
    while (offset < size)
    {
        VirtualQueryEx(m_hProcess, (LPCVOID)(dwAddress + offset), &mbi, sizeof(MEMORY_BASIC_INFORMATION));
        if (mbi.State != MEM_FREE)
        {
            byte* buffer = new byte[mbi.RegionSize];
            ReadProcessMemory(m_hProcess, mbi.BaseAddress, buffer, mbi.RegionSize, NULL);
            for (auto i = 0UL; i < mbi.RegionSize; i++)
            {
                auto pb = const_cast<unsigned char*>(buffer + i);
                if (DataCompare(pb, pattern))
                {
                    delete[] buffer;
                    return (DWORD_PTR)mbi.BaseAddress + i;
                }
            }
            delete[] buffer;
        }
        offset += mbi.RegionSize;
    }
    return 0;
}
DWORD_PTR  cProcess::FindPattern(const std::string& module, const char* pattern)
{
    return FindPattern(GetModule(module)->GetImage(), GetModule(module)->GetSize(), pattern);
}
 
 
 bool      cProcess::DumpModList()
{
    HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, m_dwProcessId);
 
    if (hSnapshot == INVALID_HANDLE_VALUE)
        return false;
 
 
    MODULEENTRY32 Entry = { NULL };
 
    Entry.dwSize = sizeof(MODULEENTRY32);
 
    if (!Module32First(hSnapshot, &Entry))
    {
        CloseHandle(hSnapshot);
        return false;
    }
 
    cModule* pMod = nullptr;
 
    do {
        char szPath[MAX_PATH] = { NULL };
 
        GetModuleFileNameEx(m_hProcess, Entry.hModule, szPath, MAX_PATH);
 
        pMod = new cModule((DWORD_PTR)Entry.hModule, (DWORD_PTR)Entry.modBaseSize, Entry.szModule, szPath);
        m_pModList.push_back(pMod);
 
    } while (Module32Next(hSnapshot, &Entry));
    CloseHandle(hSnapshot);
    return !m_pModList.empty();
}
DWORD      cProcess::GetProcessIdByName(const std::string& szNameExe)
{
    HANDLE hSnap;
    DWORD pId = 0;
    PROCESSENTRY32 pe32;
    pe32.dwSize = sizeof(PROCESSENTRY32);
 
    try {
        hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        if (!hSnap) {
            throw std::exception("Could not create process snapshot");
        }
 
        if (!Process32First(hSnap, &pe32)) {
            throw std::exception("Enumerating processes failed");
        }
 
        do {
            if (std::string(pe32.szExeFile) == szNameExe) {
                pId = pe32.th32ProcessID;
                break;
            }
        } while (Process32Next(hSnap, &pe32));
 
        CloseHandle(hSnap);
        return pId;
    }
    catch (std::exception e) {
        CloseHandle(hSnap);
        throw;
    }
}
 
cModule*   cProcess::GetModule(const std::string& ImageName)
{
    if (m_pModList.empty())
        return nullptr;
 
    for (auto& pMod : m_pModList)
    {
        if (ImageName.compare(pMod->GetName()) == 0)
        {
            return pMod;
        }
    }
    return nullptr;
}
HANDLE     cProcess::GetHandle() const
{
    return m_hProcess;
}
DWORD      cProcess::GetProcId() const
{
    return m_dwProcessId;
}
bool       cProcess::IsValidHandle() const
{
    return m_hProcess != INVALID_HANDLE_VALUE;
}
bool       cProcess::valid()
{
    DWORD dwExitCode = 0;
 
    if (!m_hProcess || !GetExitCodeProcess(m_hProcess, &dwExitCode))
        return false;
 
    return (dwExitCode == STILL_ACTIVE);
}
std::vector<cModule*>  cProcess::GetModuleList() const
{
    return m_pModList;
}
 
int  cProcess::SizeOfArray(char *chArray)
{
    for (int iLength = 1; iLength < MAX_PATH; iLength++)
        if (chArray[iLength] == '\0')
            return iLength;
 
 
    return 0;
}
bool cProcess::DataCompare(const BYTE* pData, const BYTE* pattern, const char* mask)
{
    for (; *mask; ++mask, ++pattern, ++pData)
    {
        if (*mask == 'x' && *pData != *pattern)
            return false;
    }
    return true;
}
bool cProcess::DataCompare(const BYTE* pData, const char* pattern)
{
    for (; *pattern; *pattern != ' ' ? ++pData : pData, ++pattern)
    {
        if (*pattern == ' ' || *pattern == '?')
            continue;
        if (*pData != getByte(pattern))
            return false;
        ++pattern;
    }
    return true;
}
 
 
cProcess::~cProcess()
{
}

cModule.h
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <windows.h>
#include <string>
class cModule
{
public:
    cModule(DWORD_PTR, DWORD_PTR, const std::string&, const std::string&);
    ~cModule();
    DWORD_PTR           GetImage() const;
    DWORD_PTR           GetSize() const;
    const std::string&  GetName() const;
    const std::string&  GetPath() const;
    
private:
    DWORD_PTR           m_ImageBase;
    DWORD_PTR           m_ImageSize;
    std::string         m_ImageName;
    std::string         m_ImagePath;
};

cModule.cpp
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include "cModule.h"
 
 
 
cModule::cModule(DWORD_PTR ImageBase, DWORD_PTR ImageSize, const std::string& ImageName, const std::string& ImagePath) 
    : m_ImageBase(ImageBase),
      m_ImageSize(ImageSize),
      m_ImageName(ImageName),
      m_ImagePath(ImagePath)
{
}
DWORD_PTR cModule::GetImage() const
{
    return m_ImageBase;
}
 
DWORD_PTR cModule::GetSize() const
{
    return m_ImageSize;
}
 
const std::string& cModule::GetName() const
{
    return m_ImageName;
}
 
const std::string& cModule::GetPath() const
{
    return m_ImagePath;
}
 
cModule::~cModule()
{
}

мелочи cUtilit.h
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#pragma once
 
typedef std::vector<unsigned char>                      vByte;
 
 
#define INRANGE(x,a,b)      (x >= a && x <= b) 
#define getBits( x )        (INRANGE(x,'0','9') ? (x - '0') : ((x&(~0x20)) - 'A' + 0xa))
#define getByte( x )        (getBits(x[0]) << 4 | getBits(x[1]))
 
#define LAST_STATUS_OFS (0x598 + 0x197 * (sizeof(void*)))
#define STATUS_SUCCESS                   ((NTSTATUS)0x00000000L) 
inline NTSTATUS LastNtStatus()
{
    return *(NTSTATUS*)((unsigned char*)NtCurrentTeb() + LAST_STATUS_OFS);
}
class cUtilit
{
public:
    static NTSTATUS  Priviledge(const std::basic_string<TCHAR>& name = SE_DEBUG_NAME)
    {
        TOKEN_PRIVILEGES Priv, PrivOld;
        DWORD cbPriv = sizeof(PrivOld);
        HANDLE hToken;
 
        if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, FALSE, &hToken))
        {
            if (GetLastError() != ERROR_NO_TOKEN)
                return LastNtStatus();
 
            if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, &hToken))
                return LastNtStatus();
        }
 
        Priv.PrivilegeCount = 1;
        Priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        LookupPrivilegeValue(NULL, name.c_str(), &Priv.Privileges[0].Luid);
 
        if (!AdjustTokenPrivileges(hToken, FALSE, &Priv, sizeof(Priv), &PrivOld, &cbPriv))
        {
            CloseHandle(hToken);
            return LastNtStatus();
        }
 
        if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
        {
            CloseHandle(hToken);
            return LastNtStatus();
        }
 
        return STATUS_SUCCESS;
    }
};
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
23.04.2017, 15:57
Помогаю со студенческими работами здесь

адрес второй с конца буквы R
Найти адрес второй с конца буквы R в массиве с по .

Вычислить адрес верхушки стека, адрес следующей команды, адрес переменной, адрес которой содержится в BX
Помогите решить следующие задачи: 1.Вычислить адрес верхушки стэка. 2.Вычислить адрес следующей выполняемой программы. 3. Вычислить...

Найти адрес начала и конца (для каждой секции), чтобы можно было произвести чтение/запись
в структуре IMAGE_SECTION_HEADER есть такое поле: PointerToRawData, в котором находится RVA начала секции. Но если файл загружается не...

Динамический адрес dll
Пробую написать значит прогу для начала у виде ехе файла, чтобы можно было удобней проверять написанное. Прога должна находить с памяти...

GetProcAddress не может получить адрес ф-ии из dll
Осваиваю написание dll, GetProcAddress не может получить адрес ф-ии из моей dllки? Где может быть засада? В экспоре ф-я вроде должна быть…...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11680&amp;d=1772460536 Одним из. . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru