Как на Си получить значения CS ? Для GS / FS есть операторы вида https://learn.microsoft.com/ru-ru/c...dfsdword-readfsqword-readfsword?view=msvc-170 , но для cs такого нет. Я знаю про GetThreadContext, ровно как и про асм вставки, линк асм листинга. Интересно более простое решение, если оно есть конечно.
Привет, M0rg0t! Может быть поможет. У меня x64dbg показывает GS=ES=DS=SS=2Bh CS=33h FS=53h Младшие 2 бита селектора CS = CPL (текущий уровень привилегий) Какую роль играют сегментные регистры в процессах | WASM
M0rg0t как насчет https://learn.microsoft.com/en-us/w...eadsapi/nf-processthreadsapi-getthreadcontext опс, прошу пардону у вас упомянуто уже --- Сообщение объединено, 27 янв 2025 --- Код (C++): int main() { unsigned short cs_value; __asm { mov ax, cs mov cs_value, ax } std::cout << "CS register value: " << std::hex << cs_value << std::endl; return 0; }
Где то рядом ходит функа GetThreadSelectorEntry() из kernel32.dll - можешь в неё заглянуть. А так все Win вроде одинаково выстраивают таблицу GDT, т.е. селекторы всегда одинаковые: Код (Text): 0: kd> dg 0 80 P Si Gr Pr Lo Sel Base Limit Type l ze an es ng Flags ---- ----------------- ----------------- ---------- - -- -- -- -- -------- 0000 00000000`00000000 00000000`00000000 <Reserved> 0 Nb By Np Nl 00000000 0008 00000000`00000000 00000000`00000000 <Reserved> 0 Nb By Np Nl 00000000 0010 00000000`00000000 00000000`00000000 Code RE Ac 0 Nb By P Lo 0000029b 0018 00000000`00000000 00000000`ffffffff Data RW Ac 0 Bg Pg P Nl 00000c93 0020 00000000`00000000 00000000`ffffffff Code RE Ac 3 Bg Pg P Nl 00000cfb 0028 00000000`00000000 00000000`ffffffff Data RW Ac 3 Bg Pg P Nl 00000cf3 0030 00000000`00000000 00000000`00000000 Code RE Ac 3 Nb By P Lo 000002fb 0038 00000000`00000000 00000000`00000000 <Reserved> 0 Nb By Np Nl 00000000 0040 00000000`00b9b000 00000000`00000067 TSS32 Busy 0 Nb By P Nl 0000008b 0048 00000000`0000ffff 00000000`0000f800 <Reserved> 0 Nb By Np Nl 00000000 0050 ffffffff`fffe0000 00000000`00003c00 Data RW Ac 3 Bg By P Nl 000004f3 0058 00000000`00000000 00000000`00000000 <Reserved> 0 Nb By Np Nl 00000000 0060 00000000`00000000 00000000`ffffffff Code RE 0 Bg Pg P Nl 00000c9a 0068 00000000`00000000 00000000`00000000 <Reserved> 0 Nb By Np Nl 00000000 0070 00000000`00000000 00000000`00000000 <Reserved> 0 Nb By Np Nl 00000000 0078 00000000`00000000 00000000`00000000 <Reserved> 0 Nb By Np Nl 00000000 0080 Unable to get descriptor 0: kd>
Да асм вставка плохо, что на х64 нельзя, и приходится добавлять асм файл, в этой [непечатное слово] студии. Поэтому, проще таки взять винапи, избыточно, ну да ладно.
Хард только индекс дескрипторов в GDT, т.е. всегда идёт CS/DS ядра(0), и после них CS/DS юзера(3). на х32 селектор(0) в резерве, на х64 первые два селектора(0,8). вот лог от 32-битной ХР, где в столбце PL указано кольцо защиты - если в нём 3, то нужно добавить эту тройку к значению селектора. Код (Text): kd> dg 0 80 P Si Gr Pr Lo Sel Base Limit Type l ze an es ng Flags ---- -------- -------- ----------- - -- -- -- -- -------- 0000 00000000 00000000 <Reserved> 0 Nb By Np Nl 00000000 0008 00000000 ffffffff Code RE Ac 0 Bg Pg P Nl 00000c9b 0010 00000000 ffffffff Data RW Ac 0 Bg Pg P Nl 00000c93 0018 00000000 ffffffff Code RE Ac 3 Bg Pg P Nl 00000cfb 0020 00000000 ffffffff Data RW Ac 3 Bg Pg P Nl 00000cf3 0028 80042000 000020ab TSS32 Busy 0 Nb By P Nl 0000008b 0030 ffdff000 00001fff Data RW Ac 0 Bg Pg P Nl 00000c93 0038 7ffdf000 00000fff Data RW Ac 3 Bg By P Nl 000004f3 0040 00000400 0000ffff Data RW 3 Nb By P Nl 000000f2 0048 00000000 00000000 <Reserved> 0 Nb By Np Nl 00000000 0050 80551380 00000068 TSS32 Avl 0 Nb By P Nl 00000089 0058 805513e8 00000068 TSS32 Avl 0 Nb By P Nl 00000089 0060 00022f40 0000ffff Data RW Ac 0 Nb By P Nl 00000093 0068 000b8000 00003fff Data RW 0 Nb By P Nl 00000092 0070 ffff7000 000003ff Data RW 0 Nb By P Nl 00000092 0078 80400000 0000ffff Code RE 0 Nb By P Nl 0000009a 0080 80400000 0000ffff Data RW 0 Nb By P Nl 00000092 kd>
Можно сделать не на уровне ISA, тоесть не кодировать инструкции, нп call far, а из скрипта прокинуть фаулт и обработать средствами скрипта ловушку. В контексте будет состояние задачи на момент исключения. Это получится манипуляция только структурами, без всяких idt gdt etc.
? Код (Text): #if defined(_M_X64) || defined(__x86_64__) // 64-bit #define CS_VALUE 0x33 #elif defined(_M_IX86) || defined(__i386__) // 32-bit #define CS_VALUE 0x1b #else #error "Architecture not supported" #endif static inline unsigned short get_cs(void) { #ifdef _MSC_VER // Для Microsoft Visual C++ CONTEXT ctx = {0}; ctx.ContextFlags = CONTEXT_CONTROL; GetThreadContext(GetCurrentThread(), &ctx); return (unsigned short)ctx.SegCs; #else // Для GCC/Clang unsigned short cs; __asm__ __volatile__("mov %%cs, %0" : "=r"(cs)); return cs; #endif }
galenkane Очевидно задача определить режим(cpl), может быть среду(wow)/разрядность(архитектуру в общем), такое нужно только если окружение не известно; если определен мод и можно звать его апи, селекторы читать незачем
? Код (Text): #include <windows.h> static inline int get_execution_mode(void) { // Определяем WOW64 BOOL is_wow64 = FALSE; IsWow64Process(GetCurrentProcess(), &is_wow64); if (is_wow64) { return 1; // WOW64 } #ifdef _WIN64 return 2; // Native 64-bit #else return 0; // Native 32-bit #endif } // Получение CPL через проверку привилегий процесса static inline int get_privilege_level(void) { HANDLE token; if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) { TOKEN_ELEVATION elevation; DWORD size; if (GetTokenInformation(token, TokenElevation, &elevation, sizeof(elevation), &size)) { CloseHandle(token); return elevation.TokenIsElevated ? 0 : 3; } CloseHandle(token); } return 3; // По умолчанию user mode } --- Сообщение объединено, 28 янв 2025 --- вообще https://wasm.in/threads/ischu-antidebag-indi.34964/page-2#post-443095 тут код для cpl был наскок помню
Код (Text): // Получение CPL через проверку привилегий процесса static inline int get_privilege_level(void) { HANDLE token; if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &token)) { cpl это хардверный уровень прав, не осевой. OpenProcessToken() это юзер апи и тащит импорт. В произвольный код такое не всунешь, если слинковать и скопировать дамп, выполнив в ядре к примеру это уронит ось. --- Сообщение объединено, 28 янв 2025 --- galenkane ТС нужно без асм вставок, средствами скрипта. Это врядле возможно, ловушки так нельзя использовать, защита не даст. CS регистр определяет машинный мод(ядерный cs/ss) и саму среду значение селектора. Вообще суть задачи какая ?
Можно вообще их захардкодить, т.к. эти селекторы не меняются. Но если надо в коде и без ассемблера, то на MSVC можно просто набить байтами шелл и положить в исполняемую секцию: Код (C): #include <stdio.h> #pragma code_seg(".shell") __declspec(allocate(".shell")) static const unsigned char s_readCs[] { 0x66, 0x8C, 0xC8, // mov ax, cs 0xC3 // ret }; typedef unsigned short (*ReadCs)(); unsigned short _asm_read_cs() { return ((ReadCs)&s_readCs[0])(); } int main() { printf("0x%X\n", _asm_read_cs()); return 0; } Код ( (Unknown Language)): $ .\app.exe 0x33