• XSS.stack #1 – первый литературный журнал от юзеров форума

Как обмануть декомпилятор\дизассемблер иды?

D3buG

RAID-массив
Пользователь
Регистрация
30.10.2022
Сообщения
94
Реакции
101
Гарант сделки
2
Всем привет, пишу морфер, сейчас на этапе сокрытия констант.
Есть такой код:
C:
int fun(unsigned int a, int b, int c) {
    return a + b + c;
}

int main() {
    unsigned int a = 5;
    int b = 88;
    int c = 13;

    if (c == 13)
        fun(a, b, c);
    return 0;
}

После компила он превращается в такое:
1.PNG

Четко видны константы и составить псевдокод даже для человека не составляет труда. После обфускации это выглядит так:
2.PNG

Нужные константы исчезают и появляется куча случайных арифметических операций, после которых константы снова вернуться.
Однако в псевдокоде ида сразу их расчитывает:
3.PNG


Главный вопрос: как запудрить декомпилятор иды? Количество арифметических действий, взаимодействие со стэком/регистрами не помогает.
Наверняка есть какой-то финт ушами. Теоретически можно добавить вызов какой-то функции с известным результатом и его использовать, только поможет ли это?
Если есть какие-то идеи, то буду рад прочитать
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Количество арифметических действий, взаимодействие со стэком/регистрами не помогает
Естественно, декомпилятор использует оптимизацию и видит, что вся твоя математика ни к чему не приводит. Попробуй в математике использовать глобальные переменные. Чтение и обязательно запись в них.
 
1) Как сказали выше - можно использовать глобальные переменные, тогда оптимизатор не сьест всё выражение
2) Использовать Mixed Boolean Arithmetic в связке с вызовами винапи с известным результатом, рандомным, не влияющим на результат выражения, комбинируя глобальные переменные
Например:
Код:
a = 10
b = lstrlenW("sssss")
var1 = GetLastError()
var2 = GetCurrentProcessId()
static_var1 = -753638326
res = static_var1 + static_var1 * b + 1 * (b ^ (a | (~(b ^ b) ^ ~var1 ^ var1) & (b ^ b) & a & var2)) + static_var1 * ~b
assert_eq(res, 15)
На выходе имеем нечто подобное, с бесконечным кол-вом вариаций:
image.png
 
Немного дополню из другой темы: можно также добавить фейк-бренчи прямо в предикаты - это даст дополнительное поле для манёвров при следующих проходах (Control Flow Flattening, например). Так же по окончанию обработки всего условного модуля, можно пройтись по всем сгенерированным предикатам и частичо заметить в них мат. операции на вызовы функций:
C:
int res = a ^ b;
// ->
int xor(int a, int b) {
    // random code
    return a ^ b;
}
int res = xor(a, b);
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Ситуации конечно бывают разные, но такие задачки решаются динамикой - постановкой бряки на вызов функции, считывания аргументов, результата и сравнения нескольких вызовов, чтобы подтвердить догадку.
 
Ситуации конечно бывают разные, но такие задачки решаются динамикой - постановкой бряки на вызов функции, считывания аргументов, результата и сравнения нескольких вызовов, чтобы подтвердить догадку.
Вручную это накладно делать, нужна автоматика, которая умеет эмулировать системные вызовы (при условии что они используются, конечно).
 
Всем спасибо за ответы, пока что сделал мини пок, который на выход дает примерно такой результат:
sps.PNG

Потом еще добавлю функций и прочего, там надо будет просто пофантазировать.
Заметил еще интересное поведение - почему ида в данном случае до конца не провела расчёт?
Вот есть переменная v33 = 660 - x - 499. Почему она не сократила до v33 = 161 - x ? (ну и аналогичные недорасчёты ниже)
Хотя кстати число 660 она сама посчитала (это число в моём случае получилось как минимум из нескольких)
 
Вот есть переменная v33 = 660 - x - 499. Почему она не сократила до v33 = 161 - x ?
Возможно, не хватило контекста. По идее, если с -O3 собрать то, компилятор это оптимизирует.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх