├── CObfuscateP ├── CApiCore.h ├── CObfuscateP.h ├── README.md ├── look.png └── test.cpp └── CheckAvListProc ├── AVltest.cpp ├── CApiCore.h ├── CAvList.cpp ├── CAvList.h └── README.md /CObfuscateP/CApiCore.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _CC_API_CORE_H_ 3 | #define _CC_API_CORE_H_ 4 | 5 | #define _CCAPI_BEGIN namespace CcApi { 6 | #define _CCAPI_END } 7 | #define _CCAPI ::CcApi:: 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /CObfuscateP/CObfuscateP.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _CC_OBFUSCATE_PLUS_H_ 3 | #define _CC_OBFUSCATE_PLUS_H_ 4 | #include "CApiCore.h" 5 | 6 | // 需要 C++ 14 或以上 7 | // 目前可能用于wchar_t* char*类型的字符串加密 8 | // 将 LINE __用作 /ZI__ 编译时常量时,会发生 C2975。 一种解决方案是使用 /Zi 而不是 /ZI 进行编译。 9 | // 用于混淆字符串的默认64位key。 10 | // 可以通过定义CC_OBFUSCATE_DEFAULT_KEY来自定义指定key 11 | 12 | #define CC_OBFUSCATE_DEFAULT_KEY _CCAPI RandGenerateKey(__LINE__) 13 | 14 | _CCAPI_BEGIN 15 | using SIZET = unsigned long long; 16 | using KEYT = unsigned long long; 17 | 18 | 19 | constexpr KEYT RandGenerateKey(KEYT seed) 20 | { 21 | 22 | KEYT key = seed; 23 | key ^= (key >> 33); 24 | key *= 0xff51afd7ed558ccd; 25 | key ^= (key >> 33); 26 | key *= 0xc4ceb9fe1a85ec53; 27 | key ^= (key >> 33); 28 | 29 | key |= 0x0101010101010101ull; 30 | 31 | return key; 32 | } 33 | 34 | 35 | constexpr void CipherA(char* data, SIZET size, KEYT key) 36 | { 37 | 38 | for (SIZET i = 0; i < size; i++) 39 | { 40 | data[i] ^= char(key >> ((i % 8) * 8)); 41 | } 42 | } 43 | 44 | constexpr void CipherW(wchar_t* data, SIZET size, KEYT key) 45 | { 46 | 47 | for (SIZET i = 0; i < size; i++) 48 | { 49 | data[i] ^= wchar_t(key >> ((i % 8) * 8)); 50 | } 51 | } 52 | 53 | 54 | template 55 | class CObfuscatorA 56 | { 57 | public: 58 | 59 | constexpr CObfuscatorA(const char* data) 60 | { 61 | 62 | for (SIZET i = 0; i < N; i++) 63 | { 64 | m_Data[i] = data[i]; 65 | } 66 | 67 | CipherA(m_Data, N, KEY); 68 | } 69 | 70 | constexpr const char* data() const 71 | { 72 | return &m_Data[0]; 73 | } 74 | 75 | constexpr SIZET size() const 76 | { 77 | return N; 78 | } 79 | 80 | constexpr KEYT key() const 81 | { 82 | return KEY; 83 | } 84 | 85 | private: 86 | 87 | char m_Data[N]{}; 88 | }; 89 | 90 | template 91 | class CObfuscatorW 92 | { 93 | public: 94 | 95 | constexpr CObfuscatorW(const wchar_t* data) 96 | { 97 | for (SIZET i = 0; i < N; i++) 98 | { 99 | m_Data[i] = data[i]; 100 | } 101 | 102 | CipherW(m_Data, N, KEY); 103 | } 104 | 105 | constexpr const wchar_t* data() const 106 | { 107 | return &m_Data[0]; 108 | } 109 | 110 | constexpr SIZET size() const 111 | { 112 | return N; 113 | } 114 | 115 | constexpr KEYT key() const 116 | { 117 | return KEY; 118 | } 119 | 120 | private: 121 | 122 | wchar_t m_Data[N]{}; 123 | }; 124 | 125 | template 126 | class CObfuscatedDataA 127 | { 128 | public: 129 | CObfuscatedDataA(const CObfuscatorA& obA) 130 | { 131 | for (SIZET i = 0; i < N; i++) 132 | { 133 | m_Data[i] = obA.data()[i]; 134 | } 135 | } 136 | 137 | ~CObfuscatedDataA() 138 | { 139 | 140 | for (SIZET i = 0; i < N; i++) 141 | { 142 | m_Data[i] = 0; 143 | } 144 | } 145 | 146 | operator char*() 147 | { 148 | Decrypt(); 149 | return m_Data; 150 | } 151 | 152 | void Decrypt() 153 | { 154 | if (m_isEncrypted) 155 | { 156 | CipherA(m_Data, N, KEY); 157 | m_isEncrypted = false; 158 | } 159 | } 160 | 161 | void Encrypt() 162 | { 163 | if (!m_isEncrypted) 164 | { 165 | CipherA(m_Data, N, KEY); 166 | m_isEncrypted = true; 167 | } 168 | } 169 | 170 | bool IsEncrypted() const 171 | { 172 | return m_isEncrypted; 173 | } 174 | 175 | private: 176 | 177 | char m_Data[N]; 178 | 179 | 180 | bool m_isEncrypted{ true }; 181 | }; 182 | 183 | template 184 | class CObfuscatedDataW 185 | { 186 | public: 187 | CObfuscatedDataW(const CObfuscatorW& obW) 188 | { 189 | for (SIZET i = 0; i < N; i++) 190 | { 191 | m_Data[i] = obW.data()[i]; 192 | } 193 | } 194 | 195 | ~CObfuscatedDataW() 196 | { 197 | for (SIZET i = 0; i < N; i++) 198 | { 199 | m_Data[i] = 0; 200 | } 201 | } 202 | 203 | operator wchar_t*() 204 | { 205 | Decrypt(); 206 | return m_Data; 207 | } 208 | 209 | void Decrypt() 210 | { 211 | if (m_isEncrypted) 212 | { 213 | CipherW(m_Data, N, KEY); 214 | m_isEncrypted = false; 215 | } 216 | } 217 | 218 | void Encrypt() 219 | { 220 | if (!m_isEncrypted) 221 | { 222 | CipherW(m_Data, N, KEY); 223 | m_isEncrypted = true; 224 | } 225 | } 226 | 227 | bool IsEncrypted() const 228 | { 229 | return m_isEncrypted; 230 | } 231 | 232 | private: 233 | 234 | //字符串的本地存储。调用IsEncrypted()来检查是否为 235 | //当前字符串是加密的。 236 | wchar_t m_Data[N]; 237 | 238 | 239 | bool m_isEncrypted{ true }; 240 | }; 241 | 242 | //该函数的存在纯粹是为了提取元素'N'的数量 243 | template 244 | constexpr auto MakeObfuscatorA(const char(&data)[N]) 245 | { 246 | return CObfuscatorA(data); 247 | } 248 | 249 | //该函数的存在纯粹是为了提取元素'N'的数量 250 | template 251 | constexpr auto MakeObfuscatorW(const wchar_t(&wdata)[N]) 252 | { 253 | return CObfuscatorW(wdata); 254 | } 255 | 256 | _CCAPI_END 257 | 258 | // Lambda表达式 259 | // 在编译时混淆字符串'data'并返回一个引用 260 | // CObfuscatedData对象,具有全局生命周期, 261 | // 有函数解密字符串,并且可以隐式转换为char*/wchar_t* 262 | #define CC_OBFUSCATE_KEYA(data, key) \ 263 | []() -> _CCAPI CObfuscatedDataA& { \ 264 | static_assert(sizeof(decltype(key)) == sizeof(_CCAPI KEYT), "key must be a 64 bit unsigned integer"); \ 265 | static_assert((key) >= (1ull << 56), "key must span all 8 bytes"); \ 266 | constexpr auto n = sizeof(data) / sizeof(data[0]); \ 267 | constexpr auto oba = _CCAPI MakeObfuscatorA(data); \ 268 | static auto obaData = _CCAPI CObfuscatedDataA(oba); \ 269 | return obaData; \ 270 | }() 271 | 272 | 273 | // 使用static_assert,可以在编译期发现更多的错误,用编译器来强制保证一些契约, 274 | // 帮助我们改善编译信息的可读性,尤其是用于模板时。 275 | #define CC_OBFUSCATE_KEYW(wdata, key) \ 276 | []() -> _CCAPI CObfuscatedDataW& { \ 277 | static_assert(sizeof(decltype(key)) == sizeof(_CCAPI KEYT), "key must be a 64 bit unsigned integer"); \ 278 | static_assert((key) >= (1ull << 56), "key must span all 8 bytes"); \ 279 | constexpr auto n = sizeof(wdata) / sizeof(wdata[0]); \ 280 | constexpr auto obw = _CCAPI MakeObfuscatorW(wdata); \ 281 | static auto obwData = _CCAPI CObfuscatedDataW(obw); \ 282 | return obwData; \ 283 | }() 284 | 285 | // _DEBUG关闭混淆 286 | #ifdef _DEBUG 287 | #define COSTR_OFF 288 | #endif // _DEBUG 289 | 290 | // 定义COSTR_OFF关闭混淆 291 | #ifdef COSTR_OFF 292 | #define CC_OBFUSCATE_STRINGA(data) data 293 | #define CC_OBFUSCATE_STRINGW(wdata) wdata 294 | 295 | #else 296 | // 返回隐式转换为char*/wchar_t*仅仅在宏所在函数作用域内有效,脱离函数作用域将被释放。 297 | #define CC_OBFUSCATE_STRINGA(data) CC_OBFUSCATE_KEYA(data, CC_OBFUSCATE_DEFAULT_KEY) 298 | #define CC_OBFUSCATE_STRINGW(wdata) CC_OBFUSCATE_KEYW(wdata, CC_OBFUSCATE_DEFAULT_KEY) 299 | 300 | #endif 301 | 302 | // 简化名称长度 303 | #define COSTRA CC_OBFUSCATE_STRINGA 304 | #define COSTRW CC_OBFUSCATE_STRINGW 305 | 306 | #if defined(UNICODE) 307 | #define COSTR COSTRW 308 | #else 309 | #define COSTR COSTRA 310 | #endif 311 | 312 | #endif 313 | -------------------------------------------------------------------------------- /CObfuscateP/README.md: -------------------------------------------------------------------------------- 1 | # 项目作用: 2 | 3 | 编译时混淆字符串,确保编译后的二进制PE不是明文保存的字符串。 4 | 5 | IDA F5反编译对比: 6 | 7 | ![image](https://github.com/Cc28256/ObfuscateP/blob/main/CObfuscateP/look.png) 8 | 9 | # 使用方法: 10 | 11 | 1 项目需要 CApiCore.h和CObfuscateP.h 两个文件 12 | 13 | 2 包含头文件 #include "CObfuscateP.h" 14 | 15 | 3 支持宽字符与窄字符 COSTRA加密const char* 类型 COSTRW加密const wchar_t* 类型 16 | 17 | 示例代码: 18 | 19 | ```c 20 | 21 | auto str1 = COSTRA("hello world!"); 22 | puts(str1); 23 | 24 | char* str2 = COSTRA("test string!"); 25 | printf("%s\r\n", str2); 26 | 27 | wchar_t* str3 = COSTRW(L"test wstring!"); 28 | printf("%ws\r\n", str3); 29 | 30 | ``` 31 | 32 | # 注意事项: 33 | 34 | 1 需要 C++ 14 或以上 35 | 36 | 2 编译报错 C2975 : LINE __用作 /ZI__ 编译时常量时,会发生 C2975。 一种解决方案是使用 /Zi 而不是 /ZI 进行编译。 37 | 38 | 3 随机生成(伪随机)Key加密,可通过定义CC_OBFUSCATE_DEFAULT_KEY来自定义指定key 39 | 40 | 4 COSTR宏定义Lambda表达式 表达式声明了CObfuscatedDataA对象,对象只在宏所在函数作用域有效,离开函数后,对象将被释放。 41 | 42 | 5 DEBUG 模式 或项目定义宏COSTR_OFF将关闭混淆,明文字符串将暴露在编译后的二进制文件中。可根据需求自行修改源码。 43 | 44 | 6 调用包含这段代码的shellcode时,应注意线程TLS问题,当 tls_index 为0时,该混淆仍然不起作用,需要将TLS表中AddressOfIndex指向的地址更改为1(或其他值,这不是确定的)。 45 | 46 | 47 | # 项目参考 48 | 49 | 项目基于开源项目二次更改并添加了const wchar_t* 类型的字符串混淆。 50 | 51 | https://github.com/adamyaxley/Obfuscate 52 | -------------------------------------------------------------------------------- /CObfuscateP/look.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cc28256/ObfuscateP/53609963bce2e3e21c2afd050f6eaf43f5cafa45/CObfuscateP/look.png -------------------------------------------------------------------------------- /CObfuscateP/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "CObfuscateP.h" 4 | 5 | void test() 6 | { 7 | auto str1 = COSTRA("hello world!"); 8 | puts(str1); 9 | 10 | char* str2 = COSTRA("test string!"); 11 | printf("%s\r\n", str2); 12 | 13 | wchar_t* str3 = COSTRW(L"test wstring!"); 14 | printf("%ws\r\n", str3); 15 | 16 | } 17 | 18 | int main() 19 | { 20 | test(); 21 | system("pause"); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /CheckAvListProc/AVltest.cpp: -------------------------------------------------------------------------------- 1 | // AVlist.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 2 | // 3 | 4 | #include 5 | #include "CAvList.h" 6 | 7 | int main() 8 | { 9 | _CCAPI AvList avl; 10 | 11 | if (!avl.Init()){ 12 | printf("AvList error!\r\n"); 13 | return 0; 14 | } 15 | 16 | auto pFn = [](bool b, char * c) {b ? printf(" %s exist!\r\n", c) : printf(" %s not find!\r\n", c); }; 17 | 18 | pFn(avl[EAT::_Kaspersky], "kaky"); 19 | pFn(avl[EAT::_HuoRong], "huro"); 20 | pFn(avl[EAT::_WinDef], "wind"); 21 | pFn(avl[EAT::_360WD], "30WD"); 22 | 23 | system("pause"); 24 | } 25 | 26 | -------------------------------------------------------------------------------- /CheckAvListProc/CApiCore.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef _CC_API_CORE_H_ 3 | #define _CC_API_CORE_H_ 4 | 5 | #define _CCAPI_BEGIN namespace CcApi { 6 | #define _CCAPI_END } 7 | #define _CCAPI ::CcApi:: 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /CheckAvListProc/CAvList.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cc28256/ObfuscateP/53609963bce2e3e21c2afd050f6eaf43f5cafa45/CheckAvListProc/CAvList.cpp -------------------------------------------------------------------------------- /CheckAvListProc/CAvList.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cc28256/ObfuscateP/53609963bce2e3e21c2afd050f6eaf43f5cafa45/CheckAvListProc/CAvList.h -------------------------------------------------------------------------------- /CheckAvListProc/README.md: -------------------------------------------------------------------------------- 1 | # 项目作用: 2 | 3 | 检查工作于当前计算机的杀软或进程 且不会将进程字符串明文暴露。 4 | 5 | 目前仅支持检查: 6 | 7 | 360 8 | QQ电脑管家 9 | 火绒 10 | 诺顿 11 | 赛门铁克 12 | windows def 13 | 卡巴斯基 14 | Avast 15 | 麦咖啡 16 | 趋势 17 | 金山毒霸 18 | eset 19 | 小红伞 20 | 大蜘蛛 21 | 22 | 23 | 24 | 25 | # 使用方法: 26 | 27 | 1 项目需要 CApiCore.h、CAvList.h和CAvList.cpp文件 28 | 29 | 2 包含头文件 #include "CAvList.h" 30 | 31 | 3 根据地定义可在代码中添加想要检查的杀软或进程 32 | 33 | 示例代码: 34 | 35 | ```c 36 | 37 | _CCAPI AvList avl; 38 | 39 | if (!avl.Init()){ 40 | printf("AvList error!\r\n"); 41 | return 0; 42 | } 43 | 44 | auto pFn = [](bool b, char * c) {b ? printf(" %s exist!\r\n", c) : printf(" %s not find!\r\n", c); }; 45 | 46 | pFn(avl[EAT::_Kaspersky], "kaky"); 47 | pFn(avl[EAT::_HuoRong], "huro"); 48 | pFn(avl[EAT::_WinDef], "wind"); 49 | pFn(avl[EAT::_360WD], "30WD"); 50 | 51 | ``` 52 | 53 | # 注意事项: 54 | 55 | 1 constexpr 需要 C++ 14 或以上。 56 | 57 | 2 直接使用 [EAT::XXX] 可以获取对应杀软或进程存在,但使用前尽可能使用Init()来判断流程都正确。 58 | 59 | 3 进程字符串被计算为 unsigned int 类型在编译时期存于二进制文件,因此不会暴露明文。 60 | 61 | 4 可通过在 EnumAvType枚举类型、 CheckAllAvProc函数lAvInfoList变量中添加杀软进程名称。 62 | 63 | 5 可通过在 重载运算符[]中switch块中添加自定义需要单一的进程检查。 64 | 65 | 6 在检查杀软时,只会遍历一次所有进程来确定是否存在,如果想每调用时重新遍历所有进程,那么请在调用前请使用ReviewInit()函数进行更新类数据。 66 | 67 | 7 检查自定义单一进程每次会自动遍历。 68 | 69 | 70 | --------------------------------------------------------------------------------