Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно. Вам необходимо обновить браузер или попробовать использовать другой.
Shellcode branch has undefined behavior where across compilations it sometimes cant find export address to common calls like "NtQuerySystemInformation". MASM branch works.
всем привет! завёз очень крупную обнову в которой наконец переписал то мясо что было в репозитории, и заодно подвёз новый функционал
список изменений:
[+] Добавлена поддержка компилятора gcc
[+] Добавлена поддержка компилятора clang
[+] Добавлен метод shadowcall, делает то же что и lazy_import
[+] Добавлен класс c_modules_range который позволяет енумерироваться по всем модулям загруженным в процесс
[+] Добавлен класс c_module для получения информации о заранее известном модуле
[+] Добавлен класс c_exports для получения информации о EAT (а конкретнее енумерации экспортов) загруженного в процесс dll модуля
[+] Добавлена структура hash_t хэширующая строки на этапе компиляции с гарантией consteval
[+] Добавлены структуры linux-pe, за что большое спасибо
репозиторию и его контрибьюторам
[+] Добавлена адекватная поддержка x86 архитектуры. к сожалению, но метод syscall будет недоступен, однако вы всё ещё можете юзать остальные классы и методы этой библиотеки
[+] Изменено: shadowsyscall который раньше был дефайном, сейчас является функцией
[+] Изменено: каждая ошибка что ранее обозначалась как #error стала static_assert
[+] Изменено: static_assert на x86 архитектуре триггерится только при вызове .shadowsyscall функции. остальной функционал библиотеки всё ещё остаётся рабочим
[+] Изменено: недо-мапа из прошлого репозитория заменена на std::unordered_map
[-] Удалено: фарш из дефайнов
[-] Удалено: метод .cached_call, каждый вызов теперь по дефолту является кэшированным. для полного отключения кэширования необходимо установить у дефайна SHADOWSYSCALLS_CACHING значение false
int main()
{
shadowcall<HMODULE>( "LoadLibraryA", "user32.dll" );
/// Enumerate every module loaded to current process
///
for ( auto module : shadow::c_modules_range{} )
std::wcout << module->name.to_wstring() << "\n";
/// Find exactly known module loaded to current process
/// "ntdll.dll" doesn't leave string in executable, it
/// being hashed on compile-time with conclusive guarantee
///
auto module = shadow::c_module{ "ntdll.dll" };
/// Enumerate EAT of module
///
for ( auto [export_name, export_address] : shadow::c_exports{ module } )
std::cout << export_name << " : " << export_address << "\n";
/// Enumerate sections of module
///
for ( auto section : module.image()->get_nt_headers()->sections() )
std::cout << section.name.to_string() << "\n";
/// Execute any export at runtime
///
shadowcall<int>( "MessageBoxA", nullptr, "string 1", "string 2", MB_OK );
/// We need to call actually MessageBoxA, but not just MessageBox,
/// because the MessageBox is just a line of code defined by
/// Microsoft, the actual export is MessageBoxA / MessageBoxW.
// MessageBoxA( nullptr, "string 1", "string 2", MB_OK );
/// Execute syscall
///
shadowsyscall<NTSTATUS>( "NtTerminateProcess", reinterpret_cast< HANDLE >( -1 ), -6932 );
/// Find an export address
///
auto export_address = shadow::find_export_address( "NtTerminateProcess" );
// do something with the export
}
всем привет! завёз очень крупную обнову в которой наконец переписал то мясо что было в репозитории, и заодно подвёз новый функционал
список изменений:
[+] Добавлена поддержка компилятора gcc
[+] Добавлена поддержка компилятора clang
[+] Добавлен метод shadowcall, делает то же что и lazy_import
[+] Добавлен класс c_modules_range который позволяет енумерироваться по всем модулям загруженным в процесс
[+] Добавлен класс c_module для получения информации о заранее известном модуле
[+] Добавлен класс c_exports для получения информации о EAT (а конкретнее енумерации экспортов) загруженного в процесс dll модуля
[+] Добавлена структура hash_t хэширующая строки на этапе компиляции с гарантией consteval
[+] Добавлены структуры linux-pe, за что большое спасибо
репозиторию и его контрибьюторам
[+] Добавлена адекватная поддержка x86 архитектуры. к сожалению, но метод syscall будет недоступен, однако вы всё ещё можете юзать остальные классы и методы этой библиотеки
[+] Изменено: shadowsyscall который раньше был дефайном, сейчас является функцией
[+] Изменено: каждая ошибка что ранее обозначалась как #error стала static_assert
[+] Изменено: static_assert на x86 архитектуре триггерится только при вызове .shadowsyscall функции. остальной функционал библиотеки всё ещё остаётся рабочим
[+] Изменено: недо-мапа из прошлого репозитория заменена на std::unordered_map
[-] Удалено: фарш из дефайнов
[-] Удалено: метод .cached_call, каждый вызов теперь по дефолту является кэшированным. для полного отключения кэширования необходимо установить у дефайна SHADOWSYSCALLS_CACHING значение false
int main()
{
shadowcall<HMODULE>( "LoadLibraryA", "user32.dll" );
/// Enumerate every module loaded to current process
///
for ( auto module : shadow::c_modules_range{} )
std::wcout << module->name.to_wstring() << "\n";
/// Find exactly known module loaded to current process
/// "ntdll.dll" doesn't leave string in executable, it
/// being hashed on compile-time with conclusive guarantee
///
auto module = shadow::c_module{ "ntdll.dll" };
/// Enumerate EAT of module
///
for ( auto [export_name, export_address] : shadow::c_exports{ module } )
std::cout << export_name << " : " << export_address << "\n";
/// Enumerate sections of module
///
for ( auto section : module.image()->get_nt_headers()->sections() )
std::cout << section.name.to_string() << "\n";
/// Execute any export at runtime
///
shadowcall<int>( "MessageBoxA", nullptr, "string 1", "string 2", MB_OK );
/// We need to call actually MessageBoxA, but not just MessageBox,
/// because the MessageBox is just a line of code defined by
/// Microsoft, the actual export is MessageBoxA / MessageBoxW.
// MessageBoxA( nullptr, "string 1", "string 2", MB_OK );
/// Execute syscall
///
shadowsyscall<NTSTATUS>( "NtTerminateProcess", reinterpret_cast< HANDLE >( -1 ), -6932 );
/// Find an export address
///
auto export_address = shadow::find_export_address( "NtTerminateProcess" );
// do something with the export
}
[+] Исправлена интерпретация NULL в nullptr, теперь, если параметр функции ожидает указатель, NULL и nullptr будут восприниматься одинаково ( спасибо за объяснение @Debounce )
[+] Исправлены вызовы forwarded функций через shadowcall (HeapAlloc, etc.)
[+] Добавлена возможность вызова shadowcall с указанием модуля, в котором следует искать экспорт (позволяет сильно ускорить поиск)
всем привет! завёз очень крупную обнову в которой наконец переписал то мясо что было в репозитории, и заодно подвёз новый функционал
список изменений:
[+] Добавлена поддержка компилятора gcc
[+] Добавлена поддержка компилятора clang
[+] Добавлен метод shadowcall, делает то же что и lazy_import
[+] Добавлен класс c_modules_range который позволяет енумерироваться по всем модулям загруженным в процесс
[+] Добавлен класс c_module для получения информации о заранее известном модуле
[+] Добавлен класс c_exports для получения информации о EAT (а конкретнее енумерации экспортов) загруженного в процесс dll модуля
[+] Добавлена структура hash_t хэширующая строки на этапе компиляции с гарантией consteval
[+] Добавлены структуры linux-pe, за что большое спасибо
репозиторию и его контрибьюторам
[+] Добавлена адекватная поддержка x86 архитектуры. к сожалению, но метод syscall будет недоступен, однако вы всё ещё можете юзать остальные классы и методы этой библиотеки
[+] Изменено: shadowsyscall который раньше был дефайном, сейчас является функцией
[+] Изменено: каждая ошибка что ранее обозначалась как #error стала static_assert
[+] Изменено: static_assert на x86 архитектуре триггерится только при вызове .shadowsyscall функции. остальной функционал библиотеки всё ещё остаётся рабочим
[+] Изменено: недо-мапа из прошлого репозитория заменена на std::unordered_map
[-] Удалено: фарш из дефайнов
[-] Удалено: метод .cached_call, каждый вызов теперь по дефолту является кэшированным. для полного отключения кэширования необходимо установить у дефайна SHADOWSYSCALLS_CACHING значение false
int main()
{
shadowcall<HMODULE>( "LoadLibraryA", "user32.dll" );
/// Enumerate every module loaded to current process
///
for ( auto module : shadow::c_modules_range{} )
std::wcout << module->name.to_wstring() << "\n";
/// Find exactly known module loaded to current process
/// "ntdll.dll" doesn't leave string in executable, it
/// being hashed on compile-time with conclusive guarantee
///
auto module = shadow::c_module{ "ntdll.dll" };
/// Enumerate EAT of module
///
for ( auto [export_name, export_address] : shadow::c_exports{ module } )
std::cout << export_name << " : " << export_address << "\n";
/// Enumerate sections of module
///
for ( auto section : module.image()->get_nt_headers()->sections() )
std::cout << section.name.to_string() << "\n";
/// Execute any export at runtime
///
shadowcall<int>( "MessageBoxA", nullptr, "string 1", "string 2", MB_OK );
/// We need to call actually MessageBoxA, but not just MessageBox,
/// because the MessageBox is just a line of code defined by
/// Microsoft, the actual export is MessageBoxA / MessageBoxW.
// MessageBoxA( nullptr, "string 1", "string 2", MB_OK );
/// Execute syscall
///
shadowsyscall<NTSTATUS>( "NtTerminateProcess", reinterpret_cast< HANDLE >( -1 ), -6932 );
/// Find an export address
///
auto export_address = shadow::find_export_address( "NtTerminateProcess" );
// do something with the export
}
// If “set_custom_ssn_parser” was called, the handling
// of the syscall index falls entirely on the user.
//
// This function is gonna be called once if caching is enabled.
// If not, function will be called on every syscall
std::optional<uint32_t> custom_ssn_parser( shadow::syscaller<NTSTATUS>& instance, shadow::address_t export_address ) {
if ( !export_address ) {
instance.set_last_error( shadow::errc::ssn_not_found );
return std::nullopt;
}
return *export_address.ptr<std::uint32_t>( 4 );
}
// Pass the function name as a string, it will be converted
// into a number at the compile-time by the hash64_t ctor
void execute_syscall_with_custom_ssn( shadow::hash64_t function_name ) {
shadow::syscaller<NTSTATUS> sc{ function_name };
sc.set_custom_ssn_parser( custom_ssn_parser );
auto current_process = reinterpret_cast<void*>( -1 );
std::uint32_t debug_port{ 0 };
auto [status, err] = sc( current_process, 7, &debug_port, sizeof( uint64_t ), nullptr );
if ( err )
std::cerr << "Syscall error occured: " << *err << '\n';
std::cout << "NtQueryInformationProcess status: " << status << ", debug port is: " << debug_port << "\n";
}
int main() {
execute_syscall_with_custom_ssn( "NtQueryInformationProcess" );
// Return type may not be specified since v1.2
shadowcall( "LoadLibraryA", "user32.dll" );
// When we know where to look for a specified
// export it is better to specify it right away,
// it will speed up the search.
shadowcall( { "MessageBoxA", "user32.dll" }, nullptr, "string 1", "string 2", MB_OK );
// Execute any export at runtime. Since we have ct constructor -
// every string will be converted to uint64_t during compilation time
auto message_box = shadowcall<int>( "MessageBoxA", nullptr, "string 3", "string 4", MB_OK );
// "message_box" variable is treated same as "int"
auto function_result = message_box;
std::wcout << "Result: " << function_result << ", DLL that contains MessageBoxA is: " << message_box.export_location().filepath() << '\n';
auto process = reinterpret_cast<HANDLE>( -1 );
const auto current_process = reinterpret_cast<HANDLE>( -1 );
auto start_routine = []( void* ) -> DWORD {
std::cout << "\nthread started!\n";
return 0;
};
// 1 variant - handle error by return value
// Return type may not be specified since v1.2
auto [status, error] = shadowsyscall( "NtCreateThreadEx", &process, THREAD_ALL_ACCESS, NULL, current_process,
static_cast<LPTHREAD_START_ROUTINE>( start_routine ), 0, FALSE, NULL, NULL, NULL, 0 );
if ( error )
std::cout << "NtCreateThreadEx error occured: " << *error << "\n";
else
std::cout << "NtCreateThreadEx call status: 0x" << std::hex << status << '\n';
// 2 variant - when error handling is not required, get a plain return value
auto simple_status = shadowsyscall( "NtTerminateProcess", reinterpret_cast<HANDLE>( -1 ), -6932 );
return 0;
}
shadowsyscall & shadowcall return type may not be specified since v1.2
Added support for overriding the SSN parser for shadow::syscaller<>. More details can be found in the new example.
Added support for std::ranges for iterators
Added KUSER_SHARED_DATA parser implementation
namespace shadow
Added a handy wrapper above the address, shadow::address_t, allows you to briefly and clearly cast any address in the code.
The syscaller class has been moved from shadow::syscalls to shadow
The importer class has been moved from shadow::syscalls to shadow
Namespace syscalls deleted
Implementations of DLL enumerators and exports moved to namespace detail
Added followed functions:
-- dll( hash64_t name ) - returns characteristics of the specified DLL if it is loaded into the process.
-- current_module() - returns the characteristics of the current .exe file which is the host process.
-- dlls() - returns module enumerator, range-based.
-- dll_exports( hash64_t module_name ) - returns export enumerator, range-based & iterator-based.
-- shared_data() - returns shared_data parser object.
namespace shadow::detail:
class basic_hash
Renamed and redesigned the hash_t class, instead it is now the basic_hash class, whose implementation is now independent of the passed integral type.
The constructor of the basic_hash class is clearly intended only for compile-time strings, the operator() is overloaded to convert strings known only in runtime, same as std::hash
The hash generation algorithm was changed to FNV1-a due to overhead of the previous algorithm
The overridden operator() accepts any array that has bracket access and has a .size() function
class export_enumerator
- The Iterator is now std::range compatible, and falls under the conditions of the std::bidirectional_iterator group
class module_enumerator
The Iterator is now std::range compatible, and falls under the conditions of the std::bidirectional_iterator group
Added method .find_if()
class shared_data
- New class added in v1.2. Description:
shared_data parses kernel_user_shared_data filled by the operating system when the process starts. The structure contains a lot of useful information about the operating system. The class is a high-level wrapper for parsing, which will save you from direct work with raw addresses and can greatly simplify your coding process.
- The following methods have been added:
--.raw(), - Raw pointer to KUSER_SHARED_DATA struct
--.kernel_debugger_present() ,
--.safe_boot_enabled(),
--.boot_id(),
--.physical_pages_num(),
--.system_root(),
--.timezone_id(),
--.timezone_offset(),
--.system(), - returns operation_system that is listed below
--.windows_epoch_timestamp(),
--.unix_epoch_timestamp() - returns zoned_time that is listed below
class zoned_time
- New class added in v1.2.
--.utc(), - returns time_formatter in UTC timezone
--.local(), - returns time_formatter in local system timezone
class time_formatter
- New class added in v1.2.
--.format_european(), - "dd.mm.yyyy hh:mm"
--.format_american(), - "mm/dd/yyyy hh:mm"
--.format_iso8601(), - "yyyy-mm-ddThh:mm:ss"
--.time_since_epoch(), - Raw unix timestamp as integral
class operation_system
- New class added in v1.2.
--.safe_boot_enabled(),
--.is_windows_11(),
--.is_windows_10(),
--.is_windows_8_1(),
--.is_windows_8(),
--.is_windows_7(),
--.is_windows_xp(),
--.is_windows_vista(),
--.major_version(),
--.minor_version(),
--.build_number(),
--.formatted() - returns "Windows {}.{} (Build {})" via std::format
class dynamic_link_library
- The following methods have been added:
--.raw(), - Raw pointer to Win32 struct
--.base_address(), - Base address of current DLL
--.native_handle(), - Pointer on base address of current
--.entry_point(), - Address of entrypoint
--.name(), - Name of current DLL as std::wstring_view
--.filepath(), - Filepath to current DLL as std::wstring_view
--.exports() - Exports range-enumerator of current DLL
// If “set_custom_ssn_parser” was called, the handling
// of the syscall index falls entirely on the user.
//
// This function is gonna be called once if caching is enabled.
// If not, function will be called on every syscall
std::optional<uint32_t> custom_ssn_parser( shadow::syscaller<NTSTATUS>& instance, shadow::address_t export_address ) {
if ( !export_address ) {
instance.set_last_error( shadow::errc::ssn_not_found );
return std::nullopt;
}
return *export_address.ptr<std::uint32_t>( 4 );
}
// Pass the function name as a string, it will be converted
// into a number at the compile-time by the hash64_t ctor
void execute_syscall_with_custom_ssn( shadow::hash64_t function_name ) {
shadow::syscaller<NTSTATUS> sc{ function_name };
sc.set_custom_ssn_parser( custom_ssn_parser );
auto current_process = reinterpret_cast<void*>( -1 );
std::uint32_t debug_port{ 0 };
auto [status, err] = sc( current_process, 7, &debug_port, sizeof( uint64_t ), nullptr );
if ( err )
std::cerr << "Syscall error occured: " << *err << '\n';
std::cout << "NtQueryInformationProcess status: " << status << ", debug port is: " << debug_port << "\n";
}
int main() {
execute_syscall_with_custom_ssn( "NtQueryInformationProcess" );
// Return type may not be specified since v1.2
shadowcall( "LoadLibraryA", "user32.dll" );
// When we know where to look for a specified
// export it is better to specify it right away,
// it will speed up the search.
shadowcall( { "MessageBoxA", "user32.dll" }, nullptr, "string 1", "string 2", MB_OK );
// Execute any export at runtime. Since we have ct constructor -
// every string will be converted to uint64_t during compilation time
auto message_box = shadowcall<int>( "MessageBoxA", nullptr, "string 3", "string 4", MB_OK );
// "message_box" variable is treated same as "int"
auto function_result = message_box;
std::wcout << "Result: " << function_result << ", DLL that contains MessageBoxA is: " << message_box.export_location().filepath() << '\n';
auto process = reinterpret_cast<HANDLE>( -1 );
const auto current_process = reinterpret_cast<HANDLE>( -1 );
auto start_routine = []( void* ) -> DWORD {
std::cout << "\nthread started!\n";
return 0;
};
// 1 variant - handle error by return value
// Return type may not be specified since v1.2
auto [status, error] = shadowsyscall( "NtCreateThreadEx", &process, THREAD_ALL_ACCESS, NULL, current_process,
static_cast<LPTHREAD_START_ROUTINE>( start_routine ), 0, FALSE, NULL, NULL, NULL, 0 );
if ( error )
std::cout << "NtCreateThreadEx error occured: " << *error << "\n";
else
std::cout << "NtCreateThreadEx call status: 0x" << std::hex << status << '\n';
// 2 variant - when error handling is not required, get a plain return value
auto simple_status = shadowsyscall( "NtTerminateProcess", reinterpret_cast<HANDLE>( -1 ), -6932 );
return 0;
}
shadowsyscall & shadowcall return type may not be specified since v1.2
Added support for overriding the SSN parser for shadow::syscaller<>. More details can be found in the new example.
Added support for std::ranges for iterators
Added KUSER_SHARED_DATA parser implementation
namespace shadow
Added a handy wrapper above the address, shadow::address_t, allows you to briefly and clearly cast any address in the code.
The syscaller class has been moved from shadow::syscalls to shadow
The importer class has been moved from shadow::syscalls to shadow
Namespace syscalls deleted
Implementations of DLL enumerators and exports moved to namespace detail
Added followed functions:
-- dll( hash64_t name ) - returns characteristics of the specified DLL if it is loaded into the process.
-- current_module() - returns the characteristics of the current .exe file which is the host process.
-- dlls() - returns module enumerator, range-based.
-- dll_exports( hash64_t module_name ) - returns export enumerator, range-based & iterator-based.
-- shared_data() - returns shared_data parser object.
namespace shadow::detail:
class basic_hash
Renamed and redesigned the hash_t class, instead it is now the basic_hash class, whose implementation is now independent of the passed integral type.
The constructor of the basic_hash class is clearly intended only for compile-time strings, the operator() is overloaded to convert strings known only in runtime, same as std::hash
The hash generation algorithm was changed to FNV1-a due to overhead of the previous algorithm
The overridden operator() accepts any array that has bracket access and has a .size() function
class export_enumerator
- The Iterator is now std::range compatible, and falls under the conditions of the std::bidirectional_iterator group
class module_enumerator
The Iterator is now std::range compatible, and falls under the conditions of the std::bidirectional_iterator group
Added method .find_if()
class shared_data
- New class added in v1.2. Description:
shared_data parses kernel_user_shared_data filled by the operating system when the process starts. The structure contains a lot of useful information about the operating system. The class is a high-level wrapper for parsing, which will save you from direct work with raw addresses and can greatly simplify your coding process.
- The following methods have been added:
--.raw(), - Raw pointer to KUSER_SHARED_DATA struct
--.kernel_debugger_present() ,
--.safe_boot_enabled(),
--.boot_id(),
--.physical_pages_num(),
--.system_root(),
--.timezone_id(),
--.timezone_offset(),
--.system(), - returns operation_system that is listed below
--.windows_epoch_timestamp(),
--.unix_epoch_timestamp() - returns zoned_time that is listed below
class zoned_time
- New class added in v1.2.
--.utc(), - returns time_formatter in UTC timezone
--.local(), - returns time_formatter in local system timezone
class time_formatter
- New class added in v1.2.
--.format_european(), - "dd.mm.yyyy hh:mm"
--.format_american(), - "mm/dd/yyyy hh:mm"
--.format_iso8601(), - "yyyy-mm-ddThh:mm:ss"
--.time_since_epoch(), - Raw unix timestamp as integral
class operation_system
- New class added in v1.2.
--.safe_boot_enabled(),
--.is_windows_11(),
--.is_windows_10(),
--.is_windows_8_1(),
--.is_windows_8(),
--.is_windows_7(),
--.is_windows_xp(),
--.is_windows_vista(),
--.major_version(),
--.minor_version(),
--.build_number(),
--.formatted() - returns "Windows {}.{} (Build {})" via std::format
class dynamic_link_library
- The following methods have been added:
--.raw(), - Raw pointer to Win32 struct
--.base_address(), - Base address of current DLL
--.native_handle(), - Pointer on base address of current
--.entry_point(), - Address of entrypoint
--.name(), - Name of current DLL as std::wstring_view
--.filepath(), - Filepath to current DLL as std::wstring_view
--.exports() - Exports range-enumerator of current DLL
as a side note: нет необходимости в x86/x64 optional header'ах как public api, если ты можешь предоставлять "Unified Optional Header™" с уже распаршенными полями в (например) серии uint64_t. на один ебучий генерик меньше, в разы проще использовать опшнл хедер.
class detail::memory_checksum
- Добавлены методы:
-- .compute<IntegralTy>(), - Вычисляет чексумму указанной области памяти (basically +=) используя SSE2 интринсики, не итерируя каждый байт области памяти по отдельности, а "пакуя" по 16 байт за итерацию в __m128i и собирая оставшийся "хвост" байтов если такой имеется
C++:
// Benched using 2MB span
[MSVC]
BM_SumBytesBasic 792456 ns 802176 ns // += every byte of span
BM_SumBytesSSE 85171 ns 85794 ns
[CLANG]
BM_SumBytesBasic 381638 ns 383650 ns // += every byte of span
BM_SumBytesSSE 98902 ns 97656 ns
class detail::dynamic_link_library
- Добавлены методы:
-- .section_checksum( hash32_t name ), - Вычисляет контрольную сумму указанной секции
class win::unicode_string
- Добавлены методы:
-- .as<Ty>(), - Преобразование указателя wchar_t в указанный Ty, если существует такой конструктор
-- .to_path(), - Преобразование содержимого в std::filesystem::path
-- .view(), - Возвращает буфер в виде std::wstring_view
-- .string(), - Возвращает указатель wchar_t в виде std::string
-- .data(), - Возвращает сырой указатель wchar_t на данные
в остальном то тут то там поправил некоторые моменты, по мелочи
note:
немного не понравилось как была реализована конвертация wstring to string в win::unicode_string, долго искал различные методы конвертации от стандарта, но сишный wcstombs_s зависит от локали, а codecvt устарел в 17 и будет удален в 26 стандарте. была идея самому реализовать конвертацию, но есть толстое ощущение что подобное в библиотеку не впишется от слова совсем
added CPU instruction-set & CPU cache parser
upd: я не уверен по поводу отличий в парсинге кэшей для AMD, если есть знатоки в этом вопросе то буду рад хорошему PR. поэтому пока что закрыл возможность парсинга кэшей для AMD
added CPU instruction-set & CPU cache parser
upd: я не уверен по поводу отличий в парсинге кэшей для AMD, если есть знатоки в этом вопросе то буду рад хорошему PR. поэтому пока что закрыл возможность парсинга кэшей для AMD